x3daudio1_5: Add stub dll.
[wine.git] / dlls / d2d1 / render_target.c
blobf109849e5411b0b40a019aa068e0e2af4067c971
1 /*
2 * Copyright 2014 Henri Verbeet for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 #include "config.h"
20 #include "wine/port.h"
22 #include "d2d1_private.h"
23 #include "wincodec.h"
25 WINE_DEFAULT_DEBUG_CHANNEL(d2d);
27 #define INITIAL_CLIP_STACK_SIZE 4
29 struct d2d_draw_text_layout_ctx
31 ID2D1Brush *brush;
32 D2D1_DRAW_TEXT_OPTIONS options;
35 static void d2d_point_transform(D2D1_POINT_2F *dst, const D2D1_MATRIX_3X2_F *matrix, float x, float y)
37 dst->x = x * matrix->_11 + y * matrix->_21 + matrix->_31;
38 dst->y = x * matrix->_12 + y * matrix->_22 + matrix->_32;
41 static void d2d_rect_expand(D2D1_RECT_F *dst, const D2D1_POINT_2F *point)
43 if (point->x < dst->left)
44 dst->left = point->x;
45 if (point->y < dst->top)
46 dst->top = point->y;
47 if (point->x > dst->right)
48 dst->right = point->x;
49 if (point->y > dst->bottom)
50 dst->bottom = point->y;
53 static void d2d_rect_intersect(D2D1_RECT_F *dst, const D2D1_RECT_F *src)
55 if (src->left > dst->left)
56 dst->left = src->left;
57 if (src->top > dst->top)
58 dst->top = src->top;
59 if (src->right < dst->right)
60 dst->right = src->right;
61 if (src->bottom < dst->bottom)
62 dst->bottom = src->bottom;
65 static void d2d_rect_set(D2D1_RECT_F *dst, float left, float top, float right, float bottom)
67 dst->left = left;
68 dst->top = top;
69 dst->right = right;
70 dst->bottom = bottom;
73 static BOOL d2d_clip_stack_init(struct d2d_clip_stack *stack)
75 if (!(stack->stack = HeapAlloc(GetProcessHeap(), 0, INITIAL_CLIP_STACK_SIZE * sizeof(*stack->stack))))
76 return FALSE;
78 stack->size = INITIAL_CLIP_STACK_SIZE;
79 stack->count = 0;
81 return TRUE;
84 static void d2d_clip_stack_cleanup(struct d2d_clip_stack *stack)
86 HeapFree(GetProcessHeap(), 0, stack->stack);
89 static BOOL d2d_clip_stack_push(struct d2d_clip_stack *stack, const D2D1_RECT_F *rect)
91 D2D1_RECT_F r;
93 if (stack->count == stack->size)
95 D2D1_RECT_F *new_stack;
96 unsigned int new_size;
98 if (stack->size > UINT_MAX / 2)
99 return FALSE;
101 new_size = stack->size * 2;
102 if (!(new_stack = HeapReAlloc(GetProcessHeap(), 0, stack->stack, new_size * sizeof(*stack->stack))))
103 return FALSE;
105 stack->stack = new_stack;
106 stack->size = new_size;
109 r = *rect;
110 if (stack->count)
111 d2d_rect_intersect(&r, &stack->stack[stack->count - 1]);
112 stack->stack[stack->count++] = r;
114 return TRUE;
117 static void d2d_clip_stack_pop(struct d2d_clip_stack *stack)
119 if (!stack->count)
120 return;
121 --stack->count;
124 static void d2d_draw(struct d2d_d3d_render_target *render_target, ID3D10Buffer *vs_cb,
125 ID3D10PixelShader *ps, ID3D10Buffer *ps_cb, struct d2d_brush *brush)
127 ID3D10Device *device = render_target->device;
128 unsigned int offset;
129 D3D10_VIEWPORT vp;
130 HRESULT hr;
131 static const float blend_factor[] = {1.0f, 1.0f, 1.0f, 1.0f};
133 vp.TopLeftX = 0;
134 vp.TopLeftY = 0;
135 vp.Width = render_target->pixel_size.width;
136 vp.Height = render_target->pixel_size.height;
137 vp.MinDepth = 0.0f;
138 vp.MaxDepth = 1.0f;
140 if (FAILED(hr = render_target->stateblock->lpVtbl->Capture(render_target->stateblock)))
142 WARN("Failed to capture stateblock, hr %#x.\n", hr);
143 return;
146 ID3D10Device_ClearState(device);
148 ID3D10Device_IASetInputLayout(device, render_target->il);
149 ID3D10Device_IASetPrimitiveTopology(device, D3D10_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
150 offset = 0;
151 ID3D10Device_IASetVertexBuffers(device, 0, 1, &render_target->vb,
152 &render_target->vb_stride, &offset);
153 ID3D10Device_VSSetConstantBuffers(device, 0, 1, &vs_cb);
154 ID3D10Device_VSSetShader(device, render_target->vs);
155 ID3D10Device_PSSetConstantBuffers(device, 0, 1, &ps_cb);
156 ID3D10Device_PSSetShader(device, ps);
157 ID3D10Device_RSSetViewports(device, 1, &vp);
158 if (render_target->clip_stack.count)
160 const D2D1_RECT_F *clip_rect;
161 D3D10_RECT scissor_rect;
163 clip_rect = &render_target->clip_stack.stack[render_target->clip_stack.count - 1];
164 scissor_rect.left = clip_rect->left + 0.5f;
165 scissor_rect.top = clip_rect->top + 0.5f;
166 scissor_rect.right = clip_rect->right + 0.5f;
167 scissor_rect.bottom = clip_rect->bottom + 0.5f;
168 ID3D10Device_RSSetScissorRects(device, 1, &scissor_rect);
169 ID3D10Device_RSSetState(device, render_target->rs);
171 ID3D10Device_OMSetRenderTargets(device, 1, &render_target->view, NULL);
172 if (brush)
174 ID3D10Device_OMSetBlendState(device, render_target->bs, blend_factor, D3D10_DEFAULT_SAMPLE_MASK);
175 d2d_brush_bind_resources(brush, device);
178 ID3D10Device_Draw(device, 4, 0);
180 if (FAILED(hr = render_target->stateblock->lpVtbl->Apply(render_target->stateblock)))
181 WARN("Failed to apply stateblock, hr %#x.\n", hr);
184 static inline struct d2d_d3d_render_target *impl_from_ID2D1RenderTarget(ID2D1RenderTarget *iface)
186 return CONTAINING_RECORD(iface, struct d2d_d3d_render_target, ID2D1RenderTarget_iface);
189 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_QueryInterface(ID2D1RenderTarget *iface, REFIID iid, void **out)
191 TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
193 if (IsEqualGUID(iid, &IID_ID2D1RenderTarget)
194 || IsEqualGUID(iid, &IID_ID2D1Resource)
195 || IsEqualGUID(iid, &IID_IUnknown))
197 ID2D1RenderTarget_AddRef(iface);
198 *out = iface;
199 return S_OK;
202 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
204 *out = NULL;
205 return E_NOINTERFACE;
208 static ULONG STDMETHODCALLTYPE d2d_d3d_render_target_AddRef(ID2D1RenderTarget *iface)
210 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
211 ULONG refcount = InterlockedIncrement(&render_target->refcount);
213 TRACE("%p increasing refcount to %u.\n", iface, refcount);
215 return refcount;
218 static ULONG STDMETHODCALLTYPE d2d_d3d_render_target_Release(ID2D1RenderTarget *iface)
220 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
221 ULONG refcount = InterlockedDecrement(&render_target->refcount);
223 TRACE("%p decreasing refcount to %u.\n", iface, refcount);
225 if (!refcount)
227 d2d_clip_stack_cleanup(&render_target->clip_stack);
228 ID3D10PixelShader_Release(render_target->rect_bitmap_ps);
229 ID3D10PixelShader_Release(render_target->rect_solid_ps);
230 ID3D10BlendState_Release(render_target->bs);
231 ID3D10RasterizerState_Release(render_target->rs);
232 ID3D10VertexShader_Release(render_target->vs);
233 ID3D10Buffer_Release(render_target->vb);
234 ID3D10InputLayout_Release(render_target->il);
235 render_target->stateblock->lpVtbl->Release(render_target->stateblock);
236 ID3D10RenderTargetView_Release(render_target->view);
237 ID3D10Device_Release(render_target->device);
238 HeapFree(GetProcessHeap(), 0, render_target);
241 return refcount;
244 static void STDMETHODCALLTYPE d2d_d3d_render_target_GetFactory(ID2D1RenderTarget *iface, ID2D1Factory **factory)
246 FIXME("iface %p, factory %p stub!\n", iface, factory);
248 *factory = NULL;
251 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateBitmap(ID2D1RenderTarget *iface,
252 D2D1_SIZE_U size, const void *src_data, UINT32 pitch, const D2D1_BITMAP_PROPERTIES *desc, ID2D1Bitmap **bitmap)
254 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
255 struct d2d_bitmap *object;
256 HRESULT hr;
258 TRACE("iface %p, size {%u, %u}, src_data %p, pitch %u, desc %p, bitmap %p.\n",
259 iface, size.width, size.height, src_data, pitch, desc, bitmap);
261 if (!(object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object))))
262 return E_OUTOFMEMORY;
264 if (FAILED(hr = d2d_bitmap_init(object, render_target, size, src_data, pitch, desc)))
266 WARN("Failed to initialize bitmap, hr %#x.\n", hr);
267 HeapFree(GetProcessHeap(), 0, object);
268 return hr;
271 TRACE("Created bitmap %p.\n", object);
272 *bitmap = &object->ID2D1Bitmap_iface;
274 return S_OK;
277 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateBitmapFromWicBitmap(ID2D1RenderTarget *iface,
278 IWICBitmapSource *bitmap_source, const D2D1_BITMAP_PROPERTIES *desc, ID2D1Bitmap **bitmap)
280 D2D1_BITMAP_PROPERTIES bitmap_desc;
281 unsigned int bpp, data_size;
282 D2D1_SIZE_U size;
283 WICRect rect;
284 UINT32 pitch;
285 HRESULT hr;
286 void *data;
288 TRACE("iface %p, bitmap_source %p, desc %p, bitmap %p.\n",
289 iface, bitmap_source, desc, bitmap);
291 if (FAILED(hr = IWICBitmapSource_GetSize(bitmap_source, &size.width, &size.height)))
293 WARN("Failed to get bitmap size, hr %#x.\n", hr);
294 return hr;
297 if (!desc)
299 bitmap_desc.pixelFormat.format = DXGI_FORMAT_UNKNOWN;
300 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_UNKNOWN;
301 bitmap_desc.dpiX = 0.0f;
302 bitmap_desc.dpiY = 0.0f;
304 else
306 bitmap_desc = *desc;
309 if (bitmap_desc.pixelFormat.format == DXGI_FORMAT_UNKNOWN)
311 WICPixelFormatGUID wic_format;
313 if (FAILED(hr = IWICBitmapSource_GetPixelFormat(bitmap_source, &wic_format)))
315 WARN("Failed to get bitmap format, hr %#x.\n", hr);
316 return hr;
319 if (IsEqualGUID(&wic_format, &GUID_WICPixelFormat32bppPBGRA)
320 || IsEqualGUID(&wic_format, &GUID_WICPixelFormat32bppBGR))
322 bitmap_desc.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM;
324 else
326 WARN("Unsupported WIC bitmap format %s.\n", debugstr_guid(&wic_format));
327 return D2DERR_UNSUPPORTED_PIXEL_FORMAT;
331 switch (bitmap_desc.pixelFormat.format)
333 case DXGI_FORMAT_B8G8R8A8_UNORM:
334 bpp = 4;
335 break;
337 default:
338 FIXME("Unhandled format %#x.\n", bitmap_desc.pixelFormat.format);
339 return D2DERR_UNSUPPORTED_PIXEL_FORMAT;
342 pitch = ((bpp * size.width) + 15) & ~15;
343 data_size = pitch * size.height;
344 if (!(data = HeapAlloc(GetProcessHeap(), 0, data_size)))
345 return E_OUTOFMEMORY;
347 rect.X = 0;
348 rect.Y = 0;
349 rect.Width = size.width;
350 rect.Height = size.height;
351 if (FAILED(hr = IWICBitmapSource_CopyPixels(bitmap_source, &rect, pitch, data_size, data)))
353 WARN("Failed to copy bitmap pixels, hr %#x.\n", hr);
354 HeapFree(GetProcessHeap(), 0, data);
355 return hr;
358 hr = d2d_d3d_render_target_CreateBitmap(iface, size, data, pitch, &bitmap_desc, bitmap);
360 HeapFree(GetProcessHeap(), 0, data);
362 return hr;
365 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateSharedBitmap(ID2D1RenderTarget *iface,
366 REFIID iid, void *data, const D2D1_BITMAP_PROPERTIES *desc, ID2D1Bitmap **bitmap)
368 FIXME("iface %p, iid %s, data %p, desc %p, bitmap %p stub!\n",
369 iface, debugstr_guid(iid), data, desc, bitmap);
371 return E_NOTIMPL;
374 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateBitmapBrush(ID2D1RenderTarget *iface,
375 ID2D1Bitmap *bitmap, const D2D1_BITMAP_BRUSH_PROPERTIES *bitmap_brush_desc,
376 const D2D1_BRUSH_PROPERTIES *brush_desc, ID2D1BitmapBrush **brush)
378 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
379 struct d2d_brush *object;
380 HRESULT hr;
382 TRACE("iface %p, bitmap %p, bitmap_brush_desc %p, brush_desc %p, brush %p.\n",
383 iface, bitmap, bitmap_brush_desc, brush_desc, brush);
385 if (!(object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object))))
386 return E_OUTOFMEMORY;
388 if (FAILED(hr = d2d_bitmap_brush_init(object, render_target, bitmap, bitmap_brush_desc, brush_desc)))
390 WARN("Failed to initialize brush, hr %#x.\n", hr);
391 HeapFree(GetProcessHeap(), 0, object);
392 return hr;
395 TRACE("Created brush %p.\n", object);
396 *brush = (ID2D1BitmapBrush *)&object->ID2D1Brush_iface;
398 return S_OK;
401 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateSolidColorBrush(ID2D1RenderTarget *iface,
402 const D2D1_COLOR_F *color, const D2D1_BRUSH_PROPERTIES *desc, ID2D1SolidColorBrush **brush)
404 struct d2d_brush *object;
406 TRACE("iface %p, color %p, desc %p, brush %p.\n", iface, color, desc, brush);
408 if (!(object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object))))
409 return E_OUTOFMEMORY;
411 d2d_solid_color_brush_init(object, iface, color, desc);
413 TRACE("Created brush %p.\n", object);
414 *brush = (ID2D1SolidColorBrush *)&object->ID2D1Brush_iface;
416 return S_OK;
419 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateGradientStopCollection(ID2D1RenderTarget *iface,
420 const D2D1_GRADIENT_STOP *stops, UINT32 stop_count, D2D1_GAMMA gamma, D2D1_EXTEND_MODE extend_mode,
421 ID2D1GradientStopCollection **gradient)
423 struct d2d_gradient *object;
424 HRESULT hr;
426 TRACE("iface %p, stops %p, stop_count %u, gamma %#x, extend_mode %#x, gradient %p.\n",
427 iface, stops, stop_count, gamma, extend_mode, gradient);
429 if (!(object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object))))
430 return E_OUTOFMEMORY;
432 if (FAILED(hr = d2d_gradient_init(object, iface, stops, stop_count, gamma, extend_mode)))
434 WARN("Failed to initialize gradient, hr %#x.\n", hr);
435 HeapFree(GetProcessHeap(), 0, object);
436 return hr;
439 TRACE("Created gradient %p.\n", object);
440 *gradient = &object->ID2D1GradientStopCollection_iface;
442 return S_OK;
445 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateLinearGradientBrush(ID2D1RenderTarget *iface,
446 const D2D1_LINEAR_GRADIENT_BRUSH_PROPERTIES *gradient_brush_desc, const D2D1_BRUSH_PROPERTIES *brush_desc,
447 ID2D1GradientStopCollection *gradient, ID2D1LinearGradientBrush **brush)
449 struct d2d_brush *object;
451 TRACE("iface %p, gradient_brush_desc %p, brush_desc %p, gradient %p, brush %p.\n",
452 iface, gradient_brush_desc, brush_desc, gradient, brush);
454 if (!(object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object))))
455 return E_OUTOFMEMORY;
457 d2d_linear_gradient_brush_init(object, iface, gradient_brush_desc, brush_desc, gradient);
459 TRACE("Created brush %p.\n", object);
460 *brush = (ID2D1LinearGradientBrush *)&object->ID2D1Brush_iface;
462 return S_OK;
465 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateRadialGradientBrush(ID2D1RenderTarget *iface,
466 const D2D1_RADIAL_GRADIENT_BRUSH_PROPERTIES *gradient_brush_desc, const D2D1_BRUSH_PROPERTIES *brush_desc,
467 ID2D1GradientStopCollection *gradient, ID2D1RadialGradientBrush **brush)
469 FIXME("iface %p, gradient_brush_desc %p, brush_desc %p, gradient %p, brush %p stub!\n",
470 iface, gradient_brush_desc, brush_desc, gradient, brush);
472 return E_NOTIMPL;
475 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateCompatibleRenderTarget(ID2D1RenderTarget *iface,
476 const D2D1_SIZE_F *size, const D2D1_SIZE_U *pixel_size, const D2D1_PIXEL_FORMAT *format,
477 D2D1_COMPATIBLE_RENDER_TARGET_OPTIONS options, ID2D1BitmapRenderTarget **render_target)
479 FIXME("iface %p, size %p, pixel_size %p, format %p, options %#x, render_target %p stub!\n",
480 iface, size, pixel_size, format, options, render_target);
482 return E_NOTIMPL;
485 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateLayer(ID2D1RenderTarget *iface,
486 const D2D1_SIZE_F *size, ID2D1Layer **layer)
488 FIXME("iface %p, size %p, layer %p stub!\n", iface, size, layer);
490 return E_NOTIMPL;
493 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateMesh(ID2D1RenderTarget *iface, ID2D1Mesh **mesh)
495 struct d2d_mesh *object;
497 TRACE("iface %p, mesh %p.\n", iface, mesh);
499 if (!(object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object))))
500 return E_OUTOFMEMORY;
502 d2d_mesh_init(object);
504 TRACE("Created mesh %p.\n", object);
505 *mesh = &object->ID2D1Mesh_iface;
507 return S_OK;
510 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawLine(ID2D1RenderTarget *iface,
511 D2D1_POINT_2F p0, D2D1_POINT_2F p1, ID2D1Brush *brush, float stroke_width, ID2D1StrokeStyle *stroke_style)
513 FIXME("iface %p, p0 {%.8e, %.8e}, p1 {%.8e, %.8e}, brush %p, stroke_width %.8e, stroke_style %p stub!\n",
514 iface, p0.x, p0.y, p1.x, p1.y, brush, stroke_width, stroke_style);
517 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawRectangle(ID2D1RenderTarget *iface,
518 const D2D1_RECT_F *rect, ID2D1Brush *brush, float stroke_width, ID2D1StrokeStyle *stroke_style)
520 FIXME("iface %p, rect %p, brush %p, stroke_width %.8e, stroke_style %p stub!\n",
521 iface, rect, brush, stroke_width, stroke_style);
524 static void STDMETHODCALLTYPE d2d_d3d_render_target_FillRectangle(ID2D1RenderTarget *iface,
525 const D2D1_RECT_F *rect, ID2D1Brush *brush)
527 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
528 struct d2d_brush *brush_impl = unsafe_impl_from_ID2D1Brush(brush);
529 D3D10_SUBRESOURCE_DATA buffer_data;
530 D3D10_BUFFER_DESC buffer_desc;
531 ID3D10Buffer *vs_cb, *ps_cb;
532 ID3D10PixelShader *ps;
533 D2D1_COLOR_F color;
534 float tmp_x, tmp_y;
535 HRESULT hr;
536 struct
538 float _11, _21, _31, pad0;
539 float _12, _22, _32, pad1;
540 } transform, transform_inverse;
542 TRACE("iface %p, rect %p, brush %p.\n", iface, rect, brush);
544 if (brush_impl->type != D2D_BRUSH_TYPE_SOLID
545 && brush_impl->type != D2D_BRUSH_TYPE_BITMAP)
547 FIXME("Unhandled brush type %#x.\n", brush_impl->type);
548 return;
551 /* Translate from clip space to world (D2D rendertarget) space, taking the
552 * dpi and rendertarget transform into account. */
553 tmp_x = (2.0f * render_target->dpi_x) / (96.0f * render_target->pixel_size.width);
554 tmp_y = -(2.0f * render_target->dpi_y) / (96.0f * render_target->pixel_size.height);
555 transform._11 = render_target->transform._11 * tmp_x;
556 transform._21 = render_target->transform._21 * tmp_x;
557 transform._31 = render_target->transform._31 * tmp_x - 1.0f;
558 transform.pad0 = 0.0f;
559 transform._12 = render_target->transform._12 * tmp_y;
560 transform._22 = render_target->transform._22 * tmp_y;
561 transform._32 = render_target->transform._32 * tmp_y + 1.0f;
562 transform.pad1 = 0.0f;
564 /* Translate from world space to object space. */
565 tmp_x = rect->left + (rect->right - rect->left) / 2.0f;
566 tmp_y = rect->top + (rect->bottom - rect->top) / 2.0f;
567 transform._31 += tmp_x * transform._11 + tmp_y * transform._21;
568 transform._32 += tmp_x * transform._12 + tmp_y * transform._22;
569 tmp_x = (rect->right - rect->left) / 2.0f;
570 tmp_y = (rect->bottom - rect->top) / 2.0f;
571 transform._11 *= tmp_x;
572 transform._12 *= tmp_x;
573 transform._21 *= tmp_y;
574 transform._22 *= tmp_y;
576 buffer_desc.ByteWidth = sizeof(transform);
577 buffer_desc.Usage = D3D10_USAGE_DEFAULT;
578 buffer_desc.BindFlags = D3D10_BIND_CONSTANT_BUFFER;
579 buffer_desc.CPUAccessFlags = 0;
580 buffer_desc.MiscFlags = 0;
582 buffer_data.pSysMem = &transform;
583 buffer_data.SysMemPitch = 0;
584 buffer_data.SysMemSlicePitch = 0;
586 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device, &buffer_desc, &buffer_data, &vs_cb)))
588 WARN("Failed to create constant buffer, hr %#x.\n", hr);
589 return;
592 if (brush_impl->type == D2D_BRUSH_TYPE_BITMAP)
594 struct d2d_bitmap *bitmap = brush_impl->u.bitmap.bitmap;
595 float rt_scale, rt_bitmap_scale, d;
597 ps = render_target->rect_bitmap_ps;
599 /* Scale for bitmap size and dpi. */
600 rt_scale = render_target->dpi_x / 96.0f;
601 rt_bitmap_scale = bitmap->pixel_size.width * (bitmap->dpi_x / 96.0f) * rt_scale;
602 transform._11 = brush_impl->transform._11 * rt_bitmap_scale;
603 transform._21 = brush_impl->transform._21 * rt_bitmap_scale;
604 transform._31 = brush_impl->transform._31 * rt_scale;
605 rt_scale = render_target->dpi_y / 96.0f;
606 rt_bitmap_scale = bitmap->pixel_size.height * (bitmap->dpi_y / 96.0f) * rt_scale;
607 transform._12 = brush_impl->transform._12 * rt_bitmap_scale;
608 transform._22 = brush_impl->transform._22 * rt_bitmap_scale;
609 transform._32 = brush_impl->transform._32 * rt_scale;
611 /* Invert the matrix. (Because the matrix is applied to the sampling
612 * coordinates. I.e., to scale the bitmap by 2 we need to divide the
613 * coordinates by 2.) */
614 d = transform._11 * transform._22 - transform._21 * transform._22;
615 if (d != 0.0f)
617 transform_inverse._11 = transform._22 / d;
618 transform_inverse._21 = -transform._21 / d;
619 transform_inverse._31 = (transform._21 * transform._32 - transform._31 * transform._22) / d;
620 transform_inverse._12 = -transform._12 / d;
621 transform_inverse._22 = transform._11 / d;
622 transform_inverse._32 = -(transform._11 * transform._32 - transform._31 * transform._12) / d;
625 buffer_desc.ByteWidth = sizeof(transform_inverse);
626 buffer_data.pSysMem = &transform_inverse;
628 else
630 ps = render_target->rect_solid_ps;
632 color = brush_impl->u.solid.color;
633 color.r *= brush_impl->opacity;
634 color.g *= brush_impl->opacity;
635 color.b *= brush_impl->opacity;
636 color.a *= brush_impl->opacity;
638 buffer_desc.ByteWidth = sizeof(color);
639 buffer_data.pSysMem = &color;
642 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device, &buffer_desc, &buffer_data, &ps_cb)))
644 WARN("Failed to create constant buffer, hr %#x.\n", hr);
645 ID3D10Buffer_Release(vs_cb);
646 return;
649 d2d_draw(render_target, vs_cb, ps, ps_cb, brush_impl);
651 ID3D10Buffer_Release(ps_cb);
652 ID3D10Buffer_Release(vs_cb);
655 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawRoundedRectangle(ID2D1RenderTarget *iface,
656 const D2D1_ROUNDED_RECT *rect, ID2D1Brush *brush, float stroke_width, ID2D1StrokeStyle *stroke_style)
658 FIXME("iface %p, rect %p, brush %p, stroke_width %.8e, stroke_style %p stub!\n",
659 iface, rect, brush, stroke_width, stroke_style);
662 static void STDMETHODCALLTYPE d2d_d3d_render_target_FillRoundedRectangle(ID2D1RenderTarget *iface,
663 const D2D1_ROUNDED_RECT *rect, ID2D1Brush *brush)
665 FIXME("iface %p, rect %p, brush %p stub!\n", iface, rect, brush);
668 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawEllipse(ID2D1RenderTarget *iface,
669 const D2D1_ELLIPSE *ellipse, ID2D1Brush *brush, float stroke_width, ID2D1StrokeStyle *stroke_style)
671 FIXME("iface %p, ellipse %p, brush %p, stroke_width %.8e, stroke_style %p stub!\n",
672 iface, ellipse, brush, stroke_width, stroke_style);
675 static void STDMETHODCALLTYPE d2d_d3d_render_target_FillEllipse(ID2D1RenderTarget *iface,
676 const D2D1_ELLIPSE *ellipse, ID2D1Brush *brush)
678 FIXME("iface %p, ellipse %p, brush %p stub!\n", iface, ellipse, brush);
681 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawGeometry(ID2D1RenderTarget *iface,
682 ID2D1Geometry *geometry, ID2D1Brush *brush, float stroke_width, ID2D1StrokeStyle *stroke_style)
684 FIXME("iface %p, geometry %p, brush %p, stroke_width %.8e, stroke_style %p stub!\n",
685 iface, geometry, brush, stroke_width, stroke_style);
688 static void STDMETHODCALLTYPE d2d_d3d_render_target_FillGeometry(ID2D1RenderTarget *iface,
689 ID2D1Geometry *geometry, ID2D1Brush *brush, ID2D1Brush *opacity_brush)
691 FIXME("iface %p, geometry %p, brush %p, opacity_brush %p stub!\n", iface, geometry, brush, opacity_brush);
694 static void STDMETHODCALLTYPE d2d_d3d_render_target_FillMesh(ID2D1RenderTarget *iface,
695 ID2D1Mesh *mesh, ID2D1Brush *brush)
697 FIXME("iface %p, mesh %p, brush %p stub!\n", iface, mesh, brush);
700 static void STDMETHODCALLTYPE d2d_d3d_render_target_FillOpacityMask(ID2D1RenderTarget *iface,
701 ID2D1Bitmap *mask, ID2D1Brush *brush, D2D1_OPACITY_MASK_CONTENT content,
702 const D2D1_RECT_F *dst_rect, const D2D1_RECT_F *src_rect)
704 FIXME("iface %p, mask %p, brush %p, content %#x, dst_rect %p, src_rect %p stub!\n",
705 iface, mask, brush, content, dst_rect, src_rect);
708 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawBitmap(ID2D1RenderTarget *iface,
709 ID2D1Bitmap *bitmap, const D2D1_RECT_F *dst_rect, float opacity,
710 D2D1_BITMAP_INTERPOLATION_MODE interpolation_mode, const D2D1_RECT_F *src_rect)
712 D2D1_BITMAP_BRUSH_PROPERTIES bitmap_brush_desc;
713 D2D1_BRUSH_PROPERTIES brush_desc;
714 ID2D1BitmapBrush *brush;
715 D2D1_RECT_F s, d;
716 HRESULT hr;
718 TRACE("iface %p, bitmap %p, dst_rect %p, opacity %.8e, interpolation_mode %#x, src_rect %p.\n",
719 iface, bitmap, dst_rect, opacity, interpolation_mode, src_rect);
721 if (src_rect)
723 s = *src_rect;
725 else
727 D2D1_SIZE_F size;
729 size = ID2D1Bitmap_GetSize(bitmap);
730 s.left = 0.0f;
731 s.top = 0.0f;
732 s.right = size.width;
733 s.bottom = size.height;
736 if (dst_rect)
738 d = *dst_rect;
740 else
742 d.left = 0.0f;
743 d.top = 0.0f;
744 d.right = s.right - s.left;
745 d.bottom = s.bottom - s.top;
748 bitmap_brush_desc.extendModeX = D2D1_EXTEND_MODE_CLAMP;
749 bitmap_brush_desc.extendModeY = D2D1_EXTEND_MODE_CLAMP;
750 bitmap_brush_desc.interpolationMode = interpolation_mode;
752 brush_desc.opacity = opacity;
753 brush_desc.transform._11 = (d.right - d.left) / (s.right - s.left);
754 brush_desc.transform._21 = 0.0f;
755 brush_desc.transform._31 = d.left;
756 brush_desc.transform._12 = 0.0f;
757 brush_desc.transform._22 = (d.bottom - d.top) / (s.bottom - s.top);
758 brush_desc.transform._32 = d.top;
760 if (FAILED(hr = ID2D1RenderTarget_CreateBitmapBrush(iface, bitmap, &bitmap_brush_desc, &brush_desc, &brush)))
762 ERR("Failed to create bitmap brush, hr %#x.\n", hr);
763 return;
766 ID2D1RenderTarget_FillRectangle(iface, &d, (ID2D1Brush *)brush);
767 ID2D1BitmapBrush_Release(brush);
770 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawText(ID2D1RenderTarget *iface,
771 const WCHAR *string, UINT32 string_len, IDWriteTextFormat *text_format, const D2D1_RECT_F *layout_rect,
772 ID2D1Brush *brush, D2D1_DRAW_TEXT_OPTIONS options, DWRITE_MEASURING_MODE measuring_mode)
774 FIXME("iface %p, string %s, string_len %u, text_format %p, layout_rect %p, "
775 "brush %p, options %#x, measuring_mode %#x stub!\n",
776 iface, debugstr_wn(string, string_len), string_len, text_format, layout_rect,
777 brush, options, measuring_mode);
780 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawTextLayout(ID2D1RenderTarget *iface,
781 D2D1_POINT_2F origin, IDWriteTextLayout *layout, ID2D1Brush *brush, D2D1_DRAW_TEXT_OPTIONS options)
783 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
784 struct d2d_draw_text_layout_ctx ctx;
785 HRESULT hr;
787 TRACE("iface %p, origin {%.8e, %.8e}, layout %p, brush %p, options %#x.\n",
788 iface, origin.x, origin.y, layout, brush, options);
790 ctx.brush = brush;
791 ctx.options = options;
793 if (FAILED(hr = IDWriteTextLayout_Draw(layout,
794 &ctx, &render_target->IDWriteTextRenderer_iface, origin.x, origin.y)))
795 FIXME("Failed to draw text layout, hr %#x.\n", hr);
798 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawGlyphRun(ID2D1RenderTarget *iface,
799 D2D1_POINT_2F baseline_origin, const DWRITE_GLYPH_RUN *glyph_run, ID2D1Brush *brush,
800 DWRITE_MEASURING_MODE measuring_mode)
802 FIXME("iface %p, baseline_origin {%.8e, %.8e}, glyph_run %p, brush %p, measuring_mode %#x stub!\n",
803 iface, baseline_origin.x, baseline_origin.y, glyph_run, brush, measuring_mode);
806 static void STDMETHODCALLTYPE d2d_d3d_render_target_SetTransform(ID2D1RenderTarget *iface,
807 const D2D1_MATRIX_3X2_F *transform)
809 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
811 TRACE("iface %p, transform %p.\n", iface, transform);
813 render_target->transform = *transform;
816 static void STDMETHODCALLTYPE d2d_d3d_render_target_GetTransform(ID2D1RenderTarget *iface,
817 D2D1_MATRIX_3X2_F *transform)
819 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
821 TRACE("iface %p, transform %p.\n", iface, transform);
823 *transform = render_target->transform;
826 static void STDMETHODCALLTYPE d2d_d3d_render_target_SetAntialiasMode(ID2D1RenderTarget *iface,
827 D2D1_ANTIALIAS_MODE antialias_mode)
829 FIXME("iface %p, antialias_mode %#x stub!\n", iface, antialias_mode);
832 static D2D1_ANTIALIAS_MODE STDMETHODCALLTYPE d2d_d3d_render_target_GetAntialiasMode(ID2D1RenderTarget *iface)
834 FIXME("iface %p stub!\n", iface);
836 return D2D1_ANTIALIAS_MODE_PER_PRIMITIVE;
839 static void STDMETHODCALLTYPE d2d_d3d_render_target_SetTextAntialiasMode(ID2D1RenderTarget *iface,
840 D2D1_TEXT_ANTIALIAS_MODE antialias_mode)
842 FIXME("iface %p, antialias_mode %#x stub!\n", iface, antialias_mode);
845 static D2D1_TEXT_ANTIALIAS_MODE STDMETHODCALLTYPE d2d_d3d_render_target_GetTextAntialiasMode(ID2D1RenderTarget *iface)
847 FIXME("iface %p stub!\n", iface);
849 return D2D1_TEXT_ANTIALIAS_MODE_DEFAULT;
852 static void STDMETHODCALLTYPE d2d_d3d_render_target_SetTextRenderingParams(ID2D1RenderTarget *iface,
853 IDWriteRenderingParams *text_rendering_params)
855 FIXME("iface %p, text_rendering_params %p stub!\n", iface, text_rendering_params);
858 static void STDMETHODCALLTYPE d2d_d3d_render_target_GetTextRenderingParams(ID2D1RenderTarget *iface,
859 IDWriteRenderingParams **text_rendering_params)
861 FIXME("iface %p, text_rendering_params %p stub!\n", iface, text_rendering_params);
863 *text_rendering_params = NULL;
866 static void STDMETHODCALLTYPE d2d_d3d_render_target_SetTags(ID2D1RenderTarget *iface, D2D1_TAG tag1, D2D1_TAG tag2)
868 FIXME("iface %p, tag1 %s, tag2 %s stub!\n", iface, wine_dbgstr_longlong(tag1), wine_dbgstr_longlong(tag2));
871 static void STDMETHODCALLTYPE d2d_d3d_render_target_GetTags(ID2D1RenderTarget *iface, D2D1_TAG *tag1, D2D1_TAG *tag2)
873 FIXME("iface %p, tag1 %p, tag2 %p stub!\n", iface, tag1, tag2);
875 *tag1 = 0;
876 *tag2 = 0;
879 static void STDMETHODCALLTYPE d2d_d3d_render_target_PushLayer(ID2D1RenderTarget *iface,
880 const D2D1_LAYER_PARAMETERS *layer_parameters, ID2D1Layer *layer)
882 FIXME("iface %p, layer_parameters %p, layer %p stub!\n", iface, layer_parameters, layer);
885 static void STDMETHODCALLTYPE d2d_d3d_render_target_PopLayer(ID2D1RenderTarget *iface)
887 FIXME("iface %p stub!\n", iface);
890 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_Flush(ID2D1RenderTarget *iface, D2D1_TAG *tag1, D2D1_TAG *tag2)
892 FIXME("iface %p, tag1 %p, tag2 %p stub!\n", iface, tag1, tag2);
894 return E_NOTIMPL;
897 static void STDMETHODCALLTYPE d2d_d3d_render_target_SaveDrawingState(ID2D1RenderTarget *iface,
898 ID2D1DrawingStateBlock *state_block)
900 FIXME("iface %p, state_block %p stub!\n", iface, state_block);
903 static void STDMETHODCALLTYPE d2d_d3d_render_target_RestoreDrawingState(ID2D1RenderTarget *iface,
904 ID2D1DrawingStateBlock *state_block)
906 FIXME("iface %p, state_block %p stub!\n", iface, state_block);
909 static void STDMETHODCALLTYPE d2d_d3d_render_target_PushAxisAlignedClip(ID2D1RenderTarget *iface,
910 const D2D1_RECT_F *clip_rect, D2D1_ANTIALIAS_MODE antialias_mode)
912 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
913 D2D1_RECT_F transformed_rect;
914 float x_scale, y_scale;
915 D2D1_POINT_2F point;
917 TRACE("iface %p, clip_rect %p, antialias_mode %#x.\n", iface, clip_rect, antialias_mode);
919 if (antialias_mode != D2D1_ANTIALIAS_MODE_ALIASED)
920 FIXME("Ignoring antialias_mode %#x.\n", antialias_mode);
922 x_scale = render_target->dpi_x / 96.0f;
923 y_scale = render_target->dpi_y / 96.0f;
924 d2d_point_transform(&point, &render_target->transform, clip_rect->left * x_scale, clip_rect->top * y_scale);
925 d2d_rect_set(&transformed_rect, point.x, point.y, point.x, point.y);
926 d2d_point_transform(&point, &render_target->transform, clip_rect->left * x_scale, clip_rect->bottom * y_scale);
927 d2d_rect_expand(&transformed_rect, &point);
928 d2d_point_transform(&point, &render_target->transform, clip_rect->right * x_scale, clip_rect->top * y_scale);
929 d2d_rect_expand(&transformed_rect, &point);
930 d2d_point_transform(&point, &render_target->transform, clip_rect->right * x_scale, clip_rect->bottom * y_scale);
931 d2d_rect_expand(&transformed_rect, &point);
933 if (!d2d_clip_stack_push(&render_target->clip_stack, &transformed_rect))
934 WARN("Failed to push clip rect.\n");
937 static void STDMETHODCALLTYPE d2d_d3d_render_target_PopAxisAlignedClip(ID2D1RenderTarget *iface)
939 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
941 TRACE("iface %p.\n", iface);
943 d2d_clip_stack_pop(&render_target->clip_stack);
946 static void STDMETHODCALLTYPE d2d_d3d_render_target_Clear(ID2D1RenderTarget *iface, const D2D1_COLOR_F *color)
948 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
949 D3D10_SUBRESOURCE_DATA buffer_data;
950 D3D10_BUFFER_DESC buffer_desc;
951 ID3D10Buffer *vs_cb, *ps_cb;
952 HRESULT hr;
954 static const float transform[] =
956 1.0f, 0.0f, 0.0f, 0.0f,
957 0.0f, -1.0f, 0.0f, 0.0f,
960 TRACE("iface %p, color %p.\n", iface, color);
962 buffer_desc.ByteWidth = sizeof(transform);
963 buffer_desc.Usage = D3D10_USAGE_DEFAULT;
964 buffer_desc.BindFlags = D3D10_BIND_CONSTANT_BUFFER;
965 buffer_desc.CPUAccessFlags = 0;
966 buffer_desc.MiscFlags = 0;
968 buffer_data.pSysMem = transform;
969 buffer_data.SysMemPitch = 0;
970 buffer_data.SysMemSlicePitch = 0;
972 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device, &buffer_desc, &buffer_data, &vs_cb)))
974 WARN("Failed to create constant buffer, hr %#x.\n", hr);
975 return;
978 buffer_desc.ByteWidth = sizeof(*color);
979 buffer_data.pSysMem = color;
981 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device, &buffer_desc, &buffer_data, &ps_cb)))
983 WARN("Failed to create constant buffer, hr %#x.\n", hr);
984 ID3D10Buffer_Release(vs_cb);
985 return;
988 d2d_draw(render_target, vs_cb, render_target->rect_solid_ps, ps_cb, NULL);
990 ID3D10Buffer_Release(ps_cb);
991 ID3D10Buffer_Release(vs_cb);
994 static void STDMETHODCALLTYPE d2d_d3d_render_target_BeginDraw(ID2D1RenderTarget *iface)
996 TRACE("iface %p.\n", iface);
999 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_EndDraw(ID2D1RenderTarget *iface,
1000 D2D1_TAG *tag1, D2D1_TAG *tag2)
1002 TRACE("iface %p, tag1 %p, tag2 %p.\n", iface, tag1, tag2);
1004 if (tag1)
1005 *tag1 = 0;
1006 if (tag2)
1007 *tag2 = 0;
1009 return S_OK;
1012 static D2D1_PIXEL_FORMAT * STDMETHODCALLTYPE d2d_d3d_render_target_GetPixelFormat(ID2D1RenderTarget *iface,
1013 D2D1_PIXEL_FORMAT *format)
1015 FIXME("iface %p, format %p stub!\n", iface, format);
1017 format->format = DXGI_FORMAT_UNKNOWN;
1018 format->alphaMode = D2D1_ALPHA_MODE_UNKNOWN;
1019 return format;
1022 static void STDMETHODCALLTYPE d2d_d3d_render_target_SetDpi(ID2D1RenderTarget *iface, float dpi_x, float dpi_y)
1024 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1026 TRACE("iface %p, dpi_x %.8e, dpi_y %.8e.\n", iface, dpi_x, dpi_y);
1028 if (dpi_x == 0.0f && dpi_y == 0.0f)
1030 dpi_x = 96.0f;
1031 dpi_y = 96.0f;
1034 render_target->dpi_x = dpi_x;
1035 render_target->dpi_y = dpi_y;
1038 static void STDMETHODCALLTYPE d2d_d3d_render_target_GetDpi(ID2D1RenderTarget *iface, float *dpi_x, float *dpi_y)
1040 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1042 TRACE("iface %p, dpi_x %p, dpi_y %p.\n", iface, dpi_x, dpi_y);
1044 *dpi_x = render_target->dpi_x;
1045 *dpi_y = render_target->dpi_y;
1048 static D2D1_SIZE_F * STDMETHODCALLTYPE d2d_d3d_render_target_GetSize(ID2D1RenderTarget *iface, D2D1_SIZE_F *size)
1050 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1052 TRACE("iface %p, size %p.\n", iface, size);
1054 size->width = render_target->pixel_size.width / (render_target->dpi_x / 96.0f);
1055 size->height = render_target->pixel_size.height / (render_target->dpi_y / 96.0f);
1056 return size;
1059 static D2D1_SIZE_U * STDMETHODCALLTYPE d2d_d3d_render_target_GetPixelSize(ID2D1RenderTarget *iface,
1060 D2D1_SIZE_U *pixel_size)
1062 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1064 TRACE("iface %p, pixel_size %p.\n", iface, pixel_size);
1066 *pixel_size = render_target->pixel_size;
1067 return pixel_size;
1070 static UINT32 STDMETHODCALLTYPE d2d_d3d_render_target_GetMaximumBitmapSize(ID2D1RenderTarget *iface)
1072 FIXME("iface %p stub!\n", iface);
1074 return 0;
1077 static BOOL STDMETHODCALLTYPE d2d_d3d_render_target_IsSupported(ID2D1RenderTarget *iface,
1078 const D2D1_RENDER_TARGET_PROPERTIES *desc)
1080 FIXME("iface %p, desc %p stub!\n", iface, desc);
1082 return FALSE;
1085 static const struct ID2D1RenderTargetVtbl d2d_d3d_render_target_vtbl =
1087 d2d_d3d_render_target_QueryInterface,
1088 d2d_d3d_render_target_AddRef,
1089 d2d_d3d_render_target_Release,
1090 d2d_d3d_render_target_GetFactory,
1091 d2d_d3d_render_target_CreateBitmap,
1092 d2d_d3d_render_target_CreateBitmapFromWicBitmap,
1093 d2d_d3d_render_target_CreateSharedBitmap,
1094 d2d_d3d_render_target_CreateBitmapBrush,
1095 d2d_d3d_render_target_CreateSolidColorBrush,
1096 d2d_d3d_render_target_CreateGradientStopCollection,
1097 d2d_d3d_render_target_CreateLinearGradientBrush,
1098 d2d_d3d_render_target_CreateRadialGradientBrush,
1099 d2d_d3d_render_target_CreateCompatibleRenderTarget,
1100 d2d_d3d_render_target_CreateLayer,
1101 d2d_d3d_render_target_CreateMesh,
1102 d2d_d3d_render_target_DrawLine,
1103 d2d_d3d_render_target_DrawRectangle,
1104 d2d_d3d_render_target_FillRectangle,
1105 d2d_d3d_render_target_DrawRoundedRectangle,
1106 d2d_d3d_render_target_FillRoundedRectangle,
1107 d2d_d3d_render_target_DrawEllipse,
1108 d2d_d3d_render_target_FillEllipse,
1109 d2d_d3d_render_target_DrawGeometry,
1110 d2d_d3d_render_target_FillGeometry,
1111 d2d_d3d_render_target_FillMesh,
1112 d2d_d3d_render_target_FillOpacityMask,
1113 d2d_d3d_render_target_DrawBitmap,
1114 d2d_d3d_render_target_DrawText,
1115 d2d_d3d_render_target_DrawTextLayout,
1116 d2d_d3d_render_target_DrawGlyphRun,
1117 d2d_d3d_render_target_SetTransform,
1118 d2d_d3d_render_target_GetTransform,
1119 d2d_d3d_render_target_SetAntialiasMode,
1120 d2d_d3d_render_target_GetAntialiasMode,
1121 d2d_d3d_render_target_SetTextAntialiasMode,
1122 d2d_d3d_render_target_GetTextAntialiasMode,
1123 d2d_d3d_render_target_SetTextRenderingParams,
1124 d2d_d3d_render_target_GetTextRenderingParams,
1125 d2d_d3d_render_target_SetTags,
1126 d2d_d3d_render_target_GetTags,
1127 d2d_d3d_render_target_PushLayer,
1128 d2d_d3d_render_target_PopLayer,
1129 d2d_d3d_render_target_Flush,
1130 d2d_d3d_render_target_SaveDrawingState,
1131 d2d_d3d_render_target_RestoreDrawingState,
1132 d2d_d3d_render_target_PushAxisAlignedClip,
1133 d2d_d3d_render_target_PopAxisAlignedClip,
1134 d2d_d3d_render_target_Clear,
1135 d2d_d3d_render_target_BeginDraw,
1136 d2d_d3d_render_target_EndDraw,
1137 d2d_d3d_render_target_GetPixelFormat,
1138 d2d_d3d_render_target_SetDpi,
1139 d2d_d3d_render_target_GetDpi,
1140 d2d_d3d_render_target_GetSize,
1141 d2d_d3d_render_target_GetPixelSize,
1142 d2d_d3d_render_target_GetMaximumBitmapSize,
1143 d2d_d3d_render_target_IsSupported,
1146 static inline struct d2d_d3d_render_target *impl_from_IDWriteTextRenderer(IDWriteTextRenderer *iface)
1148 return CONTAINING_RECORD(iface, struct d2d_d3d_render_target, IDWriteTextRenderer_iface);
1151 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_QueryInterface(IDWriteTextRenderer *iface, REFIID iid, void **out)
1153 TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
1155 if (IsEqualGUID(iid, &IID_IDWriteTextRenderer)
1156 || IsEqualGUID(iid, &IID_IDWritePixelSnapping)
1157 || IsEqualGUID(iid, &IID_IUnknown))
1159 IDWriteTextRenderer_AddRef(iface);
1160 *out = iface;
1161 return S_OK;
1164 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
1166 *out = NULL;
1167 return E_NOINTERFACE;
1170 static ULONG STDMETHODCALLTYPE d2d_text_renderer_AddRef(IDWriteTextRenderer *iface)
1172 struct d2d_d3d_render_target *render_target = impl_from_IDWriteTextRenderer(iface);
1174 TRACE("iface %p.\n", iface);
1176 return d2d_d3d_render_target_AddRef(&render_target->ID2D1RenderTarget_iface);
1179 static ULONG STDMETHODCALLTYPE d2d_text_renderer_Release(IDWriteTextRenderer *iface)
1181 struct d2d_d3d_render_target *render_target = impl_from_IDWriteTextRenderer(iface);
1183 TRACE("iface %p.\n", iface);
1185 return d2d_d3d_render_target_Release(&render_target->ID2D1RenderTarget_iface);
1188 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_IsPixelSnappingDisabled(IDWriteTextRenderer *iface,
1189 void *ctx, BOOL *disabled)
1191 FIXME("iface %p, ctx %p, disabled %p stub!\n", iface, ctx, disabled);
1193 return E_NOTIMPL;
1196 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_GetCurrentTransform(IDWriteTextRenderer *iface,
1197 void *ctx, DWRITE_MATRIX *transform)
1199 FIXME("iface %p, ctx %p, transform %p stub!\n", iface, ctx, transform);
1201 return E_NOTIMPL;
1204 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_GetPixelsPerDip(IDWriteTextRenderer *iface, void *ctx, float *ppd)
1206 FIXME("iface %p, ctx %p, ppd %p stub!\n", iface, ctx, ppd);
1208 return E_NOTIMPL;
1211 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_DrawGlyphRun(IDWriteTextRenderer *iface, void *ctx,
1212 float baseline_origin_x, float baseline_origin_y, DWRITE_MEASURING_MODE measuring_mode,
1213 const DWRITE_GLYPH_RUN *glyph_run, const DWRITE_GLYPH_RUN_DESCRIPTION *desc, IUnknown *effect)
1215 FIXME("iface %p, ctx %p, baseline_origin_x %.8e, baseline_origin_y %.8e, "
1216 "measuring_mode %#x, glyph_run %p, desc %p, effect %p stub!\n",
1217 iface, ctx, baseline_origin_x, baseline_origin_y,
1218 measuring_mode, glyph_run, desc, effect);
1220 return E_NOTIMPL;
1223 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_DrawUnderline(IDWriteTextRenderer *iface, void *ctx,
1224 float baseline_origin_x, float baseline_origin_y, const DWRITE_UNDERLINE *underline, IUnknown *effect)
1226 FIXME("iface %p, ctx %p, baseline_origin_x %.8e, baseline_origin_y %.8e, underline %p, effect %p stub!\n",
1227 iface, ctx, baseline_origin_x, baseline_origin_y, underline, effect);
1229 return E_NOTIMPL;
1232 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_DrawStrikethrough(IDWriteTextRenderer *iface, void *ctx,
1233 float baseline_origin_x, float baseline_origin_y, const DWRITE_STRIKETHROUGH *strikethrough, IUnknown *effect)
1235 FIXME("iface %p, ctx %p, baseline_origin_x %.8e, baseline_origin_y %.8e, strikethrough %p, effect %p stub!\n",
1236 iface, ctx, baseline_origin_x, baseline_origin_y, strikethrough, effect);
1238 return E_NOTIMPL;
1241 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_DrawInlineObject(IDWriteTextRenderer *iface, void *ctx,
1242 float origin_x, float origin_y, IDWriteInlineObject *object, BOOL is_sideways, BOOL is_rtl, IUnknown *effect)
1244 FIXME("iface %p, ctx %p, origin_x %.8e, origin_y %.8e, object %p, is_sideways %#x, is_rtl %#x, effect %p stub!\n",
1245 iface, ctx, origin_x, origin_y, object, is_sideways, is_rtl, effect);
1247 return E_NOTIMPL;
1250 static const struct IDWriteTextRendererVtbl d2d_text_renderer_vtbl =
1252 d2d_text_renderer_QueryInterface,
1253 d2d_text_renderer_AddRef,
1254 d2d_text_renderer_Release,
1255 d2d_text_renderer_IsPixelSnappingDisabled,
1256 d2d_text_renderer_GetCurrentTransform,
1257 d2d_text_renderer_GetPixelsPerDip,
1258 d2d_text_renderer_DrawGlyphRun,
1259 d2d_text_renderer_DrawUnderline,
1260 d2d_text_renderer_DrawStrikethrough,
1261 d2d_text_renderer_DrawInlineObject,
1264 HRESULT d2d_d3d_render_target_init(struct d2d_d3d_render_target *render_target, ID2D1Factory *factory,
1265 IDXGISurface *surface, const D2D1_RENDER_TARGET_PROPERTIES *desc)
1267 D3D10_SUBRESOURCE_DATA buffer_data;
1268 D3D10_STATE_BLOCK_MASK state_mask;
1269 DXGI_SURFACE_DESC surface_desc;
1270 D3D10_RASTERIZER_DESC rs_desc;
1271 D3D10_BUFFER_DESC buffer_desc;
1272 D3D10_BLEND_DESC blend_desc;
1273 ID3D10Resource *resource;
1274 HRESULT hr;
1276 static const D3D10_INPUT_ELEMENT_DESC il_desc[] =
1278 {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0},
1280 static const DWORD vs_code[] =
1282 /* float3x2 transform;
1284 * float4 main(float4 position : POSITION) : SV_POSITION
1286 * return float4(mul(position.xyw, transform), position.zw);
1287 * } */
1288 0x43425844, 0x0add3194, 0x205f74ec, 0xab527fe7, 0xbe6ad704, 0x00000001, 0x00000128, 0x00000003,
1289 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020,
1290 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000f0f, 0x49534f50, 0x4e4f4954, 0xababab00,
1291 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000001, 0x00000003,
1292 0x00000000, 0x0000000f, 0x505f5653, 0x5449534f, 0x004e4f49, 0x52444853, 0x0000008c, 0x00010040,
1293 0x00000023, 0x04000059, 0x00208e46, 0x00000000, 0x00000002, 0x0300005f, 0x001010f2, 0x00000000,
1294 0x04000067, 0x001020f2, 0x00000000, 0x00000001, 0x08000010, 0x00102012, 0x00000000, 0x00101346,
1295 0x00000000, 0x00208246, 0x00000000, 0x00000000, 0x08000010, 0x00102022, 0x00000000, 0x00101346,
1296 0x00000000, 0x00208246, 0x00000000, 0x00000001, 0x05000036, 0x001020c2, 0x00000000, 0x00101ea6,
1297 0x00000000, 0x0100003e,
1299 static const DWORD rect_solid_ps_code[] =
1301 /* float4 color;
1303 * float4 main(float4 position : SV_POSITION) : SV_Target
1305 * return color;
1306 * } */
1307 0x43425844, 0x88eefcfd, 0x93d6fd47, 0x173c242f, 0x0106d07a, 0x00000001, 0x000000dc, 0x00000003,
1308 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020,
1309 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x505f5653, 0x5449534f, 0x004e4f49,
1310 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003,
1311 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x00000040, 0x00000040,
1312 0x00000010, 0x04000059, 0x00208e46, 0x00000000, 0x00000001, 0x03000065, 0x001020f2, 0x00000000,
1313 0x06000036, 0x001020f2, 0x00000000, 0x00208e46, 0x00000000, 0x00000000, 0x0100003e,
1315 static const DWORD rect_bitmap_ps_code[] =
1317 #if 0
1318 float3x2 transform;
1319 SamplerState s;
1320 Texture2D t;
1322 float4 main(float4 position : SV_POSITION) : SV_Target
1324 return t.Sample(s, mul(float3(position.xy, 1.0), transform));
1326 #endif
1327 0x43425844, 0x20fce5be, 0x138fa37f, 0x9554f03f, 0x3dbe9c02, 0x00000001, 0x00000184, 0x00000003,
1328 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020,
1329 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000030f, 0x505f5653, 0x5449534f, 0x004e4f49,
1330 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003,
1331 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x000000e8, 0x00000040,
1332 0x0000003a, 0x04000059, 0x00208e46, 0x00000000, 0x00000002, 0x0300005a, 0x00106000, 0x00000000,
1333 0x04001858, 0x00107000, 0x00000000, 0x00005555, 0x04002064, 0x00101032, 0x00000000, 0x00000001,
1334 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000002, 0x05000036, 0x00100032, 0x00000000,
1335 0x00101046, 0x00000000, 0x05000036, 0x00100042, 0x00000000, 0x00004001, 0x3f800000, 0x08000010,
1336 0x00100012, 0x00000001, 0x00100246, 0x00000000, 0x00208246, 0x00000000, 0x00000000, 0x08000010,
1337 0x00100022, 0x00000001, 0x00100246, 0x00000000, 0x00208246, 0x00000000, 0x00000001, 0x09000045,
1338 0x001020f2, 0x00000000, 0x00100046, 0x00000001, 0x00107e46, 0x00000000, 0x00106000, 0x00000000,
1339 0x0100003e,
1341 static const struct
1343 float x, y;
1345 quad[] =
1347 {-1.0f, 1.0f},
1348 {-1.0f, -1.0f},
1349 { 1.0f, 1.0f},
1350 { 1.0f, -1.0f},
1352 static const D2D1_MATRIX_3X2_F identity =
1354 1.0f, 0.0f,
1355 0.0f, 1.0f,
1356 0.0f, 0.0f,
1359 FIXME("Ignoring render target properties.\n");
1361 render_target->ID2D1RenderTarget_iface.lpVtbl = &d2d_d3d_render_target_vtbl;
1362 render_target->IDWriteTextRenderer_iface.lpVtbl = &d2d_text_renderer_vtbl;
1363 render_target->refcount = 1;
1365 if (FAILED(hr = IDXGISurface_GetDevice(surface, &IID_ID3D10Device, (void **)&render_target->device)))
1367 WARN("Failed to get device interface, hr %#x.\n", hr);
1368 return hr;
1371 if (FAILED(hr = IDXGISurface_QueryInterface(surface, &IID_ID3D10Resource, (void **)&resource)))
1373 WARN("Failed to get ID3D10Resource interface, hr %#x.\n", hr);
1374 goto err;
1377 hr = ID3D10Device_CreateRenderTargetView(render_target->device, resource, NULL, &render_target->view);
1378 ID3D10Resource_Release(resource);
1379 if (FAILED(hr))
1381 WARN("Failed to create rendertarget view, hr %#x.\n", hr);
1382 goto err;
1385 if (FAILED(hr = D3D10StateBlockMaskEnableAll(&state_mask)))
1387 WARN("Failed to create stateblock mask, hr %#x.\n", hr);
1388 goto err;
1391 if (FAILED(hr = D3D10CreateStateBlock(render_target->device, &state_mask, &render_target->stateblock)))
1393 WARN("Failed to create stateblock, hr %#x.\n", hr);
1394 goto err;
1397 if (FAILED(hr = ID3D10Device_CreateInputLayout(render_target->device, il_desc,
1398 sizeof(il_desc) / sizeof(*il_desc), vs_code, sizeof(vs_code),
1399 &render_target->il)))
1401 WARN("Failed to create clear input layout, hr %#x.\n", hr);
1402 goto err;
1405 buffer_desc.ByteWidth = sizeof(quad);
1406 buffer_desc.Usage = D3D10_USAGE_DEFAULT;
1407 buffer_desc.BindFlags = D3D10_BIND_VERTEX_BUFFER;
1408 buffer_desc.CPUAccessFlags = 0;
1409 buffer_desc.MiscFlags = 0;
1411 buffer_data.pSysMem = quad;
1412 buffer_data.SysMemPitch = 0;
1413 buffer_data.SysMemSlicePitch = 0;
1415 render_target->vb_stride = sizeof(*quad);
1416 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device,
1417 &buffer_desc, &buffer_data, &render_target->vb)))
1419 WARN("Failed to create clear vertex buffer, hr %#x.\n", hr);
1420 goto err;
1423 if (FAILED(hr = ID3D10Device_CreateVertexShader(render_target->device,
1424 vs_code, sizeof(vs_code), &render_target->vs)))
1426 WARN("Failed to create clear vertex shader, hr %#x.\n", hr);
1427 goto err;
1430 rs_desc.FillMode = D3D10_FILL_SOLID;
1431 rs_desc.CullMode = D3D10_CULL_BACK;
1432 rs_desc.FrontCounterClockwise = FALSE;
1433 rs_desc.DepthBias = 0;
1434 rs_desc.DepthBiasClamp = 0.0f;
1435 rs_desc.SlopeScaledDepthBias = 0.0f;
1436 rs_desc.DepthClipEnable = TRUE;
1437 rs_desc.ScissorEnable = TRUE;
1438 rs_desc.MultisampleEnable = FALSE;
1439 rs_desc.AntialiasedLineEnable = FALSE;
1440 if (FAILED(hr = ID3D10Device_CreateRasterizerState(render_target->device, &rs_desc, &render_target->rs)))
1442 WARN("Failed to create clear rasterizer state, hr %#x.\n", hr);
1443 goto err;
1446 memset(&blend_desc, 0, sizeof(blend_desc));
1447 blend_desc.BlendEnable[0] = TRUE;
1448 blend_desc.SrcBlend = D3D10_BLEND_SRC_ALPHA;
1449 blend_desc.DestBlend = D3D10_BLEND_INV_SRC_ALPHA;
1450 blend_desc.BlendOp = D3D10_BLEND_OP_ADD;
1451 blend_desc.SrcBlendAlpha = D3D10_BLEND_ZERO;
1452 blend_desc.DestBlendAlpha = D3D10_BLEND_ONE;
1453 blend_desc.BlendOpAlpha = D3D10_BLEND_OP_ADD;
1454 blend_desc.RenderTargetWriteMask[0] = D3D10_COLOR_WRITE_ENABLE_ALL;
1455 if (FAILED(hr = ID3D10Device_CreateBlendState(render_target->device, &blend_desc, &render_target->bs)))
1457 WARN("Failed to create blend state, hr %#x.\n", hr);
1458 goto err;
1461 if (FAILED(hr = ID3D10Device_CreatePixelShader(render_target->device,
1462 rect_solid_ps_code, sizeof(rect_solid_ps_code), &render_target->rect_solid_ps)))
1464 WARN("Failed to create pixel shader, hr %#x.\n", hr);
1465 goto err;
1468 if (FAILED(hr = ID3D10Device_CreatePixelShader(render_target->device,
1469 rect_bitmap_ps_code, sizeof(rect_bitmap_ps_code), &render_target->rect_bitmap_ps)))
1471 WARN("Failed to create pixel shader, hr %#x.\n", hr);
1472 goto err;
1475 if (FAILED(hr = IDXGISurface_GetDesc(surface, &surface_desc)))
1477 WARN("Failed to get surface desc, hr %#x.\n", hr);
1478 goto err;
1481 render_target->pixel_size.width = surface_desc.Width;
1482 render_target->pixel_size.height = surface_desc.Height;
1483 render_target->transform = identity;
1485 if (!d2d_clip_stack_init(&render_target->clip_stack))
1487 WARN("Failed to initialize clip stack.\n");
1488 hr = E_FAIL;
1489 goto err;
1492 render_target->dpi_x = desc->dpiX;
1493 render_target->dpi_y = desc->dpiY;
1495 if (render_target->dpi_x == 0.0f && render_target->dpi_y == 0.0f)
1497 render_target->dpi_x = 96.0f;
1498 render_target->dpi_y = 96.0f;
1501 return S_OK;
1503 err:
1504 if (render_target->rect_bitmap_ps)
1505 ID3D10PixelShader_Release(render_target->rect_bitmap_ps);
1506 if (render_target->rect_solid_ps)
1507 ID3D10PixelShader_Release(render_target->rect_solid_ps);
1508 if (render_target->bs)
1509 ID3D10BlendState_Release(render_target->bs);
1510 if (render_target->rs)
1511 ID3D10RasterizerState_Release(render_target->rs);
1512 if (render_target->vs)
1513 ID3D10VertexShader_Release(render_target->vs);
1514 if (render_target->vb)
1515 ID3D10Buffer_Release(render_target->vb);
1516 if (render_target->il)
1517 ID3D10InputLayout_Release(render_target->il);
1518 if (render_target->stateblock)
1519 render_target->stateblock->lpVtbl->Release(render_target->stateblock);
1520 if (render_target->view)
1521 ID3D10RenderTargetView_Release(render_target->view);
1522 if (render_target->device)
1523 ID3D10Device_Release(render_target->device);
1524 return hr;