ole32/tests: Add some tests for loading and drawing various OLE formats.
[wine.git] / dlls / d2d1 / render_target.c
blob0ed57c43022015e3ff225cfaaa245ee3808aa160
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 D3D10_RECT scissor_rect;
137 unsigned int offset;
138 D3D10_VIEWPORT vp;
139 HRESULT hr;
141 vp.TopLeftX = 0;
142 vp.TopLeftY = 0;
143 vp.Width = render_target->pixel_size.width;
144 vp.Height = render_target->pixel_size.height;
145 vp.MinDepth = 0.0f;
146 vp.MaxDepth = 1.0f;
148 if (FAILED(hr = render_target->stateblock->lpVtbl->Capture(render_target->stateblock)))
150 WARN("Failed to capture stateblock, hr %#x.\n", hr);
151 return;
154 ID3D10Device_ClearState(device);
156 ID3D10Device_IASetInputLayout(device, shape_resources->il);
157 ID3D10Device_IASetPrimitiveTopology(device, D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
158 ID3D10Device_IASetIndexBuffer(device, ib, DXGI_FORMAT_R16_UINT, 0);
159 offset = 0;
160 ID3D10Device_IASetVertexBuffers(device, 0, 1, &vb, &vb_stride, &offset);
161 ID3D10Device_VSSetConstantBuffers(device, 0, 1, &vs_cb);
162 ID3D10Device_VSSetShader(device, shape_resources->vs);
163 ID3D10Device_PSSetConstantBuffers(device, 0, 1, &ps_cb);
164 ID3D10Device_RSSetViewports(device, 1, &vp);
165 if (render_target->clip_stack.count)
167 const D2D1_RECT_F *clip_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;
175 else
177 scissor_rect.left = 0.0f;
178 scissor_rect.top = 0.0f;
179 scissor_rect.right = render_target->pixel_size.width;
180 scissor_rect.bottom = render_target->pixel_size.height;
182 ID3D10Device_RSSetScissorRects(device, 1, &scissor_rect);
183 ID3D10Device_RSSetState(device, render_target->rs);
184 ID3D10Device_OMSetRenderTargets(device, 1, &render_target->view, NULL);
185 if (brush)
186 d2d_brush_bind_resources(brush, render_target, shape_type);
187 else
188 ID3D10Device_PSSetShader(device, shape_resources->ps[D2D_BRUSH_TYPE_SOLID]);
190 if (ib)
191 ID3D10Device_DrawIndexed(device, index_count, 0, 0);
192 else
193 ID3D10Device_Draw(device, index_count, 0);
195 if (FAILED(hr = render_target->stateblock->lpVtbl->Apply(render_target->stateblock)))
196 WARN("Failed to apply stateblock, hr %#x.\n", hr);
199 static inline struct d2d_d3d_render_target *impl_from_ID2D1RenderTarget(ID2D1RenderTarget *iface)
201 return CONTAINING_RECORD(iface, struct d2d_d3d_render_target, ID2D1RenderTarget_iface);
204 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_QueryInterface(ID2D1RenderTarget *iface, REFIID iid, void **out)
206 TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
208 if (IsEqualGUID(iid, &IID_ID2D1RenderTarget)
209 || IsEqualGUID(iid, &IID_ID2D1Resource)
210 || IsEqualGUID(iid, &IID_IUnknown))
212 ID2D1RenderTarget_AddRef(iface);
213 *out = iface;
214 return S_OK;
217 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
219 *out = NULL;
220 return E_NOINTERFACE;
223 static ULONG STDMETHODCALLTYPE d2d_d3d_render_target_AddRef(ID2D1RenderTarget *iface)
225 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
226 ULONG refcount = InterlockedIncrement(&render_target->refcount);
228 TRACE("%p increasing refcount to %u.\n", iface, refcount);
230 return refcount;
233 static ULONG STDMETHODCALLTYPE d2d_d3d_render_target_Release(ID2D1RenderTarget *iface)
235 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
236 ULONG refcount = InterlockedDecrement(&render_target->refcount);
238 TRACE("%p decreasing refcount to %u.\n", iface, refcount);
240 if (!refcount)
242 unsigned int i, j;
244 d2d_clip_stack_cleanup(&render_target->clip_stack);
245 if (render_target->text_rendering_params)
246 IDWriteRenderingParams_Release(render_target->text_rendering_params);
247 ID3D10BlendState_Release(render_target->bs);
248 ID3D10RasterizerState_Release(render_target->rs);
249 ID3D10Buffer_Release(render_target->vb);
250 ID3D10Buffer_Release(render_target->ib);
251 for (i = 0; i < D2D_SHAPE_TYPE_COUNT; ++i)
253 for (j = 0; j < D2D_BRUSH_TYPE_COUNT; ++j)
255 if (render_target->shape_resources[i].ps[j])
256 ID3D10PixelShader_Release(render_target->shape_resources[i].ps[j]);
258 ID3D10VertexShader_Release(render_target->shape_resources[i].vs);
259 ID3D10InputLayout_Release(render_target->shape_resources[i].il);
261 render_target->stateblock->lpVtbl->Release(render_target->stateblock);
262 ID3D10RenderTargetView_Release(render_target->view);
263 ID3D10Device_Release(render_target->device);
264 ID2D1Factory_Release(render_target->factory);
265 HeapFree(GetProcessHeap(), 0, render_target);
268 return refcount;
271 static void STDMETHODCALLTYPE d2d_d3d_render_target_GetFactory(ID2D1RenderTarget *iface, ID2D1Factory **factory)
273 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
275 TRACE("iface %p, factory %p.\n", iface, factory);
277 *factory = render_target->factory;
278 ID2D1Factory_AddRef(*factory);
281 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateBitmap(ID2D1RenderTarget *iface,
282 D2D1_SIZE_U size, const void *src_data, UINT32 pitch, const D2D1_BITMAP_PROPERTIES *desc, ID2D1Bitmap **bitmap)
284 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
285 struct d2d_bitmap *object;
286 HRESULT hr;
288 TRACE("iface %p, size {%u, %u}, src_data %p, pitch %u, desc %p, bitmap %p.\n",
289 iface, size.width, size.height, src_data, pitch, desc, bitmap);
291 if (!(object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object))))
292 return E_OUTOFMEMORY;
294 if (FAILED(hr = d2d_bitmap_init_memory(object, render_target, size, src_data, pitch, desc)))
296 WARN("Failed to initialize bitmap, hr %#x.\n", hr);
297 HeapFree(GetProcessHeap(), 0, object);
298 return hr;
301 TRACE("Created bitmap %p.\n", object);
302 *bitmap = &object->ID2D1Bitmap_iface;
304 return S_OK;
307 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateBitmapFromWicBitmap(ID2D1RenderTarget *iface,
308 IWICBitmapSource *bitmap_source, const D2D1_BITMAP_PROPERTIES *desc, ID2D1Bitmap **bitmap)
310 const D2D1_PIXEL_FORMAT *d2d_format;
311 D2D1_BITMAP_PROPERTIES bitmap_desc;
312 WICPixelFormatGUID wic_format;
313 unsigned int bpp, data_size;
314 D2D1_SIZE_U size;
315 unsigned int i;
316 WICRect rect;
317 UINT32 pitch;
318 HRESULT hr;
319 void *data;
321 static const struct
323 const WICPixelFormatGUID *wic;
324 D2D1_PIXEL_FORMAT d2d;
326 format_lookup[] =
328 {&GUID_WICPixelFormat32bppPBGRA, {DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_PREMULTIPLIED}},
329 {&GUID_WICPixelFormat32bppBGR, {DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_IGNORE}},
332 TRACE("iface %p, bitmap_source %p, desc %p, bitmap %p.\n",
333 iface, bitmap_source, desc, bitmap);
335 if (FAILED(hr = IWICBitmapSource_GetSize(bitmap_source, &size.width, &size.height)))
337 WARN("Failed to get bitmap size, hr %#x.\n", hr);
338 return hr;
341 if (!desc)
343 bitmap_desc.pixelFormat.format = DXGI_FORMAT_UNKNOWN;
344 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_UNKNOWN;
345 bitmap_desc.dpiX = 0.0f;
346 bitmap_desc.dpiY = 0.0f;
348 else
350 bitmap_desc = *desc;
353 if (FAILED(hr = IWICBitmapSource_GetPixelFormat(bitmap_source, &wic_format)))
355 WARN("Failed to get bitmap format, hr %#x.\n", hr);
356 return hr;
359 for (i = 0, d2d_format = NULL; i < sizeof(format_lookup) / sizeof(*format_lookup); ++i)
361 if (IsEqualGUID(&wic_format, format_lookup[i].wic))
363 d2d_format = &format_lookup[i].d2d;
364 break;
368 if (!d2d_format)
370 WARN("Unsupported WIC bitmap format %s.\n", debugstr_guid(&wic_format));
371 return D2DERR_UNSUPPORTED_PIXEL_FORMAT;
374 if (bitmap_desc.pixelFormat.format == DXGI_FORMAT_UNKNOWN)
375 bitmap_desc.pixelFormat.format = d2d_format->format;
376 if (bitmap_desc.pixelFormat.alphaMode == D2D1_ALPHA_MODE_UNKNOWN)
377 bitmap_desc.pixelFormat.alphaMode = d2d_format->alphaMode;
379 switch (bitmap_desc.pixelFormat.format)
381 case DXGI_FORMAT_B8G8R8A8_UNORM:
382 bpp = 4;
383 break;
385 default:
386 FIXME("Unhandled format %#x.\n", bitmap_desc.pixelFormat.format);
387 return D2DERR_UNSUPPORTED_PIXEL_FORMAT;
390 pitch = ((bpp * size.width) + 15) & ~15;
391 data_size = pitch * size.height;
392 if (!(data = HeapAlloc(GetProcessHeap(), 0, data_size)))
393 return E_OUTOFMEMORY;
395 rect.X = 0;
396 rect.Y = 0;
397 rect.Width = size.width;
398 rect.Height = size.height;
399 if (FAILED(hr = IWICBitmapSource_CopyPixels(bitmap_source, &rect, pitch, data_size, data)))
401 WARN("Failed to copy bitmap pixels, hr %#x.\n", hr);
402 HeapFree(GetProcessHeap(), 0, data);
403 return hr;
406 hr = d2d_d3d_render_target_CreateBitmap(iface, size, data, pitch, &bitmap_desc, bitmap);
408 HeapFree(GetProcessHeap(), 0, data);
410 return hr;
413 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateSharedBitmap(ID2D1RenderTarget *iface,
414 REFIID iid, void *data, const D2D1_BITMAP_PROPERTIES *desc, ID2D1Bitmap **bitmap)
416 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
417 struct d2d_bitmap *object;
418 HRESULT hr;
420 TRACE("iface %p, iid %s, data %p, desc %p, bitmap %p.\n",
421 iface, debugstr_guid(iid), data, desc, bitmap);
423 if (!(object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object))))
424 return E_OUTOFMEMORY;
426 if (FAILED(hr = d2d_bitmap_init_shared(object, render_target, iid, data, desc)))
428 WARN("Failed to initialize bitmap, hr %#x.\n", hr);
429 HeapFree(GetProcessHeap(), 0, object);
430 return hr;
433 TRACE("Created bitmap %p.\n", object);
434 *bitmap = &object->ID2D1Bitmap_iface;
436 return S_OK;
439 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateBitmapBrush(ID2D1RenderTarget *iface,
440 ID2D1Bitmap *bitmap, const D2D1_BITMAP_BRUSH_PROPERTIES *bitmap_brush_desc,
441 const D2D1_BRUSH_PROPERTIES *brush_desc, ID2D1BitmapBrush **brush)
443 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
444 struct d2d_brush *object;
446 TRACE("iface %p, bitmap %p, bitmap_brush_desc %p, brush_desc %p, brush %p.\n",
447 iface, bitmap, bitmap_brush_desc, brush_desc, brush);
449 if (!(object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object))))
450 return E_OUTOFMEMORY;
452 d2d_bitmap_brush_init(object, render_target->factory, bitmap, bitmap_brush_desc, brush_desc);
454 TRACE("Created brush %p.\n", object);
455 *brush = (ID2D1BitmapBrush *)&object->ID2D1Brush_iface;
457 return S_OK;
460 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateSolidColorBrush(ID2D1RenderTarget *iface,
461 const D2D1_COLOR_F *color, const D2D1_BRUSH_PROPERTIES *desc, ID2D1SolidColorBrush **brush)
463 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
464 struct d2d_brush *object;
466 TRACE("iface %p, color %p, desc %p, brush %p.\n", iface, color, desc, brush);
468 if (!(object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object))))
469 return E_OUTOFMEMORY;
471 d2d_solid_color_brush_init(object, render_target->factory, color, desc);
473 TRACE("Created brush %p.\n", object);
474 *brush = (ID2D1SolidColorBrush *)&object->ID2D1Brush_iface;
476 return S_OK;
479 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateGradientStopCollection(ID2D1RenderTarget *iface,
480 const D2D1_GRADIENT_STOP *stops, UINT32 stop_count, D2D1_GAMMA gamma, D2D1_EXTEND_MODE extend_mode,
481 ID2D1GradientStopCollection **gradient)
483 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
484 struct d2d_gradient *object;
485 HRESULT hr;
487 TRACE("iface %p, stops %p, stop_count %u, gamma %#x, extend_mode %#x, gradient %p.\n",
488 iface, stops, stop_count, gamma, extend_mode, gradient);
490 if (!(object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object))))
491 return E_OUTOFMEMORY;
493 if (FAILED(hr = d2d_gradient_init(object, render_target->factory, stops, stop_count, gamma, extend_mode)))
495 WARN("Failed to initialize gradient, hr %#x.\n", hr);
496 HeapFree(GetProcessHeap(), 0, object);
497 return hr;
500 TRACE("Created gradient %p.\n", object);
501 *gradient = &object->ID2D1GradientStopCollection_iface;
503 return S_OK;
506 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateLinearGradientBrush(ID2D1RenderTarget *iface,
507 const D2D1_LINEAR_GRADIENT_BRUSH_PROPERTIES *gradient_brush_desc, const D2D1_BRUSH_PROPERTIES *brush_desc,
508 ID2D1GradientStopCollection *gradient, ID2D1LinearGradientBrush **brush)
510 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
511 struct d2d_brush *object;
513 TRACE("iface %p, gradient_brush_desc %p, brush_desc %p, gradient %p, brush %p.\n",
514 iface, gradient_brush_desc, brush_desc, gradient, brush);
516 if (!(object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object))))
517 return E_OUTOFMEMORY;
519 d2d_linear_gradient_brush_init(object, render_target->factory, gradient_brush_desc, brush_desc, gradient);
521 TRACE("Created brush %p.\n", object);
522 *brush = (ID2D1LinearGradientBrush *)&object->ID2D1Brush_iface;
524 return S_OK;
527 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateRadialGradientBrush(ID2D1RenderTarget *iface,
528 const D2D1_RADIAL_GRADIENT_BRUSH_PROPERTIES *gradient_brush_desc, const D2D1_BRUSH_PROPERTIES *brush_desc,
529 ID2D1GradientStopCollection *gradient, ID2D1RadialGradientBrush **brush)
531 FIXME("iface %p, gradient_brush_desc %p, brush_desc %p, gradient %p, brush %p stub!\n",
532 iface, gradient_brush_desc, brush_desc, gradient, brush);
534 return E_NOTIMPL;
537 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateCompatibleRenderTarget(ID2D1RenderTarget *iface,
538 const D2D1_SIZE_F *size, const D2D1_SIZE_U *pixel_size, const D2D1_PIXEL_FORMAT *format,
539 D2D1_COMPATIBLE_RENDER_TARGET_OPTIONS options, ID2D1BitmapRenderTarget **render_target)
541 FIXME("iface %p, size %p, pixel_size %p, format %p, options %#x, render_target %p stub!\n",
542 iface, size, pixel_size, format, options, render_target);
544 return E_NOTIMPL;
547 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateLayer(ID2D1RenderTarget *iface,
548 const D2D1_SIZE_F *size, ID2D1Layer **layer)
550 FIXME("iface %p, size %p, layer %p stub!\n", iface, size, layer);
552 return E_NOTIMPL;
555 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateMesh(ID2D1RenderTarget *iface, ID2D1Mesh **mesh)
557 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
558 struct d2d_mesh *object;
560 TRACE("iface %p, mesh %p.\n", iface, mesh);
562 if (!(object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object))))
563 return E_OUTOFMEMORY;
565 d2d_mesh_init(object, render_target->factory);
567 TRACE("Created mesh %p.\n", object);
568 *mesh = &object->ID2D1Mesh_iface;
570 return S_OK;
573 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawLine(ID2D1RenderTarget *iface,
574 D2D1_POINT_2F p0, D2D1_POINT_2F p1, ID2D1Brush *brush, float stroke_width, ID2D1StrokeStyle *stroke_style)
576 FIXME("iface %p, p0 {%.8e, %.8e}, p1 {%.8e, %.8e}, brush %p, stroke_width %.8e, stroke_style %p stub!\n",
577 iface, p0.x, p0.y, p1.x, p1.y, brush, stroke_width, stroke_style);
580 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawRectangle(ID2D1RenderTarget *iface,
581 const D2D1_RECT_F *rect, ID2D1Brush *brush, float stroke_width, ID2D1StrokeStyle *stroke_style)
583 FIXME("iface %p, rect %p, brush %p, stroke_width %.8e, stroke_style %p stub!\n",
584 iface, rect, brush, stroke_width, stroke_style);
587 static void STDMETHODCALLTYPE d2d_d3d_render_target_FillRectangle(ID2D1RenderTarget *iface,
588 const D2D1_RECT_F *rect, ID2D1Brush *brush)
590 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
591 ID2D1RectangleGeometry *geometry;
592 HRESULT hr;
594 TRACE("iface %p, rect %p, brush %p.\n", iface, rect, brush);
596 if (FAILED(hr = ID2D1Factory_CreateRectangleGeometry(render_target->factory, rect, &geometry)))
598 ERR("Failed to create geometry, hr %#x.\n", hr);
599 return;
602 ID2D1RenderTarget_FillGeometry(iface, (ID2D1Geometry *)geometry, brush, NULL);
603 ID2D1RectangleGeometry_Release(geometry);
606 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawRoundedRectangle(ID2D1RenderTarget *iface,
607 const D2D1_ROUNDED_RECT *rect, ID2D1Brush *brush, float stroke_width, ID2D1StrokeStyle *stroke_style)
609 FIXME("iface %p, rect %p, brush %p, stroke_width %.8e, stroke_style %p stub!\n",
610 iface, rect, brush, stroke_width, stroke_style);
613 static void STDMETHODCALLTYPE d2d_d3d_render_target_FillRoundedRectangle(ID2D1RenderTarget *iface,
614 const D2D1_ROUNDED_RECT *rect, ID2D1Brush *brush)
616 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
617 ID2D1RoundedRectangleGeometry *geometry;
618 HRESULT hr;
620 TRACE("iface %p, rect %p, brush %p.\n", iface, rect, brush);
622 if (FAILED(hr = ID2D1Factory_CreateRoundedRectangleGeometry(render_target->factory, rect, &geometry)))
624 ERR("Failed to create geometry, hr %#x.\n", hr);
625 return;
628 ID2D1RenderTarget_FillGeometry(iface, (ID2D1Geometry *)geometry, brush, NULL);
629 ID2D1RoundedRectangleGeometry_Release(geometry);
632 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawEllipse(ID2D1RenderTarget *iface,
633 const D2D1_ELLIPSE *ellipse, ID2D1Brush *brush, float stroke_width, ID2D1StrokeStyle *stroke_style)
635 FIXME("iface %p, ellipse %p, brush %p, stroke_width %.8e, stroke_style %p stub!\n",
636 iface, ellipse, brush, stroke_width, stroke_style);
639 static void STDMETHODCALLTYPE d2d_d3d_render_target_FillEllipse(ID2D1RenderTarget *iface,
640 const D2D1_ELLIPSE *ellipse, ID2D1Brush *brush)
642 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
643 ID2D1EllipseGeometry *geometry;
644 HRESULT hr;
646 TRACE("iface %p, ellipse %p, brush %p.\n", iface, ellipse, brush);
648 if (FAILED(hr = ID2D1Factory_CreateEllipseGeometry(render_target->factory, ellipse, &geometry)))
650 ERR("Failed to create geometry, hr %#x.\n", hr);
651 return;
654 ID2D1RenderTarget_FillGeometry(iface, (ID2D1Geometry *)geometry, brush, NULL);
655 ID2D1EllipseGeometry_Release(geometry);
658 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawGeometry(ID2D1RenderTarget *iface,
659 ID2D1Geometry *geometry, ID2D1Brush *brush, float stroke_width, ID2D1StrokeStyle *stroke_style)
661 FIXME("iface %p, geometry %p, brush %p, stroke_width %.8e, stroke_style %p stub!\n",
662 iface, geometry, brush, stroke_width, stroke_style);
665 static void STDMETHODCALLTYPE d2d_d3d_render_target_FillGeometry(ID2D1RenderTarget *iface,
666 ID2D1Geometry *geometry, ID2D1Brush *brush, ID2D1Brush *opacity_brush)
668 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
669 struct d2d_brush *brush_impl = unsafe_impl_from_ID2D1Brush(brush);
670 const struct d2d_geometry *geometry_impl;
671 ID3D10Buffer *ib, *vb, *vs_cb, *ps_cb;
672 D3D10_SUBRESOURCE_DATA buffer_data;
673 D3D10_BUFFER_DESC buffer_desc;
674 D2D1_MATRIX_3X2_F w, g;
675 float tmp_x, tmp_y;
676 HRESULT hr;
677 struct
679 float _11, _21, _31, pad0;
680 float _12, _22, _32, pad1;
681 } transform;
683 TRACE("iface %p, geometry %p, brush %p, opacity_brush %p.\n", iface, geometry, brush, opacity_brush);
685 if (opacity_brush)
686 FIXME("Ignoring opacity brush %p.\n", opacity_brush);
688 geometry_impl = unsafe_impl_from_ID2D1Geometry(geometry);
690 tmp_x = (2.0f * render_target->dpi_x) / (96.0f * render_target->pixel_size.width);
691 tmp_y = -(2.0f * render_target->dpi_y) / (96.0f * render_target->pixel_size.height);
692 w = render_target->drawing_state.transform;
693 w._11 *= tmp_x;
694 w._21 *= tmp_x;
695 w._31 = w._31 * tmp_x - 1.0f;
696 w._12 *= tmp_y;
697 w._22 *= tmp_y;
698 w._32 = w._32 * tmp_y + 1.0f;
700 g = geometry_impl->transform;
701 d2d_matrix_multiply(&g, &w);
703 transform._11 = g._11;
704 transform._21 = g._21;
705 transform._31 = g._31;
706 transform.pad0 = 0.0f;
707 transform._12 = g._12;
708 transform._22 = g._22;
709 transform._32 = g._32;
710 transform.pad1 = 0.0f;
712 buffer_desc.ByteWidth = sizeof(transform);
713 buffer_desc.Usage = D3D10_USAGE_DEFAULT;
714 buffer_desc.BindFlags = D3D10_BIND_CONSTANT_BUFFER;
715 buffer_desc.CPUAccessFlags = 0;
716 buffer_desc.MiscFlags = 0;
718 buffer_data.pSysMem = &transform;
719 buffer_data.SysMemPitch = 0;
720 buffer_data.SysMemSlicePitch = 0;
722 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device, &buffer_desc, &buffer_data, &vs_cb)))
724 WARN("Failed to create constant buffer, hr %#x.\n", hr);
725 return;
728 if (FAILED(hr = d2d_brush_get_ps_cb(brush_impl, render_target, &ps_cb)))
730 WARN("Failed to get ps constant buffer, hr %#x.\n", hr);
731 ID3D10Buffer_Release(vs_cb);
732 return;
735 if (geometry_impl->face_count)
737 buffer_desc.ByteWidth = geometry_impl->face_count * sizeof(*geometry_impl->faces);
738 buffer_desc.BindFlags = D3D10_BIND_INDEX_BUFFER;
739 buffer_data.pSysMem = geometry_impl->faces;
741 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device, &buffer_desc, &buffer_data, &ib)))
743 WARN("Failed to create index buffer, hr %#x.\n", hr);
744 goto done;
747 buffer_desc.ByteWidth = geometry_impl->vertex_count * sizeof(*geometry_impl->vertices);
748 buffer_desc.BindFlags = D3D10_BIND_VERTEX_BUFFER;
749 buffer_data.pSysMem = geometry_impl->vertices;
751 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device, &buffer_desc, &buffer_data, &vb)))
753 ERR("Failed to create vertex buffer, hr %#x.\n", hr);
754 ID3D10Buffer_Release(ib);
755 goto done;
758 d2d_draw(render_target, D2D_SHAPE_TYPE_TRIANGLE, ib, 3 * geometry_impl->face_count, vb,
759 sizeof(*geometry_impl->vertices), vs_cb, ps_cb, brush_impl);
761 ID3D10Buffer_Release(vb);
762 ID3D10Buffer_Release(ib);
765 if (geometry_impl->bezier_count)
767 buffer_desc.ByteWidth = geometry_impl->bezier_count * sizeof(*geometry_impl->beziers);
768 buffer_data.pSysMem = geometry_impl->beziers;
770 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device, &buffer_desc, &buffer_data, &vb)))
772 ERR("Failed to create beziers vertex buffer, hr %#x.\n", hr);
773 goto done;
776 d2d_draw(render_target, D2D_SHAPE_TYPE_BEZIER, NULL, 3 * geometry_impl->bezier_count, vb,
777 sizeof(*geometry_impl->beziers->v), vs_cb, ps_cb, brush_impl);
779 ID3D10Buffer_Release(vb);
782 done:
783 ID3D10Buffer_Release(ps_cb);
784 ID3D10Buffer_Release(vs_cb);
787 static void STDMETHODCALLTYPE d2d_d3d_render_target_FillMesh(ID2D1RenderTarget *iface,
788 ID2D1Mesh *mesh, ID2D1Brush *brush)
790 FIXME("iface %p, mesh %p, brush %p stub!\n", iface, mesh, brush);
793 static void STDMETHODCALLTYPE d2d_d3d_render_target_FillOpacityMask(ID2D1RenderTarget *iface,
794 ID2D1Bitmap *mask, ID2D1Brush *brush, D2D1_OPACITY_MASK_CONTENT content,
795 const D2D1_RECT_F *dst_rect, const D2D1_RECT_F *src_rect)
797 FIXME("iface %p, mask %p, brush %p, content %#x, dst_rect %p, src_rect %p stub!\n",
798 iface, mask, brush, content, dst_rect, src_rect);
801 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawBitmap(ID2D1RenderTarget *iface,
802 ID2D1Bitmap *bitmap, const D2D1_RECT_F *dst_rect, float opacity,
803 D2D1_BITMAP_INTERPOLATION_MODE interpolation_mode, const D2D1_RECT_F *src_rect)
805 D2D1_BITMAP_BRUSH_PROPERTIES bitmap_brush_desc;
806 D2D1_BRUSH_PROPERTIES brush_desc;
807 ID2D1BitmapBrush *brush;
808 D2D1_RECT_F s, d;
809 HRESULT hr;
811 TRACE("iface %p, bitmap %p, dst_rect %p, opacity %.8e, interpolation_mode %#x, src_rect %p.\n",
812 iface, bitmap, dst_rect, opacity, interpolation_mode, src_rect);
814 if (src_rect)
816 s = *src_rect;
818 else
820 D2D1_SIZE_F size;
822 size = ID2D1Bitmap_GetSize(bitmap);
823 s.left = 0.0f;
824 s.top = 0.0f;
825 s.right = size.width;
826 s.bottom = size.height;
829 if (dst_rect)
831 d = *dst_rect;
833 else
835 d.left = 0.0f;
836 d.top = 0.0f;
837 d.right = s.right - s.left;
838 d.bottom = s.bottom - s.top;
841 bitmap_brush_desc.extendModeX = D2D1_EXTEND_MODE_CLAMP;
842 bitmap_brush_desc.extendModeY = D2D1_EXTEND_MODE_CLAMP;
843 bitmap_brush_desc.interpolationMode = interpolation_mode;
845 brush_desc.opacity = opacity;
846 brush_desc.transform._11 = fabsf((d.right - d.left) / (s.right - s.left));
847 brush_desc.transform._21 = 0.0f;
848 brush_desc.transform._31 = min(d.left, d.right) - min(s.left, s.right) * brush_desc.transform._11;
849 brush_desc.transform._12 = 0.0f;
850 brush_desc.transform._22 = fabsf((d.bottom - d.top) / (s.bottom - s.top));
851 brush_desc.transform._32 = min(d.top, d.bottom) - min(s.top, s.bottom) * brush_desc.transform._22;
853 if (FAILED(hr = ID2D1RenderTarget_CreateBitmapBrush(iface, bitmap, &bitmap_brush_desc, &brush_desc, &brush)))
855 ERR("Failed to create bitmap brush, hr %#x.\n", hr);
856 return;
859 ID2D1RenderTarget_FillRectangle(iface, &d, (ID2D1Brush *)brush);
860 ID2D1BitmapBrush_Release(brush);
863 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawText(ID2D1RenderTarget *iface,
864 const WCHAR *string, UINT32 string_len, IDWriteTextFormat *text_format, const D2D1_RECT_F *layout_rect,
865 ID2D1Brush *brush, D2D1_DRAW_TEXT_OPTIONS options, DWRITE_MEASURING_MODE measuring_mode)
867 IDWriteTextLayout *text_layout;
868 IDWriteFactory *dwrite_factory;
869 D2D1_POINT_2F origin;
870 HRESULT hr;
872 TRACE("iface %p, string %s, string_len %u, text_format %p, layout_rect %p, "
873 "brush %p, options %#x, measuring_mode %#x.\n",
874 iface, debugstr_wn(string, string_len), string_len, text_format, layout_rect,
875 brush, options, measuring_mode);
877 if (measuring_mode != DWRITE_MEASURING_MODE_NATURAL)
878 FIXME("Ignoring measuring mode %#x.\n", measuring_mode);
880 if (FAILED(hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED,
881 &IID_IDWriteFactory, (IUnknown **)&dwrite_factory)))
883 ERR("Failed to create dwrite factory, hr %#x.\n", hr);
884 return;
887 hr = IDWriteFactory_CreateTextLayout(dwrite_factory, string, string_len, text_format,
888 layout_rect->right - layout_rect->left, layout_rect->bottom - layout_rect->top, &text_layout);
889 IDWriteFactory_Release(dwrite_factory);
890 if (FAILED(hr))
892 ERR("Failed to create text layout, hr %#x.\n", hr);
893 return;
896 d2d_point_set(&origin, layout_rect->left, layout_rect->top);
897 ID2D1RenderTarget_DrawTextLayout(iface, origin, text_layout, brush, options);
898 IDWriteTextLayout_Release(text_layout);
901 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawTextLayout(ID2D1RenderTarget *iface,
902 D2D1_POINT_2F origin, IDWriteTextLayout *layout, ID2D1Brush *brush, D2D1_DRAW_TEXT_OPTIONS options)
904 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
905 struct d2d_draw_text_layout_ctx ctx;
906 HRESULT hr;
908 TRACE("iface %p, origin {%.8e, %.8e}, layout %p, brush %p, options %#x.\n",
909 iface, origin.x, origin.y, layout, brush, options);
911 ctx.brush = brush;
912 ctx.options = options;
914 if (FAILED(hr = IDWriteTextLayout_Draw(layout,
915 &ctx, &render_target->IDWriteTextRenderer_iface, origin.x, origin.y)))
916 FIXME("Failed to draw text layout, hr %#x.\n", hr);
919 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawGlyphRun(ID2D1RenderTarget *iface,
920 D2D1_POINT_2F baseline_origin, const DWRITE_GLYPH_RUN *glyph_run, ID2D1Brush *brush,
921 DWRITE_MEASURING_MODE measuring_mode)
923 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
924 D2D1_MATRIX_3X2_F *transform, prev_transform;
925 ID2D1PathGeometry *geometry;
926 ID2D1GeometrySink *sink;
927 HRESULT hr;
929 TRACE("iface %p, baseline_origin {%.8e, %.8e}, glyph_run %p, brush %p, measuring_mode %#x.\n",
930 iface, baseline_origin.x, baseline_origin.y, glyph_run, brush, measuring_mode);
932 if (measuring_mode)
933 FIXME("Ignoring measuring mode %#x.\n", measuring_mode);
934 if (render_target->text_rendering_params)
935 FIXME("Ignoring text rendering parameters %p.\n", render_target->text_rendering_params);
936 if (render_target->drawing_state.textAntialiasMode != D2D1_TEXT_ANTIALIAS_MODE_ALIASED)
937 FIXME("Ignoring text antialiasing mode %#x.\n", render_target->drawing_state.textAntialiasMode);
939 if (FAILED(hr = ID2D1Factory_CreatePathGeometry(render_target->factory, &geometry)))
941 ERR("Failed to create geometry, hr %#x.\n", hr);
942 return;
945 if (FAILED(hr = ID2D1PathGeometry_Open(geometry, &sink)))
947 ERR("Failed to open geometry sink, hr %#x.\n", hr);
948 ID2D1PathGeometry_Release(geometry);
949 return;
952 if (FAILED(hr = IDWriteFontFace_GetGlyphRunOutline(glyph_run->fontFace, glyph_run->fontEmSize,
953 glyph_run->glyphIndices, glyph_run->glyphAdvances, glyph_run->glyphOffsets, glyph_run->glyphCount,
954 glyph_run->isSideways, glyph_run->bidiLevel & 1, (IDWriteGeometrySink *)sink)))
956 ERR("Failed to get glyph run outline, hr %#x.\n", hr);
957 ID2D1GeometrySink_Release(sink);
958 ID2D1PathGeometry_Release(geometry);
959 return;
962 if (FAILED(hr = ID2D1GeometrySink_Close(sink)))
963 ERR("Failed to close geometry sink, hr %#x.\n", hr);
964 ID2D1GeometrySink_Release(sink);
966 transform = &render_target->drawing_state.transform;
967 prev_transform = *transform;
968 transform->_31 += baseline_origin.x * transform->_11 + baseline_origin.y * transform->_21;
969 transform->_32 += baseline_origin.x * transform->_12 + baseline_origin.y * transform->_22;
970 ID2D1RenderTarget_FillGeometry(iface, (ID2D1Geometry *)geometry, brush, NULL);
971 *transform = prev_transform;
973 ID2D1PathGeometry_Release(geometry);
976 static void STDMETHODCALLTYPE d2d_d3d_render_target_SetTransform(ID2D1RenderTarget *iface,
977 const D2D1_MATRIX_3X2_F *transform)
979 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
981 TRACE("iface %p, transform %p.\n", iface, transform);
983 render_target->drawing_state.transform = *transform;
986 static void STDMETHODCALLTYPE d2d_d3d_render_target_GetTransform(ID2D1RenderTarget *iface,
987 D2D1_MATRIX_3X2_F *transform)
989 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
991 TRACE("iface %p, transform %p.\n", iface, transform);
993 *transform = render_target->drawing_state.transform;
996 static void STDMETHODCALLTYPE d2d_d3d_render_target_SetAntialiasMode(ID2D1RenderTarget *iface,
997 D2D1_ANTIALIAS_MODE antialias_mode)
999 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1001 TRACE("iface %p, antialias_mode %#x stub!\n", iface, antialias_mode);
1003 render_target->drawing_state.antialiasMode = antialias_mode;
1006 static D2D1_ANTIALIAS_MODE STDMETHODCALLTYPE d2d_d3d_render_target_GetAntialiasMode(ID2D1RenderTarget *iface)
1008 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1010 TRACE("iface %p.\n", iface);
1012 return render_target->drawing_state.antialiasMode;
1015 static void STDMETHODCALLTYPE d2d_d3d_render_target_SetTextAntialiasMode(ID2D1RenderTarget *iface,
1016 D2D1_TEXT_ANTIALIAS_MODE antialias_mode)
1018 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1020 TRACE("iface %p, antialias_mode %#x.\n", iface, antialias_mode);
1022 render_target->drawing_state.textAntialiasMode = antialias_mode;
1025 static D2D1_TEXT_ANTIALIAS_MODE STDMETHODCALLTYPE d2d_d3d_render_target_GetTextAntialiasMode(ID2D1RenderTarget *iface)
1027 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1029 TRACE("iface %p.\n", iface);
1031 return render_target->drawing_state.textAntialiasMode;
1034 static void STDMETHODCALLTYPE d2d_d3d_render_target_SetTextRenderingParams(ID2D1RenderTarget *iface,
1035 IDWriteRenderingParams *text_rendering_params)
1037 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1039 TRACE("iface %p, text_rendering_params %p.\n", iface, text_rendering_params);
1041 if (text_rendering_params)
1042 IDWriteRenderingParams_AddRef(text_rendering_params);
1043 if (render_target->text_rendering_params)
1044 IDWriteRenderingParams_Release(render_target->text_rendering_params);
1045 render_target->text_rendering_params = text_rendering_params;
1048 static void STDMETHODCALLTYPE d2d_d3d_render_target_GetTextRenderingParams(ID2D1RenderTarget *iface,
1049 IDWriteRenderingParams **text_rendering_params)
1051 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1053 TRACE("iface %p, text_rendering_params %p.\n", iface, text_rendering_params);
1055 if ((*text_rendering_params = render_target->text_rendering_params))
1056 IDWriteRenderingParams_AddRef(*text_rendering_params);
1059 static void STDMETHODCALLTYPE d2d_d3d_render_target_SetTags(ID2D1RenderTarget *iface, D2D1_TAG tag1, D2D1_TAG tag2)
1061 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1063 TRACE("iface %p, tag1 %s, tag2 %s.\n", iface, wine_dbgstr_longlong(tag1), wine_dbgstr_longlong(tag2));
1065 render_target->drawing_state.tag1 = tag1;
1066 render_target->drawing_state.tag2 = tag2;
1069 static void STDMETHODCALLTYPE d2d_d3d_render_target_GetTags(ID2D1RenderTarget *iface, D2D1_TAG *tag1, D2D1_TAG *tag2)
1071 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1073 TRACE("iface %p, tag1 %p, tag2 %p.\n", iface, tag1, tag2);
1075 *tag1 = render_target->drawing_state.tag1;
1076 *tag2 = render_target->drawing_state.tag2;
1079 static void STDMETHODCALLTYPE d2d_d3d_render_target_PushLayer(ID2D1RenderTarget *iface,
1080 const D2D1_LAYER_PARAMETERS *layer_parameters, ID2D1Layer *layer)
1082 FIXME("iface %p, layer_parameters %p, layer %p stub!\n", iface, layer_parameters, layer);
1085 static void STDMETHODCALLTYPE d2d_d3d_render_target_PopLayer(ID2D1RenderTarget *iface)
1087 FIXME("iface %p stub!\n", iface);
1090 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_Flush(ID2D1RenderTarget *iface, D2D1_TAG *tag1, D2D1_TAG *tag2)
1092 FIXME("iface %p, tag1 %p, tag2 %p stub!\n", iface, tag1, tag2);
1094 return E_NOTIMPL;
1097 static void STDMETHODCALLTYPE d2d_d3d_render_target_SaveDrawingState(ID2D1RenderTarget *iface,
1098 ID2D1DrawingStateBlock *state_block)
1100 struct d2d_state_block *state_block_impl = unsafe_impl_from_ID2D1DrawingStateBlock(state_block);
1101 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1103 TRACE("iface %p, state_block %p.\n", iface, state_block);
1105 state_block_impl->drawing_state = render_target->drawing_state;
1106 if (render_target->text_rendering_params)
1107 IDWriteRenderingParams_AddRef(render_target->text_rendering_params);
1108 if (state_block_impl->text_rendering_params)
1109 IDWriteRenderingParams_Release(state_block_impl->text_rendering_params);
1110 state_block_impl->text_rendering_params = render_target->text_rendering_params;
1113 static void STDMETHODCALLTYPE d2d_d3d_render_target_RestoreDrawingState(ID2D1RenderTarget *iface,
1114 ID2D1DrawingStateBlock *state_block)
1116 struct d2d_state_block *state_block_impl = unsafe_impl_from_ID2D1DrawingStateBlock(state_block);
1117 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1119 TRACE("iface %p, state_block %p.\n", iface, state_block);
1121 render_target->drawing_state = state_block_impl->drawing_state;
1122 if (state_block_impl->text_rendering_params)
1123 IDWriteRenderingParams_AddRef(state_block_impl->text_rendering_params);
1124 if (render_target->text_rendering_params)
1125 IDWriteRenderingParams_Release(render_target->text_rendering_params);
1126 render_target->text_rendering_params = state_block_impl->text_rendering_params;
1129 static void STDMETHODCALLTYPE d2d_d3d_render_target_PushAxisAlignedClip(ID2D1RenderTarget *iface,
1130 const D2D1_RECT_F *clip_rect, D2D1_ANTIALIAS_MODE antialias_mode)
1132 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1133 D2D1_RECT_F transformed_rect;
1134 float x_scale, y_scale;
1135 D2D1_POINT_2F point;
1137 TRACE("iface %p, clip_rect %p, antialias_mode %#x.\n", iface, clip_rect, antialias_mode);
1139 if (antialias_mode != D2D1_ANTIALIAS_MODE_ALIASED)
1140 FIXME("Ignoring antialias_mode %#x.\n", antialias_mode);
1142 x_scale = render_target->dpi_x / 96.0f;
1143 y_scale = render_target->dpi_y / 96.0f;
1144 d2d_point_transform(&point, &render_target->drawing_state.transform,
1145 clip_rect->left * x_scale, clip_rect->top * y_scale);
1146 d2d_rect_set(&transformed_rect, point.x, point.y, point.x, point.y);
1147 d2d_point_transform(&point, &render_target->drawing_state.transform,
1148 clip_rect->left * x_scale, clip_rect->bottom * y_scale);
1149 d2d_rect_expand(&transformed_rect, &point);
1150 d2d_point_transform(&point, &render_target->drawing_state.transform,
1151 clip_rect->right * x_scale, clip_rect->top * y_scale);
1152 d2d_rect_expand(&transformed_rect, &point);
1153 d2d_point_transform(&point, &render_target->drawing_state.transform,
1154 clip_rect->right * x_scale, clip_rect->bottom * y_scale);
1155 d2d_rect_expand(&transformed_rect, &point);
1157 if (!d2d_clip_stack_push(&render_target->clip_stack, &transformed_rect))
1158 WARN("Failed to push clip rect.\n");
1161 static void STDMETHODCALLTYPE d2d_d3d_render_target_PopAxisAlignedClip(ID2D1RenderTarget *iface)
1163 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1165 TRACE("iface %p.\n", iface);
1167 d2d_clip_stack_pop(&render_target->clip_stack);
1170 static void STDMETHODCALLTYPE d2d_d3d_render_target_Clear(ID2D1RenderTarget *iface, const D2D1_COLOR_F *color)
1172 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1173 D2D1_COLOR_F c = {0.0f, 0.0f, 0.0f, 0.0f};
1174 D3D10_SUBRESOURCE_DATA buffer_data;
1175 D3D10_BUFFER_DESC buffer_desc;
1176 ID3D10Buffer *vs_cb, *ps_cb;
1177 HRESULT hr;
1179 static const float transform[] =
1181 1.0f, 0.0f, 0.0f, 0.0f,
1182 0.0f, -1.0f, 0.0f, 0.0f,
1185 TRACE("iface %p, color %p.\n", iface, color);
1187 buffer_desc.ByteWidth = sizeof(transform);
1188 buffer_desc.Usage = D3D10_USAGE_DEFAULT;
1189 buffer_desc.BindFlags = D3D10_BIND_CONSTANT_BUFFER;
1190 buffer_desc.CPUAccessFlags = 0;
1191 buffer_desc.MiscFlags = 0;
1193 buffer_data.pSysMem = transform;
1194 buffer_data.SysMemPitch = 0;
1195 buffer_data.SysMemSlicePitch = 0;
1197 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device, &buffer_desc, &buffer_data, &vs_cb)))
1199 WARN("Failed to create constant buffer, hr %#x.\n", hr);
1200 return;
1203 if (color)
1204 c = *color;
1205 if (render_target->format.alphaMode == D2D1_ALPHA_MODE_IGNORE)
1206 c.a = 1.0f;
1207 c.r *= c.a;
1208 c.g *= c.a;
1209 c.b *= c.a;
1210 buffer_desc.ByteWidth = sizeof(c);
1211 buffer_data.pSysMem = &c;
1213 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device, &buffer_desc, &buffer_data, &ps_cb)))
1215 WARN("Failed to create constant buffer, hr %#x.\n", hr);
1216 ID3D10Buffer_Release(vs_cb);
1217 return;
1220 d2d_draw(render_target, D2D_SHAPE_TYPE_TRIANGLE, render_target->ib, 6,
1221 render_target->vb, render_target->vb_stride, vs_cb, ps_cb, NULL);
1223 ID3D10Buffer_Release(ps_cb);
1224 ID3D10Buffer_Release(vs_cb);
1227 static void STDMETHODCALLTYPE d2d_d3d_render_target_BeginDraw(ID2D1RenderTarget *iface)
1229 TRACE("iface %p.\n", iface);
1232 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_EndDraw(ID2D1RenderTarget *iface,
1233 D2D1_TAG *tag1, D2D1_TAG *tag2)
1235 TRACE("iface %p, tag1 %p, tag2 %p.\n", iface, tag1, tag2);
1237 if (tag1)
1238 *tag1 = 0;
1239 if (tag2)
1240 *tag2 = 0;
1242 return S_OK;
1245 static D2D1_PIXEL_FORMAT * STDMETHODCALLTYPE d2d_d3d_render_target_GetPixelFormat(ID2D1RenderTarget *iface,
1246 D2D1_PIXEL_FORMAT *format)
1248 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1250 TRACE("iface %p, format %p.\n", iface, format);
1252 *format = render_target->format;
1253 return format;
1256 static void STDMETHODCALLTYPE d2d_d3d_render_target_SetDpi(ID2D1RenderTarget *iface, float dpi_x, float dpi_y)
1258 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1260 TRACE("iface %p, dpi_x %.8e, dpi_y %.8e.\n", iface, dpi_x, dpi_y);
1262 if (dpi_x == 0.0f && dpi_y == 0.0f)
1264 dpi_x = 96.0f;
1265 dpi_y = 96.0f;
1268 render_target->dpi_x = dpi_x;
1269 render_target->dpi_y = dpi_y;
1272 static void STDMETHODCALLTYPE d2d_d3d_render_target_GetDpi(ID2D1RenderTarget *iface, float *dpi_x, float *dpi_y)
1274 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1276 TRACE("iface %p, dpi_x %p, dpi_y %p.\n", iface, dpi_x, dpi_y);
1278 *dpi_x = render_target->dpi_x;
1279 *dpi_y = render_target->dpi_y;
1282 static D2D1_SIZE_F * STDMETHODCALLTYPE d2d_d3d_render_target_GetSize(ID2D1RenderTarget *iface, D2D1_SIZE_F *size)
1284 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1286 TRACE("iface %p, size %p.\n", iface, size);
1288 size->width = render_target->pixel_size.width / (render_target->dpi_x / 96.0f);
1289 size->height = render_target->pixel_size.height / (render_target->dpi_y / 96.0f);
1290 return size;
1293 static D2D1_SIZE_U * STDMETHODCALLTYPE d2d_d3d_render_target_GetPixelSize(ID2D1RenderTarget *iface,
1294 D2D1_SIZE_U *pixel_size)
1296 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1298 TRACE("iface %p, pixel_size %p.\n", iface, pixel_size);
1300 *pixel_size = render_target->pixel_size;
1301 return pixel_size;
1304 static UINT32 STDMETHODCALLTYPE d2d_d3d_render_target_GetMaximumBitmapSize(ID2D1RenderTarget *iface)
1306 FIXME("iface %p stub!\n", iface);
1308 return 0;
1311 static BOOL STDMETHODCALLTYPE d2d_d3d_render_target_IsSupported(ID2D1RenderTarget *iface,
1312 const D2D1_RENDER_TARGET_PROPERTIES *desc)
1314 FIXME("iface %p, desc %p stub!\n", iface, desc);
1316 return FALSE;
1319 static const struct ID2D1RenderTargetVtbl d2d_d3d_render_target_vtbl =
1321 d2d_d3d_render_target_QueryInterface,
1322 d2d_d3d_render_target_AddRef,
1323 d2d_d3d_render_target_Release,
1324 d2d_d3d_render_target_GetFactory,
1325 d2d_d3d_render_target_CreateBitmap,
1326 d2d_d3d_render_target_CreateBitmapFromWicBitmap,
1327 d2d_d3d_render_target_CreateSharedBitmap,
1328 d2d_d3d_render_target_CreateBitmapBrush,
1329 d2d_d3d_render_target_CreateSolidColorBrush,
1330 d2d_d3d_render_target_CreateGradientStopCollection,
1331 d2d_d3d_render_target_CreateLinearGradientBrush,
1332 d2d_d3d_render_target_CreateRadialGradientBrush,
1333 d2d_d3d_render_target_CreateCompatibleRenderTarget,
1334 d2d_d3d_render_target_CreateLayer,
1335 d2d_d3d_render_target_CreateMesh,
1336 d2d_d3d_render_target_DrawLine,
1337 d2d_d3d_render_target_DrawRectangle,
1338 d2d_d3d_render_target_FillRectangle,
1339 d2d_d3d_render_target_DrawRoundedRectangle,
1340 d2d_d3d_render_target_FillRoundedRectangle,
1341 d2d_d3d_render_target_DrawEllipse,
1342 d2d_d3d_render_target_FillEllipse,
1343 d2d_d3d_render_target_DrawGeometry,
1344 d2d_d3d_render_target_FillGeometry,
1345 d2d_d3d_render_target_FillMesh,
1346 d2d_d3d_render_target_FillOpacityMask,
1347 d2d_d3d_render_target_DrawBitmap,
1348 d2d_d3d_render_target_DrawText,
1349 d2d_d3d_render_target_DrawTextLayout,
1350 d2d_d3d_render_target_DrawGlyphRun,
1351 d2d_d3d_render_target_SetTransform,
1352 d2d_d3d_render_target_GetTransform,
1353 d2d_d3d_render_target_SetAntialiasMode,
1354 d2d_d3d_render_target_GetAntialiasMode,
1355 d2d_d3d_render_target_SetTextAntialiasMode,
1356 d2d_d3d_render_target_GetTextAntialiasMode,
1357 d2d_d3d_render_target_SetTextRenderingParams,
1358 d2d_d3d_render_target_GetTextRenderingParams,
1359 d2d_d3d_render_target_SetTags,
1360 d2d_d3d_render_target_GetTags,
1361 d2d_d3d_render_target_PushLayer,
1362 d2d_d3d_render_target_PopLayer,
1363 d2d_d3d_render_target_Flush,
1364 d2d_d3d_render_target_SaveDrawingState,
1365 d2d_d3d_render_target_RestoreDrawingState,
1366 d2d_d3d_render_target_PushAxisAlignedClip,
1367 d2d_d3d_render_target_PopAxisAlignedClip,
1368 d2d_d3d_render_target_Clear,
1369 d2d_d3d_render_target_BeginDraw,
1370 d2d_d3d_render_target_EndDraw,
1371 d2d_d3d_render_target_GetPixelFormat,
1372 d2d_d3d_render_target_SetDpi,
1373 d2d_d3d_render_target_GetDpi,
1374 d2d_d3d_render_target_GetSize,
1375 d2d_d3d_render_target_GetPixelSize,
1376 d2d_d3d_render_target_GetMaximumBitmapSize,
1377 d2d_d3d_render_target_IsSupported,
1380 static inline struct d2d_d3d_render_target *impl_from_IDWriteTextRenderer(IDWriteTextRenderer *iface)
1382 return CONTAINING_RECORD(iface, struct d2d_d3d_render_target, IDWriteTextRenderer_iface);
1385 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_QueryInterface(IDWriteTextRenderer *iface, REFIID iid, void **out)
1387 TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
1389 if (IsEqualGUID(iid, &IID_IDWriteTextRenderer)
1390 || IsEqualGUID(iid, &IID_IDWritePixelSnapping)
1391 || IsEqualGUID(iid, &IID_IUnknown))
1393 IDWriteTextRenderer_AddRef(iface);
1394 *out = iface;
1395 return S_OK;
1398 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
1400 *out = NULL;
1401 return E_NOINTERFACE;
1404 static ULONG STDMETHODCALLTYPE d2d_text_renderer_AddRef(IDWriteTextRenderer *iface)
1406 struct d2d_d3d_render_target *render_target = impl_from_IDWriteTextRenderer(iface);
1408 TRACE("iface %p.\n", iface);
1410 return d2d_d3d_render_target_AddRef(&render_target->ID2D1RenderTarget_iface);
1413 static ULONG STDMETHODCALLTYPE d2d_text_renderer_Release(IDWriteTextRenderer *iface)
1415 struct d2d_d3d_render_target *render_target = impl_from_IDWriteTextRenderer(iface);
1417 TRACE("iface %p.\n", iface);
1419 return d2d_d3d_render_target_Release(&render_target->ID2D1RenderTarget_iface);
1422 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_IsPixelSnappingDisabled(IDWriteTextRenderer *iface,
1423 void *ctx, BOOL *disabled)
1425 struct d2d_draw_text_layout_ctx *context = ctx;
1427 TRACE("iface %p, ctx %p, disabled %p.\n", iface, ctx, disabled);
1429 *disabled = context->options & D2D1_DRAW_TEXT_OPTIONS_NO_SNAP;
1431 return S_OK;
1434 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_GetCurrentTransform(IDWriteTextRenderer *iface,
1435 void *ctx, DWRITE_MATRIX *transform)
1437 struct d2d_d3d_render_target *render_target = impl_from_IDWriteTextRenderer(iface);
1439 TRACE("iface %p, ctx %p, transform %p.\n", iface, ctx, transform);
1441 ID2D1RenderTarget_GetTransform(&render_target->ID2D1RenderTarget_iface, (D2D1_MATRIX_3X2_F *)transform);
1443 return S_OK;
1446 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_GetPixelsPerDip(IDWriteTextRenderer *iface, void *ctx, float *ppd)
1448 struct d2d_d3d_render_target *render_target = impl_from_IDWriteTextRenderer(iface);
1450 TRACE("iface %p, ctx %p, ppd %p.\n", iface, ctx, ppd);
1452 *ppd = render_target->dpi_y / 96.0f;
1454 return S_OK;
1457 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_DrawGlyphRun(IDWriteTextRenderer *iface, void *ctx,
1458 float baseline_origin_x, float baseline_origin_y, DWRITE_MEASURING_MODE measuring_mode,
1459 const DWRITE_GLYPH_RUN *glyph_run, const DWRITE_GLYPH_RUN_DESCRIPTION *desc, IUnknown *effect)
1461 struct d2d_d3d_render_target *render_target = impl_from_IDWriteTextRenderer(iface);
1462 D2D1_POINT_2F baseline_origin = {baseline_origin_x, baseline_origin_y};
1463 struct d2d_draw_text_layout_ctx *context = ctx;
1465 TRACE("iface %p, ctx %p, baseline_origin_x %.8e, baseline_origin_y %.8e, "
1466 "measuring_mode %#x, glyph_run %p, desc %p, effect %p.\n",
1467 iface, ctx, baseline_origin_x, baseline_origin_y,
1468 measuring_mode, glyph_run, desc, effect);
1470 if (desc)
1471 WARN("Ignoring glyph run description %p.\n", desc);
1472 if (effect)
1473 FIXME("Ignoring effect %p.\n", effect);
1474 if (context->options & ~D2D1_DRAW_TEXT_OPTIONS_NO_SNAP)
1475 FIXME("Ignoring options %#x.\n", context->options);
1477 TRACE("%s\n", debugstr_wn(desc->string, desc->stringLength));
1478 ID2D1RenderTarget_DrawGlyphRun(&render_target->ID2D1RenderTarget_iface,
1479 baseline_origin, glyph_run, context->brush, measuring_mode);
1481 return S_OK;
1484 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_DrawUnderline(IDWriteTextRenderer *iface, void *ctx,
1485 float baseline_origin_x, float baseline_origin_y, const DWRITE_UNDERLINE *underline, IUnknown *effect)
1487 FIXME("iface %p, ctx %p, baseline_origin_x %.8e, baseline_origin_y %.8e, underline %p, effect %p stub!\n",
1488 iface, ctx, baseline_origin_x, baseline_origin_y, underline, effect);
1490 return E_NOTIMPL;
1493 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_DrawStrikethrough(IDWriteTextRenderer *iface, void *ctx,
1494 float baseline_origin_x, float baseline_origin_y, const DWRITE_STRIKETHROUGH *strikethrough, IUnknown *effect)
1496 FIXME("iface %p, ctx %p, baseline_origin_x %.8e, baseline_origin_y %.8e, strikethrough %p, effect %p stub!\n",
1497 iface, ctx, baseline_origin_x, baseline_origin_y, strikethrough, effect);
1499 return E_NOTIMPL;
1502 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_DrawInlineObject(IDWriteTextRenderer *iface, void *ctx,
1503 float origin_x, float origin_y, IDWriteInlineObject *object, BOOL is_sideways, BOOL is_rtl, IUnknown *effect)
1505 TRACE("iface %p, ctx %p, origin_x %.8e, origin_y %.8e, object %p, is_sideways %#x, is_rtl %#x, effect %p.\n",
1506 iface, ctx, origin_x, origin_y, object, is_sideways, is_rtl, effect);
1508 return IDWriteInlineObject_Draw(object, ctx, iface, origin_x, origin_y, is_sideways, is_rtl, effect);
1511 static const struct IDWriteTextRendererVtbl d2d_text_renderer_vtbl =
1513 d2d_text_renderer_QueryInterface,
1514 d2d_text_renderer_AddRef,
1515 d2d_text_renderer_Release,
1516 d2d_text_renderer_IsPixelSnappingDisabled,
1517 d2d_text_renderer_GetCurrentTransform,
1518 d2d_text_renderer_GetPixelsPerDip,
1519 d2d_text_renderer_DrawGlyphRun,
1520 d2d_text_renderer_DrawUnderline,
1521 d2d_text_renderer_DrawStrikethrough,
1522 d2d_text_renderer_DrawInlineObject,
1525 HRESULT d2d_d3d_render_target_init(struct d2d_d3d_render_target *render_target, ID2D1Factory *factory,
1526 IDXGISurface *surface, const D2D1_RENDER_TARGET_PROPERTIES *desc)
1528 D3D10_SUBRESOURCE_DATA buffer_data;
1529 D3D10_STATE_BLOCK_MASK state_mask;
1530 DXGI_SURFACE_DESC surface_desc;
1531 D3D10_RASTERIZER_DESC rs_desc;
1532 D3D10_BUFFER_DESC buffer_desc;
1533 D3D10_BLEND_DESC blend_desc;
1534 ID3D10Resource *resource;
1535 unsigned int i, j;
1536 HRESULT hr;
1538 static const D3D10_INPUT_ELEMENT_DESC il_desc_triangle[] =
1540 {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0},
1542 static const D3D10_INPUT_ELEMENT_DESC il_desc_bezier[] =
1544 {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0},
1545 {"TEXCOORD", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 8, D3D10_INPUT_PER_VERTEX_DATA, 0},
1547 static const DWORD vs_code_triangle[] =
1549 /* float3x2 transform;
1551 * float4 main(float4 position : POSITION) : SV_POSITION
1553 * return float4(mul(position.xyw, transform), position.zw);
1554 * } */
1555 0x43425844, 0x0add3194, 0x205f74ec, 0xab527fe7, 0xbe6ad704, 0x00000001, 0x00000128, 0x00000003,
1556 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020,
1557 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000f0f, 0x49534f50, 0x4e4f4954, 0xababab00,
1558 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000001, 0x00000003,
1559 0x00000000, 0x0000000f, 0x505f5653, 0x5449534f, 0x004e4f49, 0x52444853, 0x0000008c, 0x00010040,
1560 0x00000023, 0x04000059, 0x00208e46, 0x00000000, 0x00000002, 0x0300005f, 0x001010f2, 0x00000000,
1561 0x04000067, 0x001020f2, 0x00000000, 0x00000001, 0x08000010, 0x00102012, 0x00000000, 0x00101346,
1562 0x00000000, 0x00208246, 0x00000000, 0x00000000, 0x08000010, 0x00102022, 0x00000000, 0x00101346,
1563 0x00000000, 0x00208246, 0x00000000, 0x00000001, 0x05000036, 0x001020c2, 0x00000000, 0x00101ea6,
1564 0x00000000, 0x0100003e,
1566 static const DWORD vs_code_bezier[] =
1568 #if 0
1569 float3x2 transform;
1571 float4 main(float4 position : POSITION,
1572 inout float3 texcoord : TEXCOORD0) : SV_POSITION
1574 return float4(mul(position.xyw, transform), position.zw);
1576 #endif
1577 0x43425844, 0x5e578adb, 0x093f7e27, 0x50d478af, 0xec3dfa4f, 0x00000001, 0x00000198, 0x00000003,
1578 0x0000002c, 0x00000080, 0x000000d8, 0x4e475349, 0x0000004c, 0x00000002, 0x00000008, 0x00000038,
1579 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000f0f, 0x00000041, 0x00000000, 0x00000000,
1580 0x00000003, 0x00000001, 0x00000707, 0x49534f50, 0x4e4f4954, 0x58455400, 0x524f4f43, 0xabab0044,
1581 0x4e47534f, 0x00000050, 0x00000002, 0x00000008, 0x00000038, 0x00000000, 0x00000001, 0x00000003,
1582 0x00000000, 0x0000000f, 0x00000044, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x00000807,
1583 0x505f5653, 0x5449534f, 0x004e4f49, 0x43584554, 0x44524f4f, 0xababab00, 0x52444853, 0x000000b8,
1584 0x00010040, 0x0000002e, 0x04000059, 0x00208e46, 0x00000000, 0x00000002, 0x0300005f, 0x001010f2,
1585 0x00000000, 0x0300005f, 0x00101072, 0x00000001, 0x04000067, 0x001020f2, 0x00000000, 0x00000001,
1586 0x03000065, 0x00102072, 0x00000001, 0x08000010, 0x00102012, 0x00000000, 0x00101346, 0x00000000,
1587 0x00208246, 0x00000000, 0x00000000, 0x08000010, 0x00102022, 0x00000000, 0x00101346, 0x00000000,
1588 0x00208246, 0x00000000, 0x00000001, 0x05000036, 0x001020c2, 0x00000000, 0x00101ea6, 0x00000000,
1589 0x05000036, 0x00102072, 0x00000001, 0x00101246, 0x00000001, 0x0100003e,
1591 static const DWORD ps_code_triangle_solid[] =
1593 /* float4 color;
1595 * float4 main(float4 position : SV_POSITION) : SV_Target
1597 * return color;
1598 * } */
1599 0x43425844, 0x88eefcfd, 0x93d6fd47, 0x173c242f, 0x0106d07a, 0x00000001, 0x000000dc, 0x00000003,
1600 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020,
1601 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x505f5653, 0x5449534f, 0x004e4f49,
1602 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003,
1603 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x00000040, 0x00000040,
1604 0x00000010, 0x04000059, 0x00208e46, 0x00000000, 0x00000001, 0x03000065, 0x001020f2, 0x00000000,
1605 0x06000036, 0x001020f2, 0x00000000, 0x00208e46, 0x00000000, 0x00000000, 0x0100003e,
1607 static const DWORD ps_code_triangle_bitmap[] =
1609 #if 0
1610 float3x2 transform;
1611 float opacity;
1612 bool ignore_alpha;
1614 SamplerState s;
1615 Texture2D t;
1617 float4 main(float4 position : SV_POSITION) : SV_Target
1619 float2 texcoord;
1620 float4 ret;
1622 texcoord.x = position.x * transform._11 + position.y * transform._21 + transform._31;
1623 texcoord.y = position.x * transform._12 + position.y * transform._22 + transform._32;
1624 ret = t.Sample(s, texcoord) * opacity;
1625 if (ignore_alpha)
1626 ret.a = opacity;
1628 return ret;
1630 #endif
1631 0x43425844, 0xf5bb1e01, 0xe3386963, 0xcaa095bd, 0xea2887de, 0x00000001, 0x000001fc, 0x00000003,
1632 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020,
1633 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000030f, 0x505f5653, 0x5449534f, 0x004e4f49,
1634 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003,
1635 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x00000160, 0x00000040,
1636 0x00000058, 0x04000059, 0x00208e46, 0x00000000, 0x00000003, 0x0300005a, 0x00106000, 0x00000000,
1637 0x04001858, 0x00107000, 0x00000000, 0x00005555, 0x04002064, 0x00101032, 0x00000000, 0x00000001,
1638 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000001, 0x0800000f, 0x00100012, 0x00000000,
1639 0x00101046, 0x00000000, 0x00208046, 0x00000000, 0x00000000, 0x08000000, 0x00100012, 0x00000000,
1640 0x0010000a, 0x00000000, 0x0020802a, 0x00000000, 0x00000000, 0x0800000f, 0x00100042, 0x00000000,
1641 0x00101046, 0x00000000, 0x00208046, 0x00000000, 0x00000001, 0x08000000, 0x00100022, 0x00000000,
1642 0x0010002a, 0x00000000, 0x0020802a, 0x00000000, 0x00000001, 0x09000045, 0x001000f2, 0x00000000,
1643 0x00100046, 0x00000000, 0x00107e46, 0x00000000, 0x00106000, 0x00000000, 0x08000038, 0x001000f2,
1644 0x00000000, 0x00100e46, 0x00000000, 0x00208ff6, 0x00000000, 0x00000001, 0x0b000037, 0x00102082,
1645 0x00000000, 0x0020800a, 0x00000000, 0x00000002, 0x0020803a, 0x00000000, 0x00000001, 0x0010003a,
1646 0x00000000, 0x05000036, 0x00102072, 0x00000000, 0x00100246, 0x00000000, 0x0100003e,
1648 /* The basic idea here is to evaluate the implicit form of the curve in
1649 * texture space. "t.z" determines which side of the curve is shaded. */
1650 static const DWORD ps_code_bezier_solid[] =
1652 #if 0
1653 float4 color;
1655 float4 main(float4 position : SV_POSITION, float3 t : TEXCOORD0) : SV_Target
1657 clip((t.x * t.x - t.y) * t.z);
1658 return color;
1660 #endif
1661 0x43425844, 0x66075f9e, 0x2ffe405b, 0xb551ee63, 0xa0d9f457, 0x00000001, 0x00000180, 0x00000003,
1662 0x0000002c, 0x00000084, 0x000000b8, 0x4e475349, 0x00000050, 0x00000002, 0x00000008, 0x00000038,
1663 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x00000044, 0x00000000, 0x00000000,
1664 0x00000003, 0x00000001, 0x00000707, 0x505f5653, 0x5449534f, 0x004e4f49, 0x43584554, 0x44524f4f,
1665 0xababab00, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000,
1666 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x000000c0,
1667 0x00000040, 0x00000030, 0x04000059, 0x00208e46, 0x00000000, 0x00000001, 0x03001062, 0x00101072,
1668 0x00000001, 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000001, 0x0a000032, 0x00100012,
1669 0x00000000, 0x0010100a, 0x00000001, 0x0010100a, 0x00000001, 0x8010101a, 0x00000041, 0x00000001,
1670 0x07000038, 0x00100012, 0x00000000, 0x0010000a, 0x00000000, 0x0010102a, 0x00000001, 0x07000031,
1671 0x00100012, 0x00000000, 0x0010000a, 0x00000000, 0x00004001, 0x00000000, 0x0304000d, 0x0010000a,
1672 0x00000000, 0x06000036, 0x001020f2, 0x00000000, 0x00208e46, 0x00000000, 0x00000000, 0x0100003e,
1674 static const struct
1676 float x, y;
1678 quad[] =
1680 {-1.0f, 1.0f},
1681 {-1.0f, -1.0f},
1682 { 1.0f, 1.0f},
1683 { 1.0f, -1.0f},
1685 static const UINT16 indices[] = {0, 1, 2, 2, 1, 3};
1686 static const D2D1_MATRIX_3X2_F identity =
1688 1.0f, 0.0f,
1689 0.0f, 1.0f,
1690 0.0f, 0.0f,
1693 if (desc->type != D2D1_RENDER_TARGET_TYPE_DEFAULT && desc->type != D2D1_RENDER_TARGET_TYPE_HARDWARE)
1694 WARN("Ignoring render target type %#x.\n", desc->type);
1695 if (desc->usage != D2D1_RENDER_TARGET_USAGE_NONE)
1696 FIXME("Ignoring render target usage %#x.\n", desc->usage);
1697 if (desc->minLevel != D2D1_FEATURE_LEVEL_DEFAULT)
1698 WARN("Ignoring feature level %#x.\n", desc->minLevel);
1700 render_target->ID2D1RenderTarget_iface.lpVtbl = &d2d_d3d_render_target_vtbl;
1701 render_target->IDWriteTextRenderer_iface.lpVtbl = &d2d_text_renderer_vtbl;
1702 render_target->refcount = 1;
1703 render_target->factory = factory;
1704 ID2D1Factory_AddRef(render_target->factory);
1706 if (FAILED(hr = IDXGISurface_GetDevice(surface, &IID_ID3D10Device, (void **)&render_target->device)))
1708 WARN("Failed to get device interface, hr %#x.\n", hr);
1709 ID2D1Factory_Release(render_target->factory);
1710 return hr;
1713 if (FAILED(hr = IDXGISurface_QueryInterface(surface, &IID_ID3D10Resource, (void **)&resource)))
1715 WARN("Failed to get ID3D10Resource interface, hr %#x.\n", hr);
1716 goto err;
1719 hr = ID3D10Device_CreateRenderTargetView(render_target->device, resource, NULL, &render_target->view);
1720 ID3D10Resource_Release(resource);
1721 if (FAILED(hr))
1723 WARN("Failed to create rendertarget view, hr %#x.\n", hr);
1724 goto err;
1727 if (FAILED(hr = D3D10StateBlockMaskEnableAll(&state_mask)))
1729 WARN("Failed to create stateblock mask, hr %#x.\n", hr);
1730 goto err;
1733 if (FAILED(hr = D3D10CreateStateBlock(render_target->device, &state_mask, &render_target->stateblock)))
1735 WARN("Failed to create stateblock, hr %#x.\n", hr);
1736 goto err;
1739 if (FAILED(hr = ID3D10Device_CreateInputLayout(render_target->device, il_desc_triangle,
1740 sizeof(il_desc_triangle) / sizeof(*il_desc_triangle), vs_code_triangle, sizeof(vs_code_triangle),
1741 &render_target->shape_resources[D2D_SHAPE_TYPE_TRIANGLE].il)))
1743 WARN("Failed to create triangle input layout, hr %#x.\n", hr);
1744 goto err;
1747 if (FAILED(hr = ID3D10Device_CreateInputLayout(render_target->device, il_desc_bezier,
1748 sizeof(il_desc_bezier) / sizeof(*il_desc_bezier), vs_code_bezier, sizeof(vs_code_bezier),
1749 &render_target->shape_resources[D2D_SHAPE_TYPE_BEZIER].il)))
1751 WARN("Failed to create bezier input layout, hr %#x.\n", hr);
1752 goto err;
1755 if (FAILED(hr = ID3D10Device_CreateVertexShader(render_target->device, vs_code_triangle,
1756 sizeof(vs_code_triangle), &render_target->shape_resources[D2D_SHAPE_TYPE_TRIANGLE].vs)))
1758 WARN("Failed to create triangle vertex shader, hr %#x.\n", hr);
1759 goto err;
1762 if (FAILED(hr = ID3D10Device_CreateVertexShader(render_target->device, vs_code_bezier,
1763 sizeof(vs_code_bezier), &render_target->shape_resources[D2D_SHAPE_TYPE_BEZIER].vs)))
1765 WARN("Failed to create bezier vertex shader, hr %#x.\n", hr);
1766 goto err;
1769 if (FAILED(hr = ID3D10Device_CreatePixelShader(render_target->device,
1770 ps_code_triangle_solid, sizeof(ps_code_triangle_solid),
1771 &render_target->shape_resources[D2D_SHAPE_TYPE_TRIANGLE].ps[D2D_BRUSH_TYPE_SOLID])))
1773 WARN("Failed to create triangle/solid pixel shader, hr %#x.\n", hr);
1774 goto err;
1777 if (FAILED(hr = ID3D10Device_CreatePixelShader(render_target->device,
1778 ps_code_triangle_bitmap, sizeof(ps_code_triangle_bitmap),
1779 &render_target->shape_resources[D2D_SHAPE_TYPE_TRIANGLE].ps[D2D_BRUSH_TYPE_BITMAP])))
1781 WARN("Failed to create triangle/bitmap pixel shader, hr %#x.\n", hr);
1782 goto err;
1785 if (FAILED(hr = ID3D10Device_CreatePixelShader(render_target->device,
1786 ps_code_bezier_solid, sizeof(ps_code_bezier_solid),
1787 &render_target->shape_resources[D2D_SHAPE_TYPE_BEZIER].ps[D2D_BRUSH_TYPE_SOLID])))
1789 WARN("Failed to create bezier/solid pixel shader, hr %#x.\n", hr);
1790 goto err;
1793 buffer_desc.ByteWidth = sizeof(indices);
1794 buffer_desc.Usage = D3D10_USAGE_DEFAULT;
1795 buffer_desc.BindFlags = D3D10_BIND_INDEX_BUFFER;
1796 buffer_desc.CPUAccessFlags = 0;
1797 buffer_desc.MiscFlags = 0;
1799 buffer_data.pSysMem = indices;
1800 buffer_data.SysMemPitch = 0;
1801 buffer_data.SysMemSlicePitch = 0;
1803 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device,
1804 &buffer_desc, &buffer_data, &render_target->ib)))
1806 WARN("Failed to create clear index buffer, hr %#x.\n", hr);
1807 goto err;
1810 buffer_desc.ByteWidth = sizeof(quad);
1811 buffer_desc.BindFlags = D3D10_BIND_VERTEX_BUFFER;
1812 buffer_data.pSysMem = quad;
1814 render_target->vb_stride = sizeof(*quad);
1815 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device,
1816 &buffer_desc, &buffer_data, &render_target->vb)))
1818 WARN("Failed to create clear vertex buffer, hr %#x.\n", hr);
1819 goto err;
1822 rs_desc.FillMode = D3D10_FILL_SOLID;
1823 rs_desc.CullMode = D3D10_CULL_NONE;
1824 rs_desc.FrontCounterClockwise = FALSE;
1825 rs_desc.DepthBias = 0;
1826 rs_desc.DepthBiasClamp = 0.0f;
1827 rs_desc.SlopeScaledDepthBias = 0.0f;
1828 rs_desc.DepthClipEnable = TRUE;
1829 rs_desc.ScissorEnable = TRUE;
1830 rs_desc.MultisampleEnable = FALSE;
1831 rs_desc.AntialiasedLineEnable = FALSE;
1832 if (FAILED(hr = ID3D10Device_CreateRasterizerState(render_target->device, &rs_desc, &render_target->rs)))
1834 WARN("Failed to create clear rasterizer state, hr %#x.\n", hr);
1835 goto err;
1838 memset(&blend_desc, 0, sizeof(blend_desc));
1839 blend_desc.BlendEnable[0] = TRUE;
1840 blend_desc.SrcBlend = D3D10_BLEND_ONE;
1841 blend_desc.DestBlend = D3D10_BLEND_INV_SRC_ALPHA;
1842 blend_desc.BlendOp = D3D10_BLEND_OP_ADD;
1843 if (desc->pixelFormat.alphaMode == D2D1_ALPHA_MODE_IGNORE)
1845 blend_desc.SrcBlendAlpha = D3D10_BLEND_ZERO;
1846 blend_desc.DestBlendAlpha = D3D10_BLEND_ONE;
1848 else
1850 blend_desc.SrcBlendAlpha = D3D10_BLEND_ONE;
1851 blend_desc.DestBlendAlpha = D3D10_BLEND_INV_SRC_ALPHA;
1853 blend_desc.BlendOpAlpha = D3D10_BLEND_OP_ADD;
1854 blend_desc.RenderTargetWriteMask[0] = D3D10_COLOR_WRITE_ENABLE_ALL;
1855 if (FAILED(hr = ID3D10Device_CreateBlendState(render_target->device, &blend_desc, &render_target->bs)))
1857 WARN("Failed to create blend state, hr %#x.\n", hr);
1858 goto err;
1861 if (FAILED(hr = IDXGISurface_GetDesc(surface, &surface_desc)))
1863 WARN("Failed to get surface desc, hr %#x.\n", hr);
1864 goto err;
1867 render_target->format = desc->pixelFormat;
1868 render_target->pixel_size.width = surface_desc.Width;
1869 render_target->pixel_size.height = surface_desc.Height;
1870 render_target->drawing_state.transform = identity;
1872 if (!d2d_clip_stack_init(&render_target->clip_stack))
1874 WARN("Failed to initialize clip stack.\n");
1875 hr = E_FAIL;
1876 goto err;
1879 render_target->dpi_x = desc->dpiX;
1880 render_target->dpi_y = desc->dpiY;
1882 if (render_target->dpi_x == 0.0f && render_target->dpi_y == 0.0f)
1884 render_target->dpi_x = 96.0f;
1885 render_target->dpi_y = 96.0f;
1888 return S_OK;
1890 err:
1891 if (render_target->bs)
1892 ID3D10BlendState_Release(render_target->bs);
1893 if (render_target->rs)
1894 ID3D10RasterizerState_Release(render_target->rs);
1895 if (render_target->vb)
1896 ID3D10Buffer_Release(render_target->vb);
1897 if (render_target->ib)
1898 ID3D10Buffer_Release(render_target->ib);
1899 for (i = 0; i < D2D_SHAPE_TYPE_COUNT; ++i)
1901 for (j = 0; j < D2D_BRUSH_TYPE_COUNT; ++j)
1903 if (render_target->shape_resources[i].ps[j])
1904 ID3D10PixelShader_Release(render_target->shape_resources[i].ps[j]);
1906 if (render_target->shape_resources[i].vs)
1907 ID3D10VertexShader_Release(render_target->shape_resources[i].vs);
1908 if (render_target->shape_resources[i].il)
1909 ID3D10InputLayout_Release(render_target->shape_resources[i].il);
1911 if (render_target->stateblock)
1912 render_target->stateblock->lpVtbl->Release(render_target->stateblock);
1913 if (render_target->view)
1914 ID3D10RenderTargetView_Release(render_target->view);
1915 if (render_target->device)
1916 ID3D10Device_Release(render_target->device);
1917 ID2D1Factory_Release(render_target->factory);
1918 return hr;