msvcp110: Add tr2_sys__Make_dir_wchar implementation and test.
[wine/multimedia.git] / dlls / d2d1 / render_target.c
blob263cb91d967865d379ade012277f3d3a8d974e21
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_set(D2D1_POINT_2F *dst, float x, float y)
37 dst->x = x;
38 dst->y = y;
41 static void d2d_point_transform(D2D1_POINT_2F *dst, const D2D1_MATRIX_3X2_F *matrix, float x, float y)
43 dst->x = x * matrix->_11 + y * matrix->_21 + matrix->_31;
44 dst->y = x * matrix->_12 + y * matrix->_22 + matrix->_32;
47 static void d2d_rect_expand(D2D1_RECT_F *dst, const D2D1_POINT_2F *point)
49 if (point->x < dst->left)
50 dst->left = point->x;
51 if (point->y < dst->top)
52 dst->top = point->y;
53 if (point->x > dst->right)
54 dst->right = point->x;
55 if (point->y > dst->bottom)
56 dst->bottom = point->y;
59 static void d2d_rect_intersect(D2D1_RECT_F *dst, const D2D1_RECT_F *src)
61 if (src->left > dst->left)
62 dst->left = src->left;
63 if (src->top > dst->top)
64 dst->top = src->top;
65 if (src->right < dst->right)
66 dst->right = src->right;
67 if (src->bottom < dst->bottom)
68 dst->bottom = src->bottom;
71 static void d2d_rect_set(D2D1_RECT_F *dst, float left, float top, float right, float bottom)
73 dst->left = left;
74 dst->top = top;
75 dst->right = right;
76 dst->bottom = bottom;
79 static BOOL d2d_clip_stack_init(struct d2d_clip_stack *stack)
81 if (!(stack->stack = HeapAlloc(GetProcessHeap(), 0, INITIAL_CLIP_STACK_SIZE * sizeof(*stack->stack))))
82 return FALSE;
84 stack->size = INITIAL_CLIP_STACK_SIZE;
85 stack->count = 0;
87 return TRUE;
90 static void d2d_clip_stack_cleanup(struct d2d_clip_stack *stack)
92 HeapFree(GetProcessHeap(), 0, stack->stack);
95 static BOOL d2d_clip_stack_push(struct d2d_clip_stack *stack, const D2D1_RECT_F *rect)
97 D2D1_RECT_F r;
99 if (stack->count == stack->size)
101 D2D1_RECT_F *new_stack;
102 unsigned int new_size;
104 if (stack->size > UINT_MAX / 2)
105 return FALSE;
107 new_size = stack->size * 2;
108 if (!(new_stack = HeapReAlloc(GetProcessHeap(), 0, stack->stack, new_size * sizeof(*stack->stack))))
109 return FALSE;
111 stack->stack = new_stack;
112 stack->size = new_size;
115 r = *rect;
116 if (stack->count)
117 d2d_rect_intersect(&r, &stack->stack[stack->count - 1]);
118 stack->stack[stack->count++] = r;
120 return TRUE;
123 static void d2d_clip_stack_pop(struct d2d_clip_stack *stack)
125 if (!stack->count)
126 return;
127 --stack->count;
130 static void d2d_draw(struct d2d_d3d_render_target *render_target, enum d2d_shape_type shape_type,
131 ID3D10Buffer *ib, unsigned int index_count, ID3D10Buffer *vb, unsigned int vb_stride,
132 ID3D10Buffer *vs_cb, ID3D10Buffer *ps_cb, struct d2d_brush *brush)
134 struct d2d_shape_resources *shape_resources = &render_target->shape_resources[shape_type];
135 ID3D10Device *device = render_target->device;
136 unsigned int offset;
137 D3D10_VIEWPORT vp;
138 HRESULT hr;
140 vp.TopLeftX = 0;
141 vp.TopLeftY = 0;
142 vp.Width = render_target->pixel_size.width;
143 vp.Height = render_target->pixel_size.height;
144 vp.MinDepth = 0.0f;
145 vp.MaxDepth = 1.0f;
147 if (FAILED(hr = render_target->stateblock->lpVtbl->Capture(render_target->stateblock)))
149 WARN("Failed to capture stateblock, hr %#x.\n", hr);
150 return;
153 ID3D10Device_ClearState(device);
155 ID3D10Device_IASetInputLayout(device, shape_resources->il);
156 ID3D10Device_IASetPrimitiveTopology(device, D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
157 ID3D10Device_IASetIndexBuffer(device, ib, DXGI_FORMAT_R16_UINT, 0);
158 offset = 0;
159 ID3D10Device_IASetVertexBuffers(device, 0, 1, &vb, &vb_stride, &offset);
160 ID3D10Device_VSSetConstantBuffers(device, 0, 1, &vs_cb);
161 ID3D10Device_VSSetShader(device, shape_resources->vs);
162 ID3D10Device_PSSetConstantBuffers(device, 0, 1, &ps_cb);
163 ID3D10Device_RSSetViewports(device, 1, &vp);
164 if (render_target->clip_stack.count)
166 const D2D1_RECT_F *clip_rect;
167 D3D10_RECT scissor_rect;
169 clip_rect = &render_target->clip_stack.stack[render_target->clip_stack.count - 1];
170 scissor_rect.left = clip_rect->left + 0.5f;
171 scissor_rect.top = clip_rect->top + 0.5f;
172 scissor_rect.right = clip_rect->right + 0.5f;
173 scissor_rect.bottom = clip_rect->bottom + 0.5f;
174 ID3D10Device_RSSetScissorRects(device, 1, &scissor_rect);
175 ID3D10Device_RSSetState(device, render_target->rs);
177 ID3D10Device_OMSetRenderTargets(device, 1, &render_target->view, NULL);
178 if (brush)
179 d2d_brush_bind_resources(brush, render_target, shape_type);
180 else
181 ID3D10Device_PSSetShader(device, shape_resources->ps[D2D_BRUSH_TYPE_SOLID]);
183 if (ib)
184 ID3D10Device_DrawIndexed(device, index_count, 0, 0);
185 else
186 ID3D10Device_Draw(device, index_count, 0);
188 if (FAILED(hr = render_target->stateblock->lpVtbl->Apply(render_target->stateblock)))
189 WARN("Failed to apply stateblock, hr %#x.\n", hr);
192 static inline struct d2d_d3d_render_target *impl_from_ID2D1RenderTarget(ID2D1RenderTarget *iface)
194 return CONTAINING_RECORD(iface, struct d2d_d3d_render_target, ID2D1RenderTarget_iface);
197 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_QueryInterface(ID2D1RenderTarget *iface, REFIID iid, void **out)
199 TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
201 if (IsEqualGUID(iid, &IID_ID2D1RenderTarget)
202 || IsEqualGUID(iid, &IID_ID2D1Resource)
203 || IsEqualGUID(iid, &IID_IUnknown))
205 ID2D1RenderTarget_AddRef(iface);
206 *out = iface;
207 return S_OK;
210 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
212 *out = NULL;
213 return E_NOINTERFACE;
216 static ULONG STDMETHODCALLTYPE d2d_d3d_render_target_AddRef(ID2D1RenderTarget *iface)
218 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
219 ULONG refcount = InterlockedIncrement(&render_target->refcount);
221 TRACE("%p increasing refcount to %u.\n", iface, refcount);
223 return refcount;
226 static ULONG STDMETHODCALLTYPE d2d_d3d_render_target_Release(ID2D1RenderTarget *iface)
228 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
229 ULONG refcount = InterlockedDecrement(&render_target->refcount);
231 TRACE("%p decreasing refcount to %u.\n", iface, refcount);
233 if (!refcount)
235 unsigned int i, j;
237 d2d_clip_stack_cleanup(&render_target->clip_stack);
238 if (render_target->text_rendering_params)
239 IDWriteRenderingParams_Release(render_target->text_rendering_params);
240 ID3D10BlendState_Release(render_target->bs);
241 ID3D10RasterizerState_Release(render_target->rs);
242 ID3D10Buffer_Release(render_target->vb);
243 ID3D10Buffer_Release(render_target->ib);
244 for (i = 0; i < D2D_SHAPE_TYPE_COUNT; ++i)
246 for (j = 0; j < D2D_BRUSH_TYPE_COUNT; ++j)
248 if (render_target->shape_resources[i].ps[j])
249 ID3D10PixelShader_Release(render_target->shape_resources[i].ps[j]);
251 ID3D10VertexShader_Release(render_target->shape_resources[i].vs);
252 ID3D10InputLayout_Release(render_target->shape_resources[i].il);
254 render_target->stateblock->lpVtbl->Release(render_target->stateblock);
255 ID3D10RenderTargetView_Release(render_target->view);
256 ID3D10Device_Release(render_target->device);
257 ID2D1Factory_Release(render_target->factory);
258 HeapFree(GetProcessHeap(), 0, render_target);
261 return refcount;
264 static void STDMETHODCALLTYPE d2d_d3d_render_target_GetFactory(ID2D1RenderTarget *iface, ID2D1Factory **factory)
266 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
268 TRACE("iface %p, factory %p.\n", iface, factory);
270 *factory = render_target->factory;
271 ID2D1Factory_AddRef(*factory);
274 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateBitmap(ID2D1RenderTarget *iface,
275 D2D1_SIZE_U size, const void *src_data, UINT32 pitch, const D2D1_BITMAP_PROPERTIES *desc, ID2D1Bitmap **bitmap)
277 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
278 struct d2d_bitmap *object;
279 HRESULT hr;
281 TRACE("iface %p, size {%u, %u}, src_data %p, pitch %u, desc %p, bitmap %p.\n",
282 iface, size.width, size.height, src_data, pitch, desc, bitmap);
284 if (!(object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object))))
285 return E_OUTOFMEMORY;
287 if (FAILED(hr = d2d_bitmap_init_memory(object, render_target, size, src_data, pitch, desc)))
289 WARN("Failed to initialize bitmap, hr %#x.\n", hr);
290 HeapFree(GetProcessHeap(), 0, object);
291 return hr;
294 TRACE("Created bitmap %p.\n", object);
295 *bitmap = &object->ID2D1Bitmap_iface;
297 return S_OK;
300 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateBitmapFromWicBitmap(ID2D1RenderTarget *iface,
301 IWICBitmapSource *bitmap_source, const D2D1_BITMAP_PROPERTIES *desc, ID2D1Bitmap **bitmap)
303 const D2D1_PIXEL_FORMAT *d2d_format;
304 D2D1_BITMAP_PROPERTIES bitmap_desc;
305 WICPixelFormatGUID wic_format;
306 unsigned int bpp, data_size;
307 D2D1_SIZE_U size;
308 unsigned int i;
309 WICRect rect;
310 UINT32 pitch;
311 HRESULT hr;
312 void *data;
314 static const struct
316 const WICPixelFormatGUID *wic;
317 D2D1_PIXEL_FORMAT d2d;
319 format_lookup[] =
321 {&GUID_WICPixelFormat32bppPBGRA, {DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_PREMULTIPLIED}},
322 {&GUID_WICPixelFormat32bppBGR, {DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_IGNORE}},
325 TRACE("iface %p, bitmap_source %p, desc %p, bitmap %p.\n",
326 iface, bitmap_source, desc, bitmap);
328 if (FAILED(hr = IWICBitmapSource_GetSize(bitmap_source, &size.width, &size.height)))
330 WARN("Failed to get bitmap size, hr %#x.\n", hr);
331 return hr;
334 if (!desc)
336 bitmap_desc.pixelFormat.format = DXGI_FORMAT_UNKNOWN;
337 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_UNKNOWN;
338 bitmap_desc.dpiX = 0.0f;
339 bitmap_desc.dpiY = 0.0f;
341 else
343 bitmap_desc = *desc;
346 if (FAILED(hr = IWICBitmapSource_GetPixelFormat(bitmap_source, &wic_format)))
348 WARN("Failed to get bitmap format, hr %#x.\n", hr);
349 return hr;
352 for (i = 0, d2d_format = NULL; i < sizeof(format_lookup) / sizeof(*format_lookup); ++i)
354 if (IsEqualGUID(&wic_format, format_lookup[i].wic))
356 d2d_format = &format_lookup[i].d2d;
357 break;
361 if (!d2d_format)
363 WARN("Unsupported WIC bitmap format %s.\n", debugstr_guid(&wic_format));
364 return D2DERR_UNSUPPORTED_PIXEL_FORMAT;
367 if (bitmap_desc.pixelFormat.format == DXGI_FORMAT_UNKNOWN)
368 bitmap_desc.pixelFormat.format = d2d_format->format;
369 if (bitmap_desc.pixelFormat.alphaMode == D2D1_ALPHA_MODE_UNKNOWN)
370 bitmap_desc.pixelFormat.alphaMode = d2d_format->alphaMode;
372 switch (bitmap_desc.pixelFormat.format)
374 case DXGI_FORMAT_B8G8R8A8_UNORM:
375 bpp = 4;
376 break;
378 default:
379 FIXME("Unhandled format %#x.\n", bitmap_desc.pixelFormat.format);
380 return D2DERR_UNSUPPORTED_PIXEL_FORMAT;
383 pitch = ((bpp * size.width) + 15) & ~15;
384 data_size = pitch * size.height;
385 if (!(data = HeapAlloc(GetProcessHeap(), 0, data_size)))
386 return E_OUTOFMEMORY;
388 rect.X = 0;
389 rect.Y = 0;
390 rect.Width = size.width;
391 rect.Height = size.height;
392 if (FAILED(hr = IWICBitmapSource_CopyPixels(bitmap_source, &rect, pitch, data_size, data)))
394 WARN("Failed to copy bitmap pixels, hr %#x.\n", hr);
395 HeapFree(GetProcessHeap(), 0, data);
396 return hr;
399 hr = d2d_d3d_render_target_CreateBitmap(iface, size, data, pitch, &bitmap_desc, bitmap);
401 HeapFree(GetProcessHeap(), 0, data);
403 return hr;
406 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateSharedBitmap(ID2D1RenderTarget *iface,
407 REFIID iid, void *data, const D2D1_BITMAP_PROPERTIES *desc, ID2D1Bitmap **bitmap)
409 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
410 struct d2d_bitmap *object;
411 HRESULT hr;
413 TRACE("iface %p, iid %s, data %p, desc %p, bitmap %p.\n",
414 iface, debugstr_guid(iid), data, desc, bitmap);
416 if (!(object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object))))
417 return E_OUTOFMEMORY;
419 if (FAILED(hr = d2d_bitmap_init_shared(object, render_target, iid, data, desc)))
421 WARN("Failed to initialize bitmap, hr %#x.\n", hr);
422 HeapFree(GetProcessHeap(), 0, object);
423 return hr;
426 TRACE("Created bitmap %p.\n", object);
427 *bitmap = &object->ID2D1Bitmap_iface;
429 return S_OK;
432 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateBitmapBrush(ID2D1RenderTarget *iface,
433 ID2D1Bitmap *bitmap, const D2D1_BITMAP_BRUSH_PROPERTIES *bitmap_brush_desc,
434 const D2D1_BRUSH_PROPERTIES *brush_desc, ID2D1BitmapBrush **brush)
436 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
437 struct d2d_brush *object;
439 TRACE("iface %p, bitmap %p, bitmap_brush_desc %p, brush_desc %p, brush %p.\n",
440 iface, bitmap, bitmap_brush_desc, brush_desc, brush);
442 if (!(object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object))))
443 return E_OUTOFMEMORY;
445 d2d_bitmap_brush_init(object, render_target->factory, bitmap, bitmap_brush_desc, brush_desc);
447 TRACE("Created brush %p.\n", object);
448 *brush = (ID2D1BitmapBrush *)&object->ID2D1Brush_iface;
450 return S_OK;
453 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateSolidColorBrush(ID2D1RenderTarget *iface,
454 const D2D1_COLOR_F *color, const D2D1_BRUSH_PROPERTIES *desc, ID2D1SolidColorBrush **brush)
456 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
457 struct d2d_brush *object;
459 TRACE("iface %p, color %p, desc %p, brush %p.\n", iface, color, desc, brush);
461 if (!(object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object))))
462 return E_OUTOFMEMORY;
464 d2d_solid_color_brush_init(object, render_target->factory, color, desc);
466 TRACE("Created brush %p.\n", object);
467 *brush = (ID2D1SolidColorBrush *)&object->ID2D1Brush_iface;
469 return S_OK;
472 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateGradientStopCollection(ID2D1RenderTarget *iface,
473 const D2D1_GRADIENT_STOP *stops, UINT32 stop_count, D2D1_GAMMA gamma, D2D1_EXTEND_MODE extend_mode,
474 ID2D1GradientStopCollection **gradient)
476 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
477 struct d2d_gradient *object;
478 HRESULT hr;
480 TRACE("iface %p, stops %p, stop_count %u, gamma %#x, extend_mode %#x, gradient %p.\n",
481 iface, stops, stop_count, gamma, extend_mode, gradient);
483 if (!(object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object))))
484 return E_OUTOFMEMORY;
486 if (FAILED(hr = d2d_gradient_init(object, render_target->factory, stops, stop_count, gamma, extend_mode)))
488 WARN("Failed to initialize gradient, hr %#x.\n", hr);
489 HeapFree(GetProcessHeap(), 0, object);
490 return hr;
493 TRACE("Created gradient %p.\n", object);
494 *gradient = &object->ID2D1GradientStopCollection_iface;
496 return S_OK;
499 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateLinearGradientBrush(ID2D1RenderTarget *iface,
500 const D2D1_LINEAR_GRADIENT_BRUSH_PROPERTIES *gradient_brush_desc, const D2D1_BRUSH_PROPERTIES *brush_desc,
501 ID2D1GradientStopCollection *gradient, ID2D1LinearGradientBrush **brush)
503 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
504 struct d2d_brush *object;
506 TRACE("iface %p, gradient_brush_desc %p, brush_desc %p, gradient %p, brush %p.\n",
507 iface, gradient_brush_desc, brush_desc, gradient, brush);
509 if (!(object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object))))
510 return E_OUTOFMEMORY;
512 d2d_linear_gradient_brush_init(object, render_target->factory, gradient_brush_desc, brush_desc, gradient);
514 TRACE("Created brush %p.\n", object);
515 *brush = (ID2D1LinearGradientBrush *)&object->ID2D1Brush_iface;
517 return S_OK;
520 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateRadialGradientBrush(ID2D1RenderTarget *iface,
521 const D2D1_RADIAL_GRADIENT_BRUSH_PROPERTIES *gradient_brush_desc, const D2D1_BRUSH_PROPERTIES *brush_desc,
522 ID2D1GradientStopCollection *gradient, ID2D1RadialGradientBrush **brush)
524 FIXME("iface %p, gradient_brush_desc %p, brush_desc %p, gradient %p, brush %p stub!\n",
525 iface, gradient_brush_desc, brush_desc, gradient, brush);
527 return E_NOTIMPL;
530 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateCompatibleRenderTarget(ID2D1RenderTarget *iface,
531 const D2D1_SIZE_F *size, const D2D1_SIZE_U *pixel_size, const D2D1_PIXEL_FORMAT *format,
532 D2D1_COMPATIBLE_RENDER_TARGET_OPTIONS options, ID2D1BitmapRenderTarget **render_target)
534 FIXME("iface %p, size %p, pixel_size %p, format %p, options %#x, render_target %p stub!\n",
535 iface, size, pixel_size, format, options, render_target);
537 return E_NOTIMPL;
540 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateLayer(ID2D1RenderTarget *iface,
541 const D2D1_SIZE_F *size, ID2D1Layer **layer)
543 FIXME("iface %p, size %p, layer %p stub!\n", iface, size, layer);
545 return E_NOTIMPL;
548 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateMesh(ID2D1RenderTarget *iface, ID2D1Mesh **mesh)
550 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
551 struct d2d_mesh *object;
553 TRACE("iface %p, mesh %p.\n", iface, mesh);
555 if (!(object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object))))
556 return E_OUTOFMEMORY;
558 d2d_mesh_init(object, render_target->factory);
560 TRACE("Created mesh %p.\n", object);
561 *mesh = &object->ID2D1Mesh_iface;
563 return S_OK;
566 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawLine(ID2D1RenderTarget *iface,
567 D2D1_POINT_2F p0, D2D1_POINT_2F p1, ID2D1Brush *brush, float stroke_width, ID2D1StrokeStyle *stroke_style)
569 FIXME("iface %p, p0 {%.8e, %.8e}, p1 {%.8e, %.8e}, brush %p, stroke_width %.8e, stroke_style %p stub!\n",
570 iface, p0.x, p0.y, p1.x, p1.y, brush, stroke_width, stroke_style);
573 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawRectangle(ID2D1RenderTarget *iface,
574 const D2D1_RECT_F *rect, ID2D1Brush *brush, float stroke_width, ID2D1StrokeStyle *stroke_style)
576 FIXME("iface %p, rect %p, brush %p, stroke_width %.8e, stroke_style %p stub!\n",
577 iface, rect, brush, stroke_width, stroke_style);
580 static void STDMETHODCALLTYPE d2d_d3d_render_target_FillRectangle(ID2D1RenderTarget *iface,
581 const D2D1_RECT_F *rect, ID2D1Brush *brush)
583 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
584 ID2D1RectangleGeometry *geometry;
585 HRESULT hr;
587 TRACE("iface %p, rect %p, brush %p.\n", iface, rect, brush);
589 if (FAILED(hr = ID2D1Factory_CreateRectangleGeometry(render_target->factory, rect, &geometry)))
591 ERR("Failed to create geometry, hr %#x.\n", hr);
592 return;
595 ID2D1RenderTarget_FillGeometry(iface, (ID2D1Geometry *)geometry, brush, NULL);
596 ID2D1RectangleGeometry_Release(geometry);
599 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawRoundedRectangle(ID2D1RenderTarget *iface,
600 const D2D1_ROUNDED_RECT *rect, ID2D1Brush *brush, float stroke_width, ID2D1StrokeStyle *stroke_style)
602 FIXME("iface %p, rect %p, brush %p, stroke_width %.8e, stroke_style %p stub!\n",
603 iface, rect, brush, stroke_width, stroke_style);
606 static void STDMETHODCALLTYPE d2d_d3d_render_target_FillRoundedRectangle(ID2D1RenderTarget *iface,
607 const D2D1_ROUNDED_RECT *rect, ID2D1Brush *brush)
609 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
610 ID2D1RoundedRectangleGeometry *geometry;
611 HRESULT hr;
613 TRACE("iface %p, rect %p, brush %p.\n", iface, rect, brush);
615 if (FAILED(hr = ID2D1Factory_CreateRoundedRectangleGeometry(render_target->factory, rect, &geometry)))
617 ERR("Failed to create geometry, hr %#x.\n", hr);
618 return;
621 ID2D1RenderTarget_FillGeometry(iface, (ID2D1Geometry *)geometry, brush, NULL);
622 ID2D1RoundedRectangleGeometry_Release(geometry);
625 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawEllipse(ID2D1RenderTarget *iface,
626 const D2D1_ELLIPSE *ellipse, ID2D1Brush *brush, float stroke_width, ID2D1StrokeStyle *stroke_style)
628 FIXME("iface %p, ellipse %p, brush %p, stroke_width %.8e, stroke_style %p stub!\n",
629 iface, ellipse, brush, stroke_width, stroke_style);
632 static void STDMETHODCALLTYPE d2d_d3d_render_target_FillEllipse(ID2D1RenderTarget *iface,
633 const D2D1_ELLIPSE *ellipse, ID2D1Brush *brush)
635 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
636 ID2D1EllipseGeometry *geometry;
637 HRESULT hr;
639 TRACE("iface %p, ellipse %p, brush %p.\n", iface, ellipse, brush);
641 if (FAILED(hr = ID2D1Factory_CreateEllipseGeometry(render_target->factory, ellipse, &geometry)))
643 ERR("Failed to create geometry, hr %#x.\n", hr);
644 return;
647 ID2D1RenderTarget_FillGeometry(iface, (ID2D1Geometry *)geometry, brush, NULL);
648 ID2D1EllipseGeometry_Release(geometry);
651 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawGeometry(ID2D1RenderTarget *iface,
652 ID2D1Geometry *geometry, ID2D1Brush *brush, float stroke_width, ID2D1StrokeStyle *stroke_style)
654 FIXME("iface %p, geometry %p, brush %p, stroke_width %.8e, stroke_style %p stub!\n",
655 iface, geometry, brush, stroke_width, stroke_style);
658 static void STDMETHODCALLTYPE d2d_d3d_render_target_FillGeometry(ID2D1RenderTarget *iface,
659 ID2D1Geometry *geometry, ID2D1Brush *brush, ID2D1Brush *opacity_brush)
661 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
662 struct d2d_brush *brush_impl = unsafe_impl_from_ID2D1Brush(brush);
663 const struct d2d_geometry *geometry_impl;
664 ID3D10Buffer *ib, *vb, *vs_cb, *ps_cb;
665 D3D10_SUBRESOURCE_DATA buffer_data;
666 D3D10_BUFFER_DESC buffer_desc;
667 float tmp_x, tmp_y;
668 HRESULT hr;
669 struct
671 float _11, _21, _31, pad0;
672 float _12, _22, _32, pad1;
673 } transform;
675 TRACE("iface %p, geometry %p, brush %p, opacity_brush %p.\n", iface, geometry, brush, opacity_brush);
677 if (opacity_brush)
678 FIXME("Ignoring opacity brush %p.\n", opacity_brush);
680 geometry_impl = unsafe_impl_from_ID2D1Geometry(geometry);
682 tmp_x = (2.0f * render_target->dpi_x) / (96.0f * render_target->pixel_size.width);
683 tmp_y = -(2.0f * render_target->dpi_y) / (96.0f * render_target->pixel_size.height);
684 transform._11 = render_target->drawing_state.transform._11 * tmp_x;
685 transform._21 = render_target->drawing_state.transform._21 * tmp_x;
686 transform._31 = render_target->drawing_state.transform._31 * tmp_x - 1.0f;
687 transform.pad0 = 0.0f;
688 transform._12 = render_target->drawing_state.transform._12 * tmp_y;
689 transform._22 = render_target->drawing_state.transform._22 * tmp_y;
690 transform._32 = render_target->drawing_state.transform._32 * tmp_y + 1.0f;
691 transform.pad1 = 0.0f;
693 buffer_desc.ByteWidth = sizeof(transform);
694 buffer_desc.Usage = D3D10_USAGE_DEFAULT;
695 buffer_desc.BindFlags = D3D10_BIND_CONSTANT_BUFFER;
696 buffer_desc.CPUAccessFlags = 0;
697 buffer_desc.MiscFlags = 0;
699 buffer_data.pSysMem = &transform;
700 buffer_data.SysMemPitch = 0;
701 buffer_data.SysMemSlicePitch = 0;
703 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device, &buffer_desc, &buffer_data, &vs_cb)))
705 WARN("Failed to create constant buffer, hr %#x.\n", hr);
706 return;
709 if (FAILED(hr = d2d_brush_get_ps_cb(brush_impl, render_target, &ps_cb)))
711 WARN("Failed to get ps constant buffer, hr %#x.\n", hr);
712 ID3D10Buffer_Release(vs_cb);
713 return;
716 buffer_desc.ByteWidth = geometry_impl->face_count * sizeof(*geometry_impl->faces);
717 buffer_desc.BindFlags = D3D10_BIND_INDEX_BUFFER;
718 buffer_data.pSysMem = geometry_impl->faces;
720 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device, &buffer_desc, &buffer_data, &ib)))
722 WARN("Failed to create index buffer, hr %#x.\n", hr);
723 goto done;
726 buffer_desc.ByteWidth = geometry_impl->vertex_count * sizeof(*geometry_impl->vertices);
727 buffer_desc.BindFlags = D3D10_BIND_VERTEX_BUFFER;
728 buffer_data.pSysMem = geometry_impl->vertices;
730 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device, &buffer_desc, &buffer_data, &vb)))
732 ERR("Failed to create vertex buffer, hr %#x.\n", hr);
733 ID3D10Buffer_Release(ib);
734 goto done;
737 d2d_draw(render_target, D2D_SHAPE_TYPE_TRIANGLE, ib, 3 * geometry_impl->face_count, vb,
738 sizeof(*geometry_impl->vertices), vs_cb, ps_cb, brush_impl);
740 ID3D10Buffer_Release(vb);
741 ID3D10Buffer_Release(ib);
743 if (geometry_impl->bezier_count)
745 buffer_desc.ByteWidth = geometry_impl->bezier_count * sizeof(*geometry_impl->beziers);
746 buffer_data.pSysMem = geometry_impl->beziers;
748 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device, &buffer_desc, &buffer_data, &vb)))
750 ERR("Failed to create beziers vertex buffer, hr %#x.\n", hr);
751 goto done;
754 d2d_draw(render_target, D2D_SHAPE_TYPE_BEZIER, NULL, 3 * geometry_impl->bezier_count, vb,
755 sizeof(*geometry_impl->beziers->v), vs_cb, ps_cb, brush_impl);
757 ID3D10Buffer_Release(vb);
760 done:
761 ID3D10Buffer_Release(ps_cb);
762 ID3D10Buffer_Release(vs_cb);
765 static void STDMETHODCALLTYPE d2d_d3d_render_target_FillMesh(ID2D1RenderTarget *iface,
766 ID2D1Mesh *mesh, ID2D1Brush *brush)
768 FIXME("iface %p, mesh %p, brush %p stub!\n", iface, mesh, brush);
771 static void STDMETHODCALLTYPE d2d_d3d_render_target_FillOpacityMask(ID2D1RenderTarget *iface,
772 ID2D1Bitmap *mask, ID2D1Brush *brush, D2D1_OPACITY_MASK_CONTENT content,
773 const D2D1_RECT_F *dst_rect, const D2D1_RECT_F *src_rect)
775 FIXME("iface %p, mask %p, brush %p, content %#x, dst_rect %p, src_rect %p stub!\n",
776 iface, mask, brush, content, dst_rect, src_rect);
779 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawBitmap(ID2D1RenderTarget *iface,
780 ID2D1Bitmap *bitmap, const D2D1_RECT_F *dst_rect, float opacity,
781 D2D1_BITMAP_INTERPOLATION_MODE interpolation_mode, const D2D1_RECT_F *src_rect)
783 D2D1_BITMAP_BRUSH_PROPERTIES bitmap_brush_desc;
784 D2D1_BRUSH_PROPERTIES brush_desc;
785 ID2D1BitmapBrush *brush;
786 D2D1_RECT_F s, d;
787 HRESULT hr;
789 TRACE("iface %p, bitmap %p, dst_rect %p, opacity %.8e, interpolation_mode %#x, src_rect %p.\n",
790 iface, bitmap, dst_rect, opacity, interpolation_mode, src_rect);
792 if (src_rect)
794 s = *src_rect;
796 else
798 D2D1_SIZE_F size;
800 size = ID2D1Bitmap_GetSize(bitmap);
801 s.left = 0.0f;
802 s.top = 0.0f;
803 s.right = size.width;
804 s.bottom = size.height;
807 if (dst_rect)
809 d = *dst_rect;
811 else
813 d.left = 0.0f;
814 d.top = 0.0f;
815 d.right = s.right - s.left;
816 d.bottom = s.bottom - s.top;
819 bitmap_brush_desc.extendModeX = D2D1_EXTEND_MODE_CLAMP;
820 bitmap_brush_desc.extendModeY = D2D1_EXTEND_MODE_CLAMP;
821 bitmap_brush_desc.interpolationMode = interpolation_mode;
823 brush_desc.opacity = opacity;
824 brush_desc.transform._11 = fabsf((d.right - d.left) / (s.right - s.left));
825 brush_desc.transform._21 = 0.0f;
826 brush_desc.transform._31 = min(d.left, d.right) - min(s.left, s.right) * brush_desc.transform._11;
827 brush_desc.transform._12 = 0.0f;
828 brush_desc.transform._22 = fabsf((d.bottom - d.top) / (s.bottom - s.top));
829 brush_desc.transform._32 = min(d.top, d.bottom) - min(s.top, s.bottom) * brush_desc.transform._22;
831 if (FAILED(hr = ID2D1RenderTarget_CreateBitmapBrush(iface, bitmap, &bitmap_brush_desc, &brush_desc, &brush)))
833 ERR("Failed to create bitmap brush, hr %#x.\n", hr);
834 return;
837 ID2D1RenderTarget_FillRectangle(iface, &d, (ID2D1Brush *)brush);
838 ID2D1BitmapBrush_Release(brush);
841 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawText(ID2D1RenderTarget *iface,
842 const WCHAR *string, UINT32 string_len, IDWriteTextFormat *text_format, const D2D1_RECT_F *layout_rect,
843 ID2D1Brush *brush, D2D1_DRAW_TEXT_OPTIONS options, DWRITE_MEASURING_MODE measuring_mode)
845 IDWriteTextLayout *text_layout;
846 IDWriteFactory *dwrite_factory;
847 D2D1_POINT_2F origin;
848 HRESULT hr;
850 TRACE("iface %p, string %s, string_len %u, text_format %p, layout_rect %p, "
851 "brush %p, options %#x, measuring_mode %#x.\n",
852 iface, debugstr_wn(string, string_len), string_len, text_format, layout_rect,
853 brush, options, measuring_mode);
855 if (measuring_mode != DWRITE_MEASURING_MODE_NATURAL)
856 FIXME("Ignoring measuring mode %#x.\n", measuring_mode);
858 if (FAILED(hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED,
859 &IID_IDWriteFactory, (IUnknown **)&dwrite_factory)))
861 ERR("Failed to create dwrite factory, hr %#x.\n", hr);
862 return;
865 hr = IDWriteFactory_CreateTextLayout(dwrite_factory, string, string_len, text_format,
866 layout_rect->right - layout_rect->left, layout_rect->bottom - layout_rect->top, &text_layout);
867 IDWriteFactory_Release(dwrite_factory);
868 if (FAILED(hr))
870 ERR("Failed to create text layout, hr %#x.\n", hr);
871 return;
874 d2d_point_set(&origin, layout_rect->left, layout_rect->top);
875 ID2D1RenderTarget_DrawTextLayout(iface, origin, text_layout, brush, options);
876 IDWriteTextLayout_Release(text_layout);
879 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawTextLayout(ID2D1RenderTarget *iface,
880 D2D1_POINT_2F origin, IDWriteTextLayout *layout, ID2D1Brush *brush, D2D1_DRAW_TEXT_OPTIONS options)
882 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
883 struct d2d_draw_text_layout_ctx ctx;
884 HRESULT hr;
886 TRACE("iface %p, origin {%.8e, %.8e}, layout %p, brush %p, options %#x.\n",
887 iface, origin.x, origin.y, layout, brush, options);
889 ctx.brush = brush;
890 ctx.options = options;
892 if (FAILED(hr = IDWriteTextLayout_Draw(layout,
893 &ctx, &render_target->IDWriteTextRenderer_iface, origin.x, origin.y)))
894 FIXME("Failed to draw text layout, hr %#x.\n", hr);
897 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawGlyphRun(ID2D1RenderTarget *iface,
898 D2D1_POINT_2F baseline_origin, const DWRITE_GLYPH_RUN *glyph_run, ID2D1Brush *brush,
899 DWRITE_MEASURING_MODE measuring_mode)
901 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
902 D2D1_MATRIX_3X2_F *transform, prev_transform;
903 ID2D1PathGeometry *geometry;
904 ID2D1GeometrySink *sink;
905 HRESULT hr;
907 TRACE("iface %p, baseline_origin {%.8e, %.8e}, glyph_run %p, brush %p, measuring_mode %#x.\n",
908 iface, baseline_origin.x, baseline_origin.y, glyph_run, brush, measuring_mode);
910 if (measuring_mode)
911 FIXME("Ignoring measuring mode %#x.\n", measuring_mode);
912 if (render_target->text_rendering_params)
913 FIXME("Ignoring text rendering parameters %p.\n", render_target->text_rendering_params);
914 if (render_target->drawing_state.textAntialiasMode != D2D1_TEXT_ANTIALIAS_MODE_ALIASED)
915 FIXME("Ignoring text antialiasing mode %#x.\n", render_target->drawing_state.textAntialiasMode);
917 if (FAILED(hr = ID2D1Factory_CreatePathGeometry(render_target->factory, &geometry)))
919 ERR("Failed to create geometry, hr %#x.\n", hr);
920 return;
923 if (FAILED(hr = ID2D1PathGeometry_Open(geometry, &sink)))
925 ERR("Failed to open geometry sink, hr %#x.\n", hr);
926 ID2D1PathGeometry_Release(geometry);
927 return;
930 if (FAILED(hr = IDWriteFontFace_GetGlyphRunOutline(glyph_run->fontFace, glyph_run->fontEmSize,
931 glyph_run->glyphIndices, glyph_run->glyphAdvances, glyph_run->glyphOffsets, glyph_run->glyphCount,
932 glyph_run->isSideways, glyph_run->bidiLevel & 1, (IDWriteGeometrySink *)sink)))
934 ERR("Failed to get glyph run outline, hr %#x.\n", hr);
935 ID2D1GeometrySink_Release(sink);
936 ID2D1PathGeometry_Release(geometry);
937 return;
940 if (FAILED(hr = ID2D1GeometrySink_Close(sink)))
941 ERR("Failed to close geometry sink, hr %#x.\n", hr);
942 ID2D1GeometrySink_Release(sink);
944 transform = &render_target->drawing_state.transform;
945 prev_transform = *transform;
946 transform->_31 += baseline_origin.x * transform->_11 + baseline_origin.y * transform->_21;
947 transform->_32 += baseline_origin.x * transform->_12 + baseline_origin.y * transform->_22;
948 ID2D1RenderTarget_FillGeometry(iface, (ID2D1Geometry *)geometry, brush, NULL);
949 *transform = prev_transform;
951 ID2D1PathGeometry_Release(geometry);
954 static void STDMETHODCALLTYPE d2d_d3d_render_target_SetTransform(ID2D1RenderTarget *iface,
955 const D2D1_MATRIX_3X2_F *transform)
957 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
959 TRACE("iface %p, transform %p.\n", iface, transform);
961 render_target->drawing_state.transform = *transform;
964 static void STDMETHODCALLTYPE d2d_d3d_render_target_GetTransform(ID2D1RenderTarget *iface,
965 D2D1_MATRIX_3X2_F *transform)
967 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
969 TRACE("iface %p, transform %p.\n", iface, transform);
971 *transform = render_target->drawing_state.transform;
974 static void STDMETHODCALLTYPE d2d_d3d_render_target_SetAntialiasMode(ID2D1RenderTarget *iface,
975 D2D1_ANTIALIAS_MODE antialias_mode)
977 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
979 TRACE("iface %p, antialias_mode %#x stub!\n", iface, antialias_mode);
981 render_target->drawing_state.antialiasMode = antialias_mode;
984 static D2D1_ANTIALIAS_MODE STDMETHODCALLTYPE d2d_d3d_render_target_GetAntialiasMode(ID2D1RenderTarget *iface)
986 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
988 TRACE("iface %p.\n", iface);
990 return render_target->drawing_state.antialiasMode;
993 static void STDMETHODCALLTYPE d2d_d3d_render_target_SetTextAntialiasMode(ID2D1RenderTarget *iface,
994 D2D1_TEXT_ANTIALIAS_MODE antialias_mode)
996 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
998 TRACE("iface %p, antialias_mode %#x.\n", iface, antialias_mode);
1000 render_target->drawing_state.textAntialiasMode = antialias_mode;
1003 static D2D1_TEXT_ANTIALIAS_MODE STDMETHODCALLTYPE d2d_d3d_render_target_GetTextAntialiasMode(ID2D1RenderTarget *iface)
1005 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1007 TRACE("iface %p.\n", iface);
1009 return render_target->drawing_state.textAntialiasMode;
1012 static void STDMETHODCALLTYPE d2d_d3d_render_target_SetTextRenderingParams(ID2D1RenderTarget *iface,
1013 IDWriteRenderingParams *text_rendering_params)
1015 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1017 TRACE("iface %p, text_rendering_params %p.\n", iface, text_rendering_params);
1019 if (text_rendering_params)
1020 IDWriteRenderingParams_AddRef(text_rendering_params);
1021 if (render_target->text_rendering_params)
1022 IDWriteRenderingParams_Release(render_target->text_rendering_params);
1023 render_target->text_rendering_params = text_rendering_params;
1026 static void STDMETHODCALLTYPE d2d_d3d_render_target_GetTextRenderingParams(ID2D1RenderTarget *iface,
1027 IDWriteRenderingParams **text_rendering_params)
1029 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1031 TRACE("iface %p, text_rendering_params %p.\n", iface, text_rendering_params);
1033 if ((*text_rendering_params = render_target->text_rendering_params))
1034 IDWriteRenderingParams_AddRef(*text_rendering_params);
1037 static void STDMETHODCALLTYPE d2d_d3d_render_target_SetTags(ID2D1RenderTarget *iface, D2D1_TAG tag1, D2D1_TAG tag2)
1039 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1041 TRACE("iface %p, tag1 %s, tag2 %s.\n", iface, wine_dbgstr_longlong(tag1), wine_dbgstr_longlong(tag2));
1043 render_target->drawing_state.tag1 = tag1;
1044 render_target->drawing_state.tag2 = tag2;
1047 static void STDMETHODCALLTYPE d2d_d3d_render_target_GetTags(ID2D1RenderTarget *iface, D2D1_TAG *tag1, D2D1_TAG *tag2)
1049 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1051 TRACE("iface %p, tag1 %p, tag2 %p.\n", iface, tag1, tag2);
1053 *tag1 = render_target->drawing_state.tag1;
1054 *tag2 = render_target->drawing_state.tag2;
1057 static void STDMETHODCALLTYPE d2d_d3d_render_target_PushLayer(ID2D1RenderTarget *iface,
1058 const D2D1_LAYER_PARAMETERS *layer_parameters, ID2D1Layer *layer)
1060 FIXME("iface %p, layer_parameters %p, layer %p stub!\n", iface, layer_parameters, layer);
1063 static void STDMETHODCALLTYPE d2d_d3d_render_target_PopLayer(ID2D1RenderTarget *iface)
1065 FIXME("iface %p stub!\n", iface);
1068 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_Flush(ID2D1RenderTarget *iface, D2D1_TAG *tag1, D2D1_TAG *tag2)
1070 FIXME("iface %p, tag1 %p, tag2 %p stub!\n", iface, tag1, tag2);
1072 return E_NOTIMPL;
1075 static void STDMETHODCALLTYPE d2d_d3d_render_target_SaveDrawingState(ID2D1RenderTarget *iface,
1076 ID2D1DrawingStateBlock *state_block)
1078 struct d2d_state_block *state_block_impl = unsafe_impl_from_ID2D1DrawingStateBlock(state_block);
1079 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1081 TRACE("iface %p, state_block %p.\n", iface, state_block);
1083 state_block_impl->drawing_state = render_target->drawing_state;
1084 if (render_target->text_rendering_params)
1085 IDWriteRenderingParams_AddRef(render_target->text_rendering_params);
1086 if (state_block_impl->text_rendering_params)
1087 IDWriteRenderingParams_Release(state_block_impl->text_rendering_params);
1088 state_block_impl->text_rendering_params = render_target->text_rendering_params;
1091 static void STDMETHODCALLTYPE d2d_d3d_render_target_RestoreDrawingState(ID2D1RenderTarget *iface,
1092 ID2D1DrawingStateBlock *state_block)
1094 struct d2d_state_block *state_block_impl = unsafe_impl_from_ID2D1DrawingStateBlock(state_block);
1095 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1097 TRACE("iface %p, state_block %p.\n", iface, state_block);
1099 render_target->drawing_state = state_block_impl->drawing_state;
1100 if (state_block_impl->text_rendering_params)
1101 IDWriteRenderingParams_AddRef(state_block_impl->text_rendering_params);
1102 if (render_target->text_rendering_params)
1103 IDWriteRenderingParams_Release(render_target->text_rendering_params);
1104 render_target->text_rendering_params = state_block_impl->text_rendering_params;
1107 static void STDMETHODCALLTYPE d2d_d3d_render_target_PushAxisAlignedClip(ID2D1RenderTarget *iface,
1108 const D2D1_RECT_F *clip_rect, D2D1_ANTIALIAS_MODE antialias_mode)
1110 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1111 D2D1_RECT_F transformed_rect;
1112 float x_scale, y_scale;
1113 D2D1_POINT_2F point;
1115 TRACE("iface %p, clip_rect %p, antialias_mode %#x.\n", iface, clip_rect, antialias_mode);
1117 if (antialias_mode != D2D1_ANTIALIAS_MODE_ALIASED)
1118 FIXME("Ignoring antialias_mode %#x.\n", antialias_mode);
1120 x_scale = render_target->dpi_x / 96.0f;
1121 y_scale = render_target->dpi_y / 96.0f;
1122 d2d_point_transform(&point, &render_target->drawing_state.transform,
1123 clip_rect->left * x_scale, clip_rect->top * y_scale);
1124 d2d_rect_set(&transformed_rect, point.x, point.y, point.x, point.y);
1125 d2d_point_transform(&point, &render_target->drawing_state.transform,
1126 clip_rect->left * x_scale, clip_rect->bottom * y_scale);
1127 d2d_rect_expand(&transformed_rect, &point);
1128 d2d_point_transform(&point, &render_target->drawing_state.transform,
1129 clip_rect->right * x_scale, clip_rect->top * y_scale);
1130 d2d_rect_expand(&transformed_rect, &point);
1131 d2d_point_transform(&point, &render_target->drawing_state.transform,
1132 clip_rect->right * x_scale, clip_rect->bottom * y_scale);
1133 d2d_rect_expand(&transformed_rect, &point);
1135 if (!d2d_clip_stack_push(&render_target->clip_stack, &transformed_rect))
1136 WARN("Failed to push clip rect.\n");
1139 static void STDMETHODCALLTYPE d2d_d3d_render_target_PopAxisAlignedClip(ID2D1RenderTarget *iface)
1141 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1143 TRACE("iface %p.\n", iface);
1145 d2d_clip_stack_pop(&render_target->clip_stack);
1148 static void STDMETHODCALLTYPE d2d_d3d_render_target_Clear(ID2D1RenderTarget *iface, const D2D1_COLOR_F *color)
1150 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1151 D2D1_COLOR_F c = {0.0f, 0.0f, 0.0f, 0.0f};
1152 D3D10_SUBRESOURCE_DATA buffer_data;
1153 D3D10_BUFFER_DESC buffer_desc;
1154 ID3D10Buffer *vs_cb, *ps_cb;
1155 HRESULT hr;
1157 static const float transform[] =
1159 1.0f, 0.0f, 0.0f, 0.0f,
1160 0.0f, -1.0f, 0.0f, 0.0f,
1163 TRACE("iface %p, color %p.\n", iface, color);
1165 buffer_desc.ByteWidth = sizeof(transform);
1166 buffer_desc.Usage = D3D10_USAGE_DEFAULT;
1167 buffer_desc.BindFlags = D3D10_BIND_CONSTANT_BUFFER;
1168 buffer_desc.CPUAccessFlags = 0;
1169 buffer_desc.MiscFlags = 0;
1171 buffer_data.pSysMem = transform;
1172 buffer_data.SysMemPitch = 0;
1173 buffer_data.SysMemSlicePitch = 0;
1175 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device, &buffer_desc, &buffer_data, &vs_cb)))
1177 WARN("Failed to create constant buffer, hr %#x.\n", hr);
1178 return;
1181 if (color)
1182 c = *color;
1183 if (render_target->format.alphaMode == D2D1_ALPHA_MODE_IGNORE)
1184 c.a = 1.0f;
1185 c.r *= c.a;
1186 c.g *= c.a;
1187 c.b *= c.a;
1188 buffer_desc.ByteWidth = sizeof(c);
1189 buffer_data.pSysMem = &c;
1191 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device, &buffer_desc, &buffer_data, &ps_cb)))
1193 WARN("Failed to create constant buffer, hr %#x.\n", hr);
1194 ID3D10Buffer_Release(vs_cb);
1195 return;
1198 d2d_draw(render_target, D2D_SHAPE_TYPE_TRIANGLE, render_target->ib, 6,
1199 render_target->vb, render_target->vb_stride, vs_cb, ps_cb, NULL);
1201 ID3D10Buffer_Release(ps_cb);
1202 ID3D10Buffer_Release(vs_cb);
1205 static void STDMETHODCALLTYPE d2d_d3d_render_target_BeginDraw(ID2D1RenderTarget *iface)
1207 TRACE("iface %p.\n", iface);
1210 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_EndDraw(ID2D1RenderTarget *iface,
1211 D2D1_TAG *tag1, D2D1_TAG *tag2)
1213 TRACE("iface %p, tag1 %p, tag2 %p.\n", iface, tag1, tag2);
1215 if (tag1)
1216 *tag1 = 0;
1217 if (tag2)
1218 *tag2 = 0;
1220 return S_OK;
1223 static D2D1_PIXEL_FORMAT * STDMETHODCALLTYPE d2d_d3d_render_target_GetPixelFormat(ID2D1RenderTarget *iface,
1224 D2D1_PIXEL_FORMAT *format)
1226 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1228 TRACE("iface %p, format %p.\n", iface, format);
1230 *format = render_target->format;
1231 return format;
1234 static void STDMETHODCALLTYPE d2d_d3d_render_target_SetDpi(ID2D1RenderTarget *iface, float dpi_x, float dpi_y)
1236 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1238 TRACE("iface %p, dpi_x %.8e, dpi_y %.8e.\n", iface, dpi_x, dpi_y);
1240 if (dpi_x == 0.0f && dpi_y == 0.0f)
1242 dpi_x = 96.0f;
1243 dpi_y = 96.0f;
1246 render_target->dpi_x = dpi_x;
1247 render_target->dpi_y = dpi_y;
1250 static void STDMETHODCALLTYPE d2d_d3d_render_target_GetDpi(ID2D1RenderTarget *iface, float *dpi_x, float *dpi_y)
1252 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1254 TRACE("iface %p, dpi_x %p, dpi_y %p.\n", iface, dpi_x, dpi_y);
1256 *dpi_x = render_target->dpi_x;
1257 *dpi_y = render_target->dpi_y;
1260 static D2D1_SIZE_F * STDMETHODCALLTYPE d2d_d3d_render_target_GetSize(ID2D1RenderTarget *iface, D2D1_SIZE_F *size)
1262 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1264 TRACE("iface %p, size %p.\n", iface, size);
1266 size->width = render_target->pixel_size.width / (render_target->dpi_x / 96.0f);
1267 size->height = render_target->pixel_size.height / (render_target->dpi_y / 96.0f);
1268 return size;
1271 static D2D1_SIZE_U * STDMETHODCALLTYPE d2d_d3d_render_target_GetPixelSize(ID2D1RenderTarget *iface,
1272 D2D1_SIZE_U *pixel_size)
1274 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1276 TRACE("iface %p, pixel_size %p.\n", iface, pixel_size);
1278 *pixel_size = render_target->pixel_size;
1279 return pixel_size;
1282 static UINT32 STDMETHODCALLTYPE d2d_d3d_render_target_GetMaximumBitmapSize(ID2D1RenderTarget *iface)
1284 FIXME("iface %p stub!\n", iface);
1286 return 0;
1289 static BOOL STDMETHODCALLTYPE d2d_d3d_render_target_IsSupported(ID2D1RenderTarget *iface,
1290 const D2D1_RENDER_TARGET_PROPERTIES *desc)
1292 FIXME("iface %p, desc %p stub!\n", iface, desc);
1294 return FALSE;
1297 static const struct ID2D1RenderTargetVtbl d2d_d3d_render_target_vtbl =
1299 d2d_d3d_render_target_QueryInterface,
1300 d2d_d3d_render_target_AddRef,
1301 d2d_d3d_render_target_Release,
1302 d2d_d3d_render_target_GetFactory,
1303 d2d_d3d_render_target_CreateBitmap,
1304 d2d_d3d_render_target_CreateBitmapFromWicBitmap,
1305 d2d_d3d_render_target_CreateSharedBitmap,
1306 d2d_d3d_render_target_CreateBitmapBrush,
1307 d2d_d3d_render_target_CreateSolidColorBrush,
1308 d2d_d3d_render_target_CreateGradientStopCollection,
1309 d2d_d3d_render_target_CreateLinearGradientBrush,
1310 d2d_d3d_render_target_CreateRadialGradientBrush,
1311 d2d_d3d_render_target_CreateCompatibleRenderTarget,
1312 d2d_d3d_render_target_CreateLayer,
1313 d2d_d3d_render_target_CreateMesh,
1314 d2d_d3d_render_target_DrawLine,
1315 d2d_d3d_render_target_DrawRectangle,
1316 d2d_d3d_render_target_FillRectangle,
1317 d2d_d3d_render_target_DrawRoundedRectangle,
1318 d2d_d3d_render_target_FillRoundedRectangle,
1319 d2d_d3d_render_target_DrawEllipse,
1320 d2d_d3d_render_target_FillEllipse,
1321 d2d_d3d_render_target_DrawGeometry,
1322 d2d_d3d_render_target_FillGeometry,
1323 d2d_d3d_render_target_FillMesh,
1324 d2d_d3d_render_target_FillOpacityMask,
1325 d2d_d3d_render_target_DrawBitmap,
1326 d2d_d3d_render_target_DrawText,
1327 d2d_d3d_render_target_DrawTextLayout,
1328 d2d_d3d_render_target_DrawGlyphRun,
1329 d2d_d3d_render_target_SetTransform,
1330 d2d_d3d_render_target_GetTransform,
1331 d2d_d3d_render_target_SetAntialiasMode,
1332 d2d_d3d_render_target_GetAntialiasMode,
1333 d2d_d3d_render_target_SetTextAntialiasMode,
1334 d2d_d3d_render_target_GetTextAntialiasMode,
1335 d2d_d3d_render_target_SetTextRenderingParams,
1336 d2d_d3d_render_target_GetTextRenderingParams,
1337 d2d_d3d_render_target_SetTags,
1338 d2d_d3d_render_target_GetTags,
1339 d2d_d3d_render_target_PushLayer,
1340 d2d_d3d_render_target_PopLayer,
1341 d2d_d3d_render_target_Flush,
1342 d2d_d3d_render_target_SaveDrawingState,
1343 d2d_d3d_render_target_RestoreDrawingState,
1344 d2d_d3d_render_target_PushAxisAlignedClip,
1345 d2d_d3d_render_target_PopAxisAlignedClip,
1346 d2d_d3d_render_target_Clear,
1347 d2d_d3d_render_target_BeginDraw,
1348 d2d_d3d_render_target_EndDraw,
1349 d2d_d3d_render_target_GetPixelFormat,
1350 d2d_d3d_render_target_SetDpi,
1351 d2d_d3d_render_target_GetDpi,
1352 d2d_d3d_render_target_GetSize,
1353 d2d_d3d_render_target_GetPixelSize,
1354 d2d_d3d_render_target_GetMaximumBitmapSize,
1355 d2d_d3d_render_target_IsSupported,
1358 static inline struct d2d_d3d_render_target *impl_from_IDWriteTextRenderer(IDWriteTextRenderer *iface)
1360 return CONTAINING_RECORD(iface, struct d2d_d3d_render_target, IDWriteTextRenderer_iface);
1363 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_QueryInterface(IDWriteTextRenderer *iface, REFIID iid, void **out)
1365 TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
1367 if (IsEqualGUID(iid, &IID_IDWriteTextRenderer)
1368 || IsEqualGUID(iid, &IID_IDWritePixelSnapping)
1369 || IsEqualGUID(iid, &IID_IUnknown))
1371 IDWriteTextRenderer_AddRef(iface);
1372 *out = iface;
1373 return S_OK;
1376 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
1378 *out = NULL;
1379 return E_NOINTERFACE;
1382 static ULONG STDMETHODCALLTYPE d2d_text_renderer_AddRef(IDWriteTextRenderer *iface)
1384 struct d2d_d3d_render_target *render_target = impl_from_IDWriteTextRenderer(iface);
1386 TRACE("iface %p.\n", iface);
1388 return d2d_d3d_render_target_AddRef(&render_target->ID2D1RenderTarget_iface);
1391 static ULONG STDMETHODCALLTYPE d2d_text_renderer_Release(IDWriteTextRenderer *iface)
1393 struct d2d_d3d_render_target *render_target = impl_from_IDWriteTextRenderer(iface);
1395 TRACE("iface %p.\n", iface);
1397 return d2d_d3d_render_target_Release(&render_target->ID2D1RenderTarget_iface);
1400 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_IsPixelSnappingDisabled(IDWriteTextRenderer *iface,
1401 void *ctx, BOOL *disabled)
1403 struct d2d_draw_text_layout_ctx *context = ctx;
1405 TRACE("iface %p, ctx %p, disabled %p.\n", iface, ctx, disabled);
1407 *disabled = context->options & D2D1_DRAW_TEXT_OPTIONS_NO_SNAP;
1409 return S_OK;
1412 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_GetCurrentTransform(IDWriteTextRenderer *iface,
1413 void *ctx, DWRITE_MATRIX *transform)
1415 struct d2d_d3d_render_target *render_target = impl_from_IDWriteTextRenderer(iface);
1417 TRACE("iface %p, ctx %p, transform %p.\n", iface, ctx, transform);
1419 ID2D1RenderTarget_GetTransform(&render_target->ID2D1RenderTarget_iface, (D2D1_MATRIX_3X2_F *)transform);
1421 return S_OK;
1424 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_GetPixelsPerDip(IDWriteTextRenderer *iface, void *ctx, float *ppd)
1426 struct d2d_d3d_render_target *render_target = impl_from_IDWriteTextRenderer(iface);
1428 TRACE("iface %p, ctx %p, ppd %p.\n", iface, ctx, ppd);
1430 *ppd = render_target->dpi_y / 96.0f;
1432 return S_OK;
1435 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_DrawGlyphRun(IDWriteTextRenderer *iface, void *ctx,
1436 float baseline_origin_x, float baseline_origin_y, DWRITE_MEASURING_MODE measuring_mode,
1437 const DWRITE_GLYPH_RUN *glyph_run, const DWRITE_GLYPH_RUN_DESCRIPTION *desc, IUnknown *effect)
1439 struct d2d_d3d_render_target *render_target = impl_from_IDWriteTextRenderer(iface);
1440 D2D1_POINT_2F baseline_origin = {baseline_origin_x, baseline_origin_y};
1441 struct d2d_draw_text_layout_ctx *context = ctx;
1443 TRACE("iface %p, ctx %p, baseline_origin_x %.8e, baseline_origin_y %.8e, "
1444 "measuring_mode %#x, glyph_run %p, desc %p, effect %p.\n",
1445 iface, ctx, baseline_origin_x, baseline_origin_y,
1446 measuring_mode, glyph_run, desc, effect);
1448 if (desc)
1449 FIXME("Ignoring glyph run description %p.\n", desc);
1450 if (effect)
1451 FIXME("Ignoring effect %p.\n", effect);
1452 if (context->options & ~D2D1_DRAW_TEXT_OPTIONS_NO_SNAP)
1453 FIXME("Ignoring options %#x.\n", context->options);
1455 TRACE("%s\n", debugstr_wn(desc->string, desc->stringLength));
1456 ID2D1RenderTarget_DrawGlyphRun(&render_target->ID2D1RenderTarget_iface,
1457 baseline_origin, glyph_run, context->brush, measuring_mode);
1459 return S_OK;
1462 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_DrawUnderline(IDWriteTextRenderer *iface, void *ctx,
1463 float baseline_origin_x, float baseline_origin_y, const DWRITE_UNDERLINE *underline, IUnknown *effect)
1465 FIXME("iface %p, ctx %p, baseline_origin_x %.8e, baseline_origin_y %.8e, underline %p, effect %p stub!\n",
1466 iface, ctx, baseline_origin_x, baseline_origin_y, underline, effect);
1468 return E_NOTIMPL;
1471 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_DrawStrikethrough(IDWriteTextRenderer *iface, void *ctx,
1472 float baseline_origin_x, float baseline_origin_y, const DWRITE_STRIKETHROUGH *strikethrough, IUnknown *effect)
1474 FIXME("iface %p, ctx %p, baseline_origin_x %.8e, baseline_origin_y %.8e, strikethrough %p, effect %p stub!\n",
1475 iface, ctx, baseline_origin_x, baseline_origin_y, strikethrough, effect);
1477 return E_NOTIMPL;
1480 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_DrawInlineObject(IDWriteTextRenderer *iface, void *ctx,
1481 float origin_x, float origin_y, IDWriteInlineObject *object, BOOL is_sideways, BOOL is_rtl, IUnknown *effect)
1483 FIXME("iface %p, ctx %p, origin_x %.8e, origin_y %.8e, object %p, is_sideways %#x, is_rtl %#x, effect %p stub!\n",
1484 iface, ctx, origin_x, origin_y, object, is_sideways, is_rtl, effect);
1486 return E_NOTIMPL;
1489 static const struct IDWriteTextRendererVtbl d2d_text_renderer_vtbl =
1491 d2d_text_renderer_QueryInterface,
1492 d2d_text_renderer_AddRef,
1493 d2d_text_renderer_Release,
1494 d2d_text_renderer_IsPixelSnappingDisabled,
1495 d2d_text_renderer_GetCurrentTransform,
1496 d2d_text_renderer_GetPixelsPerDip,
1497 d2d_text_renderer_DrawGlyphRun,
1498 d2d_text_renderer_DrawUnderline,
1499 d2d_text_renderer_DrawStrikethrough,
1500 d2d_text_renderer_DrawInlineObject,
1503 HRESULT d2d_d3d_render_target_init(struct d2d_d3d_render_target *render_target, ID2D1Factory *factory,
1504 IDXGISurface *surface, const D2D1_RENDER_TARGET_PROPERTIES *desc)
1506 D3D10_SUBRESOURCE_DATA buffer_data;
1507 D3D10_STATE_BLOCK_MASK state_mask;
1508 DXGI_SURFACE_DESC surface_desc;
1509 D3D10_RASTERIZER_DESC rs_desc;
1510 D3D10_BUFFER_DESC buffer_desc;
1511 D3D10_BLEND_DESC blend_desc;
1512 ID3D10Resource *resource;
1513 unsigned int i, j;
1514 HRESULT hr;
1516 static const D3D10_INPUT_ELEMENT_DESC il_desc_triangle[] =
1518 {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0},
1520 static const D3D10_INPUT_ELEMENT_DESC il_desc_bezier[] =
1522 {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0},
1523 {"TEXCOORD", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 8, D3D10_INPUT_PER_VERTEX_DATA, 0},
1525 static const DWORD vs_code_triangle[] =
1527 /* float3x2 transform;
1529 * float4 main(float4 position : POSITION) : SV_POSITION
1531 * return float4(mul(position.xyw, transform), position.zw);
1532 * } */
1533 0x43425844, 0x0add3194, 0x205f74ec, 0xab527fe7, 0xbe6ad704, 0x00000001, 0x00000128, 0x00000003,
1534 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020,
1535 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000f0f, 0x49534f50, 0x4e4f4954, 0xababab00,
1536 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000001, 0x00000003,
1537 0x00000000, 0x0000000f, 0x505f5653, 0x5449534f, 0x004e4f49, 0x52444853, 0x0000008c, 0x00010040,
1538 0x00000023, 0x04000059, 0x00208e46, 0x00000000, 0x00000002, 0x0300005f, 0x001010f2, 0x00000000,
1539 0x04000067, 0x001020f2, 0x00000000, 0x00000001, 0x08000010, 0x00102012, 0x00000000, 0x00101346,
1540 0x00000000, 0x00208246, 0x00000000, 0x00000000, 0x08000010, 0x00102022, 0x00000000, 0x00101346,
1541 0x00000000, 0x00208246, 0x00000000, 0x00000001, 0x05000036, 0x001020c2, 0x00000000, 0x00101ea6,
1542 0x00000000, 0x0100003e,
1544 static const DWORD vs_code_bezier[] =
1546 #if 0
1547 float3x2 transform;
1549 float4 main(float4 position : POSITION,
1550 inout float3 texcoord : TEXCOORD0) : SV_POSITION
1552 return float4(mul(position.xyw, transform), position.zw);
1554 #endif
1555 0x43425844, 0x5e578adb, 0x093f7e27, 0x50d478af, 0xec3dfa4f, 0x00000001, 0x00000198, 0x00000003,
1556 0x0000002c, 0x00000080, 0x000000d8, 0x4e475349, 0x0000004c, 0x00000002, 0x00000008, 0x00000038,
1557 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000f0f, 0x00000041, 0x00000000, 0x00000000,
1558 0x00000003, 0x00000001, 0x00000707, 0x49534f50, 0x4e4f4954, 0x58455400, 0x524f4f43, 0xabab0044,
1559 0x4e47534f, 0x00000050, 0x00000002, 0x00000008, 0x00000038, 0x00000000, 0x00000001, 0x00000003,
1560 0x00000000, 0x0000000f, 0x00000044, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x00000807,
1561 0x505f5653, 0x5449534f, 0x004e4f49, 0x43584554, 0x44524f4f, 0xababab00, 0x52444853, 0x000000b8,
1562 0x00010040, 0x0000002e, 0x04000059, 0x00208e46, 0x00000000, 0x00000002, 0x0300005f, 0x001010f2,
1563 0x00000000, 0x0300005f, 0x00101072, 0x00000001, 0x04000067, 0x001020f2, 0x00000000, 0x00000001,
1564 0x03000065, 0x00102072, 0x00000001, 0x08000010, 0x00102012, 0x00000000, 0x00101346, 0x00000000,
1565 0x00208246, 0x00000000, 0x00000000, 0x08000010, 0x00102022, 0x00000000, 0x00101346, 0x00000000,
1566 0x00208246, 0x00000000, 0x00000001, 0x05000036, 0x001020c2, 0x00000000, 0x00101ea6, 0x00000000,
1567 0x05000036, 0x00102072, 0x00000001, 0x00101246, 0x00000001, 0x0100003e,
1569 static const DWORD ps_code_triangle_solid[] =
1571 /* float4 color;
1573 * float4 main(float4 position : SV_POSITION) : SV_Target
1575 * return color;
1576 * } */
1577 0x43425844, 0x88eefcfd, 0x93d6fd47, 0x173c242f, 0x0106d07a, 0x00000001, 0x000000dc, 0x00000003,
1578 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020,
1579 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x505f5653, 0x5449534f, 0x004e4f49,
1580 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003,
1581 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x00000040, 0x00000040,
1582 0x00000010, 0x04000059, 0x00208e46, 0x00000000, 0x00000001, 0x03000065, 0x001020f2, 0x00000000,
1583 0x06000036, 0x001020f2, 0x00000000, 0x00208e46, 0x00000000, 0x00000000, 0x0100003e,
1585 static const DWORD ps_code_triangle_bitmap[] =
1587 #if 0
1588 float3x2 transform;
1589 float opacity;
1590 bool ignore_alpha;
1592 SamplerState s;
1593 Texture2D t;
1595 float4 main(float4 position : SV_POSITION) : SV_Target
1597 float2 texcoord;
1598 float4 ret;
1600 texcoord.x = position.x * transform._11 + position.y * transform._21 + transform._31;
1601 texcoord.y = position.x * transform._12 + position.y * transform._22 + transform._32;
1602 ret = t.Sample(s, texcoord) * opacity;
1603 if (ignore_alpha)
1604 ret.a = opacity;
1606 return ret;
1608 #endif
1609 0x43425844, 0xf5bb1e01, 0xe3386963, 0xcaa095bd, 0xea2887de, 0x00000001, 0x000001fc, 0x00000003,
1610 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020,
1611 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000030f, 0x505f5653, 0x5449534f, 0x004e4f49,
1612 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003,
1613 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x00000160, 0x00000040,
1614 0x00000058, 0x04000059, 0x00208e46, 0x00000000, 0x00000003, 0x0300005a, 0x00106000, 0x00000000,
1615 0x04001858, 0x00107000, 0x00000000, 0x00005555, 0x04002064, 0x00101032, 0x00000000, 0x00000001,
1616 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000001, 0x0800000f, 0x00100012, 0x00000000,
1617 0x00101046, 0x00000000, 0x00208046, 0x00000000, 0x00000000, 0x08000000, 0x00100012, 0x00000000,
1618 0x0010000a, 0x00000000, 0x0020802a, 0x00000000, 0x00000000, 0x0800000f, 0x00100042, 0x00000000,
1619 0x00101046, 0x00000000, 0x00208046, 0x00000000, 0x00000001, 0x08000000, 0x00100022, 0x00000000,
1620 0x0010002a, 0x00000000, 0x0020802a, 0x00000000, 0x00000001, 0x09000045, 0x001000f2, 0x00000000,
1621 0x00100046, 0x00000000, 0x00107e46, 0x00000000, 0x00106000, 0x00000000, 0x08000038, 0x001000f2,
1622 0x00000000, 0x00100e46, 0x00000000, 0x00208ff6, 0x00000000, 0x00000001, 0x0b000037, 0x00102082,
1623 0x00000000, 0x0020800a, 0x00000000, 0x00000002, 0x0020803a, 0x00000000, 0x00000001, 0x0010003a,
1624 0x00000000, 0x05000036, 0x00102072, 0x00000000, 0x00100246, 0x00000000, 0x0100003e,
1626 /* The basic idea here is to evaluate the implicit form of the curve in
1627 * texture space. "t.z" determines which side of the curve is shaded. */
1628 static const DWORD ps_code_bezier_solid[] =
1630 #if 0
1631 float4 color;
1633 float4 main(float4 position : SV_POSITION, float3 t : TEXCOORD0) : SV_Target
1635 clip((t.x * t.x - t.y) * t.z);
1636 return color;
1638 #endif
1639 0x43425844, 0x66075f9e, 0x2ffe405b, 0xb551ee63, 0xa0d9f457, 0x00000001, 0x00000180, 0x00000003,
1640 0x0000002c, 0x00000084, 0x000000b8, 0x4e475349, 0x00000050, 0x00000002, 0x00000008, 0x00000038,
1641 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x00000044, 0x00000000, 0x00000000,
1642 0x00000003, 0x00000001, 0x00000707, 0x505f5653, 0x5449534f, 0x004e4f49, 0x43584554, 0x44524f4f,
1643 0xababab00, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000,
1644 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x000000c0,
1645 0x00000040, 0x00000030, 0x04000059, 0x00208e46, 0x00000000, 0x00000001, 0x03001062, 0x00101072,
1646 0x00000001, 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000001, 0x0a000032, 0x00100012,
1647 0x00000000, 0x0010100a, 0x00000001, 0x0010100a, 0x00000001, 0x8010101a, 0x00000041, 0x00000001,
1648 0x07000038, 0x00100012, 0x00000000, 0x0010000a, 0x00000000, 0x0010102a, 0x00000001, 0x07000031,
1649 0x00100012, 0x00000000, 0x0010000a, 0x00000000, 0x00004001, 0x00000000, 0x0304000d, 0x0010000a,
1650 0x00000000, 0x06000036, 0x001020f2, 0x00000000, 0x00208e46, 0x00000000, 0x00000000, 0x0100003e,
1652 static const struct
1654 float x, y;
1656 quad[] =
1658 {-1.0f, 1.0f},
1659 {-1.0f, -1.0f},
1660 { 1.0f, 1.0f},
1661 { 1.0f, -1.0f},
1663 static const UINT16 indices[] = {0, 1, 2, 2, 1, 3};
1664 static const D2D1_MATRIX_3X2_F identity =
1666 1.0f, 0.0f,
1667 0.0f, 1.0f,
1668 0.0f, 0.0f,
1671 FIXME("Ignoring render target properties.\n");
1673 render_target->ID2D1RenderTarget_iface.lpVtbl = &d2d_d3d_render_target_vtbl;
1674 render_target->IDWriteTextRenderer_iface.lpVtbl = &d2d_text_renderer_vtbl;
1675 render_target->refcount = 1;
1676 render_target->factory = factory;
1677 ID2D1Factory_AddRef(render_target->factory);
1679 if (FAILED(hr = IDXGISurface_GetDevice(surface, &IID_ID3D10Device, (void **)&render_target->device)))
1681 WARN("Failed to get device interface, hr %#x.\n", hr);
1682 ID2D1Factory_Release(render_target->factory);
1683 return hr;
1686 if (FAILED(hr = IDXGISurface_QueryInterface(surface, &IID_ID3D10Resource, (void **)&resource)))
1688 WARN("Failed to get ID3D10Resource interface, hr %#x.\n", hr);
1689 goto err;
1692 hr = ID3D10Device_CreateRenderTargetView(render_target->device, resource, NULL, &render_target->view);
1693 ID3D10Resource_Release(resource);
1694 if (FAILED(hr))
1696 WARN("Failed to create rendertarget view, hr %#x.\n", hr);
1697 goto err;
1700 if (FAILED(hr = D3D10StateBlockMaskEnableAll(&state_mask)))
1702 WARN("Failed to create stateblock mask, hr %#x.\n", hr);
1703 goto err;
1706 if (FAILED(hr = D3D10CreateStateBlock(render_target->device, &state_mask, &render_target->stateblock)))
1708 WARN("Failed to create stateblock, hr %#x.\n", hr);
1709 goto err;
1712 if (FAILED(hr = ID3D10Device_CreateInputLayout(render_target->device, il_desc_triangle,
1713 sizeof(il_desc_triangle) / sizeof(*il_desc_triangle), vs_code_triangle, sizeof(vs_code_triangle),
1714 &render_target->shape_resources[D2D_SHAPE_TYPE_TRIANGLE].il)))
1716 WARN("Failed to create triangle input layout, hr %#x.\n", hr);
1717 goto err;
1720 if (FAILED(hr = ID3D10Device_CreateInputLayout(render_target->device, il_desc_bezier,
1721 sizeof(il_desc_bezier) / sizeof(*il_desc_bezier), vs_code_bezier, sizeof(vs_code_bezier),
1722 &render_target->shape_resources[D2D_SHAPE_TYPE_BEZIER].il)))
1724 WARN("Failed to create bezier input layout, hr %#x.\n", hr);
1725 goto err;
1728 if (FAILED(hr = ID3D10Device_CreateVertexShader(render_target->device, vs_code_triangle,
1729 sizeof(vs_code_triangle), &render_target->shape_resources[D2D_SHAPE_TYPE_TRIANGLE].vs)))
1731 WARN("Failed to create triangle vertex shader, hr %#x.\n", hr);
1732 goto err;
1735 if (FAILED(hr = ID3D10Device_CreateVertexShader(render_target->device, vs_code_bezier,
1736 sizeof(vs_code_bezier), &render_target->shape_resources[D2D_SHAPE_TYPE_BEZIER].vs)))
1738 WARN("Failed to create bezier vertex shader, hr %#x.\n", hr);
1739 goto err;
1742 if (FAILED(hr = ID3D10Device_CreatePixelShader(render_target->device,
1743 ps_code_triangle_solid, sizeof(ps_code_triangle_solid),
1744 &render_target->shape_resources[D2D_SHAPE_TYPE_TRIANGLE].ps[D2D_BRUSH_TYPE_SOLID])))
1746 WARN("Failed to create triangle/solid pixel shader, hr %#x.\n", hr);
1747 goto err;
1750 if (FAILED(hr = ID3D10Device_CreatePixelShader(render_target->device,
1751 ps_code_triangle_bitmap, sizeof(ps_code_triangle_bitmap),
1752 &render_target->shape_resources[D2D_SHAPE_TYPE_TRIANGLE].ps[D2D_BRUSH_TYPE_BITMAP])))
1754 WARN("Failed to create triangle/bitmap pixel shader, hr %#x.\n", hr);
1755 goto err;
1758 if (FAILED(hr = ID3D10Device_CreatePixelShader(render_target->device,
1759 ps_code_bezier_solid, sizeof(ps_code_bezier_solid),
1760 &render_target->shape_resources[D2D_SHAPE_TYPE_BEZIER].ps[D2D_BRUSH_TYPE_SOLID])))
1762 WARN("Failed to create bezier/solid pixel shader, hr %#x.\n", hr);
1763 goto err;
1766 buffer_desc.ByteWidth = sizeof(indices);
1767 buffer_desc.Usage = D3D10_USAGE_DEFAULT;
1768 buffer_desc.BindFlags = D3D10_BIND_INDEX_BUFFER;
1769 buffer_desc.CPUAccessFlags = 0;
1770 buffer_desc.MiscFlags = 0;
1772 buffer_data.pSysMem = indices;
1773 buffer_data.SysMemPitch = 0;
1774 buffer_data.SysMemSlicePitch = 0;
1776 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device,
1777 &buffer_desc, &buffer_data, &render_target->ib)))
1779 WARN("Failed to create clear index buffer, hr %#x.\n", hr);
1780 goto err;
1783 buffer_desc.ByteWidth = sizeof(quad);
1784 buffer_desc.BindFlags = D3D10_BIND_VERTEX_BUFFER;
1785 buffer_data.pSysMem = quad;
1787 render_target->vb_stride = sizeof(*quad);
1788 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device,
1789 &buffer_desc, &buffer_data, &render_target->vb)))
1791 WARN("Failed to create clear vertex buffer, hr %#x.\n", hr);
1792 goto err;
1795 rs_desc.FillMode = D3D10_FILL_SOLID;
1796 rs_desc.CullMode = D3D10_CULL_BACK;
1797 rs_desc.FrontCounterClockwise = FALSE;
1798 rs_desc.DepthBias = 0;
1799 rs_desc.DepthBiasClamp = 0.0f;
1800 rs_desc.SlopeScaledDepthBias = 0.0f;
1801 rs_desc.DepthClipEnable = TRUE;
1802 rs_desc.ScissorEnable = TRUE;
1803 rs_desc.MultisampleEnable = FALSE;
1804 rs_desc.AntialiasedLineEnable = FALSE;
1805 if (FAILED(hr = ID3D10Device_CreateRasterizerState(render_target->device, &rs_desc, &render_target->rs)))
1807 WARN("Failed to create clear rasterizer state, hr %#x.\n", hr);
1808 goto err;
1811 memset(&blend_desc, 0, sizeof(blend_desc));
1812 blend_desc.BlendEnable[0] = TRUE;
1813 blend_desc.SrcBlend = D3D10_BLEND_ONE;
1814 blend_desc.DestBlend = D3D10_BLEND_INV_SRC_ALPHA;
1815 blend_desc.BlendOp = D3D10_BLEND_OP_ADD;
1816 if (desc->pixelFormat.alphaMode == D2D1_ALPHA_MODE_IGNORE)
1818 blend_desc.SrcBlendAlpha = D3D10_BLEND_ZERO;
1819 blend_desc.DestBlendAlpha = D3D10_BLEND_ONE;
1821 else
1823 blend_desc.SrcBlendAlpha = D3D10_BLEND_ONE;
1824 blend_desc.DestBlendAlpha = D3D10_BLEND_INV_SRC_ALPHA;
1826 blend_desc.BlendOpAlpha = D3D10_BLEND_OP_ADD;
1827 blend_desc.RenderTargetWriteMask[0] = D3D10_COLOR_WRITE_ENABLE_ALL;
1828 if (FAILED(hr = ID3D10Device_CreateBlendState(render_target->device, &blend_desc, &render_target->bs)))
1830 WARN("Failed to create blend state, hr %#x.\n", hr);
1831 goto err;
1834 if (FAILED(hr = IDXGISurface_GetDesc(surface, &surface_desc)))
1836 WARN("Failed to get surface desc, hr %#x.\n", hr);
1837 goto err;
1840 render_target->format = desc->pixelFormat;
1841 render_target->pixel_size.width = surface_desc.Width;
1842 render_target->pixel_size.height = surface_desc.Height;
1843 render_target->drawing_state.transform = identity;
1845 if (!d2d_clip_stack_init(&render_target->clip_stack))
1847 WARN("Failed to initialize clip stack.\n");
1848 hr = E_FAIL;
1849 goto err;
1852 render_target->dpi_x = desc->dpiX;
1853 render_target->dpi_y = desc->dpiY;
1855 if (render_target->dpi_x == 0.0f && render_target->dpi_y == 0.0f)
1857 render_target->dpi_x = 96.0f;
1858 render_target->dpi_y = 96.0f;
1861 return S_OK;
1863 err:
1864 if (render_target->bs)
1865 ID3D10BlendState_Release(render_target->bs);
1866 if (render_target->rs)
1867 ID3D10RasterizerState_Release(render_target->rs);
1868 if (render_target->vb)
1869 ID3D10Buffer_Release(render_target->vb);
1870 if (render_target->ib)
1871 ID3D10Buffer_Release(render_target->ib);
1872 for (i = 0; i < D2D_SHAPE_TYPE_COUNT; ++i)
1874 for (j = 0; j < D2D_BRUSH_TYPE_COUNT; ++j)
1876 if (render_target->shape_resources[i].ps[j])
1877 ID3D10PixelShader_Release(render_target->shape_resources[i].ps[j]);
1879 if (render_target->shape_resources[i].vs)
1880 ID3D10VertexShader_Release(render_target->shape_resources[i].vs);
1881 if (render_target->shape_resources[i].il)
1882 ID3D10InputLayout_Release(render_target->shape_resources[i].il);
1884 if (render_target->stateblock)
1885 render_target->stateblock->lpVtbl->Release(render_target->stateblock);
1886 if (render_target->view)
1887 ID3D10RenderTargetView_Release(render_target->view);
1888 if (render_target->device)
1889 ID3D10Device_Release(render_target->device);
1890 ID2D1Factory_Release(render_target->factory);
1891 return hr;