comctl32/tests: Flush events before testing edit control IME messages.
[wine.git] / dlls / d2d1 / device.c
blob72781a48d1066963fead18024b9c13b9b4ed68b5
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(ID2D1Device1 *iface)
40 return CONTAINING_RECORD(iface, struct d2d_device, ID2D1Device1_iface);
43 static struct d2d_device *unsafe_impl_from_ID2D1Device(ID2D1Device1 *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 = malloc(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 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 ID3D11Buffer *ib, unsigned int index_count, ID3D11Buffer *vb, unsigned int vb_stride,
122 struct d2d_brush *brush, struct d2d_brush *opacity_brush)
124 struct d2d_shape_resources *shape_resources = &render_target->shape_resources[shape_type];
125 ID3DDeviceContextState *prev_state;
126 ID3D11Device1 *device = render_target->d3d_device;
127 ID3D11DeviceContext1 *context;
128 ID3D11Buffer *vs_cb = render_target->vs_cb, *ps_cb = render_target->ps_cb;
129 D3D11_RECT scissor_rect;
130 unsigned int offset;
131 D3D11_VIEWPORT vp;
133 vp.TopLeftX = 0;
134 vp.TopLeftY = 0;
135 vp.Width = render_target->pixel_size.width;
136 vp.Height = render_target->pixel_size.height;
137 vp.MinDepth = 0.0f;
138 vp.MaxDepth = 1.0f;
140 ID3D11Device1_GetImmediateContext1(device, &context);
141 ID3D11DeviceContext1_SwapDeviceContextState(context, render_target->d3d_state, &prev_state);
143 ID3D11DeviceContext1_IASetInputLayout(context, shape_resources->il);
144 ID3D11DeviceContext1_IASetPrimitiveTopology(context, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
145 ID3D11DeviceContext1_IASetIndexBuffer(context, ib, DXGI_FORMAT_R16_UINT, 0);
146 offset = 0;
147 ID3D11DeviceContext1_IASetVertexBuffers(context, 0, 1, &vb, &vb_stride, &offset);
148 ID3D11DeviceContext1_VSSetConstantBuffers(context, 0, 1, &vs_cb);
149 ID3D11DeviceContext1_VSSetShader(context, shape_resources->vs, NULL, 0);
150 ID3D11DeviceContext1_PSSetConstantBuffers(context, 0, 1, &ps_cb);
151 ID3D11DeviceContext1_PSSetShader(context, render_target->ps, NULL, 0);
152 ID3D11DeviceContext1_RSSetViewports(context, 1, &vp);
153 if (render_target->clip_stack.count)
155 const D2D1_RECT_F *clip_rect;
157 clip_rect = &render_target->clip_stack.stack[render_target->clip_stack.count - 1];
158 scissor_rect.left = ceilf(clip_rect->left - 0.5f);
159 scissor_rect.top = ceilf(clip_rect->top - 0.5f);
160 scissor_rect.right = ceilf(clip_rect->right - 0.5f);
161 scissor_rect.bottom = ceilf(clip_rect->bottom - 0.5f);
163 else
165 scissor_rect.left = 0.0f;
166 scissor_rect.top = 0.0f;
167 scissor_rect.right = render_target->pixel_size.width;
168 scissor_rect.bottom = render_target->pixel_size.height;
170 ID3D11DeviceContext1_RSSetScissorRects(context, 1, &scissor_rect);
171 ID3D11DeviceContext1_RSSetState(context, render_target->rs);
172 ID3D11DeviceContext1_OMSetRenderTargets(context, 1, &render_target->target.bitmap->rtv, NULL);
173 if (brush)
175 ID3D11DeviceContext1_OMSetBlendState(context, render_target->bs, NULL, D3D11_DEFAULT_SAMPLE_MASK);
176 d2d_brush_bind_resources(brush, render_target, 0);
178 else
180 ID3D11DeviceContext1_OMSetBlendState(context, NULL, NULL, D3D11_DEFAULT_SAMPLE_MASK);
182 if (opacity_brush)
183 d2d_brush_bind_resources(opacity_brush, render_target, 1);
185 if (ib)
186 ID3D11DeviceContext1_DrawIndexed(context, index_count, 0, 0);
187 else
188 ID3D11DeviceContext1_Draw(context, index_count, 0);
190 ID3D11DeviceContext1_SwapDeviceContextState(context, prev_state, NULL);
191 ID3D11DeviceContext1_Release(context);
192 ID3DDeviceContextState_Release(prev_state);
195 static void d2d_device_context_set_error(struct d2d_device_context *context, HRESULT code)
197 context->error.code = code;
198 context->error.tag1 = context->drawing_state.tag1;
199 context->error.tag2 = context->drawing_state.tag2;
202 static inline struct d2d_device_context *impl_from_IUnknown(IUnknown *iface)
204 return CONTAINING_RECORD(iface, struct d2d_device_context, IUnknown_iface);
207 static inline struct d2d_device_context *impl_from_ID2D1DeviceContext(ID2D1DeviceContext1 *iface)
209 return CONTAINING_RECORD(iface, struct d2d_device_context, ID2D1DeviceContext1_iface);
212 static HRESULT STDMETHODCALLTYPE d2d_device_context_inner_QueryInterface(IUnknown *iface, REFIID iid, void **out)
214 struct d2d_device_context *context = impl_from_IUnknown(iface);
216 TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
218 if (IsEqualGUID(iid, &IID_ID2D1DeviceContext1)
219 || IsEqualGUID(iid, &IID_ID2D1DeviceContext)
220 || IsEqualGUID(iid, &IID_ID2D1RenderTarget)
221 || IsEqualGUID(iid, &IID_ID2D1Resource)
222 || IsEqualGUID(iid, &IID_IUnknown))
224 ID2D1DeviceContext1_AddRef(&context->ID2D1DeviceContext1_iface);
225 *out = &context->ID2D1DeviceContext1_iface;
226 return S_OK;
228 else if (IsEqualGUID(iid, &IID_ID2D1GdiInteropRenderTarget))
230 ID2D1GdiInteropRenderTarget_AddRef(&context->ID2D1GdiInteropRenderTarget_iface);
231 *out = &context->ID2D1GdiInteropRenderTarget_iface;
232 return S_OK;
235 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
237 *out = NULL;
238 return E_NOINTERFACE;
241 static ULONG STDMETHODCALLTYPE d2d_device_context_inner_AddRef(IUnknown *iface)
243 struct d2d_device_context *context = impl_from_IUnknown(iface);
244 ULONG refcount = InterlockedIncrement(&context->refcount);
246 TRACE("%p increasing refcount to %lu.\n", iface, refcount);
248 return refcount;
251 static ULONG STDMETHODCALLTYPE d2d_device_context_inner_Release(IUnknown *iface)
253 struct d2d_device_context *context = impl_from_IUnknown(iface);
254 ULONG refcount = InterlockedDecrement(&context->refcount);
256 TRACE("%p decreasing refcount to %lu.\n", iface, refcount);
258 if (!refcount)
260 unsigned int i, j, k;
262 d2d_clip_stack_cleanup(&context->clip_stack);
263 IDWriteRenderingParams_Release(context->default_text_rendering_params);
264 if (context->text_rendering_params)
265 IDWriteRenderingParams_Release(context->text_rendering_params);
266 if (context->bs)
267 ID3D11BlendState_Release(context->bs);
268 ID3D11RasterizerState_Release(context->rs);
269 ID3D11Buffer_Release(context->vb);
270 ID3D11Buffer_Release(context->ib);
271 ID3D11Buffer_Release(context->ps_cb);
272 ID3D11PixelShader_Release(context->ps);
273 ID3D11Buffer_Release(context->vs_cb);
274 for (i = 0; i < D2D_SHAPE_TYPE_COUNT; ++i)
276 ID3D11VertexShader_Release(context->shape_resources[i].vs);
277 ID3D11InputLayout_Release(context->shape_resources[i].il);
279 for (i = 0; i < D2D_SAMPLER_INTERPOLATION_MODE_COUNT; ++i)
281 for (j = 0; j < D2D_SAMPLER_EXTEND_MODE_COUNT; ++j)
283 for (k = 0; k < D2D_SAMPLER_EXTEND_MODE_COUNT; ++k)
285 if (context->sampler_states[i][j][k])
286 ID3D11SamplerState_Release(context->sampler_states[i][j][k]);
290 if (context->d3d_state)
291 ID3DDeviceContextState_Release(context->d3d_state);
292 if (context->target.object)
293 IUnknown_Release(context->target.object);
294 ID3D11Device1_Release(context->d3d_device);
295 ID2D1Factory_Release(context->factory);
296 ID2D1Device_Release(context->device);
297 free(context);
300 return refcount;
303 static const struct IUnknownVtbl d2d_device_context_inner_unknown_vtbl =
305 d2d_device_context_inner_QueryInterface,
306 d2d_device_context_inner_AddRef,
307 d2d_device_context_inner_Release,
310 static HRESULT STDMETHODCALLTYPE d2d_device_context_QueryInterface(ID2D1DeviceContext1 *iface, REFIID iid, void **out)
312 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
314 TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
316 return IUnknown_QueryInterface(context->outer_unknown, iid, out);
319 static ULONG STDMETHODCALLTYPE d2d_device_context_AddRef(ID2D1DeviceContext1 *iface)
321 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
323 TRACE("iface %p.\n", iface);
325 return IUnknown_AddRef(context->outer_unknown);
328 static ULONG STDMETHODCALLTYPE d2d_device_context_Release(ID2D1DeviceContext1 *iface)
330 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
332 TRACE("iface %p.\n", iface);
334 return IUnknown_Release(context->outer_unknown);
337 static void STDMETHODCALLTYPE d2d_device_context_GetFactory(ID2D1DeviceContext1 *iface, ID2D1Factory **factory)
339 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
341 TRACE("iface %p, factory %p.\n", iface, factory);
343 *factory = render_target->factory;
344 ID2D1Factory_AddRef(*factory);
347 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateBitmap(ID2D1DeviceContext1 *iface,
348 D2D1_SIZE_U size, const void *src_data, UINT32 pitch, const D2D1_BITMAP_PROPERTIES *desc, ID2D1Bitmap **bitmap)
350 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
351 D2D1_BITMAP_PROPERTIES1 bitmap_desc;
352 struct d2d_bitmap *object;
353 HRESULT hr;
355 TRACE("iface %p, size {%u, %u}, src_data %p, pitch %u, desc %p, bitmap %p.\n",
356 iface, size.width, size.height, src_data, pitch, desc, bitmap);
358 if (desc)
360 memcpy(&bitmap_desc, desc, sizeof(*desc));
361 bitmap_desc.bitmapOptions = 0;
362 bitmap_desc.colorContext = NULL;
365 if (SUCCEEDED(hr = d2d_bitmap_create(context, size, src_data, pitch, desc ? &bitmap_desc : NULL, &object)))
366 *bitmap = (ID2D1Bitmap *)&object->ID2D1Bitmap1_iface;
368 return hr;
371 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateBitmapFromWicBitmap(ID2D1DeviceContext1 *iface,
372 IWICBitmapSource *bitmap_source, const D2D1_BITMAP_PROPERTIES *desc, ID2D1Bitmap **bitmap)
374 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
375 D2D1_BITMAP_PROPERTIES1 bitmap_desc;
376 struct d2d_bitmap *object;
377 HRESULT hr;
379 TRACE("iface %p, bitmap_source %p, desc %p, bitmap %p.\n",
380 iface, bitmap_source, desc, bitmap);
382 if (desc)
384 memcpy(&bitmap_desc, desc, sizeof(*desc));
385 bitmap_desc.bitmapOptions = 0;
386 bitmap_desc.colorContext = NULL;
389 if (SUCCEEDED(hr = d2d_bitmap_create_from_wic_bitmap(context, bitmap_source, desc ? &bitmap_desc : NULL, &object)))
390 *bitmap = (ID2D1Bitmap *)&object->ID2D1Bitmap1_iface;
392 return hr;
395 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateSharedBitmap(ID2D1DeviceContext1 *iface,
396 REFIID iid, void *data, const D2D1_BITMAP_PROPERTIES *desc, ID2D1Bitmap **bitmap)
398 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
399 D2D1_BITMAP_PROPERTIES1 bitmap_desc;
400 struct d2d_bitmap *object;
401 HRESULT hr;
403 TRACE("iface %p, iid %s, data %p, desc %p, bitmap %p.\n",
404 iface, debugstr_guid(iid), data, desc, bitmap);
406 if (desc)
408 memcpy(&bitmap_desc, desc, sizeof(*desc));
409 if (IsEqualIID(iid, &IID_IDXGISurface) || IsEqualIID(iid, &IID_IDXGISurface1))
410 bitmap_desc.bitmapOptions = d2d_get_bitmap_options_for_surface(data);
411 else
412 bitmap_desc.bitmapOptions = D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW;
413 bitmap_desc.colorContext = NULL;
416 if (SUCCEEDED(hr = d2d_bitmap_create_shared(context, iid, data, desc ? &bitmap_desc : NULL, &object)))
417 *bitmap = (ID2D1Bitmap *)&object->ID2D1Bitmap1_iface;
419 return hr;
422 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateBitmapBrush(ID2D1DeviceContext1 *iface,
423 ID2D1Bitmap *bitmap, const D2D1_BITMAP_BRUSH_PROPERTIES *bitmap_brush_desc,
424 const D2D1_BRUSH_PROPERTIES *brush_desc, ID2D1BitmapBrush **brush)
426 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
427 struct d2d_brush *object;
428 HRESULT hr;
430 TRACE("iface %p, bitmap %p, bitmap_brush_desc %p, brush_desc %p, brush %p.\n",
431 iface, bitmap, bitmap_brush_desc, brush_desc, brush);
433 if (SUCCEEDED(hr = d2d_bitmap_brush_create(context->factory, bitmap, (const D2D1_BITMAP_BRUSH_PROPERTIES1 *)bitmap_brush_desc,
434 brush_desc, &object)))
435 *brush = (ID2D1BitmapBrush *)&object->ID2D1Brush_iface;
437 return hr;
440 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateSolidColorBrush(ID2D1DeviceContext1 *iface,
441 const D2D1_COLOR_F *color, const D2D1_BRUSH_PROPERTIES *desc, ID2D1SolidColorBrush **brush)
443 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
444 struct d2d_brush *object;
445 HRESULT hr;
447 TRACE("iface %p, color %p, desc %p, brush %p.\n", iface, color, desc, brush);
449 if (SUCCEEDED(hr = d2d_solid_color_brush_create(render_target->factory, color, desc, &object)))
450 *brush = (ID2D1SolidColorBrush *)&object->ID2D1Brush_iface;
452 return hr;
455 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateGradientStopCollection(ID2D1DeviceContext1 *iface,
456 const D2D1_GRADIENT_STOP *stops, UINT32 stop_count, D2D1_GAMMA gamma, D2D1_EXTEND_MODE extend_mode,
457 ID2D1GradientStopCollection **gradient)
459 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
460 struct d2d_gradient *object;
461 HRESULT hr;
463 TRACE("iface %p, stops %p, stop_count %u, gamma %#x, extend_mode %#x, gradient %p.\n",
464 iface, stops, stop_count, gamma, extend_mode, gradient);
466 if (SUCCEEDED(hr = d2d_gradient_create(render_target->factory, render_target->d3d_device,
467 stops, stop_count, gamma, extend_mode, &object)))
468 *gradient = &object->ID2D1GradientStopCollection_iface;
470 return hr;
473 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateLinearGradientBrush(ID2D1DeviceContext1 *iface,
474 const D2D1_LINEAR_GRADIENT_BRUSH_PROPERTIES *gradient_brush_desc, const D2D1_BRUSH_PROPERTIES *brush_desc,
475 ID2D1GradientStopCollection *gradient, ID2D1LinearGradientBrush **brush)
477 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
478 struct d2d_brush *object;
479 HRESULT hr;
481 TRACE("iface %p, gradient_brush_desc %p, brush_desc %p, gradient %p, brush %p.\n",
482 iface, gradient_brush_desc, brush_desc, gradient, brush);
484 if (SUCCEEDED(hr = d2d_linear_gradient_brush_create(render_target->factory, gradient_brush_desc, brush_desc,
485 gradient, &object)))
486 *brush = (ID2D1LinearGradientBrush *)&object->ID2D1Brush_iface;
488 return hr;
491 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateRadialGradientBrush(ID2D1DeviceContext1 *iface,
492 const D2D1_RADIAL_GRADIENT_BRUSH_PROPERTIES *gradient_brush_desc, const D2D1_BRUSH_PROPERTIES *brush_desc,
493 ID2D1GradientStopCollection *gradient, ID2D1RadialGradientBrush **brush)
495 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
496 struct d2d_brush *object;
497 HRESULT hr;
499 TRACE("iface %p, gradient_brush_desc %p, brush_desc %p, gradient %p, brush %p.\n",
500 iface, gradient_brush_desc, brush_desc, gradient, brush);
502 if (SUCCEEDED(hr = d2d_radial_gradient_brush_create(render_target->factory,
503 gradient_brush_desc, brush_desc, gradient, &object)))
504 *brush = (ID2D1RadialGradientBrush *)&object->ID2D1Brush_iface;
506 return hr;
509 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateCompatibleRenderTarget(ID2D1DeviceContext1 *iface,
510 const D2D1_SIZE_F *size, const D2D1_SIZE_U *pixel_size, const D2D1_PIXEL_FORMAT *format,
511 D2D1_COMPATIBLE_RENDER_TARGET_OPTIONS options, ID2D1BitmapRenderTarget **rt)
513 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
514 struct d2d_bitmap_render_target *object;
515 HRESULT hr;
517 TRACE("iface %p, size %p, pixel_size %p, format %p, options %#x, render_target %p.\n",
518 iface, size, pixel_size, format, options, rt);
520 if (!(object = calloc(1, sizeof(*object))))
521 return E_OUTOFMEMORY;
523 if (FAILED(hr = d2d_bitmap_render_target_init(object, render_target, size, pixel_size,
524 format, options)))
526 WARN("Failed to initialise render target, hr %#lx.\n", hr);
527 free(object);
528 return hr;
531 TRACE("Created render target %p.\n", object);
532 *rt = &object->ID2D1BitmapRenderTarget_iface;
534 return S_OK;
537 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateLayer(ID2D1DeviceContext1 *iface,
538 const D2D1_SIZE_F *size, ID2D1Layer **layer)
540 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
541 struct d2d_layer *object;
542 HRESULT hr;
544 TRACE("iface %p, size %p, layer %p.\n", iface, size, layer);
546 if (SUCCEEDED(hr = d2d_layer_create(render_target->factory, size, &object)))
547 *layer = &object->ID2D1Layer_iface;
549 return hr;
552 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateMesh(ID2D1DeviceContext1 *iface, ID2D1Mesh **mesh)
554 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
555 struct d2d_mesh *object;
556 HRESULT hr;
558 TRACE("iface %p, mesh %p.\n", iface, mesh);
560 if (SUCCEEDED(hr = d2d_mesh_create(render_target->factory, &object)))
561 *mesh = &object->ID2D1Mesh_iface;
563 return hr;
566 static void STDMETHODCALLTYPE d2d_device_context_DrawLine(ID2D1DeviceContext1 *iface,
567 D2D1_POINT_2F p0, D2D1_POINT_2F p1, ID2D1Brush *brush, float stroke_width, ID2D1StrokeStyle *stroke_style)
569 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
570 ID2D1PathGeometry *geometry;
571 ID2D1GeometrySink *sink;
572 HRESULT hr;
574 TRACE("iface %p, p0 %s, p1 %s, brush %p, stroke_width %.8e, stroke_style %p.\n",
575 iface, debug_d2d_point_2f(&p0), debug_d2d_point_2f(&p1), brush, stroke_width, stroke_style);
577 if (context->target.type == D2D_TARGET_COMMAND_LIST)
579 d2d_command_list_draw_line(context->target.command_list, context, p0, p1, brush, stroke_width, stroke_style);
580 return;
583 if (FAILED(hr = ID2D1Factory_CreatePathGeometry(context->factory, &geometry)))
585 WARN("Failed to create path geometry, hr %#lx.\n", hr);
586 return;
589 if (FAILED(hr = ID2D1PathGeometry_Open(geometry, &sink)))
591 WARN("Failed to open geometry sink, hr %#lx.\n", hr);
592 ID2D1PathGeometry_Release(geometry);
593 return;
596 ID2D1GeometrySink_BeginFigure(sink, p0, D2D1_FIGURE_BEGIN_HOLLOW);
597 ID2D1GeometrySink_AddLine(sink, p1);
598 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_OPEN);
599 if (FAILED(hr = ID2D1GeometrySink_Close(sink)))
600 WARN("Failed to close geometry sink, hr %#lx.\n", hr);
601 ID2D1GeometrySink_Release(sink);
603 ID2D1DeviceContext1_DrawGeometry(iface, (ID2D1Geometry *)geometry, brush, stroke_width, stroke_style);
604 ID2D1PathGeometry_Release(geometry);
607 static void STDMETHODCALLTYPE d2d_device_context_DrawRectangle(ID2D1DeviceContext1 *iface,
608 const D2D1_RECT_F *rect, ID2D1Brush *brush, float stroke_width, ID2D1StrokeStyle *stroke_style)
610 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
611 ID2D1RectangleGeometry *geometry;
612 HRESULT hr;
614 TRACE("iface %p, rect %s, brush %p, stroke_width %.8e, stroke_style %p.\n",
615 iface, debug_d2d_rect_f(rect), brush, stroke_width, stroke_style);
617 if (context->target.type == D2D_TARGET_COMMAND_LIST)
619 d2d_command_list_draw_rectangle(context->target.command_list, context, rect, brush, stroke_width, stroke_style);
620 return;
623 if (FAILED(hr = ID2D1Factory_CreateRectangleGeometry(context->factory, rect, &geometry)))
625 ERR("Failed to create geometry, hr %#lx.\n", hr);
626 return;
629 ID2D1DeviceContext1_DrawGeometry(iface, (ID2D1Geometry *)geometry, brush, stroke_width, stroke_style);
630 ID2D1RectangleGeometry_Release(geometry);
633 static void STDMETHODCALLTYPE d2d_device_context_FillRectangle(ID2D1DeviceContext1 *iface,
634 const D2D1_RECT_F *rect, ID2D1Brush *brush)
636 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
637 ID2D1RectangleGeometry *geometry;
638 HRESULT hr;
640 TRACE("iface %p, rect %s, brush %p.\n", iface, debug_d2d_rect_f(rect), brush);
642 if (context->target.type == D2D_TARGET_COMMAND_LIST)
644 d2d_command_list_fill_rectangle(context->target.command_list, context, rect, brush);
645 return;
648 if (FAILED(hr = ID2D1Factory_CreateRectangleGeometry(context->factory, rect, &geometry)))
650 ERR("Failed to create geometry, hr %#lx.\n", hr);
651 return;
654 ID2D1DeviceContext1_FillGeometry(iface, (ID2D1Geometry *)geometry, brush, NULL);
655 ID2D1RectangleGeometry_Release(geometry);
658 static void STDMETHODCALLTYPE d2d_device_context_DrawRoundedRectangle(ID2D1DeviceContext1 *iface,
659 const D2D1_ROUNDED_RECT *rect, ID2D1Brush *brush, float stroke_width, ID2D1StrokeStyle *stroke_style)
661 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
662 ID2D1RoundedRectangleGeometry *geometry;
663 HRESULT hr;
665 TRACE("iface %p, rect %p, brush %p, stroke_width %.8e, stroke_style %p.\n",
666 iface, rect, brush, stroke_width, stroke_style);
668 if (FAILED(hr = ID2D1Factory_CreateRoundedRectangleGeometry(render_target->factory, rect, &geometry)))
670 ERR("Failed to create geometry, hr %#lx.\n", hr);
671 return;
674 ID2D1DeviceContext1_DrawGeometry(iface, (ID2D1Geometry *)geometry, brush, stroke_width, stroke_style);
675 ID2D1RoundedRectangleGeometry_Release(geometry);
678 static void STDMETHODCALLTYPE d2d_device_context_FillRoundedRectangle(ID2D1DeviceContext1 *iface,
679 const D2D1_ROUNDED_RECT *rect, ID2D1Brush *brush)
681 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
682 ID2D1RoundedRectangleGeometry *geometry;
683 HRESULT hr;
685 TRACE("iface %p, rect %p, brush %p.\n", iface, rect, brush);
687 if (FAILED(hr = ID2D1Factory_CreateRoundedRectangleGeometry(render_target->factory, rect, &geometry)))
689 ERR("Failed to create geometry, hr %#lx.\n", hr);
690 return;
693 ID2D1DeviceContext1_FillGeometry(iface, (ID2D1Geometry *)geometry, brush, NULL);
694 ID2D1RoundedRectangleGeometry_Release(geometry);
697 static void STDMETHODCALLTYPE d2d_device_context_DrawEllipse(ID2D1DeviceContext1 *iface,
698 const D2D1_ELLIPSE *ellipse, ID2D1Brush *brush, float stroke_width, ID2D1StrokeStyle *stroke_style)
700 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
701 ID2D1EllipseGeometry *geometry;
702 HRESULT hr;
704 TRACE("iface %p, ellipse %p, brush %p, stroke_width %.8e, stroke_style %p.\n",
705 iface, ellipse, brush, stroke_width, stroke_style);
707 if (FAILED(hr = ID2D1Factory_CreateEllipseGeometry(render_target->factory, ellipse, &geometry)))
709 ERR("Failed to create geometry, hr %#lx.\n", hr);
710 return;
713 ID2D1DeviceContext1_DrawGeometry(iface, (ID2D1Geometry *)geometry, brush, stroke_width, stroke_style);
714 ID2D1EllipseGeometry_Release(geometry);
717 static void STDMETHODCALLTYPE d2d_device_context_FillEllipse(ID2D1DeviceContext1 *iface,
718 const D2D1_ELLIPSE *ellipse, ID2D1Brush *brush)
720 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
721 ID2D1EllipseGeometry *geometry;
722 HRESULT hr;
724 TRACE("iface %p, ellipse %p, brush %p.\n", iface, ellipse, brush);
726 if (FAILED(hr = ID2D1Factory_CreateEllipseGeometry(render_target->factory, ellipse, &geometry)))
728 ERR("Failed to create geometry, hr %#lx.\n", hr);
729 return;
732 ID2D1DeviceContext1_FillGeometry(iface, (ID2D1Geometry *)geometry, brush, NULL);
733 ID2D1EllipseGeometry_Release(geometry);
736 static HRESULT d2d_device_context_update_ps_cb(struct d2d_device_context *context,
737 struct d2d_brush *brush, struct d2d_brush *opacity_brush, BOOL outline, BOOL is_arc)
739 D3D11_MAPPED_SUBRESOURCE map_desc;
740 ID3D11DeviceContext *d3d_context;
741 struct d2d_ps_cb *cb_data;
742 HRESULT hr;
744 ID3D11Device1_GetImmediateContext(context->d3d_device, &d3d_context);
746 if (FAILED(hr = ID3D11DeviceContext_Map(d3d_context, (ID3D11Resource *)context->ps_cb,
747 0, D3D11_MAP_WRITE_DISCARD, 0, &map_desc)))
749 WARN("Failed to map constant buffer, hr %#lx.\n", hr);
750 ID3D11DeviceContext_Release(d3d_context);
751 return hr;
754 cb_data = map_desc.pData;
755 cb_data->outline = outline;
756 cb_data->is_arc = is_arc;
757 cb_data->pad[0] = 0;
758 cb_data->pad[1] = 0;
759 if (!d2d_brush_fill_cb(brush, &cb_data->colour_brush))
760 WARN("Failed to initialize colour brush buffer.\n");
761 if (!d2d_brush_fill_cb(opacity_brush, &cb_data->opacity_brush))
762 WARN("Failed to initialize opacity brush buffer.\n");
764 ID3D11DeviceContext_Unmap(d3d_context, (ID3D11Resource *)context->ps_cb, 0);
765 ID3D11DeviceContext_Release(d3d_context);
767 return hr;
770 static HRESULT d2d_device_context_update_vs_cb(struct d2d_device_context *context,
771 const D2D_MATRIX_3X2_F *geometry_transform, float stroke_width)
773 D3D11_MAPPED_SUBRESOURCE map_desc;
774 ID3D11DeviceContext *d3d_context;
775 const D2D1_MATRIX_3X2_F *w;
776 struct d2d_vs_cb *cb_data;
777 float tmp_x, tmp_y;
778 HRESULT hr;
780 ID3D11Device1_GetImmediateContext(context->d3d_device, &d3d_context);
782 if (FAILED(hr = ID3D11DeviceContext_Map(d3d_context, (ID3D11Resource *)context->vs_cb,
783 0, D3D11_MAP_WRITE_DISCARD, 0, &map_desc)))
785 WARN("Failed to map constant buffer, hr %#lx.\n", hr);
786 ID3D11DeviceContext_Release(d3d_context);
787 return hr;
790 cb_data = map_desc.pData;
791 cb_data->transform_geometry._11 = geometry_transform->_11;
792 cb_data->transform_geometry._21 = geometry_transform->_21;
793 cb_data->transform_geometry._31 = geometry_transform->_31;
794 cb_data->transform_geometry.pad0 = 0.0f;
795 cb_data->transform_geometry._12 = geometry_transform->_12;
796 cb_data->transform_geometry._22 = geometry_transform->_22;
797 cb_data->transform_geometry._32 = geometry_transform->_32;
798 cb_data->transform_geometry.stroke_width = stroke_width;
800 w = &context->drawing_state.transform;
802 tmp_x = context->desc.dpiX / 96.0f;
803 cb_data->transform_rtx.x = w->_11 * tmp_x;
804 cb_data->transform_rtx.y = w->_21 * tmp_x;
805 cb_data->transform_rtx.z = w->_31 * tmp_x;
806 cb_data->transform_rtx.w = 2.0f / context->pixel_size.width;
808 tmp_y = context->desc.dpiY / 96.0f;
809 cb_data->transform_rty.x = w->_12 * tmp_y;
810 cb_data->transform_rty.y = w->_22 * tmp_y;
811 cb_data->transform_rty.z = w->_32 * tmp_y;
812 cb_data->transform_rty.w = -2.0f / context->pixel_size.height;
814 ID3D11DeviceContext_Unmap(d3d_context, (ID3D11Resource *)context->vs_cb, 0);
815 ID3D11DeviceContext_Release(d3d_context);
817 return S_OK;
820 static void d2d_device_context_draw_geometry(struct d2d_device_context *render_target,
821 const struct d2d_geometry *geometry, struct d2d_brush *brush, float stroke_width)
823 D3D11_SUBRESOURCE_DATA buffer_data;
824 D3D11_BUFFER_DESC buffer_desc;
825 ID3D11Buffer *ib, *vb;
826 HRESULT hr;
828 if (FAILED(hr = d2d_device_context_update_vs_cb(render_target, &geometry->transform, stroke_width)))
830 WARN("Failed to update vs constant buffer, hr %#lx.\n", hr);
831 return;
834 if (FAILED(hr = d2d_device_context_update_ps_cb(render_target, brush, NULL, TRUE, FALSE)))
836 WARN("Failed to update ps constant buffer, hr %#lx.\n", hr);
837 return;
840 buffer_desc.Usage = D3D11_USAGE_DEFAULT;
841 buffer_desc.CPUAccessFlags = 0;
842 buffer_desc.MiscFlags = 0;
844 buffer_data.SysMemPitch = 0;
845 buffer_data.SysMemSlicePitch = 0;
847 if (geometry->outline.face_count)
849 buffer_desc.ByteWidth = geometry->outline.face_count * sizeof(*geometry->outline.faces);
850 buffer_desc.BindFlags = D3D11_BIND_INDEX_BUFFER;
851 buffer_data.pSysMem = geometry->outline.faces;
853 if (FAILED(hr = ID3D11Device1_CreateBuffer(render_target->d3d_device, &buffer_desc, &buffer_data, &ib)))
855 WARN("Failed to create index buffer, hr %#lx.\n", hr);
856 return;
859 buffer_desc.ByteWidth = geometry->outline.vertex_count * sizeof(*geometry->outline.vertices);
860 buffer_desc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
861 buffer_data.pSysMem = geometry->outline.vertices;
863 if (FAILED(hr = ID3D11Device1_CreateBuffer(render_target->d3d_device, &buffer_desc, &buffer_data, &vb)))
865 ERR("Failed to create vertex buffer, hr %#lx.\n", hr);
866 ID3D11Buffer_Release(ib);
867 return;
870 d2d_device_context_draw(render_target, D2D_SHAPE_TYPE_OUTLINE, ib, 3 * geometry->outline.face_count, vb,
871 sizeof(*geometry->outline.vertices), brush, NULL);
873 ID3D11Buffer_Release(vb);
874 ID3D11Buffer_Release(ib);
877 if (geometry->outline.bezier_face_count)
879 buffer_desc.ByteWidth = geometry->outline.bezier_face_count * sizeof(*geometry->outline.bezier_faces);
880 buffer_desc.BindFlags = D3D11_BIND_INDEX_BUFFER;
881 buffer_data.pSysMem = geometry->outline.bezier_faces;
883 if (FAILED(hr = ID3D11Device1_CreateBuffer(render_target->d3d_device, &buffer_desc, &buffer_data, &ib)))
885 WARN("Failed to create curves index buffer, hr %#lx.\n", hr);
886 return;
889 buffer_desc.ByteWidth = geometry->outline.bezier_count * sizeof(*geometry->outline.beziers);
890 buffer_desc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
891 buffer_data.pSysMem = geometry->outline.beziers;
893 if (FAILED(hr = ID3D11Device1_CreateBuffer(render_target->d3d_device, &buffer_desc, &buffer_data, &vb)))
895 ERR("Failed to create curves vertex buffer, hr %#lx.\n", hr);
896 ID3D11Buffer_Release(ib);
897 return;
900 d2d_device_context_draw(render_target, D2D_SHAPE_TYPE_BEZIER_OUTLINE, ib,
901 3 * geometry->outline.bezier_face_count, vb,
902 sizeof(*geometry->outline.beziers), brush, NULL);
904 ID3D11Buffer_Release(vb);
905 ID3D11Buffer_Release(ib);
908 if (geometry->outline.arc_face_count)
910 buffer_desc.ByteWidth = geometry->outline.arc_face_count * sizeof(*geometry->outline.arc_faces);
911 buffer_desc.BindFlags = D3D11_BIND_INDEX_BUFFER;
912 buffer_data.pSysMem = geometry->outline.arc_faces;
914 if (FAILED(hr = ID3D11Device1_CreateBuffer(render_target->d3d_device, &buffer_desc, &buffer_data, &ib)))
916 WARN("Failed to create arcs index buffer, hr %#lx.\n", hr);
917 return;
920 buffer_desc.ByteWidth = geometry->outline.arc_count * sizeof(*geometry->outline.arcs);
921 buffer_desc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
922 buffer_data.pSysMem = geometry->outline.arcs;
924 if (FAILED(hr = ID3D11Device1_CreateBuffer(render_target->d3d_device, &buffer_desc, &buffer_data, &vb)))
926 ERR("Failed to create arcs vertex buffer, hr %#lx.\n", hr);
927 ID3D11Buffer_Release(ib);
928 return;
931 if (SUCCEEDED(d2d_device_context_update_ps_cb(render_target, brush, NULL, TRUE, TRUE)))
932 d2d_device_context_draw(render_target, D2D_SHAPE_TYPE_ARC_OUTLINE, ib,
933 3 * geometry->outline.arc_face_count, vb,
934 sizeof(*geometry->outline.arcs), brush, NULL);
936 ID3D11Buffer_Release(vb);
937 ID3D11Buffer_Release(ib);
941 static void STDMETHODCALLTYPE d2d_device_context_DrawGeometry(ID2D1DeviceContext1 *iface,
942 ID2D1Geometry *geometry, ID2D1Brush *brush, float stroke_width, ID2D1StrokeStyle *stroke_style)
944 const struct d2d_geometry *geometry_impl = unsafe_impl_from_ID2D1Geometry(geometry);
945 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
946 struct d2d_brush *brush_impl = unsafe_impl_from_ID2D1Brush(brush);
948 TRACE("iface %p, geometry %p, brush %p, stroke_width %.8e, stroke_style %p.\n",
949 iface, geometry, brush, stroke_width, stroke_style);
951 if (context->target.type == D2D_TARGET_COMMAND_LIST)
953 d2d_command_list_draw_geometry(context->target.command_list, context, geometry, brush,
954 stroke_width, stroke_style);
955 return;
958 if (stroke_style)
959 FIXME("Ignoring stroke style %p.\n", stroke_style);
961 d2d_device_context_draw_geometry(context, geometry_impl, brush_impl, stroke_width);
964 static void d2d_device_context_fill_geometry(struct d2d_device_context *render_target,
965 const struct d2d_geometry *geometry, struct d2d_brush *brush, struct d2d_brush *opacity_brush)
967 D3D11_SUBRESOURCE_DATA buffer_data;
968 D3D11_BUFFER_DESC buffer_desc;
969 ID3D11Buffer *ib, *vb;
970 HRESULT hr;
972 buffer_desc.Usage = D3D11_USAGE_DEFAULT;
973 buffer_desc.CPUAccessFlags = 0;
974 buffer_desc.MiscFlags = 0;
976 buffer_data.SysMemPitch = 0;
977 buffer_data.SysMemSlicePitch = 0;
979 if (FAILED(hr = d2d_device_context_update_vs_cb(render_target, &geometry->transform, 0.0f)))
981 WARN("Failed to update vs constant buffer, hr %#lx.\n", hr);
982 return;
985 if (FAILED(hr = d2d_device_context_update_ps_cb(render_target, brush, opacity_brush, FALSE, FALSE)))
987 WARN("Failed to update ps constant buffer, hr %#lx.\n", hr);
988 return;
991 if (geometry->fill.face_count)
993 buffer_desc.ByteWidth = geometry->fill.face_count * sizeof(*geometry->fill.faces);
994 buffer_desc.BindFlags = D3D11_BIND_INDEX_BUFFER;
995 buffer_data.pSysMem = geometry->fill.faces;
997 if (FAILED(hr = ID3D11Device1_CreateBuffer(render_target->d3d_device, &buffer_desc, &buffer_data, &ib)))
999 WARN("Failed to create index buffer, hr %#lx.\n", hr);
1000 return;
1003 buffer_desc.ByteWidth = geometry->fill.vertex_count * sizeof(*geometry->fill.vertices);
1004 buffer_desc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
1005 buffer_data.pSysMem = geometry->fill.vertices;
1007 if (FAILED(hr = ID3D11Device1_CreateBuffer(render_target->d3d_device, &buffer_desc, &buffer_data, &vb)))
1009 ERR("Failed to create vertex buffer, hr %#lx.\n", hr);
1010 ID3D11Buffer_Release(ib);
1011 return;
1014 d2d_device_context_draw(render_target, D2D_SHAPE_TYPE_TRIANGLE, ib, 3 * geometry->fill.face_count, vb,
1015 sizeof(*geometry->fill.vertices), brush, opacity_brush);
1017 ID3D11Buffer_Release(vb);
1018 ID3D11Buffer_Release(ib);
1021 if (geometry->fill.bezier_vertex_count)
1023 buffer_desc.ByteWidth = geometry->fill.bezier_vertex_count * sizeof(*geometry->fill.bezier_vertices);
1024 buffer_desc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
1025 buffer_data.pSysMem = geometry->fill.bezier_vertices;
1027 if (FAILED(hr = ID3D11Device1_CreateBuffer(render_target->d3d_device, &buffer_desc, &buffer_data, &vb)))
1029 ERR("Failed to create curves vertex buffer, hr %#lx.\n", hr);
1030 return;
1033 d2d_device_context_draw(render_target, D2D_SHAPE_TYPE_CURVE, NULL, geometry->fill.bezier_vertex_count, vb,
1034 sizeof(*geometry->fill.bezier_vertices), brush, opacity_brush);
1036 ID3D11Buffer_Release(vb);
1039 if (geometry->fill.arc_vertex_count)
1041 buffer_desc.ByteWidth = geometry->fill.arc_vertex_count * sizeof(*geometry->fill.arc_vertices);
1042 buffer_desc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
1043 buffer_data.pSysMem = geometry->fill.arc_vertices;
1045 if (FAILED(hr = ID3D11Device1_CreateBuffer(render_target->d3d_device, &buffer_desc, &buffer_data, &vb)))
1047 ERR("Failed to create arc vertex buffer, hr %#lx.\n", hr);
1048 return;
1051 if (SUCCEEDED(d2d_device_context_update_ps_cb(render_target, brush, opacity_brush, FALSE, TRUE)))
1052 d2d_device_context_draw(render_target, D2D_SHAPE_TYPE_CURVE, NULL, geometry->fill.arc_vertex_count, vb,
1053 sizeof(*geometry->fill.arc_vertices), brush, opacity_brush);
1055 ID3D11Buffer_Release(vb);
1059 static void STDMETHODCALLTYPE d2d_device_context_FillGeometry(ID2D1DeviceContext1 *iface,
1060 ID2D1Geometry *geometry, ID2D1Brush *brush, ID2D1Brush *opacity_brush)
1062 const struct d2d_geometry *geometry_impl = unsafe_impl_from_ID2D1Geometry(geometry);
1063 struct d2d_brush *opacity_brush_impl = unsafe_impl_from_ID2D1Brush(opacity_brush);
1064 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
1065 struct d2d_brush *brush_impl = unsafe_impl_from_ID2D1Brush(brush);
1067 TRACE("iface %p, geometry %p, brush %p, opacity_brush %p.\n", iface, geometry, brush, opacity_brush);
1069 if (FAILED(context->error.code))
1070 return;
1072 if (opacity_brush && brush_impl->type != D2D_BRUSH_TYPE_BITMAP)
1074 d2d_device_context_set_error(context, D2DERR_INCOMPATIBLE_BRUSH_TYPES);
1075 return;
1078 if (context->target.type == D2D_TARGET_COMMAND_LIST)
1079 d2d_command_list_fill_geometry(context->target.command_list, context, geometry, brush, opacity_brush);
1080 else
1081 d2d_device_context_fill_geometry(context, geometry_impl, brush_impl, opacity_brush_impl);
1084 static void STDMETHODCALLTYPE d2d_device_context_FillMesh(ID2D1DeviceContext1 *iface,
1085 ID2D1Mesh *mesh, ID2D1Brush *brush)
1087 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
1089 FIXME("iface %p, mesh %p, brush %p stub!\n", iface, mesh, brush);
1091 if (context->target.type == D2D_TARGET_COMMAND_LIST)
1092 d2d_command_list_fill_mesh(context->target.command_list, context, mesh, brush);
1095 static void STDMETHODCALLTYPE d2d_device_context_FillOpacityMask(ID2D1DeviceContext1 *iface,
1096 ID2D1Bitmap *mask, ID2D1Brush *brush, D2D1_OPACITY_MASK_CONTENT content,
1097 const D2D1_RECT_F *dst_rect, const D2D1_RECT_F *src_rect)
1099 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
1101 FIXME("iface %p, mask %p, brush %p, content %#x, dst_rect %s, src_rect %s stub!\n",
1102 iface, mask, brush, content, debug_d2d_rect_f(dst_rect), debug_d2d_rect_f(src_rect));
1104 if (FAILED(context->error.code))
1105 return;
1107 if (context->drawing_state.antialiasMode != D2D1_ANTIALIAS_MODE_ALIASED)
1109 d2d_device_context_set_error(context, D2DERR_WRONG_STATE);
1110 return;
1113 if ((unsigned int)content > D2D1_OPACITY_MASK_CONTENT_TEXT_GDI_COMPATIBLE)
1115 d2d_device_context_set_error(context, E_INVALIDARG);
1116 return;
1119 if (context->target.type == D2D_TARGET_COMMAND_LIST)
1120 d2d_command_list_fill_opacity_mask(context->target.command_list, context, mask, brush, dst_rect, src_rect);
1123 static void d2d_device_context_draw_bitmap(struct d2d_device_context *context, ID2D1Bitmap *bitmap,
1124 const D2D1_RECT_F *dst_rect, float opacity, D2D1_INTERPOLATION_MODE interpolation_mode,
1125 const D2D1_RECT_F *src_rect, const D2D1_POINT_2F *offset,
1126 const D2D1_MATRIX_4X4_F *perspective_transform)
1128 D2D1_BITMAP_BRUSH_PROPERTIES1 bitmap_brush_desc;
1129 D2D1_BRUSH_PROPERTIES brush_desc;
1130 struct d2d_brush *brush;
1131 D2D1_SIZE_F size;
1132 D2D1_RECT_F s, d;
1133 HRESULT hr;
1135 if (perspective_transform)
1136 FIXME("Perspective transform is ignored.\n");
1138 size = ID2D1Bitmap_GetSize(bitmap);
1139 d2d_rect_set(&s, 0.0f, 0.0f, size.width, size.height);
1140 if (src_rect && src_rect->left <= src_rect->right
1141 && src_rect->top <= src_rect->bottom)
1143 d2d_rect_intersect(&s, src_rect);
1146 if (s.left == s.right || s.top == s.bottom)
1147 return;
1149 if (dst_rect)
1151 d = *dst_rect;
1153 else
1155 d.left = 0.0f;
1156 d.top = 0.0f;
1157 d.right = s.right - s.left;
1158 d.bottom = s.bottom - s.top;
1161 if (offset)
1163 d.left += offset->x;
1164 d.top += offset->y;
1165 d.right += offset->x;
1166 d.bottom += offset->y;
1169 bitmap_brush_desc.extendModeX = D2D1_EXTEND_MODE_CLAMP;
1170 bitmap_brush_desc.extendModeY = D2D1_EXTEND_MODE_CLAMP;
1171 bitmap_brush_desc.interpolationMode = interpolation_mode;
1173 brush_desc.opacity = opacity;
1174 brush_desc.transform._11 = fabsf((d.right - d.left) / (s.right - s.left));
1175 brush_desc.transform._21 = 0.0f;
1176 brush_desc.transform._31 = min(d.left, d.right) - min(s.left, s.right) * brush_desc.transform._11;
1177 brush_desc.transform._12 = 0.0f;
1178 brush_desc.transform._22 = fabsf((d.bottom - d.top) / (s.bottom - s.top));
1179 brush_desc.transform._32 = min(d.top, d.bottom) - min(s.top, s.bottom) * brush_desc.transform._22;
1181 if (FAILED(hr = d2d_bitmap_brush_create(context->factory, bitmap, &bitmap_brush_desc, &brush_desc, &brush)))
1183 ERR("Failed to create bitmap brush, hr %#lx.\n", hr);
1184 return;
1187 d2d_device_context_FillRectangle(&context->ID2D1DeviceContext1_iface, &d, &brush->ID2D1Brush_iface);
1188 ID2D1Brush_Release(&brush->ID2D1Brush_iface);
1191 static void STDMETHODCALLTYPE d2d_device_context_DrawBitmap(ID2D1DeviceContext1 *iface,
1192 ID2D1Bitmap *bitmap, const D2D1_RECT_F *dst_rect, float opacity,
1193 D2D1_BITMAP_INTERPOLATION_MODE interpolation_mode, const D2D1_RECT_F *src_rect)
1195 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
1197 TRACE("iface %p, bitmap %p, dst_rect %s, opacity %.8e, interpolation_mode %#x, src_rect %s.\n",
1198 iface, bitmap, debug_d2d_rect_f(dst_rect), opacity, interpolation_mode, debug_d2d_rect_f(src_rect));
1200 if (interpolation_mode != D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR
1201 && interpolation_mode != D2D1_BITMAP_INTERPOLATION_MODE_LINEAR)
1203 d2d_device_context_set_error(context, E_INVALIDARG);
1204 return;
1207 if (context->target.type == D2D_TARGET_COMMAND_LIST)
1209 d2d_command_list_draw_bitmap(context->target.command_list, bitmap, dst_rect, opacity,
1210 d2d1_1_interp_mode_from_d2d1(interpolation_mode), src_rect, NULL);
1212 else
1214 d2d_device_context_draw_bitmap(context, bitmap, dst_rect, opacity,
1215 d2d1_1_interp_mode_from_d2d1(interpolation_mode), src_rect, NULL, NULL);
1219 static void STDMETHODCALLTYPE d2d_device_context_DrawText(ID2D1DeviceContext1 *iface,
1220 const WCHAR *string, UINT32 string_len, IDWriteTextFormat *text_format, const D2D1_RECT_F *layout_rect,
1221 ID2D1Brush *brush, D2D1_DRAW_TEXT_OPTIONS options, DWRITE_MEASURING_MODE measuring_mode)
1223 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1224 IDWriteTextLayout *text_layout;
1225 IDWriteFactory *dwrite_factory;
1226 D2D1_POINT_2F origin;
1227 float width, height;
1228 HRESULT hr;
1230 TRACE("iface %p, string %s, string_len %u, text_format %p, layout_rect %s, "
1231 "brush %p, options %#x, measuring_mode %#x.\n",
1232 iface, debugstr_wn(string, string_len), string_len, text_format, debug_d2d_rect_f(layout_rect),
1233 brush, options, measuring_mode);
1235 if (FAILED(hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED,
1236 &IID_IDWriteFactory, (IUnknown **)&dwrite_factory)))
1238 ERR("Failed to create dwrite factory, hr %#lx.\n", hr);
1239 return;
1242 width = max(0.0f, layout_rect->right - layout_rect->left);
1243 height = max(0.0f, layout_rect->bottom - layout_rect->top);
1244 if (measuring_mode == DWRITE_MEASURING_MODE_NATURAL)
1245 hr = IDWriteFactory_CreateTextLayout(dwrite_factory, string, string_len, text_format,
1246 width, height, &text_layout);
1247 else
1248 hr = IDWriteFactory_CreateGdiCompatibleTextLayout(dwrite_factory, string, string_len, text_format,
1249 width, height, render_target->desc.dpiX / 96.0f, (DWRITE_MATRIX *)&render_target->drawing_state.transform,
1250 measuring_mode == DWRITE_MEASURING_MODE_GDI_NATURAL, &text_layout);
1251 IDWriteFactory_Release(dwrite_factory);
1252 if (FAILED(hr))
1254 ERR("Failed to create text layout, hr %#lx.\n", hr);
1255 return;
1258 d2d_point_set(&origin, min(layout_rect->left, layout_rect->right), min(layout_rect->top, layout_rect->bottom));
1259 ID2D1DeviceContext1_DrawTextLayout(iface, origin, text_layout, brush, options);
1260 IDWriteTextLayout_Release(text_layout);
1263 static void STDMETHODCALLTYPE d2d_device_context_DrawTextLayout(ID2D1DeviceContext1 *iface,
1264 D2D1_POINT_2F origin, IDWriteTextLayout *layout, ID2D1Brush *brush, D2D1_DRAW_TEXT_OPTIONS options)
1266 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1267 struct d2d_draw_text_layout_ctx ctx;
1268 HRESULT hr;
1270 TRACE("iface %p, origin %s, layout %p, brush %p, options %#x.\n",
1271 iface, debug_d2d_point_2f(&origin), layout, brush, options);
1273 ctx.brush = brush;
1274 ctx.options = options;
1276 if (FAILED(hr = IDWriteTextLayout_Draw(layout,
1277 &ctx, &render_target->IDWriteTextRenderer_iface, origin.x, origin.y)))
1278 FIXME("Failed to draw text layout, hr %#lx.\n", hr);
1281 static D2D1_ANTIALIAS_MODE d2d_device_context_set_aa_mode_from_text_aa_mode(struct d2d_device_context *rt)
1283 D2D1_ANTIALIAS_MODE prev_antialias_mode = rt->drawing_state.antialiasMode;
1284 rt->drawing_state.antialiasMode = rt->drawing_state.textAntialiasMode == D2D1_TEXT_ANTIALIAS_MODE_ALIASED ?
1285 D2D1_ANTIALIAS_MODE_ALIASED : D2D1_ANTIALIAS_MODE_PER_PRIMITIVE;
1286 return prev_antialias_mode;
1289 static void d2d_device_context_draw_glyph_run_outline(struct d2d_device_context *render_target,
1290 D2D1_POINT_2F baseline_origin, const DWRITE_GLYPH_RUN *glyph_run, ID2D1Brush *brush)
1292 D2D1_MATRIX_3X2_F *transform, prev_transform;
1293 D2D1_ANTIALIAS_MODE prev_antialias_mode;
1294 ID2D1PathGeometry *geometry;
1295 ID2D1GeometrySink *sink;
1296 HRESULT hr;
1298 if (FAILED(hr = ID2D1Factory_CreatePathGeometry(render_target->factory, &geometry)))
1300 ERR("Failed to create geometry, hr %#lx.\n", hr);
1301 return;
1304 if (FAILED(hr = ID2D1PathGeometry_Open(geometry, &sink)))
1306 ERR("Failed to open geometry sink, hr %#lx.\n", hr);
1307 ID2D1PathGeometry_Release(geometry);
1308 return;
1311 if (FAILED(hr = IDWriteFontFace_GetGlyphRunOutline(glyph_run->fontFace, glyph_run->fontEmSize,
1312 glyph_run->glyphIndices, glyph_run->glyphAdvances, glyph_run->glyphOffsets, glyph_run->glyphCount,
1313 glyph_run->isSideways, glyph_run->bidiLevel & 1, (IDWriteGeometrySink *)sink)))
1315 ERR("Failed to get glyph run outline, hr %#lx.\n", hr);
1316 ID2D1GeometrySink_Release(sink);
1317 ID2D1PathGeometry_Release(geometry);
1318 return;
1321 if (FAILED(hr = ID2D1GeometrySink_Close(sink)))
1322 ERR("Failed to close geometry sink, hr %#lx.\n", hr);
1323 ID2D1GeometrySink_Release(sink);
1325 transform = &render_target->drawing_state.transform;
1326 prev_transform = *transform;
1327 transform->_31 += baseline_origin.x * transform->_11 + baseline_origin.y * transform->_21;
1328 transform->_32 += baseline_origin.x * transform->_12 + baseline_origin.y * transform->_22;
1329 prev_antialias_mode = d2d_device_context_set_aa_mode_from_text_aa_mode(render_target);
1330 d2d_device_context_fill_geometry(render_target, unsafe_impl_from_ID2D1Geometry((ID2D1Geometry *)geometry),
1331 unsafe_impl_from_ID2D1Brush(brush), NULL);
1332 render_target->drawing_state.antialiasMode = prev_antialias_mode;
1333 *transform = prev_transform;
1335 ID2D1PathGeometry_Release(geometry);
1338 static void d2d_device_context_draw_glyph_run_bitmap(struct d2d_device_context *render_target,
1339 D2D1_POINT_2F baseline_origin, const DWRITE_GLYPH_RUN *glyph_run, ID2D1Brush *brush,
1340 DWRITE_RENDERING_MODE rendering_mode, DWRITE_MEASURING_MODE measuring_mode,
1341 DWRITE_TEXT_ANTIALIAS_MODE antialias_mode)
1343 ID2D1RectangleGeometry *geometry = NULL;
1344 ID2D1BitmapBrush *opacity_brush = NULL;
1345 D2D1_BITMAP_PROPERTIES bitmap_desc;
1346 ID2D1Bitmap *opacity_bitmap = NULL;
1347 IDWriteGlyphRunAnalysis *analysis;
1348 DWRITE_TEXTURE_TYPE texture_type;
1349 D2D1_BRUSH_PROPERTIES brush_desc;
1350 IDWriteFactory2 *dwrite_factory;
1351 D2D1_MATRIX_3X2_F *transform, m;
1352 void *opacity_values = NULL;
1353 size_t opacity_values_size;
1354 D2D1_SIZE_U bitmap_size;
1355 float scale_x, scale_y;
1356 D2D1_RECT_F run_rect;
1357 RECT bounds;
1358 HRESULT hr;
1360 if (FAILED(hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED,
1361 &IID_IDWriteFactory2, (IUnknown **)&dwrite_factory)))
1363 ERR("Failed to create dwrite factory, hr %#lx.\n", hr);
1364 return;
1367 transform = &render_target->drawing_state.transform;
1369 scale_x = render_target->desc.dpiX / 96.0f;
1370 m._11 = transform->_11 * scale_x;
1371 m._21 = transform->_21 * scale_x;
1372 m._31 = transform->_31 * scale_x;
1374 scale_y = render_target->desc.dpiY / 96.0f;
1375 m._12 = transform->_12 * scale_y;
1376 m._22 = transform->_22 * scale_y;
1377 m._32 = transform->_32 * scale_y;
1379 hr = IDWriteFactory2_CreateGlyphRunAnalysis(dwrite_factory, glyph_run, (DWRITE_MATRIX *)&m,
1380 rendering_mode, measuring_mode, DWRITE_GRID_FIT_MODE_DEFAULT, antialias_mode,
1381 baseline_origin.x, baseline_origin.y, &analysis);
1382 IDWriteFactory2_Release(dwrite_factory);
1383 if (FAILED(hr))
1385 ERR("Failed to create glyph run analysis, hr %#lx.\n", hr);
1386 return;
1389 if (rendering_mode == DWRITE_RENDERING_MODE_ALIASED || antialias_mode == DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE)
1390 texture_type = DWRITE_TEXTURE_ALIASED_1x1;
1391 else
1392 texture_type = DWRITE_TEXTURE_CLEARTYPE_3x1;
1394 if (FAILED(hr = IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis, texture_type, &bounds)))
1396 ERR("Failed to get alpha texture bounds, hr %#lx.\n", hr);
1397 goto done;
1400 d2d_size_set(&bitmap_size, bounds.right - bounds.left, bounds.bottom - bounds.top);
1401 if (!bitmap_size.width || !bitmap_size.height)
1403 /* Empty run, nothing to do. */
1404 goto done;
1407 if (texture_type == DWRITE_TEXTURE_CLEARTYPE_3x1)
1408 bitmap_size.width *= 3;
1409 if (!(opacity_values = calloc(bitmap_size.height, bitmap_size.width)))
1411 ERR("Failed to allocate opacity values.\n");
1412 goto done;
1414 opacity_values_size = bitmap_size.height * bitmap_size.width;
1416 if (FAILED(hr = IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis,
1417 texture_type, &bounds, opacity_values, opacity_values_size)))
1419 ERR("Failed to create alpha texture, hr %#lx.\n", hr);
1420 goto done;
1423 bitmap_desc.pixelFormat.format = DXGI_FORMAT_A8_UNORM;
1424 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
1425 bitmap_desc.dpiX = render_target->desc.dpiX;
1426 if (texture_type == DWRITE_TEXTURE_CLEARTYPE_3x1)
1427 bitmap_desc.dpiX *= 3.0f;
1428 bitmap_desc.dpiY = render_target->desc.dpiY;
1429 if (FAILED(hr = d2d_device_context_CreateBitmap(&render_target->ID2D1DeviceContext1_iface,
1430 bitmap_size, opacity_values, bitmap_size.width, &bitmap_desc, &opacity_bitmap)))
1432 ERR("Failed to create opacity bitmap, hr %#lx.\n", hr);
1433 goto done;
1436 d2d_rect_set(&run_rect, bounds.left / scale_x, bounds.top / scale_y,
1437 bounds.right / scale_x, bounds.bottom / scale_y);
1439 brush_desc.opacity = 1.0f;
1440 brush_desc.transform._11 = 1.0f;
1441 brush_desc.transform._12 = 0.0f;
1442 brush_desc.transform._21 = 0.0f;
1443 brush_desc.transform._22 = 1.0f;
1444 brush_desc.transform._31 = run_rect.left;
1445 brush_desc.transform._32 = run_rect.top;
1446 if (FAILED(hr = d2d_device_context_CreateBitmapBrush(&render_target->ID2D1DeviceContext1_iface,
1447 opacity_bitmap, NULL, &brush_desc, &opacity_brush)))
1449 ERR("Failed to create opacity bitmap brush, hr %#lx.\n", hr);
1450 goto done;
1453 if (FAILED(hr = ID2D1Factory_CreateRectangleGeometry(render_target->factory, &run_rect, &geometry)))
1455 ERR("Failed to create geometry, hr %#lx.\n", hr);
1456 goto done;
1459 m = *transform;
1460 *transform = identity;
1461 d2d_device_context_fill_geometry(render_target, unsafe_impl_from_ID2D1Geometry((ID2D1Geometry *)geometry),
1462 unsafe_impl_from_ID2D1Brush(brush), unsafe_impl_from_ID2D1Brush((ID2D1Brush *)opacity_brush));
1463 *transform = m;
1465 done:
1466 if (geometry)
1467 ID2D1RectangleGeometry_Release(geometry);
1468 if (opacity_brush)
1469 ID2D1BitmapBrush_Release(opacity_brush);
1470 if (opacity_bitmap)
1471 ID2D1Bitmap_Release(opacity_bitmap);
1472 free(opacity_values);
1473 IDWriteGlyphRunAnalysis_Release(analysis);
1476 static void d2d_device_context_draw_glyph_run(struct d2d_device_context *context,
1477 D2D1_POINT_2F baseline_origin, const DWRITE_GLYPH_RUN *glyph_run,
1478 const DWRITE_GLYPH_RUN_DESCRIPTION *glyph_run_desc, ID2D1Brush *brush, DWRITE_MEASURING_MODE measuring_mode)
1480 DWRITE_TEXT_ANTIALIAS_MODE antialias_mode = DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE;
1481 IDWriteRenderingParams *rendering_params;
1482 DWRITE_RENDERING_MODE rendering_mode;
1483 HRESULT hr;
1485 if (FAILED(context->error.code))
1486 return;
1488 if (context->target.type == D2D_TARGET_COMMAND_LIST)
1490 d2d_command_list_draw_glyph_run(context->target.command_list, context, baseline_origin, glyph_run,
1491 glyph_run_desc, brush, measuring_mode);
1492 return;
1495 rendering_params = context->text_rendering_params ? context->text_rendering_params
1496 : context->default_text_rendering_params;
1498 rendering_mode = IDWriteRenderingParams_GetRenderingMode(rendering_params);
1500 switch (context->drawing_state.textAntialiasMode)
1502 case D2D1_TEXT_ANTIALIAS_MODE_ALIASED:
1503 if (rendering_mode == DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL
1504 || rendering_mode == DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC
1505 || rendering_mode == DWRITE_RENDERING_MODE_CLEARTYPE_GDI_NATURAL
1506 || rendering_mode == DWRITE_RENDERING_MODE_CLEARTYPE_GDI_CLASSIC)
1507 d2d_device_context_set_error(context, E_INVALIDARG);
1508 break;
1510 case D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE:
1511 if (rendering_mode == DWRITE_RENDERING_MODE_ALIASED
1512 || rendering_mode == DWRITE_RENDERING_MODE_OUTLINE)
1513 d2d_device_context_set_error(context, E_INVALIDARG);
1514 break;
1516 case D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE:
1517 if (rendering_mode == DWRITE_RENDERING_MODE_ALIASED)
1518 d2d_device_context_set_error(context, E_INVALIDARG);
1519 break;
1521 default:
1522 break;
1525 if (FAILED(context->error.code))
1526 return;
1528 rendering_mode = DWRITE_RENDERING_MODE_DEFAULT;
1529 switch (context->drawing_state.textAntialiasMode)
1531 case D2D1_TEXT_ANTIALIAS_MODE_DEFAULT:
1532 if (IDWriteRenderingParams_GetClearTypeLevel(rendering_params) > 0.0f)
1533 antialias_mode = DWRITE_TEXT_ANTIALIAS_MODE_CLEARTYPE;
1534 break;
1536 case D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE:
1537 antialias_mode = DWRITE_TEXT_ANTIALIAS_MODE_CLEARTYPE;
1538 break;
1540 case D2D1_TEXT_ANTIALIAS_MODE_ALIASED:
1541 rendering_mode = DWRITE_RENDERING_MODE_ALIASED;
1542 break;
1544 default:
1545 break;
1548 if (rendering_mode == DWRITE_RENDERING_MODE_DEFAULT)
1550 if (FAILED(hr = IDWriteFontFace_GetRecommendedRenderingMode(glyph_run->fontFace, glyph_run->fontEmSize,
1551 max(context->desc.dpiX, context->desc.dpiY) / 96.0f,
1552 measuring_mode, rendering_params, &rendering_mode)))
1554 ERR("Failed to get recommended rendering mode, hr %#lx.\n", hr);
1555 rendering_mode = DWRITE_RENDERING_MODE_OUTLINE;
1559 if (rendering_mode == DWRITE_RENDERING_MODE_OUTLINE)
1560 d2d_device_context_draw_glyph_run_outline(context, baseline_origin, glyph_run, brush);
1561 else
1562 d2d_device_context_draw_glyph_run_bitmap(context, baseline_origin, glyph_run, brush,
1563 rendering_mode, measuring_mode, antialias_mode);
1566 static void STDMETHODCALLTYPE d2d_device_context_DrawGlyphRun(ID2D1DeviceContext1 *iface,
1567 D2D1_POINT_2F baseline_origin, const DWRITE_GLYPH_RUN *glyph_run, ID2D1Brush *brush,
1568 DWRITE_MEASURING_MODE measuring_mode)
1570 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
1572 TRACE("iface %p, baseline_origin %s, glyph_run %p, brush %p, measuring_mode %#x.\n",
1573 iface, debug_d2d_point_2f(&baseline_origin), glyph_run, brush, measuring_mode);
1575 d2d_device_context_draw_glyph_run(context, baseline_origin, glyph_run, NULL, brush, measuring_mode);
1578 static void STDMETHODCALLTYPE d2d_device_context_SetTransform(ID2D1DeviceContext1 *iface,
1579 const D2D1_MATRIX_3X2_F *transform)
1581 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
1583 TRACE("iface %p, transform %p.\n", iface, transform);
1585 if (context->target.type == D2D_TARGET_COMMAND_LIST)
1586 d2d_command_list_set_transform(context->target.command_list, transform);
1588 context->drawing_state.transform = *transform;
1591 static void STDMETHODCALLTYPE d2d_device_context_GetTransform(ID2D1DeviceContext1 *iface,
1592 D2D1_MATRIX_3X2_F *transform)
1594 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1596 TRACE("iface %p, transform %p.\n", iface, transform);
1598 *transform = render_target->drawing_state.transform;
1601 static void STDMETHODCALLTYPE d2d_device_context_SetAntialiasMode(ID2D1DeviceContext1 *iface,
1602 D2D1_ANTIALIAS_MODE antialias_mode)
1604 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
1606 TRACE("iface %p, antialias_mode %#x stub!\n", iface, antialias_mode);
1608 if (context->target.type == D2D_TARGET_COMMAND_LIST)
1609 d2d_command_list_set_antialias_mode(context->target.command_list, antialias_mode);
1611 context->drawing_state.antialiasMode = antialias_mode;
1614 static D2D1_ANTIALIAS_MODE STDMETHODCALLTYPE d2d_device_context_GetAntialiasMode(ID2D1DeviceContext1 *iface)
1616 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1618 TRACE("iface %p.\n", iface);
1620 return render_target->drawing_state.antialiasMode;
1623 static void STDMETHODCALLTYPE d2d_device_context_SetTextAntialiasMode(ID2D1DeviceContext1 *iface,
1624 D2D1_TEXT_ANTIALIAS_MODE antialias_mode)
1626 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
1628 TRACE("iface %p, antialias_mode %#x.\n", iface, antialias_mode);
1630 if (context->target.type == D2D_TARGET_COMMAND_LIST)
1631 d2d_command_list_set_text_antialias_mode(context->target.command_list, antialias_mode);
1633 context->drawing_state.textAntialiasMode = antialias_mode;
1636 static D2D1_TEXT_ANTIALIAS_MODE STDMETHODCALLTYPE d2d_device_context_GetTextAntialiasMode(ID2D1DeviceContext1 *iface)
1638 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1640 TRACE("iface %p.\n", iface);
1642 return render_target->drawing_state.textAntialiasMode;
1645 static void STDMETHODCALLTYPE d2d_device_context_SetTextRenderingParams(ID2D1DeviceContext1 *iface,
1646 IDWriteRenderingParams *text_rendering_params)
1648 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
1650 TRACE("iface %p, text_rendering_params %p.\n", iface, text_rendering_params);
1652 if (context->target.type == D2D_TARGET_COMMAND_LIST)
1653 d2d_command_list_set_text_rendering_params(context->target.command_list, text_rendering_params);
1655 if (text_rendering_params)
1656 IDWriteRenderingParams_AddRef(text_rendering_params);
1657 if (context->text_rendering_params)
1658 IDWriteRenderingParams_Release(context->text_rendering_params);
1659 context->text_rendering_params = text_rendering_params;
1662 static void STDMETHODCALLTYPE d2d_device_context_GetTextRenderingParams(ID2D1DeviceContext1 *iface,
1663 IDWriteRenderingParams **text_rendering_params)
1665 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1667 TRACE("iface %p, text_rendering_params %p.\n", iface, text_rendering_params);
1669 if ((*text_rendering_params = render_target->text_rendering_params))
1670 IDWriteRenderingParams_AddRef(*text_rendering_params);
1673 static void STDMETHODCALLTYPE d2d_device_context_SetTags(ID2D1DeviceContext1 *iface, D2D1_TAG tag1, D2D1_TAG tag2)
1675 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
1677 TRACE("iface %p, tag1 %s, tag2 %s.\n", iface, wine_dbgstr_longlong(tag1), wine_dbgstr_longlong(tag2));
1679 if (context->target.type == D2D_TARGET_COMMAND_LIST)
1680 d2d_command_list_set_tags(context->target.command_list, tag1, tag2);
1682 context->drawing_state.tag1 = tag1;
1683 context->drawing_state.tag2 = tag2;
1686 static void STDMETHODCALLTYPE d2d_device_context_GetTags(ID2D1DeviceContext1 *iface, D2D1_TAG *tag1, D2D1_TAG *tag2)
1688 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1690 TRACE("iface %p, tag1 %p, tag2 %p.\n", iface, tag1, tag2);
1692 *tag1 = render_target->drawing_state.tag1;
1693 *tag2 = render_target->drawing_state.tag2;
1696 static void STDMETHODCALLTYPE d2d_device_context_PushLayer(ID2D1DeviceContext1 *iface,
1697 const D2D1_LAYER_PARAMETERS *layer_parameters, ID2D1Layer *layer)
1699 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
1701 FIXME("iface %p, layer_parameters %p, layer %p stub!\n", iface, layer_parameters, layer);
1703 if (context->target.type == D2D_TARGET_COMMAND_LIST)
1705 D2D1_LAYER_PARAMETERS1 parameters;
1707 memcpy(&parameters, layer_parameters, sizeof(*layer_parameters));
1708 parameters.layerOptions = D2D1_LAYER_OPTIONS1_NONE;
1709 d2d_command_list_push_layer(context->target.command_list, context, &parameters, layer);
1713 static void STDMETHODCALLTYPE d2d_device_context_PopLayer(ID2D1DeviceContext1 *iface)
1715 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
1717 FIXME("iface %p stub!\n", iface);
1719 if (context->target.type == D2D_TARGET_COMMAND_LIST)
1720 d2d_command_list_pop_layer(context->target.command_list);
1723 static HRESULT STDMETHODCALLTYPE d2d_device_context_Flush(ID2D1DeviceContext1 *iface, D2D1_TAG *tag1, D2D1_TAG *tag2)
1725 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
1727 FIXME("iface %p, tag1 %p, tag2 %p stub!\n", iface, tag1, tag2);
1729 if (context->ops && context->ops->device_context_present)
1730 context->ops->device_context_present(context->outer_unknown);
1732 return E_NOTIMPL;
1735 static void STDMETHODCALLTYPE d2d_device_context_SaveDrawingState(ID2D1DeviceContext1 *iface,
1736 ID2D1DrawingStateBlock *state_block)
1738 struct d2d_state_block *state_block_impl = unsafe_impl_from_ID2D1DrawingStateBlock(state_block);
1739 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1741 TRACE("iface %p, state_block %p.\n", iface, state_block);
1743 state_block_impl->drawing_state = render_target->drawing_state;
1744 if (render_target->text_rendering_params)
1745 IDWriteRenderingParams_AddRef(render_target->text_rendering_params);
1746 if (state_block_impl->text_rendering_params)
1747 IDWriteRenderingParams_Release(state_block_impl->text_rendering_params);
1748 state_block_impl->text_rendering_params = render_target->text_rendering_params;
1751 static void STDMETHODCALLTYPE d2d_device_context_RestoreDrawingState(ID2D1DeviceContext1 *iface,
1752 ID2D1DrawingStateBlock *state_block)
1754 struct d2d_state_block *state_block_impl = unsafe_impl_from_ID2D1DrawingStateBlock(state_block);
1755 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
1757 TRACE("iface %p, state_block %p.\n", iface, state_block);
1759 if (context->target.type == D2D_TARGET_COMMAND_LIST)
1761 struct d2d_command_list *command_list = context->target.command_list;
1763 if (context->drawing_state.antialiasMode != state_block_impl->drawing_state.antialiasMode)
1764 d2d_command_list_set_antialias_mode(command_list, state_block_impl->drawing_state.antialiasMode);
1765 d2d_command_list_set_text_antialias_mode(command_list, state_block_impl->drawing_state.textAntialiasMode);
1766 d2d_command_list_set_tags(command_list, state_block_impl->drawing_state.tag1, state_block_impl->drawing_state.tag2);
1767 d2d_command_list_set_transform(command_list, &state_block_impl->drawing_state.transform);
1768 d2d_command_list_set_primitive_blend(command_list, state_block_impl->drawing_state.primitiveBlend);
1769 d2d_command_list_set_unit_mode(command_list, state_block_impl->drawing_state.unitMode);
1770 d2d_command_list_set_text_rendering_params(command_list, state_block_impl->text_rendering_params);
1773 context->drawing_state = state_block_impl->drawing_state;
1774 if (state_block_impl->text_rendering_params)
1775 IDWriteRenderingParams_AddRef(state_block_impl->text_rendering_params);
1776 if (context->text_rendering_params)
1777 IDWriteRenderingParams_Release(context->text_rendering_params);
1778 context->text_rendering_params = state_block_impl->text_rendering_params;
1781 static void STDMETHODCALLTYPE d2d_device_context_PushAxisAlignedClip(ID2D1DeviceContext1 *iface,
1782 const D2D1_RECT_F *clip_rect, D2D1_ANTIALIAS_MODE antialias_mode)
1784 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
1785 D2D1_RECT_F transformed_rect;
1786 float x_scale, y_scale;
1787 D2D1_POINT_2F point;
1789 TRACE("iface %p, clip_rect %s, antialias_mode %#x.\n", iface, debug_d2d_rect_f(clip_rect), antialias_mode);
1791 if (context->target.type == D2D_TARGET_COMMAND_LIST)
1792 d2d_command_list_push_clip(context->target.command_list, clip_rect, antialias_mode);
1794 if (antialias_mode != D2D1_ANTIALIAS_MODE_ALIASED)
1795 FIXME("Ignoring antialias_mode %#x.\n", antialias_mode);
1797 x_scale = context->desc.dpiX / 96.0f;
1798 y_scale = context->desc.dpiY / 96.0f;
1799 d2d_point_transform(&point, &context->drawing_state.transform,
1800 clip_rect->left * x_scale, clip_rect->top * y_scale);
1801 d2d_rect_set(&transformed_rect, point.x, point.y, point.x, point.y);
1802 d2d_point_transform(&point, &context->drawing_state.transform,
1803 clip_rect->left * x_scale, clip_rect->bottom * y_scale);
1804 d2d_rect_expand(&transformed_rect, &point);
1805 d2d_point_transform(&point, &context->drawing_state.transform,
1806 clip_rect->right * x_scale, clip_rect->top * y_scale);
1807 d2d_rect_expand(&transformed_rect, &point);
1808 d2d_point_transform(&point, &context->drawing_state.transform,
1809 clip_rect->right * x_scale, clip_rect->bottom * y_scale);
1810 d2d_rect_expand(&transformed_rect, &point);
1812 if (!d2d_clip_stack_push(&context->clip_stack, &transformed_rect))
1813 WARN("Failed to push clip rect.\n");
1816 static void STDMETHODCALLTYPE d2d_device_context_PopAxisAlignedClip(ID2D1DeviceContext1 *iface)
1818 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
1820 TRACE("iface %p.\n", iface);
1822 if (context->target.type == D2D_TARGET_COMMAND_LIST)
1823 d2d_command_list_pop_clip(context->target.command_list);
1825 d2d_clip_stack_pop(&context->clip_stack);
1828 static void STDMETHODCALLTYPE d2d_device_context_Clear(ID2D1DeviceContext1 *iface, const D2D1_COLOR_F *colour)
1830 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
1831 D3D11_MAPPED_SUBRESOURCE map_desc;
1832 ID3D11DeviceContext *d3d_context;
1833 struct d2d_ps_cb *ps_cb_data;
1834 struct d2d_vs_cb *vs_cb_data;
1835 D2D1_COLOR_F *c;
1836 HRESULT hr;
1838 TRACE("iface %p, colour %p.\n", iface, colour);
1840 if (context->target.type == D2D_TARGET_COMMAND_LIST)
1842 d2d_command_list_clear(context->target.command_list, colour);
1843 return;
1846 ID3D11Device1_GetImmediateContext(context->d3d_device, &d3d_context);
1848 if (FAILED(hr = ID3D11DeviceContext_Map(d3d_context, (ID3D11Resource *)context->vs_cb,
1849 0, D3D11_MAP_WRITE_DISCARD, 0, &map_desc)))
1851 WARN("Failed to map vs constant buffer, hr %#lx.\n", hr);
1852 ID3D11DeviceContext_Release(d3d_context);
1853 return;
1856 vs_cb_data = map_desc.pData;
1857 vs_cb_data->transform_geometry._11 = 1.0f;
1858 vs_cb_data->transform_geometry._21 = 0.0f;
1859 vs_cb_data->transform_geometry._31 = 0.0f;
1860 vs_cb_data->transform_geometry.pad0 = 0.0f;
1861 vs_cb_data->transform_geometry._12 = 0.0f;
1862 vs_cb_data->transform_geometry._22 = 1.0f;
1863 vs_cb_data->transform_geometry._32 = 0.0f;
1864 vs_cb_data->transform_geometry.stroke_width = 0.0f;
1865 vs_cb_data->transform_rtx.x = 1.0f;
1866 vs_cb_data->transform_rtx.y = 0.0f;
1867 vs_cb_data->transform_rtx.z = 1.0f;
1868 vs_cb_data->transform_rtx.w = 1.0f;
1869 vs_cb_data->transform_rty.x = 0.0f;
1870 vs_cb_data->transform_rty.y = 1.0f;
1871 vs_cb_data->transform_rty.z = 1.0f;
1872 vs_cb_data->transform_rty.w = -1.0f;
1874 ID3D11DeviceContext_Unmap(d3d_context, (ID3D11Resource *)context->vs_cb, 0);
1876 if (FAILED(hr = ID3D11DeviceContext_Map(d3d_context, (ID3D11Resource *)context->ps_cb,
1877 0, D3D11_MAP_WRITE_DISCARD, 0, &map_desc)))
1879 WARN("Failed to map ps constant buffer, hr %#lx.\n", hr);
1880 ID3D11DeviceContext_Release(d3d_context);
1881 return;
1884 ps_cb_data = map_desc.pData;
1885 memset(ps_cb_data, 0, sizeof(*ps_cb_data));
1886 ps_cb_data->colour_brush.type = D2D_BRUSH_TYPE_SOLID;
1887 ps_cb_data->colour_brush.opacity = 1.0f;
1888 ps_cb_data->opacity_brush.type = D2D_BRUSH_TYPE_COUNT;
1889 c = &ps_cb_data->colour_brush.u.solid.colour;
1890 if (colour)
1891 *c = *colour;
1892 if (context->desc.pixelFormat.alphaMode == D2D1_ALPHA_MODE_IGNORE)
1893 c->a = 1.0f;
1894 c->r *= c->a;
1895 c->g *= c->a;
1896 c->b *= c->a;
1898 ID3D11DeviceContext_Unmap(d3d_context, (ID3D11Resource *)context->ps_cb, 0);
1899 ID3D11DeviceContext_Release(d3d_context);
1901 d2d_device_context_draw(context, D2D_SHAPE_TYPE_TRIANGLE, context->ib, 6,
1902 context->vb, context->vb_stride, NULL, NULL);
1905 static void STDMETHODCALLTYPE d2d_device_context_BeginDraw(ID2D1DeviceContext1 *iface)
1907 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
1909 TRACE("iface %p.\n", iface);
1911 if (context->target.type == D2D_TARGET_COMMAND_LIST)
1912 d2d_command_list_begin_draw(context->target.command_list, context);
1914 memset(&context->error, 0, sizeof(context->error));
1917 static HRESULT STDMETHODCALLTYPE d2d_device_context_EndDraw(ID2D1DeviceContext1 *iface,
1918 D2D1_TAG *tag1, D2D1_TAG *tag2)
1920 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
1921 HRESULT hr;
1923 TRACE("iface %p, tag1 %p, tag2 %p.\n", iface, tag1, tag2);
1925 if (context->target.type == D2D_TARGET_COMMAND_LIST)
1927 FIXME("Unimplemented for command list target.\n");
1928 return E_NOTIMPL;
1931 if (tag1)
1932 *tag1 = context->error.tag1;
1933 if (tag2)
1934 *tag2 = context->error.tag2;
1936 if (context->ops && context->ops->device_context_present)
1938 if (FAILED(hr = context->ops->device_context_present(context->outer_unknown)))
1939 context->error.code = hr;
1942 return context->error.code;
1945 static D2D1_PIXEL_FORMAT * STDMETHODCALLTYPE d2d_device_context_GetPixelFormat(ID2D1DeviceContext1 *iface,
1946 D2D1_PIXEL_FORMAT *format)
1948 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1950 TRACE("iface %p, format %p.\n", iface, format);
1952 *format = render_target->desc.pixelFormat;
1953 return format;
1956 static void STDMETHODCALLTYPE d2d_device_context_SetDpi(ID2D1DeviceContext1 *iface, float dpi_x, float dpi_y)
1958 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1960 TRACE("iface %p, dpi_x %.8e, dpi_y %.8e.\n", iface, dpi_x, dpi_y);
1962 if (dpi_x == 0.0f && dpi_y == 0.0f)
1964 dpi_x = 96.0f;
1965 dpi_y = 96.0f;
1967 else if (dpi_x <= 0.0f || dpi_y <= 0.0f)
1968 return;
1970 render_target->desc.dpiX = dpi_x;
1971 render_target->desc.dpiY = dpi_y;
1974 static void STDMETHODCALLTYPE d2d_device_context_GetDpi(ID2D1DeviceContext1 *iface, float *dpi_x, float *dpi_y)
1976 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1978 TRACE("iface %p, dpi_x %p, dpi_y %p.\n", iface, dpi_x, dpi_y);
1980 *dpi_x = render_target->desc.dpiX;
1981 *dpi_y = render_target->desc.dpiY;
1984 static D2D1_SIZE_F * STDMETHODCALLTYPE d2d_device_context_GetSize(ID2D1DeviceContext1 *iface, D2D1_SIZE_F *size)
1986 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1988 TRACE("iface %p, size %p.\n", iface, size);
1990 size->width = render_target->pixel_size.width / (render_target->desc.dpiX / 96.0f);
1991 size->height = render_target->pixel_size.height / (render_target->desc.dpiY / 96.0f);
1992 return size;
1995 static D2D1_SIZE_U * STDMETHODCALLTYPE d2d_device_context_GetPixelSize(ID2D1DeviceContext1 *iface,
1996 D2D1_SIZE_U *pixel_size)
1998 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
2000 TRACE("iface %p, pixel_size %p.\n", iface, pixel_size);
2002 *pixel_size = render_target->pixel_size;
2003 return pixel_size;
2006 static UINT32 STDMETHODCALLTYPE d2d_device_context_GetMaximumBitmapSize(ID2D1DeviceContext1 *iface)
2008 TRACE("iface %p.\n", iface);
2010 return D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION;
2013 static BOOL STDMETHODCALLTYPE d2d_device_context_IsSupported(ID2D1DeviceContext1 *iface,
2014 const D2D1_RENDER_TARGET_PROPERTIES *desc)
2016 FIXME("iface %p, desc %p stub!\n", iface, desc);
2018 return FALSE;
2021 static HRESULT STDMETHODCALLTYPE d2d_device_context_ID2D1DeviceContext_CreateBitmap(ID2D1DeviceContext1 *iface,
2022 D2D1_SIZE_U size, const void *src_data, UINT32 pitch,
2023 const D2D1_BITMAP_PROPERTIES1 *desc, ID2D1Bitmap1 **bitmap)
2025 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
2026 struct d2d_bitmap *object;
2027 HRESULT hr;
2029 TRACE("iface %p, size {%u, %u}, src_data %p, pitch %u, desc %p, bitmap %p.\n",
2030 iface, size.width, size.height, src_data, pitch, desc, bitmap);
2032 if (SUCCEEDED(hr = d2d_bitmap_create(context, size, src_data, pitch, desc, &object)))
2033 *bitmap = &object->ID2D1Bitmap1_iface;
2035 return hr;
2038 static HRESULT STDMETHODCALLTYPE d2d_device_context_ID2D1DeviceContext_CreateBitmapFromWicBitmap(
2039 ID2D1DeviceContext1 *iface, IWICBitmapSource *bitmap_source,
2040 const D2D1_BITMAP_PROPERTIES1 *desc, ID2D1Bitmap1 **bitmap)
2042 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
2043 struct d2d_bitmap *object;
2044 HRESULT hr;
2046 TRACE("iface %p, bitmap_source %p, desc %p, bitmap %p.\n", iface, bitmap_source, desc, bitmap);
2048 if (SUCCEEDED(hr = d2d_bitmap_create_from_wic_bitmap(context, bitmap_source, desc, &object)))
2049 *bitmap = &object->ID2D1Bitmap1_iface;
2051 return hr;
2054 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateColorContext(ID2D1DeviceContext1 *iface,
2055 D2D1_COLOR_SPACE space, const BYTE *profile, UINT32 profile_size, ID2D1ColorContext **color_context)
2057 FIXME("iface %p, space %#x, profile %p, profile_size %u, color_context %p stub!\n",
2058 iface, space, profile, profile_size, color_context);
2060 return E_NOTIMPL;
2063 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateColorContextFromFilename(ID2D1DeviceContext1 *iface,
2064 const WCHAR *filename, ID2D1ColorContext **color_context)
2066 FIXME("iface %p, filename %s, color_context %p stub!\n", iface, debugstr_w(filename), color_context);
2068 return E_NOTIMPL;
2071 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateColorContextFromWicColorContext(ID2D1DeviceContext1 *iface,
2072 IWICColorContext *wic_color_context, ID2D1ColorContext **color_context)
2074 FIXME("iface %p, wic_color_context %p, color_context %p stub!\n", iface, wic_color_context, color_context);
2076 return E_NOTIMPL;
2079 static BOOL d2d_bitmap_check_options_with_surface(unsigned int options, unsigned int surface_options)
2081 switch (options)
2083 case D2D1_BITMAP_OPTIONS_NONE:
2084 case D2D1_BITMAP_OPTIONS_TARGET:
2085 case D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW:
2086 case D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW | D2D1_BITMAP_OPTIONS_GDI_COMPATIBLE:
2087 case D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_GDI_COMPATIBLE:
2088 case D2D1_BITMAP_OPTIONS_CANNOT_DRAW | D2D1_BITMAP_OPTIONS_CPU_READ:
2089 case D2D1_BITMAP_OPTIONS_CANNOT_DRAW:
2090 break;
2091 default:
2092 WARN("Invalid bitmap options %#x.\n", options);
2093 return FALSE;
2096 if (options && (options & D2D1_BITMAP_OPTIONS_TARGET) != (surface_options & D2D1_BITMAP_OPTIONS_TARGET))
2097 return FALSE;
2098 if (options & D2D1_BITMAP_OPTIONS_TARGET)
2100 if (!(options & D2D1_BITMAP_OPTIONS_CANNOT_DRAW) && (surface_options & D2D1_BITMAP_OPTIONS_CANNOT_DRAW))
2101 return FALSE;
2102 if (options & D2D1_BITMAP_OPTIONS_GDI_COMPATIBLE && !(surface_options & D2D1_BITMAP_OPTIONS_GDI_COMPATIBLE))
2103 return FALSE;
2104 return TRUE;
2107 if (options & D2D1_BITMAP_OPTIONS_CANNOT_DRAW)
2109 if (!(surface_options & D2D1_BITMAP_OPTIONS_CANNOT_DRAW))
2110 return FALSE;
2112 if (options & D2D1_BITMAP_OPTIONS_CPU_READ && !(surface_options & D2D1_BITMAP_OPTIONS_CPU_READ))
2113 return FALSE;
2116 return TRUE;
2119 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateBitmapFromDxgiSurface(ID2D1DeviceContext1 *iface,
2120 IDXGISurface *surface, const D2D1_BITMAP_PROPERTIES1 *desc, ID2D1Bitmap1 **bitmap)
2122 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
2123 D2D1_BITMAP_PROPERTIES1 bitmap_desc;
2124 unsigned int surface_options;
2125 struct d2d_bitmap *object;
2126 HRESULT hr;
2128 TRACE("iface %p, surface %p, desc %p, bitmap %p.\n", iface, surface, desc, bitmap);
2130 surface_options = d2d_get_bitmap_options_for_surface(surface);
2132 if (desc)
2134 if (!d2d_bitmap_check_options_with_surface(desc->bitmapOptions, surface_options))
2136 WARN("Incompatible bitmap options %#x, surface options %#x.\n",
2137 desc->bitmapOptions, surface_options);
2138 return E_INVALIDARG;
2141 else
2143 DXGI_SURFACE_DESC surface_desc;
2145 if (FAILED(hr = IDXGISurface_GetDesc(surface, &surface_desc)))
2147 WARN("Failed to get surface desc, hr %#lx.\n", hr);
2148 return hr;
2151 memset(&bitmap_desc, 0, sizeof(bitmap_desc));
2152 bitmap_desc.pixelFormat.format = surface_desc.Format;
2153 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
2154 bitmap_desc.bitmapOptions = surface_options;
2155 desc = &bitmap_desc;
2158 if (SUCCEEDED(hr = d2d_bitmap_create_shared(context, &IID_IDXGISurface, surface, desc, &object)))
2159 *bitmap = &object->ID2D1Bitmap1_iface;
2161 return hr;
2164 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateEffect(ID2D1DeviceContext1 *iface,
2165 REFCLSID effect_id, ID2D1Effect **effect)
2167 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
2169 TRACE("iface %p, effect_id %s, effect %p.\n", iface, debugstr_guid(effect_id), effect);
2171 return d2d_effect_create(context, effect_id, effect);
2174 static HRESULT STDMETHODCALLTYPE d2d_device_context_ID2D1DeviceContext_CreateGradientStopCollection(
2175 ID2D1DeviceContext1 *iface, const D2D1_GRADIENT_STOP *stops, UINT32 stop_count,
2176 D2D1_COLOR_SPACE preinterpolation_space, D2D1_COLOR_SPACE postinterpolation_space,
2177 D2D1_BUFFER_PRECISION buffer_precision, D2D1_EXTEND_MODE extend_mode,
2178 D2D1_COLOR_INTERPOLATION_MODE color_interpolation_mode, ID2D1GradientStopCollection1 **gradient)
2180 FIXME("iface %p, stops %p, stop_count %u, preinterpolation_space %#x, postinterpolation_space %#x, "
2181 "buffer_precision %#x, extend_mode %#x, color_interpolation_mode %#x, gradient %p stub!\n",
2182 iface, stops, stop_count, preinterpolation_space, postinterpolation_space,
2183 buffer_precision, extend_mode, color_interpolation_mode, gradient);
2185 return E_NOTIMPL;
2188 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateImageBrush(ID2D1DeviceContext1 *iface,
2189 ID2D1Image *image, const D2D1_IMAGE_BRUSH_PROPERTIES *image_brush_desc,
2190 const D2D1_BRUSH_PROPERTIES *brush_desc, ID2D1ImageBrush **brush)
2192 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
2193 struct d2d_brush *object;
2194 HRESULT hr;
2196 TRACE("iface %p, image %p, image_brush_desc %p, brush_desc %p, brush %p.\n", iface, image, image_brush_desc,
2197 brush_desc, brush);
2199 if (SUCCEEDED(hr = d2d_image_brush_create(context->factory, image, image_brush_desc,
2200 brush_desc, &object)))
2201 *brush = (ID2D1ImageBrush *)&object->ID2D1Brush_iface;
2203 return hr;
2206 static HRESULT STDMETHODCALLTYPE d2d_device_context_ID2D1DeviceContext_CreateBitmapBrush(ID2D1DeviceContext1 *iface,
2207 ID2D1Bitmap *bitmap, const D2D1_BITMAP_BRUSH_PROPERTIES1 *bitmap_brush_desc,
2208 const D2D1_BRUSH_PROPERTIES *brush_desc, ID2D1BitmapBrush1 **brush)
2210 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
2211 struct d2d_brush *object;
2212 HRESULT hr;
2214 TRACE("iface %p, bitmap %p, bitmap_brush_desc %p, brush_desc %p, brush %p.\n", iface, bitmap, bitmap_brush_desc,
2215 brush_desc, brush);
2217 if (SUCCEEDED(hr = d2d_bitmap_brush_create(context->factory, bitmap, bitmap_brush_desc, brush_desc, &object)))
2218 *brush = (ID2D1BitmapBrush1 *)&object->ID2D1Brush_iface;
2220 return hr;
2223 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateCommandList(ID2D1DeviceContext1 *iface,
2224 ID2D1CommandList **command_list)
2226 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
2227 struct d2d_command_list *object;
2228 HRESULT hr;
2230 TRACE("iface %p, command_list %p.\n", iface, command_list);
2232 if (SUCCEEDED(hr = d2d_command_list_create(context->factory, &object)))
2233 *command_list = &object->ID2D1CommandList_iface;
2235 return hr;
2238 static BOOL STDMETHODCALLTYPE d2d_device_context_IsDxgiFormatSupported(ID2D1DeviceContext1 *iface, DXGI_FORMAT format)
2240 FIXME("iface %p, format %#x stub!\n", iface, format);
2242 return FALSE;
2245 static BOOL STDMETHODCALLTYPE d2d_device_context_IsBufferPrecisionSupported(ID2D1DeviceContext1 *iface,
2246 D2D1_BUFFER_PRECISION buffer_precision)
2248 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
2249 DXGI_FORMAT format;
2250 UINT support = 0;
2251 HRESULT hr;
2253 TRACE("iface %p, buffer_precision %u.\n", iface, buffer_precision);
2255 switch (buffer_precision)
2257 case D2D1_BUFFER_PRECISION_8BPC_UNORM: format = DXGI_FORMAT_R8G8B8A8_UNORM; break;
2258 case D2D1_BUFFER_PRECISION_8BPC_UNORM_SRGB: format = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB; break;
2259 case D2D1_BUFFER_PRECISION_16BPC_UNORM: format = DXGI_FORMAT_R16G16B16A16_UNORM; break;
2260 case D2D1_BUFFER_PRECISION_16BPC_FLOAT: format = DXGI_FORMAT_R16G16B16A16_FLOAT; break;
2261 case D2D1_BUFFER_PRECISION_32BPC_FLOAT: format = DXGI_FORMAT_R32G32B32A32_FLOAT; break;
2262 default:
2263 WARN("Unexpected precision %u.\n", buffer_precision);
2264 return FALSE;
2267 if (FAILED(hr = ID3D11Device1_CheckFormatSupport(context->d3d_device, format, &support)))
2269 WARN("Format support check failed, hr %#lx.\n", hr);
2272 return !!(support & D3D11_FORMAT_SUPPORT_BUFFER);
2275 static void STDMETHODCALLTYPE d2d_device_context_GetImageLocalBounds(ID2D1DeviceContext1 *iface,
2276 ID2D1Image *image, D2D1_RECT_F *local_bounds)
2278 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
2279 D2D_SIZE_U pixel_size;
2280 ID2D1Bitmap *bitmap;
2281 D2D_SIZE_F size;
2283 TRACE("iface %p, image %p, local_bounds %p.\n", iface, image, local_bounds);
2285 if (SUCCEEDED(ID2D1Image_QueryInterface(image, &IID_ID2D1Bitmap, (void **)&bitmap)))
2287 local_bounds->left = 0.0f;
2288 local_bounds->top = 0.0f;
2289 switch (context->drawing_state.unitMode)
2291 case D2D1_UNIT_MODE_DIPS:
2292 size = ID2D1Bitmap_GetSize(bitmap);
2293 local_bounds->right = size.width;
2294 local_bounds->bottom = size.height;
2295 break;
2297 case D2D1_UNIT_MODE_PIXELS:
2298 pixel_size = ID2D1Bitmap_GetPixelSize(bitmap);
2299 local_bounds->right = pixel_size.width;
2300 local_bounds->bottom = pixel_size.height;
2301 break;
2303 default:
2304 WARN("Unknown unit mode %#x.\n", context->drawing_state.unitMode);
2305 break;
2307 ID2D1Bitmap_Release(bitmap);
2309 else
2311 FIXME("Unable to get local bounds of image %p.\n", image);
2315 static HRESULT STDMETHODCALLTYPE d2d_device_context_GetImageWorldBounds(ID2D1DeviceContext1 *iface,
2316 ID2D1Image *image, D2D1_RECT_F *world_bounds)
2318 FIXME("iface %p, image %p, world_bounds %p stub!\n", iface, image, world_bounds);
2320 return E_NOTIMPL;
2323 static HRESULT STDMETHODCALLTYPE d2d_device_context_GetGlyphRunWorldBounds(ID2D1DeviceContext1 *iface,
2324 D2D1_POINT_2F baseline_origin, const DWRITE_GLYPH_RUN *glyph_run,
2325 DWRITE_MEASURING_MODE measuring_mode, D2D1_RECT_F *bounds)
2327 FIXME("iface %p, baseline_origin %s, glyph_run %p, measuring_mode %#x, bounds %p stub!\n",
2328 iface, debug_d2d_point_2f(&baseline_origin), glyph_run, measuring_mode, bounds);
2330 return E_NOTIMPL;
2333 static void STDMETHODCALLTYPE d2d_device_context_GetDevice(ID2D1DeviceContext1 *iface, ID2D1Device **device)
2335 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
2337 TRACE("iface %p, device %p.\n", iface, device);
2339 *device = (ID2D1Device *)context->device;
2340 ID2D1Device_AddRef(*device);
2343 static void d2d_device_context_reset_target(struct d2d_device_context *context)
2345 if (!context->target.object)
2346 return;
2348 IUnknown_Release(context->target.object);
2349 memset(&context->target, 0, sizeof(context->target));
2351 /* Note that DPI settings are kept. */
2352 memset(&context->desc.pixelFormat, 0, sizeof(context->desc.pixelFormat));
2353 memset(&context->pixel_size, 0, sizeof(context->pixel_size));
2355 if (context->bs)
2356 ID3D11BlendState_Release(context->bs);
2357 context->bs = NULL;
2360 static void STDMETHODCALLTYPE d2d_device_context_SetTarget(ID2D1DeviceContext1 *iface, ID2D1Image *target)
2362 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
2363 struct d2d_command_list *command_list_impl;
2364 struct d2d_bitmap *bitmap_impl;
2365 ID2D1CommandList *command_list;
2366 D3D11_BLEND_DESC blend_desc;
2367 ID2D1Bitmap *bitmap;
2368 HRESULT hr;
2370 TRACE("iface %p, target %p.\n", iface, target);
2372 if (!target)
2374 d2d_device_context_reset_target(context);
2375 return;
2378 if (SUCCEEDED(ID2D1Image_QueryInterface(target, &IID_ID2D1Bitmap, (void **)&bitmap)))
2380 bitmap_impl = unsafe_impl_from_ID2D1Bitmap(bitmap);
2382 if (!(bitmap_impl->options & D2D1_BITMAP_OPTIONS_TARGET))
2384 ID2D1Bitmap_Release(bitmap);
2385 d2d_device_context_set_error(context, D2DERR_INVALID_TARGET);
2386 return;
2389 d2d_device_context_reset_target(context);
2391 /* Set sizes and pixel format. */
2392 context->pixel_size = bitmap_impl->pixel_size;
2393 context->desc.pixelFormat = bitmap_impl->format;
2394 context->target.bitmap = bitmap_impl;
2395 context->target.object = target;
2396 context->target.type = D2D_TARGET_BITMAP;
2398 memset(&blend_desc, 0, sizeof(blend_desc));
2399 blend_desc.IndependentBlendEnable = FALSE;
2400 blend_desc.RenderTarget[0].BlendEnable = TRUE;
2401 blend_desc.RenderTarget[0].SrcBlend = D3D11_BLEND_ONE;
2402 blend_desc.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA;
2403 blend_desc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;
2404 blend_desc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE;
2405 blend_desc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_INV_SRC_ALPHA;
2406 blend_desc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
2407 blend_desc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
2408 if (FAILED(hr = ID3D11Device1_CreateBlendState(context->d3d_device, &blend_desc, &context->bs)))
2409 WARN("Failed to create blend state, hr %#lx.\n", hr);
2411 else if (SUCCEEDED(ID2D1Image_QueryInterface(target, &IID_ID2D1CommandList, (void **)&command_list)))
2413 command_list_impl = unsafe_impl_from_ID2D1CommandList(command_list);
2415 d2d_device_context_reset_target(context);
2417 context->target.command_list = command_list_impl;
2418 context->target.object = target;
2419 context->target.type = D2D_TARGET_COMMAND_LIST;
2421 else
2423 WARN("Unsupported target type.\n");
2427 static void STDMETHODCALLTYPE d2d_device_context_GetTarget(ID2D1DeviceContext1 *iface, ID2D1Image **target)
2429 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
2431 TRACE("iface %p, target %p.\n", iface, target);
2433 *target = context->target.object ? context->target.object : NULL;
2434 if (*target)
2435 ID2D1Image_AddRef(*target);
2438 static void STDMETHODCALLTYPE d2d_device_context_SetRenderingControls(ID2D1DeviceContext1 *iface,
2439 const D2D1_RENDERING_CONTROLS *rendering_controls)
2441 FIXME("iface %p, rendering_controls %p stub!\n", iface, rendering_controls);
2444 static void STDMETHODCALLTYPE d2d_device_context_GetRenderingControls(ID2D1DeviceContext1 *iface,
2445 D2D1_RENDERING_CONTROLS *rendering_controls)
2447 FIXME("iface %p, rendering_controls %p stub!\n", iface, rendering_controls);
2450 static void STDMETHODCALLTYPE d2d_device_context_SetPrimitiveBlend(ID2D1DeviceContext1 *iface,
2451 D2D1_PRIMITIVE_BLEND primitive_blend)
2453 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
2455 TRACE("iface %p, primitive_blend %u.\n", iface, primitive_blend);
2457 if (primitive_blend > D2D1_PRIMITIVE_BLEND_MAX)
2459 WARN("Unknown blend mode %u.\n", primitive_blend);
2460 return;
2463 if (context->target.type == D2D_TARGET_COMMAND_LIST)
2464 d2d_command_list_set_primitive_blend(context->target.command_list, primitive_blend);
2466 context->drawing_state.primitiveBlend = primitive_blend;
2469 static D2D1_PRIMITIVE_BLEND STDMETHODCALLTYPE d2d_device_context_GetPrimitiveBlend(ID2D1DeviceContext1 *iface)
2471 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
2473 TRACE("iface %p.\n", iface);
2475 return context->drawing_state.primitiveBlend;
2478 static void STDMETHODCALLTYPE d2d_device_context_SetUnitMode(ID2D1DeviceContext1 *iface, D2D1_UNIT_MODE unit_mode)
2480 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
2482 TRACE("iface %p, unit_mode %#x.\n", iface, unit_mode);
2484 if (unit_mode != D2D1_UNIT_MODE_DIPS && unit_mode != D2D1_UNIT_MODE_PIXELS)
2486 WARN("Unknown unit mode %#x.\n", unit_mode);
2487 return;
2490 if (context->target.type == D2D_TARGET_COMMAND_LIST)
2491 d2d_command_list_set_unit_mode(context->target.command_list, unit_mode);
2493 context->drawing_state.unitMode = unit_mode;
2496 static D2D1_UNIT_MODE STDMETHODCALLTYPE d2d_device_context_GetUnitMode(ID2D1DeviceContext1 *iface)
2498 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
2500 TRACE("iface %p.\n", iface);
2502 return context->drawing_state.unitMode;
2505 static void STDMETHODCALLTYPE d2d_device_context_ID2D1DeviceContext_DrawGlyphRun(ID2D1DeviceContext1 *iface,
2506 D2D1_POINT_2F baseline_origin, const DWRITE_GLYPH_RUN *glyph_run,
2507 const DWRITE_GLYPH_RUN_DESCRIPTION *glyph_run_desc, ID2D1Brush *brush, DWRITE_MEASURING_MODE measuring_mode)
2509 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
2511 TRACE("iface %p, baseline_origin %s, glyph_run %p, glyph_run_desc %p, brush %p, measuring_mode %#x.\n",
2512 iface, debug_d2d_point_2f(&baseline_origin), glyph_run, glyph_run_desc, brush, measuring_mode);
2514 d2d_device_context_draw_glyph_run(context, baseline_origin, glyph_run, glyph_run_desc, brush, measuring_mode);
2517 static void STDMETHODCALLTYPE d2d_device_context_DrawImage(ID2D1DeviceContext1 *iface, ID2D1Image *image,
2518 const D2D1_POINT_2F *target_offset, const D2D1_RECT_F *image_rect, D2D1_INTERPOLATION_MODE interpolation_mode,
2519 D2D1_COMPOSITE_MODE composite_mode)
2521 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
2522 ID2D1Bitmap *bitmap;
2524 TRACE("iface %p, image %p, target_offset %s, image_rect %s, interpolation_mode %#x, composite_mode %#x.\n",
2525 iface, image, debug_d2d_point_2f(target_offset), debug_d2d_rect_f(image_rect),
2526 interpolation_mode, composite_mode);
2528 if (context->target.type == D2D_TARGET_COMMAND_LIST)
2530 d2d_command_list_draw_image(context->target.command_list, image, target_offset, image_rect,
2531 interpolation_mode, composite_mode);
2532 return;
2535 if (composite_mode != D2D1_COMPOSITE_MODE_SOURCE_OVER)
2536 FIXME("Unhandled composite mode %#x.\n", composite_mode);
2538 if (SUCCEEDED(ID2D1Image_QueryInterface(image, &IID_ID2D1Bitmap, (void **)&bitmap)))
2540 d2d_device_context_draw_bitmap(context, bitmap, NULL, 1.0f, d2d1_1_interp_mode_from_d2d1(interpolation_mode),
2541 image_rect, target_offset, NULL);
2543 ID2D1Bitmap_Release(bitmap);
2544 return;
2547 FIXME("Unhandled image %p.\n", image);
2550 static void STDMETHODCALLTYPE d2d_device_context_DrawGdiMetafile(ID2D1DeviceContext1 *iface,
2551 ID2D1GdiMetafile *metafile, const D2D1_POINT_2F *target_offset)
2553 FIXME("iface %p, metafile %p, target_offset %s stub!\n",
2554 iface, metafile, debug_d2d_point_2f(target_offset));
2557 static void STDMETHODCALLTYPE d2d_device_context_ID2D1DeviceContext_DrawBitmap(ID2D1DeviceContext1 *iface,
2558 ID2D1Bitmap *bitmap, const D2D1_RECT_F *dst_rect, float opacity, D2D1_INTERPOLATION_MODE interpolation_mode,
2559 const D2D1_RECT_F *src_rect, const D2D1_MATRIX_4X4_F *perspective_transform)
2561 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
2563 TRACE("iface %p, bitmap %p, dst_rect %s, opacity %.8e, interpolation_mode %#x, "
2564 "src_rect %s, perspective_transform %p.\n",
2565 iface, bitmap, debug_d2d_rect_f(dst_rect), opacity, interpolation_mode,
2566 debug_d2d_rect_f(src_rect), perspective_transform);
2568 if (context->target.type == D2D_TARGET_COMMAND_LIST)
2570 d2d_command_list_draw_bitmap(context->target.command_list, bitmap, dst_rect, opacity, interpolation_mode,
2571 src_rect, perspective_transform);
2573 else
2575 d2d_device_context_draw_bitmap(context, bitmap, dst_rect, opacity, interpolation_mode, src_rect,
2576 NULL, perspective_transform);
2580 static void STDMETHODCALLTYPE d2d_device_context_ID2D1DeviceContext_PushLayer(ID2D1DeviceContext1 *iface,
2581 const D2D1_LAYER_PARAMETERS1 *layer_parameters, ID2D1Layer *layer)
2583 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
2585 FIXME("iface %p, layer_parameters %p, layer %p stub!\n", iface, layer_parameters, layer);
2587 if (context->target.type == D2D_TARGET_COMMAND_LIST)
2588 d2d_command_list_push_layer(context->target.command_list, context, layer_parameters, layer);
2591 static HRESULT STDMETHODCALLTYPE d2d_device_context_InvalidateEffectInputRectangle(ID2D1DeviceContext1 *iface,
2592 ID2D1Effect *effect, UINT32 input, const D2D1_RECT_F *input_rect)
2594 FIXME("iface %p, effect %p, input %u, input_rect %s stub!\n",
2595 iface, effect, input, debug_d2d_rect_f(input_rect));
2597 return E_NOTIMPL;
2600 static HRESULT STDMETHODCALLTYPE d2d_device_context_GetEffectInvalidRectangleCount(ID2D1DeviceContext1 *iface,
2601 ID2D1Effect *effect, UINT32 *rect_count)
2603 FIXME("iface %p, effect %p, rect_count %p stub!\n", iface, effect, rect_count);
2605 return E_NOTIMPL;
2608 static HRESULT STDMETHODCALLTYPE d2d_device_context_GetEffectInvalidRectangles(ID2D1DeviceContext1 *iface,
2609 ID2D1Effect *effect, D2D1_RECT_F *rectangles, UINT32 rect_count)
2611 FIXME("iface %p, effect %p, rectangles %p, rect_count %u stub!\n", iface, effect, rectangles, rect_count);
2613 return E_NOTIMPL;
2616 static HRESULT STDMETHODCALLTYPE d2d_device_context_GetEffectRequiredInputRectangles(ID2D1DeviceContext1 *iface,
2617 ID2D1Effect *effect, const D2D1_RECT_F *image_rect, const D2D1_EFFECT_INPUT_DESCRIPTION *desc,
2618 D2D1_RECT_F *input_rect, UINT32 input_count)
2620 FIXME("iface %p, effect %p, image_rect %s, desc %p, input_rect %p, input_count %u stub!\n",
2621 iface, effect, debug_d2d_rect_f(image_rect), desc, input_rect, input_count);
2623 return E_NOTIMPL;
2626 static void STDMETHODCALLTYPE d2d_device_context_ID2D1DeviceContext_FillOpacityMask(ID2D1DeviceContext1 *iface,
2627 ID2D1Bitmap *mask, ID2D1Brush *brush, const D2D1_RECT_F *dst_rect, const D2D1_RECT_F *src_rect)
2629 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
2631 FIXME("iface %p, mask %p, brush %p, dst_rect %s, src_rect %s stub!\n",
2632 iface, mask, brush, debug_d2d_rect_f(dst_rect), debug_d2d_rect_f(src_rect));
2634 if (FAILED(context->error.code))
2635 return;
2637 if (context->drawing_state.antialiasMode != D2D1_ANTIALIAS_MODE_ALIASED)
2639 d2d_device_context_set_error(context, D2DERR_WRONG_STATE);
2640 return;
2643 if (context->target.type == D2D_TARGET_COMMAND_LIST)
2644 d2d_command_list_fill_opacity_mask(context->target.command_list, context, mask, brush, dst_rect, src_rect);
2647 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateFilledGeometryRealization(ID2D1DeviceContext1 *iface,
2648 ID2D1Geometry *geometry, float tolerance, ID2D1GeometryRealization **realization)
2650 FIXME("iface %p, geometry %p, tolerance %.8e, realization %p stub!\n", iface, geometry, tolerance,
2651 realization);
2653 return E_NOTIMPL;
2656 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateStrokedGeometryRealization(ID2D1DeviceContext1 *iface,
2657 ID2D1Geometry *geometry, float tolerance, float stroke_width, ID2D1StrokeStyle *stroke_style,
2658 ID2D1GeometryRealization **realization)
2660 FIXME("iface %p, geometry %p, tolerance %.8e, stroke_width %.8e, stroke_style %p, realization %p stub!\n",
2661 iface, geometry, tolerance, stroke_width, stroke_style, realization);
2663 return E_NOTIMPL;
2666 static void STDMETHODCALLTYPE d2d_device_context_DrawGeometryRealization(ID2D1DeviceContext1 *iface,
2667 ID2D1GeometryRealization *realization, ID2D1Brush *brush)
2669 FIXME("iface %p, realization %p, brush %p stub!\n", iface, realization, brush);
2672 static const struct ID2D1DeviceContext1Vtbl d2d_device_context_vtbl =
2674 d2d_device_context_QueryInterface,
2675 d2d_device_context_AddRef,
2676 d2d_device_context_Release,
2677 d2d_device_context_GetFactory,
2678 d2d_device_context_CreateBitmap,
2679 d2d_device_context_CreateBitmapFromWicBitmap,
2680 d2d_device_context_CreateSharedBitmap,
2681 d2d_device_context_CreateBitmapBrush,
2682 d2d_device_context_CreateSolidColorBrush,
2683 d2d_device_context_CreateGradientStopCollection,
2684 d2d_device_context_CreateLinearGradientBrush,
2685 d2d_device_context_CreateRadialGradientBrush,
2686 d2d_device_context_CreateCompatibleRenderTarget,
2687 d2d_device_context_CreateLayer,
2688 d2d_device_context_CreateMesh,
2689 d2d_device_context_DrawLine,
2690 d2d_device_context_DrawRectangle,
2691 d2d_device_context_FillRectangle,
2692 d2d_device_context_DrawRoundedRectangle,
2693 d2d_device_context_FillRoundedRectangle,
2694 d2d_device_context_DrawEllipse,
2695 d2d_device_context_FillEllipse,
2696 d2d_device_context_DrawGeometry,
2697 d2d_device_context_FillGeometry,
2698 d2d_device_context_FillMesh,
2699 d2d_device_context_FillOpacityMask,
2700 d2d_device_context_DrawBitmap,
2701 d2d_device_context_DrawText,
2702 d2d_device_context_DrawTextLayout,
2703 d2d_device_context_DrawGlyphRun,
2704 d2d_device_context_SetTransform,
2705 d2d_device_context_GetTransform,
2706 d2d_device_context_SetAntialiasMode,
2707 d2d_device_context_GetAntialiasMode,
2708 d2d_device_context_SetTextAntialiasMode,
2709 d2d_device_context_GetTextAntialiasMode,
2710 d2d_device_context_SetTextRenderingParams,
2711 d2d_device_context_GetTextRenderingParams,
2712 d2d_device_context_SetTags,
2713 d2d_device_context_GetTags,
2714 d2d_device_context_PushLayer,
2715 d2d_device_context_PopLayer,
2716 d2d_device_context_Flush,
2717 d2d_device_context_SaveDrawingState,
2718 d2d_device_context_RestoreDrawingState,
2719 d2d_device_context_PushAxisAlignedClip,
2720 d2d_device_context_PopAxisAlignedClip,
2721 d2d_device_context_Clear,
2722 d2d_device_context_BeginDraw,
2723 d2d_device_context_EndDraw,
2724 d2d_device_context_GetPixelFormat,
2725 d2d_device_context_SetDpi,
2726 d2d_device_context_GetDpi,
2727 d2d_device_context_GetSize,
2728 d2d_device_context_GetPixelSize,
2729 d2d_device_context_GetMaximumBitmapSize,
2730 d2d_device_context_IsSupported,
2731 d2d_device_context_ID2D1DeviceContext_CreateBitmap,
2732 d2d_device_context_ID2D1DeviceContext_CreateBitmapFromWicBitmap,
2733 d2d_device_context_CreateColorContext,
2734 d2d_device_context_CreateColorContextFromFilename,
2735 d2d_device_context_CreateColorContextFromWicColorContext,
2736 d2d_device_context_CreateBitmapFromDxgiSurface,
2737 d2d_device_context_CreateEffect,
2738 d2d_device_context_ID2D1DeviceContext_CreateGradientStopCollection,
2739 d2d_device_context_CreateImageBrush,
2740 d2d_device_context_ID2D1DeviceContext_CreateBitmapBrush,
2741 d2d_device_context_CreateCommandList,
2742 d2d_device_context_IsDxgiFormatSupported,
2743 d2d_device_context_IsBufferPrecisionSupported,
2744 d2d_device_context_GetImageLocalBounds,
2745 d2d_device_context_GetImageWorldBounds,
2746 d2d_device_context_GetGlyphRunWorldBounds,
2747 d2d_device_context_GetDevice,
2748 d2d_device_context_SetTarget,
2749 d2d_device_context_GetTarget,
2750 d2d_device_context_SetRenderingControls,
2751 d2d_device_context_GetRenderingControls,
2752 d2d_device_context_SetPrimitiveBlend,
2753 d2d_device_context_GetPrimitiveBlend,
2754 d2d_device_context_SetUnitMode,
2755 d2d_device_context_GetUnitMode,
2756 d2d_device_context_ID2D1DeviceContext_DrawGlyphRun,
2757 d2d_device_context_DrawImage,
2758 d2d_device_context_DrawGdiMetafile,
2759 d2d_device_context_ID2D1DeviceContext_DrawBitmap,
2760 d2d_device_context_ID2D1DeviceContext_PushLayer,
2761 d2d_device_context_InvalidateEffectInputRectangle,
2762 d2d_device_context_GetEffectInvalidRectangleCount,
2763 d2d_device_context_GetEffectInvalidRectangles,
2764 d2d_device_context_GetEffectRequiredInputRectangles,
2765 d2d_device_context_ID2D1DeviceContext_FillOpacityMask,
2766 d2d_device_context_CreateFilledGeometryRealization,
2767 d2d_device_context_CreateStrokedGeometryRealization,
2768 d2d_device_context_DrawGeometryRealization,
2771 static inline struct d2d_device_context *impl_from_IDWriteTextRenderer(IDWriteTextRenderer *iface)
2773 return CONTAINING_RECORD(iface, struct d2d_device_context, IDWriteTextRenderer_iface);
2776 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_QueryInterface(IDWriteTextRenderer *iface, REFIID iid, void **out)
2778 TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
2780 if (IsEqualGUID(iid, &IID_IDWriteTextRenderer)
2781 || IsEqualGUID(iid, &IID_IDWritePixelSnapping)
2782 || IsEqualGUID(iid, &IID_IUnknown))
2784 IDWriteTextRenderer_AddRef(iface);
2785 *out = iface;
2786 return S_OK;
2789 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
2791 *out = NULL;
2792 return E_NOINTERFACE;
2795 static ULONG STDMETHODCALLTYPE d2d_text_renderer_AddRef(IDWriteTextRenderer *iface)
2797 struct d2d_device_context *render_target = impl_from_IDWriteTextRenderer(iface);
2799 TRACE("iface %p.\n", iface);
2801 return d2d_device_context_AddRef(&render_target->ID2D1DeviceContext1_iface);
2804 static ULONG STDMETHODCALLTYPE d2d_text_renderer_Release(IDWriteTextRenderer *iface)
2806 struct d2d_device_context *render_target = impl_from_IDWriteTextRenderer(iface);
2808 TRACE("iface %p.\n", iface);
2810 return d2d_device_context_Release(&render_target->ID2D1DeviceContext1_iface);
2813 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_IsPixelSnappingDisabled(IDWriteTextRenderer *iface,
2814 void *ctx, BOOL *disabled)
2816 struct d2d_draw_text_layout_ctx *context = ctx;
2818 TRACE("iface %p, ctx %p, disabled %p.\n", iface, ctx, disabled);
2820 *disabled = context->options & D2D1_DRAW_TEXT_OPTIONS_NO_SNAP;
2822 return S_OK;
2825 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_GetCurrentTransform(IDWriteTextRenderer *iface,
2826 void *ctx, DWRITE_MATRIX *transform)
2828 struct d2d_device_context *render_target = impl_from_IDWriteTextRenderer(iface);
2830 TRACE("iface %p, ctx %p, transform %p.\n", iface, ctx, transform);
2832 d2d_device_context_GetTransform(&render_target->ID2D1DeviceContext1_iface, (D2D1_MATRIX_3X2_F *)transform);
2834 return S_OK;
2837 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_GetPixelsPerDip(IDWriteTextRenderer *iface, void *ctx, float *ppd)
2839 struct d2d_device_context *render_target = impl_from_IDWriteTextRenderer(iface);
2841 TRACE("iface %p, ctx %p, ppd %p.\n", iface, ctx, ppd);
2843 *ppd = render_target->desc.dpiY / 96.0f;
2845 return S_OK;
2848 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_DrawGlyphRun(IDWriteTextRenderer *iface, void *ctx,
2849 float baseline_origin_x, float baseline_origin_y, DWRITE_MEASURING_MODE measuring_mode,
2850 const DWRITE_GLYPH_RUN *glyph_run, const DWRITE_GLYPH_RUN_DESCRIPTION *glyph_run_desc, IUnknown *effect)
2852 struct d2d_device_context *render_target = impl_from_IDWriteTextRenderer(iface);
2853 D2D1_POINT_2F baseline_origin = {baseline_origin_x, baseline_origin_y};
2854 struct d2d_draw_text_layout_ctx *context = ctx;
2855 BOOL color_font = FALSE;
2856 ID2D1Brush *brush;
2858 TRACE("iface %p, ctx %p, baseline_origin_x %.8e, baseline_origin_y %.8e, "
2859 "measuring_mode %#x, glyph_run %p, glyph_run_desc %p, effect %p.\n",
2860 iface, ctx, baseline_origin_x, baseline_origin_y,
2861 measuring_mode, glyph_run, glyph_run_desc, effect);
2863 if (context->options & ~(D2D1_DRAW_TEXT_OPTIONS_NO_SNAP | D2D1_DRAW_TEXT_OPTIONS_ENABLE_COLOR_FONT))
2864 FIXME("Ignoring options %#x.\n", context->options);
2866 brush = d2d_draw_get_text_brush(context, effect);
2868 TRACE("%s\n", debugstr_wn(glyph_run_desc->string, glyph_run_desc->stringLength));
2870 if (context->options & D2D1_DRAW_TEXT_OPTIONS_ENABLE_COLOR_FONT)
2872 IDWriteFontFace2 *fontface;
2874 if (SUCCEEDED(IDWriteFontFace_QueryInterface(glyph_run->fontFace,
2875 &IID_IDWriteFontFace2, (void **)&fontface)))
2877 color_font = IDWriteFontFace2_IsColorFont(fontface);
2878 IDWriteFontFace2_Release(fontface);
2882 if (color_font)
2884 IDWriteColorGlyphRunEnumerator *layers;
2885 IDWriteFactory2 *dwrite_factory;
2886 HRESULT hr;
2888 if (FAILED(hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, &IID_IDWriteFactory2,
2889 (IUnknown **)&dwrite_factory)))
2891 ERR("Failed to create dwrite factory, hr %#lx.\n", hr);
2892 ID2D1Brush_Release(brush);
2893 return hr;
2896 hr = IDWriteFactory2_TranslateColorGlyphRun(dwrite_factory, baseline_origin_x, baseline_origin_y,
2897 glyph_run, glyph_run_desc, measuring_mode, (DWRITE_MATRIX *)&render_target->drawing_state.transform, 0, &layers);
2898 IDWriteFactory2_Release(dwrite_factory);
2899 if (FAILED(hr))
2901 ERR("Failed to create colour glyph run enumerator, hr %#lx.\n", hr);
2902 ID2D1Brush_Release(brush);
2903 return hr;
2906 for (;;)
2908 const DWRITE_COLOR_GLYPH_RUN *color_run;
2909 ID2D1Brush *color_brush;
2910 D2D1_POINT_2F origin;
2911 BOOL has_run = FALSE;
2913 if (FAILED(hr = IDWriteColorGlyphRunEnumerator_MoveNext(layers, &has_run)))
2915 ERR("Failed to switch colour glyph layer, hr %#lx.\n", hr);
2916 break;
2919 if (!has_run)
2920 break;
2922 if (FAILED(hr = IDWriteColorGlyphRunEnumerator_GetCurrentRun(layers, &color_run)))
2924 ERR("Failed to get current colour run, hr %#lx.\n", hr);
2925 break;
2928 if (color_run->paletteIndex == 0xffff)
2929 color_brush = brush;
2930 else
2932 if (FAILED(hr = d2d_device_context_CreateSolidColorBrush(&render_target->ID2D1DeviceContext1_iface,
2933 &color_run->runColor, NULL, (ID2D1SolidColorBrush **)&color_brush)))
2935 ERR("Failed to create solid colour brush, hr %#lx.\n", hr);
2936 break;
2940 origin.x = color_run->baselineOriginX;
2941 origin.y = color_run->baselineOriginY;
2942 d2d_device_context_draw_glyph_run(render_target, origin, &color_run->glyphRun,
2943 color_run->glyphRunDescription, color_brush, measuring_mode);
2945 if (color_brush != brush)
2946 ID2D1Brush_Release(color_brush);
2949 IDWriteColorGlyphRunEnumerator_Release(layers);
2951 else
2952 d2d_device_context_draw_glyph_run(render_target, baseline_origin, glyph_run, glyph_run_desc,
2953 brush, measuring_mode);
2955 ID2D1Brush_Release(brush);
2957 return S_OK;
2960 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_DrawUnderline(IDWriteTextRenderer *iface, void *ctx,
2961 float baseline_origin_x, float baseline_origin_y, const DWRITE_UNDERLINE *underline, IUnknown *effect)
2963 struct d2d_device_context *render_target = impl_from_IDWriteTextRenderer(iface);
2964 const D2D1_MATRIX_3X2_F *m = &render_target->drawing_state.transform;
2965 struct d2d_draw_text_layout_ctx *context = ctx;
2966 D2D1_ANTIALIAS_MODE prev_antialias_mode;
2967 D2D1_POINT_2F start, end;
2968 ID2D1Brush *brush;
2969 float thickness;
2971 TRACE("iface %p, ctx %p, baseline_origin_x %.8e, baseline_origin_y %.8e, underline %p, effect %p\n",
2972 iface, ctx, baseline_origin_x, baseline_origin_y, underline, effect);
2974 /* minimal thickness in DIPs that will result in at least 1 pixel thick line */
2975 thickness = max(96.0f / (render_target->desc.dpiY * sqrtf(m->_21 * m->_21 + m->_22 * m->_22)),
2976 underline->thickness);
2978 brush = d2d_draw_get_text_brush(context, effect);
2980 start.x = baseline_origin_x;
2981 start.y = baseline_origin_y + underline->offset + thickness / 2.0f;
2982 end.x = start.x + underline->width;
2983 end.y = start.y;
2984 prev_antialias_mode = d2d_device_context_set_aa_mode_from_text_aa_mode(render_target);
2985 d2d_device_context_DrawLine(&render_target->ID2D1DeviceContext1_iface, start, end, brush, thickness, NULL);
2986 render_target->drawing_state.antialiasMode = prev_antialias_mode;
2988 ID2D1Brush_Release(brush);
2990 return S_OK;
2993 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_DrawStrikethrough(IDWriteTextRenderer *iface, void *ctx,
2994 float baseline_origin_x, float baseline_origin_y, const DWRITE_STRIKETHROUGH *strikethrough, IUnknown *effect)
2996 struct d2d_device_context *render_target = impl_from_IDWriteTextRenderer(iface);
2997 const D2D1_MATRIX_3X2_F *m = &render_target->drawing_state.transform;
2998 struct d2d_draw_text_layout_ctx *context = ctx;
2999 D2D1_ANTIALIAS_MODE prev_antialias_mode;
3000 D2D1_POINT_2F start, end;
3001 ID2D1Brush *brush;
3002 float thickness;
3004 TRACE("iface %p, ctx %p, baseline_origin_x %.8e, baseline_origin_y %.8e, strikethrough %p, effect %p.\n",
3005 iface, ctx, baseline_origin_x, baseline_origin_y, strikethrough, effect);
3007 /* minimal thickness in DIPs that will result in at least 1 pixel thick line */
3008 thickness = max(96.0f / (render_target->desc.dpiY * sqrtf(m->_21 * m->_21 + m->_22 * m->_22)),
3009 strikethrough->thickness);
3011 brush = d2d_draw_get_text_brush(context, effect);
3013 start.x = baseline_origin_x;
3014 start.y = baseline_origin_y + strikethrough->offset + thickness / 2.0f;
3015 end.x = start.x + strikethrough->width;
3016 end.y = start.y;
3017 prev_antialias_mode = d2d_device_context_set_aa_mode_from_text_aa_mode(render_target);
3018 d2d_device_context_DrawLine(&render_target->ID2D1DeviceContext1_iface, start, end, brush, thickness, NULL);
3019 render_target->drawing_state.antialiasMode = prev_antialias_mode;
3021 ID2D1Brush_Release(brush);
3023 return S_OK;
3026 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_DrawInlineObject(IDWriteTextRenderer *iface, void *ctx,
3027 float origin_x, float origin_y, IDWriteInlineObject *object, BOOL is_sideways, BOOL is_rtl, IUnknown *effect)
3029 struct d2d_draw_text_layout_ctx *context = ctx;
3030 ID2D1Brush *brush;
3031 HRESULT hr;
3033 TRACE("iface %p, ctx %p, origin_x %.8e, origin_y %.8e, object %p, is_sideways %#x, is_rtl %#x, effect %p.\n",
3034 iface, ctx, origin_x, origin_y, object, is_sideways, is_rtl, effect);
3036 /* Inline objects may not pass effects all the way down, when using layout object internally for example.
3037 This is how default trimming sign object in DirectWrite works - it does not use effect passed to Draw(),
3038 and resulting DrawGlyphRun() is always called with NULL effect, however original effect is used and correct
3039 brush is selected at Direct2D level. */
3040 brush = context->brush;
3041 context->brush = d2d_draw_get_text_brush(context, effect);
3043 hr = IDWriteInlineObject_Draw(object, ctx, iface, origin_x, origin_y, is_sideways, is_rtl, effect);
3045 ID2D1Brush_Release(context->brush);
3046 context->brush = brush;
3048 return hr;
3051 static const struct IDWriteTextRendererVtbl d2d_text_renderer_vtbl =
3053 d2d_text_renderer_QueryInterface,
3054 d2d_text_renderer_AddRef,
3055 d2d_text_renderer_Release,
3056 d2d_text_renderer_IsPixelSnappingDisabled,
3057 d2d_text_renderer_GetCurrentTransform,
3058 d2d_text_renderer_GetPixelsPerDip,
3059 d2d_text_renderer_DrawGlyphRun,
3060 d2d_text_renderer_DrawUnderline,
3061 d2d_text_renderer_DrawStrikethrough,
3062 d2d_text_renderer_DrawInlineObject,
3065 static inline struct d2d_device_context *impl_from_ID2D1GdiInteropRenderTarget(ID2D1GdiInteropRenderTarget *iface)
3067 return CONTAINING_RECORD(iface, struct d2d_device_context, ID2D1GdiInteropRenderTarget_iface);
3070 static HRESULT STDMETHODCALLTYPE d2d_gdi_interop_render_target_QueryInterface(ID2D1GdiInteropRenderTarget *iface,
3071 REFIID iid, void **out)
3073 struct d2d_device_context *render_target = impl_from_ID2D1GdiInteropRenderTarget(iface);
3075 TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
3077 return IUnknown_QueryInterface(render_target->outer_unknown, iid, out);
3080 static ULONG STDMETHODCALLTYPE d2d_gdi_interop_render_target_AddRef(ID2D1GdiInteropRenderTarget *iface)
3082 struct d2d_device_context *render_target = impl_from_ID2D1GdiInteropRenderTarget(iface);
3084 TRACE("iface %p.\n", iface);
3086 return IUnknown_AddRef(render_target->outer_unknown);
3089 static ULONG STDMETHODCALLTYPE d2d_gdi_interop_render_target_Release(ID2D1GdiInteropRenderTarget *iface)
3091 struct d2d_device_context *render_target = impl_from_ID2D1GdiInteropRenderTarget(iface);
3093 TRACE("iface %p.\n", iface);
3095 return IUnknown_Release(render_target->outer_unknown);
3098 static HRESULT d2d_device_context_get_surface(struct d2d_device_context *context, IDXGISurface1 **surface)
3100 ID3D11Resource *resource;
3101 HRESULT hr;
3103 if (context->target.type != D2D_TARGET_BITMAP)
3105 FIXME("Unimplemented for target type %u.\n", context->target.type);
3106 return E_NOTIMPL;
3109 ID3D11RenderTargetView_GetResource(context->target.bitmap->rtv, &resource);
3110 hr = ID3D11Resource_QueryInterface(resource, &IID_IDXGISurface1, (void **)surface);
3111 ID3D11Resource_Release(resource);
3112 if (FAILED(hr))
3114 *surface = NULL;
3115 WARN("Failed to get DXGI surface, %#lx.\n", hr);
3116 return hr;
3119 return hr;
3122 static HRESULT STDMETHODCALLTYPE d2d_gdi_interop_render_target_GetDC(ID2D1GdiInteropRenderTarget *iface,
3123 D2D1_DC_INITIALIZE_MODE mode, HDC *dc)
3125 struct d2d_device_context *render_target = impl_from_ID2D1GdiInteropRenderTarget(iface);
3126 IDXGISurface1 *surface;
3127 HRESULT hr;
3129 TRACE("iface %p, mode %d, dc %p.\n", iface, mode, dc);
3131 if (FAILED(hr = d2d_device_context_get_surface(render_target, &surface)))
3132 return hr;
3134 hr = IDXGISurface1_GetDC(surface, mode != D2D1_DC_INITIALIZE_MODE_COPY, dc);
3135 IDXGISurface1_Release(surface);
3137 return hr;
3140 static HRESULT STDMETHODCALLTYPE d2d_gdi_interop_render_target_ReleaseDC(ID2D1GdiInteropRenderTarget *iface,
3141 const RECT *update)
3143 struct d2d_device_context *render_target = impl_from_ID2D1GdiInteropRenderTarget(iface);
3144 IDXGISurface1 *surface;
3145 RECT update_rect;
3146 HRESULT hr;
3148 TRACE("iface %p, update rect %s.\n", iface, wine_dbgstr_rect(update));
3150 if (FAILED(hr = d2d_device_context_get_surface(render_target, &surface)))
3151 return hr;
3153 if (update)
3154 update_rect = *update;
3155 hr = IDXGISurface1_ReleaseDC(surface, update ? &update_rect : NULL);
3156 IDXGISurface1_Release(surface);
3158 return hr;
3161 static const struct ID2D1GdiInteropRenderTargetVtbl d2d_gdi_interop_render_target_vtbl =
3163 d2d_gdi_interop_render_target_QueryInterface,
3164 d2d_gdi_interop_render_target_AddRef,
3165 d2d_gdi_interop_render_target_Release,
3166 d2d_gdi_interop_render_target_GetDC,
3167 d2d_gdi_interop_render_target_ReleaseDC,
3170 static HRESULT d2d_device_context_init(struct d2d_device_context *render_target, ID2D1Device *device,
3171 IUnknown *outer_unknown, const struct d2d_device_context_ops *ops)
3173 D3D11_SUBRESOURCE_DATA buffer_data;
3174 struct d2d_device *device_impl;
3175 IDWriteFactory *dwrite_factory;
3176 D3D11_RASTERIZER_DESC rs_desc;
3177 D3D11_BUFFER_DESC buffer_desc;
3178 unsigned int i;
3179 HRESULT hr;
3181 static const D3D11_INPUT_ELEMENT_DESC il_desc_outline[] =
3183 {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0},
3184 {"PREV", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 8, D3D11_INPUT_PER_VERTEX_DATA, 0},
3185 {"NEXT", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 16, D3D11_INPUT_PER_VERTEX_DATA, 0},
3187 static const D3D11_INPUT_ELEMENT_DESC il_desc_curve_outline[] =
3189 {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0},
3190 {"P", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 8, D3D11_INPUT_PER_VERTEX_DATA, 0},
3191 {"P", 1, DXGI_FORMAT_R32G32_FLOAT, 0, 16, D3D11_INPUT_PER_VERTEX_DATA, 0},
3192 {"P", 2, DXGI_FORMAT_R32G32_FLOAT, 0, 24, D3D11_INPUT_PER_VERTEX_DATA, 0},
3193 {"PREV", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 32, D3D11_INPUT_PER_VERTEX_DATA, 0},
3194 {"NEXT", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 40, D3D11_INPUT_PER_VERTEX_DATA, 0},
3196 static const D3D11_INPUT_ELEMENT_DESC il_desc_triangle[] =
3198 {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0},
3200 static const D3D11_INPUT_ELEMENT_DESC il_desc_curve[] =
3202 {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0},
3203 {"TEXCOORD", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 8, D3D11_INPUT_PER_VERTEX_DATA, 0},
3205 static const DWORD vs_code_outline[] =
3207 #if 0
3208 float3x2 transform_geometry;
3209 float stroke_width;
3210 float4 transform_rtx;
3211 float4 transform_rty;
3213 struct output
3215 float2 p : WORLD_POSITION;
3216 float4 b : BEZIER;
3217 nointerpolation float2x2 stroke_transform : STROKE_TRANSFORM;
3218 float4 position : SV_POSITION;
3221 /* The lines PₚᵣₑᵥP₀ and P₀Pₙₑₓₜ, both offset by ±½w, intersect each other at:
3223 * Pᵢ = P₀ ± w · ½q⃑ᵢ.
3225 * Where:
3227 * q⃑ᵢ = q̂ₚᵣₑᵥ⊥ + tan(½θ) · -q̂ₚᵣₑᵥ
3228 * θ = ∠PₚᵣₑᵥP₀Pₙₑₓₜ
3229 * q⃑ₚᵣₑᵥ = P₀ - Pₚᵣₑᵥ */
3230 void main(float2 position : POSITION, float2 prev : PREV, float2 next : NEXT, out struct output o)
3232 float2 q_prev, q_next, v_p, q_i;
3233 float2x2 geom;
3234 float l;
3236 o.stroke_transform = float2x2(transform_rtx.xy, transform_rty.xy) * stroke_width * 0.5f;
3238 geom = float2x2(transform_geometry._11_21, transform_geometry._12_22);
3239 q_prev = normalize(mul(geom, prev));
3240 q_next = normalize(mul(geom, next));
3242 /* tan(½θ) = sin(θ) / (1 + cos(θ))
3243 * = (q̂ₚᵣₑᵥ⊥ · q̂ₙₑₓₜ) / (1 + (q̂ₚᵣₑᵥ · q̂ₙₑₓₜ)) */
3244 v_p = float2(-q_prev.y, q_prev.x);
3245 l = -dot(v_p, q_next) / (1.0f + dot(q_prev, q_next));
3246 q_i = l * q_prev + v_p;
3248 o.b = float4(0.0, 0.0, 0.0, 0.0);
3250 o.p = mul(float3(position, 1.0f), transform_geometry) + stroke_width * 0.5f * q_i;
3251 position = mul(float2x3(transform_rtx.xyz, transform_rty.xyz), float3(o.p, 1.0f))
3252 * float2(transform_rtx.w, transform_rty.w);
3253 o.position = float4(position + float2(-1.0f, 1.0f), 0.0f, 1.0f);
3255 #endif
3256 0x43425844, 0xfb16cd75, 0xf5ec3e80, 0xceacf250, 0x91d29d18, 0x00000001, 0x00000608, 0x00000003,
3257 0x0000002c, 0x00000098, 0x00000154, 0x4e475349, 0x00000064, 0x00000003, 0x00000008, 0x00000050,
3258 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000303, 0x00000059, 0x00000000, 0x00000000,
3259 0x00000003, 0x00000001, 0x00000303, 0x0000005e, 0x00000000, 0x00000000, 0x00000003, 0x00000002,
3260 0x00000303, 0x49534f50, 0x4e4f4954, 0x45525000, 0x454e0056, 0xab005458, 0x4e47534f, 0x000000b4,
3261 0x00000005, 0x00000008, 0x00000080, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000c03,
3262 0x0000008f, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x0000000f, 0x00000096, 0x00000000,
3263 0x00000000, 0x00000003, 0x00000002, 0x00000c03, 0x00000096, 0x00000001, 0x00000000, 0x00000003,
3264 0x00000003, 0x00000c03, 0x000000a7, 0x00000000, 0x00000001, 0x00000003, 0x00000004, 0x0000000f,
3265 0x4c524f57, 0x4f505f44, 0x49544953, 0x42004e4f, 0x45495a45, 0x54530052, 0x454b4f52, 0x4152545f,
3266 0x4f46534e, 0x53004d52, 0x4f505f56, 0x49544953, 0xab004e4f, 0x52444853, 0x000004ac, 0x00010040,
3267 0x0000012b, 0x04000059, 0x00208e46, 0x00000000, 0x00000004, 0x0300005f, 0x00101032, 0x00000000,
3268 0x0300005f, 0x00101032, 0x00000001, 0x0300005f, 0x00101032, 0x00000002, 0x03000065, 0x00102032,
3269 0x00000000, 0x03000065, 0x001020f2, 0x00000001, 0x03000065, 0x00102032, 0x00000002, 0x03000065,
3270 0x00102032, 0x00000003, 0x04000067, 0x001020f2, 0x00000004, 0x00000001, 0x02000068, 0x00000003,
3271 0x0800000f, 0x00100012, 0x00000000, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000002,
3272 0x0800000f, 0x00100022, 0x00000000, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000002,
3273 0x0700000f, 0x00100042, 0x00000000, 0x00100046, 0x00000000, 0x00100046, 0x00000000, 0x05000044,
3274 0x00100042, 0x00000000, 0x0010002a, 0x00000000, 0x07000038, 0x00100032, 0x00000000, 0x00100aa6,
3275 0x00000000, 0x00100046, 0x00000000, 0x0800000f, 0x00100012, 0x00000001, 0x00208046, 0x00000000,
3276 0x00000000, 0x00101046, 0x00000001, 0x0800000f, 0x00100022, 0x00000001, 0x00208046, 0x00000000,
3277 0x00000001, 0x00101046, 0x00000001, 0x0700000f, 0x00100042, 0x00000000, 0x00100046, 0x00000001,
3278 0x00100046, 0x00000001, 0x05000044, 0x00100042, 0x00000000, 0x0010002a, 0x00000000, 0x07000038,
3279 0x00100032, 0x00000001, 0x00100aa6, 0x00000000, 0x00100046, 0x00000001, 0x06000036, 0x001000c2,
3280 0x00000001, 0x80100556, 0x00000041, 0x00000001, 0x0700000f, 0x00100042, 0x00000000, 0x00100a26,
3281 0x00000001, 0x00100046, 0x00000000, 0x0700000f, 0x00100012, 0x00000000, 0x00100046, 0x00000001,
3282 0x00100046, 0x00000000, 0x07000000, 0x00100012, 0x00000000, 0x0010000a, 0x00000000, 0x00004001,
3283 0x3f800000, 0x0800000e, 0x00100012, 0x00000000, 0x8010002a, 0x00000041, 0x00000000, 0x0010000a,
3284 0x00000000, 0x09000032, 0x00100032, 0x00000000, 0x00100006, 0x00000000, 0x00100046, 0x00000001,
3285 0x00100f36, 0x00000001, 0x08000038, 0x00100042, 0x00000000, 0x0020803a, 0x00000000, 0x00000001,
3286 0x00004001, 0x3f000000, 0x05000036, 0x00100032, 0x00000001, 0x00101046, 0x00000000, 0x05000036,
3287 0x00100042, 0x00000001, 0x00004001, 0x3f800000, 0x08000010, 0x00100012, 0x00000002, 0x00100246,
3288 0x00000001, 0x00208246, 0x00000000, 0x00000000, 0x08000010, 0x00100022, 0x00000002, 0x00100246,
3289 0x00000001, 0x00208246, 0x00000000, 0x00000001, 0x09000032, 0x00100032, 0x00000000, 0x00100aa6,
3290 0x00000000, 0x00100046, 0x00000000, 0x00100046, 0x00000002, 0x05000036, 0x00102032, 0x00000000,
3291 0x00100046, 0x00000000, 0x08000036, 0x001020f2, 0x00000001, 0x00004002, 0x00000000, 0x00000000,
3292 0x00000000, 0x00000000, 0x06000036, 0x00100032, 0x00000001, 0x00208046, 0x00000000, 0x00000002,
3293 0x06000036, 0x001000c2, 0x00000001, 0x00208406, 0x00000000, 0x00000003, 0x08000038, 0x001000f2,
3294 0x00000001, 0x00100e46, 0x00000001, 0x00208ff6, 0x00000000, 0x00000001, 0x0a000038, 0x001000f2,
3295 0x00000001, 0x00100e46, 0x00000001, 0x00004002, 0x3f000000, 0x3f000000, 0x3f000000, 0x3f000000,
3296 0x05000036, 0x00102032, 0x00000002, 0x00100086, 0x00000001, 0x05000036, 0x00102032, 0x00000003,
3297 0x001005d6, 0x00000001, 0x05000036, 0x00100042, 0x00000000, 0x00004001, 0x3f800000, 0x08000010,
3298 0x00100082, 0x00000000, 0x00208246, 0x00000000, 0x00000002, 0x00100246, 0x00000000, 0x08000010,
3299 0x00100012, 0x00000000, 0x00208246, 0x00000000, 0x00000003, 0x00100246, 0x00000000, 0x08000038,
3300 0x00100022, 0x00000000, 0x0010000a, 0x00000000, 0x0020803a, 0x00000000, 0x00000003, 0x08000038,
3301 0x00100012, 0x00000000, 0x0010003a, 0x00000000, 0x0020803a, 0x00000000, 0x00000002, 0x0a000000,
3302 0x00102032, 0x00000004, 0x00100046, 0x00000000, 0x00004002, 0xbf800000, 0x3f800000, 0x00000000,
3303 0x00000000, 0x08000036, 0x001020c2, 0x00000004, 0x00004002, 0x00000000, 0x00000000, 0x00000000,
3304 0x3f800000, 0x0100003e,
3306 /* ⎡p0.x p0.y 1⎤
3307 * A = ⎢p1.x p1.y 1⎥
3308 * ⎣p2.x p2.y 1⎦
3310 * ⎡0 0⎤
3311 * B = ⎢½ 0⎥
3312 * ⎣1 1⎦
3314 * A' = ⎡p1.x-p0.x p1.y-p0.y⎤
3315 * ⎣p2.x-p0.x p2.y-p0.y⎦
3317 * B' = ⎡½ 0⎤
3318 * ⎣1 1⎦
3320 * A'T = B'
3321 * T = A'⁻¹B'
3323 static const DWORD vs_code_bezier_outline[] =
3325 #if 0
3326 float3x2 transform_geometry;
3327 float stroke_width;
3328 float4 transform_rtx;
3329 float4 transform_rty;
3331 struct output
3333 float2 p : WORLD_POSITION;
3334 float4 b : BEZIER;
3335 nointerpolation float2x2 stroke_transform : STROKE_TRANSFORM;
3336 float4 position : SV_POSITION;
3339 void main(float2 position : POSITION, float2 p0 : P0, float2 p1 : P1, float2 p2 : P2,
3340 float2 prev : PREV, float2 next : NEXT, out struct output o)
3342 float2 q_prev, q_next, v_p, q_i, p;
3343 float2x2 geom, rt;
3344 float l;
3346 geom = float2x2(transform_geometry._11_21, transform_geometry._12_22);
3347 rt = float2x2(transform_rtx.xy, transform_rty.xy);
3348 o.stroke_transform = rt * stroke_width * 0.5f;
3350 p = mul(geom, position);
3351 p0 = mul(geom, p0);
3352 p1 = mul(geom, p1);
3353 p2 = mul(geom, p2);
3355 p -= p0;
3356 p1 -= p0;
3357 p2 -= p0;
3359 q_prev = normalize(mul(geom, prev));
3360 q_next = normalize(mul(geom, next));
3362 v_p = float2(-q_prev.y, q_prev.x);
3363 l = -dot(v_p, q_next) / (1.0f + dot(q_prev, q_next));
3364 q_i = l * q_prev + v_p;
3365 p += 0.5f * stroke_width * q_i;
3367 v_p = mul(rt, p2);
3368 v_p = normalize(float2(-v_p.y, v_p.x));
3369 if (abs(dot(mul(rt, p1), v_p)) < 1.0f)
3371 o.b.xzw = float3(0.0f, 0.0f, 0.0f);
3372 o.b.y = dot(mul(rt, p), v_p);
3374 else
3376 o.b.zw = sign(dot(mul(rt, p1), v_p)) * v_p;
3377 v_p = -float2(-p.y, p.x) / dot(float2(-p1.y, p1.x), p2);
3378 o.b.x = dot(v_p, p1 - 0.5f * p2);
3379 o.b.y = dot(v_p, p1);
3382 o.p = mul(float3(position, 1.0f), transform_geometry) + 0.5f * stroke_width * q_i;
3383 position = mul(float2x3(transform_rtx.xyz, transform_rty.xyz), float3(o.p, 1.0f))
3384 * float2(transform_rtx.w, transform_rty.w);
3385 o.position = float4(position + float2(-1.0f, 1.0f), 0.0f, 1.0f);
3387 #endif
3388 0x43425844, 0x356a0c5f, 0x8e4ba153, 0xe52cf793, 0xa6b774ea, 0x00000001, 0x00000afc, 0x00000003,
3389 0x0000002c, 0x000000e4, 0x000001a0, 0x4e475349, 0x000000b0, 0x00000006, 0x00000008, 0x00000098,
3390 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000303, 0x000000a1, 0x00000000, 0x00000000,
3391 0x00000003, 0x00000001, 0x00000303, 0x000000a1, 0x00000001, 0x00000000, 0x00000003, 0x00000002,
3392 0x00000303, 0x000000a1, 0x00000002, 0x00000000, 0x00000003, 0x00000003, 0x00000303, 0x000000a3,
3393 0x00000000, 0x00000000, 0x00000003, 0x00000004, 0x00000303, 0x000000a8, 0x00000000, 0x00000000,
3394 0x00000003, 0x00000005, 0x00000303, 0x49534f50, 0x4e4f4954, 0x50005000, 0x00564552, 0x5458454e,
3395 0xababab00, 0x4e47534f, 0x000000b4, 0x00000005, 0x00000008, 0x00000080, 0x00000000, 0x00000000,
3396 0x00000003, 0x00000000, 0x00000c03, 0x0000008f, 0x00000000, 0x00000000, 0x00000003, 0x00000001,
3397 0x0000000f, 0x00000096, 0x00000000, 0x00000000, 0x00000003, 0x00000002, 0x00000c03, 0x00000096,
3398 0x00000001, 0x00000000, 0x00000003, 0x00000003, 0x00000c03, 0x000000a7, 0x00000000, 0x00000001,
3399 0x00000003, 0x00000004, 0x0000000f, 0x4c524f57, 0x4f505f44, 0x49544953, 0x42004e4f, 0x45495a45,
3400 0x54530052, 0x454b4f52, 0x4152545f, 0x4f46534e, 0x53004d52, 0x4f505f56, 0x49544953, 0xab004e4f,
3401 0x52444853, 0x00000954, 0x00010040, 0x00000255, 0x04000059, 0x00208e46, 0x00000000, 0x00000004,
3402 0x0300005f, 0x00101032, 0x00000000, 0x0300005f, 0x00101032, 0x00000001, 0x0300005f, 0x00101032,
3403 0x00000002, 0x0300005f, 0x00101032, 0x00000003, 0x0300005f, 0x00101032, 0x00000004, 0x0300005f,
3404 0x00101032, 0x00000005, 0x03000065, 0x00102032, 0x00000000, 0x03000065, 0x001020f2, 0x00000001,
3405 0x03000065, 0x00102032, 0x00000002, 0x03000065, 0x00102032, 0x00000003, 0x04000067, 0x001020f2,
3406 0x00000004, 0x00000001, 0x02000068, 0x00000006, 0x0800000f, 0x00100012, 0x00000000, 0x00208046,
3407 0x00000000, 0x00000000, 0x00101046, 0x00000005, 0x0800000f, 0x00100022, 0x00000000, 0x00208046,
3408 0x00000000, 0x00000001, 0x00101046, 0x00000005, 0x0700000f, 0x00100042, 0x00000000, 0x00100046,
3409 0x00000000, 0x00100046, 0x00000000, 0x05000044, 0x00100042, 0x00000000, 0x0010002a, 0x00000000,
3410 0x07000038, 0x00100032, 0x00000000, 0x00100aa6, 0x00000000, 0x00100046, 0x00000000, 0x0800000f,
3411 0x00100012, 0x00000001, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000004, 0x0800000f,
3412 0x00100022, 0x00000001, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000004, 0x0700000f,
3413 0x00100042, 0x00000000, 0x00100046, 0x00000001, 0x00100046, 0x00000001, 0x05000044, 0x00100042,
3414 0x00000000, 0x0010002a, 0x00000000, 0x07000038, 0x00100032, 0x00000001, 0x00100aa6, 0x00000000,
3415 0x00100046, 0x00000001, 0x06000036, 0x001000c2, 0x00000001, 0x80100556, 0x00000041, 0x00000001,
3416 0x0700000f, 0x00100042, 0x00000000, 0x00100a26, 0x00000001, 0x00100046, 0x00000000, 0x0700000f,
3417 0x00100012, 0x00000000, 0x00100046, 0x00000001, 0x00100046, 0x00000000, 0x07000000, 0x00100012,
3418 0x00000000, 0x0010000a, 0x00000000, 0x00004001, 0x3f800000, 0x0800000e, 0x00100012, 0x00000000,
3419 0x8010002a, 0x00000041, 0x00000000, 0x0010000a, 0x00000000, 0x09000032, 0x00100032, 0x00000000,
3420 0x00100006, 0x00000000, 0x00100046, 0x00000001, 0x00100f36, 0x00000001, 0x05000036, 0x00100032,
3421 0x00000001, 0x00101046, 0x00000000, 0x05000036, 0x00100042, 0x00000001, 0x00004001, 0x3f800000,
3422 0x08000010, 0x00100012, 0x00000002, 0x00100246, 0x00000001, 0x00208246, 0x00000000, 0x00000000,
3423 0x08000010, 0x00100022, 0x00000002, 0x00100246, 0x00000001, 0x00208246, 0x00000000, 0x00000001,
3424 0x08000038, 0x00100042, 0x00000000, 0x0020803a, 0x00000000, 0x00000001, 0x00004001, 0x3f000000,
3425 0x09000032, 0x00100032, 0x00000001, 0x00100aa6, 0x00000000, 0x00100046, 0x00000000, 0x00100046,
3426 0x00000002, 0x05000036, 0x00102032, 0x00000000, 0x00100046, 0x00000001, 0x0800000f, 0x00100012,
3427 0x00000002, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000000, 0x0800000f, 0x00100022,
3428 0x00000002, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000000, 0x0800000f, 0x00100012,
3429 0x00000003, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000001, 0x0800000f, 0x00100022,
3430 0x00000003, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000001, 0x08000000, 0x00100032,
3431 0x00000002, 0x00100046, 0x00000002, 0x80100046, 0x00000041, 0x00000003, 0x09000032, 0x00100032,
3432 0x00000000, 0x00100aa6, 0x00000000, 0x00100046, 0x00000000, 0x00100046, 0x00000002, 0x0800000f,
3433 0x00100012, 0x00000002, 0x00208046, 0x00000000, 0x00000002, 0x00100046, 0x00000000, 0x0800000f,
3434 0x00100022, 0x00000002, 0x00208046, 0x00000000, 0x00000003, 0x00100046, 0x00000000, 0x0800000f,
3435 0x00100012, 0x00000004, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000003, 0x0800000f,
3436 0x00100022, 0x00000004, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000003, 0x08000000,
3437 0x001000c2, 0x00000002, 0x80100406, 0x00000041, 0x00000003, 0x00100406, 0x00000004, 0x0800000f,
3438 0x00100082, 0x00000000, 0x00208046, 0x00000000, 0x00000003, 0x00100ae6, 0x00000002, 0x06000036,
3439 0x00100042, 0x00000003, 0x8010003a, 0x00000041, 0x00000000, 0x0800000f, 0x00100082, 0x00000003,
3440 0x00208046, 0x00000000, 0x00000002, 0x00100ae6, 0x00000002, 0x0700000f, 0x00100082, 0x00000000,
3441 0x00100ae6, 0x00000003, 0x00100ae6, 0x00000003, 0x05000044, 0x00100082, 0x00000000, 0x0010003a,
3442 0x00000000, 0x07000038, 0x001000c2, 0x00000003, 0x00100ff6, 0x00000000, 0x00100ea6, 0x00000003,
3443 0x0700000f, 0x00100022, 0x00000004, 0x00100046, 0x00000002, 0x00100ae6, 0x00000003, 0x06000036,
3444 0x00100042, 0x00000000, 0x8010001a, 0x00000041, 0x00000000, 0x0800000f, 0x00100012, 0x00000002,
3445 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000002, 0x0800000f, 0x00100022, 0x00000002,
3446 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000002, 0x08000000, 0x00100032, 0x00000005,
3447 0x80100046, 0x00000041, 0x00000003, 0x00100046, 0x00000002, 0x06000036, 0x00100042, 0x00000005,
3448 0x8010001a, 0x00000041, 0x00000005, 0x0700000f, 0x00100022, 0x00000000, 0x00100a26, 0x00000005,
3449 0x00100ae6, 0x00000002, 0x0d000032, 0x00100032, 0x00000002, 0x80100ae6, 0x00000041, 0x00000002,
3450 0x00004002, 0x3f000000, 0x3f000000, 0x00000000, 0x00000000, 0x00100046, 0x00000005, 0x0800000e,
3451 0x00100032, 0x00000000, 0x80100a26, 0x00000041, 0x00000000, 0x00100556, 0x00000000, 0x0700000f,
3452 0x00100012, 0x00000002, 0x00100046, 0x00000000, 0x00100046, 0x00000002, 0x0700000f, 0x00100022,
3453 0x00000002, 0x00100046, 0x00000000, 0x00100046, 0x00000005, 0x0800000f, 0x00100012, 0x00000000,
3454 0x00208046, 0x00000000, 0x00000002, 0x00100046, 0x00000005, 0x0800000f, 0x00100022, 0x00000000,
3455 0x00208046, 0x00000000, 0x00000003, 0x00100046, 0x00000005, 0x0700000f, 0x00100012, 0x00000000,
3456 0x00100046, 0x00000000, 0x00100ae6, 0x00000003, 0x07000031, 0x00100022, 0x00000000, 0x00004001,
3457 0x00000000, 0x0010000a, 0x00000000, 0x07000031, 0x00100042, 0x00000000, 0x0010000a, 0x00000000,
3458 0x00004001, 0x00000000, 0x08000031, 0x00100012, 0x00000000, 0x8010000a, 0x00000081, 0x00000000,
3459 0x00004001, 0x3f800000, 0x0800001e, 0x00100022, 0x00000000, 0x8010001a, 0x00000041, 0x00000000,
3460 0x0010002a, 0x00000000, 0x0500002b, 0x00100022, 0x00000000, 0x0010001a, 0x00000000, 0x07000038,
3461 0x001000c2, 0x00000002, 0x00100ea6, 0x00000003, 0x00100556, 0x00000000, 0x08000036, 0x001000d2,
3462 0x00000004, 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x09000037, 0x001020f2,
3463 0x00000001, 0x00100006, 0x00000000, 0x00100e46, 0x00000004, 0x00100e46, 0x00000002, 0x06000036,
3464 0x00100032, 0x00000000, 0x00208046, 0x00000000, 0x00000002, 0x06000036, 0x001000c2, 0x00000000,
3465 0x00208406, 0x00000000, 0x00000003, 0x08000038, 0x001000f2, 0x00000000, 0x00100e46, 0x00000000,
3466 0x00208ff6, 0x00000000, 0x00000001, 0x0a000038, 0x001000f2, 0x00000000, 0x00100e46, 0x00000000,
3467 0x00004002, 0x3f000000, 0x3f000000, 0x3f000000, 0x3f000000, 0x05000036, 0x00102032, 0x00000002,
3468 0x00100086, 0x00000000, 0x05000036, 0x00102032, 0x00000003, 0x001005d6, 0x00000000, 0x05000036,
3469 0x00100042, 0x00000001, 0x00004001, 0x3f800000, 0x08000010, 0x00100012, 0x00000000, 0x00208246,
3470 0x00000000, 0x00000002, 0x00100246, 0x00000001, 0x08000010, 0x00100022, 0x00000000, 0x00208246,
3471 0x00000000, 0x00000003, 0x00100246, 0x00000001, 0x08000038, 0x00100022, 0x00000001, 0x0010001a,
3472 0x00000000, 0x0020803a, 0x00000000, 0x00000003, 0x08000038, 0x00100012, 0x00000001, 0x0010000a,
3473 0x00000000, 0x0020803a, 0x00000000, 0x00000002, 0x0a000000, 0x00102032, 0x00000004, 0x00100046,
3474 0x00000001, 0x00004002, 0xbf800000, 0x3f800000, 0x00000000, 0x00000000, 0x08000036, 0x001020c2,
3475 0x00000004, 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, 0x0100003e,
3477 /* ⎡p0.x p0.y 1⎤
3478 * A = ⎢p1.x p1.y 1⎥
3479 * ⎣p2.x p2.y 1⎦
3481 * ⎡1 0⎤
3482 * B = ⎢1 1⎥
3483 * ⎣0 1⎦
3485 * A' = ⎡p1.x-p0.x p1.y-p0.y⎤
3486 * ⎣p2.x-p0.x p2.y-p0.y⎦
3488 * B' = ⎡ 0 1⎤
3489 * ⎣-1 1⎦
3491 * A'T = B'
3492 * T = A'⁻¹B' = (B'⁻¹A')⁻¹
3494 static const DWORD vs_code_arc_outline[] =
3496 #if 0
3497 float3x2 transform_geometry;
3498 float stroke_width;
3499 float4 transform_rtx;
3500 float4 transform_rty;
3502 struct output
3504 float2 p : WORLD_POSITION;
3505 float4 b : BEZIER;
3506 nointerpolation float2x2 stroke_transform : STROKE_TRANSFORM;
3507 float4 position : SV_POSITION;
3510 void main(float2 position : POSITION, float2 p0 : P0, float2 p1 : P1, float2 p2 : P2,
3511 float2 prev : PREV, float2 next : NEXT, out struct output o)
3513 float2 q_prev, q_next, v_p, q_i, p;
3514 float2x2 geom, rt, p_inv;
3515 float l;
3516 float a;
3517 float2 bc;
3519 geom = float2x2(transform_geometry._11_21, transform_geometry._12_22);
3520 rt = float2x2(transform_rtx.xy, transform_rty.xy);
3521 o.stroke_transform = rt * stroke_width * 0.5f;
3523 p = mul(geom, position);
3524 p0 = mul(geom, p0);
3525 p1 = mul(geom, p1);
3526 p2 = mul(geom, p2);
3528 p -= p0;
3529 p1 -= p0;
3530 p2 -= p0;
3532 q_prev = normalize(mul(geom, prev));
3533 q_next = normalize(mul(geom, next));
3535 v_p = float2(-q_prev.y, q_prev.x);
3536 l = -dot(v_p, q_next) / (1.0f + dot(q_prev, q_next));
3537 q_i = l * q_prev + v_p;
3538 p += 0.5f * stroke_width * q_i;
3540 p_inv = float2x2(p1.y, -p1.x, p2.y - p1.y, p1.x - p2.x) / (p1.x * p2.y - p2.x * p1.y);
3541 o.b.xy = mul(p_inv, p) + float2(1.0f, 0.0f);
3542 o.b.zw = 0.0f;
3544 o.p = mul(float3(position, 1.0f), transform_geometry) + 0.5f * stroke_width * q_i;
3545 position = mul(float2x3(transform_rtx.xyz, transform_rty.xyz), float3(o.p, 1.0f))
3546 * float2(transform_rtx.w, transform_rty.w);
3547 o.position = float4(position + float2(-1.0f, 1.0f), 0.0f, 1.0f);
3549 #endif
3550 0x43425844, 0xde1911bf, 0xfff8c893, 0xb0bfc24d, 0x78c9bbc4, 0x00000001, 0x00000924, 0x00000003,
3551 0x0000002c, 0x000000e4, 0x000001a0, 0x4e475349, 0x000000b0, 0x00000006, 0x00000008, 0x00000098,
3552 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000303, 0x000000a1, 0x00000000, 0x00000000,
3553 0x00000003, 0x00000001, 0x00000303, 0x000000a1, 0x00000001, 0x00000000, 0x00000003, 0x00000002,
3554 0x00000303, 0x000000a1, 0x00000002, 0x00000000, 0x00000003, 0x00000003, 0x00000303, 0x000000a3,
3555 0x00000000, 0x00000000, 0x00000003, 0x00000004, 0x00000303, 0x000000a8, 0x00000000, 0x00000000,
3556 0x00000003, 0x00000005, 0x00000303, 0x49534f50, 0x4e4f4954, 0x50005000, 0x00564552, 0x5458454e,
3557 0xababab00, 0x4e47534f, 0x000000b4, 0x00000005, 0x00000008, 0x00000080, 0x00000000, 0x00000000,
3558 0x00000003, 0x00000000, 0x00000c03, 0x0000008f, 0x00000000, 0x00000000, 0x00000003, 0x00000001,
3559 0x0000000f, 0x00000096, 0x00000000, 0x00000000, 0x00000003, 0x00000002, 0x00000c03, 0x00000096,
3560 0x00000001, 0x00000000, 0x00000003, 0x00000003, 0x00000c03, 0x000000a7, 0x00000000, 0x00000001,
3561 0x00000003, 0x00000004, 0x0000000f, 0x4c524f57, 0x4f505f44, 0x49544953, 0x42004e4f, 0x45495a45,
3562 0x54530052, 0x454b4f52, 0x4152545f, 0x4f46534e, 0x53004d52, 0x4f505f56, 0x49544953, 0xab004e4f,
3563 0x52444853, 0x0000077c, 0x00010040, 0x000001df, 0x04000059, 0x00208e46, 0x00000000, 0x00000004,
3564 0x0300005f, 0x00101032, 0x00000000, 0x0300005f, 0x00101032, 0x00000001, 0x0300005f, 0x00101032,
3565 0x00000002, 0x0300005f, 0x00101032, 0x00000003, 0x0300005f, 0x00101032, 0x00000004, 0x0300005f,
3566 0x00101032, 0x00000005, 0x03000065, 0x00102032, 0x00000000, 0x03000065, 0x001020f2, 0x00000001,
3567 0x03000065, 0x00102032, 0x00000002, 0x03000065, 0x00102032, 0x00000003, 0x04000067, 0x001020f2,
3568 0x00000004, 0x00000001, 0x02000068, 0x00000004, 0x0800000f, 0x00100012, 0x00000000, 0x00208046,
3569 0x00000000, 0x00000000, 0x00101046, 0x00000005, 0x0800000f, 0x00100022, 0x00000000, 0x00208046,
3570 0x00000000, 0x00000001, 0x00101046, 0x00000005, 0x0700000f, 0x00100042, 0x00000000, 0x00100046,
3571 0x00000000, 0x00100046, 0x00000000, 0x05000044, 0x00100042, 0x00000000, 0x0010002a, 0x00000000,
3572 0x07000038, 0x00100032, 0x00000000, 0x00100aa6, 0x00000000, 0x00100046, 0x00000000, 0x0800000f,
3573 0x00100012, 0x00000001, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000004, 0x0800000f,
3574 0x00100022, 0x00000001, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000004, 0x0700000f,
3575 0x00100042, 0x00000000, 0x00100046, 0x00000001, 0x00100046, 0x00000001, 0x05000044, 0x00100042,
3576 0x00000000, 0x0010002a, 0x00000000, 0x07000038, 0x00100032, 0x00000001, 0x00100aa6, 0x00000000,
3577 0x00100046, 0x00000001, 0x06000036, 0x001000c2, 0x00000001, 0x80100556, 0x00000041, 0x00000001,
3578 0x0700000f, 0x00100042, 0x00000000, 0x00100a26, 0x00000001, 0x00100046, 0x00000000, 0x0700000f,
3579 0x00100012, 0x00000000, 0x00100046, 0x00000001, 0x00100046, 0x00000000, 0x07000000, 0x00100012,
3580 0x00000000, 0x0010000a, 0x00000000, 0x00004001, 0x3f800000, 0x0800000e, 0x00100012, 0x00000000,
3581 0x8010002a, 0x00000041, 0x00000000, 0x0010000a, 0x00000000, 0x09000032, 0x00100032, 0x00000000,
3582 0x00100006, 0x00000000, 0x00100046, 0x00000001, 0x00100f36, 0x00000001, 0x05000036, 0x00100032,
3583 0x00000001, 0x00101046, 0x00000000, 0x05000036, 0x00100042, 0x00000001, 0x00004001, 0x3f800000,
3584 0x08000010, 0x00100012, 0x00000002, 0x00100246, 0x00000001, 0x00208246, 0x00000000, 0x00000000,
3585 0x08000010, 0x00100022, 0x00000002, 0x00100246, 0x00000001, 0x00208246, 0x00000000, 0x00000001,
3586 0x08000038, 0x00100042, 0x00000000, 0x0020803a, 0x00000000, 0x00000001, 0x00004001, 0x3f000000,
3587 0x09000032, 0x00100032, 0x00000001, 0x00100aa6, 0x00000000, 0x00100046, 0x00000000, 0x00100046,
3588 0x00000002, 0x05000036, 0x00102032, 0x00000000, 0x00100046, 0x00000001, 0x0800000f, 0x00100012,
3589 0x00000002, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000000, 0x0800000f, 0x00100022,
3590 0x00000002, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000000, 0x0800000f, 0x00100022,
3591 0x00000003, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000001, 0x0800000f, 0x00100012,
3592 0x00000003, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000001, 0x08000000, 0x00100032,
3593 0x00000002, 0x00100046, 0x00000002, 0x80100516, 0x00000041, 0x00000003, 0x09000032, 0x00100032,
3594 0x00000000, 0x00100aa6, 0x00000000, 0x00100046, 0x00000000, 0x00100046, 0x00000002, 0x0800000f,
3595 0x00100022, 0x00000002, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000003, 0x0800000f,
3596 0x00100012, 0x00000002, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000003, 0x08000000,
3597 0x001000c2, 0x00000000, 0x80100406, 0x00000041, 0x00000003, 0x00100406, 0x00000002, 0x0800000f,
3598 0x00100022, 0x00000002, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000002, 0x0800000f,
3599 0x00100012, 0x00000002, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000002, 0x08000000,
3600 0x00100032, 0x00000002, 0x80100046, 0x00000041, 0x00000003, 0x00100046, 0x00000002, 0x07000038,
3601 0x00100082, 0x00000001, 0x0010003a, 0x00000000, 0x0010000a, 0x00000002, 0x0a000032, 0x00100082,
3602 0x00000001, 0x0010001a, 0x00000002, 0x0010002a, 0x00000000, 0x8010003a, 0x00000041, 0x00000001,
3603 0x08000000, 0x00100042, 0x00000003, 0x0010002a, 0x00000000, 0x8010000a, 0x00000041, 0x00000002,
3604 0x08000000, 0x00100082, 0x00000003, 0x8010003a, 0x00000041, 0x00000000, 0x0010001a, 0x00000002,
3605 0x0a000038, 0x00100032, 0x00000003, 0x00100046, 0x00000002, 0x00004002, 0x3f800000, 0xbf800000,
3606 0x00000000, 0x00000000, 0x0700000e, 0x001000f2, 0x00000002, 0x00100e46, 0x00000003, 0x00100ff6,
3607 0x00000001, 0x0700000f, 0x00100012, 0x00000002, 0x00100046, 0x00000002, 0x00100046, 0x00000000,
3608 0x0700000f, 0x00100022, 0x00000002, 0x00100ae6, 0x00000002, 0x00100046, 0x00000000, 0x0a000000,
3609 0x00102032, 0x00000001, 0x00100046, 0x00000002, 0x00004002, 0x3f800000, 0x00000000, 0x00000000,
3610 0x00000000, 0x08000036, 0x001020c2, 0x00000001, 0x00004002, 0x00000000, 0x00000000, 0x00000000,
3611 0x00000000, 0x06000036, 0x00100032, 0x00000000, 0x00208046, 0x00000000, 0x00000002, 0x06000036,
3612 0x001000c2, 0x00000000, 0x00208406, 0x00000000, 0x00000003, 0x08000038, 0x001000f2, 0x00000000,
3613 0x00100e46, 0x00000000, 0x00208ff6, 0x00000000, 0x00000001, 0x0a000038, 0x001000f2, 0x00000000,
3614 0x00100e46, 0x00000000, 0x00004002, 0x3f000000, 0x3f000000, 0x3f000000, 0x3f000000, 0x05000036,
3615 0x00102032, 0x00000002, 0x00100086, 0x00000000, 0x05000036, 0x00102032, 0x00000003, 0x001005d6,
3616 0x00000000, 0x05000036, 0x00100042, 0x00000001, 0x00004001, 0x3f800000, 0x08000010, 0x00100012,
3617 0x00000000, 0x00208246, 0x00000000, 0x00000002, 0x00100246, 0x00000001, 0x08000010, 0x00100022,
3618 0x00000000, 0x00208246, 0x00000000, 0x00000003, 0x00100246, 0x00000001, 0x08000038, 0x00100022,
3619 0x00000001, 0x0010001a, 0x00000000, 0x0020803a, 0x00000000, 0x00000003, 0x08000038, 0x00100012,
3620 0x00000001, 0x0010000a, 0x00000000, 0x0020803a, 0x00000000, 0x00000002, 0x0a000000, 0x00102032,
3621 0x00000004, 0x00100046, 0x00000001, 0x00004002, 0xbf800000, 0x3f800000, 0x00000000, 0x00000000,
3622 0x08000036, 0x001020c2, 0x00000004, 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x3f800000,
3623 0x0100003e,
3625 static const DWORD vs_code_triangle[] =
3627 #if 0
3628 float3x2 transform_geometry;
3629 float4 transform_rtx;
3630 float4 transform_rty;
3632 struct output
3634 float2 p : WORLD_POSITION;
3635 float4 b : BEZIER;
3636 nointerpolation float2x2 stroke_transform : STROKE_TRANSFORM;
3637 float4 position : SV_POSITION;
3640 void main(float2 position : POSITION, out struct output o)
3642 o.p = mul(float3(position, 1.0f), transform_geometry);
3643 o.b = float4(1.0, 0.0, 1.0, 1.0);
3644 o.stroke_transform = float2x2(1.0, 0.0, 0.0, 1.0);
3645 position = mul(float2x3(transform_rtx.xyz, transform_rty.xyz), float3(o.p, 1.0f))
3646 * float2(transform_rtx.w, transform_rty.w);
3647 o.position = float4(position + float2(-1.0f, 1.0f), 0.0f, 1.0f);
3649 #endif
3650 0x43425844, 0xda43bf17, 0x06e6d155, 0xdbce2ae5, 0x8aed6fd8, 0x00000001, 0x0000034c, 0x00000003,
3651 0x0000002c, 0x00000060, 0x0000011c, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020,
3652 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000303, 0x49534f50, 0x4e4f4954, 0xababab00,
3653 0x4e47534f, 0x000000b4, 0x00000005, 0x00000008, 0x00000080, 0x00000000, 0x00000000, 0x00000003,
3654 0x00000000, 0x00000c03, 0x0000008f, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x0000000f,
3655 0x00000096, 0x00000000, 0x00000000, 0x00000003, 0x00000002, 0x00000c03, 0x00000096, 0x00000001,
3656 0x00000000, 0x00000003, 0x00000003, 0x00000c03, 0x000000a7, 0x00000000, 0x00000001, 0x00000003,
3657 0x00000004, 0x0000000f, 0x4c524f57, 0x4f505f44, 0x49544953, 0x42004e4f, 0x45495a45, 0x54530052,
3658 0x454b4f52, 0x4152545f, 0x4f46534e, 0x53004d52, 0x4f505f56, 0x49544953, 0xab004e4f, 0x52444853,
3659 0x00000228, 0x00010040, 0x0000008a, 0x04000059, 0x00208e46, 0x00000000, 0x00000004, 0x0300005f,
3660 0x00101032, 0x00000000, 0x03000065, 0x00102032, 0x00000000, 0x03000065, 0x001020f2, 0x00000001,
3661 0x03000065, 0x00102032, 0x00000002, 0x03000065, 0x00102032, 0x00000003, 0x04000067, 0x001020f2,
3662 0x00000004, 0x00000001, 0x02000068, 0x00000002, 0x05000036, 0x00100032, 0x00000000, 0x00101046,
3663 0x00000000, 0x05000036, 0x00100042, 0x00000000, 0x00004001, 0x3f800000, 0x08000010, 0x00100012,
3664 0x00000001, 0x00100246, 0x00000000, 0x00208246, 0x00000000, 0x00000000, 0x08000010, 0x00100022,
3665 0x00000001, 0x00100246, 0x00000000, 0x00208246, 0x00000000, 0x00000001, 0x05000036, 0x00102032,
3666 0x00000000, 0x00100046, 0x00000001, 0x08000036, 0x001020f2, 0x00000001, 0x00004002, 0x3f800000,
3667 0x00000000, 0x3f800000, 0x3f800000, 0x08000036, 0x00102032, 0x00000002, 0x00004002, 0x3f800000,
3668 0x00000000, 0x00000000, 0x00000000, 0x08000036, 0x00102032, 0x00000003, 0x00004002, 0x00000000,
3669 0x3f800000, 0x00000000, 0x00000000, 0x05000036, 0x00100042, 0x00000001, 0x00004001, 0x3f800000,
3670 0x08000010, 0x00100012, 0x00000000, 0x00208246, 0x00000000, 0x00000002, 0x00100246, 0x00000001,
3671 0x08000010, 0x00100022, 0x00000000, 0x00208246, 0x00000000, 0x00000003, 0x00100246, 0x00000001,
3672 0x08000038, 0x00100022, 0x00000001, 0x0010001a, 0x00000000, 0x0020803a, 0x00000000, 0x00000003,
3673 0x08000038, 0x00100012, 0x00000001, 0x0010000a, 0x00000000, 0x0020803a, 0x00000000, 0x00000002,
3674 0x0a000000, 0x00102032, 0x00000004, 0x00100046, 0x00000001, 0x00004002, 0xbf800000, 0x3f800000,
3675 0x00000000, 0x00000000, 0x08000036, 0x001020c2, 0x00000004, 0x00004002, 0x00000000, 0x00000000,
3676 0x00000000, 0x3f800000, 0x0100003e,
3678 static const DWORD vs_code_curve[] =
3680 #if 0
3681 float3x2 transform_geometry;
3682 float4 transform_rtx;
3683 float4 transform_rty;
3685 struct output
3687 float2 p : WORLD_POSITION;
3688 float4 b : BEZIER;
3689 nointerpolation float2x2 stroke_transform : STROKE_TRANSFORM;
3690 float4 position : SV_POSITION;
3693 void main(float2 position : POSITION, float3 texcoord : TEXCOORD0, out struct output o)
3695 o.p = mul(float3(position, 1.0f), transform_geometry);
3696 o.b = float4(texcoord, 1.0);
3697 o.stroke_transform = float2x2(1.0, 0.0, 0.0, 1.0);
3698 position = mul(float2x3(transform_rtx.xyz, transform_rty.xyz), float3(o.p, 1.0f))
3699 * float2(transform_rtx.w, transform_rty.w);
3700 o.position = float4(position + float2(-1.0f, 1.0f), 0.0f, 1.0f);
3702 #endif
3703 0x43425844, 0xedb7472a, 0x2c2ea147, 0x36710079, 0xffc2e907, 0x00000001, 0x00000380, 0x00000003,
3704 0x0000002c, 0x00000080, 0x0000013c, 0x4e475349, 0x0000004c, 0x00000002, 0x00000008, 0x00000038,
3705 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000303, 0x00000041, 0x00000000, 0x00000000,
3706 0x00000003, 0x00000001, 0x00000707, 0x49534f50, 0x4e4f4954, 0x58455400, 0x524f4f43, 0xabab0044,
3707 0x4e47534f, 0x000000b4, 0x00000005, 0x00000008, 0x00000080, 0x00000000, 0x00000000, 0x00000003,
3708 0x00000000, 0x00000c03, 0x0000008f, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x0000000f,
3709 0x00000096, 0x00000000, 0x00000000, 0x00000003, 0x00000002, 0x00000c03, 0x00000096, 0x00000001,
3710 0x00000000, 0x00000003, 0x00000003, 0x00000c03, 0x000000a7, 0x00000000, 0x00000001, 0x00000003,
3711 0x00000004, 0x0000000f, 0x4c524f57, 0x4f505f44, 0x49544953, 0x42004e4f, 0x45495a45, 0x54530052,
3712 0x454b4f52, 0x4152545f, 0x4f46534e, 0x53004d52, 0x4f505f56, 0x49544953, 0xab004e4f, 0x52444853,
3713 0x0000023c, 0x00010040, 0x0000008f, 0x04000059, 0x00208e46, 0x00000000, 0x00000004, 0x0300005f,
3714 0x00101032, 0x00000000, 0x0300005f, 0x00101072, 0x00000001, 0x03000065, 0x00102032, 0x00000000,
3715 0x03000065, 0x001020f2, 0x00000001, 0x03000065, 0x00102032, 0x00000002, 0x03000065, 0x00102032,
3716 0x00000003, 0x04000067, 0x001020f2, 0x00000004, 0x00000001, 0x02000068, 0x00000002, 0x05000036,
3717 0x00100032, 0x00000000, 0x00101046, 0x00000000, 0x05000036, 0x00100042, 0x00000000, 0x00004001,
3718 0x3f800000, 0x08000010, 0x00100012, 0x00000001, 0x00100246, 0x00000000, 0x00208246, 0x00000000,
3719 0x00000000, 0x08000010, 0x00100022, 0x00000001, 0x00100246, 0x00000000, 0x00208246, 0x00000000,
3720 0x00000001, 0x05000036, 0x00102032, 0x00000000, 0x00100046, 0x00000001, 0x05000036, 0x00102072,
3721 0x00000001, 0x00101246, 0x00000001, 0x05000036, 0x00102082, 0x00000001, 0x00004001, 0x3f800000,
3722 0x08000036, 0x00102032, 0x00000002, 0x00004002, 0x3f800000, 0x00000000, 0x00000000, 0x00000000,
3723 0x08000036, 0x00102032, 0x00000003, 0x00004002, 0x00000000, 0x3f800000, 0x00000000, 0x00000000,
3724 0x05000036, 0x00100042, 0x00000001, 0x00004001, 0x3f800000, 0x08000010, 0x00100012, 0x00000000,
3725 0x00208246, 0x00000000, 0x00000002, 0x00100246, 0x00000001, 0x08000010, 0x00100022, 0x00000000,
3726 0x00208246, 0x00000000, 0x00000003, 0x00100246, 0x00000001, 0x08000038, 0x00100022, 0x00000001,
3727 0x0010001a, 0x00000000, 0x0020803a, 0x00000000, 0x00000003, 0x08000038, 0x00100012, 0x00000001,
3728 0x0010000a, 0x00000000, 0x0020803a, 0x00000000, 0x00000002, 0x0a000000, 0x00102032, 0x00000004,
3729 0x00100046, 0x00000001, 0x00004002, 0xbf800000, 0x3f800000, 0x00000000, 0x00000000, 0x08000036,
3730 0x001020c2, 0x00000004, 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, 0x0100003e,
3732 static const DWORD ps_code[] =
3734 #if 0
3735 #define BRUSH_TYPE_SOLID 0
3736 #define BRUSH_TYPE_LINEAR 1
3737 #define BRUSH_TYPE_RADIAL 2
3738 #define BRUSH_TYPE_BITMAP 3
3739 #define BRUSH_TYPE_COUNT 4
3741 bool outline;
3742 bool is_arc;
3743 struct brush
3745 uint type;
3746 float opacity;
3747 float4 data[3];
3748 } colour_brush, opacity_brush;
3750 SamplerState s0, s1;
3751 Texture2D t0, t1;
3752 Buffer<float4> b0, b1;
3754 struct input
3756 float2 p : WORLD_POSITION;
3757 float4 b : BEZIER;
3758 nointerpolation float2x2 stroke_transform : STROKE_TRANSFORM;
3761 float4 sample_gradient(Buffer<float4> gradient, uint stop_count, float position)
3763 float4 c_low, c_high;
3764 float p_low, p_high;
3765 uint i;
3767 p_low = gradient.Load(0).x;
3768 c_low = gradient.Load(1);
3769 c_high = c_low;
3771 if (position < p_low)
3772 return c_low;
3774 for (i = 1; i < stop_count; ++i)
3776 p_high = gradient.Load(i * 2).x;
3777 c_high = gradient.Load(i * 2 + 1);
3779 if (position >= p_low && position <= p_high)
3780 return lerp(c_low, c_high, (position - p_low) / (p_high - p_low));
3782 p_low = p_high;
3783 c_low = c_high;
3786 return c_high;
3789 float4 brush_linear(struct brush brush, Buffer<float4> gradient, float2 position)
3791 float2 start, end, v_p, v_q;
3792 uint stop_count;
3793 float p;
3795 start = brush.data[0].xy;
3796 end = brush.data[0].zw;
3797 stop_count = asuint(brush.data[1].x);
3799 v_p = position - start;
3800 v_q = end - start;
3801 p = dot(v_q, v_p) / dot(v_q, v_q);
3803 return sample_gradient(gradient, stop_count, p);
3806 float4 brush_radial(struct brush brush, Buffer<float4> gradient, float2 position)
3808 float2 centre, offset, ra, rb, v_p, v_q, r;
3809 float b, c, l, t;
3810 uint stop_count;
3812 centre = brush.data[0].xy;
3813 offset = brush.data[0].zw;
3814 ra = brush.data[1].xy;
3815 rb = brush.data[1].zw;
3816 stop_count = asuint(brush.data[2].x);
3818 /* Project onto ra, rb. */
3819 r = float2(dot(ra, ra), dot(rb, rb));
3820 v_p = position - (centre + offset);
3821 v_p = float2(dot(v_p, ra), dot(v_p, rb)) / r;
3822 v_q = float2(dot(offset, ra), dot(offset, rb)) / r;
3824 /* ‖t·p̂ + q⃑‖ = 1
3825 * (t·p̂ + q⃑) · (t·p̂ + q⃑) = 1
3826 * t² + 2·(p̂·q⃑)·t + (q⃑·q⃑) = 1
3828 * b = p̂·q⃑
3829 * c = q⃑·q⃑ - 1
3830 * t = -b + √(b² - c) */
3831 l = length(v_p);
3832 b = dot(v_p, v_q) / l;
3833 c = dot(v_q, v_q) - 1.0;
3834 t = -b + sqrt(b * b - c);
3836 return sample_gradient(gradient, stop_count, l / t);
3839 float4 brush_bitmap(struct brush brush, Texture2D t, SamplerState s, float2 position)
3841 float3 transform[2];
3842 bool ignore_alpha;
3843 float2 texcoord;
3844 float4 colour;
3846 transform[0] = brush.data[0].xyz;
3847 transform[1] = brush.data[1].xyz;
3848 ignore_alpha = asuint(brush.data[1].w);
3850 texcoord.x = dot(position.xy, transform[0].xy) + transform[0].z;
3851 texcoord.y = dot(position.xy, transform[1].xy) + transform[1].z;
3852 colour = t.Sample(s, texcoord);
3853 if (ignore_alpha)
3854 colour.a = 1.0;
3855 return colour;
3858 float4 sample_brush(struct brush brush, Texture2D t, SamplerState s, Buffer<float4> b, float2 position)
3860 if (brush.type == BRUSH_TYPE_SOLID)
3861 return brush.data[0] * brush.opacity;
3862 if (brush.type == BRUSH_TYPE_LINEAR)
3863 return brush_linear(brush, b, position) * brush.opacity;
3864 if (brush.type == BRUSH_TYPE_RADIAL)
3865 return brush_radial(brush, b, position) * brush.opacity;
3866 if (brush.type == BRUSH_TYPE_BITMAP)
3867 return brush_bitmap(brush, t, s, position) * brush.opacity;
3868 return float4(0.0, 0.0, 0.0, brush.opacity);
3871 float4 main(struct input i) : SV_Target
3873 float4 colour;
3875 colour = sample_brush(colour_brush, t0, s0, b0, i.p);
3876 if (opacity_brush.type < BRUSH_TYPE_COUNT)
3877 colour *= sample_brush(opacity_brush, t1, s1, b1, i.p).a;
3879 if (outline)
3881 float2 du, dv, df;
3882 float4 uv;
3884 /* Evaluate the implicit form of the curve (u² - v = 0
3885 * for Béziers, u² + v² - 1 = 0 for arcs) in texture
3886 * space, using the screen-space partial derivatives
3887 * to convert the calculated distance to object space.
3889 * d(x, y) = |f(x, y)| / ‖∇f(x, y)‖
3890 * = |f(x, y)| / √((∂f/∂x)² + (∂f/∂y)²)
3892 * For Béziers:
3893 * f(x, y) = u(x, y)² - v(x, y)
3894 * ∂f/∂x = 2u · ∂u/∂x - ∂v/∂x
3895 * ∂f/∂y = 2u · ∂u/∂y - ∂v/∂y
3897 * For arcs:
3898 * f(x, y) = u(x, y)² + v(x, y)² - 1
3899 * ∂f/∂x = 2u · ∂u/∂x + 2v · ∂v/∂x
3900 * ∂f/∂y = 2u · ∂u/∂y + 2v · ∂v/∂y */
3901 uv = i.b;
3902 du = float2(ddx(uv.x), ddy(uv.x));
3903 dv = float2(ddx(uv.y), ddy(uv.y));
3905 if (!is_arc)
3907 df = 2.0f * uv.x * du - dv;
3909 clip(dot(df, uv.zw));
3910 clip(length(mul(i.stroke_transform, df)) - abs(uv.x * uv.x - uv.y));
3912 else
3914 df = 2.0f * uv.x * du + 2.0f * uv.y * dv;
3916 clip(dot(df, uv.zw));
3917 clip(length(mul(i.stroke_transform, df)) - abs(uv.x * uv.x + uv.y * uv.y - 1.0f));
3920 else
3922 /* Evaluate the implicit form of the curve in texture space.
3923 * "i.b.z" determines which side of the curve is shaded. */
3924 if (!is_arc)
3926 clip((i.b.x * i.b.x - i.b.y) * i.b.z);
3928 else
3930 clip((i.b.x * i.b.x + i.b.y * i.b.y - 1.0) * i.b.z);
3934 return colour;
3936 #endif
3937 0x43425844, 0xa8fee730, 0x92fa2196, 0xaf9f3eff, 0x888d4048, 0x00000001, 0x00002000, 0x00000003,
3938 0x0000002c, 0x000000c4, 0x000000f8, 0x4e475349, 0x00000090, 0x00000004, 0x00000008, 0x00000068,
3939 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000303, 0x00000077, 0x00000000, 0x00000000,
3940 0x00000003, 0x00000001, 0x00000f0f, 0x0000007e, 0x00000000, 0x00000000, 0x00000003, 0x00000002,
3941 0x00000303, 0x0000007e, 0x00000001, 0x00000000, 0x00000003, 0x00000003, 0x00000303, 0x4c524f57,
3942 0x4f505f44, 0x49544953, 0x42004e4f, 0x45495a45, 0x54530052, 0x454b4f52, 0x4152545f, 0x4f46534e,
3943 0xab004d52, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000,
3944 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x00001f00,
3945 0x00000040, 0x000007c0, 0x04000059, 0x00208e46, 0x00000000, 0x00000009, 0x0300005a, 0x00106000,
3946 0x00000000, 0x0300005a, 0x00106000, 0x00000001, 0x04001858, 0x00107000, 0x00000000, 0x00005555,
3947 0x04001858, 0x00107000, 0x00000001, 0x00005555, 0x04000858, 0x00107000, 0x00000002, 0x00005555,
3948 0x04000858, 0x00107000, 0x00000003, 0x00005555, 0x03001062, 0x00101032, 0x00000000, 0x03001062,
3949 0x001010f2, 0x00000001, 0x03000862, 0x00101032, 0x00000002, 0x03000862, 0x00101032, 0x00000003,
3950 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x0000000a, 0x09000038, 0x001000f2, 0x00000000,
3951 0x00208556, 0x00000000, 0x00000001, 0x00208e46, 0x00000000, 0x00000002, 0x0404001f, 0x0020800a,
3952 0x00000000, 0x00000001, 0x08000020, 0x00100012, 0x00000001, 0x0020800a, 0x00000000, 0x00000001,
3953 0x00004001, 0x00000001, 0x0304001f, 0x0010000a, 0x00000001, 0x09000000, 0x00100062, 0x00000001,
3954 0x00101106, 0x00000000, 0x80208106, 0x00000041, 0x00000000, 0x00000002, 0x0a000000, 0x00100032,
3955 0x00000002, 0x80208046, 0x00000041, 0x00000000, 0x00000002, 0x00208ae6, 0x00000000, 0x00000002,
3956 0x0700000f, 0x00100022, 0x00000001, 0x00100046, 0x00000002, 0x00100596, 0x00000001, 0x0700000f,
3957 0x00100042, 0x00000001, 0x00100046, 0x00000002, 0x00100046, 0x00000002, 0x0700000e, 0x00100022,
3958 0x00000001, 0x0010001a, 0x00000001, 0x0010002a, 0x00000001, 0x0a00002d, 0x001000f2, 0x00000002,
3959 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00107e46, 0x00000002, 0x0a00002d,
3960 0x001000f2, 0x00000003, 0x00004002, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00107e46,
3961 0x00000002, 0x0700001d, 0x00100042, 0x00000001, 0x0010001a, 0x00000001, 0x0010000a, 0x00000002,
3962 0x0304001f, 0x0010002a, 0x00000001, 0x05000036, 0x001000f2, 0x00000004, 0x00100e46, 0x00000003,
3963 0x05000036, 0x001000f2, 0x00000005, 0x00100e46, 0x00000003, 0x05000036, 0x001000f2, 0x00000006,
3964 0x00100e46, 0x00000003, 0x05000036, 0x00100042, 0x00000001, 0x0010000a, 0x00000002, 0x05000036,
3965 0x00100082, 0x00000001, 0x00004001, 0x00000001, 0x05000036, 0x00100022, 0x00000002, 0x00004001,
3966 0x00000000, 0x01000030, 0x08000050, 0x00100042, 0x00000002, 0x0010003a, 0x00000001, 0x0020800a,
3967 0x00000000, 0x00000003, 0x05000036, 0x00100022, 0x00000002, 0x00004001, 0x00000000, 0x03040003,
3968 0x0010002a, 0x00000002, 0x07000029, 0x00100042, 0x00000002, 0x0010003a, 0x00000001, 0x00004001,
3969 0x00000001, 0x0700002d, 0x001000f2, 0x00000007, 0x00100aa6, 0x00000002, 0x00107e46, 0x00000002,
3970 0x0700001e, 0x00100042, 0x00000002, 0x0010002a, 0x00000002, 0x00004001, 0x00000001, 0x0700002d,
3971 0x001000f2, 0x00000008, 0x00100aa6, 0x00000002, 0x00107e46, 0x00000002, 0x0700001d, 0x00100042,
3972 0x00000002, 0x0010001a, 0x00000001, 0x0010002a, 0x00000001, 0x0700001d, 0x00100082, 0x00000002,
3973 0x0010000a, 0x00000007, 0x0010001a, 0x00000001, 0x07000001, 0x00100042, 0x00000002, 0x0010003a,
3974 0x00000002, 0x0010002a, 0x00000002, 0x0304001f, 0x0010002a, 0x00000002, 0x08000000, 0x00100082,
3975 0x00000002, 0x8010002a, 0x00000041, 0x00000001, 0x0010001a, 0x00000001, 0x08000000, 0x00100022,
3976 0x00000007, 0x8010002a, 0x00000041, 0x00000001, 0x0010000a, 0x00000007, 0x0700000e, 0x00100082,
3977 0x00000002, 0x0010003a, 0x00000002, 0x0010001a, 0x00000007, 0x08000000, 0x001000f2, 0x00000009,
3978 0x80100e46, 0x00000041, 0x00000005, 0x00100e46, 0x00000008, 0x09000032, 0x001000f2, 0x00000009,
3979 0x00100ff6, 0x00000002, 0x00100e46, 0x00000009, 0x00100e46, 0x00000005, 0x05000036, 0x001000f2,
3980 0x00000006, 0x00100e46, 0x00000008, 0x05000036, 0x00100022, 0x00000002, 0x00004001, 0xffffffff,
3981 0x05000036, 0x001000f2, 0x00000004, 0x00100e46, 0x00000009, 0x01000002, 0x01000015, 0x05000036,
3982 0x001000f2, 0x00000005, 0x00100e46, 0x00000008, 0x05000036, 0x00100042, 0x00000001, 0x0010000a,
3983 0x00000007, 0x0700001e, 0x00100082, 0x00000001, 0x0010003a, 0x00000001, 0x00004001, 0x00000001,
3984 0x05000036, 0x001000f2, 0x00000006, 0x00100e46, 0x00000008, 0x05000036, 0x00100022, 0x00000002,
3985 0x0010002a, 0x00000002, 0x01000016, 0x09000037, 0x001000f2, 0x00000003, 0x00100556, 0x00000002,
3986 0x00100e46, 0x00000004, 0x00100e46, 0x00000006, 0x01000015, 0x08000038, 0x001000f2, 0x00000000,
3987 0x00100e46, 0x00000003, 0x00208556, 0x00000000, 0x00000001, 0x01000015, 0x0300001f, 0x0010000a,
3988 0x00000001, 0x08000020, 0x00100012, 0x00000001, 0x0020800a, 0x00000000, 0x00000001, 0x00004001,
3989 0x00000002, 0x0304001f, 0x0010000a, 0x00000001, 0x0900000f, 0x00100012, 0x00000002, 0x00208046,
3990 0x00000000, 0x00000003, 0x00208046, 0x00000000, 0x00000003, 0x0900000f, 0x00100022, 0x00000002,
3991 0x00208ae6, 0x00000000, 0x00000003, 0x00208ae6, 0x00000000, 0x00000003, 0x09000000, 0x00100062,
3992 0x00000001, 0x00208ba6, 0x00000000, 0x00000002, 0x00208106, 0x00000000, 0x00000002, 0x08000000,
3993 0x00100062, 0x00000001, 0x80100656, 0x00000041, 0x00000001, 0x00101106, 0x00000000, 0x0800000f,
3994 0x00100012, 0x00000003, 0x00100596, 0x00000001, 0x00208046, 0x00000000, 0x00000003, 0x0800000f,
3995 0x00100022, 0x00000003, 0x00100596, 0x00000001, 0x00208ae6, 0x00000000, 0x00000003, 0x0700000e,
3996 0x00100062, 0x00000001, 0x00100106, 0x00000003, 0x00100106, 0x00000002, 0x0900000f, 0x00100012,
3997 0x00000003, 0x00208ae6, 0x00000000, 0x00000002, 0x00208046, 0x00000000, 0x00000003, 0x0900000f,
3998 0x00100022, 0x00000003, 0x00208ae6, 0x00000000, 0x00000002, 0x00208ae6, 0x00000000, 0x00000003,
3999 0x0700000e, 0x00100032, 0x00000002, 0x00100046, 0x00000003, 0x00100046, 0x00000002, 0x0700000f,
4000 0x00100082, 0x00000001, 0x00100596, 0x00000001, 0x00100596, 0x00000001, 0x0500004b, 0x00100082,
4001 0x00000001, 0x0010003a, 0x00000001, 0x0700000f, 0x00100022, 0x00000001, 0x00100596, 0x00000001,
4002 0x00100046, 0x00000002, 0x0700000e, 0x00100022, 0x00000001, 0x0010001a, 0x00000001, 0x0010003a,
4003 0x00000001, 0x0700000f, 0x00100042, 0x00000001, 0x00100046, 0x00000002, 0x00100046, 0x00000002,
4004 0x07000000, 0x00100042, 0x00000001, 0x0010002a, 0x00000001, 0x00004001, 0xbf800000, 0x0a000032,
4005 0x00100042, 0x00000001, 0x0010001a, 0x00000001, 0x0010001a, 0x00000001, 0x8010002a, 0x00000041,
4006 0x00000001, 0x0500004b, 0x00100042, 0x00000001, 0x0010002a, 0x00000001, 0x08000000, 0x00100022,
4007 0x00000001, 0x0010002a, 0x00000001, 0x8010001a, 0x00000041, 0x00000001, 0x0700000e, 0x00100022,
4008 0x00000001, 0x0010003a, 0x00000001, 0x0010001a, 0x00000001, 0x0a00002d, 0x001000f2, 0x00000002,
4009 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00107e46, 0x00000002, 0x0a00002d,
4010 0x001000f2, 0x00000003, 0x00004002, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00107e46,
4011 0x00000002, 0x0700001d, 0x00100042, 0x00000001, 0x0010001a, 0x00000001, 0x0010000a, 0x00000002,
4012 0x0304001f, 0x0010002a, 0x00000001, 0x05000036, 0x001000f2, 0x00000004, 0x00100e46, 0x00000003,
4013 0x05000036, 0x001000f2, 0x00000005, 0x00100e46, 0x00000003, 0x05000036, 0x001000f2, 0x00000006,
4014 0x00100e46, 0x00000003, 0x05000036, 0x00100042, 0x00000001, 0x0010000a, 0x00000002, 0x05000036,
4015 0x00100082, 0x00000001, 0x00004001, 0x00000001, 0x05000036, 0x00100022, 0x00000002, 0x00004001,
4016 0x00000000, 0x01000030, 0x08000050, 0x00100042, 0x00000002, 0x0010003a, 0x00000001, 0x0020800a,
4017 0x00000000, 0x00000004, 0x05000036, 0x00100022, 0x00000002, 0x00004001, 0x00000000, 0x03040003,
4018 0x0010002a, 0x00000002, 0x07000029, 0x00100042, 0x00000002, 0x0010003a, 0x00000001, 0x00004001,
4019 0x00000001, 0x0700002d, 0x001000f2, 0x00000007, 0x00100aa6, 0x00000002, 0x00107e46, 0x00000002,
4020 0x0700001e, 0x00100042, 0x00000002, 0x0010002a, 0x00000002, 0x00004001, 0x00000001, 0x0700002d,
4021 0x001000f2, 0x00000008, 0x00100aa6, 0x00000002, 0x00107e46, 0x00000002, 0x0700001d, 0x00100042,
4022 0x00000002, 0x0010001a, 0x00000001, 0x0010002a, 0x00000001, 0x0700001d, 0x00100082, 0x00000002,
4023 0x0010000a, 0x00000007, 0x0010001a, 0x00000001, 0x07000001, 0x00100042, 0x00000002, 0x0010003a,
4024 0x00000002, 0x0010002a, 0x00000002, 0x0304001f, 0x0010002a, 0x00000002, 0x08000000, 0x00100082,
4025 0x00000002, 0x8010002a, 0x00000041, 0x00000001, 0x0010001a, 0x00000001, 0x08000000, 0x00100022,
4026 0x00000007, 0x8010002a, 0x00000041, 0x00000001, 0x0010000a, 0x00000007, 0x0700000e, 0x00100082,
4027 0x00000002, 0x0010003a, 0x00000002, 0x0010001a, 0x00000007, 0x08000000, 0x001000f2, 0x00000009,
4028 0x80100e46, 0x00000041, 0x00000005, 0x00100e46, 0x00000008, 0x09000032, 0x001000f2, 0x00000009,
4029 0x00100ff6, 0x00000002, 0x00100e46, 0x00000009, 0x00100e46, 0x00000005, 0x05000036, 0x001000f2,
4030 0x00000006, 0x00100e46, 0x00000008, 0x05000036, 0x00100022, 0x00000002, 0x00004001, 0xffffffff,
4031 0x05000036, 0x001000f2, 0x00000004, 0x00100e46, 0x00000009, 0x01000002, 0x01000015, 0x05000036,
4032 0x001000f2, 0x00000005, 0x00100e46, 0x00000008, 0x05000036, 0x00100042, 0x00000001, 0x0010000a,
4033 0x00000007, 0x0700001e, 0x00100082, 0x00000001, 0x0010003a, 0x00000001, 0x00004001, 0x00000001,
4034 0x05000036, 0x001000f2, 0x00000006, 0x00100e46, 0x00000008, 0x05000036, 0x00100022, 0x00000002,
4035 0x0010002a, 0x00000002, 0x01000016, 0x09000037, 0x001000f2, 0x00000003, 0x00100556, 0x00000002,
4036 0x00100e46, 0x00000004, 0x00100e46, 0x00000006, 0x01000015, 0x08000038, 0x001000f2, 0x00000000,
4037 0x00100e46, 0x00000003, 0x00208556, 0x00000000, 0x00000001, 0x01000015, 0x0300001f, 0x0010000a,
4038 0x00000001, 0x08000020, 0x00100012, 0x00000001, 0x0020800a, 0x00000000, 0x00000001, 0x00004001,
4039 0x00000003, 0x0304001f, 0x0010000a, 0x00000001, 0x0800000f, 0x00100022, 0x00000001, 0x00101046,
4040 0x00000000, 0x00208046, 0x00000000, 0x00000002, 0x08000000, 0x00100012, 0x00000002, 0x0010001a,
4041 0x00000001, 0x0020802a, 0x00000000, 0x00000002, 0x0800000f, 0x00100022, 0x00000001, 0x00101046,
4042 0x00000000, 0x00208046, 0x00000000, 0x00000003, 0x08000000, 0x00100022, 0x00000002, 0x0010001a,
4043 0x00000001, 0x0020802a, 0x00000000, 0x00000003, 0x09000045, 0x001000f2, 0x00000002, 0x00100046,
4044 0x00000002, 0x00107e46, 0x00000000, 0x00106000, 0x00000000, 0x0a000037, 0x00100082, 0x00000002,
4045 0x0020803a, 0x00000000, 0x00000003, 0x00004001, 0x3f800000, 0x0010003a, 0x00000002, 0x08000038,
4046 0x001000f2, 0x00000000, 0x00100e46, 0x00000002, 0x00208556, 0x00000000, 0x00000001, 0x01000015,
4047 0x05000036, 0x00100012, 0x00000002, 0x00004001, 0x00000000, 0x06000036, 0x00100082, 0x00000002,
4048 0x0020801a, 0x00000000, 0x00000001, 0x09000037, 0x001000f2, 0x00000000, 0x00100006, 0x00000001,
4049 0x00100e46, 0x00000000, 0x00100c06, 0x00000002, 0x01000015, 0x01000015, 0x01000015, 0x0800004f,
4050 0x00100012, 0x00000001, 0x0020800a, 0x00000000, 0x00000005, 0x00004001, 0x00000004, 0x0304001f,
4051 0x0010000a, 0x00000001, 0x09000038, 0x00100012, 0x00000001, 0x0020801a, 0x00000000, 0x00000005,
4052 0x0020803a, 0x00000000, 0x00000006, 0x0404001f, 0x0020800a, 0x00000000, 0x00000005, 0x08000020,
4053 0x00100022, 0x00000001, 0x0020800a, 0x00000000, 0x00000005, 0x00004001, 0x00000001, 0x0304001f,
4054 0x0010001a, 0x00000001, 0x09000000, 0x001000c2, 0x00000001, 0x00101406, 0x00000000, 0x80208406,
4055 0x00000041, 0x00000000, 0x00000006, 0x0a000000, 0x00100032, 0x00000002, 0x80208046, 0x00000041,
4056 0x00000000, 0x00000006, 0x00208ae6, 0x00000000, 0x00000006, 0x0700000f, 0x00100042, 0x00000001,
4057 0x00100046, 0x00000002, 0x00100ae6, 0x00000001, 0x0700000f, 0x00100082, 0x00000001, 0x00100046,
4058 0x00000002, 0x00100046, 0x00000002, 0x0700000e, 0x00100042, 0x00000001, 0x0010002a, 0x00000001,
4059 0x0010003a, 0x00000001, 0x0a00002d, 0x001000f2, 0x00000002, 0x00004002, 0x00000000, 0x00000000,
4060 0x00000000, 0x00000000, 0x00107e46, 0x00000003, 0x0a00002d, 0x001000f2, 0x00000003, 0x00004002,
4061 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00107e46, 0x00000003, 0x0700001d, 0x00100082,
4062 0x00000001, 0x0010002a, 0x00000001, 0x0010000a, 0x00000002, 0x0304001f, 0x0010003a, 0x00000001,
4063 0x05000036, 0x00100082, 0x00000001, 0x0010003a, 0x00000003, 0x05000036, 0x00100062, 0x00000002,
4064 0x00100ff6, 0x00000003, 0x05000036, 0x00100082, 0x00000002, 0x0010000a, 0x00000002, 0x08000036,
4065 0x00100032, 0x00000003, 0x00004002, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x01000030,
4066 0x08000050, 0x00100042, 0x00000003, 0x0010000a, 0x00000003, 0x0020800a, 0x00000000, 0x00000007,
4067 0x05000036, 0x00100022, 0x00000003, 0x00004001, 0x00000000, 0x03040003, 0x0010002a, 0x00000003,
4068 0x07000029, 0x00100042, 0x00000003, 0x0010000a, 0x00000003, 0x00004001, 0x00000001, 0x0700002d,
4069 0x001000f2, 0x00000004, 0x00100aa6, 0x00000003, 0x00107e46, 0x00000003, 0x0700001e, 0x00100042,
4070 0x00000003, 0x0010002a, 0x00000003, 0x00004001, 0x00000001, 0x0700002d, 0x001000f2, 0x00000005,
4071 0x00100aa6, 0x00000003, 0x00107e46, 0x00000003, 0x0700001d, 0x00100042, 0x00000003, 0x0010002a,
4072 0x00000001, 0x0010003a, 0x00000002, 0x0700001d, 0x00100022, 0x00000004, 0x0010000a, 0x00000004,
4073 0x0010002a, 0x00000001, 0x07000001, 0x00100042, 0x00000003, 0x0010002a, 0x00000003, 0x0010001a,
4074 0x00000004, 0x0304001f, 0x0010002a, 0x00000003, 0x08000000, 0x00100022, 0x00000004, 0x0010002a,
4075 0x00000001, 0x8010003a, 0x00000041, 0x00000002, 0x08000000, 0x00100042, 0x00000004, 0x8010003a,
4076 0x00000041, 0x00000002, 0x0010000a, 0x00000004, 0x0700000e, 0x00100022, 0x00000004, 0x0010001a,
4077 0x00000004, 0x0010002a, 0x00000004, 0x08000000, 0x00100042, 0x00000004, 0x8010001a, 0x00000041,
4078 0x00000002, 0x0010003a, 0x00000005, 0x09000032, 0x00100022, 0x00000004, 0x0010001a, 0x00000004,
4079 0x0010002a, 0x00000004, 0x0010001a, 0x00000002, 0x05000036, 0x00100042, 0x00000002, 0x0010003a,
4080 0x00000005, 0x05000036, 0x00100022, 0x00000003, 0x00004001, 0xffffffff, 0x05000036, 0x00100082,
4081 0x00000001, 0x0010001a, 0x00000004, 0x01000002, 0x01000015, 0x05000036, 0x00100022, 0x00000002,
4082 0x0010003a, 0x00000005, 0x05000036, 0x00100082, 0x00000002, 0x0010000a, 0x00000004, 0x0700001e,
4083 0x00100012, 0x00000003, 0x0010000a, 0x00000003, 0x00004001, 0x00000001, 0x05000036, 0x00100042,
4084 0x00000002, 0x0010003a, 0x00000005, 0x05000036, 0x00100032, 0x00000003, 0x00100086, 0x00000003,
4085 0x01000016, 0x09000037, 0x00100042, 0x00000001, 0x0010001a, 0x00000003, 0x0010003a, 0x00000001,
4086 0x0010002a, 0x00000002, 0x01000012, 0x05000036, 0x00100042, 0x00000001, 0x0010003a, 0x00000003,
4087 0x01000015, 0x08000038, 0x00100012, 0x00000001, 0x0010002a, 0x00000001, 0x0020801a, 0x00000000,
4088 0x00000005, 0x01000015, 0x0300001f, 0x0010001a, 0x00000001, 0x08000020, 0x00100022, 0x00000001,
4089 0x0020800a, 0x00000000, 0x00000005, 0x00004001, 0x00000002, 0x0304001f, 0x0010001a, 0x00000001,
4090 0x0900000f, 0x00100012, 0x00000002, 0x00208046, 0x00000000, 0x00000007, 0x00208046, 0x00000000,
4091 0x00000007, 0x0900000f, 0x00100022, 0x00000002, 0x00208ae6, 0x00000000, 0x00000007, 0x00208ae6,
4092 0x00000000, 0x00000007, 0x09000000, 0x001000c2, 0x00000001, 0x00208ea6, 0x00000000, 0x00000006,
4093 0x00208406, 0x00000000, 0x00000006, 0x08000000, 0x001000c2, 0x00000001, 0x80100ea6, 0x00000041,
4094 0x00000001, 0x00101406, 0x00000000, 0x0800000f, 0x00100012, 0x00000003, 0x00100ae6, 0x00000001,
4095 0x00208046, 0x00000000, 0x00000007, 0x0800000f, 0x00100022, 0x00000003, 0x00100ae6, 0x00000001,
4096 0x00208ae6, 0x00000000, 0x00000007, 0x0700000e, 0x001000c2, 0x00000001, 0x00100406, 0x00000003,
4097 0x00100406, 0x00000002, 0x0900000f, 0x00100012, 0x00000003, 0x00208ae6, 0x00000000, 0x00000006,
4098 0x00208046, 0x00000000, 0x00000007, 0x0900000f, 0x00100022, 0x00000003, 0x00208ae6, 0x00000000,
4099 0x00000006, 0x00208ae6, 0x00000000, 0x00000007, 0x0700000e, 0x00100032, 0x00000002, 0x00100046,
4100 0x00000003, 0x00100046, 0x00000002, 0x0700000f, 0x00100042, 0x00000002, 0x00100ae6, 0x00000001,
4101 0x00100ae6, 0x00000001, 0x0500004b, 0x00100042, 0x00000002, 0x0010002a, 0x00000002, 0x0700000f,
4102 0x00100042, 0x00000001, 0x00100ae6, 0x00000001, 0x00100046, 0x00000002, 0x0700000e, 0x00100042,
4103 0x00000001, 0x0010002a, 0x00000001, 0x0010002a, 0x00000002, 0x0700000f, 0x00100082, 0x00000001,
4104 0x00100046, 0x00000002, 0x00100046, 0x00000002, 0x07000000, 0x00100082, 0x00000001, 0x0010003a,
4105 0x00000001, 0x00004001, 0xbf800000, 0x0a000032, 0x00100082, 0x00000001, 0x0010002a, 0x00000001,
4106 0x0010002a, 0x00000001, 0x8010003a, 0x00000041, 0x00000001, 0x0500004b, 0x00100082, 0x00000001,
4107 0x0010003a, 0x00000001, 0x08000000, 0x00100042, 0x00000001, 0x0010003a, 0x00000001, 0x8010002a,
4108 0x00000041, 0x00000001, 0x0700000e, 0x00100042, 0x00000001, 0x0010002a, 0x00000002, 0x0010002a,
4109 0x00000001, 0x0a00002d, 0x001000f2, 0x00000002, 0x00004002, 0x00000000, 0x00000000, 0x00000000,
4110 0x00000000, 0x00107e46, 0x00000003, 0x0a00002d, 0x001000f2, 0x00000003, 0x00004002, 0x00000001,
4111 0x00000001, 0x00000001, 0x00000001, 0x00107e46, 0x00000003, 0x0700001d, 0x00100082, 0x00000001,
4112 0x0010002a, 0x00000001, 0x0010000a, 0x00000002, 0x0304001f, 0x0010003a, 0x00000001, 0x05000036,
4113 0x00100082, 0x00000001, 0x0010003a, 0x00000003, 0x05000036, 0x00100062, 0x00000002, 0x00100ff6,
4114 0x00000003, 0x05000036, 0x00100082, 0x00000002, 0x0010000a, 0x00000002, 0x08000036, 0x00100032,
4115 0x00000003, 0x00004002, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x01000030, 0x08000050,
4116 0x00100042, 0x00000003, 0x0010000a, 0x00000003, 0x0020800a, 0x00000000, 0x00000008, 0x05000036,
4117 0x00100022, 0x00000003, 0x00004001, 0x00000000, 0x03040003, 0x0010002a, 0x00000003, 0x07000029,
4118 0x00100042, 0x00000003, 0x0010000a, 0x00000003, 0x00004001, 0x00000001, 0x0700002d, 0x001000f2,
4119 0x00000004, 0x00100aa6, 0x00000003, 0x00107e46, 0x00000003, 0x0700001e, 0x00100042, 0x00000003,
4120 0x0010002a, 0x00000003, 0x00004001, 0x00000001, 0x0700002d, 0x001000f2, 0x00000005, 0x00100aa6,
4121 0x00000003, 0x00107e46, 0x00000003, 0x0700001d, 0x00100042, 0x00000003, 0x0010002a, 0x00000001,
4122 0x0010003a, 0x00000002, 0x0700001d, 0x00100022, 0x00000004, 0x0010000a, 0x00000004, 0x0010002a,
4123 0x00000001, 0x07000001, 0x00100042, 0x00000003, 0x0010002a, 0x00000003, 0x0010001a, 0x00000004,
4124 0x0304001f, 0x0010002a, 0x00000003, 0x08000000, 0x00100022, 0x00000004, 0x0010002a, 0x00000001,
4125 0x8010003a, 0x00000041, 0x00000002, 0x08000000, 0x00100042, 0x00000004, 0x8010003a, 0x00000041,
4126 0x00000002, 0x0010000a, 0x00000004, 0x0700000e, 0x00100022, 0x00000004, 0x0010001a, 0x00000004,
4127 0x0010002a, 0x00000004, 0x08000000, 0x00100042, 0x00000004, 0x8010001a, 0x00000041, 0x00000002,
4128 0x0010003a, 0x00000005, 0x09000032, 0x00100022, 0x00000004, 0x0010001a, 0x00000004, 0x0010002a,
4129 0x00000004, 0x0010001a, 0x00000002, 0x05000036, 0x00100042, 0x00000002, 0x0010003a, 0x00000005,
4130 0x05000036, 0x00100022, 0x00000003, 0x00004001, 0xffffffff, 0x05000036, 0x00100082, 0x00000001,
4131 0x0010001a, 0x00000004, 0x01000002, 0x01000015, 0x05000036, 0x00100022, 0x00000002, 0x0010003a,
4132 0x00000005, 0x05000036, 0x00100082, 0x00000002, 0x0010000a, 0x00000004, 0x0700001e, 0x00100012,
4133 0x00000003, 0x0010000a, 0x00000003, 0x00004001, 0x00000001, 0x05000036, 0x00100042, 0x00000002,
4134 0x0010003a, 0x00000005, 0x05000036, 0x00100032, 0x00000003, 0x00100086, 0x00000003, 0x01000016,
4135 0x09000037, 0x00100042, 0x00000001, 0x0010001a, 0x00000003, 0x0010003a, 0x00000001, 0x0010002a,
4136 0x00000002, 0x01000012, 0x05000036, 0x00100042, 0x00000001, 0x0010003a, 0x00000003, 0x01000015,
4137 0x08000038, 0x00100012, 0x00000001, 0x0010002a, 0x00000001, 0x0020801a, 0x00000000, 0x00000005,
4138 0x01000015, 0x0300001f, 0x0010001a, 0x00000001, 0x08000020, 0x00100022, 0x00000001, 0x0020800a,
4139 0x00000000, 0x00000005, 0x00004001, 0x00000003, 0x0304001f, 0x0010001a, 0x00000001, 0x0800000f,
4140 0x00100042, 0x00000001, 0x00101046, 0x00000000, 0x00208046, 0x00000000, 0x00000006, 0x08000000,
4141 0x00100012, 0x00000002, 0x0010002a, 0x00000001, 0x0020802a, 0x00000000, 0x00000006, 0x0800000f,
4142 0x00100042, 0x00000001, 0x00101046, 0x00000000, 0x00208046, 0x00000000, 0x00000007, 0x08000000,
4143 0x00100022, 0x00000002, 0x0010002a, 0x00000001, 0x0020802a, 0x00000000, 0x00000007, 0x09000045,
4144 0x001000f2, 0x00000002, 0x00100046, 0x00000002, 0x00107e46, 0x00000001, 0x00106000, 0x00000001,
4145 0x0a000037, 0x00100042, 0x00000001, 0x0020803a, 0x00000000, 0x00000007, 0x00004001, 0x3f800000,
4146 0x0010003a, 0x00000002, 0x08000038, 0x00100012, 0x00000001, 0x0010002a, 0x00000001, 0x0020801a,
4147 0x00000000, 0x00000005, 0x01000015, 0x0a000037, 0x00100012, 0x00000001, 0x0010001a, 0x00000001,
4148 0x0010000a, 0x00000001, 0x0020801a, 0x00000000, 0x00000005, 0x01000015, 0x01000015, 0x01000015,
4149 0x07000038, 0x001020f2, 0x00000000, 0x00100e46, 0x00000000, 0x00100006, 0x00000001, 0x01000012,
4150 0x05000036, 0x001020f2, 0x00000000, 0x00100e46, 0x00000000, 0x01000015, 0x0404001f, 0x0020800a,
4151 0x00000000, 0x00000000, 0x0500000b, 0x00100032, 0x00000000, 0x00101046, 0x00000001, 0x0500000c,
4152 0x001000c2, 0x00000000, 0x00101406, 0x00000001, 0x08000027, 0x00100012, 0x00000001, 0x0020801a,
4153 0x00000000, 0x00000000, 0x00004001, 0x00000000, 0x0500003b, 0x00100022, 0x00000001, 0x0010000a,
4154 0x00000001, 0x07000000, 0x001000c2, 0x00000001, 0x00101406, 0x00000001, 0x00101406, 0x00000001,
4155 0x07000038, 0x001000f2, 0x00000002, 0x00100d86, 0x00000000, 0x00100fa6, 0x00000001, 0x0a000032,
4156 0x00100032, 0x00000000, 0x00100aa6, 0x00000001, 0x00100086, 0x00000000, 0x801005d6, 0x00000041,
4157 0x00000000, 0x0700000f, 0x00100042, 0x00000000, 0x00100046, 0x00000000, 0x00101ae6, 0x00000001,
4158 0x07000031, 0x00100042, 0x00000000, 0x0010002a, 0x00000000, 0x00004001, 0x00000000, 0x07000001,
4159 0x00100042, 0x00000000, 0x0010001a, 0x00000001, 0x0010002a, 0x00000000, 0x0304000d, 0x0010002a,
4160 0x00000000, 0x07000038, 0x00100062, 0x00000000, 0x00100556, 0x00000000, 0x00101106, 0x00000003,
4161 0x09000032, 0x00100032, 0x00000000, 0x00101046, 0x00000002, 0x00100006, 0x00000000, 0x00100596,
4162 0x00000000, 0x0700000f, 0x00100012, 0x00000000, 0x00100046, 0x00000000, 0x00100046, 0x00000000,
4163 0x0500004b, 0x00100012, 0x00000000, 0x0010000a, 0x00000000, 0x07000038, 0x00100062, 0x00000000,
4164 0x00101106, 0x00000001, 0x00101106, 0x00000001, 0x0a000032, 0x00100082, 0x00000000, 0x0010100a,
4165 0x00000001, 0x0010100a, 0x00000001, 0x8010101a, 0x00000041, 0x00000001, 0x08000000, 0x00100012,
4166 0x00000000, 0x8010003a, 0x000000c1, 0x00000000, 0x0010000a, 0x00000000, 0x07000031, 0x00100012,
4167 0x00000000, 0x0010000a, 0x00000000, 0x00004001, 0x00000000, 0x07000001, 0x00100012, 0x00000000,
4168 0x0010001a, 0x00000001, 0x0010000a, 0x00000000, 0x0304000d, 0x0010000a, 0x00000000, 0x07000000,
4169 0x00100092, 0x00000000, 0x00100ea6, 0x00000002, 0x00100406, 0x00000002, 0x0700000f, 0x00100022,
4170 0x00000001, 0x001000c6, 0x00000000, 0x00101ae6, 0x00000001, 0x07000031, 0x00100022, 0x00000001,
4171 0x0010001a, 0x00000001, 0x00004001, 0x00000000, 0x07000001, 0x00100022, 0x00000001, 0x0010000a,
4172 0x00000001, 0x0010001a, 0x00000001, 0x0304000d, 0x0010001a, 0x00000001, 0x07000038, 0x00100062,
4173 0x00000001, 0x00100ff6, 0x00000000, 0x00101106, 0x00000003, 0x09000032, 0x00100092, 0x00000000,
4174 0x00101406, 0x00000002, 0x00100006, 0x00000000, 0x00100956, 0x00000001, 0x0700000f, 0x00100012,
4175 0x00000000, 0x001000c6, 0x00000000, 0x001000c6, 0x00000000, 0x0500004b, 0x00100012, 0x00000000,
4176 0x0010000a, 0x00000000, 0x07000000, 0x00100022, 0x00000000, 0x0010002a, 0x00000000, 0x0010001a,
4177 0x00000000, 0x07000000, 0x00100022, 0x00000000, 0x0010001a, 0x00000000, 0x00004001, 0xbf800000,
4178 0x08000000, 0x00100012, 0x00000000, 0x8010001a, 0x000000c1, 0x00000000, 0x0010000a, 0x00000000,
4179 0x07000031, 0x00100012, 0x00000000, 0x0010000a, 0x00000000, 0x00004001, 0x00000000, 0x07000001,
4180 0x00100012, 0x00000000, 0x0010000a, 0x00000001, 0x0010000a, 0x00000000, 0x0304000d, 0x0010000a,
4181 0x00000000, 0x01000012, 0x08000027, 0x00100012, 0x00000000, 0x0020801a, 0x00000000, 0x00000000,
4182 0x00004001, 0x00000000, 0x0500003b, 0x00100022, 0x00000000, 0x0010000a, 0x00000000, 0x07000038,
4183 0x001000c2, 0x00000000, 0x00101406, 0x00000001, 0x00101406, 0x00000001, 0x0a000032, 0x00100012,
4184 0x00000001, 0x0010100a, 0x00000001, 0x0010100a, 0x00000001, 0x8010101a, 0x00000041, 0x00000001,
4185 0x07000038, 0x00100012, 0x00000001, 0x0010000a, 0x00000001, 0x0010102a, 0x00000001, 0x07000031,
4186 0x00100012, 0x00000001, 0x0010000a, 0x00000001, 0x00004001, 0x00000000, 0x07000001, 0x00100022,
4187 0x00000000, 0x0010001a, 0x00000000, 0x0010000a, 0x00000001, 0x0304000d, 0x0010001a, 0x00000000,
4188 0x07000000, 0x00100022, 0x00000000, 0x0010003a, 0x00000000, 0x0010002a, 0x00000000, 0x07000000,
4189 0x00100022, 0x00000000, 0x0010001a, 0x00000000, 0x00004001, 0xbf800000, 0x07000038, 0x00100022,
4190 0x00000000, 0x0010001a, 0x00000000, 0x0010102a, 0x00000001, 0x07000031, 0x00100022, 0x00000000,
4191 0x0010001a, 0x00000000, 0x00004001, 0x00000000, 0x07000001, 0x00100012, 0x00000000, 0x0010000a,
4192 0x00000000, 0x0010001a, 0x00000000, 0x0304000d, 0x0010000a, 0x00000000, 0x01000015, 0x0100003e,
4194 static const struct shape_info
4196 enum d2d_shape_type shape_type;
4197 const D3D11_INPUT_ELEMENT_DESC *il_desc;
4198 unsigned int il_element_count;
4199 const void *vs_code;
4200 size_t vs_code_size;
4202 shape_info[] =
4204 {D2D_SHAPE_TYPE_OUTLINE, il_desc_outline, ARRAY_SIZE(il_desc_outline),
4205 vs_code_outline, sizeof(vs_code_outline)},
4206 {D2D_SHAPE_TYPE_BEZIER_OUTLINE, il_desc_curve_outline, ARRAY_SIZE(il_desc_curve_outline),
4207 vs_code_bezier_outline, sizeof(vs_code_bezier_outline)},
4208 {D2D_SHAPE_TYPE_ARC_OUTLINE, il_desc_curve_outline, ARRAY_SIZE(il_desc_curve_outline),
4209 vs_code_arc_outline, sizeof(vs_code_arc_outline)},
4210 {D2D_SHAPE_TYPE_TRIANGLE, il_desc_triangle, ARRAY_SIZE(il_desc_triangle),
4211 vs_code_triangle, sizeof(vs_code_triangle)},
4212 {D2D_SHAPE_TYPE_CURVE, il_desc_curve, ARRAY_SIZE(il_desc_curve),
4213 vs_code_curve, sizeof(vs_code_curve)},
4215 static const struct
4217 float x, y;
4219 quad[] =
4221 {-1.0f, 1.0f},
4222 {-1.0f, -1.0f},
4223 { 1.0f, 1.0f},
4224 { 1.0f, -1.0f},
4226 static const UINT16 indices[] = {0, 1, 2, 2, 1, 3};
4227 static const D3D_FEATURE_LEVEL feature_levels = D3D_FEATURE_LEVEL_10_0;
4229 render_target->ID2D1DeviceContext1_iface.lpVtbl = &d2d_device_context_vtbl;
4230 render_target->ID2D1GdiInteropRenderTarget_iface.lpVtbl = &d2d_gdi_interop_render_target_vtbl;
4231 render_target->IDWriteTextRenderer_iface.lpVtbl = &d2d_text_renderer_vtbl;
4232 render_target->IUnknown_iface.lpVtbl = &d2d_device_context_inner_unknown_vtbl;
4233 render_target->refcount = 1;
4234 ID2D1Device_GetFactory(device, &render_target->factory);
4235 render_target->device = device;
4236 ID2D1Device_AddRef(render_target->device);
4238 render_target->outer_unknown = outer_unknown ? outer_unknown : &render_target->IUnknown_iface;
4239 render_target->ops = ops;
4241 device_impl = unsafe_impl_from_ID2D1Device((ID2D1Device1 *)device);
4242 if (FAILED(hr = IDXGIDevice_QueryInterface(device_impl->dxgi_device,
4243 &IID_ID3D11Device1, (void **)&render_target->d3d_device)))
4245 WARN("Failed to query ID3D11Device1 interface, hr %#lx.\n", hr);
4246 goto err;
4249 if (FAILED(hr = ID3D11Device1_CreateDeviceContextState(render_target->d3d_device,
4250 0, &feature_levels, 1, D3D11_SDK_VERSION, &IID_ID3D11Device1, NULL,
4251 &render_target->d3d_state)))
4253 WARN("Failed to create device context state, hr %#lx.\n", hr);
4254 goto err;
4257 for (i = 0; i < ARRAY_SIZE(shape_info); ++i)
4259 const struct shape_info *si = &shape_info[i];
4261 if (FAILED(hr = ID3D11Device1_CreateInputLayout(render_target->d3d_device, si->il_desc, si->il_element_count,
4262 si->vs_code, si->vs_code_size, &render_target->shape_resources[si->shape_type].il)))
4264 WARN("Failed to create input layout for shape type %#x, hr %#lx.\n", si->shape_type, hr);
4265 goto err;
4268 if (FAILED(hr = ID3D11Device1_CreateVertexShader(render_target->d3d_device, si->vs_code,
4269 si->vs_code_size, NULL, &render_target->shape_resources[si->shape_type].vs)))
4271 WARN("Failed to create vertex shader for shape type %#x, hr %#lx.\n", si->shape_type, hr);
4272 goto err;
4277 buffer_desc.ByteWidth = sizeof(struct d2d_vs_cb);
4278 buffer_desc.Usage = D3D11_USAGE_DYNAMIC;
4279 buffer_desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
4280 buffer_desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
4281 buffer_desc.MiscFlags = 0;
4283 if (FAILED(hr = ID3D11Device1_CreateBuffer(render_target->d3d_device, &buffer_desc, NULL,
4284 &render_target->vs_cb)))
4286 WARN("Failed to create constant buffer, hr %#lx.\n", hr);
4287 goto err;
4290 if (FAILED(hr = ID3D11Device1_CreatePixelShader(render_target->d3d_device,
4291 ps_code, sizeof(ps_code), NULL, &render_target->ps)))
4293 WARN("Failed to create pixel shader, hr %#lx.\n", hr);
4294 goto err;
4297 buffer_desc.ByteWidth = sizeof(struct d2d_ps_cb);
4298 buffer_desc.Usage = D3D11_USAGE_DYNAMIC;
4299 buffer_desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
4300 buffer_desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
4301 buffer_desc.MiscFlags = 0;
4303 if (FAILED(hr = ID3D11Device1_CreateBuffer(render_target->d3d_device, &buffer_desc, NULL,
4304 &render_target->ps_cb)))
4306 WARN("Failed to create constant buffer, hr %#lx.\n", hr);
4307 goto err;
4310 buffer_desc.ByteWidth = sizeof(indices);
4311 buffer_desc.Usage = D3D11_USAGE_DEFAULT;
4312 buffer_desc.BindFlags = D3D11_BIND_INDEX_BUFFER;
4313 buffer_desc.CPUAccessFlags = 0;
4314 buffer_desc.MiscFlags = 0;
4316 buffer_data.pSysMem = indices;
4317 buffer_data.SysMemPitch = 0;
4318 buffer_data.SysMemSlicePitch = 0;
4320 if (FAILED(hr = ID3D11Device1_CreateBuffer(render_target->d3d_device,
4321 &buffer_desc, &buffer_data, &render_target->ib)))
4323 WARN("Failed to create clear index buffer, hr %#lx.\n", hr);
4324 goto err;
4327 buffer_desc.ByteWidth = sizeof(quad);
4328 buffer_desc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
4329 buffer_data.pSysMem = quad;
4331 render_target->vb_stride = sizeof(*quad);
4332 if (FAILED(hr = ID3D11Device1_CreateBuffer(render_target->d3d_device,
4333 &buffer_desc, &buffer_data, &render_target->vb)))
4335 WARN("Failed to create clear vertex buffer, hr %#lx.\n", hr);
4336 goto err;
4339 rs_desc.FillMode = D3D11_FILL_SOLID;
4340 rs_desc.CullMode = D3D11_CULL_NONE;
4341 rs_desc.FrontCounterClockwise = FALSE;
4342 rs_desc.DepthBias = 0;
4343 rs_desc.DepthBiasClamp = 0.0f;
4344 rs_desc.SlopeScaledDepthBias = 0.0f;
4345 rs_desc.DepthClipEnable = TRUE;
4346 rs_desc.ScissorEnable = TRUE;
4347 rs_desc.MultisampleEnable = FALSE;
4348 rs_desc.AntialiasedLineEnable = FALSE;
4349 if (FAILED(hr = ID3D11Device1_CreateRasterizerState(render_target->d3d_device, &rs_desc, &render_target->rs)))
4351 WARN("Failed to create clear rasteriser state, hr %#lx.\n", hr);
4352 goto err;
4355 if (FAILED(hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED,
4356 &IID_IDWriteFactory, (IUnknown **)&dwrite_factory)))
4358 ERR("Failed to create dwrite factory, hr %#lx.\n", hr);
4359 goto err;
4362 hr = IDWriteFactory_CreateRenderingParams(dwrite_factory, &render_target->default_text_rendering_params);
4363 IDWriteFactory_Release(dwrite_factory);
4364 if (FAILED(hr))
4366 ERR("Failed to create default text rendering parameters, hr %#lx.\n", hr);
4367 goto err;
4370 render_target->drawing_state.transform = identity;
4372 if (!d2d_clip_stack_init(&render_target->clip_stack))
4374 WARN("Failed to initialize clip stack.\n");
4375 hr = E_FAIL;
4376 goto err;
4379 render_target->desc.dpiX = 96.0f;
4380 render_target->desc.dpiY = 96.0f;
4382 return S_OK;
4384 err:
4385 if (render_target->default_text_rendering_params)
4386 IDWriteRenderingParams_Release(render_target->default_text_rendering_params);
4387 if (render_target->rs)
4388 ID3D11RasterizerState_Release(render_target->rs);
4389 if (render_target->vb)
4390 ID3D11Buffer_Release(render_target->vb);
4391 if (render_target->ib)
4392 ID3D11Buffer_Release(render_target->ib);
4393 if (render_target->ps_cb)
4394 ID3D11Buffer_Release(render_target->ps_cb);
4395 if (render_target->ps)
4396 ID3D11PixelShader_Release(render_target->ps);
4397 if (render_target->vs_cb)
4398 ID3D11Buffer_Release(render_target->vs_cb);
4399 for (i = 0; i < D2D_SHAPE_TYPE_COUNT; ++i)
4401 if (render_target->shape_resources[i].vs)
4402 ID3D11VertexShader_Release(render_target->shape_resources[i].vs);
4403 if (render_target->shape_resources[i].il)
4404 ID3D11InputLayout_Release(render_target->shape_resources[i].il);
4406 if (render_target->d3d_state)
4407 ID3DDeviceContextState_Release(render_target->d3d_state);
4408 if (render_target->d3d_device)
4409 ID3D11Device1_Release(render_target->d3d_device);
4410 ID2D1Device_Release(render_target->device);
4411 ID2D1Factory_Release(render_target->factory);
4412 return hr;
4415 HRESULT d2d_d3d_create_render_target(ID2D1Device *device, IDXGISurface *surface, IUnknown *outer_unknown,
4416 const struct d2d_device_context_ops *ops, const D2D1_RENDER_TARGET_PROPERTIES *desc, void **render_target)
4418 D2D1_BITMAP_PROPERTIES1 bitmap_desc;
4419 struct d2d_device_context *object;
4420 ID2D1Bitmap1 *bitmap;
4421 HRESULT hr;
4423 if (desc->type != D2D1_RENDER_TARGET_TYPE_DEFAULT && desc->type != D2D1_RENDER_TARGET_TYPE_HARDWARE)
4424 WARN("Ignoring render target type %#x.\n", desc->type);
4425 if (desc->usage != D2D1_RENDER_TARGET_USAGE_NONE)
4426 FIXME("Ignoring render target usage %#x.\n", desc->usage);
4427 if (desc->minLevel != D2D1_FEATURE_LEVEL_DEFAULT)
4428 WARN("Ignoring feature level %#x.\n", desc->minLevel);
4430 bitmap_desc.dpiX = desc->dpiX;
4431 bitmap_desc.dpiY = desc->dpiY;
4433 if (bitmap_desc.dpiX == 0.0f && bitmap_desc.dpiY == 0.0f)
4435 bitmap_desc.dpiX = 96.0f;
4436 bitmap_desc.dpiY = 96.0f;
4438 else if (bitmap_desc.dpiX <= 0.0f || bitmap_desc.dpiY <= 0.0f)
4439 return E_INVALIDARG;
4441 if (!(object = calloc(1, sizeof(*object))))
4442 return E_OUTOFMEMORY;
4444 if (FAILED(hr = d2d_device_context_init(object, device, outer_unknown, ops)))
4446 WARN("Failed to initialise render target, hr %#lx.\n", hr);
4447 free(object);
4448 return hr;
4451 ID2D1DeviceContext1_SetDpi(&object->ID2D1DeviceContext1_iface, bitmap_desc.dpiX, bitmap_desc.dpiY);
4453 if (surface)
4455 bitmap_desc.pixelFormat = desc->pixelFormat;
4456 bitmap_desc.bitmapOptions = D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW;
4457 bitmap_desc.colorContext = NULL;
4459 if (FAILED(hr = ID2D1DeviceContext1_CreateBitmapFromDxgiSurface(&object->ID2D1DeviceContext1_iface,
4460 surface, &bitmap_desc, &bitmap)))
4462 WARN("Failed to create target bitmap, hr %#lx.\n", hr);
4463 IUnknown_Release(&object->IUnknown_iface);
4464 free(object);
4465 return hr;
4468 ID2D1DeviceContext1_SetTarget(&object->ID2D1DeviceContext1_iface, (ID2D1Image *)bitmap);
4469 ID2D1Bitmap1_Release(bitmap);
4471 else
4472 object->desc.pixelFormat = desc->pixelFormat;
4474 TRACE("Created render target %p.\n", object);
4475 *render_target = outer_unknown ? &object->IUnknown_iface : (IUnknown *)&object->ID2D1DeviceContext1_iface;
4477 return S_OK;
4480 static HRESULT WINAPI d2d_device_QueryInterface(ID2D1Device1 *iface, REFIID iid, void **out)
4482 TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
4484 if (IsEqualGUID(iid, &IID_ID2D1Device1)
4485 || IsEqualGUID(iid, &IID_ID2D1Device)
4486 || IsEqualGUID(iid, &IID_ID2D1Resource)
4487 || IsEqualGUID(iid, &IID_IUnknown))
4489 ID2D1Device1_AddRef(iface);
4490 *out = iface;
4491 return S_OK;
4494 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
4496 *out = NULL;
4497 return E_NOINTERFACE;
4500 static ULONG WINAPI d2d_device_AddRef(ID2D1Device1 *iface)
4502 struct d2d_device *device = impl_from_ID2D1Device(iface);
4503 ULONG refcount = InterlockedIncrement(&device->refcount);
4505 TRACE("%p increasing refcount to %lu.\n", iface, refcount);
4507 return refcount;
4510 static ULONG WINAPI d2d_device_Release(ID2D1Device1 *iface)
4512 struct d2d_device *device = impl_from_ID2D1Device(iface);
4513 ULONG refcount = InterlockedDecrement(&device->refcount);
4515 TRACE("%p decreasing refcount to %lu.\n", iface, refcount);
4517 if (!refcount)
4519 IDXGIDevice_Release(device->dxgi_device);
4520 ID2D1Factory1_Release(device->factory);
4521 free(device);
4524 return refcount;
4527 static void WINAPI d2d_device_GetFactory(ID2D1Device1 *iface, ID2D1Factory **factory)
4529 struct d2d_device *device = impl_from_ID2D1Device(iface);
4531 TRACE("iface %p, factory %p.\n", iface, factory);
4533 *factory = (ID2D1Factory *)device->factory;
4534 ID2D1Factory1_AddRef(device->factory);
4537 static HRESULT d2d_device_create_device_context(ID2D1Device1 *iface, D2D1_DEVICE_CONTEXT_OPTIONS options,
4538 ID2D1DeviceContext1 **context) {
4539 struct d2d_device_context *object;
4540 HRESULT hr;
4542 if (options)
4543 FIXME("Options are ignored %#x.\n", options);
4545 if (!(object = calloc(1, sizeof(*object))))
4546 return E_OUTOFMEMORY;
4548 if (FAILED(hr = d2d_device_context_init(object, (ID2D1Device *)iface, NULL, NULL)))
4550 WARN("Failed to initialise device context, hr %#lx.\n", hr);
4551 free(object);
4552 return hr;
4555 TRACE("Created device context %p.\n", object);
4556 *context = &object->ID2D1DeviceContext1_iface;
4558 return S_OK;
4561 static HRESULT WINAPI d2d_device_CreateDeviceContext(ID2D1Device1 *iface, D2D1_DEVICE_CONTEXT_OPTIONS options,
4562 ID2D1DeviceContext **context)
4564 TRACE("iface %p, options %#x, context %p.\n", iface, options, context);
4566 return d2d_device_create_device_context(iface, options, (ID2D1DeviceContext1 **)context);
4569 static HRESULT WINAPI d2d_device_CreatePrintControl(ID2D1Device1 *iface, IWICImagingFactory *wic_factory,
4570 IPrintDocumentPackageTarget *document_target, const D2D1_PRINT_CONTROL_PROPERTIES *desc,
4571 ID2D1PrintControl **print_control)
4573 FIXME("iface %p, wic_factory %p, document_target %p, desc %p, print_control %p stub!\n", iface, wic_factory,
4574 document_target, desc, print_control);
4576 return E_NOTIMPL;
4579 static void WINAPI d2d_device_SetMaximumTextureMemory(ID2D1Device1 *iface, UINT64 max_texture_memory)
4581 FIXME("iface %p, max_texture_memory %s stub!\n", iface, wine_dbgstr_longlong(max_texture_memory));
4584 static UINT64 WINAPI d2d_device_GetMaximumTextureMemory(ID2D1Device1 *iface)
4586 FIXME("iface %p stub!\n", iface);
4588 return 0;
4591 static HRESULT WINAPI d2d_device_ClearResources(ID2D1Device1 *iface, UINT msec_since_use)
4593 FIXME("iface %p, msec_since_use %u stub!\n", iface, msec_since_use);
4595 return E_NOTIMPL;
4598 static D2D1_RENDERING_PRIORITY WINAPI d2d_device_GetRenderingPriority(ID2D1Device1 *iface)
4600 FIXME("iface %p stub!\n", iface);
4602 return D2D1_RENDERING_PRIORITY_NORMAL;
4605 static void WINAPI d2d_device_SetRenderingPriority(ID2D1Device1 *iface, D2D1_RENDERING_PRIORITY priority)
4607 FIXME("iface %p, priority %#x stub!\n", iface, priority);
4610 static HRESULT WINAPI d2d_device_CreateDeviceContext1(ID2D1Device1 *iface, D2D1_DEVICE_CONTEXT_OPTIONS options,
4611 ID2D1DeviceContext1 **context)
4613 TRACE("iface %p, options %#x, context %p.\n", iface, options, context);
4615 return d2d_device_create_device_context(iface, options, context);
4618 static const struct ID2D1Device1Vtbl d2d_device_vtbl =
4620 d2d_device_QueryInterface,
4621 d2d_device_AddRef,
4622 d2d_device_Release,
4623 d2d_device_GetFactory,
4624 d2d_device_CreateDeviceContext,
4625 d2d_device_CreatePrintControl,
4626 d2d_device_SetMaximumTextureMemory,
4627 d2d_device_GetMaximumTextureMemory,
4628 d2d_device_ClearResources,
4629 d2d_device_GetRenderingPriority,
4630 d2d_device_SetRenderingPriority,
4631 d2d_device_CreateDeviceContext1,
4634 static struct d2d_device *unsafe_impl_from_ID2D1Device(ID2D1Device1 *iface)
4636 if (!iface)
4637 return NULL;
4638 assert(iface->lpVtbl == &d2d_device_vtbl);
4639 return CONTAINING_RECORD(iface, struct d2d_device, ID2D1Device1_iface);
4642 void d2d_device_init(struct d2d_device *device, ID2D1Factory1 *iface, IDXGIDevice *dxgi_device)
4644 device->ID2D1Device1_iface.lpVtbl = &d2d_device_vtbl;
4645 device->refcount = 1;
4646 device->factory = iface;
4647 ID2D1Factory1_AddRef(device->factory);
4648 device->dxgi_device = dxgi_device;
4649 IDXGIDevice_AddRef(device->dxgi_device);