wined3d: Invalidate sRGB write state in wined3d_cs_exec_set_rendertarget_view() if...
[wine.git] / dlls / d2d1 / device.c
blob23ce03dce5ef495887486dab2620c69b9d15612d
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 "d2d1_private.h"
21 WINE_DEFAULT_DEBUG_CHANNEL(d2d);
23 #define INITIAL_CLIP_STACK_SIZE 4
25 static const D2D1_MATRIX_3X2_F identity =
26 {{{
27 1.0f, 0.0f,
28 0.0f, 1.0f,
29 0.0f, 0.0f,
30 }}};
32 struct d2d_draw_text_layout_ctx
34 ID2D1Brush *brush;
35 D2D1_DRAW_TEXT_OPTIONS options;
38 static inline struct d2d_device *impl_from_ID2D1Device(ID2D1Device *iface)
40 return CONTAINING_RECORD(iface, struct d2d_device, ID2D1Device_iface);
43 static struct d2d_device *unsafe_impl_from_ID2D1Device(ID2D1Device *iface);
45 static ID2D1Brush *d2d_draw_get_text_brush(struct d2d_draw_text_layout_ctx *context, IUnknown *effect)
47 ID2D1Brush *brush = NULL;
49 if (effect && SUCCEEDED(IUnknown_QueryInterface(effect, &IID_ID2D1Brush, (void**)&brush)))
50 return brush;
52 ID2D1Brush_AddRef(context->brush);
53 return context->brush;
56 static void d2d_rect_intersect(D2D1_RECT_F *dst, const D2D1_RECT_F *src)
58 if (src->left > dst->left)
59 dst->left = src->left;
60 if (src->top > dst->top)
61 dst->top = src->top;
62 if (src->right < dst->right)
63 dst->right = src->right;
64 if (src->bottom < dst->bottom)
65 dst->bottom = src->bottom;
68 static void d2d_rect_set(D2D1_RECT_F *dst, float left, float top, float right, float bottom)
70 dst->left = left;
71 dst->top = top;
72 dst->right = right;
73 dst->bottom = bottom;
76 static void d2d_size_set(D2D1_SIZE_U *dst, float width, float height)
78 dst->width = width;
79 dst->height = height;
82 static BOOL d2d_clip_stack_init(struct d2d_clip_stack *stack)
84 if (!(stack->stack = heap_alloc(INITIAL_CLIP_STACK_SIZE * sizeof(*stack->stack))))
85 return FALSE;
87 stack->size = INITIAL_CLIP_STACK_SIZE;
88 stack->count = 0;
90 return TRUE;
93 static void d2d_clip_stack_cleanup(struct d2d_clip_stack *stack)
95 heap_free(stack->stack);
98 static BOOL d2d_clip_stack_push(struct d2d_clip_stack *stack, const D2D1_RECT_F *rect)
100 D2D1_RECT_F r;
102 if (!d2d_array_reserve((void **)&stack->stack, &stack->size, stack->count + 1, sizeof(*stack->stack)))
103 return FALSE;
105 r = *rect;
106 if (stack->count)
107 d2d_rect_intersect(&r, &stack->stack[stack->count - 1]);
108 stack->stack[stack->count++] = r;
110 return TRUE;
113 static void d2d_clip_stack_pop(struct d2d_clip_stack *stack)
115 if (!stack->count)
116 return;
117 --stack->count;
120 static void d2d_device_context_draw(struct d2d_device_context *render_target, enum d2d_shape_type shape_type,
121 ID3D10Buffer *ib, unsigned int index_count, ID3D10Buffer *vb, unsigned int vb_stride,
122 ID3D10Buffer *vs_cb, ID3D10Buffer *ps_cb, struct d2d_brush *brush, struct d2d_brush *opacity_brush)
124 struct d2d_shape_resources *shape_resources = &render_target->shape_resources[shape_type];
125 ID3D10Device *device = render_target->d3d_device;
126 D3D10_RECT scissor_rect;
127 unsigned int offset;
128 D3D10_VIEWPORT vp;
129 HRESULT hr;
131 vp.TopLeftX = 0;
132 vp.TopLeftY = 0;
133 vp.Width = render_target->pixel_size.width;
134 vp.Height = render_target->pixel_size.height;
135 vp.MinDepth = 0.0f;
136 vp.MaxDepth = 1.0f;
138 if (FAILED(hr = render_target->stateblock->lpVtbl->Capture(render_target->stateblock)))
140 WARN("Failed to capture stateblock, hr %#x.\n", hr);
141 return;
144 ID3D10Device_ClearState(device);
146 ID3D10Device_IASetInputLayout(device, shape_resources->il);
147 ID3D10Device_IASetPrimitiveTopology(device, D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
148 ID3D10Device_IASetIndexBuffer(device, ib, DXGI_FORMAT_R16_UINT, 0);
149 offset = 0;
150 ID3D10Device_IASetVertexBuffers(device, 0, 1, &vb, &vb_stride, &offset);
151 ID3D10Device_VSSetConstantBuffers(device, 0, 1, &vs_cb);
152 ID3D10Device_VSSetShader(device, shape_resources->vs);
153 ID3D10Device_PSSetConstantBuffers(device, 0, 1, &ps_cb);
154 ID3D10Device_PSSetShader(device, render_target->ps);
155 ID3D10Device_RSSetViewports(device, 1, &vp);
156 if (render_target->clip_stack.count)
158 const D2D1_RECT_F *clip_rect;
160 clip_rect = &render_target->clip_stack.stack[render_target->clip_stack.count - 1];
161 scissor_rect.left = ceilf(clip_rect->left - 0.5f);
162 scissor_rect.top = ceilf(clip_rect->top - 0.5f);
163 scissor_rect.right = ceilf(clip_rect->right - 0.5f);
164 scissor_rect.bottom = ceilf(clip_rect->bottom - 0.5f);
166 else
168 scissor_rect.left = 0.0f;
169 scissor_rect.top = 0.0f;
170 scissor_rect.right = render_target->pixel_size.width;
171 scissor_rect.bottom = render_target->pixel_size.height;
173 ID3D10Device_RSSetScissorRects(device, 1, &scissor_rect);
174 ID3D10Device_RSSetState(device, render_target->rs);
175 ID3D10Device_OMSetRenderTargets(device, 1, &render_target->target->rtv, NULL);
176 if (brush)
178 ID3D10Device_OMSetBlendState(device, render_target->bs, NULL, D3D10_DEFAULT_SAMPLE_MASK);
179 d2d_brush_bind_resources(brush, device, 0);
181 if (opacity_brush)
182 d2d_brush_bind_resources(opacity_brush, device, 1);
184 if (ib)
185 ID3D10Device_DrawIndexed(device, index_count, 0, 0);
186 else
187 ID3D10Device_Draw(device, index_count, 0);
189 if (FAILED(hr = render_target->stateblock->lpVtbl->Apply(render_target->stateblock)))
190 WARN("Failed to apply stateblock, hr %#x.\n", hr);
193 static void d2d_device_context_set_error(struct d2d_device_context *context, HRESULT code)
195 context->error.code = code;
196 context->error.tag1 = context->drawing_state.tag1;
197 context->error.tag2 = context->drawing_state.tag2;
200 static inline struct d2d_device_context *impl_from_IUnknown(IUnknown *iface)
202 return CONTAINING_RECORD(iface, struct d2d_device_context, IUnknown_iface);
205 static inline struct d2d_device_context *impl_from_ID2D1DeviceContext(ID2D1DeviceContext *iface)
207 return CONTAINING_RECORD(iface, struct d2d_device_context, ID2D1DeviceContext_iface);
210 static HRESULT STDMETHODCALLTYPE d2d_device_context_inner_QueryInterface(IUnknown *iface, REFIID iid, void **out)
212 struct d2d_device_context *context = impl_from_IUnknown(iface);
214 TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
216 if (IsEqualGUID(iid, &IID_ID2D1DeviceContext)
217 || IsEqualGUID(iid, &IID_ID2D1RenderTarget)
218 || IsEqualGUID(iid, &IID_ID2D1Resource)
219 || IsEqualGUID(iid, &IID_IUnknown))
221 ID2D1DeviceContext_AddRef(&context->ID2D1DeviceContext_iface);
222 *out = &context->ID2D1DeviceContext_iface;
223 return S_OK;
225 else if (IsEqualGUID(iid, &IID_ID2D1GdiInteropRenderTarget))
227 ID2D1GdiInteropRenderTarget_AddRef(&context->ID2D1GdiInteropRenderTarget_iface);
228 *out = &context->ID2D1GdiInteropRenderTarget_iface;
229 return S_OK;
232 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
234 *out = NULL;
235 return E_NOINTERFACE;
238 static ULONG STDMETHODCALLTYPE d2d_device_context_inner_AddRef(IUnknown *iface)
240 struct d2d_device_context *context = impl_from_IUnknown(iface);
241 ULONG refcount = InterlockedIncrement(&context->refcount);
243 TRACE("%p increasing refcount to %u.\n", iface, refcount);
245 return refcount;
248 static ULONG STDMETHODCALLTYPE d2d_device_context_inner_Release(IUnknown *iface)
250 struct d2d_device_context *context = impl_from_IUnknown(iface);
251 ULONG refcount = InterlockedDecrement(&context->refcount);
253 TRACE("%p decreasing refcount to %u.\n", iface, refcount);
255 if (!refcount)
257 unsigned int i;
259 d2d_clip_stack_cleanup(&context->clip_stack);
260 IDWriteRenderingParams_Release(context->default_text_rendering_params);
261 if (context->text_rendering_params)
262 IDWriteRenderingParams_Release(context->text_rendering_params);
263 if (context->bs)
264 ID3D10BlendState_Release(context->bs);
265 ID3D10RasterizerState_Release(context->rs);
266 ID3D10Buffer_Release(context->vb);
267 ID3D10Buffer_Release(context->ib);
268 ID3D10PixelShader_Release(context->ps);
269 for (i = 0; i < D2D_SHAPE_TYPE_COUNT; ++i)
271 ID3D10VertexShader_Release(context->shape_resources[i].vs);
272 ID3D10InputLayout_Release(context->shape_resources[i].il);
274 context->stateblock->lpVtbl->Release(context->stateblock);
275 if (context->target)
276 ID2D1Bitmap1_Release(&context->target->ID2D1Bitmap1_iface);
277 ID3D10Device_Release(context->d3d_device);
278 ID2D1Factory_Release(context->factory);
279 ID2D1Device_Release(context->device);
280 heap_free(context);
283 return refcount;
286 static const struct IUnknownVtbl d2d_device_context_inner_unknown_vtbl =
288 d2d_device_context_inner_QueryInterface,
289 d2d_device_context_inner_AddRef,
290 d2d_device_context_inner_Release,
293 static HRESULT STDMETHODCALLTYPE d2d_device_context_QueryInterface(ID2D1DeviceContext *iface, REFIID iid, void **out)
295 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
297 TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
299 return IUnknown_QueryInterface(context->outer_unknown, iid, out);
302 static ULONG STDMETHODCALLTYPE d2d_device_context_AddRef(ID2D1DeviceContext *iface)
304 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
306 TRACE("iface %p.\n", iface);
308 return IUnknown_AddRef(context->outer_unknown);
311 static ULONG STDMETHODCALLTYPE d2d_device_context_Release(ID2D1DeviceContext *iface)
313 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
315 TRACE("iface %p.\n", iface);
317 return IUnknown_Release(context->outer_unknown);
320 static void STDMETHODCALLTYPE d2d_device_context_GetFactory(ID2D1DeviceContext *iface, ID2D1Factory **factory)
322 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
324 TRACE("iface %p, factory %p.\n", iface, factory);
326 *factory = render_target->factory;
327 ID2D1Factory_AddRef(*factory);
330 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateBitmap(ID2D1DeviceContext *iface,
331 D2D1_SIZE_U size, const void *src_data, UINT32 pitch, const D2D1_BITMAP_PROPERTIES *desc, ID2D1Bitmap **bitmap)
333 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
334 D2D1_BITMAP_PROPERTIES1 bitmap_desc;
335 struct d2d_bitmap *object;
336 HRESULT hr;
338 TRACE("iface %p, size {%u, %u}, src_data %p, pitch %u, desc %p, bitmap %p.\n",
339 iface, size.width, size.height, src_data, pitch, desc, bitmap);
341 if (desc)
343 memcpy(&bitmap_desc, desc, sizeof(*desc));
344 bitmap_desc.bitmapOptions = 0;
345 bitmap_desc.colorContext = NULL;
348 if (SUCCEEDED(hr = d2d_bitmap_create(context, size, src_data, pitch, desc ? &bitmap_desc : NULL, &object)))
349 *bitmap = (ID2D1Bitmap *)&object->ID2D1Bitmap1_iface;
351 return hr;
354 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateBitmapFromWicBitmap(ID2D1DeviceContext *iface,
355 IWICBitmapSource *bitmap_source, const D2D1_BITMAP_PROPERTIES *desc, ID2D1Bitmap **bitmap)
357 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
358 D2D1_BITMAP_PROPERTIES1 bitmap_desc;
359 struct d2d_bitmap *object;
360 HRESULT hr;
362 TRACE("iface %p, bitmap_source %p, desc %p, bitmap %p.\n",
363 iface, bitmap_source, desc, bitmap);
365 if (desc)
367 memcpy(&bitmap_desc, desc, sizeof(*desc));
368 bitmap_desc.bitmapOptions = 0;
369 bitmap_desc.colorContext = NULL;
372 if (SUCCEEDED(hr = d2d_bitmap_create_from_wic_bitmap(context, bitmap_source, desc ? &bitmap_desc : NULL, &object)))
373 *bitmap = (ID2D1Bitmap *)&object->ID2D1Bitmap1_iface;
375 return hr;
378 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateSharedBitmap(ID2D1DeviceContext *iface,
379 REFIID iid, void *data, const D2D1_BITMAP_PROPERTIES *desc, ID2D1Bitmap **bitmap)
381 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
382 D2D1_BITMAP_PROPERTIES1 bitmap_desc;
383 struct d2d_bitmap *object;
384 HRESULT hr;
386 TRACE("iface %p, iid %s, data %p, desc %p, bitmap %p.\n",
387 iface, debugstr_guid(iid), data, desc, bitmap);
389 if (desc)
391 memcpy(&bitmap_desc, desc, sizeof(*desc));
392 bitmap_desc.bitmapOptions = D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW;
393 bitmap_desc.colorContext = NULL;
396 if (SUCCEEDED(hr = d2d_bitmap_create_shared(context, iid, data, desc ? &bitmap_desc : NULL, &object)))
397 *bitmap = (ID2D1Bitmap *)&object->ID2D1Bitmap1_iface;
399 return hr;
402 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateBitmapBrush(ID2D1DeviceContext *iface,
403 ID2D1Bitmap *bitmap, const D2D1_BITMAP_BRUSH_PROPERTIES *bitmap_brush_desc,
404 const D2D1_BRUSH_PROPERTIES *brush_desc, ID2D1BitmapBrush **brush)
406 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
407 struct d2d_brush *object;
408 HRESULT hr;
410 TRACE("iface %p, bitmap %p, bitmap_brush_desc %p, brush_desc %p, brush %p.\n",
411 iface, bitmap, bitmap_brush_desc, brush_desc, brush);
413 if (SUCCEEDED(hr = d2d_bitmap_brush_create(context->factory, bitmap, (const D2D1_BITMAP_BRUSH_PROPERTIES1 *)bitmap_brush_desc,
414 brush_desc, &object)))
415 *brush = (ID2D1BitmapBrush *)&object->ID2D1Brush_iface;
417 return hr;
420 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateSolidColorBrush(ID2D1DeviceContext *iface,
421 const D2D1_COLOR_F *color, const D2D1_BRUSH_PROPERTIES *desc, ID2D1SolidColorBrush **brush)
423 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
424 struct d2d_brush *object;
425 HRESULT hr;
427 TRACE("iface %p, color %p, desc %p, brush %p.\n", iface, color, desc, brush);
429 if (SUCCEEDED(hr = d2d_solid_color_brush_create(render_target->factory, color, desc, &object)))
430 *brush = (ID2D1SolidColorBrush *)&object->ID2D1Brush_iface;
432 return hr;
435 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateGradientStopCollection(ID2D1DeviceContext *iface,
436 const D2D1_GRADIENT_STOP *stops, UINT32 stop_count, D2D1_GAMMA gamma, D2D1_EXTEND_MODE extend_mode,
437 ID2D1GradientStopCollection **gradient)
439 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
440 struct d2d_gradient *object;
441 HRESULT hr;
443 TRACE("iface %p, stops %p, stop_count %u, gamma %#x, extend_mode %#x, gradient %p.\n",
444 iface, stops, stop_count, gamma, extend_mode, gradient);
446 if (SUCCEEDED(hr = d2d_gradient_create(render_target->factory, render_target->d3d_device,
447 stops, stop_count, gamma, extend_mode, &object)))
448 *gradient = &object->ID2D1GradientStopCollection_iface;
450 return hr;
453 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateLinearGradientBrush(ID2D1DeviceContext *iface,
454 const D2D1_LINEAR_GRADIENT_BRUSH_PROPERTIES *gradient_brush_desc, const D2D1_BRUSH_PROPERTIES *brush_desc,
455 ID2D1GradientStopCollection *gradient, ID2D1LinearGradientBrush **brush)
457 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
458 struct d2d_brush *object;
459 HRESULT hr;
461 TRACE("iface %p, gradient_brush_desc %p, brush_desc %p, gradient %p, brush %p.\n",
462 iface, gradient_brush_desc, brush_desc, gradient, brush);
464 if (SUCCEEDED(hr = d2d_linear_gradient_brush_create(render_target->factory, gradient_brush_desc, brush_desc,
465 gradient, &object)))
466 *brush = (ID2D1LinearGradientBrush *)&object->ID2D1Brush_iface;
468 return hr;
471 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateRadialGradientBrush(ID2D1DeviceContext *iface,
472 const D2D1_RADIAL_GRADIENT_BRUSH_PROPERTIES *gradient_brush_desc, const D2D1_BRUSH_PROPERTIES *brush_desc,
473 ID2D1GradientStopCollection *gradient, ID2D1RadialGradientBrush **brush)
475 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
476 struct d2d_brush *object;
477 HRESULT hr;
479 TRACE("iface %p, gradient_brush_desc %p, brush_desc %p, gradient %p, brush %p.\n",
480 iface, gradient_brush_desc, brush_desc, gradient, brush);
482 if (SUCCEEDED(hr = d2d_radial_gradient_brush_create(render_target->factory,
483 gradient_brush_desc, brush_desc, gradient, &object)))
484 *brush = (ID2D1RadialGradientBrush *)&object->ID2D1Brush_iface;
486 return hr;
489 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateCompatibleRenderTarget(ID2D1DeviceContext *iface,
490 const D2D1_SIZE_F *size, const D2D1_SIZE_U *pixel_size, const D2D1_PIXEL_FORMAT *format,
491 D2D1_COMPATIBLE_RENDER_TARGET_OPTIONS options, ID2D1BitmapRenderTarget **rt)
493 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
494 struct d2d_bitmap_render_target *object;
495 HRESULT hr;
497 TRACE("iface %p, size %p, pixel_size %p, format %p, options %#x, render_target %p.\n",
498 iface, size, pixel_size, format, options, rt);
500 if (!(object = heap_alloc_zero(sizeof(*object))))
501 return E_OUTOFMEMORY;
503 if (FAILED(hr = d2d_bitmap_render_target_init(object, render_target, size, pixel_size,
504 format, options)))
506 WARN("Failed to initialize render target, hr %#x.\n", hr);
507 heap_free(object);
508 return hr;
511 TRACE("Created render target %p.\n", object);
512 *rt = &object->ID2D1BitmapRenderTarget_iface;
514 return S_OK;
517 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateLayer(ID2D1DeviceContext *iface,
518 const D2D1_SIZE_F *size, ID2D1Layer **layer)
520 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
521 struct d2d_layer *object;
522 HRESULT hr;
524 TRACE("iface %p, size %p, layer %p.\n", iface, size, layer);
526 if (SUCCEEDED(hr = d2d_layer_create(render_target->factory, size, &object)))
527 *layer = &object->ID2D1Layer_iface;
529 return hr;
532 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateMesh(ID2D1DeviceContext *iface, ID2D1Mesh **mesh)
534 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
535 struct d2d_mesh *object;
536 HRESULT hr;
538 TRACE("iface %p, mesh %p.\n", iface, mesh);
540 if (SUCCEEDED(hr = d2d_mesh_create(render_target->factory, &object)))
541 *mesh = &object->ID2D1Mesh_iface;
543 return hr;
546 static void STDMETHODCALLTYPE d2d_device_context_DrawLine(ID2D1DeviceContext *iface,
547 D2D1_POINT_2F p0, D2D1_POINT_2F p1, ID2D1Brush *brush, float stroke_width, ID2D1StrokeStyle *stroke_style)
549 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
550 ID2D1PathGeometry *geometry;
551 ID2D1GeometrySink *sink;
552 HRESULT hr;
554 TRACE("iface %p, p0 %s, p1 %s, brush %p, stroke_width %.8e, stroke_style %p.\n",
555 iface, debug_d2d_point_2f(&p0), debug_d2d_point_2f(&p1), brush, stroke_width, stroke_style);
557 if (FAILED(hr = ID2D1Factory_CreatePathGeometry(render_target->factory, &geometry)))
559 WARN("Failed to create path geometry, %#x.\n", hr);
560 return;
563 if (FAILED(hr = ID2D1PathGeometry_Open(geometry, &sink)))
565 WARN("Open() failed, %#x.\n", hr);
566 ID2D1PathGeometry_Release(geometry);
567 return;
570 ID2D1GeometrySink_BeginFigure(sink, p0, D2D1_FIGURE_BEGIN_HOLLOW);
571 ID2D1GeometrySink_AddLine(sink, p1);
572 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_OPEN);
573 if (FAILED(hr = ID2D1GeometrySink_Close(sink)))
574 WARN("Close() failed, %#x.\n", hr);
575 ID2D1GeometrySink_Release(sink);
577 ID2D1DeviceContext_DrawGeometry(iface, (ID2D1Geometry *)geometry, brush, stroke_width, stroke_style);
578 ID2D1PathGeometry_Release(geometry);
581 static void STDMETHODCALLTYPE d2d_device_context_DrawRectangle(ID2D1DeviceContext *iface,
582 const D2D1_RECT_F *rect, ID2D1Brush *brush, float stroke_width, ID2D1StrokeStyle *stroke_style)
584 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
585 ID2D1RectangleGeometry *geometry;
586 HRESULT hr;
588 TRACE("iface %p, rect %s, brush %p, stroke_width %.8e, stroke_style %p.\n",
589 iface, debug_d2d_rect_f(rect), brush, stroke_width, stroke_style);
591 if (FAILED(hr = ID2D1Factory_CreateRectangleGeometry(render_target->factory, rect, &geometry)))
593 ERR("Failed to create geometry, hr %#x.\n", hr);
594 return;
597 ID2D1DeviceContext_DrawGeometry(iface, (ID2D1Geometry *)geometry, brush, stroke_width, stroke_style);
598 ID2D1RectangleGeometry_Release(geometry);
601 static void STDMETHODCALLTYPE d2d_device_context_FillRectangle(ID2D1DeviceContext *iface,
602 const D2D1_RECT_F *rect, ID2D1Brush *brush)
604 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
605 ID2D1RectangleGeometry *geometry;
606 HRESULT hr;
608 TRACE("iface %p, rect %s, brush %p.\n", iface, debug_d2d_rect_f(rect), brush);
610 if (FAILED(hr = ID2D1Factory_CreateRectangleGeometry(render_target->factory, rect, &geometry)))
612 ERR("Failed to create geometry, hr %#x.\n", hr);
613 return;
616 ID2D1DeviceContext_FillGeometry(iface, (ID2D1Geometry *)geometry, brush, NULL);
617 ID2D1RectangleGeometry_Release(geometry);
620 static void STDMETHODCALLTYPE d2d_device_context_DrawRoundedRectangle(ID2D1DeviceContext *iface,
621 const D2D1_ROUNDED_RECT *rect, ID2D1Brush *brush, float stroke_width, ID2D1StrokeStyle *stroke_style)
623 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
624 ID2D1RoundedRectangleGeometry *geometry;
625 HRESULT hr;
627 TRACE("iface %p, rect %p, brush %p, stroke_width %.8e, stroke_style %p.\n",
628 iface, rect, brush, stroke_width, stroke_style);
630 if (FAILED(hr = ID2D1Factory_CreateRoundedRectangleGeometry(render_target->factory, rect, &geometry)))
632 ERR("Failed to create geometry, hr %#x.\n", hr);
633 return;
636 ID2D1DeviceContext_DrawGeometry(iface, (ID2D1Geometry *)geometry, brush, stroke_width, stroke_style);
637 ID2D1RoundedRectangleGeometry_Release(geometry);
640 static void STDMETHODCALLTYPE d2d_device_context_FillRoundedRectangle(ID2D1DeviceContext *iface,
641 const D2D1_ROUNDED_RECT *rect, ID2D1Brush *brush)
643 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
644 ID2D1RoundedRectangleGeometry *geometry;
645 HRESULT hr;
647 TRACE("iface %p, rect %p, brush %p.\n", iface, rect, brush);
649 if (FAILED(hr = ID2D1Factory_CreateRoundedRectangleGeometry(render_target->factory, rect, &geometry)))
651 ERR("Failed to create geometry, hr %#x.\n", hr);
652 return;
655 ID2D1DeviceContext_FillGeometry(iface, (ID2D1Geometry *)geometry, brush, NULL);
656 ID2D1RoundedRectangleGeometry_Release(geometry);
659 static void STDMETHODCALLTYPE d2d_device_context_DrawEllipse(ID2D1DeviceContext *iface,
660 const D2D1_ELLIPSE *ellipse, ID2D1Brush *brush, float stroke_width, ID2D1StrokeStyle *stroke_style)
662 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
663 ID2D1EllipseGeometry *geometry;
664 HRESULT hr;
666 TRACE("iface %p, ellipse %p, brush %p, stroke_width %.8e, stroke_style %p.\n",
667 iface, ellipse, brush, stroke_width, stroke_style);
669 if (FAILED(hr = ID2D1Factory_CreateEllipseGeometry(render_target->factory, ellipse, &geometry)))
671 ERR("Failed to create geometry, hr %#x.\n", hr);
672 return;
675 ID2D1DeviceContext_DrawGeometry(iface, (ID2D1Geometry *)geometry, brush, stroke_width, stroke_style);
676 ID2D1EllipseGeometry_Release(geometry);
679 static void STDMETHODCALLTYPE d2d_device_context_FillEllipse(ID2D1DeviceContext *iface,
680 const D2D1_ELLIPSE *ellipse, ID2D1Brush *brush)
682 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
683 ID2D1EllipseGeometry *geometry;
684 HRESULT hr;
686 TRACE("iface %p, ellipse %p, brush %p.\n", iface, ellipse, brush);
688 if (FAILED(hr = ID2D1Factory_CreateEllipseGeometry(render_target->factory, ellipse, &geometry)))
690 ERR("Failed to create geometry, hr %#x.\n", hr);
691 return;
694 ID2D1DeviceContext_FillGeometry(iface, (ID2D1Geometry *)geometry, brush, NULL);
695 ID2D1EllipseGeometry_Release(geometry);
698 static void d2d_device_context_draw_geometry(struct d2d_device_context *render_target,
699 const struct d2d_geometry *geometry, struct d2d_brush *brush, float stroke_width)
701 ID3D10Buffer *ib, *vb, *vs_cb, *ps_cb_bezier, *ps_cb_arc;
702 D3D10_SUBRESOURCE_DATA buffer_data;
703 D3D10_BUFFER_DESC buffer_desc;
704 const D2D1_MATRIX_3X2_F *w;
705 float tmp_x, tmp_y;
706 HRESULT hr;
707 struct
709 struct
711 float _11, _21, _31, pad0;
712 float _12, _22, _32, stroke_width;
713 } transform_geometry;
714 struct d2d_vec4 transform_rtx;
715 struct d2d_vec4 transform_rty;
716 } vs_cb_data;
718 vs_cb_data.transform_geometry._11 = geometry->transform._11;
719 vs_cb_data.transform_geometry._21 = geometry->transform._21;
720 vs_cb_data.transform_geometry._31 = geometry->transform._31;
721 vs_cb_data.transform_geometry.pad0 = 0.0f;
722 vs_cb_data.transform_geometry._12 = geometry->transform._12;
723 vs_cb_data.transform_geometry._22 = geometry->transform._22;
724 vs_cb_data.transform_geometry._32 = geometry->transform._32;
725 vs_cb_data.transform_geometry.stroke_width = stroke_width;
727 w = &render_target->drawing_state.transform;
729 tmp_x = render_target->desc.dpiX / 96.0f;
730 vs_cb_data.transform_rtx.x = w->_11 * tmp_x;
731 vs_cb_data.transform_rtx.y = w->_21 * tmp_x;
732 vs_cb_data.transform_rtx.z = w->_31 * tmp_x;
733 vs_cb_data.transform_rtx.w = 2.0f / render_target->pixel_size.width;
735 tmp_y = render_target->desc.dpiY / 96.0f;
736 vs_cb_data.transform_rty.x = w->_12 * tmp_y;
737 vs_cb_data.transform_rty.y = w->_22 * tmp_y;
738 vs_cb_data.transform_rty.z = w->_32 * tmp_y;
739 vs_cb_data.transform_rty.w = -2.0f / render_target->pixel_size.height;
741 buffer_desc.ByteWidth = sizeof(vs_cb_data);
742 buffer_desc.Usage = D3D10_USAGE_DEFAULT;
743 buffer_desc.BindFlags = D3D10_BIND_CONSTANT_BUFFER;
744 buffer_desc.CPUAccessFlags = 0;
745 buffer_desc.MiscFlags = 0;
747 buffer_data.pSysMem = &vs_cb_data;
748 buffer_data.SysMemPitch = 0;
749 buffer_data.SysMemSlicePitch = 0;
751 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->d3d_device, &buffer_desc, &buffer_data, &vs_cb)))
753 WARN("Failed to create constant buffer, hr %#x.\n", hr);
754 return;
757 if (FAILED(hr = d2d_brush_get_ps_cb(brush, NULL, TRUE, FALSE, render_target, &ps_cb_bezier)))
759 WARN("Failed to get ps constant buffer, hr %#x.\n", hr);
760 ID3D10Buffer_Release(vs_cb);
761 return;
764 if (FAILED(hr = d2d_brush_get_ps_cb(brush, NULL, TRUE, TRUE, render_target, &ps_cb_arc)))
766 WARN("Failed to get ps constant buffer, hr %#x.\n", hr);
767 ID3D10Buffer_Release(vs_cb);
768 ID3D10Buffer_Release(ps_cb_bezier);
769 return;
772 if (geometry->outline.face_count)
774 buffer_desc.ByteWidth = geometry->outline.face_count * sizeof(*geometry->outline.faces);
775 buffer_desc.BindFlags = D3D10_BIND_INDEX_BUFFER;
776 buffer_data.pSysMem = geometry->outline.faces;
778 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->d3d_device, &buffer_desc, &buffer_data, &ib)))
780 WARN("Failed to create index buffer, hr %#x.\n", hr);
781 goto done;
784 buffer_desc.ByteWidth = geometry->outline.vertex_count * sizeof(*geometry->outline.vertices);
785 buffer_desc.BindFlags = D3D10_BIND_VERTEX_BUFFER;
786 buffer_data.pSysMem = geometry->outline.vertices;
788 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->d3d_device, &buffer_desc, &buffer_data, &vb)))
790 ERR("Failed to create vertex buffer, hr %#x.\n", hr);
791 ID3D10Buffer_Release(ib);
792 goto done;
795 d2d_device_context_draw(render_target, D2D_SHAPE_TYPE_OUTLINE, ib, 3 * geometry->outline.face_count, vb,
796 sizeof(*geometry->outline.vertices), vs_cb, ps_cb_bezier, brush, NULL);
798 ID3D10Buffer_Release(vb);
799 ID3D10Buffer_Release(ib);
802 if (geometry->outline.bezier_face_count)
804 buffer_desc.ByteWidth = geometry->outline.bezier_face_count * sizeof(*geometry->outline.bezier_faces);
805 buffer_desc.BindFlags = D3D10_BIND_INDEX_BUFFER;
806 buffer_data.pSysMem = geometry->outline.bezier_faces;
808 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->d3d_device, &buffer_desc, &buffer_data, &ib)))
810 WARN("Failed to create beziers index buffer, hr %#x.\n", hr);
811 goto done;
814 buffer_desc.ByteWidth = geometry->outline.bezier_count * sizeof(*geometry->outline.beziers);
815 buffer_desc.BindFlags = D3D10_BIND_VERTEX_BUFFER;
816 buffer_data.pSysMem = geometry->outline.beziers;
818 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->d3d_device, &buffer_desc, &buffer_data, &vb)))
820 ERR("Failed to create beziers vertex buffer, hr %#x.\n", hr);
821 ID3D10Buffer_Release(ib);
822 goto done;
825 d2d_device_context_draw(render_target, D2D_SHAPE_TYPE_BEZIER_OUTLINE, ib,
826 3 * geometry->outline.bezier_face_count, vb,
827 sizeof(*geometry->outline.beziers), vs_cb, ps_cb_bezier, brush, NULL);
829 ID3D10Buffer_Release(vb);
830 ID3D10Buffer_Release(ib);
833 if (geometry->outline.arc_face_count)
835 buffer_desc.ByteWidth = geometry->outline.arc_face_count * sizeof(*geometry->outline.arc_faces);
836 buffer_desc.BindFlags = D3D10_BIND_INDEX_BUFFER;
837 buffer_data.pSysMem = geometry->outline.arc_faces;
839 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->d3d_device, &buffer_desc, &buffer_data, &ib)))
841 WARN("Failed to create arcs index buffer, hr %#x.\n", hr);
842 goto done;
845 buffer_desc.ByteWidth = geometry->outline.arc_count * sizeof(*geometry->outline.arcs);
846 buffer_desc.BindFlags = D3D10_BIND_VERTEX_BUFFER;
847 buffer_data.pSysMem = geometry->outline.arcs;
849 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->d3d_device, &buffer_desc, &buffer_data, &vb)))
851 ERR("Failed to create arcs vertex buffer, hr %#x.\n", hr);
852 ID3D10Buffer_Release(ib);
853 goto done;
856 d2d_device_context_draw(render_target, D2D_SHAPE_TYPE_ARC_OUTLINE, ib,
857 3 * geometry->outline.arc_face_count, vb,
858 sizeof(*geometry->outline.arcs), vs_cb, ps_cb_arc, brush, NULL);
860 ID3D10Buffer_Release(vb);
861 ID3D10Buffer_Release(ib);
864 done:
865 ID3D10Buffer_Release(ps_cb_arc);
866 ID3D10Buffer_Release(ps_cb_bezier);
867 ID3D10Buffer_Release(vs_cb);
870 static void STDMETHODCALLTYPE d2d_device_context_DrawGeometry(ID2D1DeviceContext *iface,
871 ID2D1Geometry *geometry, ID2D1Brush *brush, float stroke_width, ID2D1StrokeStyle *stroke_style)
873 const struct d2d_geometry *geometry_impl = unsafe_impl_from_ID2D1Geometry(geometry);
874 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
875 struct d2d_brush *brush_impl = unsafe_impl_from_ID2D1Brush(brush);
877 TRACE("iface %p, geometry %p, brush %p, stroke_width %.8e, stroke_style %p.\n",
878 iface, geometry, brush, stroke_width, stroke_style);
880 if (stroke_style)
881 FIXME("Ignoring stroke style %p.\n", stroke_style);
883 d2d_device_context_draw_geometry(render_target, geometry_impl, brush_impl, stroke_width);
886 static void d2d_device_context_fill_geometry(struct d2d_device_context *render_target,
887 const struct d2d_geometry *geometry, struct d2d_brush *brush, struct d2d_brush *opacity_brush)
889 ID3D10Buffer *ib, *vb, *vs_cb, *ps_cb_bezier, *ps_cb_arc;
890 D3D10_SUBRESOURCE_DATA buffer_data;
891 D3D10_BUFFER_DESC buffer_desc;
892 D2D1_MATRIX_3X2_F *w;
893 float tmp_x, tmp_y;
894 HRESULT hr;
895 struct
897 struct
899 float _11, _21, _31, pad0;
900 float _12, _22, _32, pad1;
901 } transform_geometry;
902 struct d2d_vec4 transform_rtx;
903 struct d2d_vec4 transform_rty;
904 } vs_cb_data;
906 vs_cb_data.transform_geometry._11 = geometry->transform._11;
907 vs_cb_data.transform_geometry._21 = geometry->transform._21;
908 vs_cb_data.transform_geometry._31 = geometry->transform._31;
909 vs_cb_data.transform_geometry.pad0 = 0.0f;
910 vs_cb_data.transform_geometry._12 = geometry->transform._12;
911 vs_cb_data.transform_geometry._22 = geometry->transform._22;
912 vs_cb_data.transform_geometry._32 = geometry->transform._32;
913 vs_cb_data.transform_geometry.pad1 = 0.0f;
915 w = &render_target->drawing_state.transform;
917 tmp_x = render_target->desc.dpiX / 96.0f;
918 vs_cb_data.transform_rtx.x = w->_11 * tmp_x;
919 vs_cb_data.transform_rtx.y = w->_21 * tmp_x;
920 vs_cb_data.transform_rtx.z = w->_31 * tmp_x;
921 vs_cb_data.transform_rtx.w = 2.0f / render_target->pixel_size.width;
923 tmp_y = render_target->desc.dpiY / 96.0f;
924 vs_cb_data.transform_rty.x = w->_12 * tmp_y;
925 vs_cb_data.transform_rty.y = w->_22 * tmp_y;
926 vs_cb_data.transform_rty.z = w->_32 * tmp_y;
927 vs_cb_data.transform_rty.w = -2.0f / render_target->pixel_size.height;
929 buffer_desc.ByteWidth = sizeof(vs_cb_data);
930 buffer_desc.Usage = D3D10_USAGE_DEFAULT;
931 buffer_desc.BindFlags = D3D10_BIND_CONSTANT_BUFFER;
932 buffer_desc.CPUAccessFlags = 0;
933 buffer_desc.MiscFlags = 0;
935 buffer_data.pSysMem = &vs_cb_data;
936 buffer_data.SysMemPitch = 0;
937 buffer_data.SysMemSlicePitch = 0;
939 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->d3d_device, &buffer_desc, &buffer_data, &vs_cb)))
941 WARN("Failed to create constant buffer, hr %#x.\n", hr);
942 return;
945 if (FAILED(hr = d2d_brush_get_ps_cb(brush, opacity_brush, FALSE, FALSE, render_target, &ps_cb_bezier)))
947 WARN("Failed to get ps constant buffer, hr %#x.\n", hr);
948 ID3D10Buffer_Release(vs_cb);
949 return;
952 if (FAILED(hr = d2d_brush_get_ps_cb(brush, opacity_brush, FALSE, TRUE, render_target, &ps_cb_arc)))
954 WARN("Failed to get ps constant buffer, hr %#x.\n", hr);
955 ID3D10Buffer_Release(vs_cb);
956 ID3D10Buffer_Release(ps_cb_bezier);
957 return;
960 if (geometry->fill.face_count)
962 buffer_desc.ByteWidth = geometry->fill.face_count * sizeof(*geometry->fill.faces);
963 buffer_desc.BindFlags = D3D10_BIND_INDEX_BUFFER;
964 buffer_data.pSysMem = geometry->fill.faces;
966 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->d3d_device, &buffer_desc, &buffer_data, &ib)))
968 WARN("Failed to create index buffer, hr %#x.\n", hr);
969 goto done;
972 buffer_desc.ByteWidth = geometry->fill.vertex_count * sizeof(*geometry->fill.vertices);
973 buffer_desc.BindFlags = D3D10_BIND_VERTEX_BUFFER;
974 buffer_data.pSysMem = geometry->fill.vertices;
976 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->d3d_device, &buffer_desc, &buffer_data, &vb)))
978 ERR("Failed to create vertex buffer, hr %#x.\n", hr);
979 ID3D10Buffer_Release(ib);
980 goto done;
983 d2d_device_context_draw(render_target, D2D_SHAPE_TYPE_TRIANGLE, ib, 3 * geometry->fill.face_count, vb,
984 sizeof(*geometry->fill.vertices), vs_cb, ps_cb_bezier, brush, opacity_brush);
986 ID3D10Buffer_Release(vb);
987 ID3D10Buffer_Release(ib);
990 if (geometry->fill.bezier_vertex_count)
992 buffer_desc.ByteWidth = geometry->fill.bezier_vertex_count * sizeof(*geometry->fill.bezier_vertices);
993 buffer_desc.BindFlags = D3D10_BIND_VERTEX_BUFFER;
994 buffer_data.pSysMem = geometry->fill.bezier_vertices;
996 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->d3d_device, &buffer_desc, &buffer_data, &vb)))
998 ERR("Failed to create beziers vertex buffer, hr %#x.\n", hr);
999 goto done;
1002 d2d_device_context_draw(render_target, D2D_SHAPE_TYPE_CURVE, NULL, geometry->fill.bezier_vertex_count, vb,
1003 sizeof(*geometry->fill.bezier_vertices), vs_cb, ps_cb_bezier, brush, opacity_brush);
1005 ID3D10Buffer_Release(vb);
1008 if (geometry->fill.arc_vertex_count)
1010 buffer_desc.ByteWidth = geometry->fill.arc_vertex_count * sizeof(*geometry->fill.arc_vertices);
1011 buffer_desc.BindFlags = D3D10_BIND_VERTEX_BUFFER;
1012 buffer_data.pSysMem = geometry->fill.arc_vertices;
1014 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->d3d_device, &buffer_desc, &buffer_data, &vb)))
1016 ERR("Failed to create arc vertex buffer, hr %#x.\n", hr);
1017 goto done;
1020 d2d_device_context_draw(render_target, D2D_SHAPE_TYPE_CURVE, NULL, geometry->fill.arc_vertex_count, vb,
1021 sizeof(*geometry->fill.arc_vertices), vs_cb, ps_cb_arc, brush, opacity_brush);
1023 ID3D10Buffer_Release(vb);
1026 done:
1027 ID3D10Buffer_Release(ps_cb_arc);
1028 ID3D10Buffer_Release(ps_cb_bezier);
1029 ID3D10Buffer_Release(vs_cb);
1032 static void STDMETHODCALLTYPE d2d_device_context_FillGeometry(ID2D1DeviceContext *iface,
1033 ID2D1Geometry *geometry, ID2D1Brush *brush, ID2D1Brush *opacity_brush)
1035 const struct d2d_geometry *geometry_impl = unsafe_impl_from_ID2D1Geometry(geometry);
1036 struct d2d_brush *opacity_brush_impl = unsafe_impl_from_ID2D1Brush(opacity_brush);
1037 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
1038 struct d2d_brush *brush_impl = unsafe_impl_from_ID2D1Brush(brush);
1040 TRACE("iface %p, geometry %p, brush %p, opacity_brush %p.\n", iface, geometry, brush, opacity_brush);
1042 if (FAILED(context->error.code))
1043 return;
1045 if (opacity_brush && brush_impl->type != D2D_BRUSH_TYPE_BITMAP)
1047 d2d_device_context_set_error(context, D2DERR_INCOMPATIBLE_BRUSH_TYPES);
1048 return;
1051 d2d_device_context_fill_geometry(context, geometry_impl, brush_impl, opacity_brush_impl);
1054 static void STDMETHODCALLTYPE d2d_device_context_FillMesh(ID2D1DeviceContext *iface,
1055 ID2D1Mesh *mesh, ID2D1Brush *brush)
1057 FIXME("iface %p, mesh %p, brush %p stub!\n", iface, mesh, brush);
1060 static void STDMETHODCALLTYPE d2d_device_context_FillOpacityMask(ID2D1DeviceContext *iface,
1061 ID2D1Bitmap *mask, ID2D1Brush *brush, D2D1_OPACITY_MASK_CONTENT content,
1062 const D2D1_RECT_F *dst_rect, const D2D1_RECT_F *src_rect)
1064 FIXME("iface %p, mask %p, brush %p, content %#x, dst_rect %s, src_rect %s stub!\n",
1065 iface, mask, brush, content, debug_d2d_rect_f(dst_rect), debug_d2d_rect_f(src_rect));
1068 static void d2d_device_context_draw_bitmap(struct d2d_device_context *context, ID2D1Bitmap *bitmap,
1069 const D2D1_RECT_F *dst_rect, float opacity, D2D1_INTERPOLATION_MODE interpolation_mode,
1070 const D2D1_RECT_F *src_rect, const D2D1_POINT_2F *offset,
1071 const D2D1_MATRIX_4X4_F *perspective_transform)
1073 D2D1_BITMAP_BRUSH_PROPERTIES1 bitmap_brush_desc;
1074 D2D1_BRUSH_PROPERTIES brush_desc;
1075 struct d2d_brush *brush;
1076 D2D1_SIZE_F size;
1077 D2D1_RECT_F s, d;
1078 HRESULT hr;
1080 if (perspective_transform)
1081 FIXME("Perspective transform is ignored.\n");
1083 size = ID2D1Bitmap_GetSize(bitmap);
1084 d2d_rect_set(&s, 0.0f, 0.0f, size.width, size.height);
1085 if (src_rect && src_rect->left <= src_rect->right
1086 && src_rect->top <= src_rect->bottom)
1088 d2d_rect_intersect(&s, src_rect);
1091 if (s.left == s.right || s.top == s.bottom)
1092 return;
1094 if (dst_rect)
1096 d = *dst_rect;
1098 else
1100 d.left = 0.0f;
1101 d.top = 0.0f;
1102 d.right = s.right - s.left;
1103 d.bottom = s.bottom - s.top;
1106 if (offset)
1108 d.left += offset->x;
1109 d.top += offset->y;
1110 d.right += offset->x;
1111 d.bottom += offset->y;
1114 bitmap_brush_desc.extendModeX = D2D1_EXTEND_MODE_CLAMP;
1115 bitmap_brush_desc.extendModeY = D2D1_EXTEND_MODE_CLAMP;
1116 bitmap_brush_desc.interpolationMode = interpolation_mode;
1118 brush_desc.opacity = opacity;
1119 brush_desc.transform._11 = fabsf((d.right - d.left) / (s.right - s.left));
1120 brush_desc.transform._21 = 0.0f;
1121 brush_desc.transform._31 = min(d.left, d.right) - min(s.left, s.right) * brush_desc.transform._11;
1122 brush_desc.transform._12 = 0.0f;
1123 brush_desc.transform._22 = fabsf((d.bottom - d.top) / (s.bottom - s.top));
1124 brush_desc.transform._32 = min(d.top, d.bottom) - min(s.top, s.bottom) * brush_desc.transform._22;
1126 if (FAILED(hr = d2d_bitmap_brush_create(context->factory, bitmap, &bitmap_brush_desc, &brush_desc, &brush)))
1128 ERR("Failed to create bitmap brush, hr %#x.\n", hr);
1129 return;
1132 d2d_device_context_FillRectangle(&context->ID2D1DeviceContext_iface, &d, &brush->ID2D1Brush_iface);
1133 ID2D1Brush_Release(&brush->ID2D1Brush_iface);
1136 static void STDMETHODCALLTYPE d2d_device_context_DrawBitmap(ID2D1DeviceContext *iface,
1137 ID2D1Bitmap *bitmap, const D2D1_RECT_F *dst_rect, float opacity,
1138 D2D1_BITMAP_INTERPOLATION_MODE interpolation_mode, const D2D1_RECT_F *src_rect)
1140 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
1142 TRACE("iface %p, bitmap %p, dst_rect %s, opacity %.8e, interpolation_mode %#x, src_rect %s.\n",
1143 iface, bitmap, debug_d2d_rect_f(dst_rect), opacity, interpolation_mode, debug_d2d_rect_f(src_rect));
1145 if (interpolation_mode != D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR
1146 && interpolation_mode != D2D1_BITMAP_INTERPOLATION_MODE_LINEAR)
1148 d2d_device_context_set_error(context, E_INVALIDARG);
1149 return;
1152 d2d_device_context_draw_bitmap(context, bitmap, dst_rect, opacity, d2d1_1_interp_mode_from_d2d1(interpolation_mode),
1153 src_rect, NULL, NULL);
1156 static void STDMETHODCALLTYPE d2d_device_context_DrawText(ID2D1DeviceContext *iface,
1157 const WCHAR *string, UINT32 string_len, IDWriteTextFormat *text_format, const D2D1_RECT_F *layout_rect,
1158 ID2D1Brush *brush, D2D1_DRAW_TEXT_OPTIONS options, DWRITE_MEASURING_MODE measuring_mode)
1160 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1161 IDWriteTextLayout *text_layout;
1162 IDWriteFactory *dwrite_factory;
1163 D2D1_POINT_2F origin;
1164 float width, height;
1165 HRESULT hr;
1167 TRACE("iface %p, string %s, string_len %u, text_format %p, layout_rect %s, "
1168 "brush %p, options %#x, measuring_mode %#x.\n",
1169 iface, debugstr_wn(string, string_len), string_len, text_format, debug_d2d_rect_f(layout_rect),
1170 brush, options, measuring_mode);
1172 if (FAILED(hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED,
1173 &IID_IDWriteFactory, (IUnknown **)&dwrite_factory)))
1175 ERR("Failed to create dwrite factory, hr %#x.\n", hr);
1176 return;
1179 width = max(0.0f, layout_rect->right - layout_rect->left);
1180 height = max(0.0f, layout_rect->bottom - layout_rect->top);
1181 if (measuring_mode == DWRITE_MEASURING_MODE_NATURAL)
1182 hr = IDWriteFactory_CreateTextLayout(dwrite_factory, string, string_len, text_format,
1183 width, height, &text_layout);
1184 else
1185 hr = IDWriteFactory_CreateGdiCompatibleTextLayout(dwrite_factory, string, string_len, text_format,
1186 width, height, render_target->desc.dpiX / 96.0f, (DWRITE_MATRIX *)&render_target->drawing_state.transform,
1187 measuring_mode == DWRITE_MEASURING_MODE_GDI_NATURAL, &text_layout);
1188 IDWriteFactory_Release(dwrite_factory);
1189 if (FAILED(hr))
1191 ERR("Failed to create text layout, hr %#x.\n", hr);
1192 return;
1195 d2d_point_set(&origin, min(layout_rect->left, layout_rect->right), min(layout_rect->top, layout_rect->bottom));
1196 ID2D1DeviceContext_DrawTextLayout(iface, origin, text_layout, brush, options);
1197 IDWriteTextLayout_Release(text_layout);
1200 static void STDMETHODCALLTYPE d2d_device_context_DrawTextLayout(ID2D1DeviceContext *iface,
1201 D2D1_POINT_2F origin, IDWriteTextLayout *layout, ID2D1Brush *brush, D2D1_DRAW_TEXT_OPTIONS options)
1203 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1204 struct d2d_draw_text_layout_ctx ctx;
1205 HRESULT hr;
1207 TRACE("iface %p, origin %s, layout %p, brush %p, options %#x.\n",
1208 iface, debug_d2d_point_2f(&origin), layout, brush, options);
1210 ctx.brush = brush;
1211 ctx.options = options;
1213 if (FAILED(hr = IDWriteTextLayout_Draw(layout,
1214 &ctx, &render_target->IDWriteTextRenderer_iface, origin.x, origin.y)))
1215 FIXME("Failed to draw text layout, hr %#x.\n", hr);
1218 static D2D1_ANTIALIAS_MODE d2d_device_context_set_aa_mode_from_text_aa_mode(struct d2d_device_context *rt)
1220 D2D1_ANTIALIAS_MODE prev_antialias_mode = rt->drawing_state.antialiasMode;
1221 rt->drawing_state.antialiasMode = rt->drawing_state.textAntialiasMode == D2D1_TEXT_ANTIALIAS_MODE_ALIASED ?
1222 D2D1_ANTIALIAS_MODE_ALIASED : D2D1_ANTIALIAS_MODE_PER_PRIMITIVE;
1223 return prev_antialias_mode;
1226 static void d2d_device_context_draw_glyph_run_outline(struct d2d_device_context *render_target,
1227 D2D1_POINT_2F baseline_origin, const DWRITE_GLYPH_RUN *glyph_run, ID2D1Brush *brush)
1229 D2D1_MATRIX_3X2_F *transform, prev_transform;
1230 D2D1_ANTIALIAS_MODE prev_antialias_mode;
1231 ID2D1PathGeometry *geometry;
1232 ID2D1GeometrySink *sink;
1233 HRESULT hr;
1235 if (FAILED(hr = ID2D1Factory_CreatePathGeometry(render_target->factory, &geometry)))
1237 ERR("Failed to create geometry, hr %#x.\n", hr);
1238 return;
1241 if (FAILED(hr = ID2D1PathGeometry_Open(geometry, &sink)))
1243 ERR("Failed to open geometry sink, hr %#x.\n", hr);
1244 ID2D1PathGeometry_Release(geometry);
1245 return;
1248 if (FAILED(hr = IDWriteFontFace_GetGlyphRunOutline(glyph_run->fontFace, glyph_run->fontEmSize,
1249 glyph_run->glyphIndices, glyph_run->glyphAdvances, glyph_run->glyphOffsets, glyph_run->glyphCount,
1250 glyph_run->isSideways, glyph_run->bidiLevel & 1, (IDWriteGeometrySink *)sink)))
1252 ERR("Failed to get glyph run outline, hr %#x.\n", hr);
1253 ID2D1GeometrySink_Release(sink);
1254 ID2D1PathGeometry_Release(geometry);
1255 return;
1258 if (FAILED(hr = ID2D1GeometrySink_Close(sink)))
1259 ERR("Failed to close geometry sink, hr %#x.\n", hr);
1260 ID2D1GeometrySink_Release(sink);
1262 transform = &render_target->drawing_state.transform;
1263 prev_transform = *transform;
1264 transform->_31 += baseline_origin.x * transform->_11 + baseline_origin.y * transform->_21;
1265 transform->_32 += baseline_origin.x * transform->_12 + baseline_origin.y * transform->_22;
1266 prev_antialias_mode = d2d_device_context_set_aa_mode_from_text_aa_mode(render_target);
1267 d2d_device_context_fill_geometry(render_target, unsafe_impl_from_ID2D1Geometry((ID2D1Geometry *)geometry),
1268 unsafe_impl_from_ID2D1Brush(brush), NULL);
1269 render_target->drawing_state.antialiasMode = prev_antialias_mode;
1270 *transform = prev_transform;
1272 ID2D1PathGeometry_Release(geometry);
1275 static void d2d_device_context_draw_glyph_run_bitmap(struct d2d_device_context *render_target,
1276 D2D1_POINT_2F baseline_origin, const DWRITE_GLYPH_RUN *glyph_run, ID2D1Brush *brush,
1277 DWRITE_RENDERING_MODE rendering_mode, DWRITE_MEASURING_MODE measuring_mode,
1278 DWRITE_TEXT_ANTIALIAS_MODE antialias_mode)
1280 ID2D1RectangleGeometry *geometry = NULL;
1281 ID2D1BitmapBrush *opacity_brush = NULL;
1282 D2D1_BITMAP_PROPERTIES bitmap_desc;
1283 ID2D1Bitmap *opacity_bitmap = NULL;
1284 IDWriteGlyphRunAnalysis *analysis;
1285 DWRITE_TEXTURE_TYPE texture_type;
1286 D2D1_BRUSH_PROPERTIES brush_desc;
1287 IDWriteFactory2 *dwrite_factory;
1288 D2D1_MATRIX_3X2_F *transform, m;
1289 void *opacity_values = NULL;
1290 size_t opacity_values_size;
1291 D2D1_SIZE_U bitmap_size;
1292 float scale_x, scale_y;
1293 D2D1_RECT_F run_rect;
1294 RECT bounds;
1295 HRESULT hr;
1297 if (FAILED(hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED,
1298 &IID_IDWriteFactory2, (IUnknown **)&dwrite_factory)))
1300 ERR("Failed to create dwrite factory, hr %#x.\n", hr);
1301 return;
1304 transform = &render_target->drawing_state.transform;
1306 scale_x = render_target->desc.dpiX / 96.0f;
1307 m._11 = transform->_11 * scale_x;
1308 m._21 = transform->_21 * scale_x;
1309 m._31 = transform->_31 * scale_x;
1311 scale_y = render_target->desc.dpiY / 96.0f;
1312 m._12 = transform->_12 * scale_y;
1313 m._22 = transform->_22 * scale_y;
1314 m._32 = transform->_32 * scale_y;
1316 hr = IDWriteFactory2_CreateGlyphRunAnalysis(dwrite_factory, glyph_run, (DWRITE_MATRIX *)&m,
1317 rendering_mode, measuring_mode, DWRITE_GRID_FIT_MODE_DEFAULT, antialias_mode,
1318 baseline_origin.x, baseline_origin.y, &analysis);
1319 IDWriteFactory2_Release(dwrite_factory);
1320 if (FAILED(hr))
1322 ERR("Failed to create glyph run analysis, hr %#x.\n", hr);
1323 return;
1326 if (rendering_mode == DWRITE_RENDERING_MODE_ALIASED || antialias_mode == DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE)
1327 texture_type = DWRITE_TEXTURE_ALIASED_1x1;
1328 else
1329 texture_type = DWRITE_TEXTURE_CLEARTYPE_3x1;
1331 if (FAILED(hr = IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis, texture_type, &bounds)))
1333 ERR("Failed to get alpha texture bounds, hr %#x.\n", hr);
1334 goto done;
1337 d2d_size_set(&bitmap_size, bounds.right - bounds.left, bounds.bottom - bounds.top);
1338 if (!bitmap_size.width || !bitmap_size.height)
1340 /* Empty run, nothing to do. */
1341 goto done;
1344 if (texture_type == DWRITE_TEXTURE_CLEARTYPE_3x1)
1345 bitmap_size.width *= 3;
1346 if (!(opacity_values = heap_calloc(bitmap_size.height, bitmap_size.width)))
1348 ERR("Failed to allocate opacity values.\n");
1349 goto done;
1351 opacity_values_size = bitmap_size.height * bitmap_size.width;
1353 if (FAILED(hr = IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis,
1354 texture_type, &bounds, opacity_values, opacity_values_size)))
1356 ERR("Failed to create alpha texture, hr %#x.\n", hr);
1357 goto done;
1360 bitmap_desc.pixelFormat.format = DXGI_FORMAT_A8_UNORM;
1361 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
1362 bitmap_desc.dpiX = render_target->desc.dpiX;
1363 if (texture_type == DWRITE_TEXTURE_CLEARTYPE_3x1)
1364 bitmap_desc.dpiX *= 3.0f;
1365 bitmap_desc.dpiY = render_target->desc.dpiY;
1366 if (FAILED(hr = d2d_device_context_CreateBitmap(&render_target->ID2D1DeviceContext_iface,
1367 bitmap_size, opacity_values, bitmap_size.width, &bitmap_desc, &opacity_bitmap)))
1369 ERR("Failed to create opacity bitmap, hr %#x.\n", hr);
1370 goto done;
1373 d2d_rect_set(&run_rect, bounds.left / scale_x, bounds.top / scale_y,
1374 bounds.right / scale_x, bounds.bottom / scale_y);
1376 brush_desc.opacity = 1.0f;
1377 brush_desc.transform._11 = 1.0f;
1378 brush_desc.transform._12 = 0.0f;
1379 brush_desc.transform._21 = 0.0f;
1380 brush_desc.transform._22 = 1.0f;
1381 brush_desc.transform._31 = run_rect.left;
1382 brush_desc.transform._32 = run_rect.top;
1383 if (FAILED(hr = d2d_device_context_CreateBitmapBrush(&render_target->ID2D1DeviceContext_iface,
1384 opacity_bitmap, NULL, &brush_desc, &opacity_brush)))
1386 ERR("Failed to create opacity bitmap brush, hr %#x.\n", hr);
1387 goto done;
1390 if (FAILED(hr = ID2D1Factory_CreateRectangleGeometry(render_target->factory, &run_rect, &geometry)))
1392 ERR("Failed to create geometry, hr %#x.\n", hr);
1393 goto done;
1396 m = *transform;
1397 *transform = identity;
1398 d2d_device_context_fill_geometry(render_target, unsafe_impl_from_ID2D1Geometry((ID2D1Geometry *)geometry),
1399 unsafe_impl_from_ID2D1Brush(brush), unsafe_impl_from_ID2D1Brush((ID2D1Brush *)opacity_brush));
1400 *transform = m;
1402 done:
1403 if (geometry)
1404 ID2D1RectangleGeometry_Release(geometry);
1405 if (opacity_brush)
1406 ID2D1BitmapBrush_Release(opacity_brush);
1407 if (opacity_bitmap)
1408 ID2D1Bitmap_Release(opacity_bitmap);
1409 heap_free(opacity_values);
1410 IDWriteGlyphRunAnalysis_Release(analysis);
1413 static void STDMETHODCALLTYPE d2d_device_context_DrawGlyphRun(ID2D1DeviceContext *iface,
1414 D2D1_POINT_2F baseline_origin, const DWRITE_GLYPH_RUN *glyph_run, ID2D1Brush *brush,
1415 DWRITE_MEASURING_MODE measuring_mode)
1417 TRACE("iface %p, baseline_origin %s, glyph_run %p, brush %p, measuring_mode %#x.\n",
1418 iface, debug_d2d_point_2f(&baseline_origin), glyph_run, brush, measuring_mode);
1420 ID2D1DeviceContext_DrawGlyphRun(iface, baseline_origin, glyph_run, NULL, brush, measuring_mode);
1423 static void STDMETHODCALLTYPE d2d_device_context_SetTransform(ID2D1DeviceContext *iface,
1424 const D2D1_MATRIX_3X2_F *transform)
1426 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1428 TRACE("iface %p, transform %p.\n", iface, transform);
1430 render_target->drawing_state.transform = *transform;
1433 static void STDMETHODCALLTYPE d2d_device_context_GetTransform(ID2D1DeviceContext *iface,
1434 D2D1_MATRIX_3X2_F *transform)
1436 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1438 TRACE("iface %p, transform %p.\n", iface, transform);
1440 *transform = render_target->drawing_state.transform;
1443 static void STDMETHODCALLTYPE d2d_device_context_SetAntialiasMode(ID2D1DeviceContext *iface,
1444 D2D1_ANTIALIAS_MODE antialias_mode)
1446 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1448 TRACE("iface %p, antialias_mode %#x stub!\n", iface, antialias_mode);
1450 render_target->drawing_state.antialiasMode = antialias_mode;
1453 static D2D1_ANTIALIAS_MODE STDMETHODCALLTYPE d2d_device_context_GetAntialiasMode(ID2D1DeviceContext *iface)
1455 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1457 TRACE("iface %p.\n", iface);
1459 return render_target->drawing_state.antialiasMode;
1462 static void STDMETHODCALLTYPE d2d_device_context_SetTextAntialiasMode(ID2D1DeviceContext *iface,
1463 D2D1_TEXT_ANTIALIAS_MODE antialias_mode)
1465 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1467 TRACE("iface %p, antialias_mode %#x.\n", iface, antialias_mode);
1469 render_target->drawing_state.textAntialiasMode = antialias_mode;
1472 static D2D1_TEXT_ANTIALIAS_MODE STDMETHODCALLTYPE d2d_device_context_GetTextAntialiasMode(ID2D1DeviceContext *iface)
1474 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1476 TRACE("iface %p.\n", iface);
1478 return render_target->drawing_state.textAntialiasMode;
1481 static void STDMETHODCALLTYPE d2d_device_context_SetTextRenderingParams(ID2D1DeviceContext *iface,
1482 IDWriteRenderingParams *text_rendering_params)
1484 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1486 TRACE("iface %p, text_rendering_params %p.\n", iface, text_rendering_params);
1488 if (text_rendering_params)
1489 IDWriteRenderingParams_AddRef(text_rendering_params);
1490 if (render_target->text_rendering_params)
1491 IDWriteRenderingParams_Release(render_target->text_rendering_params);
1492 render_target->text_rendering_params = text_rendering_params;
1495 static void STDMETHODCALLTYPE d2d_device_context_GetTextRenderingParams(ID2D1DeviceContext *iface,
1496 IDWriteRenderingParams **text_rendering_params)
1498 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1500 TRACE("iface %p, text_rendering_params %p.\n", iface, text_rendering_params);
1502 if ((*text_rendering_params = render_target->text_rendering_params))
1503 IDWriteRenderingParams_AddRef(*text_rendering_params);
1506 static void STDMETHODCALLTYPE d2d_device_context_SetTags(ID2D1DeviceContext *iface, D2D1_TAG tag1, D2D1_TAG tag2)
1508 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1510 TRACE("iface %p, tag1 %s, tag2 %s.\n", iface, wine_dbgstr_longlong(tag1), wine_dbgstr_longlong(tag2));
1512 render_target->drawing_state.tag1 = tag1;
1513 render_target->drawing_state.tag2 = tag2;
1516 static void STDMETHODCALLTYPE d2d_device_context_GetTags(ID2D1DeviceContext *iface, D2D1_TAG *tag1, D2D1_TAG *tag2)
1518 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1520 TRACE("iface %p, tag1 %p, tag2 %p.\n", iface, tag1, tag2);
1522 *tag1 = render_target->drawing_state.tag1;
1523 *tag2 = render_target->drawing_state.tag2;
1526 static void STDMETHODCALLTYPE d2d_device_context_PushLayer(ID2D1DeviceContext *iface,
1527 const D2D1_LAYER_PARAMETERS *layer_parameters, ID2D1Layer *layer)
1529 FIXME("iface %p, layer_parameters %p, layer %p stub!\n", iface, layer_parameters, layer);
1532 static void STDMETHODCALLTYPE d2d_device_context_PopLayer(ID2D1DeviceContext *iface)
1534 FIXME("iface %p stub!\n", iface);
1537 static HRESULT STDMETHODCALLTYPE d2d_device_context_Flush(ID2D1DeviceContext *iface, D2D1_TAG *tag1, D2D1_TAG *tag2)
1539 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
1541 FIXME("iface %p, tag1 %p, tag2 %p stub!\n", iface, tag1, tag2);
1543 if (context->ops && context->ops->device_context_present)
1544 context->ops->device_context_present(context->outer_unknown);
1546 return E_NOTIMPL;
1549 static void STDMETHODCALLTYPE d2d_device_context_SaveDrawingState(ID2D1DeviceContext *iface,
1550 ID2D1DrawingStateBlock *state_block)
1552 struct d2d_state_block *state_block_impl = unsafe_impl_from_ID2D1DrawingStateBlock(state_block);
1553 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1555 TRACE("iface %p, state_block %p.\n", iface, state_block);
1557 state_block_impl->drawing_state = render_target->drawing_state;
1558 if (render_target->text_rendering_params)
1559 IDWriteRenderingParams_AddRef(render_target->text_rendering_params);
1560 if (state_block_impl->text_rendering_params)
1561 IDWriteRenderingParams_Release(state_block_impl->text_rendering_params);
1562 state_block_impl->text_rendering_params = render_target->text_rendering_params;
1565 static void STDMETHODCALLTYPE d2d_device_context_RestoreDrawingState(ID2D1DeviceContext *iface,
1566 ID2D1DrawingStateBlock *state_block)
1568 struct d2d_state_block *state_block_impl = unsafe_impl_from_ID2D1DrawingStateBlock(state_block);
1569 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1571 TRACE("iface %p, state_block %p.\n", iface, state_block);
1573 render_target->drawing_state = state_block_impl->drawing_state;
1574 if (state_block_impl->text_rendering_params)
1575 IDWriteRenderingParams_AddRef(state_block_impl->text_rendering_params);
1576 if (render_target->text_rendering_params)
1577 IDWriteRenderingParams_Release(render_target->text_rendering_params);
1578 render_target->text_rendering_params = state_block_impl->text_rendering_params;
1581 static void STDMETHODCALLTYPE d2d_device_context_PushAxisAlignedClip(ID2D1DeviceContext *iface,
1582 const D2D1_RECT_F *clip_rect, D2D1_ANTIALIAS_MODE antialias_mode)
1584 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1585 D2D1_RECT_F transformed_rect;
1586 float x_scale, y_scale;
1587 D2D1_POINT_2F point;
1589 TRACE("iface %p, clip_rect %s, antialias_mode %#x.\n", iface, debug_d2d_rect_f(clip_rect), antialias_mode);
1591 if (antialias_mode != D2D1_ANTIALIAS_MODE_ALIASED)
1592 FIXME("Ignoring antialias_mode %#x.\n", antialias_mode);
1594 x_scale = render_target->desc.dpiX / 96.0f;
1595 y_scale = render_target->desc.dpiY / 96.0f;
1596 d2d_point_transform(&point, &render_target->drawing_state.transform,
1597 clip_rect->left * x_scale, clip_rect->top * y_scale);
1598 d2d_rect_set(&transformed_rect, point.x, point.y, point.x, point.y);
1599 d2d_point_transform(&point, &render_target->drawing_state.transform,
1600 clip_rect->left * x_scale, clip_rect->bottom * y_scale);
1601 d2d_rect_expand(&transformed_rect, &point);
1602 d2d_point_transform(&point, &render_target->drawing_state.transform,
1603 clip_rect->right * x_scale, clip_rect->top * y_scale);
1604 d2d_rect_expand(&transformed_rect, &point);
1605 d2d_point_transform(&point, &render_target->drawing_state.transform,
1606 clip_rect->right * x_scale, clip_rect->bottom * y_scale);
1607 d2d_rect_expand(&transformed_rect, &point);
1609 if (!d2d_clip_stack_push(&render_target->clip_stack, &transformed_rect))
1610 WARN("Failed to push clip rect.\n");
1613 static void STDMETHODCALLTYPE d2d_device_context_PopAxisAlignedClip(ID2D1DeviceContext *iface)
1615 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1617 TRACE("iface %p.\n", iface);
1619 d2d_clip_stack_pop(&render_target->clip_stack);
1622 static void STDMETHODCALLTYPE d2d_device_context_Clear(ID2D1DeviceContext *iface, const D2D1_COLOR_F *colour)
1624 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1625 D3D10_SUBRESOURCE_DATA buffer_data;
1626 struct d2d_ps_cb ps_cb_data = {0};
1627 D3D10_BUFFER_DESC buffer_desc;
1628 ID3D10Buffer *vs_cb, *ps_cb;
1629 D2D1_COLOR_F *c;
1630 HRESULT hr;
1632 static const struct
1634 struct
1636 float _11, _21, _31, pad0;
1637 float _12, _22, _32, pad1;
1638 } transform_geometry;
1639 struct d2d_vec4 transform_rtx;
1640 struct d2d_vec4 transform_rty;
1642 vs_cb_data =
1644 {1.0f, 0.0f, 0.0f, 0.0f,
1645 0.0f, 1.0f, 0.0f, 0.0f},
1646 {1.0f, 0.0f, 1.0f, 1.0f},
1647 {0.0f, 1.0f, 1.0f, -1.0f},
1650 TRACE("iface %p, colour %p.\n", iface, colour);
1652 buffer_desc.ByteWidth = sizeof(vs_cb_data);
1653 buffer_desc.Usage = D3D10_USAGE_DEFAULT;
1654 buffer_desc.BindFlags = D3D10_BIND_CONSTANT_BUFFER;
1655 buffer_desc.CPUAccessFlags = 0;
1656 buffer_desc.MiscFlags = 0;
1658 buffer_data.pSysMem = &vs_cb_data;
1659 buffer_data.SysMemPitch = 0;
1660 buffer_data.SysMemSlicePitch = 0;
1662 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->d3d_device, &buffer_desc, &buffer_data, &vs_cb)))
1664 WARN("Failed to create constant buffer, hr %#x.\n", hr);
1665 return;
1668 ps_cb_data.outline = FALSE;
1669 ps_cb_data.colour_brush.type = D2D_BRUSH_TYPE_SOLID;
1670 ps_cb_data.colour_brush.opacity = 1.0f;
1671 c = &ps_cb_data.colour_brush.u.solid.colour;
1672 if (colour)
1673 *c = *colour;
1674 if (render_target->desc.pixelFormat.alphaMode == D2D1_ALPHA_MODE_IGNORE)
1675 c->a = 1.0f;
1676 c->r *= c->a;
1677 c->g *= c->a;
1678 c->b *= c->a;
1680 ps_cb_data.opacity_brush.type = D2D_BRUSH_TYPE_COUNT;
1682 buffer_desc.ByteWidth = sizeof(ps_cb_data);
1683 buffer_data.pSysMem = &ps_cb_data;
1685 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->d3d_device, &buffer_desc, &buffer_data, &ps_cb)))
1687 WARN("Failed to create constant buffer, hr %#x.\n", hr);
1688 ID3D10Buffer_Release(vs_cb);
1689 return;
1692 d2d_device_context_draw(render_target, D2D_SHAPE_TYPE_TRIANGLE, render_target->ib, 6,
1693 render_target->vb, render_target->vb_stride, vs_cb, ps_cb, NULL, NULL);
1695 ID3D10Buffer_Release(ps_cb);
1696 ID3D10Buffer_Release(vs_cb);
1699 static void STDMETHODCALLTYPE d2d_device_context_BeginDraw(ID2D1DeviceContext *iface)
1701 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1703 TRACE("iface %p.\n", iface);
1705 memset(&render_target->error, 0, sizeof(render_target->error));
1708 static HRESULT STDMETHODCALLTYPE d2d_device_context_EndDraw(ID2D1DeviceContext *iface,
1709 D2D1_TAG *tag1, D2D1_TAG *tag2)
1711 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
1712 HRESULT hr;
1714 TRACE("iface %p, tag1 %p, tag2 %p.\n", iface, tag1, tag2);
1716 if (tag1)
1717 *tag1 = context->error.tag1;
1718 if (tag2)
1719 *tag2 = context->error.tag2;
1721 if (context->ops && context->ops->device_context_present)
1723 if (FAILED(hr = context->ops->device_context_present(context->outer_unknown)))
1724 context->error.code = hr;
1727 return context->error.code;
1730 static D2D1_PIXEL_FORMAT * STDMETHODCALLTYPE d2d_device_context_GetPixelFormat(ID2D1DeviceContext *iface,
1731 D2D1_PIXEL_FORMAT *format)
1733 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1735 TRACE("iface %p, format %p.\n", iface, format);
1737 *format = render_target->desc.pixelFormat;
1738 return format;
1741 static void STDMETHODCALLTYPE d2d_device_context_SetDpi(ID2D1DeviceContext *iface, float dpi_x, float dpi_y)
1743 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1745 TRACE("iface %p, dpi_x %.8e, dpi_y %.8e.\n", iface, dpi_x, dpi_y);
1747 if (dpi_x == 0.0f && dpi_y == 0.0f)
1749 dpi_x = 96.0f;
1750 dpi_y = 96.0f;
1752 else if (dpi_x <= 0.0f || dpi_y <= 0.0f)
1753 return;
1755 render_target->desc.dpiX = dpi_x;
1756 render_target->desc.dpiY = dpi_y;
1759 static void STDMETHODCALLTYPE d2d_device_context_GetDpi(ID2D1DeviceContext *iface, float *dpi_x, float *dpi_y)
1761 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1763 TRACE("iface %p, dpi_x %p, dpi_y %p.\n", iface, dpi_x, dpi_y);
1765 *dpi_x = render_target->desc.dpiX;
1766 *dpi_y = render_target->desc.dpiY;
1769 static D2D1_SIZE_F * STDMETHODCALLTYPE d2d_device_context_GetSize(ID2D1DeviceContext *iface, D2D1_SIZE_F *size)
1771 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1773 TRACE("iface %p, size %p.\n", iface, size);
1775 size->width = render_target->pixel_size.width / (render_target->desc.dpiX / 96.0f);
1776 size->height = render_target->pixel_size.height / (render_target->desc.dpiY / 96.0f);
1777 return size;
1780 static D2D1_SIZE_U * STDMETHODCALLTYPE d2d_device_context_GetPixelSize(ID2D1DeviceContext *iface,
1781 D2D1_SIZE_U *pixel_size)
1783 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1785 TRACE("iface %p, pixel_size %p.\n", iface, pixel_size);
1787 *pixel_size = render_target->pixel_size;
1788 return pixel_size;
1791 static UINT32 STDMETHODCALLTYPE d2d_device_context_GetMaximumBitmapSize(ID2D1DeviceContext *iface)
1793 TRACE("iface %p.\n", iface);
1795 return D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION;
1798 static BOOL STDMETHODCALLTYPE d2d_device_context_IsSupported(ID2D1DeviceContext *iface,
1799 const D2D1_RENDER_TARGET_PROPERTIES *desc)
1801 FIXME("iface %p, desc %p stub!\n", iface, desc);
1803 return FALSE;
1806 static HRESULT STDMETHODCALLTYPE d2d_device_context_ID2D1DeviceContext_CreateBitmap(ID2D1DeviceContext *iface,
1807 D2D1_SIZE_U size, const void *src_data, UINT32 pitch,
1808 const D2D1_BITMAP_PROPERTIES1 *desc, ID2D1Bitmap1 **bitmap)
1810 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
1811 struct d2d_bitmap *object;
1812 HRESULT hr;
1814 TRACE("iface %p, size {%u, %u}, src_data %p, pitch %u, desc %p, bitmap %p.\n",
1815 iface, size.width, size.height, src_data, pitch, desc, bitmap);
1817 if (SUCCEEDED(hr = d2d_bitmap_create(context, size, src_data, pitch, desc, &object)))
1818 *bitmap = &object->ID2D1Bitmap1_iface;
1820 return hr;
1823 static HRESULT STDMETHODCALLTYPE d2d_device_context_ID2D1DeviceContext_CreateBitmapFromWicBitmap(
1824 ID2D1DeviceContext *iface, IWICBitmapSource *bitmap_source,
1825 const D2D1_BITMAP_PROPERTIES1 *desc, ID2D1Bitmap1 **bitmap)
1827 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
1828 struct d2d_bitmap *object;
1829 HRESULT hr;
1831 TRACE("iface %p, bitmap_source %p, desc %p, bitmap %p.\n", iface, bitmap_source, desc, bitmap);
1833 if (SUCCEEDED(hr = d2d_bitmap_create_from_wic_bitmap(context, bitmap_source, desc, &object)))
1834 *bitmap = &object->ID2D1Bitmap1_iface;
1836 return hr;
1839 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateColorContext(ID2D1DeviceContext *iface,
1840 D2D1_COLOR_SPACE space, const BYTE *profile, UINT32 profile_size, ID2D1ColorContext **color_context)
1842 FIXME("iface %p, space %#x, profile %p, profile_size %u, color_context %p stub!\n",
1843 iface, space, profile, profile_size, color_context);
1845 return E_NOTIMPL;
1848 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateColorContextFromFilename(ID2D1DeviceContext *iface,
1849 const WCHAR *filename, ID2D1ColorContext **color_context)
1851 FIXME("iface %p, filename %s, color_context %p stub!\n", iface, debugstr_w(filename), color_context);
1853 return E_NOTIMPL;
1856 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateColorContextFromWicColorContext(ID2D1DeviceContext *iface,
1857 IWICColorContext *wic_color_context, ID2D1ColorContext **color_context)
1859 FIXME("iface %p, wic_color_context %p, color_context %p stub!\n", iface, wic_color_context, color_context);
1861 return E_NOTIMPL;
1864 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateBitmapFromDxgiSurface(ID2D1DeviceContext *iface,
1865 IDXGISurface *surface, const D2D1_BITMAP_PROPERTIES1 *desc, ID2D1Bitmap1 **bitmap)
1867 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
1868 D2D1_BITMAP_PROPERTIES1 bitmap_desc;
1869 struct d2d_bitmap *object;
1870 HRESULT hr;
1872 TRACE("iface %p, surface %p, desc %p, bitmap %p.\n", iface, surface, desc, bitmap);
1874 if (!desc)
1876 DXGI_SURFACE_DESC surface_desc;
1878 if (FAILED(hr = IDXGISurface_GetDesc(surface, &surface_desc)))
1880 WARN("Failed to get surface desc, hr %#x.\n", hr);
1881 return hr;
1884 memset(&bitmap_desc, 0, sizeof(bitmap_desc));
1885 bitmap_desc.pixelFormat.format = surface_desc.Format;
1886 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
1887 bitmap_desc.bitmapOptions = D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW;
1888 desc = &bitmap_desc;
1891 if (SUCCEEDED(hr = d2d_bitmap_create_shared(context, &IID_IDXGISurface, surface, desc, &object)))
1892 *bitmap = &object->ID2D1Bitmap1_iface;
1894 return hr;
1897 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateEffect(ID2D1DeviceContext *iface,
1898 REFCLSID effect_id, ID2D1Effect **effect)
1900 struct d2d_effect *object;
1902 FIXME("iface %p, effect_id %s, effect %p stub!\n", iface, debugstr_guid(effect_id), effect);
1904 if (!(object = heap_alloc_zero(sizeof(*object))))
1905 return E_OUTOFMEMORY;
1907 d2d_effect_init(object);
1909 TRACE("Created effect %p.\n", object);
1910 *effect = &object->ID2D1Effect_iface;
1912 return S_OK;
1915 static HRESULT STDMETHODCALLTYPE d2d_device_context_ID2D1DeviceContext_CreateGradientStopCollection(
1916 ID2D1DeviceContext *iface, const D2D1_GRADIENT_STOP *stops, UINT32 stop_count,
1917 D2D1_COLOR_SPACE preinterpolation_space, D2D1_COLOR_SPACE postinterpolation_space,
1918 D2D1_BUFFER_PRECISION buffer_precision, D2D1_EXTEND_MODE extend_mode,
1919 D2D1_COLOR_INTERPOLATION_MODE color_interpolation_mode, ID2D1GradientStopCollection1 **gradient)
1921 FIXME("iface %p, stops %p, stop_count %u, preinterpolation_space %#x, postinterpolation_space %#x, "
1922 "buffer_precision %#x, extend_mode %#x, color_interpolation_mode %#x, gradient %p stub!\n",
1923 iface, stops, stop_count, preinterpolation_space, postinterpolation_space,
1924 buffer_precision, extend_mode, color_interpolation_mode, gradient);
1926 return E_NOTIMPL;
1929 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateImageBrush(ID2D1DeviceContext *iface,
1930 ID2D1Image *image, const D2D1_IMAGE_BRUSH_PROPERTIES *image_brush_desc,
1931 const D2D1_BRUSH_PROPERTIES *brush_desc, ID2D1ImageBrush **brush)
1933 FIXME("iface %p, image %p, image_brush_desc %p, brush_desc %p, brush %p stub!\n",
1934 iface, image, image_brush_desc, brush_desc, brush);
1936 return E_NOTIMPL;
1939 static HRESULT STDMETHODCALLTYPE d2d_device_context_ID2D1DeviceContext_CreateBitmapBrush(ID2D1DeviceContext *iface,
1940 ID2D1Bitmap *bitmap, const D2D1_BITMAP_BRUSH_PROPERTIES1 *bitmap_brush_desc,
1941 const D2D1_BRUSH_PROPERTIES *brush_desc, ID2D1BitmapBrush1 **brush)
1943 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
1944 struct d2d_brush *object;
1945 HRESULT hr;
1947 TRACE("iface %p, bitmap %p, bitmap_brush_desc %p, brush_desc %p, brush %p.\n", iface, bitmap, bitmap_brush_desc,
1948 brush_desc, brush);
1950 if (SUCCEEDED(hr = d2d_bitmap_brush_create(context->factory, bitmap, bitmap_brush_desc, brush_desc, &object)))
1951 *brush = (ID2D1BitmapBrush1 *)&object->ID2D1Brush_iface;
1953 return hr;
1956 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateCommandList(ID2D1DeviceContext *iface,
1957 ID2D1CommandList **command_list)
1959 FIXME("iface %p, command_list %p stub!\n", iface, command_list);
1961 return E_NOTIMPL;
1964 static BOOL STDMETHODCALLTYPE d2d_device_context_IsDxgiFormatSupported(ID2D1DeviceContext *iface, DXGI_FORMAT format)
1966 FIXME("iface %p, format %#x stub!\n", iface, format);
1968 return FALSE;
1971 static BOOL STDMETHODCALLTYPE d2d_device_context_IsBufferPrecisionSupported(ID2D1DeviceContext *iface,
1972 D2D1_BUFFER_PRECISION buffer_precision)
1974 FIXME("iface %p, buffer_precision %#x stub!\n", iface, buffer_precision);
1976 return FALSE;
1979 static void STDMETHODCALLTYPE d2d_device_context_GetImageLocalBounds(ID2D1DeviceContext *iface,
1980 ID2D1Image *image, D2D1_RECT_F *local_bounds)
1982 FIXME("iface %p, image %p, local_bounds %p stub!\n", iface, image, local_bounds);
1985 static HRESULT STDMETHODCALLTYPE d2d_device_context_GetImageWorldBounds(ID2D1DeviceContext *iface,
1986 ID2D1Image *image, D2D1_RECT_F *world_bounds)
1988 FIXME("iface %p, image %p, world_bounds %p stub!\n", iface, image, world_bounds);
1990 return E_NOTIMPL;
1993 static HRESULT STDMETHODCALLTYPE d2d_device_context_GetGlyphRunWorldBounds(ID2D1DeviceContext *iface,
1994 D2D1_POINT_2F baseline_origin, const DWRITE_GLYPH_RUN *glyph_run,
1995 DWRITE_MEASURING_MODE measuring_mode, D2D1_RECT_F *bounds)
1997 FIXME("iface %p, baseline_origin %s, glyph_run %p, measuring_mode %#x, bounds %p stub!\n",
1998 iface, debug_d2d_point_2f(&baseline_origin), glyph_run, measuring_mode, bounds);
2000 return E_NOTIMPL;
2003 static void STDMETHODCALLTYPE d2d_device_context_GetDevice(ID2D1DeviceContext *iface, ID2D1Device **device)
2005 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
2007 TRACE("iface %p, device %p.\n", iface, device);
2009 *device = context->device;
2010 ID2D1Device_AddRef(*device);
2013 static void d2d_device_context_reset_target(struct d2d_device_context *context)
2015 if (!context->target)
2016 return;
2018 ID2D1Bitmap1_Release(&context->target->ID2D1Bitmap1_iface);
2019 context->target = NULL;
2021 /* Note that DPI settings are kept. */
2022 memset(&context->desc.pixelFormat, 0, sizeof(context->desc.pixelFormat));
2023 memset(&context->pixel_size, 0, sizeof(context->pixel_size));
2025 ID3D10BlendState_Release(context->bs);
2026 context->bs = NULL;
2029 static void STDMETHODCALLTYPE d2d_device_context_SetTarget(ID2D1DeviceContext *iface, ID2D1Image *target)
2031 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
2032 struct d2d_bitmap *bitmap_impl;
2033 D3D10_BLEND_DESC blend_desc;
2034 ID2D1Bitmap *bitmap;
2035 HRESULT hr;
2037 TRACE("iface %p, target %p.\n", iface, target);
2039 if (!target)
2041 d2d_device_context_reset_target(context);
2042 return;
2045 if (FAILED(ID2D1Image_QueryInterface(target, &IID_ID2D1Bitmap, (void **)&bitmap)))
2047 FIXME("Only bitmap targets are supported.\n");
2048 return;
2051 bitmap_impl = unsafe_impl_from_ID2D1Bitmap(bitmap);
2053 if (!(bitmap_impl->options & D2D1_BITMAP_OPTIONS_TARGET))
2055 d2d_device_context_set_error(context, D2DERR_INVALID_TARGET);
2056 return;
2059 d2d_device_context_reset_target(context);
2061 /* Set sizes and pixel format. */
2062 context->pixel_size = bitmap_impl->pixel_size;
2063 context->desc.pixelFormat = bitmap_impl->format;
2064 context->target = bitmap_impl;
2066 memset(&blend_desc, 0, sizeof(blend_desc));
2067 blend_desc.BlendEnable[0] = TRUE;
2068 blend_desc.SrcBlend = D3D10_BLEND_ONE;
2069 blend_desc.DestBlend = D3D10_BLEND_INV_SRC_ALPHA;
2070 blend_desc.BlendOp = D3D10_BLEND_OP_ADD;
2071 if (context->desc.pixelFormat.alphaMode == D2D1_ALPHA_MODE_IGNORE)
2073 blend_desc.SrcBlendAlpha = D3D10_BLEND_ZERO;
2074 blend_desc.DestBlendAlpha = D3D10_BLEND_ONE;
2076 else
2078 blend_desc.SrcBlendAlpha = D3D10_BLEND_ONE;
2079 blend_desc.DestBlendAlpha = D3D10_BLEND_INV_SRC_ALPHA;
2081 blend_desc.BlendOpAlpha = D3D10_BLEND_OP_ADD;
2082 blend_desc.RenderTargetWriteMask[0] = D3D10_COLOR_WRITE_ENABLE_ALL;
2083 if (FAILED(hr = ID3D10Device_CreateBlendState(context->d3d_device, &blend_desc, &context->bs)))
2084 WARN("Failed to create blend state, hr %#x.\n", hr);
2087 static void STDMETHODCALLTYPE d2d_device_context_GetTarget(ID2D1DeviceContext *iface, ID2D1Image **target)
2089 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
2091 TRACE("iface %p, target %p.\n", iface, target);
2093 *target = context->target ? (ID2D1Image *)&context->target->ID2D1Bitmap1_iface : NULL;
2094 if (*target)
2095 ID2D1Image_AddRef(*target);
2098 static void STDMETHODCALLTYPE d2d_device_context_SetRenderingControls(ID2D1DeviceContext *iface,
2099 const D2D1_RENDERING_CONTROLS *rendering_controls)
2101 FIXME("iface %p, rendering_controls %p stub!\n", iface, rendering_controls);
2104 static void STDMETHODCALLTYPE d2d_device_context_GetRenderingControls(ID2D1DeviceContext *iface,
2105 D2D1_RENDERING_CONTROLS *rendering_controls)
2107 FIXME("iface %p, rendering_controls %p stub!\n", iface, rendering_controls);
2110 static void STDMETHODCALLTYPE d2d_device_context_SetPrimitiveBlend(ID2D1DeviceContext *iface,
2111 D2D1_PRIMITIVE_BLEND primitive_blend)
2113 FIXME("iface %p, primitive_blend %#x stub!\n", iface, primitive_blend);
2116 static D2D1_PRIMITIVE_BLEND STDMETHODCALLTYPE d2d_device_context_GetPrimitiveBlend(ID2D1DeviceContext *iface)
2118 FIXME("iface %p stub!\n", iface);
2120 return D2D1_PRIMITIVE_BLEND_SOURCE_OVER;
2123 static void STDMETHODCALLTYPE d2d_device_context_SetUnitMode(ID2D1DeviceContext *iface, D2D1_UNIT_MODE unit_mode)
2125 FIXME("iface %p, unit_mode %#x stub!\n", iface, unit_mode);
2128 static D2D1_UNIT_MODE STDMETHODCALLTYPE d2d_device_context_GetUnitMode(ID2D1DeviceContext *iface)
2130 FIXME("iface %p stub!\n", iface);
2132 return D2D1_UNIT_MODE_DIPS;
2135 static void STDMETHODCALLTYPE d2d_device_context_ID2D1DeviceContext_DrawGlyphRun(ID2D1DeviceContext *iface,
2136 D2D1_POINT_2F baseline_origin, const DWRITE_GLYPH_RUN *glyph_run,
2137 const DWRITE_GLYPH_RUN_DESCRIPTION *glyph_run_desc, ID2D1Brush *brush, DWRITE_MEASURING_MODE measuring_mode)
2139 DWRITE_TEXT_ANTIALIAS_MODE antialias_mode = DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE;
2140 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
2141 IDWriteRenderingParams *rendering_params;
2142 DWRITE_RENDERING_MODE rendering_mode;
2143 HRESULT hr;
2145 TRACE("iface %p, baseline_origin %s, glyph_run %p, glyph_run_desc %p, brush %p, measuring_mode %#x.\n",
2146 iface, debug_d2d_point_2f(&baseline_origin), glyph_run, glyph_run_desc, brush, measuring_mode);
2148 if (FAILED(context->error.code))
2149 return;
2151 rendering_params = context->text_rendering_params ? context->text_rendering_params
2152 : context->default_text_rendering_params;
2154 rendering_mode = IDWriteRenderingParams_GetRenderingMode(rendering_params);
2156 switch (context->drawing_state.textAntialiasMode)
2158 case D2D1_TEXT_ANTIALIAS_MODE_ALIASED:
2159 if (rendering_mode == DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL
2160 || rendering_mode == DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC
2161 || rendering_mode == DWRITE_RENDERING_MODE_CLEARTYPE_GDI_NATURAL
2162 || rendering_mode == DWRITE_RENDERING_MODE_CLEARTYPE_GDI_CLASSIC)
2163 d2d_device_context_set_error(context, E_INVALIDARG);
2164 break;
2166 case D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE:
2167 if (rendering_mode == DWRITE_RENDERING_MODE_ALIASED
2168 || rendering_mode == DWRITE_RENDERING_MODE_OUTLINE)
2169 d2d_device_context_set_error(context, E_INVALIDARG);
2170 break;
2172 case D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE:
2173 if (rendering_mode == DWRITE_RENDERING_MODE_ALIASED)
2174 d2d_device_context_set_error(context, E_INVALIDARG);
2175 break;
2177 default:
2178 break;
2181 if (FAILED(context->error.code))
2182 return;
2184 rendering_mode = DWRITE_RENDERING_MODE_DEFAULT;
2185 switch (context->drawing_state.textAntialiasMode)
2187 case D2D1_TEXT_ANTIALIAS_MODE_DEFAULT:
2188 if (IDWriteRenderingParams_GetClearTypeLevel(rendering_params) > 0.0f)
2189 antialias_mode = DWRITE_TEXT_ANTIALIAS_MODE_CLEARTYPE;
2190 break;
2192 case D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE:
2193 antialias_mode = DWRITE_TEXT_ANTIALIAS_MODE_CLEARTYPE;
2194 break;
2196 case D2D1_TEXT_ANTIALIAS_MODE_ALIASED:
2197 rendering_mode = DWRITE_RENDERING_MODE_ALIASED;
2198 break;
2200 default:
2201 break;
2204 if (rendering_mode == DWRITE_RENDERING_MODE_DEFAULT)
2206 if (FAILED(hr = IDWriteFontFace_GetRecommendedRenderingMode(glyph_run->fontFace, glyph_run->fontEmSize,
2207 max(context->desc.dpiX, context->desc.dpiY) / 96.0f,
2208 measuring_mode, rendering_params, &rendering_mode)))
2210 ERR("Failed to get recommended rendering mode, hr %#x.\n", hr);
2211 rendering_mode = DWRITE_RENDERING_MODE_OUTLINE;
2215 if (rendering_mode == DWRITE_RENDERING_MODE_OUTLINE)
2216 d2d_device_context_draw_glyph_run_outline(context, baseline_origin, glyph_run, brush);
2217 else
2218 d2d_device_context_draw_glyph_run_bitmap(context, baseline_origin, glyph_run, brush,
2219 rendering_mode, measuring_mode, antialias_mode);
2222 static void STDMETHODCALLTYPE d2d_device_context_DrawImage(ID2D1DeviceContext *iface, ID2D1Image *image,
2223 const D2D1_POINT_2F *target_offset, const D2D1_RECT_F *image_rect, D2D1_INTERPOLATION_MODE interpolation_mode,
2224 D2D1_COMPOSITE_MODE composite_mode)
2226 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
2227 ID2D1Bitmap *bitmap;
2229 TRACE("iface %p, image %p, target_offset %s, image_rect %s, interpolation_mode %#x, composite_mode %#x.\n",
2230 iface, image, debug_d2d_point_2f(target_offset), debug_d2d_rect_f(image_rect),
2231 interpolation_mode, composite_mode);
2233 if (composite_mode != D2D1_COMPOSITE_MODE_SOURCE_OVER)
2234 FIXME("Unhandled composite mode %#x.\n", composite_mode);
2236 if (SUCCEEDED(ID2D1Image_QueryInterface(image, &IID_ID2D1Bitmap, (void **)&bitmap)))
2238 d2d_device_context_draw_bitmap(context, bitmap, NULL, 1.0f, d2d1_1_interp_mode_from_d2d1(interpolation_mode),
2239 image_rect, target_offset, NULL);
2241 ID2D1Bitmap_Release(bitmap);
2242 return;
2245 FIXME("Unhandled image %p.\n", image);
2248 static void STDMETHODCALLTYPE d2d_device_context_DrawGdiMetafile(ID2D1DeviceContext *iface,
2249 ID2D1GdiMetafile *metafile, const D2D1_POINT_2F *target_offset)
2251 FIXME("iface %p, metafile %p, target_offset %s stub!\n",
2252 iface, metafile, debug_d2d_point_2f(target_offset));
2255 static void STDMETHODCALLTYPE d2d_device_context_ID2D1DeviceContext_DrawBitmap(ID2D1DeviceContext *iface,
2256 ID2D1Bitmap *bitmap, const D2D1_RECT_F *dst_rect, float opacity, D2D1_INTERPOLATION_MODE interpolation_mode,
2257 const D2D1_RECT_F *src_rect, const D2D1_MATRIX_4X4_F *perspective_transform)
2259 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
2261 TRACE("iface %p, bitmap %p, dst_rect %s, opacity %.8e, interpolation_mode %#x, "
2262 "src_rect %s, perspective_transform %p.\n",
2263 iface, bitmap, debug_d2d_rect_f(dst_rect), opacity, interpolation_mode,
2264 debug_d2d_rect_f(src_rect), perspective_transform);
2266 d2d_device_context_draw_bitmap(context, bitmap, dst_rect, opacity, interpolation_mode, src_rect,
2267 NULL, perspective_transform);
2270 static void STDMETHODCALLTYPE d2d_device_context_ID2D1DeviceContext_PushLayer(ID2D1DeviceContext *iface,
2271 const D2D1_LAYER_PARAMETERS1 *layer_parameters, ID2D1Layer *layer)
2273 FIXME("iface %p, layer_parameters %p, layer %p stub!\n", iface, layer_parameters, layer);
2276 static HRESULT STDMETHODCALLTYPE d2d_device_context_InvalidateEffectInputRectangle(ID2D1DeviceContext *iface,
2277 ID2D1Effect *effect, UINT32 input, const D2D1_RECT_F *input_rect)
2279 FIXME("iface %p, effect %p, input %u, input_rect %s stub!\n",
2280 iface, effect, input, debug_d2d_rect_f(input_rect));
2282 return E_NOTIMPL;
2285 static HRESULT STDMETHODCALLTYPE d2d_device_context_GetEffectInvalidRectangleCount(ID2D1DeviceContext *iface,
2286 ID2D1Effect *effect, UINT32 *rect_count)
2288 FIXME("iface %p, effect %p, rect_count %p stub!\n", iface, effect, rect_count);
2290 return E_NOTIMPL;
2293 static HRESULT STDMETHODCALLTYPE d2d_device_context_GetEffectInvalidRectangles(ID2D1DeviceContext *iface,
2294 ID2D1Effect *effect, D2D1_RECT_F *rectangles, UINT32 rect_count)
2296 FIXME("iface %p, effect %p, rectangles %p, rect_count %u stub!\n", iface, effect, rectangles, rect_count);
2298 return E_NOTIMPL;
2301 static HRESULT STDMETHODCALLTYPE d2d_device_context_GetEffectRequiredInputRectangles(ID2D1DeviceContext *iface,
2302 ID2D1Effect *effect, const D2D1_RECT_F *image_rect, const D2D1_EFFECT_INPUT_DESCRIPTION *desc,
2303 D2D1_RECT_F *input_rect, UINT32 input_count)
2305 FIXME("iface %p, effect %p, image_rect %s, desc %p, input_rect %p, input_count %u stub!\n",
2306 iface, effect, debug_d2d_rect_f(image_rect), desc, input_rect, input_count);
2308 return E_NOTIMPL;
2311 static void STDMETHODCALLTYPE d2d_device_context_ID2D1DeviceContext_FillOpacityMask(ID2D1DeviceContext *iface,
2312 ID2D1Bitmap *mask, ID2D1Brush *brush, const D2D1_RECT_F *dst_rect, const D2D1_RECT_F *src_rect)
2314 FIXME("iface %p, mask %p, brush %p, dst_rect %s, src_rect %s stub!\n",
2315 iface, mask, brush, debug_d2d_rect_f(dst_rect), debug_d2d_rect_f(src_rect));
2318 static const struct ID2D1DeviceContextVtbl d2d_device_context_vtbl =
2320 d2d_device_context_QueryInterface,
2321 d2d_device_context_AddRef,
2322 d2d_device_context_Release,
2323 d2d_device_context_GetFactory,
2324 d2d_device_context_CreateBitmap,
2325 d2d_device_context_CreateBitmapFromWicBitmap,
2326 d2d_device_context_CreateSharedBitmap,
2327 d2d_device_context_CreateBitmapBrush,
2328 d2d_device_context_CreateSolidColorBrush,
2329 d2d_device_context_CreateGradientStopCollection,
2330 d2d_device_context_CreateLinearGradientBrush,
2331 d2d_device_context_CreateRadialGradientBrush,
2332 d2d_device_context_CreateCompatibleRenderTarget,
2333 d2d_device_context_CreateLayer,
2334 d2d_device_context_CreateMesh,
2335 d2d_device_context_DrawLine,
2336 d2d_device_context_DrawRectangle,
2337 d2d_device_context_FillRectangle,
2338 d2d_device_context_DrawRoundedRectangle,
2339 d2d_device_context_FillRoundedRectangle,
2340 d2d_device_context_DrawEllipse,
2341 d2d_device_context_FillEllipse,
2342 d2d_device_context_DrawGeometry,
2343 d2d_device_context_FillGeometry,
2344 d2d_device_context_FillMesh,
2345 d2d_device_context_FillOpacityMask,
2346 d2d_device_context_DrawBitmap,
2347 d2d_device_context_DrawText,
2348 d2d_device_context_DrawTextLayout,
2349 d2d_device_context_DrawGlyphRun,
2350 d2d_device_context_SetTransform,
2351 d2d_device_context_GetTransform,
2352 d2d_device_context_SetAntialiasMode,
2353 d2d_device_context_GetAntialiasMode,
2354 d2d_device_context_SetTextAntialiasMode,
2355 d2d_device_context_GetTextAntialiasMode,
2356 d2d_device_context_SetTextRenderingParams,
2357 d2d_device_context_GetTextRenderingParams,
2358 d2d_device_context_SetTags,
2359 d2d_device_context_GetTags,
2360 d2d_device_context_PushLayer,
2361 d2d_device_context_PopLayer,
2362 d2d_device_context_Flush,
2363 d2d_device_context_SaveDrawingState,
2364 d2d_device_context_RestoreDrawingState,
2365 d2d_device_context_PushAxisAlignedClip,
2366 d2d_device_context_PopAxisAlignedClip,
2367 d2d_device_context_Clear,
2368 d2d_device_context_BeginDraw,
2369 d2d_device_context_EndDraw,
2370 d2d_device_context_GetPixelFormat,
2371 d2d_device_context_SetDpi,
2372 d2d_device_context_GetDpi,
2373 d2d_device_context_GetSize,
2374 d2d_device_context_GetPixelSize,
2375 d2d_device_context_GetMaximumBitmapSize,
2376 d2d_device_context_IsSupported,
2377 d2d_device_context_ID2D1DeviceContext_CreateBitmap,
2378 d2d_device_context_ID2D1DeviceContext_CreateBitmapFromWicBitmap,
2379 d2d_device_context_CreateColorContext,
2380 d2d_device_context_CreateColorContextFromFilename,
2381 d2d_device_context_CreateColorContextFromWicColorContext,
2382 d2d_device_context_CreateBitmapFromDxgiSurface,
2383 d2d_device_context_CreateEffect,
2384 d2d_device_context_ID2D1DeviceContext_CreateGradientStopCollection,
2385 d2d_device_context_CreateImageBrush,
2386 d2d_device_context_ID2D1DeviceContext_CreateBitmapBrush,
2387 d2d_device_context_CreateCommandList,
2388 d2d_device_context_IsDxgiFormatSupported,
2389 d2d_device_context_IsBufferPrecisionSupported,
2390 d2d_device_context_GetImageLocalBounds,
2391 d2d_device_context_GetImageWorldBounds,
2392 d2d_device_context_GetGlyphRunWorldBounds,
2393 d2d_device_context_GetDevice,
2394 d2d_device_context_SetTarget,
2395 d2d_device_context_GetTarget,
2396 d2d_device_context_SetRenderingControls,
2397 d2d_device_context_GetRenderingControls,
2398 d2d_device_context_SetPrimitiveBlend,
2399 d2d_device_context_GetPrimitiveBlend,
2400 d2d_device_context_SetUnitMode,
2401 d2d_device_context_GetUnitMode,
2402 d2d_device_context_ID2D1DeviceContext_DrawGlyphRun,
2403 d2d_device_context_DrawImage,
2404 d2d_device_context_DrawGdiMetafile,
2405 d2d_device_context_ID2D1DeviceContext_DrawBitmap,
2406 d2d_device_context_ID2D1DeviceContext_PushLayer,
2407 d2d_device_context_InvalidateEffectInputRectangle,
2408 d2d_device_context_GetEffectInvalidRectangleCount,
2409 d2d_device_context_GetEffectInvalidRectangles,
2410 d2d_device_context_GetEffectRequiredInputRectangles,
2411 d2d_device_context_ID2D1DeviceContext_FillOpacityMask,
2414 static inline struct d2d_device_context *impl_from_IDWriteTextRenderer(IDWriteTextRenderer *iface)
2416 return CONTAINING_RECORD(iface, struct d2d_device_context, IDWriteTextRenderer_iface);
2419 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_QueryInterface(IDWriteTextRenderer *iface, REFIID iid, void **out)
2421 TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
2423 if (IsEqualGUID(iid, &IID_IDWriteTextRenderer)
2424 || IsEqualGUID(iid, &IID_IDWritePixelSnapping)
2425 || IsEqualGUID(iid, &IID_IUnknown))
2427 IDWriteTextRenderer_AddRef(iface);
2428 *out = iface;
2429 return S_OK;
2432 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
2434 *out = NULL;
2435 return E_NOINTERFACE;
2438 static ULONG STDMETHODCALLTYPE d2d_text_renderer_AddRef(IDWriteTextRenderer *iface)
2440 struct d2d_device_context *render_target = impl_from_IDWriteTextRenderer(iface);
2442 TRACE("iface %p.\n", iface);
2444 return d2d_device_context_AddRef(&render_target->ID2D1DeviceContext_iface);
2447 static ULONG STDMETHODCALLTYPE d2d_text_renderer_Release(IDWriteTextRenderer *iface)
2449 struct d2d_device_context *render_target = impl_from_IDWriteTextRenderer(iface);
2451 TRACE("iface %p.\n", iface);
2453 return d2d_device_context_Release(&render_target->ID2D1DeviceContext_iface);
2456 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_IsPixelSnappingDisabled(IDWriteTextRenderer *iface,
2457 void *ctx, BOOL *disabled)
2459 struct d2d_draw_text_layout_ctx *context = ctx;
2461 TRACE("iface %p, ctx %p, disabled %p.\n", iface, ctx, disabled);
2463 *disabled = context->options & D2D1_DRAW_TEXT_OPTIONS_NO_SNAP;
2465 return S_OK;
2468 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_GetCurrentTransform(IDWriteTextRenderer *iface,
2469 void *ctx, DWRITE_MATRIX *transform)
2471 struct d2d_device_context *render_target = impl_from_IDWriteTextRenderer(iface);
2473 TRACE("iface %p, ctx %p, transform %p.\n", iface, ctx, transform);
2475 d2d_device_context_GetTransform(&render_target->ID2D1DeviceContext_iface, (D2D1_MATRIX_3X2_F *)transform);
2477 return S_OK;
2480 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_GetPixelsPerDip(IDWriteTextRenderer *iface, void *ctx, float *ppd)
2482 struct d2d_device_context *render_target = impl_from_IDWriteTextRenderer(iface);
2484 TRACE("iface %p, ctx %p, ppd %p.\n", iface, ctx, ppd);
2486 *ppd = render_target->desc.dpiY / 96.0f;
2488 return S_OK;
2491 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_DrawGlyphRun(IDWriteTextRenderer *iface, void *ctx,
2492 float baseline_origin_x, float baseline_origin_y, DWRITE_MEASURING_MODE measuring_mode,
2493 const DWRITE_GLYPH_RUN *glyph_run, const DWRITE_GLYPH_RUN_DESCRIPTION *desc, IUnknown *effect)
2495 struct d2d_device_context *render_target = impl_from_IDWriteTextRenderer(iface);
2496 D2D1_POINT_2F baseline_origin = {baseline_origin_x, baseline_origin_y};
2497 struct d2d_draw_text_layout_ctx *context = ctx;
2498 BOOL color_font = FALSE;
2499 ID2D1Brush *brush;
2501 TRACE("iface %p, ctx %p, baseline_origin_x %.8e, baseline_origin_y %.8e, "
2502 "measuring_mode %#x, glyph_run %p, desc %p, effect %p.\n",
2503 iface, ctx, baseline_origin_x, baseline_origin_y,
2504 measuring_mode, glyph_run, desc, effect);
2506 if (desc)
2507 WARN("Ignoring glyph run description %p.\n", desc);
2508 if (context->options & ~(D2D1_DRAW_TEXT_OPTIONS_NO_SNAP | D2D1_DRAW_TEXT_OPTIONS_ENABLE_COLOR_FONT))
2509 FIXME("Ignoring options %#x.\n", context->options);
2511 brush = d2d_draw_get_text_brush(context, effect);
2513 TRACE("%s\n", debugstr_wn(desc->string, desc->stringLength));
2515 if (context->options & D2D1_DRAW_TEXT_OPTIONS_ENABLE_COLOR_FONT)
2517 IDWriteFontFace2 *fontface;
2519 if (SUCCEEDED(IDWriteFontFace_QueryInterface(glyph_run->fontFace,
2520 &IID_IDWriteFontFace2, (void **)&fontface)))
2522 color_font = IDWriteFontFace2_IsColorFont(fontface);
2523 IDWriteFontFace2_Release(fontface);
2527 if (color_font)
2529 IDWriteColorGlyphRunEnumerator *layers;
2530 IDWriteFactory2 *dwrite_factory;
2531 HRESULT hr;
2533 if (FAILED(hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, &IID_IDWriteFactory2,
2534 (IUnknown **)&dwrite_factory)))
2536 ERR("Failed to create dwrite factory, hr %#x.\n", hr);
2537 ID2D1Brush_Release(brush);
2538 return hr;
2541 hr = IDWriteFactory2_TranslateColorGlyphRun(dwrite_factory, baseline_origin_x, baseline_origin_y,
2542 glyph_run, desc, measuring_mode, (DWRITE_MATRIX *)&render_target->drawing_state.transform, 0, &layers);
2543 IDWriteFactory2_Release(dwrite_factory);
2544 if (FAILED(hr))
2546 ERR("Failed to create color glyph run enumerator, hr %#x.\n", hr);
2547 ID2D1Brush_Release(brush);
2548 return hr;
2551 for (;;)
2553 const DWRITE_COLOR_GLYPH_RUN *color_run;
2554 ID2D1Brush *color_brush;
2555 D2D1_POINT_2F origin;
2556 BOOL has_run = FALSE;
2558 if (FAILED(hr = IDWriteColorGlyphRunEnumerator_MoveNext(layers, &has_run)))
2560 ERR("Failed to switch color glyph layer, hr %#x.\n", hr);
2561 break;
2564 if (!has_run)
2565 break;
2567 if (FAILED(hr = IDWriteColorGlyphRunEnumerator_GetCurrentRun(layers, &color_run)))
2569 ERR("Failed to get current color run, hr %#x.\n", hr);
2570 break;
2573 if (color_run->paletteIndex == 0xffff)
2574 color_brush = brush;
2575 else
2577 if (FAILED(hr = d2d_device_context_CreateSolidColorBrush(&render_target->ID2D1DeviceContext_iface,
2578 &color_run->runColor, NULL, (ID2D1SolidColorBrush **)&color_brush)))
2580 ERR("Failed to create solid color brush, hr %#x.\n", hr);
2581 break;
2585 origin.x = color_run->baselineOriginX;
2586 origin.y = color_run->baselineOriginY;
2587 d2d_device_context_DrawGlyphRun(&render_target->ID2D1DeviceContext_iface,
2588 origin, &color_run->glyphRun, color_brush, measuring_mode);
2590 if (color_brush != brush)
2591 ID2D1Brush_Release(color_brush);
2594 IDWriteColorGlyphRunEnumerator_Release(layers);
2596 else
2597 d2d_device_context_DrawGlyphRun(&render_target->ID2D1DeviceContext_iface,
2598 baseline_origin, glyph_run, brush, measuring_mode);
2600 ID2D1Brush_Release(brush);
2602 return S_OK;
2605 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_DrawUnderline(IDWriteTextRenderer *iface, void *ctx,
2606 float baseline_origin_x, float baseline_origin_y, const DWRITE_UNDERLINE *underline, IUnknown *effect)
2608 struct d2d_device_context *render_target = impl_from_IDWriteTextRenderer(iface);
2609 const D2D1_MATRIX_3X2_F *m = &render_target->drawing_state.transform;
2610 struct d2d_draw_text_layout_ctx *context = ctx;
2611 D2D1_ANTIALIAS_MODE prev_antialias_mode;
2612 D2D1_POINT_2F start, end;
2613 ID2D1Brush *brush;
2614 float thickness;
2616 TRACE("iface %p, ctx %p, baseline_origin_x %.8e, baseline_origin_y %.8e, underline %p, effect %p\n",
2617 iface, ctx, baseline_origin_x, baseline_origin_y, underline, effect);
2619 /* minimal thickness in DIPs that will result in at least 1 pixel thick line */
2620 thickness = max(96.0f / (render_target->desc.dpiY * sqrtf(m->_21 * m->_21 + m->_22 * m->_22)),
2621 underline->thickness);
2623 brush = d2d_draw_get_text_brush(context, effect);
2625 start.x = baseline_origin_x;
2626 start.y = baseline_origin_y + underline->offset + thickness / 2.0f;
2627 end.x = start.x + underline->width;
2628 end.y = start.y;
2629 prev_antialias_mode = d2d_device_context_set_aa_mode_from_text_aa_mode(render_target);
2630 d2d_device_context_DrawLine(&render_target->ID2D1DeviceContext_iface, start, end, brush, thickness, NULL);
2631 render_target->drawing_state.antialiasMode = prev_antialias_mode;
2633 ID2D1Brush_Release(brush);
2635 return S_OK;
2638 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_DrawStrikethrough(IDWriteTextRenderer *iface, void *ctx,
2639 float baseline_origin_x, float baseline_origin_y, const DWRITE_STRIKETHROUGH *strikethrough, IUnknown *effect)
2641 struct d2d_device_context *render_target = impl_from_IDWriteTextRenderer(iface);
2642 const D2D1_MATRIX_3X2_F *m = &render_target->drawing_state.transform;
2643 struct d2d_draw_text_layout_ctx *context = ctx;
2644 D2D1_ANTIALIAS_MODE prev_antialias_mode;
2645 D2D1_POINT_2F start, end;
2646 ID2D1Brush *brush;
2647 float thickness;
2649 TRACE("iface %p, ctx %p, baseline_origin_x %.8e, baseline_origin_y %.8e, strikethrough %p, effect %p.\n",
2650 iface, ctx, baseline_origin_x, baseline_origin_y, strikethrough, effect);
2652 /* minimal thickness in DIPs that will result in at least 1 pixel thick line */
2653 thickness = max(96.0f / (render_target->desc.dpiY * sqrtf(m->_21 * m->_21 + m->_22 * m->_22)),
2654 strikethrough->thickness);
2656 brush = d2d_draw_get_text_brush(context, effect);
2658 start.x = baseline_origin_x;
2659 start.y = baseline_origin_y + strikethrough->offset + thickness / 2.0f;
2660 end.x = start.x + strikethrough->width;
2661 end.y = start.y;
2662 prev_antialias_mode = d2d_device_context_set_aa_mode_from_text_aa_mode(render_target);
2663 d2d_device_context_DrawLine(&render_target->ID2D1DeviceContext_iface, start, end, brush, thickness, NULL);
2664 render_target->drawing_state.antialiasMode = prev_antialias_mode;
2666 ID2D1Brush_Release(brush);
2668 return S_OK;
2671 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_DrawInlineObject(IDWriteTextRenderer *iface, void *ctx,
2672 float origin_x, float origin_y, IDWriteInlineObject *object, BOOL is_sideways, BOOL is_rtl, IUnknown *effect)
2674 struct d2d_draw_text_layout_ctx *context = ctx;
2675 ID2D1Brush *brush;
2676 HRESULT hr;
2678 TRACE("iface %p, ctx %p, origin_x %.8e, origin_y %.8e, object %p, is_sideways %#x, is_rtl %#x, effect %p.\n",
2679 iface, ctx, origin_x, origin_y, object, is_sideways, is_rtl, effect);
2681 /* Inline objects may not pass effects all the way down, when using layout object internally for example.
2682 This is how default trimming sign object in DirectWrite works - it does not use effect passed to Draw(),
2683 and resulting DrawGlyphRun() is always called with NULL effect, however original effect is used and correct
2684 brush is selected at Direct2D level. */
2685 brush = context->brush;
2686 context->brush = d2d_draw_get_text_brush(context, effect);
2688 hr = IDWriteInlineObject_Draw(object, ctx, iface, origin_x, origin_y, is_sideways, is_rtl, effect);
2690 ID2D1Brush_Release(context->brush);
2691 context->brush = brush;
2693 return hr;
2696 static const struct IDWriteTextRendererVtbl d2d_text_renderer_vtbl =
2698 d2d_text_renderer_QueryInterface,
2699 d2d_text_renderer_AddRef,
2700 d2d_text_renderer_Release,
2701 d2d_text_renderer_IsPixelSnappingDisabled,
2702 d2d_text_renderer_GetCurrentTransform,
2703 d2d_text_renderer_GetPixelsPerDip,
2704 d2d_text_renderer_DrawGlyphRun,
2705 d2d_text_renderer_DrawUnderline,
2706 d2d_text_renderer_DrawStrikethrough,
2707 d2d_text_renderer_DrawInlineObject,
2710 static inline struct d2d_device_context *impl_from_ID2D1GdiInteropRenderTarget(ID2D1GdiInteropRenderTarget *iface)
2712 return CONTAINING_RECORD(iface, struct d2d_device_context, ID2D1GdiInteropRenderTarget_iface);
2715 static HRESULT STDMETHODCALLTYPE d2d_gdi_interop_render_target_QueryInterface(ID2D1GdiInteropRenderTarget *iface,
2716 REFIID iid, void **out)
2718 struct d2d_device_context *render_target = impl_from_ID2D1GdiInteropRenderTarget(iface);
2720 TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
2722 return IUnknown_QueryInterface(render_target->outer_unknown, iid, out);
2725 static ULONG STDMETHODCALLTYPE d2d_gdi_interop_render_target_AddRef(ID2D1GdiInteropRenderTarget *iface)
2727 struct d2d_device_context *render_target = impl_from_ID2D1GdiInteropRenderTarget(iface);
2729 TRACE("iface %p.\n", iface);
2731 return IUnknown_AddRef(render_target->outer_unknown);
2734 static ULONG STDMETHODCALLTYPE d2d_gdi_interop_render_target_Release(ID2D1GdiInteropRenderTarget *iface)
2736 struct d2d_device_context *render_target = impl_from_ID2D1GdiInteropRenderTarget(iface);
2738 TRACE("iface %p.\n", iface);
2740 return IUnknown_Release(render_target->outer_unknown);
2743 static HRESULT d2d_device_context_get_surface(struct d2d_device_context *render_target, IDXGISurface1 **surface)
2745 ID3D10Resource *resource;
2746 HRESULT hr;
2748 ID3D10RenderTargetView_GetResource(render_target->target->rtv, &resource);
2749 hr = ID3D10Resource_QueryInterface(resource, &IID_IDXGISurface1, (void **)surface);
2750 ID3D10Resource_Release(resource);
2751 if (FAILED(hr))
2753 *surface = NULL;
2754 WARN("Failed to get DXGI surface, %#x.\n", hr);
2755 return hr;
2758 return hr;
2761 static HRESULT STDMETHODCALLTYPE d2d_gdi_interop_render_target_GetDC(ID2D1GdiInteropRenderTarget *iface,
2762 D2D1_DC_INITIALIZE_MODE mode, HDC *dc)
2764 struct d2d_device_context *render_target = impl_from_ID2D1GdiInteropRenderTarget(iface);
2765 IDXGISurface1 *surface;
2766 HRESULT hr;
2768 TRACE("iface %p, mode %d, dc %p.\n", iface, mode, dc);
2770 if (FAILED(hr = d2d_device_context_get_surface(render_target, &surface)))
2771 return hr;
2773 hr = IDXGISurface1_GetDC(surface, mode != D2D1_DC_INITIALIZE_MODE_COPY, dc);
2774 IDXGISurface1_Release(surface);
2776 return hr;
2779 static HRESULT STDMETHODCALLTYPE d2d_gdi_interop_render_target_ReleaseDC(ID2D1GdiInteropRenderTarget *iface,
2780 const RECT *update)
2782 struct d2d_device_context *render_target = impl_from_ID2D1GdiInteropRenderTarget(iface);
2783 IDXGISurface1 *surface;
2784 RECT update_rect;
2785 HRESULT hr;
2787 TRACE("iface %p, update rect %s.\n", iface, wine_dbgstr_rect(update));
2789 if (FAILED(hr = d2d_device_context_get_surface(render_target, &surface)))
2790 return hr;
2792 if (update)
2793 update_rect = *update;
2794 hr = IDXGISurface1_ReleaseDC(surface, update ? &update_rect : NULL);
2795 IDXGISurface1_Release(surface);
2797 return hr;
2800 static const struct ID2D1GdiInteropRenderTargetVtbl d2d_gdi_interop_render_target_vtbl =
2802 d2d_gdi_interop_render_target_QueryInterface,
2803 d2d_gdi_interop_render_target_AddRef,
2804 d2d_gdi_interop_render_target_Release,
2805 d2d_gdi_interop_render_target_GetDC,
2806 d2d_gdi_interop_render_target_ReleaseDC,
2809 static HRESULT d2d_device_context_init(struct d2d_device_context *render_target, ID2D1Device *device,
2810 IUnknown *outer_unknown, const struct d2d_device_context_ops *ops)
2812 D3D10_SUBRESOURCE_DATA buffer_data;
2813 D3D10_STATE_BLOCK_MASK state_mask;
2814 struct d2d_device *device_impl;
2815 IDWriteFactory *dwrite_factory;
2816 D3D10_RASTERIZER_DESC rs_desc;
2817 D3D10_BUFFER_DESC buffer_desc;
2818 unsigned int i;
2819 HRESULT hr;
2821 static const D3D10_INPUT_ELEMENT_DESC il_desc_outline[] =
2823 {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0},
2824 {"PREV", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 8, D3D10_INPUT_PER_VERTEX_DATA, 0},
2825 {"NEXT", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 16, D3D10_INPUT_PER_VERTEX_DATA, 0},
2827 static const D3D10_INPUT_ELEMENT_DESC il_desc_curve_outline[] =
2829 {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0},
2830 {"P", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 8, D3D10_INPUT_PER_VERTEX_DATA, 0},
2831 {"P", 1, DXGI_FORMAT_R32G32_FLOAT, 0, 16, D3D10_INPUT_PER_VERTEX_DATA, 0},
2832 {"P", 2, DXGI_FORMAT_R32G32_FLOAT, 0, 24, D3D10_INPUT_PER_VERTEX_DATA, 0},
2833 {"PREV", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 32, D3D10_INPUT_PER_VERTEX_DATA, 0},
2834 {"NEXT", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 40, D3D10_INPUT_PER_VERTEX_DATA, 0},
2836 static const D3D10_INPUT_ELEMENT_DESC il_desc_triangle[] =
2838 {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0},
2840 static const D3D10_INPUT_ELEMENT_DESC il_desc_curve[] =
2842 {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0},
2843 {"TEXCOORD", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 8, D3D10_INPUT_PER_VERTEX_DATA, 0},
2845 static const DWORD vs_code_outline[] =
2847 #if 0
2848 float3x2 transform_geometry;
2849 float stroke_width;
2850 float4 transform_rtx;
2851 float4 transform_rty;
2853 struct output
2855 float2 p : WORLD_POSITION;
2856 float4 b : BEZIER;
2857 nointerpolation float2x2 stroke_transform : STROKE_TRANSFORM;
2858 float4 position : SV_POSITION;
2861 /* The lines PₚᵣₑᵥP₀ and P₀Pₙₑₓₜ, both offset by ±½w, intersect each other at:
2863 * Pᵢ = P₀ ± w · ½q⃑ᵢ.
2865 * Where:
2867 * q⃑ᵢ = q̂ₚᵣₑᵥ⊥ + tan(½θ) · -q̂ₚᵣₑᵥ
2868 * θ = ∠PₚᵣₑᵥP₀Pₙₑₓₜ
2869 * q⃑ₚᵣₑᵥ = P₀ - Pₚᵣₑᵥ */
2870 void main(float2 position : POSITION, float2 prev : PREV, float2 next : NEXT, out struct output o)
2872 float2 q_prev, q_next, v_p, q_i;
2873 float2x2 geom;
2874 float l;
2876 o.stroke_transform = float2x2(transform_rtx.xy, transform_rty.xy) * stroke_width * 0.5f;
2878 geom = float2x2(transform_geometry._11_21, transform_geometry._12_22);
2879 q_prev = normalize(mul(geom, prev));
2880 q_next = normalize(mul(geom, next));
2882 /* tan(½θ) = sin(θ) / (1 + cos(θ))
2883 * = (q̂ₚᵣₑᵥ⊥ · q̂ₙₑₓₜ) / (1 + (q̂ₚᵣₑᵥ · q̂ₙₑₓₜ)) */
2884 v_p = float2(-q_prev.y, q_prev.x);
2885 l = -dot(v_p, q_next) / (1.0f + dot(q_prev, q_next));
2886 q_i = l * q_prev + v_p;
2888 o.b = float4(0.0, 0.0, 0.0, 0.0);
2890 o.p = mul(float3(position, 1.0f), transform_geometry) + stroke_width * 0.5f * q_i;
2891 position = mul(float2x3(transform_rtx.xyz, transform_rty.xyz), float3(o.p, 1.0f))
2892 * float2(transform_rtx.w, transform_rty.w);
2893 o.position = float4(position + float2(-1.0f, 1.0f), 0.0f, 1.0f);
2895 #endif
2896 0x43425844, 0xfb16cd75, 0xf5ec3e80, 0xceacf250, 0x91d29d18, 0x00000001, 0x00000608, 0x00000003,
2897 0x0000002c, 0x00000098, 0x00000154, 0x4e475349, 0x00000064, 0x00000003, 0x00000008, 0x00000050,
2898 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000303, 0x00000059, 0x00000000, 0x00000000,
2899 0x00000003, 0x00000001, 0x00000303, 0x0000005e, 0x00000000, 0x00000000, 0x00000003, 0x00000002,
2900 0x00000303, 0x49534f50, 0x4e4f4954, 0x45525000, 0x454e0056, 0xab005458, 0x4e47534f, 0x000000b4,
2901 0x00000005, 0x00000008, 0x00000080, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000c03,
2902 0x0000008f, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x0000000f, 0x00000096, 0x00000000,
2903 0x00000000, 0x00000003, 0x00000002, 0x00000c03, 0x00000096, 0x00000001, 0x00000000, 0x00000003,
2904 0x00000003, 0x00000c03, 0x000000a7, 0x00000000, 0x00000001, 0x00000003, 0x00000004, 0x0000000f,
2905 0x4c524f57, 0x4f505f44, 0x49544953, 0x42004e4f, 0x45495a45, 0x54530052, 0x454b4f52, 0x4152545f,
2906 0x4f46534e, 0x53004d52, 0x4f505f56, 0x49544953, 0xab004e4f, 0x52444853, 0x000004ac, 0x00010040,
2907 0x0000012b, 0x04000059, 0x00208e46, 0x00000000, 0x00000004, 0x0300005f, 0x00101032, 0x00000000,
2908 0x0300005f, 0x00101032, 0x00000001, 0x0300005f, 0x00101032, 0x00000002, 0x03000065, 0x00102032,
2909 0x00000000, 0x03000065, 0x001020f2, 0x00000001, 0x03000065, 0x00102032, 0x00000002, 0x03000065,
2910 0x00102032, 0x00000003, 0x04000067, 0x001020f2, 0x00000004, 0x00000001, 0x02000068, 0x00000003,
2911 0x0800000f, 0x00100012, 0x00000000, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000002,
2912 0x0800000f, 0x00100022, 0x00000000, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000002,
2913 0x0700000f, 0x00100042, 0x00000000, 0x00100046, 0x00000000, 0x00100046, 0x00000000, 0x05000044,
2914 0x00100042, 0x00000000, 0x0010002a, 0x00000000, 0x07000038, 0x00100032, 0x00000000, 0x00100aa6,
2915 0x00000000, 0x00100046, 0x00000000, 0x0800000f, 0x00100012, 0x00000001, 0x00208046, 0x00000000,
2916 0x00000000, 0x00101046, 0x00000001, 0x0800000f, 0x00100022, 0x00000001, 0x00208046, 0x00000000,
2917 0x00000001, 0x00101046, 0x00000001, 0x0700000f, 0x00100042, 0x00000000, 0x00100046, 0x00000001,
2918 0x00100046, 0x00000001, 0x05000044, 0x00100042, 0x00000000, 0x0010002a, 0x00000000, 0x07000038,
2919 0x00100032, 0x00000001, 0x00100aa6, 0x00000000, 0x00100046, 0x00000001, 0x06000036, 0x001000c2,
2920 0x00000001, 0x80100556, 0x00000041, 0x00000001, 0x0700000f, 0x00100042, 0x00000000, 0x00100a26,
2921 0x00000001, 0x00100046, 0x00000000, 0x0700000f, 0x00100012, 0x00000000, 0x00100046, 0x00000001,
2922 0x00100046, 0x00000000, 0x07000000, 0x00100012, 0x00000000, 0x0010000a, 0x00000000, 0x00004001,
2923 0x3f800000, 0x0800000e, 0x00100012, 0x00000000, 0x8010002a, 0x00000041, 0x00000000, 0x0010000a,
2924 0x00000000, 0x09000032, 0x00100032, 0x00000000, 0x00100006, 0x00000000, 0x00100046, 0x00000001,
2925 0x00100f36, 0x00000001, 0x08000038, 0x00100042, 0x00000000, 0x0020803a, 0x00000000, 0x00000001,
2926 0x00004001, 0x3f000000, 0x05000036, 0x00100032, 0x00000001, 0x00101046, 0x00000000, 0x05000036,
2927 0x00100042, 0x00000001, 0x00004001, 0x3f800000, 0x08000010, 0x00100012, 0x00000002, 0x00100246,
2928 0x00000001, 0x00208246, 0x00000000, 0x00000000, 0x08000010, 0x00100022, 0x00000002, 0x00100246,
2929 0x00000001, 0x00208246, 0x00000000, 0x00000001, 0x09000032, 0x00100032, 0x00000000, 0x00100aa6,
2930 0x00000000, 0x00100046, 0x00000000, 0x00100046, 0x00000002, 0x05000036, 0x00102032, 0x00000000,
2931 0x00100046, 0x00000000, 0x08000036, 0x001020f2, 0x00000001, 0x00004002, 0x00000000, 0x00000000,
2932 0x00000000, 0x00000000, 0x06000036, 0x00100032, 0x00000001, 0x00208046, 0x00000000, 0x00000002,
2933 0x06000036, 0x001000c2, 0x00000001, 0x00208406, 0x00000000, 0x00000003, 0x08000038, 0x001000f2,
2934 0x00000001, 0x00100e46, 0x00000001, 0x00208ff6, 0x00000000, 0x00000001, 0x0a000038, 0x001000f2,
2935 0x00000001, 0x00100e46, 0x00000001, 0x00004002, 0x3f000000, 0x3f000000, 0x3f000000, 0x3f000000,
2936 0x05000036, 0x00102032, 0x00000002, 0x00100086, 0x00000001, 0x05000036, 0x00102032, 0x00000003,
2937 0x001005d6, 0x00000001, 0x05000036, 0x00100042, 0x00000000, 0x00004001, 0x3f800000, 0x08000010,
2938 0x00100082, 0x00000000, 0x00208246, 0x00000000, 0x00000002, 0x00100246, 0x00000000, 0x08000010,
2939 0x00100012, 0x00000000, 0x00208246, 0x00000000, 0x00000003, 0x00100246, 0x00000000, 0x08000038,
2940 0x00100022, 0x00000000, 0x0010000a, 0x00000000, 0x0020803a, 0x00000000, 0x00000003, 0x08000038,
2941 0x00100012, 0x00000000, 0x0010003a, 0x00000000, 0x0020803a, 0x00000000, 0x00000002, 0x0a000000,
2942 0x00102032, 0x00000004, 0x00100046, 0x00000000, 0x00004002, 0xbf800000, 0x3f800000, 0x00000000,
2943 0x00000000, 0x08000036, 0x001020c2, 0x00000004, 0x00004002, 0x00000000, 0x00000000, 0x00000000,
2944 0x3f800000, 0x0100003e,
2946 /* ⎡p0.x p0.y 1⎤
2947 * A = ⎢p1.x p1.y 1⎥
2948 * ⎣p2.x p2.y 1⎦
2950 * ⎡0 0⎤
2951 * B = ⎢½ 0⎥
2952 * ⎣1 1⎦
2954 * A' = ⎡p1.x-p0.x p1.y-p0.y⎤
2955 * ⎣p2.x-p0.x p2.y-p0.y⎦
2957 * B' = ⎡½ 0⎤
2958 * ⎣1 1⎦
2960 * A'T = B'
2961 * T = A'⁻¹B'
2963 static const DWORD vs_code_bezier_outline[] =
2965 #if 0
2966 float3x2 transform_geometry;
2967 float stroke_width;
2968 float4 transform_rtx;
2969 float4 transform_rty;
2971 struct output
2973 float2 p : WORLD_POSITION;
2974 float4 b : BEZIER;
2975 nointerpolation float2x2 stroke_transform : STROKE_TRANSFORM;
2976 float4 position : SV_POSITION;
2979 void main(float2 position : POSITION, float2 p0 : P0, float2 p1 : P1, float2 p2 : P2,
2980 float2 prev : PREV, float2 next : NEXT, out struct output o)
2982 float2 q_prev, q_next, v_p, q_i, p;
2983 float2x2 geom, rt;
2984 float l;
2986 geom = float2x2(transform_geometry._11_21, transform_geometry._12_22);
2987 rt = float2x2(transform_rtx.xy, transform_rty.xy);
2988 o.stroke_transform = rt * stroke_width * 0.5f;
2990 p = mul(geom, position);
2991 p0 = mul(geom, p0);
2992 p1 = mul(geom, p1);
2993 p2 = mul(geom, p2);
2995 p -= p0;
2996 p1 -= p0;
2997 p2 -= p0;
2999 q_prev = normalize(mul(geom, prev));
3000 q_next = normalize(mul(geom, next));
3002 v_p = float2(-q_prev.y, q_prev.x);
3003 l = -dot(v_p, q_next) / (1.0f + dot(q_prev, q_next));
3004 q_i = l * q_prev + v_p;
3005 p += 0.5f * stroke_width * q_i;
3007 v_p = mul(rt, p2);
3008 v_p = normalize(float2(-v_p.y, v_p.x));
3009 if (abs(dot(mul(rt, p1), v_p)) < 1.0f)
3011 o.b.xzw = float3(0.0f, 0.0f, 0.0f);
3012 o.b.y = dot(mul(rt, p), v_p);
3014 else
3016 o.b.zw = sign(dot(mul(rt, p1), v_p)) * v_p;
3017 v_p = -float2(-p.y, p.x) / dot(float2(-p1.y, p1.x), p2);
3018 o.b.x = dot(v_p, p1 - 0.5f * p2);
3019 o.b.y = dot(v_p, p1);
3022 o.p = mul(float3(position, 1.0f), transform_geometry) + 0.5f * stroke_width * q_i;
3023 position = mul(float2x3(transform_rtx.xyz, transform_rty.xyz), float3(o.p, 1.0f))
3024 * float2(transform_rtx.w, transform_rty.w);
3025 o.position = float4(position + float2(-1.0f, 1.0f), 0.0f, 1.0f);
3027 #endif
3028 0x43425844, 0x356a0c5f, 0x8e4ba153, 0xe52cf793, 0xa6b774ea, 0x00000001, 0x00000afc, 0x00000003,
3029 0x0000002c, 0x000000e4, 0x000001a0, 0x4e475349, 0x000000b0, 0x00000006, 0x00000008, 0x00000098,
3030 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000303, 0x000000a1, 0x00000000, 0x00000000,
3031 0x00000003, 0x00000001, 0x00000303, 0x000000a1, 0x00000001, 0x00000000, 0x00000003, 0x00000002,
3032 0x00000303, 0x000000a1, 0x00000002, 0x00000000, 0x00000003, 0x00000003, 0x00000303, 0x000000a3,
3033 0x00000000, 0x00000000, 0x00000003, 0x00000004, 0x00000303, 0x000000a8, 0x00000000, 0x00000000,
3034 0x00000003, 0x00000005, 0x00000303, 0x49534f50, 0x4e4f4954, 0x50005000, 0x00564552, 0x5458454e,
3035 0xababab00, 0x4e47534f, 0x000000b4, 0x00000005, 0x00000008, 0x00000080, 0x00000000, 0x00000000,
3036 0x00000003, 0x00000000, 0x00000c03, 0x0000008f, 0x00000000, 0x00000000, 0x00000003, 0x00000001,
3037 0x0000000f, 0x00000096, 0x00000000, 0x00000000, 0x00000003, 0x00000002, 0x00000c03, 0x00000096,
3038 0x00000001, 0x00000000, 0x00000003, 0x00000003, 0x00000c03, 0x000000a7, 0x00000000, 0x00000001,
3039 0x00000003, 0x00000004, 0x0000000f, 0x4c524f57, 0x4f505f44, 0x49544953, 0x42004e4f, 0x45495a45,
3040 0x54530052, 0x454b4f52, 0x4152545f, 0x4f46534e, 0x53004d52, 0x4f505f56, 0x49544953, 0xab004e4f,
3041 0x52444853, 0x00000954, 0x00010040, 0x00000255, 0x04000059, 0x00208e46, 0x00000000, 0x00000004,
3042 0x0300005f, 0x00101032, 0x00000000, 0x0300005f, 0x00101032, 0x00000001, 0x0300005f, 0x00101032,
3043 0x00000002, 0x0300005f, 0x00101032, 0x00000003, 0x0300005f, 0x00101032, 0x00000004, 0x0300005f,
3044 0x00101032, 0x00000005, 0x03000065, 0x00102032, 0x00000000, 0x03000065, 0x001020f2, 0x00000001,
3045 0x03000065, 0x00102032, 0x00000002, 0x03000065, 0x00102032, 0x00000003, 0x04000067, 0x001020f2,
3046 0x00000004, 0x00000001, 0x02000068, 0x00000006, 0x0800000f, 0x00100012, 0x00000000, 0x00208046,
3047 0x00000000, 0x00000000, 0x00101046, 0x00000005, 0x0800000f, 0x00100022, 0x00000000, 0x00208046,
3048 0x00000000, 0x00000001, 0x00101046, 0x00000005, 0x0700000f, 0x00100042, 0x00000000, 0x00100046,
3049 0x00000000, 0x00100046, 0x00000000, 0x05000044, 0x00100042, 0x00000000, 0x0010002a, 0x00000000,
3050 0x07000038, 0x00100032, 0x00000000, 0x00100aa6, 0x00000000, 0x00100046, 0x00000000, 0x0800000f,
3051 0x00100012, 0x00000001, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000004, 0x0800000f,
3052 0x00100022, 0x00000001, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000004, 0x0700000f,
3053 0x00100042, 0x00000000, 0x00100046, 0x00000001, 0x00100046, 0x00000001, 0x05000044, 0x00100042,
3054 0x00000000, 0x0010002a, 0x00000000, 0x07000038, 0x00100032, 0x00000001, 0x00100aa6, 0x00000000,
3055 0x00100046, 0x00000001, 0x06000036, 0x001000c2, 0x00000001, 0x80100556, 0x00000041, 0x00000001,
3056 0x0700000f, 0x00100042, 0x00000000, 0x00100a26, 0x00000001, 0x00100046, 0x00000000, 0x0700000f,
3057 0x00100012, 0x00000000, 0x00100046, 0x00000001, 0x00100046, 0x00000000, 0x07000000, 0x00100012,
3058 0x00000000, 0x0010000a, 0x00000000, 0x00004001, 0x3f800000, 0x0800000e, 0x00100012, 0x00000000,
3059 0x8010002a, 0x00000041, 0x00000000, 0x0010000a, 0x00000000, 0x09000032, 0x00100032, 0x00000000,
3060 0x00100006, 0x00000000, 0x00100046, 0x00000001, 0x00100f36, 0x00000001, 0x05000036, 0x00100032,
3061 0x00000001, 0x00101046, 0x00000000, 0x05000036, 0x00100042, 0x00000001, 0x00004001, 0x3f800000,
3062 0x08000010, 0x00100012, 0x00000002, 0x00100246, 0x00000001, 0x00208246, 0x00000000, 0x00000000,
3063 0x08000010, 0x00100022, 0x00000002, 0x00100246, 0x00000001, 0x00208246, 0x00000000, 0x00000001,
3064 0x08000038, 0x00100042, 0x00000000, 0x0020803a, 0x00000000, 0x00000001, 0x00004001, 0x3f000000,
3065 0x09000032, 0x00100032, 0x00000001, 0x00100aa6, 0x00000000, 0x00100046, 0x00000000, 0x00100046,
3066 0x00000002, 0x05000036, 0x00102032, 0x00000000, 0x00100046, 0x00000001, 0x0800000f, 0x00100012,
3067 0x00000002, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000000, 0x0800000f, 0x00100022,
3068 0x00000002, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000000, 0x0800000f, 0x00100012,
3069 0x00000003, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000001, 0x0800000f, 0x00100022,
3070 0x00000003, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000001, 0x08000000, 0x00100032,
3071 0x00000002, 0x00100046, 0x00000002, 0x80100046, 0x00000041, 0x00000003, 0x09000032, 0x00100032,
3072 0x00000000, 0x00100aa6, 0x00000000, 0x00100046, 0x00000000, 0x00100046, 0x00000002, 0x0800000f,
3073 0x00100012, 0x00000002, 0x00208046, 0x00000000, 0x00000002, 0x00100046, 0x00000000, 0x0800000f,
3074 0x00100022, 0x00000002, 0x00208046, 0x00000000, 0x00000003, 0x00100046, 0x00000000, 0x0800000f,
3075 0x00100012, 0x00000004, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000003, 0x0800000f,
3076 0x00100022, 0x00000004, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000003, 0x08000000,
3077 0x001000c2, 0x00000002, 0x80100406, 0x00000041, 0x00000003, 0x00100406, 0x00000004, 0x0800000f,
3078 0x00100082, 0x00000000, 0x00208046, 0x00000000, 0x00000003, 0x00100ae6, 0x00000002, 0x06000036,
3079 0x00100042, 0x00000003, 0x8010003a, 0x00000041, 0x00000000, 0x0800000f, 0x00100082, 0x00000003,
3080 0x00208046, 0x00000000, 0x00000002, 0x00100ae6, 0x00000002, 0x0700000f, 0x00100082, 0x00000000,
3081 0x00100ae6, 0x00000003, 0x00100ae6, 0x00000003, 0x05000044, 0x00100082, 0x00000000, 0x0010003a,
3082 0x00000000, 0x07000038, 0x001000c2, 0x00000003, 0x00100ff6, 0x00000000, 0x00100ea6, 0x00000003,
3083 0x0700000f, 0x00100022, 0x00000004, 0x00100046, 0x00000002, 0x00100ae6, 0x00000003, 0x06000036,
3084 0x00100042, 0x00000000, 0x8010001a, 0x00000041, 0x00000000, 0x0800000f, 0x00100012, 0x00000002,
3085 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000002, 0x0800000f, 0x00100022, 0x00000002,
3086 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000002, 0x08000000, 0x00100032, 0x00000005,
3087 0x80100046, 0x00000041, 0x00000003, 0x00100046, 0x00000002, 0x06000036, 0x00100042, 0x00000005,
3088 0x8010001a, 0x00000041, 0x00000005, 0x0700000f, 0x00100022, 0x00000000, 0x00100a26, 0x00000005,
3089 0x00100ae6, 0x00000002, 0x0d000032, 0x00100032, 0x00000002, 0x80100ae6, 0x00000041, 0x00000002,
3090 0x00004002, 0x3f000000, 0x3f000000, 0x00000000, 0x00000000, 0x00100046, 0x00000005, 0x0800000e,
3091 0x00100032, 0x00000000, 0x80100a26, 0x00000041, 0x00000000, 0x00100556, 0x00000000, 0x0700000f,
3092 0x00100012, 0x00000002, 0x00100046, 0x00000000, 0x00100046, 0x00000002, 0x0700000f, 0x00100022,
3093 0x00000002, 0x00100046, 0x00000000, 0x00100046, 0x00000005, 0x0800000f, 0x00100012, 0x00000000,
3094 0x00208046, 0x00000000, 0x00000002, 0x00100046, 0x00000005, 0x0800000f, 0x00100022, 0x00000000,
3095 0x00208046, 0x00000000, 0x00000003, 0x00100046, 0x00000005, 0x0700000f, 0x00100012, 0x00000000,
3096 0x00100046, 0x00000000, 0x00100ae6, 0x00000003, 0x07000031, 0x00100022, 0x00000000, 0x00004001,
3097 0x00000000, 0x0010000a, 0x00000000, 0x07000031, 0x00100042, 0x00000000, 0x0010000a, 0x00000000,
3098 0x00004001, 0x00000000, 0x08000031, 0x00100012, 0x00000000, 0x8010000a, 0x00000081, 0x00000000,
3099 0x00004001, 0x3f800000, 0x0800001e, 0x00100022, 0x00000000, 0x8010001a, 0x00000041, 0x00000000,
3100 0x0010002a, 0x00000000, 0x0500002b, 0x00100022, 0x00000000, 0x0010001a, 0x00000000, 0x07000038,
3101 0x001000c2, 0x00000002, 0x00100ea6, 0x00000003, 0x00100556, 0x00000000, 0x08000036, 0x001000d2,
3102 0x00000004, 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x09000037, 0x001020f2,
3103 0x00000001, 0x00100006, 0x00000000, 0x00100e46, 0x00000004, 0x00100e46, 0x00000002, 0x06000036,
3104 0x00100032, 0x00000000, 0x00208046, 0x00000000, 0x00000002, 0x06000036, 0x001000c2, 0x00000000,
3105 0x00208406, 0x00000000, 0x00000003, 0x08000038, 0x001000f2, 0x00000000, 0x00100e46, 0x00000000,
3106 0x00208ff6, 0x00000000, 0x00000001, 0x0a000038, 0x001000f2, 0x00000000, 0x00100e46, 0x00000000,
3107 0x00004002, 0x3f000000, 0x3f000000, 0x3f000000, 0x3f000000, 0x05000036, 0x00102032, 0x00000002,
3108 0x00100086, 0x00000000, 0x05000036, 0x00102032, 0x00000003, 0x001005d6, 0x00000000, 0x05000036,
3109 0x00100042, 0x00000001, 0x00004001, 0x3f800000, 0x08000010, 0x00100012, 0x00000000, 0x00208246,
3110 0x00000000, 0x00000002, 0x00100246, 0x00000001, 0x08000010, 0x00100022, 0x00000000, 0x00208246,
3111 0x00000000, 0x00000003, 0x00100246, 0x00000001, 0x08000038, 0x00100022, 0x00000001, 0x0010001a,
3112 0x00000000, 0x0020803a, 0x00000000, 0x00000003, 0x08000038, 0x00100012, 0x00000001, 0x0010000a,
3113 0x00000000, 0x0020803a, 0x00000000, 0x00000002, 0x0a000000, 0x00102032, 0x00000004, 0x00100046,
3114 0x00000001, 0x00004002, 0xbf800000, 0x3f800000, 0x00000000, 0x00000000, 0x08000036, 0x001020c2,
3115 0x00000004, 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, 0x0100003e,
3117 /* ⎡p0.x p0.y 1⎤
3118 * A = ⎢p1.x p1.y 1⎥
3119 * ⎣p2.x p2.y 1⎦
3121 * ⎡1 0⎤
3122 * B = ⎢1 1⎥
3123 * ⎣0 1⎦
3125 * A' = ⎡p1.x-p0.x p1.y-p0.y⎤
3126 * ⎣p2.x-p0.x p2.y-p0.y⎦
3128 * B' = ⎡ 0 1⎤
3129 * ⎣-1 1⎦
3131 * A'T = B'
3132 * T = A'⁻¹B' = (B'⁻¹A')⁻¹
3134 static const DWORD vs_code_arc_outline[] =
3136 #if 0
3137 float3x2 transform_geometry;
3138 float stroke_width;
3139 float4 transform_rtx;
3140 float4 transform_rty;
3142 struct output
3144 float2 p : WORLD_POSITION;
3145 float4 b : BEZIER;
3146 nointerpolation float2x2 stroke_transform : STROKE_TRANSFORM;
3147 float4 position : SV_POSITION;
3150 void main(float2 position : POSITION, float2 p0 : P0, float2 p1 : P1, float2 p2 : P2,
3151 float2 prev : PREV, float2 next : NEXT, out struct output o)
3153 float2 q_prev, q_next, v_p, q_i, p;
3154 float2x2 geom, rt, p_inv;
3155 float l;
3156 float a;
3157 float2 bc;
3159 geom = float2x2(transform_geometry._11_21, transform_geometry._12_22);
3160 rt = float2x2(transform_rtx.xy, transform_rty.xy);
3161 o.stroke_transform = rt * stroke_width * 0.5f;
3163 p = mul(geom, position);
3164 p0 = mul(geom, p0);
3165 p1 = mul(geom, p1);
3166 p2 = mul(geom, p2);
3168 p -= p0;
3169 p1 -= p0;
3170 p2 -= p0;
3172 q_prev = normalize(mul(geom, prev));
3173 q_next = normalize(mul(geom, next));
3175 v_p = float2(-q_prev.y, q_prev.x);
3176 l = -dot(v_p, q_next) / (1.0f + dot(q_prev, q_next));
3177 q_i = l * q_prev + v_p;
3178 p += 0.5f * stroke_width * q_i;
3180 p_inv = float2x2(p1.y, -p1.x, p2.y - p1.y, p1.x - p2.x) / (p1.x * p2.y - p2.x * p1.y);
3181 o.b.xy = mul(p_inv, p) + float2(1.0f, 0.0f);
3182 o.b.zw = 0.0f;
3184 o.p = mul(float3(position, 1.0f), transform_geometry) + 0.5f * stroke_width * q_i;
3185 position = mul(float2x3(transform_rtx.xyz, transform_rty.xyz), float3(o.p, 1.0f))
3186 * float2(transform_rtx.w, transform_rty.w);
3187 o.position = float4(position + float2(-1.0f, 1.0f), 0.0f, 1.0f);
3189 #endif
3190 0x43425844, 0xde1911bf, 0xfff8c893, 0xb0bfc24d, 0x78c9bbc4, 0x00000001, 0x00000924, 0x00000003,
3191 0x0000002c, 0x000000e4, 0x000001a0, 0x4e475349, 0x000000b0, 0x00000006, 0x00000008, 0x00000098,
3192 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000303, 0x000000a1, 0x00000000, 0x00000000,
3193 0x00000003, 0x00000001, 0x00000303, 0x000000a1, 0x00000001, 0x00000000, 0x00000003, 0x00000002,
3194 0x00000303, 0x000000a1, 0x00000002, 0x00000000, 0x00000003, 0x00000003, 0x00000303, 0x000000a3,
3195 0x00000000, 0x00000000, 0x00000003, 0x00000004, 0x00000303, 0x000000a8, 0x00000000, 0x00000000,
3196 0x00000003, 0x00000005, 0x00000303, 0x49534f50, 0x4e4f4954, 0x50005000, 0x00564552, 0x5458454e,
3197 0xababab00, 0x4e47534f, 0x000000b4, 0x00000005, 0x00000008, 0x00000080, 0x00000000, 0x00000000,
3198 0x00000003, 0x00000000, 0x00000c03, 0x0000008f, 0x00000000, 0x00000000, 0x00000003, 0x00000001,
3199 0x0000000f, 0x00000096, 0x00000000, 0x00000000, 0x00000003, 0x00000002, 0x00000c03, 0x00000096,
3200 0x00000001, 0x00000000, 0x00000003, 0x00000003, 0x00000c03, 0x000000a7, 0x00000000, 0x00000001,
3201 0x00000003, 0x00000004, 0x0000000f, 0x4c524f57, 0x4f505f44, 0x49544953, 0x42004e4f, 0x45495a45,
3202 0x54530052, 0x454b4f52, 0x4152545f, 0x4f46534e, 0x53004d52, 0x4f505f56, 0x49544953, 0xab004e4f,
3203 0x52444853, 0x0000077c, 0x00010040, 0x000001df, 0x04000059, 0x00208e46, 0x00000000, 0x00000004,
3204 0x0300005f, 0x00101032, 0x00000000, 0x0300005f, 0x00101032, 0x00000001, 0x0300005f, 0x00101032,
3205 0x00000002, 0x0300005f, 0x00101032, 0x00000003, 0x0300005f, 0x00101032, 0x00000004, 0x0300005f,
3206 0x00101032, 0x00000005, 0x03000065, 0x00102032, 0x00000000, 0x03000065, 0x001020f2, 0x00000001,
3207 0x03000065, 0x00102032, 0x00000002, 0x03000065, 0x00102032, 0x00000003, 0x04000067, 0x001020f2,
3208 0x00000004, 0x00000001, 0x02000068, 0x00000004, 0x0800000f, 0x00100012, 0x00000000, 0x00208046,
3209 0x00000000, 0x00000000, 0x00101046, 0x00000005, 0x0800000f, 0x00100022, 0x00000000, 0x00208046,
3210 0x00000000, 0x00000001, 0x00101046, 0x00000005, 0x0700000f, 0x00100042, 0x00000000, 0x00100046,
3211 0x00000000, 0x00100046, 0x00000000, 0x05000044, 0x00100042, 0x00000000, 0x0010002a, 0x00000000,
3212 0x07000038, 0x00100032, 0x00000000, 0x00100aa6, 0x00000000, 0x00100046, 0x00000000, 0x0800000f,
3213 0x00100012, 0x00000001, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000004, 0x0800000f,
3214 0x00100022, 0x00000001, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000004, 0x0700000f,
3215 0x00100042, 0x00000000, 0x00100046, 0x00000001, 0x00100046, 0x00000001, 0x05000044, 0x00100042,
3216 0x00000000, 0x0010002a, 0x00000000, 0x07000038, 0x00100032, 0x00000001, 0x00100aa6, 0x00000000,
3217 0x00100046, 0x00000001, 0x06000036, 0x001000c2, 0x00000001, 0x80100556, 0x00000041, 0x00000001,
3218 0x0700000f, 0x00100042, 0x00000000, 0x00100a26, 0x00000001, 0x00100046, 0x00000000, 0x0700000f,
3219 0x00100012, 0x00000000, 0x00100046, 0x00000001, 0x00100046, 0x00000000, 0x07000000, 0x00100012,
3220 0x00000000, 0x0010000a, 0x00000000, 0x00004001, 0x3f800000, 0x0800000e, 0x00100012, 0x00000000,
3221 0x8010002a, 0x00000041, 0x00000000, 0x0010000a, 0x00000000, 0x09000032, 0x00100032, 0x00000000,
3222 0x00100006, 0x00000000, 0x00100046, 0x00000001, 0x00100f36, 0x00000001, 0x05000036, 0x00100032,
3223 0x00000001, 0x00101046, 0x00000000, 0x05000036, 0x00100042, 0x00000001, 0x00004001, 0x3f800000,
3224 0x08000010, 0x00100012, 0x00000002, 0x00100246, 0x00000001, 0x00208246, 0x00000000, 0x00000000,
3225 0x08000010, 0x00100022, 0x00000002, 0x00100246, 0x00000001, 0x00208246, 0x00000000, 0x00000001,
3226 0x08000038, 0x00100042, 0x00000000, 0x0020803a, 0x00000000, 0x00000001, 0x00004001, 0x3f000000,
3227 0x09000032, 0x00100032, 0x00000001, 0x00100aa6, 0x00000000, 0x00100046, 0x00000000, 0x00100046,
3228 0x00000002, 0x05000036, 0x00102032, 0x00000000, 0x00100046, 0x00000001, 0x0800000f, 0x00100012,
3229 0x00000002, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000000, 0x0800000f, 0x00100022,
3230 0x00000002, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000000, 0x0800000f, 0x00100022,
3231 0x00000003, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000001, 0x0800000f, 0x00100012,
3232 0x00000003, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000001, 0x08000000, 0x00100032,
3233 0x00000002, 0x00100046, 0x00000002, 0x80100516, 0x00000041, 0x00000003, 0x09000032, 0x00100032,
3234 0x00000000, 0x00100aa6, 0x00000000, 0x00100046, 0x00000000, 0x00100046, 0x00000002, 0x0800000f,
3235 0x00100022, 0x00000002, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000003, 0x0800000f,
3236 0x00100012, 0x00000002, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000003, 0x08000000,
3237 0x001000c2, 0x00000000, 0x80100406, 0x00000041, 0x00000003, 0x00100406, 0x00000002, 0x0800000f,
3238 0x00100022, 0x00000002, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000002, 0x0800000f,
3239 0x00100012, 0x00000002, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000002, 0x08000000,
3240 0x00100032, 0x00000002, 0x80100046, 0x00000041, 0x00000003, 0x00100046, 0x00000002, 0x07000038,
3241 0x00100082, 0x00000001, 0x0010003a, 0x00000000, 0x0010000a, 0x00000002, 0x0a000032, 0x00100082,
3242 0x00000001, 0x0010001a, 0x00000002, 0x0010002a, 0x00000000, 0x8010003a, 0x00000041, 0x00000001,
3243 0x08000000, 0x00100042, 0x00000003, 0x0010002a, 0x00000000, 0x8010000a, 0x00000041, 0x00000002,
3244 0x08000000, 0x00100082, 0x00000003, 0x8010003a, 0x00000041, 0x00000000, 0x0010001a, 0x00000002,
3245 0x0a000038, 0x00100032, 0x00000003, 0x00100046, 0x00000002, 0x00004002, 0x3f800000, 0xbf800000,
3246 0x00000000, 0x00000000, 0x0700000e, 0x001000f2, 0x00000002, 0x00100e46, 0x00000003, 0x00100ff6,
3247 0x00000001, 0x0700000f, 0x00100012, 0x00000002, 0x00100046, 0x00000002, 0x00100046, 0x00000000,
3248 0x0700000f, 0x00100022, 0x00000002, 0x00100ae6, 0x00000002, 0x00100046, 0x00000000, 0x0a000000,
3249 0x00102032, 0x00000001, 0x00100046, 0x00000002, 0x00004002, 0x3f800000, 0x00000000, 0x00000000,
3250 0x00000000, 0x08000036, 0x001020c2, 0x00000001, 0x00004002, 0x00000000, 0x00000000, 0x00000000,
3251 0x00000000, 0x06000036, 0x00100032, 0x00000000, 0x00208046, 0x00000000, 0x00000002, 0x06000036,
3252 0x001000c2, 0x00000000, 0x00208406, 0x00000000, 0x00000003, 0x08000038, 0x001000f2, 0x00000000,
3253 0x00100e46, 0x00000000, 0x00208ff6, 0x00000000, 0x00000001, 0x0a000038, 0x001000f2, 0x00000000,
3254 0x00100e46, 0x00000000, 0x00004002, 0x3f000000, 0x3f000000, 0x3f000000, 0x3f000000, 0x05000036,
3255 0x00102032, 0x00000002, 0x00100086, 0x00000000, 0x05000036, 0x00102032, 0x00000003, 0x001005d6,
3256 0x00000000, 0x05000036, 0x00100042, 0x00000001, 0x00004001, 0x3f800000, 0x08000010, 0x00100012,
3257 0x00000000, 0x00208246, 0x00000000, 0x00000002, 0x00100246, 0x00000001, 0x08000010, 0x00100022,
3258 0x00000000, 0x00208246, 0x00000000, 0x00000003, 0x00100246, 0x00000001, 0x08000038, 0x00100022,
3259 0x00000001, 0x0010001a, 0x00000000, 0x0020803a, 0x00000000, 0x00000003, 0x08000038, 0x00100012,
3260 0x00000001, 0x0010000a, 0x00000000, 0x0020803a, 0x00000000, 0x00000002, 0x0a000000, 0x00102032,
3261 0x00000004, 0x00100046, 0x00000001, 0x00004002, 0xbf800000, 0x3f800000, 0x00000000, 0x00000000,
3262 0x08000036, 0x001020c2, 0x00000004, 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x3f800000,
3263 0x0100003e,
3265 static const DWORD vs_code_triangle[] =
3267 #if 0
3268 float3x2 transform_geometry;
3269 float4 transform_rtx;
3270 float4 transform_rty;
3272 struct output
3274 float2 p : WORLD_POSITION;
3275 float4 b : BEZIER;
3276 nointerpolation float2x2 stroke_transform : STROKE_TRANSFORM;
3277 float4 position : SV_POSITION;
3280 void main(float2 position : POSITION, out struct output o)
3282 o.p = mul(float3(position, 1.0f), transform_geometry);
3283 o.b = float4(1.0, 0.0, 1.0, 1.0);
3284 o.stroke_transform = float2x2(1.0, 0.0, 0.0, 1.0);
3285 position = mul(float2x3(transform_rtx.xyz, transform_rty.xyz), float3(o.p, 1.0f))
3286 * float2(transform_rtx.w, transform_rty.w);
3287 o.position = float4(position + float2(-1.0f, 1.0f), 0.0f, 1.0f);
3289 #endif
3290 0x43425844, 0xda43bf17, 0x06e6d155, 0xdbce2ae5, 0x8aed6fd8, 0x00000001, 0x0000034c, 0x00000003,
3291 0x0000002c, 0x00000060, 0x0000011c, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020,
3292 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000303, 0x49534f50, 0x4e4f4954, 0xababab00,
3293 0x4e47534f, 0x000000b4, 0x00000005, 0x00000008, 0x00000080, 0x00000000, 0x00000000, 0x00000003,
3294 0x00000000, 0x00000c03, 0x0000008f, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x0000000f,
3295 0x00000096, 0x00000000, 0x00000000, 0x00000003, 0x00000002, 0x00000c03, 0x00000096, 0x00000001,
3296 0x00000000, 0x00000003, 0x00000003, 0x00000c03, 0x000000a7, 0x00000000, 0x00000001, 0x00000003,
3297 0x00000004, 0x0000000f, 0x4c524f57, 0x4f505f44, 0x49544953, 0x42004e4f, 0x45495a45, 0x54530052,
3298 0x454b4f52, 0x4152545f, 0x4f46534e, 0x53004d52, 0x4f505f56, 0x49544953, 0xab004e4f, 0x52444853,
3299 0x00000228, 0x00010040, 0x0000008a, 0x04000059, 0x00208e46, 0x00000000, 0x00000004, 0x0300005f,
3300 0x00101032, 0x00000000, 0x03000065, 0x00102032, 0x00000000, 0x03000065, 0x001020f2, 0x00000001,
3301 0x03000065, 0x00102032, 0x00000002, 0x03000065, 0x00102032, 0x00000003, 0x04000067, 0x001020f2,
3302 0x00000004, 0x00000001, 0x02000068, 0x00000002, 0x05000036, 0x00100032, 0x00000000, 0x00101046,
3303 0x00000000, 0x05000036, 0x00100042, 0x00000000, 0x00004001, 0x3f800000, 0x08000010, 0x00100012,
3304 0x00000001, 0x00100246, 0x00000000, 0x00208246, 0x00000000, 0x00000000, 0x08000010, 0x00100022,
3305 0x00000001, 0x00100246, 0x00000000, 0x00208246, 0x00000000, 0x00000001, 0x05000036, 0x00102032,
3306 0x00000000, 0x00100046, 0x00000001, 0x08000036, 0x001020f2, 0x00000001, 0x00004002, 0x3f800000,
3307 0x00000000, 0x3f800000, 0x3f800000, 0x08000036, 0x00102032, 0x00000002, 0x00004002, 0x3f800000,
3308 0x00000000, 0x00000000, 0x00000000, 0x08000036, 0x00102032, 0x00000003, 0x00004002, 0x00000000,
3309 0x3f800000, 0x00000000, 0x00000000, 0x05000036, 0x00100042, 0x00000001, 0x00004001, 0x3f800000,
3310 0x08000010, 0x00100012, 0x00000000, 0x00208246, 0x00000000, 0x00000002, 0x00100246, 0x00000001,
3311 0x08000010, 0x00100022, 0x00000000, 0x00208246, 0x00000000, 0x00000003, 0x00100246, 0x00000001,
3312 0x08000038, 0x00100022, 0x00000001, 0x0010001a, 0x00000000, 0x0020803a, 0x00000000, 0x00000003,
3313 0x08000038, 0x00100012, 0x00000001, 0x0010000a, 0x00000000, 0x0020803a, 0x00000000, 0x00000002,
3314 0x0a000000, 0x00102032, 0x00000004, 0x00100046, 0x00000001, 0x00004002, 0xbf800000, 0x3f800000,
3315 0x00000000, 0x00000000, 0x08000036, 0x001020c2, 0x00000004, 0x00004002, 0x00000000, 0x00000000,
3316 0x00000000, 0x3f800000, 0x0100003e,
3318 static const DWORD vs_code_curve[] =
3320 #if 0
3321 float3x2 transform_geometry;
3322 float4 transform_rtx;
3323 float4 transform_rty;
3325 struct output
3327 float2 p : WORLD_POSITION;
3328 float4 b : BEZIER;
3329 nointerpolation float2x2 stroke_transform : STROKE_TRANSFORM;
3330 float4 position : SV_POSITION;
3333 void main(float2 position : POSITION, float3 texcoord : TEXCOORD0, out struct output o)
3335 o.p = mul(float3(position, 1.0f), transform_geometry);
3336 o.b = float4(texcoord, 1.0);
3337 o.stroke_transform = float2x2(1.0, 0.0, 0.0, 1.0);
3338 position = mul(float2x3(transform_rtx.xyz, transform_rty.xyz), float3(o.p, 1.0f))
3339 * float2(transform_rtx.w, transform_rty.w);
3340 o.position = float4(position + float2(-1.0f, 1.0f), 0.0f, 1.0f);
3342 #endif
3343 0x43425844, 0xedb7472a, 0x2c2ea147, 0x36710079, 0xffc2e907, 0x00000001, 0x00000380, 0x00000003,
3344 0x0000002c, 0x00000080, 0x0000013c, 0x4e475349, 0x0000004c, 0x00000002, 0x00000008, 0x00000038,
3345 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000303, 0x00000041, 0x00000000, 0x00000000,
3346 0x00000003, 0x00000001, 0x00000707, 0x49534f50, 0x4e4f4954, 0x58455400, 0x524f4f43, 0xabab0044,
3347 0x4e47534f, 0x000000b4, 0x00000005, 0x00000008, 0x00000080, 0x00000000, 0x00000000, 0x00000003,
3348 0x00000000, 0x00000c03, 0x0000008f, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x0000000f,
3349 0x00000096, 0x00000000, 0x00000000, 0x00000003, 0x00000002, 0x00000c03, 0x00000096, 0x00000001,
3350 0x00000000, 0x00000003, 0x00000003, 0x00000c03, 0x000000a7, 0x00000000, 0x00000001, 0x00000003,
3351 0x00000004, 0x0000000f, 0x4c524f57, 0x4f505f44, 0x49544953, 0x42004e4f, 0x45495a45, 0x54530052,
3352 0x454b4f52, 0x4152545f, 0x4f46534e, 0x53004d52, 0x4f505f56, 0x49544953, 0xab004e4f, 0x52444853,
3353 0x0000023c, 0x00010040, 0x0000008f, 0x04000059, 0x00208e46, 0x00000000, 0x00000004, 0x0300005f,
3354 0x00101032, 0x00000000, 0x0300005f, 0x00101072, 0x00000001, 0x03000065, 0x00102032, 0x00000000,
3355 0x03000065, 0x001020f2, 0x00000001, 0x03000065, 0x00102032, 0x00000002, 0x03000065, 0x00102032,
3356 0x00000003, 0x04000067, 0x001020f2, 0x00000004, 0x00000001, 0x02000068, 0x00000002, 0x05000036,
3357 0x00100032, 0x00000000, 0x00101046, 0x00000000, 0x05000036, 0x00100042, 0x00000000, 0x00004001,
3358 0x3f800000, 0x08000010, 0x00100012, 0x00000001, 0x00100246, 0x00000000, 0x00208246, 0x00000000,
3359 0x00000000, 0x08000010, 0x00100022, 0x00000001, 0x00100246, 0x00000000, 0x00208246, 0x00000000,
3360 0x00000001, 0x05000036, 0x00102032, 0x00000000, 0x00100046, 0x00000001, 0x05000036, 0x00102072,
3361 0x00000001, 0x00101246, 0x00000001, 0x05000036, 0x00102082, 0x00000001, 0x00004001, 0x3f800000,
3362 0x08000036, 0x00102032, 0x00000002, 0x00004002, 0x3f800000, 0x00000000, 0x00000000, 0x00000000,
3363 0x08000036, 0x00102032, 0x00000003, 0x00004002, 0x00000000, 0x3f800000, 0x00000000, 0x00000000,
3364 0x05000036, 0x00100042, 0x00000001, 0x00004001, 0x3f800000, 0x08000010, 0x00100012, 0x00000000,
3365 0x00208246, 0x00000000, 0x00000002, 0x00100246, 0x00000001, 0x08000010, 0x00100022, 0x00000000,
3366 0x00208246, 0x00000000, 0x00000003, 0x00100246, 0x00000001, 0x08000038, 0x00100022, 0x00000001,
3367 0x0010001a, 0x00000000, 0x0020803a, 0x00000000, 0x00000003, 0x08000038, 0x00100012, 0x00000001,
3368 0x0010000a, 0x00000000, 0x0020803a, 0x00000000, 0x00000002, 0x0a000000, 0x00102032, 0x00000004,
3369 0x00100046, 0x00000001, 0x00004002, 0xbf800000, 0x3f800000, 0x00000000, 0x00000000, 0x08000036,
3370 0x001020c2, 0x00000004, 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, 0x0100003e,
3372 static const DWORD ps_code[] =
3374 #if 0
3375 #define BRUSH_TYPE_SOLID 0
3376 #define BRUSH_TYPE_LINEAR 1
3377 #define BRUSH_TYPE_RADIAL 2
3378 #define BRUSH_TYPE_BITMAP 3
3379 #define BRUSH_TYPE_COUNT 4
3381 bool outline;
3382 bool is_arc;
3383 struct brush
3385 uint type;
3386 float opacity;
3387 float4 data[3];
3388 } colour_brush, opacity_brush;
3390 SamplerState s0, s1;
3391 Texture2D t0, t1;
3392 Buffer<float4> b0, b1;
3394 struct input
3396 float2 p : WORLD_POSITION;
3397 float4 b : BEZIER;
3398 nointerpolation float2x2 stroke_transform : STROKE_TRANSFORM;
3401 float4 sample_gradient(Buffer<float4> gradient, uint stop_count, float position)
3403 float4 c_low, c_high;
3404 float p_low, p_high;
3405 uint i;
3407 p_low = gradient.Load(0).x;
3408 c_low = gradient.Load(1);
3409 c_high = c_low;
3411 if (position < p_low)
3412 return c_low;
3414 for (i = 1; i < stop_count; ++i)
3416 p_high = gradient.Load(i * 2).x;
3417 c_high = gradient.Load(i * 2 + 1);
3419 if (position >= p_low && position <= p_high)
3420 return lerp(c_low, c_high, (position - p_low) / (p_high - p_low));
3422 p_low = p_high;
3423 c_low = c_high;
3426 return c_high;
3429 float4 brush_linear(struct brush brush, Buffer<float4> gradient, float2 position)
3431 float2 start, end, v_p, v_q;
3432 uint stop_count;
3433 float p;
3435 start = brush.data[0].xy;
3436 end = brush.data[0].zw;
3437 stop_count = asuint(brush.data[1].x);
3439 v_p = position - start;
3440 v_q = end - start;
3441 p = dot(v_q, v_p) / dot(v_q, v_q);
3443 return sample_gradient(gradient, stop_count, p);
3446 float4 brush_radial(struct brush brush, Buffer<float4> gradient, float2 position)
3448 float2 centre, offset, ra, rb, v_p, v_q, r;
3449 float b, c, l, t;
3450 uint stop_count;
3452 centre = brush.data[0].xy;
3453 offset = brush.data[0].zw;
3454 ra = brush.data[1].xy;
3455 rb = brush.data[1].zw;
3456 stop_count = asuint(brush.data[2].x);
3458 /* Project onto ra, rb. */
3459 r = float2(dot(ra, ra), dot(rb, rb));
3460 v_p = position - (centre + offset);
3461 v_p = float2(dot(v_p, ra), dot(v_p, rb)) / r;
3462 v_q = float2(dot(offset, ra), dot(offset, rb)) / r;
3464 /* ‖t·p̂ + q⃑‖ = 1
3465 * (t·p̂ + q⃑) · (t·p̂ + q⃑) = 1
3466 * t² + 2·(p̂·q⃑)·t + (q⃑·q⃑) = 1
3468 * b = p̂·q⃑
3469 * c = q⃑·q⃑ - 1
3470 * t = -b + √(b² - c) */
3471 l = length(v_p);
3472 b = dot(v_p, v_q) / l;
3473 c = dot(v_q, v_q) - 1.0;
3474 t = -b + sqrt(b * b - c);
3476 return sample_gradient(gradient, stop_count, l / t);
3479 float4 brush_bitmap(struct brush brush, Texture2D t, SamplerState s, float2 position)
3481 float3 transform[2];
3482 bool ignore_alpha;
3483 float2 texcoord;
3484 float4 colour;
3486 transform[0] = brush.data[0].xyz;
3487 transform[1] = brush.data[1].xyz;
3488 ignore_alpha = asuint(brush.data[1].w);
3490 texcoord.x = dot(position.xy, transform[0].xy) + transform[0].z;
3491 texcoord.y = dot(position.xy, transform[1].xy) + transform[1].z;
3492 colour = t.Sample(s, texcoord);
3493 if (ignore_alpha)
3494 colour.a = 1.0;
3495 return colour;
3498 float4 sample_brush(struct brush brush, Texture2D t, SamplerState s, Buffer<float4> b, float2 position)
3500 if (brush.type == BRUSH_TYPE_SOLID)
3501 return brush.data[0] * brush.opacity;
3502 if (brush.type == BRUSH_TYPE_LINEAR)
3503 return brush_linear(brush, b, position) * brush.opacity;
3504 if (brush.type == BRUSH_TYPE_RADIAL)
3505 return brush_radial(brush, b, position) * brush.opacity;
3506 if (brush.type == BRUSH_TYPE_BITMAP)
3507 return brush_bitmap(brush, t, s, position) * brush.opacity;
3508 return float4(0.0, 0.0, 0.0, brush.opacity);
3511 float4 main(struct input i) : SV_Target
3513 float4 colour;
3515 colour = sample_brush(colour_brush, t0, s0, b0, i.p);
3516 if (opacity_brush.type < BRUSH_TYPE_COUNT)
3517 colour *= sample_brush(opacity_brush, t1, s1, b1, i.p).a;
3519 if (outline)
3521 float2 du, dv, df;
3522 float4 uv;
3524 /* Evaluate the implicit form of the curve (u² - v = 0
3525 * for Béziers, u² + v² - 1 = 0 for arcs) in texture
3526 * space, using the screen-space partial derivatives
3527 * to convert the calculated distance to object space.
3529 * d(x, y) = |f(x, y)| / ‖∇f(x, y)‖
3530 * = |f(x, y)| / √((∂f/∂x)² + (∂f/∂y)²)
3532 * For Béziers:
3533 * f(x, y) = u(x, y)² - v(x, y)
3534 * ∂f/∂x = 2u · ∂u/∂x - ∂v/∂x
3535 * ∂f/∂y = 2u · ∂u/∂y - ∂v/∂y
3537 * For arcs:
3538 * f(x, y) = u(x, y)² + v(x, y)² - 1
3539 * ∂f/∂x = 2u · ∂u/∂x + 2v · ∂v/∂x
3540 * ∂f/∂y = 2u · ∂u/∂y + 2v · ∂v/∂y */
3541 uv = i.b;
3542 du = float2(ddx(uv.x), ddy(uv.x));
3543 dv = float2(ddx(uv.y), ddy(uv.y));
3545 if (!is_arc)
3547 df = 2.0f * uv.x * du - dv;
3549 clip(dot(df, uv.zw));
3550 clip(length(mul(i.stroke_transform, df)) - abs(uv.x * uv.x - uv.y));
3552 else
3554 df = 2.0f * uv.x * du + 2.0f * uv.y * dv;
3556 clip(dot(df, uv.zw));
3557 clip(length(mul(i.stroke_transform, df)) - abs(uv.x * uv.x + uv.y * uv.y - 1.0f));
3560 else
3562 /* Evaluate the implicit form of the curve in texture space.
3563 * "i.b.z" determines which side of the curve is shaded. */
3564 if (!is_arc)
3566 clip((i.b.x * i.b.x - i.b.y) * i.b.z);
3568 else
3570 clip((i.b.x * i.b.x + i.b.y * i.b.y - 1.0) * i.b.z);
3574 return colour;
3576 #endif
3577 0x43425844, 0xa8fee730, 0x92fa2196, 0xaf9f3eff, 0x888d4048, 0x00000001, 0x00002000, 0x00000003,
3578 0x0000002c, 0x000000c4, 0x000000f8, 0x4e475349, 0x00000090, 0x00000004, 0x00000008, 0x00000068,
3579 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000303, 0x00000077, 0x00000000, 0x00000000,
3580 0x00000003, 0x00000001, 0x00000f0f, 0x0000007e, 0x00000000, 0x00000000, 0x00000003, 0x00000002,
3581 0x00000303, 0x0000007e, 0x00000001, 0x00000000, 0x00000003, 0x00000003, 0x00000303, 0x4c524f57,
3582 0x4f505f44, 0x49544953, 0x42004e4f, 0x45495a45, 0x54530052, 0x454b4f52, 0x4152545f, 0x4f46534e,
3583 0xab004d52, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000,
3584 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x00001f00,
3585 0x00000040, 0x000007c0, 0x04000059, 0x00208e46, 0x00000000, 0x00000009, 0x0300005a, 0x00106000,
3586 0x00000000, 0x0300005a, 0x00106000, 0x00000001, 0x04001858, 0x00107000, 0x00000000, 0x00005555,
3587 0x04001858, 0x00107000, 0x00000001, 0x00005555, 0x04000858, 0x00107000, 0x00000002, 0x00005555,
3588 0x04000858, 0x00107000, 0x00000003, 0x00005555, 0x03001062, 0x00101032, 0x00000000, 0x03001062,
3589 0x001010f2, 0x00000001, 0x03000862, 0x00101032, 0x00000002, 0x03000862, 0x00101032, 0x00000003,
3590 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x0000000a, 0x09000038, 0x001000f2, 0x00000000,
3591 0x00208556, 0x00000000, 0x00000001, 0x00208e46, 0x00000000, 0x00000002, 0x0404001f, 0x0020800a,
3592 0x00000000, 0x00000001, 0x08000020, 0x00100012, 0x00000001, 0x0020800a, 0x00000000, 0x00000001,
3593 0x00004001, 0x00000001, 0x0304001f, 0x0010000a, 0x00000001, 0x09000000, 0x00100062, 0x00000001,
3594 0x00101106, 0x00000000, 0x80208106, 0x00000041, 0x00000000, 0x00000002, 0x0a000000, 0x00100032,
3595 0x00000002, 0x80208046, 0x00000041, 0x00000000, 0x00000002, 0x00208ae6, 0x00000000, 0x00000002,
3596 0x0700000f, 0x00100022, 0x00000001, 0x00100046, 0x00000002, 0x00100596, 0x00000001, 0x0700000f,
3597 0x00100042, 0x00000001, 0x00100046, 0x00000002, 0x00100046, 0x00000002, 0x0700000e, 0x00100022,
3598 0x00000001, 0x0010001a, 0x00000001, 0x0010002a, 0x00000001, 0x0a00002d, 0x001000f2, 0x00000002,
3599 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00107e46, 0x00000002, 0x0a00002d,
3600 0x001000f2, 0x00000003, 0x00004002, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00107e46,
3601 0x00000002, 0x0700001d, 0x00100042, 0x00000001, 0x0010001a, 0x00000001, 0x0010000a, 0x00000002,
3602 0x0304001f, 0x0010002a, 0x00000001, 0x05000036, 0x001000f2, 0x00000004, 0x00100e46, 0x00000003,
3603 0x05000036, 0x001000f2, 0x00000005, 0x00100e46, 0x00000003, 0x05000036, 0x001000f2, 0x00000006,
3604 0x00100e46, 0x00000003, 0x05000036, 0x00100042, 0x00000001, 0x0010000a, 0x00000002, 0x05000036,
3605 0x00100082, 0x00000001, 0x00004001, 0x00000001, 0x05000036, 0x00100022, 0x00000002, 0x00004001,
3606 0x00000000, 0x01000030, 0x08000050, 0x00100042, 0x00000002, 0x0010003a, 0x00000001, 0x0020800a,
3607 0x00000000, 0x00000003, 0x05000036, 0x00100022, 0x00000002, 0x00004001, 0x00000000, 0x03040003,
3608 0x0010002a, 0x00000002, 0x07000029, 0x00100042, 0x00000002, 0x0010003a, 0x00000001, 0x00004001,
3609 0x00000001, 0x0700002d, 0x001000f2, 0x00000007, 0x00100aa6, 0x00000002, 0x00107e46, 0x00000002,
3610 0x0700001e, 0x00100042, 0x00000002, 0x0010002a, 0x00000002, 0x00004001, 0x00000001, 0x0700002d,
3611 0x001000f2, 0x00000008, 0x00100aa6, 0x00000002, 0x00107e46, 0x00000002, 0x0700001d, 0x00100042,
3612 0x00000002, 0x0010001a, 0x00000001, 0x0010002a, 0x00000001, 0x0700001d, 0x00100082, 0x00000002,
3613 0x0010000a, 0x00000007, 0x0010001a, 0x00000001, 0x07000001, 0x00100042, 0x00000002, 0x0010003a,
3614 0x00000002, 0x0010002a, 0x00000002, 0x0304001f, 0x0010002a, 0x00000002, 0x08000000, 0x00100082,
3615 0x00000002, 0x8010002a, 0x00000041, 0x00000001, 0x0010001a, 0x00000001, 0x08000000, 0x00100022,
3616 0x00000007, 0x8010002a, 0x00000041, 0x00000001, 0x0010000a, 0x00000007, 0x0700000e, 0x00100082,
3617 0x00000002, 0x0010003a, 0x00000002, 0x0010001a, 0x00000007, 0x08000000, 0x001000f2, 0x00000009,
3618 0x80100e46, 0x00000041, 0x00000005, 0x00100e46, 0x00000008, 0x09000032, 0x001000f2, 0x00000009,
3619 0x00100ff6, 0x00000002, 0x00100e46, 0x00000009, 0x00100e46, 0x00000005, 0x05000036, 0x001000f2,
3620 0x00000006, 0x00100e46, 0x00000008, 0x05000036, 0x00100022, 0x00000002, 0x00004001, 0xffffffff,
3621 0x05000036, 0x001000f2, 0x00000004, 0x00100e46, 0x00000009, 0x01000002, 0x01000015, 0x05000036,
3622 0x001000f2, 0x00000005, 0x00100e46, 0x00000008, 0x05000036, 0x00100042, 0x00000001, 0x0010000a,
3623 0x00000007, 0x0700001e, 0x00100082, 0x00000001, 0x0010003a, 0x00000001, 0x00004001, 0x00000001,
3624 0x05000036, 0x001000f2, 0x00000006, 0x00100e46, 0x00000008, 0x05000036, 0x00100022, 0x00000002,
3625 0x0010002a, 0x00000002, 0x01000016, 0x09000037, 0x001000f2, 0x00000003, 0x00100556, 0x00000002,
3626 0x00100e46, 0x00000004, 0x00100e46, 0x00000006, 0x01000015, 0x08000038, 0x001000f2, 0x00000000,
3627 0x00100e46, 0x00000003, 0x00208556, 0x00000000, 0x00000001, 0x01000015, 0x0300001f, 0x0010000a,
3628 0x00000001, 0x08000020, 0x00100012, 0x00000001, 0x0020800a, 0x00000000, 0x00000001, 0x00004001,
3629 0x00000002, 0x0304001f, 0x0010000a, 0x00000001, 0x0900000f, 0x00100012, 0x00000002, 0x00208046,
3630 0x00000000, 0x00000003, 0x00208046, 0x00000000, 0x00000003, 0x0900000f, 0x00100022, 0x00000002,
3631 0x00208ae6, 0x00000000, 0x00000003, 0x00208ae6, 0x00000000, 0x00000003, 0x09000000, 0x00100062,
3632 0x00000001, 0x00208ba6, 0x00000000, 0x00000002, 0x00208106, 0x00000000, 0x00000002, 0x08000000,
3633 0x00100062, 0x00000001, 0x80100656, 0x00000041, 0x00000001, 0x00101106, 0x00000000, 0x0800000f,
3634 0x00100012, 0x00000003, 0x00100596, 0x00000001, 0x00208046, 0x00000000, 0x00000003, 0x0800000f,
3635 0x00100022, 0x00000003, 0x00100596, 0x00000001, 0x00208ae6, 0x00000000, 0x00000003, 0x0700000e,
3636 0x00100062, 0x00000001, 0x00100106, 0x00000003, 0x00100106, 0x00000002, 0x0900000f, 0x00100012,
3637 0x00000003, 0x00208ae6, 0x00000000, 0x00000002, 0x00208046, 0x00000000, 0x00000003, 0x0900000f,
3638 0x00100022, 0x00000003, 0x00208ae6, 0x00000000, 0x00000002, 0x00208ae6, 0x00000000, 0x00000003,
3639 0x0700000e, 0x00100032, 0x00000002, 0x00100046, 0x00000003, 0x00100046, 0x00000002, 0x0700000f,
3640 0x00100082, 0x00000001, 0x00100596, 0x00000001, 0x00100596, 0x00000001, 0x0500004b, 0x00100082,
3641 0x00000001, 0x0010003a, 0x00000001, 0x0700000f, 0x00100022, 0x00000001, 0x00100596, 0x00000001,
3642 0x00100046, 0x00000002, 0x0700000e, 0x00100022, 0x00000001, 0x0010001a, 0x00000001, 0x0010003a,
3643 0x00000001, 0x0700000f, 0x00100042, 0x00000001, 0x00100046, 0x00000002, 0x00100046, 0x00000002,
3644 0x07000000, 0x00100042, 0x00000001, 0x0010002a, 0x00000001, 0x00004001, 0xbf800000, 0x0a000032,
3645 0x00100042, 0x00000001, 0x0010001a, 0x00000001, 0x0010001a, 0x00000001, 0x8010002a, 0x00000041,
3646 0x00000001, 0x0500004b, 0x00100042, 0x00000001, 0x0010002a, 0x00000001, 0x08000000, 0x00100022,
3647 0x00000001, 0x0010002a, 0x00000001, 0x8010001a, 0x00000041, 0x00000001, 0x0700000e, 0x00100022,
3648 0x00000001, 0x0010003a, 0x00000001, 0x0010001a, 0x00000001, 0x0a00002d, 0x001000f2, 0x00000002,
3649 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00107e46, 0x00000002, 0x0a00002d,
3650 0x001000f2, 0x00000003, 0x00004002, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00107e46,
3651 0x00000002, 0x0700001d, 0x00100042, 0x00000001, 0x0010001a, 0x00000001, 0x0010000a, 0x00000002,
3652 0x0304001f, 0x0010002a, 0x00000001, 0x05000036, 0x001000f2, 0x00000004, 0x00100e46, 0x00000003,
3653 0x05000036, 0x001000f2, 0x00000005, 0x00100e46, 0x00000003, 0x05000036, 0x001000f2, 0x00000006,
3654 0x00100e46, 0x00000003, 0x05000036, 0x00100042, 0x00000001, 0x0010000a, 0x00000002, 0x05000036,
3655 0x00100082, 0x00000001, 0x00004001, 0x00000001, 0x05000036, 0x00100022, 0x00000002, 0x00004001,
3656 0x00000000, 0x01000030, 0x08000050, 0x00100042, 0x00000002, 0x0010003a, 0x00000001, 0x0020800a,
3657 0x00000000, 0x00000004, 0x05000036, 0x00100022, 0x00000002, 0x00004001, 0x00000000, 0x03040003,
3658 0x0010002a, 0x00000002, 0x07000029, 0x00100042, 0x00000002, 0x0010003a, 0x00000001, 0x00004001,
3659 0x00000001, 0x0700002d, 0x001000f2, 0x00000007, 0x00100aa6, 0x00000002, 0x00107e46, 0x00000002,
3660 0x0700001e, 0x00100042, 0x00000002, 0x0010002a, 0x00000002, 0x00004001, 0x00000001, 0x0700002d,
3661 0x001000f2, 0x00000008, 0x00100aa6, 0x00000002, 0x00107e46, 0x00000002, 0x0700001d, 0x00100042,
3662 0x00000002, 0x0010001a, 0x00000001, 0x0010002a, 0x00000001, 0x0700001d, 0x00100082, 0x00000002,
3663 0x0010000a, 0x00000007, 0x0010001a, 0x00000001, 0x07000001, 0x00100042, 0x00000002, 0x0010003a,
3664 0x00000002, 0x0010002a, 0x00000002, 0x0304001f, 0x0010002a, 0x00000002, 0x08000000, 0x00100082,
3665 0x00000002, 0x8010002a, 0x00000041, 0x00000001, 0x0010001a, 0x00000001, 0x08000000, 0x00100022,
3666 0x00000007, 0x8010002a, 0x00000041, 0x00000001, 0x0010000a, 0x00000007, 0x0700000e, 0x00100082,
3667 0x00000002, 0x0010003a, 0x00000002, 0x0010001a, 0x00000007, 0x08000000, 0x001000f2, 0x00000009,
3668 0x80100e46, 0x00000041, 0x00000005, 0x00100e46, 0x00000008, 0x09000032, 0x001000f2, 0x00000009,
3669 0x00100ff6, 0x00000002, 0x00100e46, 0x00000009, 0x00100e46, 0x00000005, 0x05000036, 0x001000f2,
3670 0x00000006, 0x00100e46, 0x00000008, 0x05000036, 0x00100022, 0x00000002, 0x00004001, 0xffffffff,
3671 0x05000036, 0x001000f2, 0x00000004, 0x00100e46, 0x00000009, 0x01000002, 0x01000015, 0x05000036,
3672 0x001000f2, 0x00000005, 0x00100e46, 0x00000008, 0x05000036, 0x00100042, 0x00000001, 0x0010000a,
3673 0x00000007, 0x0700001e, 0x00100082, 0x00000001, 0x0010003a, 0x00000001, 0x00004001, 0x00000001,
3674 0x05000036, 0x001000f2, 0x00000006, 0x00100e46, 0x00000008, 0x05000036, 0x00100022, 0x00000002,
3675 0x0010002a, 0x00000002, 0x01000016, 0x09000037, 0x001000f2, 0x00000003, 0x00100556, 0x00000002,
3676 0x00100e46, 0x00000004, 0x00100e46, 0x00000006, 0x01000015, 0x08000038, 0x001000f2, 0x00000000,
3677 0x00100e46, 0x00000003, 0x00208556, 0x00000000, 0x00000001, 0x01000015, 0x0300001f, 0x0010000a,
3678 0x00000001, 0x08000020, 0x00100012, 0x00000001, 0x0020800a, 0x00000000, 0x00000001, 0x00004001,
3679 0x00000003, 0x0304001f, 0x0010000a, 0x00000001, 0x0800000f, 0x00100022, 0x00000001, 0x00101046,
3680 0x00000000, 0x00208046, 0x00000000, 0x00000002, 0x08000000, 0x00100012, 0x00000002, 0x0010001a,
3681 0x00000001, 0x0020802a, 0x00000000, 0x00000002, 0x0800000f, 0x00100022, 0x00000001, 0x00101046,
3682 0x00000000, 0x00208046, 0x00000000, 0x00000003, 0x08000000, 0x00100022, 0x00000002, 0x0010001a,
3683 0x00000001, 0x0020802a, 0x00000000, 0x00000003, 0x09000045, 0x001000f2, 0x00000002, 0x00100046,
3684 0x00000002, 0x00107e46, 0x00000000, 0x00106000, 0x00000000, 0x0a000037, 0x00100082, 0x00000002,
3685 0x0020803a, 0x00000000, 0x00000003, 0x00004001, 0x3f800000, 0x0010003a, 0x00000002, 0x08000038,
3686 0x001000f2, 0x00000000, 0x00100e46, 0x00000002, 0x00208556, 0x00000000, 0x00000001, 0x01000015,
3687 0x05000036, 0x00100012, 0x00000002, 0x00004001, 0x00000000, 0x06000036, 0x00100082, 0x00000002,
3688 0x0020801a, 0x00000000, 0x00000001, 0x09000037, 0x001000f2, 0x00000000, 0x00100006, 0x00000001,
3689 0x00100e46, 0x00000000, 0x00100c06, 0x00000002, 0x01000015, 0x01000015, 0x01000015, 0x0800004f,
3690 0x00100012, 0x00000001, 0x0020800a, 0x00000000, 0x00000005, 0x00004001, 0x00000004, 0x0304001f,
3691 0x0010000a, 0x00000001, 0x09000038, 0x00100012, 0x00000001, 0x0020801a, 0x00000000, 0x00000005,
3692 0x0020803a, 0x00000000, 0x00000006, 0x0404001f, 0x0020800a, 0x00000000, 0x00000005, 0x08000020,
3693 0x00100022, 0x00000001, 0x0020800a, 0x00000000, 0x00000005, 0x00004001, 0x00000001, 0x0304001f,
3694 0x0010001a, 0x00000001, 0x09000000, 0x001000c2, 0x00000001, 0x00101406, 0x00000000, 0x80208406,
3695 0x00000041, 0x00000000, 0x00000006, 0x0a000000, 0x00100032, 0x00000002, 0x80208046, 0x00000041,
3696 0x00000000, 0x00000006, 0x00208ae6, 0x00000000, 0x00000006, 0x0700000f, 0x00100042, 0x00000001,
3697 0x00100046, 0x00000002, 0x00100ae6, 0x00000001, 0x0700000f, 0x00100082, 0x00000001, 0x00100046,
3698 0x00000002, 0x00100046, 0x00000002, 0x0700000e, 0x00100042, 0x00000001, 0x0010002a, 0x00000001,
3699 0x0010003a, 0x00000001, 0x0a00002d, 0x001000f2, 0x00000002, 0x00004002, 0x00000000, 0x00000000,
3700 0x00000000, 0x00000000, 0x00107e46, 0x00000003, 0x0a00002d, 0x001000f2, 0x00000003, 0x00004002,
3701 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00107e46, 0x00000003, 0x0700001d, 0x00100082,
3702 0x00000001, 0x0010002a, 0x00000001, 0x0010000a, 0x00000002, 0x0304001f, 0x0010003a, 0x00000001,
3703 0x05000036, 0x00100082, 0x00000001, 0x0010003a, 0x00000003, 0x05000036, 0x00100062, 0x00000002,
3704 0x00100ff6, 0x00000003, 0x05000036, 0x00100082, 0x00000002, 0x0010000a, 0x00000002, 0x08000036,
3705 0x00100032, 0x00000003, 0x00004002, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x01000030,
3706 0x08000050, 0x00100042, 0x00000003, 0x0010000a, 0x00000003, 0x0020800a, 0x00000000, 0x00000007,
3707 0x05000036, 0x00100022, 0x00000003, 0x00004001, 0x00000000, 0x03040003, 0x0010002a, 0x00000003,
3708 0x07000029, 0x00100042, 0x00000003, 0x0010000a, 0x00000003, 0x00004001, 0x00000001, 0x0700002d,
3709 0x001000f2, 0x00000004, 0x00100aa6, 0x00000003, 0x00107e46, 0x00000003, 0x0700001e, 0x00100042,
3710 0x00000003, 0x0010002a, 0x00000003, 0x00004001, 0x00000001, 0x0700002d, 0x001000f2, 0x00000005,
3711 0x00100aa6, 0x00000003, 0x00107e46, 0x00000003, 0x0700001d, 0x00100042, 0x00000003, 0x0010002a,
3712 0x00000001, 0x0010003a, 0x00000002, 0x0700001d, 0x00100022, 0x00000004, 0x0010000a, 0x00000004,
3713 0x0010002a, 0x00000001, 0x07000001, 0x00100042, 0x00000003, 0x0010002a, 0x00000003, 0x0010001a,
3714 0x00000004, 0x0304001f, 0x0010002a, 0x00000003, 0x08000000, 0x00100022, 0x00000004, 0x0010002a,
3715 0x00000001, 0x8010003a, 0x00000041, 0x00000002, 0x08000000, 0x00100042, 0x00000004, 0x8010003a,
3716 0x00000041, 0x00000002, 0x0010000a, 0x00000004, 0x0700000e, 0x00100022, 0x00000004, 0x0010001a,
3717 0x00000004, 0x0010002a, 0x00000004, 0x08000000, 0x00100042, 0x00000004, 0x8010001a, 0x00000041,
3718 0x00000002, 0x0010003a, 0x00000005, 0x09000032, 0x00100022, 0x00000004, 0x0010001a, 0x00000004,
3719 0x0010002a, 0x00000004, 0x0010001a, 0x00000002, 0x05000036, 0x00100042, 0x00000002, 0x0010003a,
3720 0x00000005, 0x05000036, 0x00100022, 0x00000003, 0x00004001, 0xffffffff, 0x05000036, 0x00100082,
3721 0x00000001, 0x0010001a, 0x00000004, 0x01000002, 0x01000015, 0x05000036, 0x00100022, 0x00000002,
3722 0x0010003a, 0x00000005, 0x05000036, 0x00100082, 0x00000002, 0x0010000a, 0x00000004, 0x0700001e,
3723 0x00100012, 0x00000003, 0x0010000a, 0x00000003, 0x00004001, 0x00000001, 0x05000036, 0x00100042,
3724 0x00000002, 0x0010003a, 0x00000005, 0x05000036, 0x00100032, 0x00000003, 0x00100086, 0x00000003,
3725 0x01000016, 0x09000037, 0x00100042, 0x00000001, 0x0010001a, 0x00000003, 0x0010003a, 0x00000001,
3726 0x0010002a, 0x00000002, 0x01000012, 0x05000036, 0x00100042, 0x00000001, 0x0010003a, 0x00000003,
3727 0x01000015, 0x08000038, 0x00100012, 0x00000001, 0x0010002a, 0x00000001, 0x0020801a, 0x00000000,
3728 0x00000005, 0x01000015, 0x0300001f, 0x0010001a, 0x00000001, 0x08000020, 0x00100022, 0x00000001,
3729 0x0020800a, 0x00000000, 0x00000005, 0x00004001, 0x00000002, 0x0304001f, 0x0010001a, 0x00000001,
3730 0x0900000f, 0x00100012, 0x00000002, 0x00208046, 0x00000000, 0x00000007, 0x00208046, 0x00000000,
3731 0x00000007, 0x0900000f, 0x00100022, 0x00000002, 0x00208ae6, 0x00000000, 0x00000007, 0x00208ae6,
3732 0x00000000, 0x00000007, 0x09000000, 0x001000c2, 0x00000001, 0x00208ea6, 0x00000000, 0x00000006,
3733 0x00208406, 0x00000000, 0x00000006, 0x08000000, 0x001000c2, 0x00000001, 0x80100ea6, 0x00000041,
3734 0x00000001, 0x00101406, 0x00000000, 0x0800000f, 0x00100012, 0x00000003, 0x00100ae6, 0x00000001,
3735 0x00208046, 0x00000000, 0x00000007, 0x0800000f, 0x00100022, 0x00000003, 0x00100ae6, 0x00000001,
3736 0x00208ae6, 0x00000000, 0x00000007, 0x0700000e, 0x001000c2, 0x00000001, 0x00100406, 0x00000003,
3737 0x00100406, 0x00000002, 0x0900000f, 0x00100012, 0x00000003, 0x00208ae6, 0x00000000, 0x00000006,
3738 0x00208046, 0x00000000, 0x00000007, 0x0900000f, 0x00100022, 0x00000003, 0x00208ae6, 0x00000000,
3739 0x00000006, 0x00208ae6, 0x00000000, 0x00000007, 0x0700000e, 0x00100032, 0x00000002, 0x00100046,
3740 0x00000003, 0x00100046, 0x00000002, 0x0700000f, 0x00100042, 0x00000002, 0x00100ae6, 0x00000001,
3741 0x00100ae6, 0x00000001, 0x0500004b, 0x00100042, 0x00000002, 0x0010002a, 0x00000002, 0x0700000f,
3742 0x00100042, 0x00000001, 0x00100ae6, 0x00000001, 0x00100046, 0x00000002, 0x0700000e, 0x00100042,
3743 0x00000001, 0x0010002a, 0x00000001, 0x0010002a, 0x00000002, 0x0700000f, 0x00100082, 0x00000001,
3744 0x00100046, 0x00000002, 0x00100046, 0x00000002, 0x07000000, 0x00100082, 0x00000001, 0x0010003a,
3745 0x00000001, 0x00004001, 0xbf800000, 0x0a000032, 0x00100082, 0x00000001, 0x0010002a, 0x00000001,
3746 0x0010002a, 0x00000001, 0x8010003a, 0x00000041, 0x00000001, 0x0500004b, 0x00100082, 0x00000001,
3747 0x0010003a, 0x00000001, 0x08000000, 0x00100042, 0x00000001, 0x0010003a, 0x00000001, 0x8010002a,
3748 0x00000041, 0x00000001, 0x0700000e, 0x00100042, 0x00000001, 0x0010002a, 0x00000002, 0x0010002a,
3749 0x00000001, 0x0a00002d, 0x001000f2, 0x00000002, 0x00004002, 0x00000000, 0x00000000, 0x00000000,
3750 0x00000000, 0x00107e46, 0x00000003, 0x0a00002d, 0x001000f2, 0x00000003, 0x00004002, 0x00000001,
3751 0x00000001, 0x00000001, 0x00000001, 0x00107e46, 0x00000003, 0x0700001d, 0x00100082, 0x00000001,
3752 0x0010002a, 0x00000001, 0x0010000a, 0x00000002, 0x0304001f, 0x0010003a, 0x00000001, 0x05000036,
3753 0x00100082, 0x00000001, 0x0010003a, 0x00000003, 0x05000036, 0x00100062, 0x00000002, 0x00100ff6,
3754 0x00000003, 0x05000036, 0x00100082, 0x00000002, 0x0010000a, 0x00000002, 0x08000036, 0x00100032,
3755 0x00000003, 0x00004002, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x01000030, 0x08000050,
3756 0x00100042, 0x00000003, 0x0010000a, 0x00000003, 0x0020800a, 0x00000000, 0x00000008, 0x05000036,
3757 0x00100022, 0x00000003, 0x00004001, 0x00000000, 0x03040003, 0x0010002a, 0x00000003, 0x07000029,
3758 0x00100042, 0x00000003, 0x0010000a, 0x00000003, 0x00004001, 0x00000001, 0x0700002d, 0x001000f2,
3759 0x00000004, 0x00100aa6, 0x00000003, 0x00107e46, 0x00000003, 0x0700001e, 0x00100042, 0x00000003,
3760 0x0010002a, 0x00000003, 0x00004001, 0x00000001, 0x0700002d, 0x001000f2, 0x00000005, 0x00100aa6,
3761 0x00000003, 0x00107e46, 0x00000003, 0x0700001d, 0x00100042, 0x00000003, 0x0010002a, 0x00000001,
3762 0x0010003a, 0x00000002, 0x0700001d, 0x00100022, 0x00000004, 0x0010000a, 0x00000004, 0x0010002a,
3763 0x00000001, 0x07000001, 0x00100042, 0x00000003, 0x0010002a, 0x00000003, 0x0010001a, 0x00000004,
3764 0x0304001f, 0x0010002a, 0x00000003, 0x08000000, 0x00100022, 0x00000004, 0x0010002a, 0x00000001,
3765 0x8010003a, 0x00000041, 0x00000002, 0x08000000, 0x00100042, 0x00000004, 0x8010003a, 0x00000041,
3766 0x00000002, 0x0010000a, 0x00000004, 0x0700000e, 0x00100022, 0x00000004, 0x0010001a, 0x00000004,
3767 0x0010002a, 0x00000004, 0x08000000, 0x00100042, 0x00000004, 0x8010001a, 0x00000041, 0x00000002,
3768 0x0010003a, 0x00000005, 0x09000032, 0x00100022, 0x00000004, 0x0010001a, 0x00000004, 0x0010002a,
3769 0x00000004, 0x0010001a, 0x00000002, 0x05000036, 0x00100042, 0x00000002, 0x0010003a, 0x00000005,
3770 0x05000036, 0x00100022, 0x00000003, 0x00004001, 0xffffffff, 0x05000036, 0x00100082, 0x00000001,
3771 0x0010001a, 0x00000004, 0x01000002, 0x01000015, 0x05000036, 0x00100022, 0x00000002, 0x0010003a,
3772 0x00000005, 0x05000036, 0x00100082, 0x00000002, 0x0010000a, 0x00000004, 0x0700001e, 0x00100012,
3773 0x00000003, 0x0010000a, 0x00000003, 0x00004001, 0x00000001, 0x05000036, 0x00100042, 0x00000002,
3774 0x0010003a, 0x00000005, 0x05000036, 0x00100032, 0x00000003, 0x00100086, 0x00000003, 0x01000016,
3775 0x09000037, 0x00100042, 0x00000001, 0x0010001a, 0x00000003, 0x0010003a, 0x00000001, 0x0010002a,
3776 0x00000002, 0x01000012, 0x05000036, 0x00100042, 0x00000001, 0x0010003a, 0x00000003, 0x01000015,
3777 0x08000038, 0x00100012, 0x00000001, 0x0010002a, 0x00000001, 0x0020801a, 0x00000000, 0x00000005,
3778 0x01000015, 0x0300001f, 0x0010001a, 0x00000001, 0x08000020, 0x00100022, 0x00000001, 0x0020800a,
3779 0x00000000, 0x00000005, 0x00004001, 0x00000003, 0x0304001f, 0x0010001a, 0x00000001, 0x0800000f,
3780 0x00100042, 0x00000001, 0x00101046, 0x00000000, 0x00208046, 0x00000000, 0x00000006, 0x08000000,
3781 0x00100012, 0x00000002, 0x0010002a, 0x00000001, 0x0020802a, 0x00000000, 0x00000006, 0x0800000f,
3782 0x00100042, 0x00000001, 0x00101046, 0x00000000, 0x00208046, 0x00000000, 0x00000007, 0x08000000,
3783 0x00100022, 0x00000002, 0x0010002a, 0x00000001, 0x0020802a, 0x00000000, 0x00000007, 0x09000045,
3784 0x001000f2, 0x00000002, 0x00100046, 0x00000002, 0x00107e46, 0x00000001, 0x00106000, 0x00000001,
3785 0x0a000037, 0x00100042, 0x00000001, 0x0020803a, 0x00000000, 0x00000007, 0x00004001, 0x3f800000,
3786 0x0010003a, 0x00000002, 0x08000038, 0x00100012, 0x00000001, 0x0010002a, 0x00000001, 0x0020801a,
3787 0x00000000, 0x00000005, 0x01000015, 0x0a000037, 0x00100012, 0x00000001, 0x0010001a, 0x00000001,
3788 0x0010000a, 0x00000001, 0x0020801a, 0x00000000, 0x00000005, 0x01000015, 0x01000015, 0x01000015,
3789 0x07000038, 0x001020f2, 0x00000000, 0x00100e46, 0x00000000, 0x00100006, 0x00000001, 0x01000012,
3790 0x05000036, 0x001020f2, 0x00000000, 0x00100e46, 0x00000000, 0x01000015, 0x0404001f, 0x0020800a,
3791 0x00000000, 0x00000000, 0x0500000b, 0x00100032, 0x00000000, 0x00101046, 0x00000001, 0x0500000c,
3792 0x001000c2, 0x00000000, 0x00101406, 0x00000001, 0x08000027, 0x00100012, 0x00000001, 0x0020801a,
3793 0x00000000, 0x00000000, 0x00004001, 0x00000000, 0x0500003b, 0x00100022, 0x00000001, 0x0010000a,
3794 0x00000001, 0x07000000, 0x001000c2, 0x00000001, 0x00101406, 0x00000001, 0x00101406, 0x00000001,
3795 0x07000038, 0x001000f2, 0x00000002, 0x00100d86, 0x00000000, 0x00100fa6, 0x00000001, 0x0a000032,
3796 0x00100032, 0x00000000, 0x00100aa6, 0x00000001, 0x00100086, 0x00000000, 0x801005d6, 0x00000041,
3797 0x00000000, 0x0700000f, 0x00100042, 0x00000000, 0x00100046, 0x00000000, 0x00101ae6, 0x00000001,
3798 0x07000031, 0x00100042, 0x00000000, 0x0010002a, 0x00000000, 0x00004001, 0x00000000, 0x07000001,
3799 0x00100042, 0x00000000, 0x0010001a, 0x00000001, 0x0010002a, 0x00000000, 0x0304000d, 0x0010002a,
3800 0x00000000, 0x07000038, 0x00100062, 0x00000000, 0x00100556, 0x00000000, 0x00101106, 0x00000003,
3801 0x09000032, 0x00100032, 0x00000000, 0x00101046, 0x00000002, 0x00100006, 0x00000000, 0x00100596,
3802 0x00000000, 0x0700000f, 0x00100012, 0x00000000, 0x00100046, 0x00000000, 0x00100046, 0x00000000,
3803 0x0500004b, 0x00100012, 0x00000000, 0x0010000a, 0x00000000, 0x07000038, 0x00100062, 0x00000000,
3804 0x00101106, 0x00000001, 0x00101106, 0x00000001, 0x0a000032, 0x00100082, 0x00000000, 0x0010100a,
3805 0x00000001, 0x0010100a, 0x00000001, 0x8010101a, 0x00000041, 0x00000001, 0x08000000, 0x00100012,
3806 0x00000000, 0x8010003a, 0x000000c1, 0x00000000, 0x0010000a, 0x00000000, 0x07000031, 0x00100012,
3807 0x00000000, 0x0010000a, 0x00000000, 0x00004001, 0x00000000, 0x07000001, 0x00100012, 0x00000000,
3808 0x0010001a, 0x00000001, 0x0010000a, 0x00000000, 0x0304000d, 0x0010000a, 0x00000000, 0x07000000,
3809 0x00100092, 0x00000000, 0x00100ea6, 0x00000002, 0x00100406, 0x00000002, 0x0700000f, 0x00100022,
3810 0x00000001, 0x001000c6, 0x00000000, 0x00101ae6, 0x00000001, 0x07000031, 0x00100022, 0x00000001,
3811 0x0010001a, 0x00000001, 0x00004001, 0x00000000, 0x07000001, 0x00100022, 0x00000001, 0x0010000a,
3812 0x00000001, 0x0010001a, 0x00000001, 0x0304000d, 0x0010001a, 0x00000001, 0x07000038, 0x00100062,
3813 0x00000001, 0x00100ff6, 0x00000000, 0x00101106, 0x00000003, 0x09000032, 0x00100092, 0x00000000,
3814 0x00101406, 0x00000002, 0x00100006, 0x00000000, 0x00100956, 0x00000001, 0x0700000f, 0x00100012,
3815 0x00000000, 0x001000c6, 0x00000000, 0x001000c6, 0x00000000, 0x0500004b, 0x00100012, 0x00000000,
3816 0x0010000a, 0x00000000, 0x07000000, 0x00100022, 0x00000000, 0x0010002a, 0x00000000, 0x0010001a,
3817 0x00000000, 0x07000000, 0x00100022, 0x00000000, 0x0010001a, 0x00000000, 0x00004001, 0xbf800000,
3818 0x08000000, 0x00100012, 0x00000000, 0x8010001a, 0x000000c1, 0x00000000, 0x0010000a, 0x00000000,
3819 0x07000031, 0x00100012, 0x00000000, 0x0010000a, 0x00000000, 0x00004001, 0x00000000, 0x07000001,
3820 0x00100012, 0x00000000, 0x0010000a, 0x00000001, 0x0010000a, 0x00000000, 0x0304000d, 0x0010000a,
3821 0x00000000, 0x01000012, 0x08000027, 0x00100012, 0x00000000, 0x0020801a, 0x00000000, 0x00000000,
3822 0x00004001, 0x00000000, 0x0500003b, 0x00100022, 0x00000000, 0x0010000a, 0x00000000, 0x07000038,
3823 0x001000c2, 0x00000000, 0x00101406, 0x00000001, 0x00101406, 0x00000001, 0x0a000032, 0x00100012,
3824 0x00000001, 0x0010100a, 0x00000001, 0x0010100a, 0x00000001, 0x8010101a, 0x00000041, 0x00000001,
3825 0x07000038, 0x00100012, 0x00000001, 0x0010000a, 0x00000001, 0x0010102a, 0x00000001, 0x07000031,
3826 0x00100012, 0x00000001, 0x0010000a, 0x00000001, 0x00004001, 0x00000000, 0x07000001, 0x00100022,
3827 0x00000000, 0x0010001a, 0x00000000, 0x0010000a, 0x00000001, 0x0304000d, 0x0010001a, 0x00000000,
3828 0x07000000, 0x00100022, 0x00000000, 0x0010003a, 0x00000000, 0x0010002a, 0x00000000, 0x07000000,
3829 0x00100022, 0x00000000, 0x0010001a, 0x00000000, 0x00004001, 0xbf800000, 0x07000038, 0x00100022,
3830 0x00000000, 0x0010001a, 0x00000000, 0x0010102a, 0x00000001, 0x07000031, 0x00100022, 0x00000000,
3831 0x0010001a, 0x00000000, 0x00004001, 0x00000000, 0x07000001, 0x00100012, 0x00000000, 0x0010000a,
3832 0x00000000, 0x0010001a, 0x00000000, 0x0304000d, 0x0010000a, 0x00000000, 0x01000015, 0x0100003e,
3834 static const struct shape_info
3836 enum d2d_shape_type shape_type;
3837 const D3D10_INPUT_ELEMENT_DESC *il_desc;
3838 unsigned int il_element_count;
3839 const void *vs_code;
3840 size_t vs_code_size;
3842 shape_info[] =
3844 {D2D_SHAPE_TYPE_OUTLINE, il_desc_outline, ARRAY_SIZE(il_desc_outline),
3845 vs_code_outline, sizeof(vs_code_outline)},
3846 {D2D_SHAPE_TYPE_BEZIER_OUTLINE, il_desc_curve_outline, ARRAY_SIZE(il_desc_curve_outline),
3847 vs_code_bezier_outline, sizeof(vs_code_bezier_outline)},
3848 {D2D_SHAPE_TYPE_ARC_OUTLINE, il_desc_curve_outline, ARRAY_SIZE(il_desc_curve_outline),
3849 vs_code_arc_outline, sizeof(vs_code_arc_outline)},
3850 {D2D_SHAPE_TYPE_TRIANGLE, il_desc_triangle, ARRAY_SIZE(il_desc_triangle),
3851 vs_code_triangle, sizeof(vs_code_triangle)},
3852 {D2D_SHAPE_TYPE_CURVE, il_desc_curve, ARRAY_SIZE(il_desc_curve),
3853 vs_code_curve, sizeof(vs_code_curve)},
3855 static const struct
3857 float x, y;
3859 quad[] =
3861 {-1.0f, 1.0f},
3862 {-1.0f, -1.0f},
3863 { 1.0f, 1.0f},
3864 { 1.0f, -1.0f},
3866 static const UINT16 indices[] = {0, 1, 2, 2, 1, 3};
3868 render_target->ID2D1DeviceContext_iface.lpVtbl = &d2d_device_context_vtbl;
3869 render_target->ID2D1GdiInteropRenderTarget_iface.lpVtbl = &d2d_gdi_interop_render_target_vtbl;
3870 render_target->IDWriteTextRenderer_iface.lpVtbl = &d2d_text_renderer_vtbl;
3871 render_target->IUnknown_iface.lpVtbl = &d2d_device_context_inner_unknown_vtbl;
3872 render_target->refcount = 1;
3873 ID2D1Device_GetFactory(device, &render_target->factory);
3874 render_target->device = device;
3875 ID2D1Device_AddRef(render_target->device);
3877 render_target->outer_unknown = outer_unknown ? outer_unknown : &render_target->IUnknown_iface;
3878 render_target->ops = ops;
3880 device_impl = unsafe_impl_from_ID2D1Device(device);
3881 if (FAILED(hr = IDXGIDevice_QueryInterface(device_impl->dxgi_device,
3882 &IID_ID3D10Device, (void **)&render_target->d3d_device)))
3884 WARN("Failed to get device interface, hr %#x.\n", hr);
3885 ID2D1Factory_Release(render_target->factory);
3886 return hr;
3889 if (FAILED(hr = D3D10StateBlockMaskEnableAll(&state_mask)))
3891 WARN("Failed to create stateblock mask, hr %#x.\n", hr);
3892 goto err;
3895 if (FAILED(hr = D3D10CreateStateBlock(render_target->d3d_device, &state_mask, &render_target->stateblock)))
3897 WARN("Failed to create stateblock, hr %#x.\n", hr);
3898 goto err;
3901 for (i = 0; i < ARRAY_SIZE(shape_info); ++i)
3903 const struct shape_info *si = &shape_info[i];
3905 if (FAILED(hr = ID3D10Device_CreateInputLayout(render_target->d3d_device, si->il_desc, si->il_element_count,
3906 si->vs_code, si->vs_code_size, &render_target->shape_resources[si->shape_type].il)))
3908 WARN("Failed to create input layout for shape type %#x, hr %#x.\n", si->shape_type, hr);
3909 goto err;
3912 if (FAILED(hr = ID3D10Device_CreateVertexShader(render_target->d3d_device, si->vs_code,
3913 si->vs_code_size, &render_target->shape_resources[si->shape_type].vs)))
3915 WARN("Failed to create vertex shader for shape type %#x, hr %#x.\n", si->shape_type, hr);
3916 goto err;
3921 if (FAILED(hr = ID3D10Device_CreatePixelShader(render_target->d3d_device,
3922 ps_code, sizeof(ps_code), &render_target->ps)))
3924 WARN("Failed to create pixel shader, hr %#x.\n", hr);
3925 goto err;
3928 buffer_desc.ByteWidth = sizeof(indices);
3929 buffer_desc.Usage = D3D10_USAGE_DEFAULT;
3930 buffer_desc.BindFlags = D3D10_BIND_INDEX_BUFFER;
3931 buffer_desc.CPUAccessFlags = 0;
3932 buffer_desc.MiscFlags = 0;
3934 buffer_data.pSysMem = indices;
3935 buffer_data.SysMemPitch = 0;
3936 buffer_data.SysMemSlicePitch = 0;
3938 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->d3d_device,
3939 &buffer_desc, &buffer_data, &render_target->ib)))
3941 WARN("Failed to create clear index buffer, hr %#x.\n", hr);
3942 goto err;
3945 buffer_desc.ByteWidth = sizeof(quad);
3946 buffer_desc.BindFlags = D3D10_BIND_VERTEX_BUFFER;
3947 buffer_data.pSysMem = quad;
3949 render_target->vb_stride = sizeof(*quad);
3950 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->d3d_device,
3951 &buffer_desc, &buffer_data, &render_target->vb)))
3953 WARN("Failed to create clear vertex buffer, hr %#x.\n", hr);
3954 goto err;
3957 rs_desc.FillMode = D3D10_FILL_SOLID;
3958 rs_desc.CullMode = D3D10_CULL_NONE;
3959 rs_desc.FrontCounterClockwise = FALSE;
3960 rs_desc.DepthBias = 0;
3961 rs_desc.DepthBiasClamp = 0.0f;
3962 rs_desc.SlopeScaledDepthBias = 0.0f;
3963 rs_desc.DepthClipEnable = TRUE;
3964 rs_desc.ScissorEnable = TRUE;
3965 rs_desc.MultisampleEnable = FALSE;
3966 rs_desc.AntialiasedLineEnable = FALSE;
3967 if (FAILED(hr = ID3D10Device_CreateRasterizerState(render_target->d3d_device, &rs_desc, &render_target->rs)))
3969 WARN("Failed to create clear rasterizer state, hr %#x.\n", hr);
3970 goto err;
3973 if (FAILED(hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED,
3974 &IID_IDWriteFactory, (IUnknown **)&dwrite_factory)))
3976 ERR("Failed to create dwrite factory, hr %#x.\n", hr);
3977 goto err;
3980 hr = IDWriteFactory_CreateRenderingParams(dwrite_factory, &render_target->default_text_rendering_params);
3981 IDWriteFactory_Release(dwrite_factory);
3982 if (FAILED(hr))
3984 ERR("Failed to create default text rendering parameters, hr %#x.\n", hr);
3985 goto err;
3988 render_target->drawing_state.transform = identity;
3990 if (!d2d_clip_stack_init(&render_target->clip_stack))
3992 WARN("Failed to initialize clip stack.\n");
3993 hr = E_FAIL;
3994 goto err;
3997 render_target->desc.dpiX = 96.0f;
3998 render_target->desc.dpiY = 96.0f;
4000 return S_OK;
4002 err:
4003 if (render_target->default_text_rendering_params)
4004 IDWriteRenderingParams_Release(render_target->default_text_rendering_params);
4005 if (render_target->rs)
4006 ID3D10RasterizerState_Release(render_target->rs);
4007 if (render_target->vb)
4008 ID3D10Buffer_Release(render_target->vb);
4009 if (render_target->ib)
4010 ID3D10Buffer_Release(render_target->ib);
4011 if (render_target->ps)
4012 ID3D10PixelShader_Release(render_target->ps);
4013 for (i = 0; i < D2D_SHAPE_TYPE_COUNT; ++i)
4015 if (render_target->shape_resources[i].vs)
4016 ID3D10VertexShader_Release(render_target->shape_resources[i].vs);
4017 if (render_target->shape_resources[i].il)
4018 ID3D10InputLayout_Release(render_target->shape_resources[i].il);
4020 if (render_target->stateblock)
4021 render_target->stateblock->lpVtbl->Release(render_target->stateblock);
4022 if (render_target->d3d_device)
4023 ID3D10Device_Release(render_target->d3d_device);
4024 ID2D1Device_Release(render_target->device);
4025 ID2D1Factory_Release(render_target->factory);
4026 return hr;
4029 HRESULT d2d_d3d_create_render_target(ID2D1Device *device, IDXGISurface *surface, IUnknown *outer_unknown,
4030 const struct d2d_device_context_ops *ops, const D2D1_RENDER_TARGET_PROPERTIES *desc, void **render_target)
4032 D2D1_BITMAP_PROPERTIES1 bitmap_desc;
4033 struct d2d_device_context *object;
4034 ID2D1Bitmap1 *bitmap;
4035 HRESULT hr;
4037 if (desc->type != D2D1_RENDER_TARGET_TYPE_DEFAULT && desc->type != D2D1_RENDER_TARGET_TYPE_HARDWARE)
4038 WARN("Ignoring render target type %#x.\n", desc->type);
4039 if (desc->usage != D2D1_RENDER_TARGET_USAGE_NONE)
4040 FIXME("Ignoring render target usage %#x.\n", desc->usage);
4041 if (desc->minLevel != D2D1_FEATURE_LEVEL_DEFAULT)
4042 WARN("Ignoring feature level %#x.\n", desc->minLevel);
4044 bitmap_desc.dpiX = desc->dpiX;
4045 bitmap_desc.dpiY = desc->dpiY;
4047 if (bitmap_desc.dpiX == 0.0f && bitmap_desc.dpiY == 0.0f)
4049 bitmap_desc.dpiX = 96.0f;
4050 bitmap_desc.dpiY = 96.0f;
4052 else if (bitmap_desc.dpiX <= 0.0f || bitmap_desc.dpiY <= 0.0f)
4053 return E_INVALIDARG;
4055 if (!(object = heap_alloc_zero(sizeof(*object))))
4056 return E_OUTOFMEMORY;
4058 if (FAILED(hr = d2d_device_context_init(object, device, outer_unknown, ops)))
4060 WARN("Failed to initialize render target, hr %#x.\n", hr);
4061 heap_free(object);
4062 return hr;
4065 ID2D1DeviceContext_SetDpi(&object->ID2D1DeviceContext_iface, bitmap_desc.dpiX, bitmap_desc.dpiY);
4067 if (surface)
4069 bitmap_desc.pixelFormat = desc->pixelFormat;
4070 bitmap_desc.bitmapOptions = D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW;
4071 bitmap_desc.colorContext = NULL;
4073 if (FAILED(hr = ID2D1DeviceContext_CreateBitmapFromDxgiSurface(&object->ID2D1DeviceContext_iface,
4074 surface, &bitmap_desc, &bitmap)))
4076 WARN("Failed to create target bitmap, hr %#x.\n", hr);
4077 IUnknown_Release(&object->IUnknown_iface);
4078 heap_free(object);
4079 return hr;
4082 ID2D1DeviceContext_SetTarget(&object->ID2D1DeviceContext_iface, (ID2D1Image *)bitmap);
4083 ID2D1Bitmap1_Release(bitmap);
4085 else
4086 object->desc.pixelFormat = desc->pixelFormat;
4088 TRACE("Created render target %p.\n", object);
4089 *render_target = outer_unknown ? &object->IUnknown_iface : (IUnknown *)&object->ID2D1DeviceContext_iface;
4091 return S_OK;
4094 static HRESULT WINAPI d2d_device_QueryInterface(ID2D1Device *iface, REFIID iid, void **out)
4096 TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
4098 if (IsEqualGUID(iid, &IID_ID2D1Device)
4099 || IsEqualGUID(iid, &IID_ID2D1Resource)
4100 || IsEqualGUID(iid, &IID_IUnknown))
4102 ID2D1Device_AddRef(iface);
4103 *out = iface;
4104 return S_OK;
4107 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
4109 *out = NULL;
4110 return E_NOINTERFACE;
4113 static ULONG WINAPI d2d_device_AddRef(ID2D1Device *iface)
4115 struct d2d_device *device = impl_from_ID2D1Device(iface);
4116 ULONG refcount = InterlockedIncrement(&device->refcount);
4118 TRACE("%p increasing refcount to %u.\n", iface, refcount);
4120 return refcount;
4123 static ULONG WINAPI d2d_device_Release(ID2D1Device *iface)
4125 struct d2d_device *device = impl_from_ID2D1Device(iface);
4126 ULONG refcount = InterlockedDecrement(&device->refcount);
4128 TRACE("%p decreasing refcount to %u.\n", iface, refcount);
4130 if (!refcount)
4132 IDXGIDevice_Release(device->dxgi_device);
4133 ID2D1Factory1_Release(device->factory);
4134 heap_free(device);
4137 return refcount;
4140 static void WINAPI d2d_device_GetFactory(ID2D1Device *iface, ID2D1Factory **factory)
4142 struct d2d_device *device = impl_from_ID2D1Device(iface);
4144 TRACE("iface %p, factory %p.\n", iface, factory);
4146 *factory = (ID2D1Factory *)device->factory;
4147 ID2D1Factory1_AddRef(device->factory);
4150 static HRESULT WINAPI d2d_device_CreateDeviceContext(ID2D1Device *iface, D2D1_DEVICE_CONTEXT_OPTIONS options,
4151 ID2D1DeviceContext **context)
4153 struct d2d_device_context *object;
4154 HRESULT hr;
4156 TRACE("iface %p, options %#x, context %p.\n", iface, options, context);
4158 if (options)
4159 FIXME("Options are ignored %#x.\n", options);
4161 if (!(object = heap_alloc_zero(sizeof(*object))))
4162 return E_OUTOFMEMORY;
4164 if (FAILED(hr = d2d_device_context_init(object, iface, NULL, NULL)))
4166 WARN("Failed to initialize device context, hr %#x.\n", hr);
4167 heap_free(object);
4168 return hr;
4171 TRACE("Created device context %p.\n", object);
4172 *context = &object->ID2D1DeviceContext_iface;
4174 return S_OK;
4177 static HRESULT WINAPI d2d_device_CreatePrintControl(ID2D1Device *iface, IWICImagingFactory *wic_factory,
4178 IPrintDocumentPackageTarget *document_target, const D2D1_PRINT_CONTROL_PROPERTIES *desc,
4179 ID2D1PrintControl **print_control)
4181 FIXME("iface %p, wic_factory %p, document_target %p, desc %p, print_control %p stub!\n", iface, wic_factory,
4182 document_target, desc, print_control);
4184 return E_NOTIMPL;
4187 static void WINAPI d2d_device_SetMaximumTextureMemory(ID2D1Device *iface, UINT64 max_texture_memory)
4189 FIXME("iface %p, max_texture_memory %s stub!\n", iface, wine_dbgstr_longlong(max_texture_memory));
4192 static UINT64 WINAPI d2d_device_GetMaximumTextureMemory(ID2D1Device *iface)
4194 FIXME("iface %p stub!\n", iface);
4196 return 0;
4199 static HRESULT WINAPI d2d_device_ClearResources(ID2D1Device *iface, UINT msec_since_use)
4201 FIXME("iface %p, msec_since_use %u stub!\n", iface, msec_since_use);
4203 return E_NOTIMPL;
4206 static const struct ID2D1DeviceVtbl d2d_device_vtbl =
4208 d2d_device_QueryInterface,
4209 d2d_device_AddRef,
4210 d2d_device_Release,
4211 d2d_device_GetFactory,
4212 d2d_device_CreateDeviceContext,
4213 d2d_device_CreatePrintControl,
4214 d2d_device_SetMaximumTextureMemory,
4215 d2d_device_GetMaximumTextureMemory,
4216 d2d_device_ClearResources,
4219 static struct d2d_device *unsafe_impl_from_ID2D1Device(ID2D1Device *iface)
4221 if (!iface)
4222 return NULL;
4223 assert(iface->lpVtbl == &d2d_device_vtbl);
4224 return CONTAINING_RECORD(iface, struct d2d_device, ID2D1Device_iface);
4227 void d2d_device_init(struct d2d_device *device, ID2D1Factory1 *iface, IDXGIDevice *dxgi_device)
4229 device->ID2D1Device_iface.lpVtbl = &d2d_device_vtbl;
4230 device->refcount = 1;
4231 device->factory = iface;
4232 ID2D1Factory1_AddRef(device->factory);
4233 device->dxgi_device = dxgi_device;
4234 IDXGIDevice_AddRef(device->dxgi_device);