d2d1: Scale stroke width for D2D1_STROKE_TRANSFORM_TYPE_FIXED in DrawGeometry::ID2D1D...
[wine.git] / dlls / d2d1 / device.c
bloba8993e79d4dcf6602cba557664bb064be85ebfdf
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 ID2D1Brush *d2d_draw_get_text_brush(struct d2d_draw_text_layout_ctx *context, IUnknown *effect)
45 ID2D1Brush *brush = NULL;
47 if (effect && SUCCEEDED(IUnknown_QueryInterface(effect, &IID_ID2D1Brush, (void**)&brush)))
48 return brush;
50 ID2D1Brush_AddRef(context->brush);
51 return context->brush;
54 static void d2d_rect_intersect(D2D1_RECT_F *dst, const D2D1_RECT_F *src)
56 if (src->left > dst->left)
57 dst->left = src->left;
58 if (src->top > dst->top)
59 dst->top = src->top;
60 if (src->right < dst->right)
61 dst->right = src->right;
62 if (src->bottom < dst->bottom)
63 dst->bottom = src->bottom;
66 static void d2d_rect_set(D2D1_RECT_F *dst, float left, float top, float right, float bottom)
68 dst->left = left;
69 dst->top = top;
70 dst->right = right;
71 dst->bottom = bottom;
74 static void d2d_size_set(D2D1_SIZE_U *dst, float width, float height)
76 dst->width = width;
77 dst->height = height;
80 static BOOL d2d_clip_stack_init(struct d2d_clip_stack *stack)
82 if (!(stack->stack = malloc(INITIAL_CLIP_STACK_SIZE * sizeof(*stack->stack))))
83 return FALSE;
85 stack->size = INITIAL_CLIP_STACK_SIZE;
86 stack->count = 0;
88 return TRUE;
91 static void d2d_clip_stack_cleanup(struct d2d_clip_stack *stack)
93 free(stack->stack);
96 static BOOL d2d_clip_stack_push(struct d2d_clip_stack *stack, const D2D1_RECT_F *rect)
98 D2D1_RECT_F r;
100 if (!d2d_array_reserve((void **)&stack->stack, &stack->size, stack->count + 1, sizeof(*stack->stack)))
101 return FALSE;
103 r = *rect;
104 if (stack->count)
105 d2d_rect_intersect(&r, &stack->stack[stack->count - 1]);
106 stack->stack[stack->count++] = r;
108 return TRUE;
111 static void d2d_clip_stack_pop(struct d2d_clip_stack *stack)
113 if (!stack->count)
114 return;
115 --stack->count;
118 static void d2d_device_context_draw(struct d2d_device_context *render_target, enum d2d_shape_type shape_type,
119 ID3D11Buffer *ib, unsigned int index_count, ID3D11Buffer *vb, unsigned int vb_stride,
120 struct d2d_brush *brush, struct d2d_brush *opacity_brush)
122 struct d2d_shape_resources *shape_resources = &render_target->shape_resources[shape_type];
123 ID3DDeviceContextState *prev_state;
124 ID3D11Device1 *device = render_target->d3d_device;
125 ID3D11DeviceContext1 *context;
126 ID3D11Buffer *vs_cb = render_target->vs_cb, *ps_cb = render_target->ps_cb;
127 D3D11_RECT scissor_rect;
128 unsigned int offset;
129 D3D11_VIEWPORT vp;
131 vp.TopLeftX = 0;
132 vp.TopLeftY = 0;
133 vp.Width = render_target->pixel_size.width;
134 vp.Height = render_target->pixel_size.height;
135 vp.MinDepth = 0.0f;
136 vp.MaxDepth = 1.0f;
138 ID3D11Device1_GetImmediateContext1(device, &context);
139 ID3D11DeviceContext1_SwapDeviceContextState(context, render_target->d3d_state, &prev_state);
141 ID3D11DeviceContext1_IASetInputLayout(context, shape_resources->il);
142 ID3D11DeviceContext1_IASetPrimitiveTopology(context, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
143 ID3D11DeviceContext1_IASetIndexBuffer(context, ib, DXGI_FORMAT_R16_UINT, 0);
144 offset = 0;
145 ID3D11DeviceContext1_IASetVertexBuffers(context, 0, 1, &vb, &vb_stride, &offset);
146 ID3D11DeviceContext1_VSSetConstantBuffers(context, 0, 1, &vs_cb);
147 ID3D11DeviceContext1_VSSetShader(context, shape_resources->vs, NULL, 0);
148 ID3D11DeviceContext1_PSSetConstantBuffers(context, 0, 1, &ps_cb);
149 ID3D11DeviceContext1_PSSetShader(context, render_target->ps, NULL, 0);
150 ID3D11DeviceContext1_RSSetViewports(context, 1, &vp);
151 if (render_target->clip_stack.count)
153 const D2D1_RECT_F *clip_rect;
155 clip_rect = &render_target->clip_stack.stack[render_target->clip_stack.count - 1];
156 scissor_rect.left = ceilf(clip_rect->left - 0.5f);
157 scissor_rect.top = ceilf(clip_rect->top - 0.5f);
158 scissor_rect.right = ceilf(clip_rect->right - 0.5f);
159 scissor_rect.bottom = ceilf(clip_rect->bottom - 0.5f);
161 else
163 scissor_rect.left = 0.0f;
164 scissor_rect.top = 0.0f;
165 scissor_rect.right = render_target->pixel_size.width;
166 scissor_rect.bottom = render_target->pixel_size.height;
168 ID3D11DeviceContext1_RSSetScissorRects(context, 1, &scissor_rect);
169 ID3D11DeviceContext1_RSSetState(context, render_target->rs);
170 ID3D11DeviceContext1_OMSetRenderTargets(context, 1, &render_target->target.bitmap->rtv, NULL);
171 if (brush)
173 ID3D11DeviceContext1_OMSetBlendState(context, render_target->bs, NULL, D3D11_DEFAULT_SAMPLE_MASK);
174 d2d_brush_bind_resources(brush, render_target, 0);
176 else
178 ID3D11DeviceContext1_OMSetBlendState(context, NULL, NULL, D3D11_DEFAULT_SAMPLE_MASK);
180 if (opacity_brush)
181 d2d_brush_bind_resources(opacity_brush, render_target, 1);
183 if (ib)
184 ID3D11DeviceContext1_DrawIndexed(context, index_count, 0, 0);
185 else
186 ID3D11DeviceContext1_Draw(context, index_count, 0);
188 ID3D11DeviceContext1_SwapDeviceContextState(context, prev_state, NULL);
189 ID3D11DeviceContext1_Release(context);
190 ID3DDeviceContextState_Release(prev_state);
193 static void d2d_device_context_set_error(struct d2d_device_context *context, HRESULT code)
195 context->error.code = code;
196 context->error.tag1 = context->drawing_state.tag1;
197 context->error.tag2 = context->drawing_state.tag2;
200 static inline struct d2d_device_context *impl_from_IUnknown(IUnknown *iface)
202 return CONTAINING_RECORD(iface, struct d2d_device_context, IUnknown_iface);
205 static inline struct d2d_device_context *impl_from_ID2D1DeviceContext(ID2D1DeviceContext1 *iface)
207 return CONTAINING_RECORD(iface, struct d2d_device_context, ID2D1DeviceContext1_iface);
210 static HRESULT STDMETHODCALLTYPE d2d_device_context_inner_QueryInterface(IUnknown *iface, REFIID iid, void **out)
212 struct d2d_device_context *context = impl_from_IUnknown(iface);
214 TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
216 if (IsEqualGUID(iid, &IID_ID2D1DeviceContext1)
217 || IsEqualGUID(iid, &IID_ID2D1DeviceContext)
218 || IsEqualGUID(iid, &IID_ID2D1RenderTarget)
219 || IsEqualGUID(iid, &IID_ID2D1Resource)
220 || IsEqualGUID(iid, &IID_IUnknown))
222 ID2D1DeviceContext1_AddRef(&context->ID2D1DeviceContext1_iface);
223 *out = &context->ID2D1DeviceContext1_iface;
224 return S_OK;
226 else if (IsEqualGUID(iid, &IID_ID2D1GdiInteropRenderTarget))
228 ID2D1GdiInteropRenderTarget_AddRef(&context->ID2D1GdiInteropRenderTarget_iface);
229 *out = &context->ID2D1GdiInteropRenderTarget_iface;
230 return S_OK;
233 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
235 *out = NULL;
236 return E_NOINTERFACE;
239 static ULONG STDMETHODCALLTYPE d2d_device_context_inner_AddRef(IUnknown *iface)
241 struct d2d_device_context *context = impl_from_IUnknown(iface);
242 ULONG refcount = InterlockedIncrement(&context->refcount);
244 TRACE("%p increasing refcount to %lu.\n", iface, refcount);
246 return refcount;
249 static ULONG STDMETHODCALLTYPE d2d_device_context_inner_Release(IUnknown *iface)
251 struct d2d_device_context *context = impl_from_IUnknown(iface);
252 ULONG refcount = InterlockedDecrement(&context->refcount);
254 TRACE("%p decreasing refcount to %lu.\n", iface, refcount);
256 if (!refcount)
258 unsigned int i, j, k;
260 d2d_clip_stack_cleanup(&context->clip_stack);
261 IDWriteRenderingParams_Release(context->default_text_rendering_params);
262 if (context->text_rendering_params)
263 IDWriteRenderingParams_Release(context->text_rendering_params);
264 if (context->bs)
265 ID3D11BlendState_Release(context->bs);
266 ID3D11RasterizerState_Release(context->rs);
267 ID3D11Buffer_Release(context->vb);
268 ID3D11Buffer_Release(context->ib);
269 ID3D11Buffer_Release(context->ps_cb);
270 ID3D11PixelShader_Release(context->ps);
271 ID3D11Buffer_Release(context->vs_cb);
272 for (i = 0; i < D2D_SHAPE_TYPE_COUNT; ++i)
274 ID3D11VertexShader_Release(context->shape_resources[i].vs);
275 ID3D11InputLayout_Release(context->shape_resources[i].il);
277 for (i = 0; i < D2D_SAMPLER_INTERPOLATION_MODE_COUNT; ++i)
279 for (j = 0; j < D2D_SAMPLER_EXTEND_MODE_COUNT; ++j)
281 for (k = 0; k < D2D_SAMPLER_EXTEND_MODE_COUNT; ++k)
283 if (context->sampler_states[i][j][k])
284 ID3D11SamplerState_Release(context->sampler_states[i][j][k]);
288 if (context->d3d_state)
289 ID3DDeviceContextState_Release(context->d3d_state);
290 if (context->target.object)
291 IUnknown_Release(context->target.object);
292 ID3D11Device1_Release(context->d3d_device);
293 ID2D1Factory_Release(context->factory);
294 ID2D1Device1_Release(&context->device->ID2D1Device1_iface);
295 free(context);
298 return refcount;
301 static const struct IUnknownVtbl d2d_device_context_inner_unknown_vtbl =
303 d2d_device_context_inner_QueryInterface,
304 d2d_device_context_inner_AddRef,
305 d2d_device_context_inner_Release,
308 static HRESULT STDMETHODCALLTYPE d2d_device_context_QueryInterface(ID2D1DeviceContext1 *iface, REFIID iid, void **out)
310 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
312 TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
314 return IUnknown_QueryInterface(context->outer_unknown, iid, out);
317 static ULONG STDMETHODCALLTYPE d2d_device_context_AddRef(ID2D1DeviceContext1 *iface)
319 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
321 TRACE("iface %p.\n", iface);
323 return IUnknown_AddRef(context->outer_unknown);
326 static ULONG STDMETHODCALLTYPE d2d_device_context_Release(ID2D1DeviceContext1 *iface)
328 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
330 TRACE("iface %p.\n", iface);
332 return IUnknown_Release(context->outer_unknown);
335 static void STDMETHODCALLTYPE d2d_device_context_GetFactory(ID2D1DeviceContext1 *iface, ID2D1Factory **factory)
337 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
339 TRACE("iface %p, factory %p.\n", iface, factory);
341 *factory = render_target->factory;
342 ID2D1Factory_AddRef(*factory);
345 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateBitmap(ID2D1DeviceContext1 *iface,
346 D2D1_SIZE_U size, const void *src_data, UINT32 pitch, const D2D1_BITMAP_PROPERTIES *desc, ID2D1Bitmap **bitmap)
348 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
349 D2D1_BITMAP_PROPERTIES1 bitmap_desc;
350 struct d2d_bitmap *object;
351 HRESULT hr;
353 TRACE("iface %p, size {%u, %u}, src_data %p, pitch %u, desc %p, bitmap %p.\n",
354 iface, size.width, size.height, src_data, pitch, desc, bitmap);
356 if (desc)
358 memcpy(&bitmap_desc, desc, sizeof(*desc));
359 bitmap_desc.bitmapOptions = 0;
360 bitmap_desc.colorContext = NULL;
363 if (SUCCEEDED(hr = d2d_bitmap_create(context, size, src_data, pitch, desc ? &bitmap_desc : NULL, &object)))
364 *bitmap = (ID2D1Bitmap *)&object->ID2D1Bitmap1_iface;
366 return hr;
369 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateBitmapFromWicBitmap(ID2D1DeviceContext1 *iface,
370 IWICBitmapSource *bitmap_source, const D2D1_BITMAP_PROPERTIES *desc, ID2D1Bitmap **bitmap)
372 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
373 D2D1_BITMAP_PROPERTIES1 bitmap_desc;
374 struct d2d_bitmap *object;
375 HRESULT hr;
377 TRACE("iface %p, bitmap_source %p, desc %p, bitmap %p.\n",
378 iface, bitmap_source, desc, bitmap);
380 if (desc)
382 memcpy(&bitmap_desc, desc, sizeof(*desc));
383 bitmap_desc.bitmapOptions = 0;
384 bitmap_desc.colorContext = NULL;
387 if (SUCCEEDED(hr = d2d_bitmap_create_from_wic_bitmap(context, bitmap_source, desc ? &bitmap_desc : NULL, &object)))
388 *bitmap = (ID2D1Bitmap *)&object->ID2D1Bitmap1_iface;
390 return hr;
393 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateSharedBitmap(ID2D1DeviceContext1 *iface,
394 REFIID iid, void *data, const D2D1_BITMAP_PROPERTIES *desc, ID2D1Bitmap **bitmap)
396 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
397 D2D1_BITMAP_PROPERTIES1 bitmap_desc;
398 struct d2d_bitmap *object;
399 HRESULT hr;
401 TRACE("iface %p, iid %s, data %p, desc %p, bitmap %p.\n",
402 iface, debugstr_guid(iid), data, desc, bitmap);
404 if (desc)
406 memcpy(&bitmap_desc, desc, sizeof(*desc));
407 if (IsEqualIID(iid, &IID_IDXGISurface) || IsEqualIID(iid, &IID_IDXGISurface1))
408 bitmap_desc.bitmapOptions = d2d_get_bitmap_options_for_surface(data);
409 else
410 bitmap_desc.bitmapOptions = D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW;
411 bitmap_desc.colorContext = NULL;
414 if (SUCCEEDED(hr = d2d_bitmap_create_shared(context, iid, data, desc ? &bitmap_desc : NULL, &object)))
415 *bitmap = (ID2D1Bitmap *)&object->ID2D1Bitmap1_iface;
417 return hr;
420 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateBitmapBrush(ID2D1DeviceContext1 *iface,
421 ID2D1Bitmap *bitmap, const D2D1_BITMAP_BRUSH_PROPERTIES *bitmap_brush_desc,
422 const D2D1_BRUSH_PROPERTIES *brush_desc, ID2D1BitmapBrush **brush)
424 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
425 struct d2d_brush *object;
426 HRESULT hr;
428 TRACE("iface %p, bitmap %p, bitmap_brush_desc %p, brush_desc %p, brush %p.\n",
429 iface, bitmap, bitmap_brush_desc, brush_desc, brush);
431 if (SUCCEEDED(hr = d2d_bitmap_brush_create(context->factory, bitmap, (const D2D1_BITMAP_BRUSH_PROPERTIES1 *)bitmap_brush_desc,
432 brush_desc, &object)))
433 *brush = (ID2D1BitmapBrush *)&object->ID2D1Brush_iface;
435 return hr;
438 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateSolidColorBrush(ID2D1DeviceContext1 *iface,
439 const D2D1_COLOR_F *color, const D2D1_BRUSH_PROPERTIES *desc, ID2D1SolidColorBrush **brush)
441 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
442 struct d2d_brush *object;
443 HRESULT hr;
445 TRACE("iface %p, color %p, desc %p, brush %p.\n", iface, color, desc, brush);
447 if (SUCCEEDED(hr = d2d_solid_color_brush_create(render_target->factory, color, desc, &object)))
448 *brush = (ID2D1SolidColorBrush *)&object->ID2D1Brush_iface;
450 return hr;
453 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateGradientStopCollection(ID2D1DeviceContext1 *iface,
454 const D2D1_GRADIENT_STOP *stops, UINT32 stop_count, D2D1_GAMMA gamma, D2D1_EXTEND_MODE extend_mode,
455 ID2D1GradientStopCollection **gradient)
457 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
458 struct d2d_gradient *object;
459 HRESULT hr;
461 TRACE("iface %p, stops %p, stop_count %u, gamma %#x, extend_mode %#x, gradient %p.\n",
462 iface, stops, stop_count, gamma, extend_mode, gradient);
464 if (SUCCEEDED(hr = d2d_gradient_create(render_target->factory, render_target->d3d_device,
465 stops, stop_count, gamma, extend_mode, &object)))
466 *gradient = &object->ID2D1GradientStopCollection_iface;
468 return hr;
471 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateLinearGradientBrush(ID2D1DeviceContext1 *iface,
472 const D2D1_LINEAR_GRADIENT_BRUSH_PROPERTIES *gradient_brush_desc, const D2D1_BRUSH_PROPERTIES *brush_desc,
473 ID2D1GradientStopCollection *gradient, ID2D1LinearGradientBrush **brush)
475 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
476 struct d2d_brush *object;
477 HRESULT hr;
479 TRACE("iface %p, gradient_brush_desc %p, brush_desc %p, gradient %p, brush %p.\n",
480 iface, gradient_brush_desc, brush_desc, gradient, brush);
482 if (SUCCEEDED(hr = d2d_linear_gradient_brush_create(render_target->factory, gradient_brush_desc, brush_desc,
483 gradient, &object)))
484 *brush = (ID2D1LinearGradientBrush *)&object->ID2D1Brush_iface;
486 return hr;
489 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateRadialGradientBrush(ID2D1DeviceContext1 *iface,
490 const D2D1_RADIAL_GRADIENT_BRUSH_PROPERTIES *gradient_brush_desc, const D2D1_BRUSH_PROPERTIES *brush_desc,
491 ID2D1GradientStopCollection *gradient, ID2D1RadialGradientBrush **brush)
493 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
494 struct d2d_brush *object;
495 HRESULT hr;
497 TRACE("iface %p, gradient_brush_desc %p, brush_desc %p, gradient %p, brush %p.\n",
498 iface, gradient_brush_desc, brush_desc, gradient, brush);
500 if (SUCCEEDED(hr = d2d_radial_gradient_brush_create(render_target->factory,
501 gradient_brush_desc, brush_desc, gradient, &object)))
502 *brush = (ID2D1RadialGradientBrush *)&object->ID2D1Brush_iface;
504 return hr;
507 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateCompatibleRenderTarget(ID2D1DeviceContext1 *iface,
508 const D2D1_SIZE_F *size, const D2D1_SIZE_U *pixel_size, const D2D1_PIXEL_FORMAT *format,
509 D2D1_COMPATIBLE_RENDER_TARGET_OPTIONS options, ID2D1BitmapRenderTarget **rt)
511 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
512 struct d2d_bitmap_render_target *object;
513 HRESULT hr;
515 TRACE("iface %p, size %p, pixel_size %p, format %p, options %#x, render_target %p.\n",
516 iface, size, pixel_size, format, options, rt);
518 if (!(object = calloc(1, sizeof(*object))))
519 return E_OUTOFMEMORY;
521 if (FAILED(hr = d2d_bitmap_render_target_init(object, render_target, size, pixel_size,
522 format, options)))
524 WARN("Failed to initialise render target, hr %#lx.\n", hr);
525 free(object);
526 return hr;
529 TRACE("Created render target %p.\n", object);
530 *rt = &object->ID2D1BitmapRenderTarget_iface;
532 return S_OK;
535 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateLayer(ID2D1DeviceContext1 *iface,
536 const D2D1_SIZE_F *size, ID2D1Layer **layer)
538 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
539 struct d2d_layer *object;
540 HRESULT hr;
542 TRACE("iface %p, size %p, layer %p.\n", iface, size, layer);
544 if (SUCCEEDED(hr = d2d_layer_create(render_target->factory, size, &object)))
545 *layer = &object->ID2D1Layer_iface;
547 return hr;
550 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateMesh(ID2D1DeviceContext1 *iface, ID2D1Mesh **mesh)
552 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
553 struct d2d_mesh *object;
554 HRESULT hr;
556 TRACE("iface %p, mesh %p.\n", iface, mesh);
558 if (SUCCEEDED(hr = d2d_mesh_create(render_target->factory, &object)))
559 *mesh = &object->ID2D1Mesh_iface;
561 return hr;
564 static void STDMETHODCALLTYPE d2d_device_context_DrawLine(ID2D1DeviceContext1 *iface,
565 D2D1_POINT_2F p0, D2D1_POINT_2F p1, ID2D1Brush *brush, float stroke_width, ID2D1StrokeStyle *stroke_style)
567 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
568 ID2D1PathGeometry *geometry;
569 ID2D1GeometrySink *sink;
570 HRESULT hr;
572 TRACE("iface %p, p0 %s, p1 %s, brush %p, stroke_width %.8e, stroke_style %p.\n",
573 iface, debug_d2d_point_2f(&p0), debug_d2d_point_2f(&p1), brush, stroke_width, stroke_style);
575 if (context->target.type == D2D_TARGET_COMMAND_LIST)
577 d2d_command_list_draw_line(context->target.command_list, context, p0, p1, brush, stroke_width, stroke_style);
578 return;
581 if (FAILED(hr = ID2D1Factory_CreatePathGeometry(context->factory, &geometry)))
583 WARN("Failed to create path geometry, hr %#lx.\n", hr);
584 return;
587 if (FAILED(hr = ID2D1PathGeometry_Open(geometry, &sink)))
589 WARN("Failed to open geometry sink, hr %#lx.\n", hr);
590 ID2D1PathGeometry_Release(geometry);
591 return;
594 ID2D1GeometrySink_BeginFigure(sink, p0, D2D1_FIGURE_BEGIN_HOLLOW);
595 ID2D1GeometrySink_AddLine(sink, p1);
596 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_OPEN);
597 if (FAILED(hr = ID2D1GeometrySink_Close(sink)))
598 WARN("Failed to close geometry sink, hr %#lx.\n", hr);
599 ID2D1GeometrySink_Release(sink);
601 ID2D1DeviceContext1_DrawGeometry(iface, (ID2D1Geometry *)geometry, brush, stroke_width, stroke_style);
602 ID2D1PathGeometry_Release(geometry);
605 static void STDMETHODCALLTYPE d2d_device_context_DrawRectangle(ID2D1DeviceContext1 *iface,
606 const D2D1_RECT_F *rect, ID2D1Brush *brush, float stroke_width, ID2D1StrokeStyle *stroke_style)
608 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
609 ID2D1RectangleGeometry *geometry;
610 HRESULT hr;
612 TRACE("iface %p, rect %s, brush %p, stroke_width %.8e, stroke_style %p.\n",
613 iface, debug_d2d_rect_f(rect), brush, stroke_width, stroke_style);
615 if (context->target.type == D2D_TARGET_COMMAND_LIST)
617 d2d_command_list_draw_rectangle(context->target.command_list, context, rect, brush, stroke_width, stroke_style);
618 return;
621 if (FAILED(hr = ID2D1Factory_CreateRectangleGeometry(context->factory, rect, &geometry)))
623 ERR("Failed to create geometry, hr %#lx.\n", hr);
624 return;
627 ID2D1DeviceContext1_DrawGeometry(iface, (ID2D1Geometry *)geometry, brush, stroke_width, stroke_style);
628 ID2D1RectangleGeometry_Release(geometry);
631 static void STDMETHODCALLTYPE d2d_device_context_FillRectangle(ID2D1DeviceContext1 *iface,
632 const D2D1_RECT_F *rect, ID2D1Brush *brush)
634 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
635 ID2D1RectangleGeometry *geometry;
636 HRESULT hr;
638 TRACE("iface %p, rect %s, brush %p.\n", iface, debug_d2d_rect_f(rect), brush);
640 if (context->target.type == D2D_TARGET_COMMAND_LIST)
642 d2d_command_list_fill_rectangle(context->target.command_list, context, rect, brush);
643 return;
646 if (FAILED(hr = ID2D1Factory_CreateRectangleGeometry(context->factory, rect, &geometry)))
648 ERR("Failed to create geometry, hr %#lx.\n", hr);
649 return;
652 ID2D1DeviceContext1_FillGeometry(iface, (ID2D1Geometry *)geometry, brush, NULL);
653 ID2D1RectangleGeometry_Release(geometry);
656 static void STDMETHODCALLTYPE d2d_device_context_DrawRoundedRectangle(ID2D1DeviceContext1 *iface,
657 const D2D1_ROUNDED_RECT *rect, ID2D1Brush *brush, float stroke_width, ID2D1StrokeStyle *stroke_style)
659 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
660 ID2D1RoundedRectangleGeometry *geometry;
661 HRESULT hr;
663 TRACE("iface %p, rect %p, brush %p, stroke_width %.8e, stroke_style %p.\n",
664 iface, rect, brush, stroke_width, stroke_style);
666 if (FAILED(hr = ID2D1Factory_CreateRoundedRectangleGeometry(render_target->factory, rect, &geometry)))
668 ERR("Failed to create geometry, hr %#lx.\n", hr);
669 return;
672 ID2D1DeviceContext1_DrawGeometry(iface, (ID2D1Geometry *)geometry, brush, stroke_width, stroke_style);
673 ID2D1RoundedRectangleGeometry_Release(geometry);
676 static void STDMETHODCALLTYPE d2d_device_context_FillRoundedRectangle(ID2D1DeviceContext1 *iface,
677 const D2D1_ROUNDED_RECT *rect, ID2D1Brush *brush)
679 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
680 ID2D1RoundedRectangleGeometry *geometry;
681 HRESULT hr;
683 TRACE("iface %p, rect %p, brush %p.\n", iface, rect, brush);
685 if (FAILED(hr = ID2D1Factory_CreateRoundedRectangleGeometry(render_target->factory, rect, &geometry)))
687 ERR("Failed to create geometry, hr %#lx.\n", hr);
688 return;
691 ID2D1DeviceContext1_FillGeometry(iface, (ID2D1Geometry *)geometry, brush, NULL);
692 ID2D1RoundedRectangleGeometry_Release(geometry);
695 static void STDMETHODCALLTYPE d2d_device_context_DrawEllipse(ID2D1DeviceContext1 *iface,
696 const D2D1_ELLIPSE *ellipse, ID2D1Brush *brush, float stroke_width, ID2D1StrokeStyle *stroke_style)
698 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
699 ID2D1EllipseGeometry *geometry;
700 HRESULT hr;
702 TRACE("iface %p, ellipse %p, brush %p, stroke_width %.8e, stroke_style %p.\n",
703 iface, ellipse, brush, stroke_width, stroke_style);
705 if (FAILED(hr = ID2D1Factory_CreateEllipseGeometry(render_target->factory, ellipse, &geometry)))
707 ERR("Failed to create geometry, hr %#lx.\n", hr);
708 return;
711 ID2D1DeviceContext1_DrawGeometry(iface, (ID2D1Geometry *)geometry, brush, stroke_width, stroke_style);
712 ID2D1EllipseGeometry_Release(geometry);
715 static void STDMETHODCALLTYPE d2d_device_context_FillEllipse(ID2D1DeviceContext1 *iface,
716 const D2D1_ELLIPSE *ellipse, ID2D1Brush *brush)
718 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
719 ID2D1EllipseGeometry *geometry;
720 HRESULT hr;
722 TRACE("iface %p, ellipse %p, brush %p.\n", iface, ellipse, brush);
724 if (FAILED(hr = ID2D1Factory_CreateEllipseGeometry(render_target->factory, ellipse, &geometry)))
726 ERR("Failed to create geometry, hr %#lx.\n", hr);
727 return;
730 ID2D1DeviceContext1_FillGeometry(iface, (ID2D1Geometry *)geometry, brush, NULL);
731 ID2D1EllipseGeometry_Release(geometry);
734 static HRESULT d2d_device_context_update_ps_cb(struct d2d_device_context *context,
735 struct d2d_brush *brush, struct d2d_brush *opacity_brush, BOOL outline, BOOL is_arc)
737 D3D11_MAPPED_SUBRESOURCE map_desc;
738 ID3D11DeviceContext *d3d_context;
739 struct d2d_ps_cb *cb_data;
740 HRESULT hr;
742 ID3D11Device1_GetImmediateContext(context->d3d_device, &d3d_context);
744 if (FAILED(hr = ID3D11DeviceContext_Map(d3d_context, (ID3D11Resource *)context->ps_cb,
745 0, D3D11_MAP_WRITE_DISCARD, 0, &map_desc)))
747 WARN("Failed to map constant buffer, hr %#lx.\n", hr);
748 ID3D11DeviceContext_Release(d3d_context);
749 return hr;
752 cb_data = map_desc.pData;
753 cb_data->outline = outline;
754 cb_data->is_arc = is_arc;
755 cb_data->pad[0] = 0;
756 cb_data->pad[1] = 0;
757 if (!d2d_brush_fill_cb(brush, &cb_data->colour_brush))
758 WARN("Failed to initialize colour brush buffer.\n");
759 if (!d2d_brush_fill_cb(opacity_brush, &cb_data->opacity_brush))
760 WARN("Failed to initialize opacity brush buffer.\n");
762 ID3D11DeviceContext_Unmap(d3d_context, (ID3D11Resource *)context->ps_cb, 0);
763 ID3D11DeviceContext_Release(d3d_context);
765 return hr;
768 static HRESULT d2d_device_context_update_vs_cb(struct d2d_device_context *context,
769 const D2D_MATRIX_3X2_F *geometry_transform, float stroke_width)
771 D3D11_MAPPED_SUBRESOURCE map_desc;
772 ID3D11DeviceContext *d3d_context;
773 const D2D1_MATRIX_3X2_F *w;
774 struct d2d_vs_cb *cb_data;
775 float tmp_x, tmp_y;
776 HRESULT hr;
778 ID3D11Device1_GetImmediateContext(context->d3d_device, &d3d_context);
780 if (FAILED(hr = ID3D11DeviceContext_Map(d3d_context, (ID3D11Resource *)context->vs_cb,
781 0, D3D11_MAP_WRITE_DISCARD, 0, &map_desc)))
783 WARN("Failed to map constant buffer, hr %#lx.\n", hr);
784 ID3D11DeviceContext_Release(d3d_context);
785 return hr;
788 cb_data = map_desc.pData;
789 cb_data->transform_geometry._11 = geometry_transform->_11;
790 cb_data->transform_geometry._21 = geometry_transform->_21;
791 cb_data->transform_geometry._31 = geometry_transform->_31;
792 cb_data->transform_geometry.pad0 = 0.0f;
793 cb_data->transform_geometry._12 = geometry_transform->_12;
794 cb_data->transform_geometry._22 = geometry_transform->_22;
795 cb_data->transform_geometry._32 = geometry_transform->_32;
796 cb_data->transform_geometry.stroke_width = stroke_width;
798 w = &context->drawing_state.transform;
800 tmp_x = context->desc.dpiX / 96.0f;
801 cb_data->transform_rtx.x = w->_11 * tmp_x;
802 cb_data->transform_rtx.y = w->_21 * tmp_x;
803 cb_data->transform_rtx.z = w->_31 * tmp_x;
804 cb_data->transform_rtx.w = 2.0f / context->pixel_size.width;
806 tmp_y = context->desc.dpiY / 96.0f;
807 cb_data->transform_rty.x = w->_12 * tmp_y;
808 cb_data->transform_rty.y = w->_22 * tmp_y;
809 cb_data->transform_rty.z = w->_32 * tmp_y;
810 cb_data->transform_rty.w = -2.0f / context->pixel_size.height;
812 ID3D11DeviceContext_Unmap(d3d_context, (ID3D11Resource *)context->vs_cb, 0);
813 ID3D11DeviceContext_Release(d3d_context);
815 return S_OK;
818 static void d2d_device_context_draw_geometry(struct d2d_device_context *render_target,
819 const struct d2d_geometry *geometry, struct d2d_brush *brush, float stroke_width)
821 D3D11_SUBRESOURCE_DATA buffer_data;
822 D3D11_BUFFER_DESC buffer_desc;
823 ID3D11Buffer *ib, *vb;
824 HRESULT hr;
826 if (FAILED(hr = d2d_device_context_update_vs_cb(render_target, &geometry->transform, stroke_width)))
828 WARN("Failed to update vs constant buffer, hr %#lx.\n", hr);
829 return;
832 if (FAILED(hr = d2d_device_context_update_ps_cb(render_target, brush, NULL, TRUE, FALSE)))
834 WARN("Failed to update ps constant buffer, hr %#lx.\n", hr);
835 return;
838 buffer_desc.Usage = D3D11_USAGE_DEFAULT;
839 buffer_desc.CPUAccessFlags = 0;
840 buffer_desc.MiscFlags = 0;
842 buffer_data.SysMemPitch = 0;
843 buffer_data.SysMemSlicePitch = 0;
845 if (geometry->outline.face_count)
847 buffer_desc.ByteWidth = geometry->outline.face_count * sizeof(*geometry->outline.faces);
848 buffer_desc.BindFlags = D3D11_BIND_INDEX_BUFFER;
849 buffer_data.pSysMem = geometry->outline.faces;
851 if (FAILED(hr = ID3D11Device1_CreateBuffer(render_target->d3d_device, &buffer_desc, &buffer_data, &ib)))
853 WARN("Failed to create index buffer, hr %#lx.\n", hr);
854 return;
857 buffer_desc.ByteWidth = geometry->outline.vertex_count * sizeof(*geometry->outline.vertices);
858 buffer_desc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
859 buffer_data.pSysMem = geometry->outline.vertices;
861 if (FAILED(hr = ID3D11Device1_CreateBuffer(render_target->d3d_device, &buffer_desc, &buffer_data, &vb)))
863 ERR("Failed to create vertex buffer, hr %#lx.\n", hr);
864 ID3D11Buffer_Release(ib);
865 return;
868 d2d_device_context_draw(render_target, D2D_SHAPE_TYPE_OUTLINE, ib, 3 * geometry->outline.face_count, vb,
869 sizeof(*geometry->outline.vertices), brush, NULL);
871 ID3D11Buffer_Release(vb);
872 ID3D11Buffer_Release(ib);
875 if (geometry->outline.bezier_face_count)
877 buffer_desc.ByteWidth = geometry->outline.bezier_face_count * sizeof(*geometry->outline.bezier_faces);
878 buffer_desc.BindFlags = D3D11_BIND_INDEX_BUFFER;
879 buffer_data.pSysMem = geometry->outline.bezier_faces;
881 if (FAILED(hr = ID3D11Device1_CreateBuffer(render_target->d3d_device, &buffer_desc, &buffer_data, &ib)))
883 WARN("Failed to create curves index buffer, hr %#lx.\n", hr);
884 return;
887 buffer_desc.ByteWidth = geometry->outline.bezier_count * sizeof(*geometry->outline.beziers);
888 buffer_desc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
889 buffer_data.pSysMem = geometry->outline.beziers;
891 if (FAILED(hr = ID3D11Device1_CreateBuffer(render_target->d3d_device, &buffer_desc, &buffer_data, &vb)))
893 ERR("Failed to create curves vertex buffer, hr %#lx.\n", hr);
894 ID3D11Buffer_Release(ib);
895 return;
898 d2d_device_context_draw(render_target, D2D_SHAPE_TYPE_BEZIER_OUTLINE, ib,
899 3 * geometry->outline.bezier_face_count, vb,
900 sizeof(*geometry->outline.beziers), brush, NULL);
902 ID3D11Buffer_Release(vb);
903 ID3D11Buffer_Release(ib);
906 if (geometry->outline.arc_face_count)
908 buffer_desc.ByteWidth = geometry->outline.arc_face_count * sizeof(*geometry->outline.arc_faces);
909 buffer_desc.BindFlags = D3D11_BIND_INDEX_BUFFER;
910 buffer_data.pSysMem = geometry->outline.arc_faces;
912 if (FAILED(hr = ID3D11Device1_CreateBuffer(render_target->d3d_device, &buffer_desc, &buffer_data, &ib)))
914 WARN("Failed to create arcs index buffer, hr %#lx.\n", hr);
915 return;
918 buffer_desc.ByteWidth = geometry->outline.arc_count * sizeof(*geometry->outline.arcs);
919 buffer_desc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
920 buffer_data.pSysMem = geometry->outline.arcs;
922 if (FAILED(hr = ID3D11Device1_CreateBuffer(render_target->d3d_device, &buffer_desc, &buffer_data, &vb)))
924 ERR("Failed to create arcs vertex buffer, hr %#lx.\n", hr);
925 ID3D11Buffer_Release(ib);
926 return;
929 if (SUCCEEDED(d2d_device_context_update_ps_cb(render_target, brush, NULL, TRUE, TRUE)))
930 d2d_device_context_draw(render_target, D2D_SHAPE_TYPE_ARC_OUTLINE, ib,
931 3 * geometry->outline.arc_face_count, vb,
932 sizeof(*geometry->outline.arcs), brush, NULL);
934 ID3D11Buffer_Release(vb);
935 ID3D11Buffer_Release(ib);
939 static void STDMETHODCALLTYPE d2d_device_context_DrawGeometry(ID2D1DeviceContext1 *iface,
940 ID2D1Geometry *geometry, ID2D1Brush *brush, float stroke_width, ID2D1StrokeStyle *stroke_style)
942 const struct d2d_geometry *geometry_impl = unsafe_impl_from_ID2D1Geometry(geometry);
943 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
944 struct d2d_brush *brush_impl = unsafe_impl_from_ID2D1Brush(brush);
945 struct d2d_stroke_style *stroke_style_impl = unsafe_impl_from_ID2D1StrokeStyle(stroke_style);
947 TRACE("iface %p, geometry %p, brush %p, stroke_width %.8e, stroke_style %p.\n",
948 iface, geometry, brush, stroke_width, stroke_style);
950 if (context->target.type == D2D_TARGET_COMMAND_LIST)
952 d2d_command_list_draw_geometry(context->target.command_list, context, geometry, brush,
953 stroke_width, stroke_style);
954 return;
957 if (stroke_style)
958 FIXME("Ignoring stroke style %p.\n", stroke_style);
960 if (stroke_style_impl)
962 if (stroke_style_impl->desc.transformType == D2D1_STROKE_TRANSFORM_TYPE_FIXED)
963 stroke_width /= context->drawing_state.transform.m11;
966 d2d_device_context_draw_geometry(context, geometry_impl, brush_impl, stroke_width);
969 static void d2d_device_context_fill_geometry(struct d2d_device_context *render_target,
970 const struct d2d_geometry *geometry, struct d2d_brush *brush, struct d2d_brush *opacity_brush)
972 D3D11_SUBRESOURCE_DATA buffer_data;
973 D3D11_BUFFER_DESC buffer_desc;
974 ID3D11Buffer *ib, *vb;
975 HRESULT hr;
977 buffer_desc.Usage = D3D11_USAGE_DEFAULT;
978 buffer_desc.CPUAccessFlags = 0;
979 buffer_desc.MiscFlags = 0;
981 buffer_data.SysMemPitch = 0;
982 buffer_data.SysMemSlicePitch = 0;
984 if (FAILED(hr = d2d_device_context_update_vs_cb(render_target, &geometry->transform, 0.0f)))
986 WARN("Failed to update vs constant buffer, hr %#lx.\n", hr);
987 return;
990 if (FAILED(hr = d2d_device_context_update_ps_cb(render_target, brush, opacity_brush, FALSE, FALSE)))
992 WARN("Failed to update ps constant buffer, hr %#lx.\n", hr);
993 return;
996 if (geometry->fill.face_count)
998 buffer_desc.ByteWidth = geometry->fill.face_count * sizeof(*geometry->fill.faces);
999 buffer_desc.BindFlags = D3D11_BIND_INDEX_BUFFER;
1000 buffer_data.pSysMem = geometry->fill.faces;
1002 if (FAILED(hr = ID3D11Device1_CreateBuffer(render_target->d3d_device, &buffer_desc, &buffer_data, &ib)))
1004 WARN("Failed to create index buffer, hr %#lx.\n", hr);
1005 return;
1008 buffer_desc.ByteWidth = geometry->fill.vertex_count * sizeof(*geometry->fill.vertices);
1009 buffer_desc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
1010 buffer_data.pSysMem = geometry->fill.vertices;
1012 if (FAILED(hr = ID3D11Device1_CreateBuffer(render_target->d3d_device, &buffer_desc, &buffer_data, &vb)))
1014 ERR("Failed to create vertex buffer, hr %#lx.\n", hr);
1015 ID3D11Buffer_Release(ib);
1016 return;
1019 d2d_device_context_draw(render_target, D2D_SHAPE_TYPE_TRIANGLE, ib, 3 * geometry->fill.face_count, vb,
1020 sizeof(*geometry->fill.vertices), brush, opacity_brush);
1022 ID3D11Buffer_Release(vb);
1023 ID3D11Buffer_Release(ib);
1026 if (geometry->fill.bezier_vertex_count)
1028 buffer_desc.ByteWidth = geometry->fill.bezier_vertex_count * sizeof(*geometry->fill.bezier_vertices);
1029 buffer_desc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
1030 buffer_data.pSysMem = geometry->fill.bezier_vertices;
1032 if (FAILED(hr = ID3D11Device1_CreateBuffer(render_target->d3d_device, &buffer_desc, &buffer_data, &vb)))
1034 ERR("Failed to create curves vertex buffer, hr %#lx.\n", hr);
1035 return;
1038 d2d_device_context_draw(render_target, D2D_SHAPE_TYPE_CURVE, NULL, geometry->fill.bezier_vertex_count, vb,
1039 sizeof(*geometry->fill.bezier_vertices), brush, opacity_brush);
1041 ID3D11Buffer_Release(vb);
1044 if (geometry->fill.arc_vertex_count)
1046 buffer_desc.ByteWidth = geometry->fill.arc_vertex_count * sizeof(*geometry->fill.arc_vertices);
1047 buffer_desc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
1048 buffer_data.pSysMem = geometry->fill.arc_vertices;
1050 if (FAILED(hr = ID3D11Device1_CreateBuffer(render_target->d3d_device, &buffer_desc, &buffer_data, &vb)))
1052 ERR("Failed to create arc vertex buffer, hr %#lx.\n", hr);
1053 return;
1056 if (SUCCEEDED(d2d_device_context_update_ps_cb(render_target, brush, opacity_brush, FALSE, TRUE)))
1057 d2d_device_context_draw(render_target, D2D_SHAPE_TYPE_CURVE, NULL, geometry->fill.arc_vertex_count, vb,
1058 sizeof(*geometry->fill.arc_vertices), brush, opacity_brush);
1060 ID3D11Buffer_Release(vb);
1064 static void STDMETHODCALLTYPE d2d_device_context_FillGeometry(ID2D1DeviceContext1 *iface,
1065 ID2D1Geometry *geometry, ID2D1Brush *brush, ID2D1Brush *opacity_brush)
1067 const struct d2d_geometry *geometry_impl = unsafe_impl_from_ID2D1Geometry(geometry);
1068 struct d2d_brush *opacity_brush_impl = unsafe_impl_from_ID2D1Brush(opacity_brush);
1069 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
1070 struct d2d_brush *brush_impl = unsafe_impl_from_ID2D1Brush(brush);
1072 TRACE("iface %p, geometry %p, brush %p, opacity_brush %p.\n", iface, geometry, brush, opacity_brush);
1074 if (FAILED(context->error.code))
1075 return;
1077 if (opacity_brush && brush_impl->type != D2D_BRUSH_TYPE_BITMAP)
1079 d2d_device_context_set_error(context, D2DERR_INCOMPATIBLE_BRUSH_TYPES);
1080 return;
1083 if (context->target.type == D2D_TARGET_COMMAND_LIST)
1084 d2d_command_list_fill_geometry(context->target.command_list, context, geometry, brush, opacity_brush);
1085 else
1086 d2d_device_context_fill_geometry(context, geometry_impl, brush_impl, opacity_brush_impl);
1089 static void STDMETHODCALLTYPE d2d_device_context_FillMesh(ID2D1DeviceContext1 *iface,
1090 ID2D1Mesh *mesh, ID2D1Brush *brush)
1092 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
1094 FIXME("iface %p, mesh %p, brush %p stub!\n", iface, mesh, brush);
1096 if (context->target.type == D2D_TARGET_COMMAND_LIST)
1097 d2d_command_list_fill_mesh(context->target.command_list, context, mesh, brush);
1100 static void STDMETHODCALLTYPE d2d_device_context_FillOpacityMask(ID2D1DeviceContext1 *iface,
1101 ID2D1Bitmap *mask, ID2D1Brush *brush, D2D1_OPACITY_MASK_CONTENT content,
1102 const D2D1_RECT_F *dst_rect, const D2D1_RECT_F *src_rect)
1104 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
1106 FIXME("iface %p, mask %p, brush %p, content %#x, dst_rect %s, src_rect %s stub!\n",
1107 iface, mask, brush, content, debug_d2d_rect_f(dst_rect), debug_d2d_rect_f(src_rect));
1109 if (FAILED(context->error.code))
1110 return;
1112 if (context->drawing_state.antialiasMode != D2D1_ANTIALIAS_MODE_ALIASED)
1114 d2d_device_context_set_error(context, D2DERR_WRONG_STATE);
1115 return;
1118 if ((unsigned int)content > D2D1_OPACITY_MASK_CONTENT_TEXT_GDI_COMPATIBLE)
1120 d2d_device_context_set_error(context, E_INVALIDARG);
1121 return;
1124 if (context->target.type == D2D_TARGET_COMMAND_LIST)
1125 d2d_command_list_fill_opacity_mask(context->target.command_list, context, mask, brush, dst_rect, src_rect);
1128 static void d2d_device_context_draw_bitmap(struct d2d_device_context *context, ID2D1Bitmap *bitmap,
1129 const D2D1_RECT_F *dst_rect, float opacity, D2D1_INTERPOLATION_MODE interpolation_mode,
1130 const D2D1_RECT_F *src_rect, const D2D1_POINT_2F *offset,
1131 const D2D1_MATRIX_4X4_F *perspective_transform)
1133 D2D1_BITMAP_BRUSH_PROPERTIES1 bitmap_brush_desc;
1134 D2D1_BRUSH_PROPERTIES brush_desc;
1135 struct d2d_brush *brush;
1136 D2D1_SIZE_F size;
1137 D2D1_RECT_F s, d;
1138 HRESULT hr;
1140 if (perspective_transform)
1141 FIXME("Perspective transform is ignored.\n");
1143 size = ID2D1Bitmap_GetSize(bitmap);
1144 d2d_rect_set(&s, 0.0f, 0.0f, size.width, size.height);
1145 if (src_rect && src_rect->left <= src_rect->right
1146 && src_rect->top <= src_rect->bottom)
1148 d2d_rect_intersect(&s, src_rect);
1151 if (s.left == s.right || s.top == s.bottom)
1152 return;
1154 if (dst_rect)
1156 d = *dst_rect;
1158 else
1160 d.left = 0.0f;
1161 d.top = 0.0f;
1162 d.right = s.right - s.left;
1163 d.bottom = s.bottom - s.top;
1166 if (offset)
1168 d.left += offset->x;
1169 d.top += offset->y;
1170 d.right += offset->x;
1171 d.bottom += offset->y;
1174 bitmap_brush_desc.extendModeX = D2D1_EXTEND_MODE_CLAMP;
1175 bitmap_brush_desc.extendModeY = D2D1_EXTEND_MODE_CLAMP;
1176 bitmap_brush_desc.interpolationMode = interpolation_mode;
1178 brush_desc.opacity = opacity;
1179 brush_desc.transform._11 = fabsf((d.right - d.left) / (s.right - s.left));
1180 brush_desc.transform._21 = 0.0f;
1181 brush_desc.transform._31 = min(d.left, d.right) - min(s.left, s.right) * brush_desc.transform._11;
1182 brush_desc.transform._12 = 0.0f;
1183 brush_desc.transform._22 = fabsf((d.bottom - d.top) / (s.bottom - s.top));
1184 brush_desc.transform._32 = min(d.top, d.bottom) - min(s.top, s.bottom) * brush_desc.transform._22;
1186 if (FAILED(hr = d2d_bitmap_brush_create(context->factory, bitmap, &bitmap_brush_desc, &brush_desc, &brush)))
1188 ERR("Failed to create bitmap brush, hr %#lx.\n", hr);
1189 return;
1192 d2d_device_context_FillRectangle(&context->ID2D1DeviceContext1_iface, &d, &brush->ID2D1Brush_iface);
1193 ID2D1Brush_Release(&brush->ID2D1Brush_iface);
1196 static void STDMETHODCALLTYPE d2d_device_context_DrawBitmap(ID2D1DeviceContext1 *iface,
1197 ID2D1Bitmap *bitmap, const D2D1_RECT_F *dst_rect, float opacity,
1198 D2D1_BITMAP_INTERPOLATION_MODE interpolation_mode, const D2D1_RECT_F *src_rect)
1200 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
1202 TRACE("iface %p, bitmap %p, dst_rect %s, opacity %.8e, interpolation_mode %#x, src_rect %s.\n",
1203 iface, bitmap, debug_d2d_rect_f(dst_rect), opacity, interpolation_mode, debug_d2d_rect_f(src_rect));
1205 if (interpolation_mode != D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR
1206 && interpolation_mode != D2D1_BITMAP_INTERPOLATION_MODE_LINEAR)
1208 d2d_device_context_set_error(context, E_INVALIDARG);
1209 return;
1212 if (context->target.type == D2D_TARGET_COMMAND_LIST)
1214 d2d_command_list_draw_bitmap(context->target.command_list, bitmap, dst_rect, opacity,
1215 d2d1_1_interp_mode_from_d2d1(interpolation_mode), src_rect, NULL);
1217 else
1219 d2d_device_context_draw_bitmap(context, bitmap, dst_rect, opacity,
1220 d2d1_1_interp_mode_from_d2d1(interpolation_mode), src_rect, NULL, NULL);
1224 static void STDMETHODCALLTYPE d2d_device_context_DrawText(ID2D1DeviceContext1 *iface,
1225 const WCHAR *string, UINT32 string_len, IDWriteTextFormat *text_format, const D2D1_RECT_F *layout_rect,
1226 ID2D1Brush *brush, D2D1_DRAW_TEXT_OPTIONS options, DWRITE_MEASURING_MODE measuring_mode)
1228 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1229 IDWriteTextLayout *text_layout;
1230 IDWriteFactory *dwrite_factory;
1231 D2D1_POINT_2F origin;
1232 float width, height;
1233 HRESULT hr;
1235 TRACE("iface %p, string %s, string_len %u, text_format %p, layout_rect %s, "
1236 "brush %p, options %#x, measuring_mode %#x.\n",
1237 iface, debugstr_wn(string, string_len), string_len, text_format, debug_d2d_rect_f(layout_rect),
1238 brush, options, measuring_mode);
1240 if (FAILED(hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED,
1241 &IID_IDWriteFactory, (IUnknown **)&dwrite_factory)))
1243 ERR("Failed to create dwrite factory, hr %#lx.\n", hr);
1244 return;
1247 width = max(0.0f, layout_rect->right - layout_rect->left);
1248 height = max(0.0f, layout_rect->bottom - layout_rect->top);
1249 if (measuring_mode == DWRITE_MEASURING_MODE_NATURAL)
1250 hr = IDWriteFactory_CreateTextLayout(dwrite_factory, string, string_len, text_format,
1251 width, height, &text_layout);
1252 else
1253 hr = IDWriteFactory_CreateGdiCompatibleTextLayout(dwrite_factory, string, string_len, text_format,
1254 width, height, render_target->desc.dpiX / 96.0f, (DWRITE_MATRIX *)&render_target->drawing_state.transform,
1255 measuring_mode == DWRITE_MEASURING_MODE_GDI_NATURAL, &text_layout);
1256 IDWriteFactory_Release(dwrite_factory);
1257 if (FAILED(hr))
1259 ERR("Failed to create text layout, hr %#lx.\n", hr);
1260 return;
1263 d2d_point_set(&origin, min(layout_rect->left, layout_rect->right), min(layout_rect->top, layout_rect->bottom));
1264 ID2D1DeviceContext1_DrawTextLayout(iface, origin, text_layout, brush, options);
1265 IDWriteTextLayout_Release(text_layout);
1268 static void STDMETHODCALLTYPE d2d_device_context_DrawTextLayout(ID2D1DeviceContext1 *iface,
1269 D2D1_POINT_2F origin, IDWriteTextLayout *layout, ID2D1Brush *brush, D2D1_DRAW_TEXT_OPTIONS options)
1271 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1272 struct d2d_draw_text_layout_ctx ctx;
1273 HRESULT hr;
1275 TRACE("iface %p, origin %s, layout %p, brush %p, options %#x.\n",
1276 iface, debug_d2d_point_2f(&origin), layout, brush, options);
1278 ctx.brush = brush;
1279 ctx.options = options;
1281 if (FAILED(hr = IDWriteTextLayout_Draw(layout,
1282 &ctx, &render_target->IDWriteTextRenderer_iface, origin.x, origin.y)))
1283 FIXME("Failed to draw text layout, hr %#lx.\n", hr);
1286 static D2D1_ANTIALIAS_MODE d2d_device_context_set_aa_mode_from_text_aa_mode(struct d2d_device_context *rt)
1288 D2D1_ANTIALIAS_MODE prev_antialias_mode = rt->drawing_state.antialiasMode;
1289 rt->drawing_state.antialiasMode = rt->drawing_state.textAntialiasMode == D2D1_TEXT_ANTIALIAS_MODE_ALIASED ?
1290 D2D1_ANTIALIAS_MODE_ALIASED : D2D1_ANTIALIAS_MODE_PER_PRIMITIVE;
1291 return prev_antialias_mode;
1294 static void d2d_device_context_draw_glyph_run_outline(struct d2d_device_context *render_target,
1295 D2D1_POINT_2F baseline_origin, const DWRITE_GLYPH_RUN *glyph_run, ID2D1Brush *brush)
1297 D2D1_MATRIX_3X2_F *transform, prev_transform;
1298 D2D1_ANTIALIAS_MODE prev_antialias_mode;
1299 ID2D1PathGeometry *geometry;
1300 ID2D1GeometrySink *sink;
1301 HRESULT hr;
1303 if (FAILED(hr = ID2D1Factory_CreatePathGeometry(render_target->factory, &geometry)))
1305 ERR("Failed to create geometry, hr %#lx.\n", hr);
1306 return;
1309 if (FAILED(hr = ID2D1PathGeometry_Open(geometry, &sink)))
1311 ERR("Failed to open geometry sink, hr %#lx.\n", hr);
1312 ID2D1PathGeometry_Release(geometry);
1313 return;
1316 if (FAILED(hr = IDWriteFontFace_GetGlyphRunOutline(glyph_run->fontFace, glyph_run->fontEmSize,
1317 glyph_run->glyphIndices, glyph_run->glyphAdvances, glyph_run->glyphOffsets, glyph_run->glyphCount,
1318 glyph_run->isSideways, glyph_run->bidiLevel & 1, (IDWriteGeometrySink *)sink)))
1320 ERR("Failed to get glyph run outline, hr %#lx.\n", hr);
1321 ID2D1GeometrySink_Release(sink);
1322 ID2D1PathGeometry_Release(geometry);
1323 return;
1326 if (FAILED(hr = ID2D1GeometrySink_Close(sink)))
1327 ERR("Failed to close geometry sink, hr %#lx.\n", hr);
1328 ID2D1GeometrySink_Release(sink);
1330 transform = &render_target->drawing_state.transform;
1331 prev_transform = *transform;
1332 transform->_31 += baseline_origin.x * transform->_11 + baseline_origin.y * transform->_21;
1333 transform->_32 += baseline_origin.x * transform->_12 + baseline_origin.y * transform->_22;
1334 prev_antialias_mode = d2d_device_context_set_aa_mode_from_text_aa_mode(render_target);
1335 d2d_device_context_fill_geometry(render_target, unsafe_impl_from_ID2D1Geometry((ID2D1Geometry *)geometry),
1336 unsafe_impl_from_ID2D1Brush(brush), NULL);
1337 render_target->drawing_state.antialiasMode = prev_antialias_mode;
1338 *transform = prev_transform;
1340 ID2D1PathGeometry_Release(geometry);
1343 static void d2d_device_context_draw_glyph_run_bitmap(struct d2d_device_context *render_target,
1344 D2D1_POINT_2F baseline_origin, const DWRITE_GLYPH_RUN *glyph_run, ID2D1Brush *brush,
1345 DWRITE_RENDERING_MODE rendering_mode, DWRITE_MEASURING_MODE measuring_mode,
1346 DWRITE_TEXT_ANTIALIAS_MODE antialias_mode)
1348 ID2D1RectangleGeometry *geometry = NULL;
1349 ID2D1BitmapBrush *opacity_brush = NULL;
1350 D2D1_BITMAP_PROPERTIES bitmap_desc;
1351 ID2D1Bitmap *opacity_bitmap = NULL;
1352 IDWriteGlyphRunAnalysis *analysis;
1353 DWRITE_TEXTURE_TYPE texture_type;
1354 D2D1_BRUSH_PROPERTIES brush_desc;
1355 IDWriteFactory2 *dwrite_factory;
1356 D2D1_MATRIX_3X2_F *transform, m;
1357 void *opacity_values = NULL;
1358 size_t opacity_values_size;
1359 D2D1_SIZE_U bitmap_size;
1360 float scale_x, scale_y;
1361 D2D1_RECT_F run_rect;
1362 RECT bounds;
1363 HRESULT hr;
1365 if (FAILED(hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED,
1366 &IID_IDWriteFactory2, (IUnknown **)&dwrite_factory)))
1368 ERR("Failed to create dwrite factory, hr %#lx.\n", hr);
1369 return;
1372 transform = &render_target->drawing_state.transform;
1374 scale_x = render_target->desc.dpiX / 96.0f;
1375 m._11 = transform->_11 * scale_x;
1376 m._21 = transform->_21 * scale_x;
1377 m._31 = transform->_31 * scale_x;
1379 scale_y = render_target->desc.dpiY / 96.0f;
1380 m._12 = transform->_12 * scale_y;
1381 m._22 = transform->_22 * scale_y;
1382 m._32 = transform->_32 * scale_y;
1384 hr = IDWriteFactory2_CreateGlyphRunAnalysis(dwrite_factory, glyph_run, (DWRITE_MATRIX *)&m,
1385 rendering_mode, measuring_mode, DWRITE_GRID_FIT_MODE_DEFAULT, antialias_mode,
1386 baseline_origin.x, baseline_origin.y, &analysis);
1387 IDWriteFactory2_Release(dwrite_factory);
1388 if (FAILED(hr))
1390 ERR("Failed to create glyph run analysis, hr %#lx.\n", hr);
1391 return;
1394 if (rendering_mode == DWRITE_RENDERING_MODE_ALIASED || antialias_mode == DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE)
1395 texture_type = DWRITE_TEXTURE_ALIASED_1x1;
1396 else
1397 texture_type = DWRITE_TEXTURE_CLEARTYPE_3x1;
1399 if (FAILED(hr = IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis, texture_type, &bounds)))
1401 ERR("Failed to get alpha texture bounds, hr %#lx.\n", hr);
1402 goto done;
1405 d2d_size_set(&bitmap_size, bounds.right - bounds.left, bounds.bottom - bounds.top);
1406 if (!bitmap_size.width || !bitmap_size.height)
1408 /* Empty run, nothing to do. */
1409 goto done;
1412 if (texture_type == DWRITE_TEXTURE_CLEARTYPE_3x1)
1413 bitmap_size.width *= 3;
1414 if (!(opacity_values = calloc(bitmap_size.height, bitmap_size.width)))
1416 ERR("Failed to allocate opacity values.\n");
1417 goto done;
1419 opacity_values_size = bitmap_size.height * bitmap_size.width;
1421 if (FAILED(hr = IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis,
1422 texture_type, &bounds, opacity_values, opacity_values_size)))
1424 ERR("Failed to create alpha texture, hr %#lx.\n", hr);
1425 goto done;
1428 bitmap_desc.pixelFormat.format = DXGI_FORMAT_A8_UNORM;
1429 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
1430 bitmap_desc.dpiX = render_target->desc.dpiX;
1431 if (texture_type == DWRITE_TEXTURE_CLEARTYPE_3x1)
1432 bitmap_desc.dpiX *= 3.0f;
1433 bitmap_desc.dpiY = render_target->desc.dpiY;
1434 if (FAILED(hr = d2d_device_context_CreateBitmap(&render_target->ID2D1DeviceContext1_iface,
1435 bitmap_size, opacity_values, bitmap_size.width, &bitmap_desc, &opacity_bitmap)))
1437 ERR("Failed to create opacity bitmap, hr %#lx.\n", hr);
1438 goto done;
1441 d2d_rect_set(&run_rect, bounds.left / scale_x, bounds.top / scale_y,
1442 bounds.right / scale_x, bounds.bottom / scale_y);
1444 brush_desc.opacity = 1.0f;
1445 brush_desc.transform._11 = 1.0f;
1446 brush_desc.transform._12 = 0.0f;
1447 brush_desc.transform._21 = 0.0f;
1448 brush_desc.transform._22 = 1.0f;
1449 brush_desc.transform._31 = run_rect.left;
1450 brush_desc.transform._32 = run_rect.top;
1451 if (FAILED(hr = d2d_device_context_CreateBitmapBrush(&render_target->ID2D1DeviceContext1_iface,
1452 opacity_bitmap, NULL, &brush_desc, &opacity_brush)))
1454 ERR("Failed to create opacity bitmap brush, hr %#lx.\n", hr);
1455 goto done;
1458 if (FAILED(hr = ID2D1Factory_CreateRectangleGeometry(render_target->factory, &run_rect, &geometry)))
1460 ERR("Failed to create geometry, hr %#lx.\n", hr);
1461 goto done;
1464 m = *transform;
1465 *transform = identity;
1466 d2d_device_context_fill_geometry(render_target, unsafe_impl_from_ID2D1Geometry((ID2D1Geometry *)geometry),
1467 unsafe_impl_from_ID2D1Brush(brush), unsafe_impl_from_ID2D1Brush((ID2D1Brush *)opacity_brush));
1468 *transform = m;
1470 done:
1471 if (geometry)
1472 ID2D1RectangleGeometry_Release(geometry);
1473 if (opacity_brush)
1474 ID2D1BitmapBrush_Release(opacity_brush);
1475 if (opacity_bitmap)
1476 ID2D1Bitmap_Release(opacity_bitmap);
1477 free(opacity_values);
1478 IDWriteGlyphRunAnalysis_Release(analysis);
1481 static void d2d_device_context_draw_glyph_run(struct d2d_device_context *context,
1482 D2D1_POINT_2F baseline_origin, const DWRITE_GLYPH_RUN *glyph_run,
1483 const DWRITE_GLYPH_RUN_DESCRIPTION *glyph_run_desc, ID2D1Brush *brush, DWRITE_MEASURING_MODE measuring_mode)
1485 DWRITE_TEXT_ANTIALIAS_MODE antialias_mode = DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE;
1486 IDWriteRenderingParams *rendering_params;
1487 DWRITE_RENDERING_MODE rendering_mode;
1488 HRESULT hr;
1490 if (FAILED(context->error.code))
1491 return;
1493 if (context->target.type == D2D_TARGET_COMMAND_LIST)
1495 d2d_command_list_draw_glyph_run(context->target.command_list, context, baseline_origin, glyph_run,
1496 glyph_run_desc, brush, measuring_mode);
1497 return;
1500 rendering_params = context->text_rendering_params ? context->text_rendering_params
1501 : context->default_text_rendering_params;
1503 rendering_mode = IDWriteRenderingParams_GetRenderingMode(rendering_params);
1505 switch (context->drawing_state.textAntialiasMode)
1507 case D2D1_TEXT_ANTIALIAS_MODE_ALIASED:
1508 if (rendering_mode == DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL
1509 || rendering_mode == DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC
1510 || rendering_mode == DWRITE_RENDERING_MODE_CLEARTYPE_GDI_NATURAL
1511 || rendering_mode == DWRITE_RENDERING_MODE_CLEARTYPE_GDI_CLASSIC)
1512 d2d_device_context_set_error(context, E_INVALIDARG);
1513 break;
1515 case D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE:
1516 if (rendering_mode == DWRITE_RENDERING_MODE_ALIASED
1517 || rendering_mode == DWRITE_RENDERING_MODE_OUTLINE)
1518 d2d_device_context_set_error(context, E_INVALIDARG);
1519 break;
1521 case D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE:
1522 if (rendering_mode == DWRITE_RENDERING_MODE_ALIASED)
1523 d2d_device_context_set_error(context, E_INVALIDARG);
1524 break;
1526 default:
1527 break;
1530 if (FAILED(context->error.code))
1531 return;
1533 rendering_mode = DWRITE_RENDERING_MODE_DEFAULT;
1534 switch (context->drawing_state.textAntialiasMode)
1536 case D2D1_TEXT_ANTIALIAS_MODE_DEFAULT:
1537 if (IDWriteRenderingParams_GetClearTypeLevel(rendering_params) > 0.0f)
1538 antialias_mode = DWRITE_TEXT_ANTIALIAS_MODE_CLEARTYPE;
1539 break;
1541 case D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE:
1542 antialias_mode = DWRITE_TEXT_ANTIALIAS_MODE_CLEARTYPE;
1543 break;
1545 case D2D1_TEXT_ANTIALIAS_MODE_ALIASED:
1546 rendering_mode = DWRITE_RENDERING_MODE_ALIASED;
1547 break;
1549 default:
1550 break;
1553 if (rendering_mode == DWRITE_RENDERING_MODE_DEFAULT)
1555 if (FAILED(hr = IDWriteFontFace_GetRecommendedRenderingMode(glyph_run->fontFace, glyph_run->fontEmSize,
1556 max(context->desc.dpiX, context->desc.dpiY) / 96.0f,
1557 measuring_mode, rendering_params, &rendering_mode)))
1559 ERR("Failed to get recommended rendering mode, hr %#lx.\n", hr);
1560 rendering_mode = DWRITE_RENDERING_MODE_OUTLINE;
1564 if (rendering_mode == DWRITE_RENDERING_MODE_OUTLINE)
1565 d2d_device_context_draw_glyph_run_outline(context, baseline_origin, glyph_run, brush);
1566 else
1567 d2d_device_context_draw_glyph_run_bitmap(context, baseline_origin, glyph_run, brush,
1568 rendering_mode, measuring_mode, antialias_mode);
1571 static void STDMETHODCALLTYPE d2d_device_context_DrawGlyphRun(ID2D1DeviceContext1 *iface,
1572 D2D1_POINT_2F baseline_origin, const DWRITE_GLYPH_RUN *glyph_run, ID2D1Brush *brush,
1573 DWRITE_MEASURING_MODE measuring_mode)
1575 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
1577 TRACE("iface %p, baseline_origin %s, glyph_run %p, brush %p, measuring_mode %#x.\n",
1578 iface, debug_d2d_point_2f(&baseline_origin), glyph_run, brush, measuring_mode);
1580 d2d_device_context_draw_glyph_run(context, baseline_origin, glyph_run, NULL, brush, measuring_mode);
1583 static void STDMETHODCALLTYPE d2d_device_context_SetTransform(ID2D1DeviceContext1 *iface,
1584 const D2D1_MATRIX_3X2_F *transform)
1586 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
1588 TRACE("iface %p, transform %p.\n", iface, transform);
1590 if (context->target.type == D2D_TARGET_COMMAND_LIST)
1591 d2d_command_list_set_transform(context->target.command_list, transform);
1593 context->drawing_state.transform = *transform;
1596 static void STDMETHODCALLTYPE d2d_device_context_GetTransform(ID2D1DeviceContext1 *iface,
1597 D2D1_MATRIX_3X2_F *transform)
1599 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1601 TRACE("iface %p, transform %p.\n", iface, transform);
1603 *transform = render_target->drawing_state.transform;
1606 static void STDMETHODCALLTYPE d2d_device_context_SetAntialiasMode(ID2D1DeviceContext1 *iface,
1607 D2D1_ANTIALIAS_MODE antialias_mode)
1609 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
1611 TRACE("iface %p, antialias_mode %#x stub!\n", iface, antialias_mode);
1613 if (context->target.type == D2D_TARGET_COMMAND_LIST)
1614 d2d_command_list_set_antialias_mode(context->target.command_list, antialias_mode);
1616 context->drawing_state.antialiasMode = antialias_mode;
1619 static D2D1_ANTIALIAS_MODE STDMETHODCALLTYPE d2d_device_context_GetAntialiasMode(ID2D1DeviceContext1 *iface)
1621 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1623 TRACE("iface %p.\n", iface);
1625 return render_target->drawing_state.antialiasMode;
1628 static void STDMETHODCALLTYPE d2d_device_context_SetTextAntialiasMode(ID2D1DeviceContext1 *iface,
1629 D2D1_TEXT_ANTIALIAS_MODE antialias_mode)
1631 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
1633 TRACE("iface %p, antialias_mode %#x.\n", iface, antialias_mode);
1635 if (context->target.type == D2D_TARGET_COMMAND_LIST)
1636 d2d_command_list_set_text_antialias_mode(context->target.command_list, antialias_mode);
1638 context->drawing_state.textAntialiasMode = antialias_mode;
1641 static D2D1_TEXT_ANTIALIAS_MODE STDMETHODCALLTYPE d2d_device_context_GetTextAntialiasMode(ID2D1DeviceContext1 *iface)
1643 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1645 TRACE("iface %p.\n", iface);
1647 return render_target->drawing_state.textAntialiasMode;
1650 static void STDMETHODCALLTYPE d2d_device_context_SetTextRenderingParams(ID2D1DeviceContext1 *iface,
1651 IDWriteRenderingParams *text_rendering_params)
1653 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
1655 TRACE("iface %p, text_rendering_params %p.\n", iface, text_rendering_params);
1657 if (context->target.type == D2D_TARGET_COMMAND_LIST)
1658 d2d_command_list_set_text_rendering_params(context->target.command_list, text_rendering_params);
1660 if (text_rendering_params)
1661 IDWriteRenderingParams_AddRef(text_rendering_params);
1662 if (context->text_rendering_params)
1663 IDWriteRenderingParams_Release(context->text_rendering_params);
1664 context->text_rendering_params = text_rendering_params;
1667 static void STDMETHODCALLTYPE d2d_device_context_GetTextRenderingParams(ID2D1DeviceContext1 *iface,
1668 IDWriteRenderingParams **text_rendering_params)
1670 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1672 TRACE("iface %p, text_rendering_params %p.\n", iface, text_rendering_params);
1674 if ((*text_rendering_params = render_target->text_rendering_params))
1675 IDWriteRenderingParams_AddRef(*text_rendering_params);
1678 static void STDMETHODCALLTYPE d2d_device_context_SetTags(ID2D1DeviceContext1 *iface, D2D1_TAG tag1, D2D1_TAG tag2)
1680 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
1682 TRACE("iface %p, tag1 %s, tag2 %s.\n", iface, wine_dbgstr_longlong(tag1), wine_dbgstr_longlong(tag2));
1684 if (context->target.type == D2D_TARGET_COMMAND_LIST)
1685 d2d_command_list_set_tags(context->target.command_list, tag1, tag2);
1687 context->drawing_state.tag1 = tag1;
1688 context->drawing_state.tag2 = tag2;
1691 static void STDMETHODCALLTYPE d2d_device_context_GetTags(ID2D1DeviceContext1 *iface, D2D1_TAG *tag1, D2D1_TAG *tag2)
1693 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1695 TRACE("iface %p, tag1 %p, tag2 %p.\n", iface, tag1, tag2);
1697 *tag1 = render_target->drawing_state.tag1;
1698 *tag2 = render_target->drawing_state.tag2;
1701 static void STDMETHODCALLTYPE d2d_device_context_PushLayer(ID2D1DeviceContext1 *iface,
1702 const D2D1_LAYER_PARAMETERS *layer_parameters, ID2D1Layer *layer)
1704 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
1706 FIXME("iface %p, layer_parameters %p, layer %p stub!\n", iface, layer_parameters, layer);
1708 if (context->target.type == D2D_TARGET_COMMAND_LIST)
1710 D2D1_LAYER_PARAMETERS1 parameters;
1712 memcpy(&parameters, layer_parameters, sizeof(*layer_parameters));
1713 parameters.layerOptions = D2D1_LAYER_OPTIONS1_NONE;
1714 d2d_command_list_push_layer(context->target.command_list, context, &parameters, layer);
1718 static void STDMETHODCALLTYPE d2d_device_context_PopLayer(ID2D1DeviceContext1 *iface)
1720 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
1722 FIXME("iface %p stub!\n", iface);
1724 if (context->target.type == D2D_TARGET_COMMAND_LIST)
1725 d2d_command_list_pop_layer(context->target.command_list);
1728 static HRESULT STDMETHODCALLTYPE d2d_device_context_Flush(ID2D1DeviceContext1 *iface, D2D1_TAG *tag1, D2D1_TAG *tag2)
1730 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
1732 FIXME("iface %p, tag1 %p, tag2 %p stub!\n", iface, tag1, tag2);
1734 if (context->ops && context->ops->device_context_present)
1735 context->ops->device_context_present(context->outer_unknown);
1737 return E_NOTIMPL;
1740 static void STDMETHODCALLTYPE d2d_device_context_SaveDrawingState(ID2D1DeviceContext1 *iface,
1741 ID2D1DrawingStateBlock *state_block)
1743 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1744 struct d2d_state_block *state_block_impl;
1746 TRACE("iface %p, state_block %p.\n", iface, state_block);
1748 if (!(state_block_impl = unsafe_impl_from_ID2D1DrawingStateBlock(state_block))) return;
1749 state_block_impl->drawing_state = render_target->drawing_state;
1750 if (render_target->text_rendering_params)
1751 IDWriteRenderingParams_AddRef(render_target->text_rendering_params);
1752 if (state_block_impl->text_rendering_params)
1753 IDWriteRenderingParams_Release(state_block_impl->text_rendering_params);
1754 state_block_impl->text_rendering_params = render_target->text_rendering_params;
1757 static void STDMETHODCALLTYPE d2d_device_context_RestoreDrawingState(ID2D1DeviceContext1 *iface,
1758 ID2D1DrawingStateBlock *state_block)
1760 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
1761 struct d2d_state_block *state_block_impl;
1763 TRACE("iface %p, state_block %p.\n", iface, state_block);
1765 if (!(state_block_impl = unsafe_impl_from_ID2D1DrawingStateBlock(state_block))) return;
1766 if (context->target.type == D2D_TARGET_COMMAND_LIST)
1768 struct d2d_command_list *command_list = context->target.command_list;
1770 if (context->drawing_state.antialiasMode != state_block_impl->drawing_state.antialiasMode)
1771 d2d_command_list_set_antialias_mode(command_list, state_block_impl->drawing_state.antialiasMode);
1772 d2d_command_list_set_text_antialias_mode(command_list, state_block_impl->drawing_state.textAntialiasMode);
1773 d2d_command_list_set_tags(command_list, state_block_impl->drawing_state.tag1, state_block_impl->drawing_state.tag2);
1774 d2d_command_list_set_transform(command_list, &state_block_impl->drawing_state.transform);
1775 d2d_command_list_set_primitive_blend(command_list, state_block_impl->drawing_state.primitiveBlend);
1776 d2d_command_list_set_unit_mode(command_list, state_block_impl->drawing_state.unitMode);
1777 d2d_command_list_set_text_rendering_params(command_list, state_block_impl->text_rendering_params);
1780 context->drawing_state = state_block_impl->drawing_state;
1781 if (state_block_impl->text_rendering_params)
1782 IDWriteRenderingParams_AddRef(state_block_impl->text_rendering_params);
1783 if (context->text_rendering_params)
1784 IDWriteRenderingParams_Release(context->text_rendering_params);
1785 context->text_rendering_params = state_block_impl->text_rendering_params;
1788 static void STDMETHODCALLTYPE d2d_device_context_PushAxisAlignedClip(ID2D1DeviceContext1 *iface,
1789 const D2D1_RECT_F *clip_rect, D2D1_ANTIALIAS_MODE antialias_mode)
1791 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
1792 D2D1_RECT_F transformed_rect;
1793 float x_scale, y_scale;
1794 D2D1_POINT_2F point;
1796 TRACE("iface %p, clip_rect %s, antialias_mode %#x.\n", iface, debug_d2d_rect_f(clip_rect), antialias_mode);
1798 if (context->target.type == D2D_TARGET_COMMAND_LIST)
1799 d2d_command_list_push_clip(context->target.command_list, clip_rect, antialias_mode);
1801 if (antialias_mode != D2D1_ANTIALIAS_MODE_ALIASED)
1802 FIXME("Ignoring antialias_mode %#x.\n", antialias_mode);
1804 x_scale = context->desc.dpiX / 96.0f;
1805 y_scale = context->desc.dpiY / 96.0f;
1806 d2d_point_transform(&point, &context->drawing_state.transform,
1807 clip_rect->left * x_scale, clip_rect->top * y_scale);
1808 d2d_rect_set(&transformed_rect, point.x, point.y, point.x, point.y);
1809 d2d_point_transform(&point, &context->drawing_state.transform,
1810 clip_rect->left * x_scale, clip_rect->bottom * y_scale);
1811 d2d_rect_expand(&transformed_rect, &point);
1812 d2d_point_transform(&point, &context->drawing_state.transform,
1813 clip_rect->right * x_scale, clip_rect->top * y_scale);
1814 d2d_rect_expand(&transformed_rect, &point);
1815 d2d_point_transform(&point, &context->drawing_state.transform,
1816 clip_rect->right * x_scale, clip_rect->bottom * y_scale);
1817 d2d_rect_expand(&transformed_rect, &point);
1819 if (!d2d_clip_stack_push(&context->clip_stack, &transformed_rect))
1820 WARN("Failed to push clip rect.\n");
1823 static void STDMETHODCALLTYPE d2d_device_context_PopAxisAlignedClip(ID2D1DeviceContext1 *iface)
1825 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
1827 TRACE("iface %p.\n", iface);
1829 if (context->target.type == D2D_TARGET_COMMAND_LIST)
1830 d2d_command_list_pop_clip(context->target.command_list);
1832 d2d_clip_stack_pop(&context->clip_stack);
1835 static void STDMETHODCALLTYPE d2d_device_context_Clear(ID2D1DeviceContext1 *iface, const D2D1_COLOR_F *colour)
1837 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
1838 D3D11_MAPPED_SUBRESOURCE map_desc;
1839 ID3D11DeviceContext *d3d_context;
1840 struct d2d_ps_cb *ps_cb_data;
1841 struct d2d_vs_cb *vs_cb_data;
1842 D2D1_COLOR_F *c;
1843 HRESULT hr;
1845 TRACE("iface %p, colour %p.\n", iface, colour);
1847 if (context->target.type == D2D_TARGET_COMMAND_LIST)
1849 d2d_command_list_clear(context->target.command_list, colour);
1850 return;
1853 ID3D11Device1_GetImmediateContext(context->d3d_device, &d3d_context);
1855 if (FAILED(hr = ID3D11DeviceContext_Map(d3d_context, (ID3D11Resource *)context->vs_cb,
1856 0, D3D11_MAP_WRITE_DISCARD, 0, &map_desc)))
1858 WARN("Failed to map vs constant buffer, hr %#lx.\n", hr);
1859 ID3D11DeviceContext_Release(d3d_context);
1860 return;
1863 vs_cb_data = map_desc.pData;
1864 vs_cb_data->transform_geometry._11 = 1.0f;
1865 vs_cb_data->transform_geometry._21 = 0.0f;
1866 vs_cb_data->transform_geometry._31 = 0.0f;
1867 vs_cb_data->transform_geometry.pad0 = 0.0f;
1868 vs_cb_data->transform_geometry._12 = 0.0f;
1869 vs_cb_data->transform_geometry._22 = 1.0f;
1870 vs_cb_data->transform_geometry._32 = 0.0f;
1871 vs_cb_data->transform_geometry.stroke_width = 0.0f;
1872 vs_cb_data->transform_rtx.x = 1.0f;
1873 vs_cb_data->transform_rtx.y = 0.0f;
1874 vs_cb_data->transform_rtx.z = 1.0f;
1875 vs_cb_data->transform_rtx.w = 1.0f;
1876 vs_cb_data->transform_rty.x = 0.0f;
1877 vs_cb_data->transform_rty.y = 1.0f;
1878 vs_cb_data->transform_rty.z = 1.0f;
1879 vs_cb_data->transform_rty.w = -1.0f;
1881 ID3D11DeviceContext_Unmap(d3d_context, (ID3D11Resource *)context->vs_cb, 0);
1883 if (FAILED(hr = ID3D11DeviceContext_Map(d3d_context, (ID3D11Resource *)context->ps_cb,
1884 0, D3D11_MAP_WRITE_DISCARD, 0, &map_desc)))
1886 WARN("Failed to map ps constant buffer, hr %#lx.\n", hr);
1887 ID3D11DeviceContext_Release(d3d_context);
1888 return;
1891 ps_cb_data = map_desc.pData;
1892 memset(ps_cb_data, 0, sizeof(*ps_cb_data));
1893 ps_cb_data->colour_brush.type = D2D_BRUSH_TYPE_SOLID;
1894 ps_cb_data->colour_brush.opacity = 1.0f;
1895 ps_cb_data->opacity_brush.type = D2D_BRUSH_TYPE_COUNT;
1896 c = &ps_cb_data->colour_brush.u.solid.colour;
1897 if (colour)
1898 *c = *colour;
1899 if (context->desc.pixelFormat.alphaMode == D2D1_ALPHA_MODE_IGNORE)
1900 c->a = 1.0f;
1901 c->r *= c->a;
1902 c->g *= c->a;
1903 c->b *= c->a;
1905 ID3D11DeviceContext_Unmap(d3d_context, (ID3D11Resource *)context->ps_cb, 0);
1906 ID3D11DeviceContext_Release(d3d_context);
1908 d2d_device_context_draw(context, D2D_SHAPE_TYPE_TRIANGLE, context->ib, 6,
1909 context->vb, context->vb_stride, NULL, NULL);
1912 static void STDMETHODCALLTYPE d2d_device_context_BeginDraw(ID2D1DeviceContext1 *iface)
1914 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
1916 TRACE("iface %p.\n", iface);
1918 if (context->target.type == D2D_TARGET_COMMAND_LIST)
1919 d2d_command_list_begin_draw(context->target.command_list, context);
1921 memset(&context->error, 0, sizeof(context->error));
1924 static HRESULT STDMETHODCALLTYPE d2d_device_context_EndDraw(ID2D1DeviceContext1 *iface,
1925 D2D1_TAG *tag1, D2D1_TAG *tag2)
1927 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
1928 HRESULT hr;
1930 TRACE("iface %p, tag1 %p, tag2 %p.\n", iface, tag1, tag2);
1932 if (context->target.type == D2D_TARGET_COMMAND_LIST)
1934 FIXME("Unimplemented for command list target.\n");
1935 return E_NOTIMPL;
1938 if (tag1)
1939 *tag1 = context->error.tag1;
1940 if (tag2)
1941 *tag2 = context->error.tag2;
1943 if (context->ops && context->ops->device_context_present)
1945 if (FAILED(hr = context->ops->device_context_present(context->outer_unknown)))
1946 context->error.code = hr;
1949 return context->error.code;
1952 static D2D1_PIXEL_FORMAT * STDMETHODCALLTYPE d2d_device_context_GetPixelFormat(ID2D1DeviceContext1 *iface,
1953 D2D1_PIXEL_FORMAT *format)
1955 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1957 TRACE("iface %p, format %p.\n", iface, format);
1959 *format = render_target->desc.pixelFormat;
1960 return format;
1963 static void STDMETHODCALLTYPE d2d_device_context_SetDpi(ID2D1DeviceContext1 *iface, float dpi_x, float dpi_y)
1965 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1967 TRACE("iface %p, dpi_x %.8e, dpi_y %.8e.\n", iface, dpi_x, dpi_y);
1969 if (dpi_x == 0.0f && dpi_y == 0.0f)
1971 dpi_x = 96.0f;
1972 dpi_y = 96.0f;
1974 else if (dpi_x <= 0.0f || dpi_y <= 0.0f)
1975 return;
1977 render_target->desc.dpiX = dpi_x;
1978 render_target->desc.dpiY = dpi_y;
1981 static void STDMETHODCALLTYPE d2d_device_context_GetDpi(ID2D1DeviceContext1 *iface, float *dpi_x, float *dpi_y)
1983 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1985 TRACE("iface %p, dpi_x %p, dpi_y %p.\n", iface, dpi_x, dpi_y);
1987 *dpi_x = render_target->desc.dpiX;
1988 *dpi_y = render_target->desc.dpiY;
1991 static D2D1_SIZE_F * STDMETHODCALLTYPE d2d_device_context_GetSize(ID2D1DeviceContext1 *iface, D2D1_SIZE_F *size)
1993 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
1995 TRACE("iface %p, size %p.\n", iface, size);
1997 size->width = render_target->pixel_size.width / (render_target->desc.dpiX / 96.0f);
1998 size->height = render_target->pixel_size.height / (render_target->desc.dpiY / 96.0f);
1999 return size;
2002 static D2D1_SIZE_U * STDMETHODCALLTYPE d2d_device_context_GetPixelSize(ID2D1DeviceContext1 *iface,
2003 D2D1_SIZE_U *pixel_size)
2005 struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface);
2007 TRACE("iface %p, pixel_size %p.\n", iface, pixel_size);
2009 *pixel_size = render_target->pixel_size;
2010 return pixel_size;
2013 static UINT32 STDMETHODCALLTYPE d2d_device_context_GetMaximumBitmapSize(ID2D1DeviceContext1 *iface)
2015 TRACE("iface %p.\n", iface);
2017 return D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION;
2020 static BOOL STDMETHODCALLTYPE d2d_device_context_IsSupported(ID2D1DeviceContext1 *iface,
2021 const D2D1_RENDER_TARGET_PROPERTIES *desc)
2023 FIXME("iface %p, desc %p stub!\n", iface, desc);
2025 return FALSE;
2028 static HRESULT STDMETHODCALLTYPE d2d_device_context_ID2D1DeviceContext_CreateBitmap(ID2D1DeviceContext1 *iface,
2029 D2D1_SIZE_U size, const void *src_data, UINT32 pitch,
2030 const D2D1_BITMAP_PROPERTIES1 *desc, ID2D1Bitmap1 **bitmap)
2032 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
2033 struct d2d_bitmap *object;
2034 HRESULT hr;
2036 TRACE("iface %p, size {%u, %u}, src_data %p, pitch %u, desc %p, bitmap %p.\n",
2037 iface, size.width, size.height, src_data, pitch, desc, bitmap);
2039 if (SUCCEEDED(hr = d2d_bitmap_create(context, size, src_data, pitch, desc, &object)))
2040 *bitmap = &object->ID2D1Bitmap1_iface;
2042 return hr;
2045 static HRESULT STDMETHODCALLTYPE d2d_device_context_ID2D1DeviceContext_CreateBitmapFromWicBitmap(
2046 ID2D1DeviceContext1 *iface, IWICBitmapSource *bitmap_source,
2047 const D2D1_BITMAP_PROPERTIES1 *desc, ID2D1Bitmap1 **bitmap)
2049 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
2050 struct d2d_bitmap *object;
2051 HRESULT hr;
2053 TRACE("iface %p, bitmap_source %p, desc %p, bitmap %p.\n", iface, bitmap_source, desc, bitmap);
2055 if (SUCCEEDED(hr = d2d_bitmap_create_from_wic_bitmap(context, bitmap_source, desc, &object)))
2056 *bitmap = &object->ID2D1Bitmap1_iface;
2058 return hr;
2061 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateColorContext(ID2D1DeviceContext1 *iface,
2062 D2D1_COLOR_SPACE space, const BYTE *profile, UINT32 profile_size, ID2D1ColorContext **color_context)
2064 FIXME("iface %p, space %#x, profile %p, profile_size %u, color_context %p stub!\n",
2065 iface, space, profile, profile_size, color_context);
2067 return E_NOTIMPL;
2070 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateColorContextFromFilename(ID2D1DeviceContext1 *iface,
2071 const WCHAR *filename, ID2D1ColorContext **color_context)
2073 FIXME("iface %p, filename %s, color_context %p stub!\n", iface, debugstr_w(filename), color_context);
2075 return E_NOTIMPL;
2078 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateColorContextFromWicColorContext(ID2D1DeviceContext1 *iface,
2079 IWICColorContext *wic_color_context, ID2D1ColorContext **color_context)
2081 FIXME("iface %p, wic_color_context %p, color_context %p stub!\n", iface, wic_color_context, color_context);
2083 return E_NOTIMPL;
2086 static BOOL d2d_bitmap_check_options_with_surface(unsigned int options, unsigned int surface_options)
2088 switch (options)
2090 case D2D1_BITMAP_OPTIONS_NONE:
2091 case D2D1_BITMAP_OPTIONS_TARGET:
2092 case D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW:
2093 case D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW | D2D1_BITMAP_OPTIONS_GDI_COMPATIBLE:
2094 case D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_GDI_COMPATIBLE:
2095 case D2D1_BITMAP_OPTIONS_CANNOT_DRAW | D2D1_BITMAP_OPTIONS_CPU_READ:
2096 case D2D1_BITMAP_OPTIONS_CANNOT_DRAW:
2097 break;
2098 default:
2099 WARN("Invalid bitmap options %#x.\n", options);
2100 return FALSE;
2103 if (options && (options & D2D1_BITMAP_OPTIONS_TARGET) != (surface_options & D2D1_BITMAP_OPTIONS_TARGET))
2104 return FALSE;
2105 if (!(options & D2D1_BITMAP_OPTIONS_CANNOT_DRAW) && (surface_options & D2D1_BITMAP_OPTIONS_CANNOT_DRAW))
2106 return FALSE;
2107 if (options & D2D1_BITMAP_OPTIONS_TARGET)
2109 if (options & D2D1_BITMAP_OPTIONS_GDI_COMPATIBLE && !(surface_options & D2D1_BITMAP_OPTIONS_GDI_COMPATIBLE))
2110 return FALSE;
2111 return TRUE;
2114 if (options & D2D1_BITMAP_OPTIONS_CANNOT_DRAW)
2116 if (!(surface_options & D2D1_BITMAP_OPTIONS_CANNOT_DRAW))
2117 return FALSE;
2119 if (options & D2D1_BITMAP_OPTIONS_CPU_READ && !(surface_options & D2D1_BITMAP_OPTIONS_CPU_READ))
2120 return FALSE;
2123 return TRUE;
2126 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateBitmapFromDxgiSurface(ID2D1DeviceContext1 *iface,
2127 IDXGISurface *surface, const D2D1_BITMAP_PROPERTIES1 *desc, ID2D1Bitmap1 **bitmap)
2129 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
2130 D2D1_BITMAP_PROPERTIES1 bitmap_desc;
2131 unsigned int surface_options;
2132 struct d2d_bitmap *object;
2133 HRESULT hr;
2135 TRACE("iface %p, surface %p, desc %p, bitmap %p.\n", iface, surface, desc, bitmap);
2137 surface_options = d2d_get_bitmap_options_for_surface(surface);
2139 if (desc)
2141 if (!d2d_bitmap_check_options_with_surface(desc->bitmapOptions, surface_options))
2143 WARN("Incompatible bitmap options %#x, surface options %#x.\n",
2144 desc->bitmapOptions, surface_options);
2145 return E_INVALIDARG;
2148 else
2150 DXGI_SURFACE_DESC surface_desc;
2152 if (FAILED(hr = IDXGISurface_GetDesc(surface, &surface_desc)))
2154 WARN("Failed to get surface desc, hr %#lx.\n", hr);
2155 return hr;
2158 memset(&bitmap_desc, 0, sizeof(bitmap_desc));
2159 bitmap_desc.pixelFormat.format = surface_desc.Format;
2160 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
2161 bitmap_desc.bitmapOptions = surface_options;
2162 desc = &bitmap_desc;
2165 if (SUCCEEDED(hr = d2d_bitmap_create_shared(context, &IID_IDXGISurface, surface, desc, &object)))
2166 *bitmap = &object->ID2D1Bitmap1_iface;
2168 return hr;
2171 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateEffect(ID2D1DeviceContext1 *iface,
2172 REFCLSID effect_id, ID2D1Effect **effect)
2174 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
2176 TRACE("iface %p, effect_id %s, effect %p.\n", iface, debugstr_guid(effect_id), effect);
2178 return d2d_effect_create(context, effect_id, effect);
2181 static HRESULT STDMETHODCALLTYPE d2d_device_context_ID2D1DeviceContext_CreateGradientStopCollection(
2182 ID2D1DeviceContext1 *iface, const D2D1_GRADIENT_STOP *stops, UINT32 stop_count,
2183 D2D1_COLOR_SPACE preinterpolation_space, D2D1_COLOR_SPACE postinterpolation_space,
2184 D2D1_BUFFER_PRECISION buffer_precision, D2D1_EXTEND_MODE extend_mode,
2185 D2D1_COLOR_INTERPOLATION_MODE color_interpolation_mode, ID2D1GradientStopCollection1 **gradient)
2187 FIXME("iface %p, stops %p, stop_count %u, preinterpolation_space %#x, postinterpolation_space %#x, "
2188 "buffer_precision %#x, extend_mode %#x, color_interpolation_mode %#x, gradient %p stub!\n",
2189 iface, stops, stop_count, preinterpolation_space, postinterpolation_space,
2190 buffer_precision, extend_mode, color_interpolation_mode, gradient);
2192 return E_NOTIMPL;
2195 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateImageBrush(ID2D1DeviceContext1 *iface,
2196 ID2D1Image *image, const D2D1_IMAGE_BRUSH_PROPERTIES *image_brush_desc,
2197 const D2D1_BRUSH_PROPERTIES *brush_desc, ID2D1ImageBrush **brush)
2199 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
2200 struct d2d_brush *object;
2201 HRESULT hr;
2203 TRACE("iface %p, image %p, image_brush_desc %p, brush_desc %p, brush %p.\n", iface, image, image_brush_desc,
2204 brush_desc, brush);
2206 if (SUCCEEDED(hr = d2d_image_brush_create(context->factory, image, image_brush_desc,
2207 brush_desc, &object)))
2208 *brush = (ID2D1ImageBrush *)&object->ID2D1Brush_iface;
2210 return hr;
2213 static HRESULT STDMETHODCALLTYPE d2d_device_context_ID2D1DeviceContext_CreateBitmapBrush(ID2D1DeviceContext1 *iface,
2214 ID2D1Bitmap *bitmap, const D2D1_BITMAP_BRUSH_PROPERTIES1 *bitmap_brush_desc,
2215 const D2D1_BRUSH_PROPERTIES *brush_desc, ID2D1BitmapBrush1 **brush)
2217 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
2218 struct d2d_brush *object;
2219 HRESULT hr;
2221 TRACE("iface %p, bitmap %p, bitmap_brush_desc %p, brush_desc %p, brush %p.\n", iface, bitmap, bitmap_brush_desc,
2222 brush_desc, brush);
2224 if (SUCCEEDED(hr = d2d_bitmap_brush_create(context->factory, bitmap, bitmap_brush_desc, brush_desc, &object)))
2225 *brush = (ID2D1BitmapBrush1 *)&object->ID2D1Brush_iface;
2227 return hr;
2230 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateCommandList(ID2D1DeviceContext1 *iface,
2231 ID2D1CommandList **command_list)
2233 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
2234 struct d2d_command_list *object;
2235 HRESULT hr;
2237 TRACE("iface %p, command_list %p.\n", iface, command_list);
2239 if (SUCCEEDED(hr = d2d_command_list_create(context->factory, &object)))
2240 *command_list = &object->ID2D1CommandList_iface;
2242 return hr;
2245 static BOOL STDMETHODCALLTYPE d2d_device_context_IsDxgiFormatSupported(ID2D1DeviceContext1 *iface, DXGI_FORMAT format)
2247 FIXME("iface %p, format %#x stub!\n", iface, format);
2249 return FALSE;
2252 static BOOL STDMETHODCALLTYPE d2d_device_context_IsBufferPrecisionSupported(ID2D1DeviceContext1 *iface,
2253 D2D1_BUFFER_PRECISION buffer_precision)
2255 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
2256 DXGI_FORMAT format;
2257 UINT support = 0;
2258 HRESULT hr;
2260 TRACE("iface %p, buffer_precision %u.\n", iface, buffer_precision);
2262 switch (buffer_precision)
2264 case D2D1_BUFFER_PRECISION_8BPC_UNORM: format = DXGI_FORMAT_R8G8B8A8_UNORM; break;
2265 case D2D1_BUFFER_PRECISION_8BPC_UNORM_SRGB: format = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB; break;
2266 case D2D1_BUFFER_PRECISION_16BPC_UNORM: format = DXGI_FORMAT_R16G16B16A16_UNORM; break;
2267 case D2D1_BUFFER_PRECISION_16BPC_FLOAT: format = DXGI_FORMAT_R16G16B16A16_FLOAT; break;
2268 case D2D1_BUFFER_PRECISION_32BPC_FLOAT: format = DXGI_FORMAT_R32G32B32A32_FLOAT; break;
2269 default:
2270 WARN("Unexpected precision %u.\n", buffer_precision);
2271 return FALSE;
2274 if (FAILED(hr = ID3D11Device1_CheckFormatSupport(context->d3d_device, format, &support)))
2276 WARN("Format support check failed, hr %#lx.\n", hr);
2279 return !!(support & D3D11_FORMAT_SUPPORT_BUFFER);
2282 static void STDMETHODCALLTYPE d2d_device_context_GetImageLocalBounds(ID2D1DeviceContext1 *iface,
2283 ID2D1Image *image, D2D1_RECT_F *local_bounds)
2285 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
2286 D2D_SIZE_U pixel_size;
2287 ID2D1Bitmap *bitmap;
2288 D2D_SIZE_F size;
2290 TRACE("iface %p, image %p, local_bounds %p.\n", iface, image, local_bounds);
2292 if (SUCCEEDED(ID2D1Image_QueryInterface(image, &IID_ID2D1Bitmap, (void **)&bitmap)))
2294 local_bounds->left = 0.0f;
2295 local_bounds->top = 0.0f;
2296 switch (context->drawing_state.unitMode)
2298 case D2D1_UNIT_MODE_DIPS:
2299 size = ID2D1Bitmap_GetSize(bitmap);
2300 local_bounds->right = size.width;
2301 local_bounds->bottom = size.height;
2302 break;
2304 case D2D1_UNIT_MODE_PIXELS:
2305 pixel_size = ID2D1Bitmap_GetPixelSize(bitmap);
2306 local_bounds->right = pixel_size.width;
2307 local_bounds->bottom = pixel_size.height;
2308 break;
2310 default:
2311 WARN("Unknown unit mode %#x.\n", context->drawing_state.unitMode);
2312 break;
2314 ID2D1Bitmap_Release(bitmap);
2316 else
2318 FIXME("Unable to get local bounds of image %p.\n", image);
2322 static HRESULT STDMETHODCALLTYPE d2d_device_context_GetImageWorldBounds(ID2D1DeviceContext1 *iface,
2323 ID2D1Image *image, D2D1_RECT_F *world_bounds)
2325 FIXME("iface %p, image %p, world_bounds %p stub!\n", iface, image, world_bounds);
2327 return E_NOTIMPL;
2330 static HRESULT STDMETHODCALLTYPE d2d_device_context_GetGlyphRunWorldBounds(ID2D1DeviceContext1 *iface,
2331 D2D1_POINT_2F baseline_origin, const DWRITE_GLYPH_RUN *glyph_run,
2332 DWRITE_MEASURING_MODE measuring_mode, D2D1_RECT_F *bounds)
2334 FIXME("iface %p, baseline_origin %s, glyph_run %p, measuring_mode %#x, bounds %p stub!\n",
2335 iface, debug_d2d_point_2f(&baseline_origin), glyph_run, measuring_mode, bounds);
2337 return E_NOTIMPL;
2340 static void STDMETHODCALLTYPE d2d_device_context_GetDevice(ID2D1DeviceContext1 *iface, ID2D1Device **device)
2342 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
2344 TRACE("iface %p, device %p.\n", iface, device);
2346 *device = (ID2D1Device *)&context->device->ID2D1Device1_iface;
2347 ID2D1Device_AddRef(*device);
2350 static void d2d_device_context_reset_target(struct d2d_device_context *context)
2352 if (!context->target.object)
2353 return;
2355 IUnknown_Release(context->target.object);
2356 memset(&context->target, 0, sizeof(context->target));
2358 /* Note that DPI settings are kept. */
2359 memset(&context->desc.pixelFormat, 0, sizeof(context->desc.pixelFormat));
2360 memset(&context->pixel_size, 0, sizeof(context->pixel_size));
2362 if (context->bs)
2363 ID3D11BlendState_Release(context->bs);
2364 context->bs = NULL;
2367 static void STDMETHODCALLTYPE d2d_device_context_SetTarget(ID2D1DeviceContext1 *iface, ID2D1Image *target)
2369 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
2370 struct d2d_command_list *command_list_impl;
2371 struct d2d_bitmap *bitmap_impl;
2372 ID2D1CommandList *command_list;
2373 D3D11_BLEND_DESC blend_desc;
2374 ID2D1Bitmap *bitmap;
2375 HRESULT hr;
2377 TRACE("iface %p, target %p.\n", iface, target);
2379 if (!target)
2381 d2d_device_context_reset_target(context);
2382 return;
2385 if (SUCCEEDED(ID2D1Image_QueryInterface(target, &IID_ID2D1Bitmap, (void **)&bitmap)))
2387 bitmap_impl = unsafe_impl_from_ID2D1Bitmap(bitmap);
2389 if (!(bitmap_impl->options & D2D1_BITMAP_OPTIONS_TARGET))
2391 ID2D1Bitmap_Release(bitmap);
2392 d2d_device_context_set_error(context, D2DERR_INVALID_TARGET);
2393 return;
2396 d2d_device_context_reset_target(context);
2398 /* Set sizes and pixel format. */
2399 context->pixel_size = bitmap_impl->pixel_size;
2400 context->desc.pixelFormat = bitmap_impl->format;
2401 context->target.bitmap = bitmap_impl;
2402 context->target.object = target;
2403 context->target.type = D2D_TARGET_BITMAP;
2405 memset(&blend_desc, 0, sizeof(blend_desc));
2406 blend_desc.IndependentBlendEnable = FALSE;
2407 blend_desc.RenderTarget[0].BlendEnable = TRUE;
2408 blend_desc.RenderTarget[0].SrcBlend = D3D11_BLEND_ONE;
2409 blend_desc.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA;
2410 blend_desc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;
2411 blend_desc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE;
2412 blend_desc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_INV_SRC_ALPHA;
2413 blend_desc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
2414 blend_desc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
2415 if (FAILED(hr = ID3D11Device1_CreateBlendState(context->d3d_device, &blend_desc, &context->bs)))
2416 WARN("Failed to create blend state, hr %#lx.\n", hr);
2418 else if (SUCCEEDED(ID2D1Image_QueryInterface(target, &IID_ID2D1CommandList, (void **)&command_list)))
2420 command_list_impl = unsafe_impl_from_ID2D1CommandList(command_list);
2422 d2d_device_context_reset_target(context);
2424 context->target.command_list = command_list_impl;
2425 context->target.object = target;
2426 context->target.type = D2D_TARGET_COMMAND_LIST;
2428 else
2430 WARN("Unsupported target type.\n");
2434 static void STDMETHODCALLTYPE d2d_device_context_GetTarget(ID2D1DeviceContext1 *iface, ID2D1Image **target)
2436 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
2438 TRACE("iface %p, target %p.\n", iface, target);
2440 *target = context->target.object ? context->target.object : NULL;
2441 if (*target)
2442 ID2D1Image_AddRef(*target);
2445 static void STDMETHODCALLTYPE d2d_device_context_SetRenderingControls(ID2D1DeviceContext1 *iface,
2446 const D2D1_RENDERING_CONTROLS *rendering_controls)
2448 FIXME("iface %p, rendering_controls %p stub!\n", iface, rendering_controls);
2451 static void STDMETHODCALLTYPE d2d_device_context_GetRenderingControls(ID2D1DeviceContext1 *iface,
2452 D2D1_RENDERING_CONTROLS *rendering_controls)
2454 FIXME("iface %p, rendering_controls %p stub!\n", iface, rendering_controls);
2457 static void STDMETHODCALLTYPE d2d_device_context_SetPrimitiveBlend(ID2D1DeviceContext1 *iface,
2458 D2D1_PRIMITIVE_BLEND primitive_blend)
2460 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
2462 TRACE("iface %p, primitive_blend %u.\n", iface, primitive_blend);
2464 if (primitive_blend > D2D1_PRIMITIVE_BLEND_MAX)
2466 WARN("Unknown blend mode %u.\n", primitive_blend);
2467 return;
2470 if (context->target.type == D2D_TARGET_COMMAND_LIST)
2471 d2d_command_list_set_primitive_blend(context->target.command_list, primitive_blend);
2473 context->drawing_state.primitiveBlend = primitive_blend;
2476 static D2D1_PRIMITIVE_BLEND STDMETHODCALLTYPE d2d_device_context_GetPrimitiveBlend(ID2D1DeviceContext1 *iface)
2478 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
2480 TRACE("iface %p.\n", iface);
2482 return context->drawing_state.primitiveBlend;
2485 static void STDMETHODCALLTYPE d2d_device_context_SetUnitMode(ID2D1DeviceContext1 *iface, D2D1_UNIT_MODE unit_mode)
2487 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
2489 TRACE("iface %p, unit_mode %#x.\n", iface, unit_mode);
2491 if (unit_mode != D2D1_UNIT_MODE_DIPS && unit_mode != D2D1_UNIT_MODE_PIXELS)
2493 WARN("Unknown unit mode %#x.\n", unit_mode);
2494 return;
2497 if (context->target.type == D2D_TARGET_COMMAND_LIST)
2498 d2d_command_list_set_unit_mode(context->target.command_list, unit_mode);
2500 context->drawing_state.unitMode = unit_mode;
2503 static D2D1_UNIT_MODE STDMETHODCALLTYPE d2d_device_context_GetUnitMode(ID2D1DeviceContext1 *iface)
2505 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
2507 TRACE("iface %p.\n", iface);
2509 return context->drawing_state.unitMode;
2512 static void STDMETHODCALLTYPE d2d_device_context_ID2D1DeviceContext_DrawGlyphRun(ID2D1DeviceContext1 *iface,
2513 D2D1_POINT_2F baseline_origin, const DWRITE_GLYPH_RUN *glyph_run,
2514 const DWRITE_GLYPH_RUN_DESCRIPTION *glyph_run_desc, ID2D1Brush *brush, DWRITE_MEASURING_MODE measuring_mode)
2516 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
2518 TRACE("iface %p, baseline_origin %s, glyph_run %p, glyph_run_desc %p, brush %p, measuring_mode %#x.\n",
2519 iface, debug_d2d_point_2f(&baseline_origin), glyph_run, glyph_run_desc, brush, measuring_mode);
2521 d2d_device_context_draw_glyph_run(context, baseline_origin, glyph_run, glyph_run_desc, brush, measuring_mode);
2524 static void STDMETHODCALLTYPE d2d_device_context_DrawImage(ID2D1DeviceContext1 *iface, ID2D1Image *image,
2525 const D2D1_POINT_2F *target_offset, const D2D1_RECT_F *image_rect, D2D1_INTERPOLATION_MODE interpolation_mode,
2526 D2D1_COMPOSITE_MODE composite_mode)
2528 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
2529 ID2D1Bitmap *bitmap;
2531 TRACE("iface %p, image %p, target_offset %s, image_rect %s, interpolation_mode %#x, composite_mode %#x.\n",
2532 iface, image, debug_d2d_point_2f(target_offset), debug_d2d_rect_f(image_rect),
2533 interpolation_mode, composite_mode);
2535 if (context->target.type == D2D_TARGET_COMMAND_LIST)
2537 d2d_command_list_draw_image(context->target.command_list, image, target_offset, image_rect,
2538 interpolation_mode, composite_mode);
2539 return;
2542 if (composite_mode != D2D1_COMPOSITE_MODE_SOURCE_OVER)
2543 FIXME("Unhandled composite mode %#x.\n", composite_mode);
2545 if (SUCCEEDED(ID2D1Image_QueryInterface(image, &IID_ID2D1Bitmap, (void **)&bitmap)))
2547 d2d_device_context_draw_bitmap(context, bitmap, NULL, 1.0f, d2d1_1_interp_mode_from_d2d1(interpolation_mode),
2548 image_rect, target_offset, NULL);
2550 ID2D1Bitmap_Release(bitmap);
2551 return;
2554 FIXME("Unhandled image %p.\n", image);
2557 static void STDMETHODCALLTYPE d2d_device_context_DrawGdiMetafile(ID2D1DeviceContext1 *iface,
2558 ID2D1GdiMetafile *metafile, const D2D1_POINT_2F *target_offset)
2560 FIXME("iface %p, metafile %p, target_offset %s stub!\n",
2561 iface, metafile, debug_d2d_point_2f(target_offset));
2564 static void STDMETHODCALLTYPE d2d_device_context_ID2D1DeviceContext_DrawBitmap(ID2D1DeviceContext1 *iface,
2565 ID2D1Bitmap *bitmap, const D2D1_RECT_F *dst_rect, float opacity, D2D1_INTERPOLATION_MODE interpolation_mode,
2566 const D2D1_RECT_F *src_rect, const D2D1_MATRIX_4X4_F *perspective_transform)
2568 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
2570 TRACE("iface %p, bitmap %p, dst_rect %s, opacity %.8e, interpolation_mode %#x, "
2571 "src_rect %s, perspective_transform %p.\n",
2572 iface, bitmap, debug_d2d_rect_f(dst_rect), opacity, interpolation_mode,
2573 debug_d2d_rect_f(src_rect), perspective_transform);
2575 if (context->target.type == D2D_TARGET_COMMAND_LIST)
2577 d2d_command_list_draw_bitmap(context->target.command_list, bitmap, dst_rect, opacity, interpolation_mode,
2578 src_rect, perspective_transform);
2580 else
2582 d2d_device_context_draw_bitmap(context, bitmap, dst_rect, opacity, interpolation_mode, src_rect,
2583 NULL, perspective_transform);
2587 static void STDMETHODCALLTYPE d2d_device_context_ID2D1DeviceContext_PushLayer(ID2D1DeviceContext1 *iface,
2588 const D2D1_LAYER_PARAMETERS1 *layer_parameters, ID2D1Layer *layer)
2590 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
2592 FIXME("iface %p, layer_parameters %p, layer %p stub!\n", iface, layer_parameters, layer);
2594 if (context->target.type == D2D_TARGET_COMMAND_LIST)
2595 d2d_command_list_push_layer(context->target.command_list, context, layer_parameters, layer);
2598 static HRESULT STDMETHODCALLTYPE d2d_device_context_InvalidateEffectInputRectangle(ID2D1DeviceContext1 *iface,
2599 ID2D1Effect *effect, UINT32 input, const D2D1_RECT_F *input_rect)
2601 FIXME("iface %p, effect %p, input %u, input_rect %s stub!\n",
2602 iface, effect, input, debug_d2d_rect_f(input_rect));
2604 return E_NOTIMPL;
2607 static HRESULT STDMETHODCALLTYPE d2d_device_context_GetEffectInvalidRectangleCount(ID2D1DeviceContext1 *iface,
2608 ID2D1Effect *effect, UINT32 *rect_count)
2610 FIXME("iface %p, effect %p, rect_count %p stub!\n", iface, effect, rect_count);
2612 return E_NOTIMPL;
2615 static HRESULT STDMETHODCALLTYPE d2d_device_context_GetEffectInvalidRectangles(ID2D1DeviceContext1 *iface,
2616 ID2D1Effect *effect, D2D1_RECT_F *rectangles, UINT32 rect_count)
2618 FIXME("iface %p, effect %p, rectangles %p, rect_count %u stub!\n", iface, effect, rectangles, rect_count);
2620 return E_NOTIMPL;
2623 static HRESULT STDMETHODCALLTYPE d2d_device_context_GetEffectRequiredInputRectangles(ID2D1DeviceContext1 *iface,
2624 ID2D1Effect *effect, const D2D1_RECT_F *image_rect, const D2D1_EFFECT_INPUT_DESCRIPTION *desc,
2625 D2D1_RECT_F *input_rect, UINT32 input_count)
2627 FIXME("iface %p, effect %p, image_rect %s, desc %p, input_rect %p, input_count %u stub!\n",
2628 iface, effect, debug_d2d_rect_f(image_rect), desc, input_rect, input_count);
2630 return E_NOTIMPL;
2633 static void STDMETHODCALLTYPE d2d_device_context_ID2D1DeviceContext_FillOpacityMask(ID2D1DeviceContext1 *iface,
2634 ID2D1Bitmap *mask, ID2D1Brush *brush, const D2D1_RECT_F *dst_rect, const D2D1_RECT_F *src_rect)
2636 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
2638 FIXME("iface %p, mask %p, brush %p, dst_rect %s, src_rect %s stub!\n",
2639 iface, mask, brush, debug_d2d_rect_f(dst_rect), debug_d2d_rect_f(src_rect));
2641 if (FAILED(context->error.code))
2642 return;
2644 if (context->drawing_state.antialiasMode != D2D1_ANTIALIAS_MODE_ALIASED)
2646 d2d_device_context_set_error(context, D2DERR_WRONG_STATE);
2647 return;
2650 if (context->target.type == D2D_TARGET_COMMAND_LIST)
2651 d2d_command_list_fill_opacity_mask(context->target.command_list, context, mask, brush, dst_rect, src_rect);
2654 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateFilledGeometryRealization(ID2D1DeviceContext1 *iface,
2655 ID2D1Geometry *geometry, float tolerance, ID2D1GeometryRealization **realization)
2657 FIXME("iface %p, geometry %p, tolerance %.8e, realization %p stub!\n", iface, geometry, tolerance,
2658 realization);
2660 return E_NOTIMPL;
2663 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateStrokedGeometryRealization(ID2D1DeviceContext1 *iface,
2664 ID2D1Geometry *geometry, float tolerance, float stroke_width, ID2D1StrokeStyle *stroke_style,
2665 ID2D1GeometryRealization **realization)
2667 FIXME("iface %p, geometry %p, tolerance %.8e, stroke_width %.8e, stroke_style %p, realization %p stub!\n",
2668 iface, geometry, tolerance, stroke_width, stroke_style, realization);
2670 return E_NOTIMPL;
2673 static void STDMETHODCALLTYPE d2d_device_context_DrawGeometryRealization(ID2D1DeviceContext1 *iface,
2674 ID2D1GeometryRealization *realization, ID2D1Brush *brush)
2676 FIXME("iface %p, realization %p, brush %p stub!\n", iface, realization, brush);
2679 static const struct ID2D1DeviceContext1Vtbl d2d_device_context_vtbl =
2681 d2d_device_context_QueryInterface,
2682 d2d_device_context_AddRef,
2683 d2d_device_context_Release,
2684 d2d_device_context_GetFactory,
2685 d2d_device_context_CreateBitmap,
2686 d2d_device_context_CreateBitmapFromWicBitmap,
2687 d2d_device_context_CreateSharedBitmap,
2688 d2d_device_context_CreateBitmapBrush,
2689 d2d_device_context_CreateSolidColorBrush,
2690 d2d_device_context_CreateGradientStopCollection,
2691 d2d_device_context_CreateLinearGradientBrush,
2692 d2d_device_context_CreateRadialGradientBrush,
2693 d2d_device_context_CreateCompatibleRenderTarget,
2694 d2d_device_context_CreateLayer,
2695 d2d_device_context_CreateMesh,
2696 d2d_device_context_DrawLine,
2697 d2d_device_context_DrawRectangle,
2698 d2d_device_context_FillRectangle,
2699 d2d_device_context_DrawRoundedRectangle,
2700 d2d_device_context_FillRoundedRectangle,
2701 d2d_device_context_DrawEllipse,
2702 d2d_device_context_FillEllipse,
2703 d2d_device_context_DrawGeometry,
2704 d2d_device_context_FillGeometry,
2705 d2d_device_context_FillMesh,
2706 d2d_device_context_FillOpacityMask,
2707 d2d_device_context_DrawBitmap,
2708 d2d_device_context_DrawText,
2709 d2d_device_context_DrawTextLayout,
2710 d2d_device_context_DrawGlyphRun,
2711 d2d_device_context_SetTransform,
2712 d2d_device_context_GetTransform,
2713 d2d_device_context_SetAntialiasMode,
2714 d2d_device_context_GetAntialiasMode,
2715 d2d_device_context_SetTextAntialiasMode,
2716 d2d_device_context_GetTextAntialiasMode,
2717 d2d_device_context_SetTextRenderingParams,
2718 d2d_device_context_GetTextRenderingParams,
2719 d2d_device_context_SetTags,
2720 d2d_device_context_GetTags,
2721 d2d_device_context_PushLayer,
2722 d2d_device_context_PopLayer,
2723 d2d_device_context_Flush,
2724 d2d_device_context_SaveDrawingState,
2725 d2d_device_context_RestoreDrawingState,
2726 d2d_device_context_PushAxisAlignedClip,
2727 d2d_device_context_PopAxisAlignedClip,
2728 d2d_device_context_Clear,
2729 d2d_device_context_BeginDraw,
2730 d2d_device_context_EndDraw,
2731 d2d_device_context_GetPixelFormat,
2732 d2d_device_context_SetDpi,
2733 d2d_device_context_GetDpi,
2734 d2d_device_context_GetSize,
2735 d2d_device_context_GetPixelSize,
2736 d2d_device_context_GetMaximumBitmapSize,
2737 d2d_device_context_IsSupported,
2738 d2d_device_context_ID2D1DeviceContext_CreateBitmap,
2739 d2d_device_context_ID2D1DeviceContext_CreateBitmapFromWicBitmap,
2740 d2d_device_context_CreateColorContext,
2741 d2d_device_context_CreateColorContextFromFilename,
2742 d2d_device_context_CreateColorContextFromWicColorContext,
2743 d2d_device_context_CreateBitmapFromDxgiSurface,
2744 d2d_device_context_CreateEffect,
2745 d2d_device_context_ID2D1DeviceContext_CreateGradientStopCollection,
2746 d2d_device_context_CreateImageBrush,
2747 d2d_device_context_ID2D1DeviceContext_CreateBitmapBrush,
2748 d2d_device_context_CreateCommandList,
2749 d2d_device_context_IsDxgiFormatSupported,
2750 d2d_device_context_IsBufferPrecisionSupported,
2751 d2d_device_context_GetImageLocalBounds,
2752 d2d_device_context_GetImageWorldBounds,
2753 d2d_device_context_GetGlyphRunWorldBounds,
2754 d2d_device_context_GetDevice,
2755 d2d_device_context_SetTarget,
2756 d2d_device_context_GetTarget,
2757 d2d_device_context_SetRenderingControls,
2758 d2d_device_context_GetRenderingControls,
2759 d2d_device_context_SetPrimitiveBlend,
2760 d2d_device_context_GetPrimitiveBlend,
2761 d2d_device_context_SetUnitMode,
2762 d2d_device_context_GetUnitMode,
2763 d2d_device_context_ID2D1DeviceContext_DrawGlyphRun,
2764 d2d_device_context_DrawImage,
2765 d2d_device_context_DrawGdiMetafile,
2766 d2d_device_context_ID2D1DeviceContext_DrawBitmap,
2767 d2d_device_context_ID2D1DeviceContext_PushLayer,
2768 d2d_device_context_InvalidateEffectInputRectangle,
2769 d2d_device_context_GetEffectInvalidRectangleCount,
2770 d2d_device_context_GetEffectInvalidRectangles,
2771 d2d_device_context_GetEffectRequiredInputRectangles,
2772 d2d_device_context_ID2D1DeviceContext_FillOpacityMask,
2773 d2d_device_context_CreateFilledGeometryRealization,
2774 d2d_device_context_CreateStrokedGeometryRealization,
2775 d2d_device_context_DrawGeometryRealization,
2778 static inline struct d2d_device_context *impl_from_IDWriteTextRenderer(IDWriteTextRenderer *iface)
2780 return CONTAINING_RECORD(iface, struct d2d_device_context, IDWriteTextRenderer_iface);
2783 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_QueryInterface(IDWriteTextRenderer *iface, REFIID iid, void **out)
2785 TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
2787 if (IsEqualGUID(iid, &IID_IDWriteTextRenderer)
2788 || IsEqualGUID(iid, &IID_IDWritePixelSnapping)
2789 || IsEqualGUID(iid, &IID_IUnknown))
2791 IDWriteTextRenderer_AddRef(iface);
2792 *out = iface;
2793 return S_OK;
2796 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
2798 *out = NULL;
2799 return E_NOINTERFACE;
2802 static ULONG STDMETHODCALLTYPE d2d_text_renderer_AddRef(IDWriteTextRenderer *iface)
2804 struct d2d_device_context *render_target = impl_from_IDWriteTextRenderer(iface);
2806 TRACE("iface %p.\n", iface);
2808 return d2d_device_context_AddRef(&render_target->ID2D1DeviceContext1_iface);
2811 static ULONG STDMETHODCALLTYPE d2d_text_renderer_Release(IDWriteTextRenderer *iface)
2813 struct d2d_device_context *render_target = impl_from_IDWriteTextRenderer(iface);
2815 TRACE("iface %p.\n", iface);
2817 return d2d_device_context_Release(&render_target->ID2D1DeviceContext1_iface);
2820 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_IsPixelSnappingDisabled(IDWriteTextRenderer *iface,
2821 void *ctx, BOOL *disabled)
2823 struct d2d_draw_text_layout_ctx *context = ctx;
2825 TRACE("iface %p, ctx %p, disabled %p.\n", iface, ctx, disabled);
2827 *disabled = context->options & D2D1_DRAW_TEXT_OPTIONS_NO_SNAP;
2829 return S_OK;
2832 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_GetCurrentTransform(IDWriteTextRenderer *iface,
2833 void *ctx, DWRITE_MATRIX *transform)
2835 struct d2d_device_context *render_target = impl_from_IDWriteTextRenderer(iface);
2837 TRACE("iface %p, ctx %p, transform %p.\n", iface, ctx, transform);
2839 d2d_device_context_GetTransform(&render_target->ID2D1DeviceContext1_iface, (D2D1_MATRIX_3X2_F *)transform);
2841 return S_OK;
2844 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_GetPixelsPerDip(IDWriteTextRenderer *iface, void *ctx, float *ppd)
2846 struct d2d_device_context *render_target = impl_from_IDWriteTextRenderer(iface);
2848 TRACE("iface %p, ctx %p, ppd %p.\n", iface, ctx, ppd);
2850 *ppd = render_target->desc.dpiY / 96.0f;
2852 return S_OK;
2855 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_DrawGlyphRun(IDWriteTextRenderer *iface, void *ctx,
2856 float baseline_origin_x, float baseline_origin_y, DWRITE_MEASURING_MODE measuring_mode,
2857 const DWRITE_GLYPH_RUN *glyph_run, const DWRITE_GLYPH_RUN_DESCRIPTION *glyph_run_desc, IUnknown *effect)
2859 struct d2d_device_context *render_target = impl_from_IDWriteTextRenderer(iface);
2860 D2D1_POINT_2F baseline_origin = {baseline_origin_x, baseline_origin_y};
2861 struct d2d_draw_text_layout_ctx *context = ctx;
2862 BOOL color_font = FALSE;
2863 ID2D1Brush *brush;
2865 TRACE("iface %p, ctx %p, baseline_origin_x %.8e, baseline_origin_y %.8e, "
2866 "measuring_mode %#x, glyph_run %p, glyph_run_desc %p, effect %p.\n",
2867 iface, ctx, baseline_origin_x, baseline_origin_y,
2868 measuring_mode, glyph_run, glyph_run_desc, effect);
2870 if (context->options & ~(D2D1_DRAW_TEXT_OPTIONS_NO_SNAP | D2D1_DRAW_TEXT_OPTIONS_ENABLE_COLOR_FONT))
2871 FIXME("Ignoring options %#x.\n", context->options);
2873 brush = d2d_draw_get_text_brush(context, effect);
2875 TRACE("%s\n", debugstr_wn(glyph_run_desc->string, glyph_run_desc->stringLength));
2877 if (context->options & D2D1_DRAW_TEXT_OPTIONS_ENABLE_COLOR_FONT)
2879 IDWriteFontFace2 *fontface;
2881 if (SUCCEEDED(IDWriteFontFace_QueryInterface(glyph_run->fontFace,
2882 &IID_IDWriteFontFace2, (void **)&fontface)))
2884 color_font = IDWriteFontFace2_IsColorFont(fontface);
2885 IDWriteFontFace2_Release(fontface);
2889 if (color_font)
2891 IDWriteColorGlyphRunEnumerator *layers;
2892 IDWriteFactory2 *dwrite_factory;
2893 HRESULT hr;
2895 if (FAILED(hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, &IID_IDWriteFactory2,
2896 (IUnknown **)&dwrite_factory)))
2898 ERR("Failed to create dwrite factory, hr %#lx.\n", hr);
2899 ID2D1Brush_Release(brush);
2900 return hr;
2903 hr = IDWriteFactory2_TranslateColorGlyphRun(dwrite_factory, baseline_origin_x, baseline_origin_y,
2904 glyph_run, glyph_run_desc, measuring_mode, (DWRITE_MATRIX *)&render_target->drawing_state.transform, 0, &layers);
2905 IDWriteFactory2_Release(dwrite_factory);
2906 if (FAILED(hr))
2908 ERR("Failed to create colour glyph run enumerator, hr %#lx.\n", hr);
2909 ID2D1Brush_Release(brush);
2910 return hr;
2913 for (;;)
2915 const DWRITE_COLOR_GLYPH_RUN *color_run;
2916 ID2D1Brush *color_brush;
2917 D2D1_POINT_2F origin;
2918 BOOL has_run = FALSE;
2920 if (FAILED(hr = IDWriteColorGlyphRunEnumerator_MoveNext(layers, &has_run)))
2922 ERR("Failed to switch colour glyph layer, hr %#lx.\n", hr);
2923 break;
2926 if (!has_run)
2927 break;
2929 if (FAILED(hr = IDWriteColorGlyphRunEnumerator_GetCurrentRun(layers, &color_run)))
2931 ERR("Failed to get current colour run, hr %#lx.\n", hr);
2932 break;
2935 if (color_run->paletteIndex == 0xffff)
2936 color_brush = brush;
2937 else
2939 if (FAILED(hr = d2d_device_context_CreateSolidColorBrush(&render_target->ID2D1DeviceContext1_iface,
2940 &color_run->runColor, NULL, (ID2D1SolidColorBrush **)&color_brush)))
2942 ERR("Failed to create solid colour brush, hr %#lx.\n", hr);
2943 break;
2947 origin.x = color_run->baselineOriginX;
2948 origin.y = color_run->baselineOriginY;
2949 d2d_device_context_draw_glyph_run(render_target, origin, &color_run->glyphRun,
2950 color_run->glyphRunDescription, color_brush, measuring_mode);
2952 if (color_brush != brush)
2953 ID2D1Brush_Release(color_brush);
2956 IDWriteColorGlyphRunEnumerator_Release(layers);
2958 else
2959 d2d_device_context_draw_glyph_run(render_target, baseline_origin, glyph_run, glyph_run_desc,
2960 brush, measuring_mode);
2962 ID2D1Brush_Release(brush);
2964 return S_OK;
2967 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_DrawUnderline(IDWriteTextRenderer *iface, void *ctx,
2968 float baseline_origin_x, float baseline_origin_y, const DWRITE_UNDERLINE *underline, IUnknown *effect)
2970 struct d2d_device_context *render_target = impl_from_IDWriteTextRenderer(iface);
2971 const D2D1_MATRIX_3X2_F *m = &render_target->drawing_state.transform;
2972 struct d2d_draw_text_layout_ctx *context = ctx;
2973 D2D1_ANTIALIAS_MODE prev_antialias_mode;
2974 D2D1_POINT_2F start, end;
2975 ID2D1Brush *brush;
2976 float thickness;
2978 TRACE("iface %p, ctx %p, baseline_origin_x %.8e, baseline_origin_y %.8e, underline %p, effect %p\n",
2979 iface, ctx, baseline_origin_x, baseline_origin_y, underline, effect);
2981 /* minimal thickness in DIPs that will result in at least 1 pixel thick line */
2982 thickness = max(96.0f / (render_target->desc.dpiY * sqrtf(m->_21 * m->_21 + m->_22 * m->_22)),
2983 underline->thickness);
2985 brush = d2d_draw_get_text_brush(context, effect);
2987 start.x = baseline_origin_x;
2988 start.y = baseline_origin_y + underline->offset + thickness / 2.0f;
2989 end.x = start.x + underline->width;
2990 end.y = start.y;
2991 prev_antialias_mode = d2d_device_context_set_aa_mode_from_text_aa_mode(render_target);
2992 d2d_device_context_DrawLine(&render_target->ID2D1DeviceContext1_iface, start, end, brush, thickness, NULL);
2993 render_target->drawing_state.antialiasMode = prev_antialias_mode;
2995 ID2D1Brush_Release(brush);
2997 return S_OK;
3000 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_DrawStrikethrough(IDWriteTextRenderer *iface, void *ctx,
3001 float baseline_origin_x, float baseline_origin_y, const DWRITE_STRIKETHROUGH *strikethrough, IUnknown *effect)
3003 struct d2d_device_context *render_target = impl_from_IDWriteTextRenderer(iface);
3004 const D2D1_MATRIX_3X2_F *m = &render_target->drawing_state.transform;
3005 struct d2d_draw_text_layout_ctx *context = ctx;
3006 D2D1_ANTIALIAS_MODE prev_antialias_mode;
3007 D2D1_POINT_2F start, end;
3008 ID2D1Brush *brush;
3009 float thickness;
3011 TRACE("iface %p, ctx %p, baseline_origin_x %.8e, baseline_origin_y %.8e, strikethrough %p, effect %p.\n",
3012 iface, ctx, baseline_origin_x, baseline_origin_y, strikethrough, effect);
3014 /* minimal thickness in DIPs that will result in at least 1 pixel thick line */
3015 thickness = max(96.0f / (render_target->desc.dpiY * sqrtf(m->_21 * m->_21 + m->_22 * m->_22)),
3016 strikethrough->thickness);
3018 brush = d2d_draw_get_text_brush(context, effect);
3020 start.x = baseline_origin_x;
3021 start.y = baseline_origin_y + strikethrough->offset + thickness / 2.0f;
3022 end.x = start.x + strikethrough->width;
3023 end.y = start.y;
3024 prev_antialias_mode = d2d_device_context_set_aa_mode_from_text_aa_mode(render_target);
3025 d2d_device_context_DrawLine(&render_target->ID2D1DeviceContext1_iface, start, end, brush, thickness, NULL);
3026 render_target->drawing_state.antialiasMode = prev_antialias_mode;
3028 ID2D1Brush_Release(brush);
3030 return S_OK;
3033 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_DrawInlineObject(IDWriteTextRenderer *iface, void *ctx,
3034 float origin_x, float origin_y, IDWriteInlineObject *object, BOOL is_sideways, BOOL is_rtl, IUnknown *effect)
3036 struct d2d_draw_text_layout_ctx *context = ctx;
3037 ID2D1Brush *brush;
3038 HRESULT hr;
3040 TRACE("iface %p, ctx %p, origin_x %.8e, origin_y %.8e, object %p, is_sideways %#x, is_rtl %#x, effect %p.\n",
3041 iface, ctx, origin_x, origin_y, object, is_sideways, is_rtl, effect);
3043 /* Inline objects may not pass effects all the way down, when using layout object internally for example.
3044 This is how default trimming sign object in DirectWrite works - it does not use effect passed to Draw(),
3045 and resulting DrawGlyphRun() is always called with NULL effect, however original effect is used and correct
3046 brush is selected at Direct2D level. */
3047 brush = context->brush;
3048 context->brush = d2d_draw_get_text_brush(context, effect);
3050 hr = IDWriteInlineObject_Draw(object, ctx, iface, origin_x, origin_y, is_sideways, is_rtl, effect);
3052 ID2D1Brush_Release(context->brush);
3053 context->brush = brush;
3055 return hr;
3058 static const struct IDWriteTextRendererVtbl d2d_text_renderer_vtbl =
3060 d2d_text_renderer_QueryInterface,
3061 d2d_text_renderer_AddRef,
3062 d2d_text_renderer_Release,
3063 d2d_text_renderer_IsPixelSnappingDisabled,
3064 d2d_text_renderer_GetCurrentTransform,
3065 d2d_text_renderer_GetPixelsPerDip,
3066 d2d_text_renderer_DrawGlyphRun,
3067 d2d_text_renderer_DrawUnderline,
3068 d2d_text_renderer_DrawStrikethrough,
3069 d2d_text_renderer_DrawInlineObject,
3072 static inline struct d2d_device_context *impl_from_ID2D1GdiInteropRenderTarget(ID2D1GdiInteropRenderTarget *iface)
3074 return CONTAINING_RECORD(iface, struct d2d_device_context, ID2D1GdiInteropRenderTarget_iface);
3077 static HRESULT STDMETHODCALLTYPE d2d_gdi_interop_render_target_QueryInterface(ID2D1GdiInteropRenderTarget *iface,
3078 REFIID iid, void **out)
3080 struct d2d_device_context *render_target = impl_from_ID2D1GdiInteropRenderTarget(iface);
3082 TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
3084 return IUnknown_QueryInterface(render_target->outer_unknown, iid, out);
3087 static ULONG STDMETHODCALLTYPE d2d_gdi_interop_render_target_AddRef(ID2D1GdiInteropRenderTarget *iface)
3089 struct d2d_device_context *render_target = impl_from_ID2D1GdiInteropRenderTarget(iface);
3091 TRACE("iface %p.\n", iface);
3093 return IUnknown_AddRef(render_target->outer_unknown);
3096 static ULONG STDMETHODCALLTYPE d2d_gdi_interop_render_target_Release(ID2D1GdiInteropRenderTarget *iface)
3098 struct d2d_device_context *render_target = impl_from_ID2D1GdiInteropRenderTarget(iface);
3100 TRACE("iface %p.\n", iface);
3102 return IUnknown_Release(render_target->outer_unknown);
3105 static HRESULT d2d_gdi_interop_get_surface(struct d2d_device_context *context, IDXGISurface1 **surface)
3107 ID3D11Resource *resource;
3108 HRESULT hr;
3110 if (context->target.type != D2D_TARGET_BITMAP)
3112 FIXME("Unimplemented for target type %u.\n", context->target.type);
3113 return E_NOTIMPL;
3116 if (!(context->target.bitmap->options & D2D1_BITMAP_OPTIONS_GDI_COMPATIBLE))
3117 return D2DERR_TARGET_NOT_GDI_COMPATIBLE;
3119 ID3D11RenderTargetView_GetResource(context->target.bitmap->rtv, &resource);
3120 hr = ID3D11Resource_QueryInterface(resource, &IID_IDXGISurface1, (void **)surface);
3121 ID3D11Resource_Release(resource);
3122 if (FAILED(hr))
3124 *surface = NULL;
3125 WARN("Failed to get DXGI surface, %#lx.\n", hr);
3126 return hr;
3129 return hr;
3132 static HRESULT STDMETHODCALLTYPE d2d_gdi_interop_render_target_GetDC(ID2D1GdiInteropRenderTarget *iface,
3133 D2D1_DC_INITIALIZE_MODE mode, HDC *dc)
3135 struct d2d_device_context *render_target = impl_from_ID2D1GdiInteropRenderTarget(iface);
3136 IDXGISurface1 *surface;
3137 HRESULT hr;
3139 TRACE("iface %p, mode %d, dc %p.\n", iface, mode, dc);
3141 *dc = NULL;
3143 if (render_target->target.hdc)
3144 return D2DERR_WRONG_STATE;
3146 if (FAILED(hr = d2d_gdi_interop_get_surface(render_target, &surface)))
3147 return hr;
3149 hr = IDXGISurface1_GetDC(surface, mode != D2D1_DC_INITIALIZE_MODE_COPY, &render_target->target.hdc);
3150 IDXGISurface1_Release(surface);
3152 if (SUCCEEDED(hr))
3153 *dc = render_target->target.hdc;
3155 return hr;
3158 static HRESULT STDMETHODCALLTYPE d2d_gdi_interop_render_target_ReleaseDC(ID2D1GdiInteropRenderTarget *iface,
3159 const RECT *update)
3161 struct d2d_device_context *render_target = impl_from_ID2D1GdiInteropRenderTarget(iface);
3162 IDXGISurface1 *surface;
3163 RECT update_rect;
3164 HRESULT hr;
3166 TRACE("iface %p, update rect %s.\n", iface, wine_dbgstr_rect(update));
3168 if (!render_target->target.hdc)
3169 return D2DERR_WRONG_STATE;
3171 if (FAILED(hr = d2d_gdi_interop_get_surface(render_target, &surface)))
3172 return hr;
3174 render_target->target.hdc = NULL;
3175 if (update)
3176 update_rect = *update;
3177 hr = IDXGISurface1_ReleaseDC(surface, update ? &update_rect : NULL);
3178 IDXGISurface1_Release(surface);
3180 return hr;
3183 static const struct ID2D1GdiInteropRenderTargetVtbl d2d_gdi_interop_render_target_vtbl =
3185 d2d_gdi_interop_render_target_QueryInterface,
3186 d2d_gdi_interop_render_target_AddRef,
3187 d2d_gdi_interop_render_target_Release,
3188 d2d_gdi_interop_render_target_GetDC,
3189 d2d_gdi_interop_render_target_ReleaseDC,
3192 static HRESULT d2d_device_context_init(struct d2d_device_context *render_target,
3193 struct d2d_device *device, IUnknown *outer_unknown, const struct d2d_device_context_ops *ops)
3195 D3D11_SUBRESOURCE_DATA buffer_data;
3196 struct d2d_device *device_impl;
3197 IDWriteFactory *dwrite_factory;
3198 D3D11_RASTERIZER_DESC rs_desc;
3199 D3D11_BUFFER_DESC buffer_desc;
3200 unsigned int i;
3201 HRESULT hr;
3203 static const D3D11_INPUT_ELEMENT_DESC il_desc_outline[] =
3205 {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0},
3206 {"PREV", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 8, D3D11_INPUT_PER_VERTEX_DATA, 0},
3207 {"NEXT", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 16, D3D11_INPUT_PER_VERTEX_DATA, 0},
3209 static const D3D11_INPUT_ELEMENT_DESC il_desc_curve_outline[] =
3211 {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0},
3212 {"P", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 8, D3D11_INPUT_PER_VERTEX_DATA, 0},
3213 {"P", 1, DXGI_FORMAT_R32G32_FLOAT, 0, 16, D3D11_INPUT_PER_VERTEX_DATA, 0},
3214 {"P", 2, DXGI_FORMAT_R32G32_FLOAT, 0, 24, D3D11_INPUT_PER_VERTEX_DATA, 0},
3215 {"PREV", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 32, D3D11_INPUT_PER_VERTEX_DATA, 0},
3216 {"NEXT", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 40, D3D11_INPUT_PER_VERTEX_DATA, 0},
3218 static const D3D11_INPUT_ELEMENT_DESC il_desc_triangle[] =
3220 {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0},
3222 static const D3D11_INPUT_ELEMENT_DESC il_desc_curve[] =
3224 {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0},
3225 {"TEXCOORD", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 8, D3D11_INPUT_PER_VERTEX_DATA, 0},
3227 static const DWORD vs_code_outline[] =
3229 #if 0
3230 float3x2 transform_geometry;
3231 float stroke_width;
3232 float4 transform_rtx;
3233 float4 transform_rty;
3235 struct output
3237 float2 p : WORLD_POSITION;
3238 float4 b : BEZIER;
3239 nointerpolation float2x2 stroke_transform : STROKE_TRANSFORM;
3240 float4 position : SV_POSITION;
3243 /* The lines PₚᵣₑᵥP₀ and P₀Pₙₑₓₜ, both offset by ±½w, intersect each other at:
3245 * Pᵢ = P₀ ± w · ½q⃑ᵢ.
3247 * Where:
3249 * q⃑ᵢ = q̂ₚᵣₑᵥ⊥ + tan(½θ) · -q̂ₚᵣₑᵥ
3250 * θ = ∠PₚᵣₑᵥP₀Pₙₑₓₜ
3251 * q⃑ₚᵣₑᵥ = P₀ - Pₚᵣₑᵥ */
3252 void main(float2 position : POSITION, float2 prev : PREV, float2 next : NEXT, out struct output o)
3254 float2 q_prev, q_next, v_p, q_i;
3255 float2x2 geom;
3256 float l;
3258 o.stroke_transform = float2x2(transform_rtx.xy, transform_rty.xy) * stroke_width * 0.5f;
3260 geom = float2x2(transform_geometry._11_21, transform_geometry._12_22);
3261 q_prev = normalize(mul(geom, prev));
3262 q_next = normalize(mul(geom, next));
3264 /* tan(½θ) = sin(θ) / (1 + cos(θ))
3265 * = (q̂ₚᵣₑᵥ⊥ · q̂ₙₑₓₜ) / (1 + (q̂ₚᵣₑᵥ · q̂ₙₑₓₜ)) */
3266 v_p = float2(-q_prev.y, q_prev.x);
3267 l = -dot(v_p, q_next) / (1.0f + dot(q_prev, q_next));
3268 q_i = l * q_prev + v_p;
3270 o.b = float4(0.0, 0.0, 0.0, 0.0);
3272 o.p = mul(float3(position, 1.0f), transform_geometry) + stroke_width * 0.5f * q_i;
3273 position = mul(float2x3(transform_rtx.xyz, transform_rty.xyz), float3(o.p, 1.0f))
3274 * float2(transform_rtx.w, transform_rty.w);
3275 o.position = float4(position + float2(-1.0f, 1.0f), 0.0f, 1.0f);
3277 #endif
3278 0x43425844, 0xfb16cd75, 0xf5ec3e80, 0xceacf250, 0x91d29d18, 0x00000001, 0x00000608, 0x00000003,
3279 0x0000002c, 0x00000098, 0x00000154, 0x4e475349, 0x00000064, 0x00000003, 0x00000008, 0x00000050,
3280 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000303, 0x00000059, 0x00000000, 0x00000000,
3281 0x00000003, 0x00000001, 0x00000303, 0x0000005e, 0x00000000, 0x00000000, 0x00000003, 0x00000002,
3282 0x00000303, 0x49534f50, 0x4e4f4954, 0x45525000, 0x454e0056, 0xab005458, 0x4e47534f, 0x000000b4,
3283 0x00000005, 0x00000008, 0x00000080, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000c03,
3284 0x0000008f, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x0000000f, 0x00000096, 0x00000000,
3285 0x00000000, 0x00000003, 0x00000002, 0x00000c03, 0x00000096, 0x00000001, 0x00000000, 0x00000003,
3286 0x00000003, 0x00000c03, 0x000000a7, 0x00000000, 0x00000001, 0x00000003, 0x00000004, 0x0000000f,
3287 0x4c524f57, 0x4f505f44, 0x49544953, 0x42004e4f, 0x45495a45, 0x54530052, 0x454b4f52, 0x4152545f,
3288 0x4f46534e, 0x53004d52, 0x4f505f56, 0x49544953, 0xab004e4f, 0x52444853, 0x000004ac, 0x00010040,
3289 0x0000012b, 0x04000059, 0x00208e46, 0x00000000, 0x00000004, 0x0300005f, 0x00101032, 0x00000000,
3290 0x0300005f, 0x00101032, 0x00000001, 0x0300005f, 0x00101032, 0x00000002, 0x03000065, 0x00102032,
3291 0x00000000, 0x03000065, 0x001020f2, 0x00000001, 0x03000065, 0x00102032, 0x00000002, 0x03000065,
3292 0x00102032, 0x00000003, 0x04000067, 0x001020f2, 0x00000004, 0x00000001, 0x02000068, 0x00000003,
3293 0x0800000f, 0x00100012, 0x00000000, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000002,
3294 0x0800000f, 0x00100022, 0x00000000, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000002,
3295 0x0700000f, 0x00100042, 0x00000000, 0x00100046, 0x00000000, 0x00100046, 0x00000000, 0x05000044,
3296 0x00100042, 0x00000000, 0x0010002a, 0x00000000, 0x07000038, 0x00100032, 0x00000000, 0x00100aa6,
3297 0x00000000, 0x00100046, 0x00000000, 0x0800000f, 0x00100012, 0x00000001, 0x00208046, 0x00000000,
3298 0x00000000, 0x00101046, 0x00000001, 0x0800000f, 0x00100022, 0x00000001, 0x00208046, 0x00000000,
3299 0x00000001, 0x00101046, 0x00000001, 0x0700000f, 0x00100042, 0x00000000, 0x00100046, 0x00000001,
3300 0x00100046, 0x00000001, 0x05000044, 0x00100042, 0x00000000, 0x0010002a, 0x00000000, 0x07000038,
3301 0x00100032, 0x00000001, 0x00100aa6, 0x00000000, 0x00100046, 0x00000001, 0x06000036, 0x001000c2,
3302 0x00000001, 0x80100556, 0x00000041, 0x00000001, 0x0700000f, 0x00100042, 0x00000000, 0x00100a26,
3303 0x00000001, 0x00100046, 0x00000000, 0x0700000f, 0x00100012, 0x00000000, 0x00100046, 0x00000001,
3304 0x00100046, 0x00000000, 0x07000000, 0x00100012, 0x00000000, 0x0010000a, 0x00000000, 0x00004001,
3305 0x3f800000, 0x0800000e, 0x00100012, 0x00000000, 0x8010002a, 0x00000041, 0x00000000, 0x0010000a,
3306 0x00000000, 0x09000032, 0x00100032, 0x00000000, 0x00100006, 0x00000000, 0x00100046, 0x00000001,
3307 0x00100f36, 0x00000001, 0x08000038, 0x00100042, 0x00000000, 0x0020803a, 0x00000000, 0x00000001,
3308 0x00004001, 0x3f000000, 0x05000036, 0x00100032, 0x00000001, 0x00101046, 0x00000000, 0x05000036,
3309 0x00100042, 0x00000001, 0x00004001, 0x3f800000, 0x08000010, 0x00100012, 0x00000002, 0x00100246,
3310 0x00000001, 0x00208246, 0x00000000, 0x00000000, 0x08000010, 0x00100022, 0x00000002, 0x00100246,
3311 0x00000001, 0x00208246, 0x00000000, 0x00000001, 0x09000032, 0x00100032, 0x00000000, 0x00100aa6,
3312 0x00000000, 0x00100046, 0x00000000, 0x00100046, 0x00000002, 0x05000036, 0x00102032, 0x00000000,
3313 0x00100046, 0x00000000, 0x08000036, 0x001020f2, 0x00000001, 0x00004002, 0x00000000, 0x00000000,
3314 0x00000000, 0x00000000, 0x06000036, 0x00100032, 0x00000001, 0x00208046, 0x00000000, 0x00000002,
3315 0x06000036, 0x001000c2, 0x00000001, 0x00208406, 0x00000000, 0x00000003, 0x08000038, 0x001000f2,
3316 0x00000001, 0x00100e46, 0x00000001, 0x00208ff6, 0x00000000, 0x00000001, 0x0a000038, 0x001000f2,
3317 0x00000001, 0x00100e46, 0x00000001, 0x00004002, 0x3f000000, 0x3f000000, 0x3f000000, 0x3f000000,
3318 0x05000036, 0x00102032, 0x00000002, 0x00100086, 0x00000001, 0x05000036, 0x00102032, 0x00000003,
3319 0x001005d6, 0x00000001, 0x05000036, 0x00100042, 0x00000000, 0x00004001, 0x3f800000, 0x08000010,
3320 0x00100082, 0x00000000, 0x00208246, 0x00000000, 0x00000002, 0x00100246, 0x00000000, 0x08000010,
3321 0x00100012, 0x00000000, 0x00208246, 0x00000000, 0x00000003, 0x00100246, 0x00000000, 0x08000038,
3322 0x00100022, 0x00000000, 0x0010000a, 0x00000000, 0x0020803a, 0x00000000, 0x00000003, 0x08000038,
3323 0x00100012, 0x00000000, 0x0010003a, 0x00000000, 0x0020803a, 0x00000000, 0x00000002, 0x0a000000,
3324 0x00102032, 0x00000004, 0x00100046, 0x00000000, 0x00004002, 0xbf800000, 0x3f800000, 0x00000000,
3325 0x00000000, 0x08000036, 0x001020c2, 0x00000004, 0x00004002, 0x00000000, 0x00000000, 0x00000000,
3326 0x3f800000, 0x0100003e,
3328 /* ⎡p0.x p0.y 1⎤
3329 * A = ⎢p1.x p1.y 1⎥
3330 * ⎣p2.x p2.y 1⎦
3332 * ⎡0 0⎤
3333 * B = ⎢½ 0⎥
3334 * ⎣1 1⎦
3336 * A' = ⎡p1.x-p0.x p1.y-p0.y⎤
3337 * ⎣p2.x-p0.x p2.y-p0.y⎦
3339 * B' = ⎡½ 0⎤
3340 * ⎣1 1⎦
3342 * A'T = B'
3343 * T = A'⁻¹B'
3345 static const DWORD vs_code_bezier_outline[] =
3347 #if 0
3348 float3x2 transform_geometry;
3349 float stroke_width;
3350 float4 transform_rtx;
3351 float4 transform_rty;
3353 struct output
3355 float2 p : WORLD_POSITION;
3356 float4 b : BEZIER;
3357 nointerpolation float2x2 stroke_transform : STROKE_TRANSFORM;
3358 float4 position : SV_POSITION;
3361 void main(float2 position : POSITION, float2 p0 : P0, float2 p1 : P1, float2 p2 : P2,
3362 float2 prev : PREV, float2 next : NEXT, out struct output o)
3364 float2 q_prev, q_next, v_p, q_i, p;
3365 float2x2 geom, rt;
3366 float l;
3368 geom = float2x2(transform_geometry._11_21, transform_geometry._12_22);
3369 rt = float2x2(transform_rtx.xy, transform_rty.xy);
3370 o.stroke_transform = rt * stroke_width * 0.5f;
3372 p = mul(geom, position);
3373 p0 = mul(geom, p0);
3374 p1 = mul(geom, p1);
3375 p2 = mul(geom, p2);
3377 p -= p0;
3378 p1 -= p0;
3379 p2 -= p0;
3381 q_prev = normalize(mul(geom, prev));
3382 q_next = normalize(mul(geom, next));
3384 v_p = float2(-q_prev.y, q_prev.x);
3385 l = -dot(v_p, q_next) / (1.0f + dot(q_prev, q_next));
3386 q_i = l * q_prev + v_p;
3387 p += 0.5f * stroke_width * q_i;
3389 v_p = mul(rt, p2);
3390 v_p = normalize(float2(-v_p.y, v_p.x));
3391 if (abs(dot(mul(rt, p1), v_p)) < 1.0f)
3393 o.b.xzw = float3(0.0f, 0.0f, 0.0f);
3394 o.b.y = dot(mul(rt, p), v_p);
3396 else
3398 o.b.zw = sign(dot(mul(rt, p1), v_p)) * v_p;
3399 v_p = -float2(-p.y, p.x) / dot(float2(-p1.y, p1.x), p2);
3400 o.b.x = dot(v_p, p1 - 0.5f * p2);
3401 o.b.y = dot(v_p, p1);
3404 o.p = mul(float3(position, 1.0f), transform_geometry) + 0.5f * stroke_width * q_i;
3405 position = mul(float2x3(transform_rtx.xyz, transform_rty.xyz), float3(o.p, 1.0f))
3406 * float2(transform_rtx.w, transform_rty.w);
3407 o.position = float4(position + float2(-1.0f, 1.0f), 0.0f, 1.0f);
3409 #endif
3410 0x43425844, 0x356a0c5f, 0x8e4ba153, 0xe52cf793, 0xa6b774ea, 0x00000001, 0x00000afc, 0x00000003,
3411 0x0000002c, 0x000000e4, 0x000001a0, 0x4e475349, 0x000000b0, 0x00000006, 0x00000008, 0x00000098,
3412 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000303, 0x000000a1, 0x00000000, 0x00000000,
3413 0x00000003, 0x00000001, 0x00000303, 0x000000a1, 0x00000001, 0x00000000, 0x00000003, 0x00000002,
3414 0x00000303, 0x000000a1, 0x00000002, 0x00000000, 0x00000003, 0x00000003, 0x00000303, 0x000000a3,
3415 0x00000000, 0x00000000, 0x00000003, 0x00000004, 0x00000303, 0x000000a8, 0x00000000, 0x00000000,
3416 0x00000003, 0x00000005, 0x00000303, 0x49534f50, 0x4e4f4954, 0x50005000, 0x00564552, 0x5458454e,
3417 0xababab00, 0x4e47534f, 0x000000b4, 0x00000005, 0x00000008, 0x00000080, 0x00000000, 0x00000000,
3418 0x00000003, 0x00000000, 0x00000c03, 0x0000008f, 0x00000000, 0x00000000, 0x00000003, 0x00000001,
3419 0x0000000f, 0x00000096, 0x00000000, 0x00000000, 0x00000003, 0x00000002, 0x00000c03, 0x00000096,
3420 0x00000001, 0x00000000, 0x00000003, 0x00000003, 0x00000c03, 0x000000a7, 0x00000000, 0x00000001,
3421 0x00000003, 0x00000004, 0x0000000f, 0x4c524f57, 0x4f505f44, 0x49544953, 0x42004e4f, 0x45495a45,
3422 0x54530052, 0x454b4f52, 0x4152545f, 0x4f46534e, 0x53004d52, 0x4f505f56, 0x49544953, 0xab004e4f,
3423 0x52444853, 0x00000954, 0x00010040, 0x00000255, 0x04000059, 0x00208e46, 0x00000000, 0x00000004,
3424 0x0300005f, 0x00101032, 0x00000000, 0x0300005f, 0x00101032, 0x00000001, 0x0300005f, 0x00101032,
3425 0x00000002, 0x0300005f, 0x00101032, 0x00000003, 0x0300005f, 0x00101032, 0x00000004, 0x0300005f,
3426 0x00101032, 0x00000005, 0x03000065, 0x00102032, 0x00000000, 0x03000065, 0x001020f2, 0x00000001,
3427 0x03000065, 0x00102032, 0x00000002, 0x03000065, 0x00102032, 0x00000003, 0x04000067, 0x001020f2,
3428 0x00000004, 0x00000001, 0x02000068, 0x00000006, 0x0800000f, 0x00100012, 0x00000000, 0x00208046,
3429 0x00000000, 0x00000000, 0x00101046, 0x00000005, 0x0800000f, 0x00100022, 0x00000000, 0x00208046,
3430 0x00000000, 0x00000001, 0x00101046, 0x00000005, 0x0700000f, 0x00100042, 0x00000000, 0x00100046,
3431 0x00000000, 0x00100046, 0x00000000, 0x05000044, 0x00100042, 0x00000000, 0x0010002a, 0x00000000,
3432 0x07000038, 0x00100032, 0x00000000, 0x00100aa6, 0x00000000, 0x00100046, 0x00000000, 0x0800000f,
3433 0x00100012, 0x00000001, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000004, 0x0800000f,
3434 0x00100022, 0x00000001, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000004, 0x0700000f,
3435 0x00100042, 0x00000000, 0x00100046, 0x00000001, 0x00100046, 0x00000001, 0x05000044, 0x00100042,
3436 0x00000000, 0x0010002a, 0x00000000, 0x07000038, 0x00100032, 0x00000001, 0x00100aa6, 0x00000000,
3437 0x00100046, 0x00000001, 0x06000036, 0x001000c2, 0x00000001, 0x80100556, 0x00000041, 0x00000001,
3438 0x0700000f, 0x00100042, 0x00000000, 0x00100a26, 0x00000001, 0x00100046, 0x00000000, 0x0700000f,
3439 0x00100012, 0x00000000, 0x00100046, 0x00000001, 0x00100046, 0x00000000, 0x07000000, 0x00100012,
3440 0x00000000, 0x0010000a, 0x00000000, 0x00004001, 0x3f800000, 0x0800000e, 0x00100012, 0x00000000,
3441 0x8010002a, 0x00000041, 0x00000000, 0x0010000a, 0x00000000, 0x09000032, 0x00100032, 0x00000000,
3442 0x00100006, 0x00000000, 0x00100046, 0x00000001, 0x00100f36, 0x00000001, 0x05000036, 0x00100032,
3443 0x00000001, 0x00101046, 0x00000000, 0x05000036, 0x00100042, 0x00000001, 0x00004001, 0x3f800000,
3444 0x08000010, 0x00100012, 0x00000002, 0x00100246, 0x00000001, 0x00208246, 0x00000000, 0x00000000,
3445 0x08000010, 0x00100022, 0x00000002, 0x00100246, 0x00000001, 0x00208246, 0x00000000, 0x00000001,
3446 0x08000038, 0x00100042, 0x00000000, 0x0020803a, 0x00000000, 0x00000001, 0x00004001, 0x3f000000,
3447 0x09000032, 0x00100032, 0x00000001, 0x00100aa6, 0x00000000, 0x00100046, 0x00000000, 0x00100046,
3448 0x00000002, 0x05000036, 0x00102032, 0x00000000, 0x00100046, 0x00000001, 0x0800000f, 0x00100012,
3449 0x00000002, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000000, 0x0800000f, 0x00100022,
3450 0x00000002, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000000, 0x0800000f, 0x00100012,
3451 0x00000003, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000001, 0x0800000f, 0x00100022,
3452 0x00000003, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000001, 0x08000000, 0x00100032,
3453 0x00000002, 0x00100046, 0x00000002, 0x80100046, 0x00000041, 0x00000003, 0x09000032, 0x00100032,
3454 0x00000000, 0x00100aa6, 0x00000000, 0x00100046, 0x00000000, 0x00100046, 0x00000002, 0x0800000f,
3455 0x00100012, 0x00000002, 0x00208046, 0x00000000, 0x00000002, 0x00100046, 0x00000000, 0x0800000f,
3456 0x00100022, 0x00000002, 0x00208046, 0x00000000, 0x00000003, 0x00100046, 0x00000000, 0x0800000f,
3457 0x00100012, 0x00000004, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000003, 0x0800000f,
3458 0x00100022, 0x00000004, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000003, 0x08000000,
3459 0x001000c2, 0x00000002, 0x80100406, 0x00000041, 0x00000003, 0x00100406, 0x00000004, 0x0800000f,
3460 0x00100082, 0x00000000, 0x00208046, 0x00000000, 0x00000003, 0x00100ae6, 0x00000002, 0x06000036,
3461 0x00100042, 0x00000003, 0x8010003a, 0x00000041, 0x00000000, 0x0800000f, 0x00100082, 0x00000003,
3462 0x00208046, 0x00000000, 0x00000002, 0x00100ae6, 0x00000002, 0x0700000f, 0x00100082, 0x00000000,
3463 0x00100ae6, 0x00000003, 0x00100ae6, 0x00000003, 0x05000044, 0x00100082, 0x00000000, 0x0010003a,
3464 0x00000000, 0x07000038, 0x001000c2, 0x00000003, 0x00100ff6, 0x00000000, 0x00100ea6, 0x00000003,
3465 0x0700000f, 0x00100022, 0x00000004, 0x00100046, 0x00000002, 0x00100ae6, 0x00000003, 0x06000036,
3466 0x00100042, 0x00000000, 0x8010001a, 0x00000041, 0x00000000, 0x0800000f, 0x00100012, 0x00000002,
3467 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000002, 0x0800000f, 0x00100022, 0x00000002,
3468 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000002, 0x08000000, 0x00100032, 0x00000005,
3469 0x80100046, 0x00000041, 0x00000003, 0x00100046, 0x00000002, 0x06000036, 0x00100042, 0x00000005,
3470 0x8010001a, 0x00000041, 0x00000005, 0x0700000f, 0x00100022, 0x00000000, 0x00100a26, 0x00000005,
3471 0x00100ae6, 0x00000002, 0x0d000032, 0x00100032, 0x00000002, 0x80100ae6, 0x00000041, 0x00000002,
3472 0x00004002, 0x3f000000, 0x3f000000, 0x00000000, 0x00000000, 0x00100046, 0x00000005, 0x0800000e,
3473 0x00100032, 0x00000000, 0x80100a26, 0x00000041, 0x00000000, 0x00100556, 0x00000000, 0x0700000f,
3474 0x00100012, 0x00000002, 0x00100046, 0x00000000, 0x00100046, 0x00000002, 0x0700000f, 0x00100022,
3475 0x00000002, 0x00100046, 0x00000000, 0x00100046, 0x00000005, 0x0800000f, 0x00100012, 0x00000000,
3476 0x00208046, 0x00000000, 0x00000002, 0x00100046, 0x00000005, 0x0800000f, 0x00100022, 0x00000000,
3477 0x00208046, 0x00000000, 0x00000003, 0x00100046, 0x00000005, 0x0700000f, 0x00100012, 0x00000000,
3478 0x00100046, 0x00000000, 0x00100ae6, 0x00000003, 0x07000031, 0x00100022, 0x00000000, 0x00004001,
3479 0x00000000, 0x0010000a, 0x00000000, 0x07000031, 0x00100042, 0x00000000, 0x0010000a, 0x00000000,
3480 0x00004001, 0x00000000, 0x08000031, 0x00100012, 0x00000000, 0x8010000a, 0x00000081, 0x00000000,
3481 0x00004001, 0x3f800000, 0x0800001e, 0x00100022, 0x00000000, 0x8010001a, 0x00000041, 0x00000000,
3482 0x0010002a, 0x00000000, 0x0500002b, 0x00100022, 0x00000000, 0x0010001a, 0x00000000, 0x07000038,
3483 0x001000c2, 0x00000002, 0x00100ea6, 0x00000003, 0x00100556, 0x00000000, 0x08000036, 0x001000d2,
3484 0x00000004, 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x09000037, 0x001020f2,
3485 0x00000001, 0x00100006, 0x00000000, 0x00100e46, 0x00000004, 0x00100e46, 0x00000002, 0x06000036,
3486 0x00100032, 0x00000000, 0x00208046, 0x00000000, 0x00000002, 0x06000036, 0x001000c2, 0x00000000,
3487 0x00208406, 0x00000000, 0x00000003, 0x08000038, 0x001000f2, 0x00000000, 0x00100e46, 0x00000000,
3488 0x00208ff6, 0x00000000, 0x00000001, 0x0a000038, 0x001000f2, 0x00000000, 0x00100e46, 0x00000000,
3489 0x00004002, 0x3f000000, 0x3f000000, 0x3f000000, 0x3f000000, 0x05000036, 0x00102032, 0x00000002,
3490 0x00100086, 0x00000000, 0x05000036, 0x00102032, 0x00000003, 0x001005d6, 0x00000000, 0x05000036,
3491 0x00100042, 0x00000001, 0x00004001, 0x3f800000, 0x08000010, 0x00100012, 0x00000000, 0x00208246,
3492 0x00000000, 0x00000002, 0x00100246, 0x00000001, 0x08000010, 0x00100022, 0x00000000, 0x00208246,
3493 0x00000000, 0x00000003, 0x00100246, 0x00000001, 0x08000038, 0x00100022, 0x00000001, 0x0010001a,
3494 0x00000000, 0x0020803a, 0x00000000, 0x00000003, 0x08000038, 0x00100012, 0x00000001, 0x0010000a,
3495 0x00000000, 0x0020803a, 0x00000000, 0x00000002, 0x0a000000, 0x00102032, 0x00000004, 0x00100046,
3496 0x00000001, 0x00004002, 0xbf800000, 0x3f800000, 0x00000000, 0x00000000, 0x08000036, 0x001020c2,
3497 0x00000004, 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, 0x0100003e,
3499 /* ⎡p0.x p0.y 1⎤
3500 * A = ⎢p1.x p1.y 1⎥
3501 * ⎣p2.x p2.y 1⎦
3503 * ⎡1 0⎤
3504 * B = ⎢1 1⎥
3505 * ⎣0 1⎦
3507 * A' = ⎡p1.x-p0.x p1.y-p0.y⎤
3508 * ⎣p2.x-p0.x p2.y-p0.y⎦
3510 * B' = ⎡ 0 1⎤
3511 * ⎣-1 1⎦
3513 * A'T = B'
3514 * T = A'⁻¹B' = (B'⁻¹A')⁻¹
3516 static const DWORD vs_code_arc_outline[] =
3518 #if 0
3519 float3x2 transform_geometry;
3520 float stroke_width;
3521 float4 transform_rtx;
3522 float4 transform_rty;
3524 struct output
3526 float2 p : WORLD_POSITION;
3527 float4 b : BEZIER;
3528 nointerpolation float2x2 stroke_transform : STROKE_TRANSFORM;
3529 float4 position : SV_POSITION;
3532 void main(float2 position : POSITION, float2 p0 : P0, float2 p1 : P1, float2 p2 : P2,
3533 float2 prev : PREV, float2 next : NEXT, out struct output o)
3535 float2 q_prev, q_next, v_p, q_i, p;
3536 float2x2 geom, rt, p_inv;
3537 float l;
3538 float a;
3539 float2 bc;
3541 geom = float2x2(transform_geometry._11_21, transform_geometry._12_22);
3542 rt = float2x2(transform_rtx.xy, transform_rty.xy);
3543 o.stroke_transform = rt * stroke_width * 0.5f;
3545 p = mul(geom, position);
3546 p0 = mul(geom, p0);
3547 p1 = mul(geom, p1);
3548 p2 = mul(geom, p2);
3550 p -= p0;
3551 p1 -= p0;
3552 p2 -= p0;
3554 q_prev = normalize(mul(geom, prev));
3555 q_next = normalize(mul(geom, next));
3557 v_p = float2(-q_prev.y, q_prev.x);
3558 l = -dot(v_p, q_next) / (1.0f + dot(q_prev, q_next));
3559 q_i = l * q_prev + v_p;
3560 p += 0.5f * stroke_width * q_i;
3562 p_inv = float2x2(p1.y, -p1.x, p2.y - p1.y, p1.x - p2.x) / (p1.x * p2.y - p2.x * p1.y);
3563 o.b.xy = mul(p_inv, p) + float2(1.0f, 0.0f);
3564 o.b.zw = 0.0f;
3566 o.p = mul(float3(position, 1.0f), transform_geometry) + 0.5f * stroke_width * q_i;
3567 position = mul(float2x3(transform_rtx.xyz, transform_rty.xyz), float3(o.p, 1.0f))
3568 * float2(transform_rtx.w, transform_rty.w);
3569 o.position = float4(position + float2(-1.0f, 1.0f), 0.0f, 1.0f);
3571 #endif
3572 0x43425844, 0xde1911bf, 0xfff8c893, 0xb0bfc24d, 0x78c9bbc4, 0x00000001, 0x00000924, 0x00000003,
3573 0x0000002c, 0x000000e4, 0x000001a0, 0x4e475349, 0x000000b0, 0x00000006, 0x00000008, 0x00000098,
3574 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000303, 0x000000a1, 0x00000000, 0x00000000,
3575 0x00000003, 0x00000001, 0x00000303, 0x000000a1, 0x00000001, 0x00000000, 0x00000003, 0x00000002,
3576 0x00000303, 0x000000a1, 0x00000002, 0x00000000, 0x00000003, 0x00000003, 0x00000303, 0x000000a3,
3577 0x00000000, 0x00000000, 0x00000003, 0x00000004, 0x00000303, 0x000000a8, 0x00000000, 0x00000000,
3578 0x00000003, 0x00000005, 0x00000303, 0x49534f50, 0x4e4f4954, 0x50005000, 0x00564552, 0x5458454e,
3579 0xababab00, 0x4e47534f, 0x000000b4, 0x00000005, 0x00000008, 0x00000080, 0x00000000, 0x00000000,
3580 0x00000003, 0x00000000, 0x00000c03, 0x0000008f, 0x00000000, 0x00000000, 0x00000003, 0x00000001,
3581 0x0000000f, 0x00000096, 0x00000000, 0x00000000, 0x00000003, 0x00000002, 0x00000c03, 0x00000096,
3582 0x00000001, 0x00000000, 0x00000003, 0x00000003, 0x00000c03, 0x000000a7, 0x00000000, 0x00000001,
3583 0x00000003, 0x00000004, 0x0000000f, 0x4c524f57, 0x4f505f44, 0x49544953, 0x42004e4f, 0x45495a45,
3584 0x54530052, 0x454b4f52, 0x4152545f, 0x4f46534e, 0x53004d52, 0x4f505f56, 0x49544953, 0xab004e4f,
3585 0x52444853, 0x0000077c, 0x00010040, 0x000001df, 0x04000059, 0x00208e46, 0x00000000, 0x00000004,
3586 0x0300005f, 0x00101032, 0x00000000, 0x0300005f, 0x00101032, 0x00000001, 0x0300005f, 0x00101032,
3587 0x00000002, 0x0300005f, 0x00101032, 0x00000003, 0x0300005f, 0x00101032, 0x00000004, 0x0300005f,
3588 0x00101032, 0x00000005, 0x03000065, 0x00102032, 0x00000000, 0x03000065, 0x001020f2, 0x00000001,
3589 0x03000065, 0x00102032, 0x00000002, 0x03000065, 0x00102032, 0x00000003, 0x04000067, 0x001020f2,
3590 0x00000004, 0x00000001, 0x02000068, 0x00000004, 0x0800000f, 0x00100012, 0x00000000, 0x00208046,
3591 0x00000000, 0x00000000, 0x00101046, 0x00000005, 0x0800000f, 0x00100022, 0x00000000, 0x00208046,
3592 0x00000000, 0x00000001, 0x00101046, 0x00000005, 0x0700000f, 0x00100042, 0x00000000, 0x00100046,
3593 0x00000000, 0x00100046, 0x00000000, 0x05000044, 0x00100042, 0x00000000, 0x0010002a, 0x00000000,
3594 0x07000038, 0x00100032, 0x00000000, 0x00100aa6, 0x00000000, 0x00100046, 0x00000000, 0x0800000f,
3595 0x00100012, 0x00000001, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000004, 0x0800000f,
3596 0x00100022, 0x00000001, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000004, 0x0700000f,
3597 0x00100042, 0x00000000, 0x00100046, 0x00000001, 0x00100046, 0x00000001, 0x05000044, 0x00100042,
3598 0x00000000, 0x0010002a, 0x00000000, 0x07000038, 0x00100032, 0x00000001, 0x00100aa6, 0x00000000,
3599 0x00100046, 0x00000001, 0x06000036, 0x001000c2, 0x00000001, 0x80100556, 0x00000041, 0x00000001,
3600 0x0700000f, 0x00100042, 0x00000000, 0x00100a26, 0x00000001, 0x00100046, 0x00000000, 0x0700000f,
3601 0x00100012, 0x00000000, 0x00100046, 0x00000001, 0x00100046, 0x00000000, 0x07000000, 0x00100012,
3602 0x00000000, 0x0010000a, 0x00000000, 0x00004001, 0x3f800000, 0x0800000e, 0x00100012, 0x00000000,
3603 0x8010002a, 0x00000041, 0x00000000, 0x0010000a, 0x00000000, 0x09000032, 0x00100032, 0x00000000,
3604 0x00100006, 0x00000000, 0x00100046, 0x00000001, 0x00100f36, 0x00000001, 0x05000036, 0x00100032,
3605 0x00000001, 0x00101046, 0x00000000, 0x05000036, 0x00100042, 0x00000001, 0x00004001, 0x3f800000,
3606 0x08000010, 0x00100012, 0x00000002, 0x00100246, 0x00000001, 0x00208246, 0x00000000, 0x00000000,
3607 0x08000010, 0x00100022, 0x00000002, 0x00100246, 0x00000001, 0x00208246, 0x00000000, 0x00000001,
3608 0x08000038, 0x00100042, 0x00000000, 0x0020803a, 0x00000000, 0x00000001, 0x00004001, 0x3f000000,
3609 0x09000032, 0x00100032, 0x00000001, 0x00100aa6, 0x00000000, 0x00100046, 0x00000000, 0x00100046,
3610 0x00000002, 0x05000036, 0x00102032, 0x00000000, 0x00100046, 0x00000001, 0x0800000f, 0x00100012,
3611 0x00000002, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000000, 0x0800000f, 0x00100022,
3612 0x00000002, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000000, 0x0800000f, 0x00100022,
3613 0x00000003, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000001, 0x0800000f, 0x00100012,
3614 0x00000003, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000001, 0x08000000, 0x00100032,
3615 0x00000002, 0x00100046, 0x00000002, 0x80100516, 0x00000041, 0x00000003, 0x09000032, 0x00100032,
3616 0x00000000, 0x00100aa6, 0x00000000, 0x00100046, 0x00000000, 0x00100046, 0x00000002, 0x0800000f,
3617 0x00100022, 0x00000002, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000003, 0x0800000f,
3618 0x00100012, 0x00000002, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000003, 0x08000000,
3619 0x001000c2, 0x00000000, 0x80100406, 0x00000041, 0x00000003, 0x00100406, 0x00000002, 0x0800000f,
3620 0x00100022, 0x00000002, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000002, 0x0800000f,
3621 0x00100012, 0x00000002, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000002, 0x08000000,
3622 0x00100032, 0x00000002, 0x80100046, 0x00000041, 0x00000003, 0x00100046, 0x00000002, 0x07000038,
3623 0x00100082, 0x00000001, 0x0010003a, 0x00000000, 0x0010000a, 0x00000002, 0x0a000032, 0x00100082,
3624 0x00000001, 0x0010001a, 0x00000002, 0x0010002a, 0x00000000, 0x8010003a, 0x00000041, 0x00000001,
3625 0x08000000, 0x00100042, 0x00000003, 0x0010002a, 0x00000000, 0x8010000a, 0x00000041, 0x00000002,
3626 0x08000000, 0x00100082, 0x00000003, 0x8010003a, 0x00000041, 0x00000000, 0x0010001a, 0x00000002,
3627 0x0a000038, 0x00100032, 0x00000003, 0x00100046, 0x00000002, 0x00004002, 0x3f800000, 0xbf800000,
3628 0x00000000, 0x00000000, 0x0700000e, 0x001000f2, 0x00000002, 0x00100e46, 0x00000003, 0x00100ff6,
3629 0x00000001, 0x0700000f, 0x00100012, 0x00000002, 0x00100046, 0x00000002, 0x00100046, 0x00000000,
3630 0x0700000f, 0x00100022, 0x00000002, 0x00100ae6, 0x00000002, 0x00100046, 0x00000000, 0x0a000000,
3631 0x00102032, 0x00000001, 0x00100046, 0x00000002, 0x00004002, 0x3f800000, 0x00000000, 0x00000000,
3632 0x00000000, 0x08000036, 0x001020c2, 0x00000001, 0x00004002, 0x00000000, 0x00000000, 0x00000000,
3633 0x00000000, 0x06000036, 0x00100032, 0x00000000, 0x00208046, 0x00000000, 0x00000002, 0x06000036,
3634 0x001000c2, 0x00000000, 0x00208406, 0x00000000, 0x00000003, 0x08000038, 0x001000f2, 0x00000000,
3635 0x00100e46, 0x00000000, 0x00208ff6, 0x00000000, 0x00000001, 0x0a000038, 0x001000f2, 0x00000000,
3636 0x00100e46, 0x00000000, 0x00004002, 0x3f000000, 0x3f000000, 0x3f000000, 0x3f000000, 0x05000036,
3637 0x00102032, 0x00000002, 0x00100086, 0x00000000, 0x05000036, 0x00102032, 0x00000003, 0x001005d6,
3638 0x00000000, 0x05000036, 0x00100042, 0x00000001, 0x00004001, 0x3f800000, 0x08000010, 0x00100012,
3639 0x00000000, 0x00208246, 0x00000000, 0x00000002, 0x00100246, 0x00000001, 0x08000010, 0x00100022,
3640 0x00000000, 0x00208246, 0x00000000, 0x00000003, 0x00100246, 0x00000001, 0x08000038, 0x00100022,
3641 0x00000001, 0x0010001a, 0x00000000, 0x0020803a, 0x00000000, 0x00000003, 0x08000038, 0x00100012,
3642 0x00000001, 0x0010000a, 0x00000000, 0x0020803a, 0x00000000, 0x00000002, 0x0a000000, 0x00102032,
3643 0x00000004, 0x00100046, 0x00000001, 0x00004002, 0xbf800000, 0x3f800000, 0x00000000, 0x00000000,
3644 0x08000036, 0x001020c2, 0x00000004, 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x3f800000,
3645 0x0100003e,
3647 static const DWORD vs_code_triangle[] =
3649 #if 0
3650 float3x2 transform_geometry;
3651 float4 transform_rtx;
3652 float4 transform_rty;
3654 struct output
3656 float2 p : WORLD_POSITION;
3657 float4 b : BEZIER;
3658 nointerpolation float2x2 stroke_transform : STROKE_TRANSFORM;
3659 float4 position : SV_POSITION;
3662 void main(float2 position : POSITION, out struct output o)
3664 o.p = mul(float3(position, 1.0f), transform_geometry);
3665 o.b = float4(1.0, 0.0, 1.0, 1.0);
3666 o.stroke_transform = float2x2(1.0, 0.0, 0.0, 1.0);
3667 position = mul(float2x3(transform_rtx.xyz, transform_rty.xyz), float3(o.p, 1.0f))
3668 * float2(transform_rtx.w, transform_rty.w);
3669 o.position = float4(position + float2(-1.0f, 1.0f), 0.0f, 1.0f);
3671 #endif
3672 0x43425844, 0xda43bf17, 0x06e6d155, 0xdbce2ae5, 0x8aed6fd8, 0x00000001, 0x0000034c, 0x00000003,
3673 0x0000002c, 0x00000060, 0x0000011c, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020,
3674 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000303, 0x49534f50, 0x4e4f4954, 0xababab00,
3675 0x4e47534f, 0x000000b4, 0x00000005, 0x00000008, 0x00000080, 0x00000000, 0x00000000, 0x00000003,
3676 0x00000000, 0x00000c03, 0x0000008f, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x0000000f,
3677 0x00000096, 0x00000000, 0x00000000, 0x00000003, 0x00000002, 0x00000c03, 0x00000096, 0x00000001,
3678 0x00000000, 0x00000003, 0x00000003, 0x00000c03, 0x000000a7, 0x00000000, 0x00000001, 0x00000003,
3679 0x00000004, 0x0000000f, 0x4c524f57, 0x4f505f44, 0x49544953, 0x42004e4f, 0x45495a45, 0x54530052,
3680 0x454b4f52, 0x4152545f, 0x4f46534e, 0x53004d52, 0x4f505f56, 0x49544953, 0xab004e4f, 0x52444853,
3681 0x00000228, 0x00010040, 0x0000008a, 0x04000059, 0x00208e46, 0x00000000, 0x00000004, 0x0300005f,
3682 0x00101032, 0x00000000, 0x03000065, 0x00102032, 0x00000000, 0x03000065, 0x001020f2, 0x00000001,
3683 0x03000065, 0x00102032, 0x00000002, 0x03000065, 0x00102032, 0x00000003, 0x04000067, 0x001020f2,
3684 0x00000004, 0x00000001, 0x02000068, 0x00000002, 0x05000036, 0x00100032, 0x00000000, 0x00101046,
3685 0x00000000, 0x05000036, 0x00100042, 0x00000000, 0x00004001, 0x3f800000, 0x08000010, 0x00100012,
3686 0x00000001, 0x00100246, 0x00000000, 0x00208246, 0x00000000, 0x00000000, 0x08000010, 0x00100022,
3687 0x00000001, 0x00100246, 0x00000000, 0x00208246, 0x00000000, 0x00000001, 0x05000036, 0x00102032,
3688 0x00000000, 0x00100046, 0x00000001, 0x08000036, 0x001020f2, 0x00000001, 0x00004002, 0x3f800000,
3689 0x00000000, 0x3f800000, 0x3f800000, 0x08000036, 0x00102032, 0x00000002, 0x00004002, 0x3f800000,
3690 0x00000000, 0x00000000, 0x00000000, 0x08000036, 0x00102032, 0x00000003, 0x00004002, 0x00000000,
3691 0x3f800000, 0x00000000, 0x00000000, 0x05000036, 0x00100042, 0x00000001, 0x00004001, 0x3f800000,
3692 0x08000010, 0x00100012, 0x00000000, 0x00208246, 0x00000000, 0x00000002, 0x00100246, 0x00000001,
3693 0x08000010, 0x00100022, 0x00000000, 0x00208246, 0x00000000, 0x00000003, 0x00100246, 0x00000001,
3694 0x08000038, 0x00100022, 0x00000001, 0x0010001a, 0x00000000, 0x0020803a, 0x00000000, 0x00000003,
3695 0x08000038, 0x00100012, 0x00000001, 0x0010000a, 0x00000000, 0x0020803a, 0x00000000, 0x00000002,
3696 0x0a000000, 0x00102032, 0x00000004, 0x00100046, 0x00000001, 0x00004002, 0xbf800000, 0x3f800000,
3697 0x00000000, 0x00000000, 0x08000036, 0x001020c2, 0x00000004, 0x00004002, 0x00000000, 0x00000000,
3698 0x00000000, 0x3f800000, 0x0100003e,
3700 static const DWORD vs_code_curve[] =
3702 #if 0
3703 float3x2 transform_geometry;
3704 float4 transform_rtx;
3705 float4 transform_rty;
3707 struct output
3709 float2 p : WORLD_POSITION;
3710 float4 b : BEZIER;
3711 nointerpolation float2x2 stroke_transform : STROKE_TRANSFORM;
3712 float4 position : SV_POSITION;
3715 void main(float2 position : POSITION, float3 texcoord : TEXCOORD0, out struct output o)
3717 o.p = mul(float3(position, 1.0f), transform_geometry);
3718 o.b = float4(texcoord, 1.0);
3719 o.stroke_transform = float2x2(1.0, 0.0, 0.0, 1.0);
3720 position = mul(float2x3(transform_rtx.xyz, transform_rty.xyz), float3(o.p, 1.0f))
3721 * float2(transform_rtx.w, transform_rty.w);
3722 o.position = float4(position + float2(-1.0f, 1.0f), 0.0f, 1.0f);
3724 #endif
3725 0x43425844, 0xedb7472a, 0x2c2ea147, 0x36710079, 0xffc2e907, 0x00000001, 0x00000380, 0x00000003,
3726 0x0000002c, 0x00000080, 0x0000013c, 0x4e475349, 0x0000004c, 0x00000002, 0x00000008, 0x00000038,
3727 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000303, 0x00000041, 0x00000000, 0x00000000,
3728 0x00000003, 0x00000001, 0x00000707, 0x49534f50, 0x4e4f4954, 0x58455400, 0x524f4f43, 0xabab0044,
3729 0x4e47534f, 0x000000b4, 0x00000005, 0x00000008, 0x00000080, 0x00000000, 0x00000000, 0x00000003,
3730 0x00000000, 0x00000c03, 0x0000008f, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x0000000f,
3731 0x00000096, 0x00000000, 0x00000000, 0x00000003, 0x00000002, 0x00000c03, 0x00000096, 0x00000001,
3732 0x00000000, 0x00000003, 0x00000003, 0x00000c03, 0x000000a7, 0x00000000, 0x00000001, 0x00000003,
3733 0x00000004, 0x0000000f, 0x4c524f57, 0x4f505f44, 0x49544953, 0x42004e4f, 0x45495a45, 0x54530052,
3734 0x454b4f52, 0x4152545f, 0x4f46534e, 0x53004d52, 0x4f505f56, 0x49544953, 0xab004e4f, 0x52444853,
3735 0x0000023c, 0x00010040, 0x0000008f, 0x04000059, 0x00208e46, 0x00000000, 0x00000004, 0x0300005f,
3736 0x00101032, 0x00000000, 0x0300005f, 0x00101072, 0x00000001, 0x03000065, 0x00102032, 0x00000000,
3737 0x03000065, 0x001020f2, 0x00000001, 0x03000065, 0x00102032, 0x00000002, 0x03000065, 0x00102032,
3738 0x00000003, 0x04000067, 0x001020f2, 0x00000004, 0x00000001, 0x02000068, 0x00000002, 0x05000036,
3739 0x00100032, 0x00000000, 0x00101046, 0x00000000, 0x05000036, 0x00100042, 0x00000000, 0x00004001,
3740 0x3f800000, 0x08000010, 0x00100012, 0x00000001, 0x00100246, 0x00000000, 0x00208246, 0x00000000,
3741 0x00000000, 0x08000010, 0x00100022, 0x00000001, 0x00100246, 0x00000000, 0x00208246, 0x00000000,
3742 0x00000001, 0x05000036, 0x00102032, 0x00000000, 0x00100046, 0x00000001, 0x05000036, 0x00102072,
3743 0x00000001, 0x00101246, 0x00000001, 0x05000036, 0x00102082, 0x00000001, 0x00004001, 0x3f800000,
3744 0x08000036, 0x00102032, 0x00000002, 0x00004002, 0x3f800000, 0x00000000, 0x00000000, 0x00000000,
3745 0x08000036, 0x00102032, 0x00000003, 0x00004002, 0x00000000, 0x3f800000, 0x00000000, 0x00000000,
3746 0x05000036, 0x00100042, 0x00000001, 0x00004001, 0x3f800000, 0x08000010, 0x00100012, 0x00000000,
3747 0x00208246, 0x00000000, 0x00000002, 0x00100246, 0x00000001, 0x08000010, 0x00100022, 0x00000000,
3748 0x00208246, 0x00000000, 0x00000003, 0x00100246, 0x00000001, 0x08000038, 0x00100022, 0x00000001,
3749 0x0010001a, 0x00000000, 0x0020803a, 0x00000000, 0x00000003, 0x08000038, 0x00100012, 0x00000001,
3750 0x0010000a, 0x00000000, 0x0020803a, 0x00000000, 0x00000002, 0x0a000000, 0x00102032, 0x00000004,
3751 0x00100046, 0x00000001, 0x00004002, 0xbf800000, 0x3f800000, 0x00000000, 0x00000000, 0x08000036,
3752 0x001020c2, 0x00000004, 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, 0x0100003e,
3754 static const DWORD ps_code[] =
3756 #if 0
3757 #define BRUSH_TYPE_SOLID 0
3758 #define BRUSH_TYPE_LINEAR 1
3759 #define BRUSH_TYPE_RADIAL 2
3760 #define BRUSH_TYPE_BITMAP 3
3761 #define BRUSH_TYPE_COUNT 4
3763 bool outline;
3764 bool is_arc;
3765 struct brush
3767 uint type;
3768 float opacity;
3769 float4 data[3];
3770 } colour_brush, opacity_brush;
3772 SamplerState s0, s1;
3773 Texture2D t0, t1;
3774 Buffer<float4> b0, b1;
3776 struct input
3778 float2 p : WORLD_POSITION;
3779 float4 b : BEZIER;
3780 nointerpolation float2x2 stroke_transform : STROKE_TRANSFORM;
3783 float4 sample_gradient(Buffer<float4> gradient, uint stop_count, float position)
3785 float4 c_low, c_high;
3786 float p_low, p_high;
3787 uint i;
3789 p_low = gradient.Load(0).x;
3790 c_low = gradient.Load(1);
3791 c_high = c_low;
3793 if (position < p_low)
3794 return c_low;
3796 for (i = 1; i < stop_count; ++i)
3798 p_high = gradient.Load(i * 2).x;
3799 c_high = gradient.Load(i * 2 + 1);
3801 if (position >= p_low && position <= p_high)
3802 return lerp(c_low, c_high, (position - p_low) / (p_high - p_low));
3804 p_low = p_high;
3805 c_low = c_high;
3808 return c_high;
3811 float4 brush_linear(struct brush brush, Buffer<float4> gradient, float2 position)
3813 float2 start, end, v_p, v_q;
3814 uint stop_count;
3815 float p;
3817 start = brush.data[0].xy;
3818 end = brush.data[0].zw;
3819 stop_count = asuint(brush.data[1].x);
3821 v_p = position - start;
3822 v_q = end - start;
3823 p = dot(v_q, v_p) / dot(v_q, v_q);
3825 return sample_gradient(gradient, stop_count, p);
3828 float4 brush_radial(struct brush brush, Buffer<float4> gradient, float2 position)
3830 float2 centre, offset, ra, rb, v_p, v_q, r;
3831 float b, c, l, t;
3832 uint stop_count;
3834 centre = brush.data[0].xy;
3835 offset = brush.data[0].zw;
3836 ra = brush.data[1].xy;
3837 rb = brush.data[1].zw;
3838 stop_count = asuint(brush.data[2].x);
3840 /* Project onto ra, rb. */
3841 r = float2(dot(ra, ra), dot(rb, rb));
3842 v_p = position - (centre + offset);
3843 v_p = float2(dot(v_p, ra), dot(v_p, rb)) / r;
3844 v_q = float2(dot(offset, ra), dot(offset, rb)) / r;
3846 /* ‖t·p̂ + q⃑‖ = 1
3847 * (t·p̂ + q⃑) · (t·p̂ + q⃑) = 1
3848 * t² + 2·(p̂·q⃑)·t + (q⃑·q⃑) = 1
3850 * b = p̂·q⃑
3851 * c = q⃑·q⃑ - 1
3852 * t = -b + √(b² - c) */
3853 l = length(v_p);
3854 b = dot(v_p, v_q) / l;
3855 c = dot(v_q, v_q) - 1.0;
3856 t = -b + sqrt(b * b - c);
3858 return sample_gradient(gradient, stop_count, l / t);
3861 float4 brush_bitmap(struct brush brush, Texture2D t, SamplerState s, float2 position)
3863 float3 transform[2];
3864 bool ignore_alpha;
3865 float2 texcoord;
3866 float4 colour;
3868 transform[0] = brush.data[0].xyz;
3869 transform[1] = brush.data[1].xyz;
3870 ignore_alpha = asuint(brush.data[1].w);
3872 texcoord.x = dot(position.xy, transform[0].xy) + transform[0].z;
3873 texcoord.y = dot(position.xy, transform[1].xy) + transform[1].z;
3874 colour = t.Sample(s, texcoord);
3875 if (ignore_alpha)
3876 colour.a = 1.0;
3877 return colour;
3880 float4 sample_brush(struct brush brush, Texture2D t, SamplerState s, Buffer<float4> b, float2 position)
3882 if (brush.type == BRUSH_TYPE_SOLID)
3883 return brush.data[0] * brush.opacity;
3884 if (brush.type == BRUSH_TYPE_LINEAR)
3885 return brush_linear(brush, b, position) * brush.opacity;
3886 if (brush.type == BRUSH_TYPE_RADIAL)
3887 return brush_radial(brush, b, position) * brush.opacity;
3888 if (brush.type == BRUSH_TYPE_BITMAP)
3889 return brush_bitmap(brush, t, s, position) * brush.opacity;
3890 return float4(0.0, 0.0, 0.0, brush.opacity);
3893 float4 main(struct input i) : SV_Target
3895 float4 colour;
3897 colour = sample_brush(colour_brush, t0, s0, b0, i.p);
3898 if (opacity_brush.type < BRUSH_TYPE_COUNT)
3899 colour *= sample_brush(opacity_brush, t1, s1, b1, i.p).a;
3901 if (outline)
3903 float2 du, dv, df;
3904 float4 uv;
3906 /* Evaluate the implicit form of the curve (u² - v = 0
3907 * for Béziers, u² + v² - 1 = 0 for arcs) in texture
3908 * space, using the screen-space partial derivatives
3909 * to convert the calculated distance to object space.
3911 * d(x, y) = |f(x, y)| / ‖∇f(x, y)‖
3912 * = |f(x, y)| / √((∂f/∂x)² + (∂f/∂y)²)
3914 * For Béziers:
3915 * f(x, y) = u(x, y)² - v(x, y)
3916 * ∂f/∂x = 2u · ∂u/∂x - ∂v/∂x
3917 * ∂f/∂y = 2u · ∂u/∂y - ∂v/∂y
3919 * For arcs:
3920 * f(x, y) = u(x, y)² + v(x, y)² - 1
3921 * ∂f/∂x = 2u · ∂u/∂x + 2v · ∂v/∂x
3922 * ∂f/∂y = 2u · ∂u/∂y + 2v · ∂v/∂y */
3923 uv = i.b;
3924 du = float2(ddx(uv.x), ddy(uv.x));
3925 dv = float2(ddx(uv.y), ddy(uv.y));
3927 if (!is_arc)
3929 df = 2.0f * uv.x * du - dv;
3931 clip(dot(df, uv.zw));
3932 clip(length(mul(i.stroke_transform, df)) - abs(uv.x * uv.x - uv.y));
3934 else
3936 df = 2.0f * uv.x * du + 2.0f * uv.y * dv;
3938 clip(dot(df, uv.zw));
3939 clip(length(mul(i.stroke_transform, df)) - abs(uv.x * uv.x + uv.y * uv.y - 1.0f));
3942 else
3944 /* Evaluate the implicit form of the curve in texture space.
3945 * "i.b.z" determines which side of the curve is shaded. */
3946 if (!is_arc)
3948 clip((i.b.x * i.b.x - i.b.y) * i.b.z);
3950 else
3952 clip((i.b.x * i.b.x + i.b.y * i.b.y - 1.0) * i.b.z);
3956 return colour;
3958 #endif
3959 0x43425844, 0xa8fee730, 0x92fa2196, 0xaf9f3eff, 0x888d4048, 0x00000001, 0x00002000, 0x00000003,
3960 0x0000002c, 0x000000c4, 0x000000f8, 0x4e475349, 0x00000090, 0x00000004, 0x00000008, 0x00000068,
3961 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000303, 0x00000077, 0x00000000, 0x00000000,
3962 0x00000003, 0x00000001, 0x00000f0f, 0x0000007e, 0x00000000, 0x00000000, 0x00000003, 0x00000002,
3963 0x00000303, 0x0000007e, 0x00000001, 0x00000000, 0x00000003, 0x00000003, 0x00000303, 0x4c524f57,
3964 0x4f505f44, 0x49544953, 0x42004e4f, 0x45495a45, 0x54530052, 0x454b4f52, 0x4152545f, 0x4f46534e,
3965 0xab004d52, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000,
3966 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x00001f00,
3967 0x00000040, 0x000007c0, 0x04000059, 0x00208e46, 0x00000000, 0x00000009, 0x0300005a, 0x00106000,
3968 0x00000000, 0x0300005a, 0x00106000, 0x00000001, 0x04001858, 0x00107000, 0x00000000, 0x00005555,
3969 0x04001858, 0x00107000, 0x00000001, 0x00005555, 0x04000858, 0x00107000, 0x00000002, 0x00005555,
3970 0x04000858, 0x00107000, 0x00000003, 0x00005555, 0x03001062, 0x00101032, 0x00000000, 0x03001062,
3971 0x001010f2, 0x00000001, 0x03000862, 0x00101032, 0x00000002, 0x03000862, 0x00101032, 0x00000003,
3972 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x0000000a, 0x09000038, 0x001000f2, 0x00000000,
3973 0x00208556, 0x00000000, 0x00000001, 0x00208e46, 0x00000000, 0x00000002, 0x0404001f, 0x0020800a,
3974 0x00000000, 0x00000001, 0x08000020, 0x00100012, 0x00000001, 0x0020800a, 0x00000000, 0x00000001,
3975 0x00004001, 0x00000001, 0x0304001f, 0x0010000a, 0x00000001, 0x09000000, 0x00100062, 0x00000001,
3976 0x00101106, 0x00000000, 0x80208106, 0x00000041, 0x00000000, 0x00000002, 0x0a000000, 0x00100032,
3977 0x00000002, 0x80208046, 0x00000041, 0x00000000, 0x00000002, 0x00208ae6, 0x00000000, 0x00000002,
3978 0x0700000f, 0x00100022, 0x00000001, 0x00100046, 0x00000002, 0x00100596, 0x00000001, 0x0700000f,
3979 0x00100042, 0x00000001, 0x00100046, 0x00000002, 0x00100046, 0x00000002, 0x0700000e, 0x00100022,
3980 0x00000001, 0x0010001a, 0x00000001, 0x0010002a, 0x00000001, 0x0a00002d, 0x001000f2, 0x00000002,
3981 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00107e46, 0x00000002, 0x0a00002d,
3982 0x001000f2, 0x00000003, 0x00004002, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00107e46,
3983 0x00000002, 0x0700001d, 0x00100042, 0x00000001, 0x0010001a, 0x00000001, 0x0010000a, 0x00000002,
3984 0x0304001f, 0x0010002a, 0x00000001, 0x05000036, 0x001000f2, 0x00000004, 0x00100e46, 0x00000003,
3985 0x05000036, 0x001000f2, 0x00000005, 0x00100e46, 0x00000003, 0x05000036, 0x001000f2, 0x00000006,
3986 0x00100e46, 0x00000003, 0x05000036, 0x00100042, 0x00000001, 0x0010000a, 0x00000002, 0x05000036,
3987 0x00100082, 0x00000001, 0x00004001, 0x00000001, 0x05000036, 0x00100022, 0x00000002, 0x00004001,
3988 0x00000000, 0x01000030, 0x08000050, 0x00100042, 0x00000002, 0x0010003a, 0x00000001, 0x0020800a,
3989 0x00000000, 0x00000003, 0x05000036, 0x00100022, 0x00000002, 0x00004001, 0x00000000, 0x03040003,
3990 0x0010002a, 0x00000002, 0x07000029, 0x00100042, 0x00000002, 0x0010003a, 0x00000001, 0x00004001,
3991 0x00000001, 0x0700002d, 0x001000f2, 0x00000007, 0x00100aa6, 0x00000002, 0x00107e46, 0x00000002,
3992 0x0700001e, 0x00100042, 0x00000002, 0x0010002a, 0x00000002, 0x00004001, 0x00000001, 0x0700002d,
3993 0x001000f2, 0x00000008, 0x00100aa6, 0x00000002, 0x00107e46, 0x00000002, 0x0700001d, 0x00100042,
3994 0x00000002, 0x0010001a, 0x00000001, 0x0010002a, 0x00000001, 0x0700001d, 0x00100082, 0x00000002,
3995 0x0010000a, 0x00000007, 0x0010001a, 0x00000001, 0x07000001, 0x00100042, 0x00000002, 0x0010003a,
3996 0x00000002, 0x0010002a, 0x00000002, 0x0304001f, 0x0010002a, 0x00000002, 0x08000000, 0x00100082,
3997 0x00000002, 0x8010002a, 0x00000041, 0x00000001, 0x0010001a, 0x00000001, 0x08000000, 0x00100022,
3998 0x00000007, 0x8010002a, 0x00000041, 0x00000001, 0x0010000a, 0x00000007, 0x0700000e, 0x00100082,
3999 0x00000002, 0x0010003a, 0x00000002, 0x0010001a, 0x00000007, 0x08000000, 0x001000f2, 0x00000009,
4000 0x80100e46, 0x00000041, 0x00000005, 0x00100e46, 0x00000008, 0x09000032, 0x001000f2, 0x00000009,
4001 0x00100ff6, 0x00000002, 0x00100e46, 0x00000009, 0x00100e46, 0x00000005, 0x05000036, 0x001000f2,
4002 0x00000006, 0x00100e46, 0x00000008, 0x05000036, 0x00100022, 0x00000002, 0x00004001, 0xffffffff,
4003 0x05000036, 0x001000f2, 0x00000004, 0x00100e46, 0x00000009, 0x01000002, 0x01000015, 0x05000036,
4004 0x001000f2, 0x00000005, 0x00100e46, 0x00000008, 0x05000036, 0x00100042, 0x00000001, 0x0010000a,
4005 0x00000007, 0x0700001e, 0x00100082, 0x00000001, 0x0010003a, 0x00000001, 0x00004001, 0x00000001,
4006 0x05000036, 0x001000f2, 0x00000006, 0x00100e46, 0x00000008, 0x05000036, 0x00100022, 0x00000002,
4007 0x0010002a, 0x00000002, 0x01000016, 0x09000037, 0x001000f2, 0x00000003, 0x00100556, 0x00000002,
4008 0x00100e46, 0x00000004, 0x00100e46, 0x00000006, 0x01000015, 0x08000038, 0x001000f2, 0x00000000,
4009 0x00100e46, 0x00000003, 0x00208556, 0x00000000, 0x00000001, 0x01000015, 0x0300001f, 0x0010000a,
4010 0x00000001, 0x08000020, 0x00100012, 0x00000001, 0x0020800a, 0x00000000, 0x00000001, 0x00004001,
4011 0x00000002, 0x0304001f, 0x0010000a, 0x00000001, 0x0900000f, 0x00100012, 0x00000002, 0x00208046,
4012 0x00000000, 0x00000003, 0x00208046, 0x00000000, 0x00000003, 0x0900000f, 0x00100022, 0x00000002,
4013 0x00208ae6, 0x00000000, 0x00000003, 0x00208ae6, 0x00000000, 0x00000003, 0x09000000, 0x00100062,
4014 0x00000001, 0x00208ba6, 0x00000000, 0x00000002, 0x00208106, 0x00000000, 0x00000002, 0x08000000,
4015 0x00100062, 0x00000001, 0x80100656, 0x00000041, 0x00000001, 0x00101106, 0x00000000, 0x0800000f,
4016 0x00100012, 0x00000003, 0x00100596, 0x00000001, 0x00208046, 0x00000000, 0x00000003, 0x0800000f,
4017 0x00100022, 0x00000003, 0x00100596, 0x00000001, 0x00208ae6, 0x00000000, 0x00000003, 0x0700000e,
4018 0x00100062, 0x00000001, 0x00100106, 0x00000003, 0x00100106, 0x00000002, 0x0900000f, 0x00100012,
4019 0x00000003, 0x00208ae6, 0x00000000, 0x00000002, 0x00208046, 0x00000000, 0x00000003, 0x0900000f,
4020 0x00100022, 0x00000003, 0x00208ae6, 0x00000000, 0x00000002, 0x00208ae6, 0x00000000, 0x00000003,
4021 0x0700000e, 0x00100032, 0x00000002, 0x00100046, 0x00000003, 0x00100046, 0x00000002, 0x0700000f,
4022 0x00100082, 0x00000001, 0x00100596, 0x00000001, 0x00100596, 0x00000001, 0x0500004b, 0x00100082,
4023 0x00000001, 0x0010003a, 0x00000001, 0x0700000f, 0x00100022, 0x00000001, 0x00100596, 0x00000001,
4024 0x00100046, 0x00000002, 0x0700000e, 0x00100022, 0x00000001, 0x0010001a, 0x00000001, 0x0010003a,
4025 0x00000001, 0x0700000f, 0x00100042, 0x00000001, 0x00100046, 0x00000002, 0x00100046, 0x00000002,
4026 0x07000000, 0x00100042, 0x00000001, 0x0010002a, 0x00000001, 0x00004001, 0xbf800000, 0x0a000032,
4027 0x00100042, 0x00000001, 0x0010001a, 0x00000001, 0x0010001a, 0x00000001, 0x8010002a, 0x00000041,
4028 0x00000001, 0x0500004b, 0x00100042, 0x00000001, 0x0010002a, 0x00000001, 0x08000000, 0x00100022,
4029 0x00000001, 0x0010002a, 0x00000001, 0x8010001a, 0x00000041, 0x00000001, 0x0700000e, 0x00100022,
4030 0x00000001, 0x0010003a, 0x00000001, 0x0010001a, 0x00000001, 0x0a00002d, 0x001000f2, 0x00000002,
4031 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00107e46, 0x00000002, 0x0a00002d,
4032 0x001000f2, 0x00000003, 0x00004002, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00107e46,
4033 0x00000002, 0x0700001d, 0x00100042, 0x00000001, 0x0010001a, 0x00000001, 0x0010000a, 0x00000002,
4034 0x0304001f, 0x0010002a, 0x00000001, 0x05000036, 0x001000f2, 0x00000004, 0x00100e46, 0x00000003,
4035 0x05000036, 0x001000f2, 0x00000005, 0x00100e46, 0x00000003, 0x05000036, 0x001000f2, 0x00000006,
4036 0x00100e46, 0x00000003, 0x05000036, 0x00100042, 0x00000001, 0x0010000a, 0x00000002, 0x05000036,
4037 0x00100082, 0x00000001, 0x00004001, 0x00000001, 0x05000036, 0x00100022, 0x00000002, 0x00004001,
4038 0x00000000, 0x01000030, 0x08000050, 0x00100042, 0x00000002, 0x0010003a, 0x00000001, 0x0020800a,
4039 0x00000000, 0x00000004, 0x05000036, 0x00100022, 0x00000002, 0x00004001, 0x00000000, 0x03040003,
4040 0x0010002a, 0x00000002, 0x07000029, 0x00100042, 0x00000002, 0x0010003a, 0x00000001, 0x00004001,
4041 0x00000001, 0x0700002d, 0x001000f2, 0x00000007, 0x00100aa6, 0x00000002, 0x00107e46, 0x00000002,
4042 0x0700001e, 0x00100042, 0x00000002, 0x0010002a, 0x00000002, 0x00004001, 0x00000001, 0x0700002d,
4043 0x001000f2, 0x00000008, 0x00100aa6, 0x00000002, 0x00107e46, 0x00000002, 0x0700001d, 0x00100042,
4044 0x00000002, 0x0010001a, 0x00000001, 0x0010002a, 0x00000001, 0x0700001d, 0x00100082, 0x00000002,
4045 0x0010000a, 0x00000007, 0x0010001a, 0x00000001, 0x07000001, 0x00100042, 0x00000002, 0x0010003a,
4046 0x00000002, 0x0010002a, 0x00000002, 0x0304001f, 0x0010002a, 0x00000002, 0x08000000, 0x00100082,
4047 0x00000002, 0x8010002a, 0x00000041, 0x00000001, 0x0010001a, 0x00000001, 0x08000000, 0x00100022,
4048 0x00000007, 0x8010002a, 0x00000041, 0x00000001, 0x0010000a, 0x00000007, 0x0700000e, 0x00100082,
4049 0x00000002, 0x0010003a, 0x00000002, 0x0010001a, 0x00000007, 0x08000000, 0x001000f2, 0x00000009,
4050 0x80100e46, 0x00000041, 0x00000005, 0x00100e46, 0x00000008, 0x09000032, 0x001000f2, 0x00000009,
4051 0x00100ff6, 0x00000002, 0x00100e46, 0x00000009, 0x00100e46, 0x00000005, 0x05000036, 0x001000f2,
4052 0x00000006, 0x00100e46, 0x00000008, 0x05000036, 0x00100022, 0x00000002, 0x00004001, 0xffffffff,
4053 0x05000036, 0x001000f2, 0x00000004, 0x00100e46, 0x00000009, 0x01000002, 0x01000015, 0x05000036,
4054 0x001000f2, 0x00000005, 0x00100e46, 0x00000008, 0x05000036, 0x00100042, 0x00000001, 0x0010000a,
4055 0x00000007, 0x0700001e, 0x00100082, 0x00000001, 0x0010003a, 0x00000001, 0x00004001, 0x00000001,
4056 0x05000036, 0x001000f2, 0x00000006, 0x00100e46, 0x00000008, 0x05000036, 0x00100022, 0x00000002,
4057 0x0010002a, 0x00000002, 0x01000016, 0x09000037, 0x001000f2, 0x00000003, 0x00100556, 0x00000002,
4058 0x00100e46, 0x00000004, 0x00100e46, 0x00000006, 0x01000015, 0x08000038, 0x001000f2, 0x00000000,
4059 0x00100e46, 0x00000003, 0x00208556, 0x00000000, 0x00000001, 0x01000015, 0x0300001f, 0x0010000a,
4060 0x00000001, 0x08000020, 0x00100012, 0x00000001, 0x0020800a, 0x00000000, 0x00000001, 0x00004001,
4061 0x00000003, 0x0304001f, 0x0010000a, 0x00000001, 0x0800000f, 0x00100022, 0x00000001, 0x00101046,
4062 0x00000000, 0x00208046, 0x00000000, 0x00000002, 0x08000000, 0x00100012, 0x00000002, 0x0010001a,
4063 0x00000001, 0x0020802a, 0x00000000, 0x00000002, 0x0800000f, 0x00100022, 0x00000001, 0x00101046,
4064 0x00000000, 0x00208046, 0x00000000, 0x00000003, 0x08000000, 0x00100022, 0x00000002, 0x0010001a,
4065 0x00000001, 0x0020802a, 0x00000000, 0x00000003, 0x09000045, 0x001000f2, 0x00000002, 0x00100046,
4066 0x00000002, 0x00107e46, 0x00000000, 0x00106000, 0x00000000, 0x0a000037, 0x00100082, 0x00000002,
4067 0x0020803a, 0x00000000, 0x00000003, 0x00004001, 0x3f800000, 0x0010003a, 0x00000002, 0x08000038,
4068 0x001000f2, 0x00000000, 0x00100e46, 0x00000002, 0x00208556, 0x00000000, 0x00000001, 0x01000015,
4069 0x05000036, 0x00100012, 0x00000002, 0x00004001, 0x00000000, 0x06000036, 0x00100082, 0x00000002,
4070 0x0020801a, 0x00000000, 0x00000001, 0x09000037, 0x001000f2, 0x00000000, 0x00100006, 0x00000001,
4071 0x00100e46, 0x00000000, 0x00100c06, 0x00000002, 0x01000015, 0x01000015, 0x01000015, 0x0800004f,
4072 0x00100012, 0x00000001, 0x0020800a, 0x00000000, 0x00000005, 0x00004001, 0x00000004, 0x0304001f,
4073 0x0010000a, 0x00000001, 0x09000038, 0x00100012, 0x00000001, 0x0020801a, 0x00000000, 0x00000005,
4074 0x0020803a, 0x00000000, 0x00000006, 0x0404001f, 0x0020800a, 0x00000000, 0x00000005, 0x08000020,
4075 0x00100022, 0x00000001, 0x0020800a, 0x00000000, 0x00000005, 0x00004001, 0x00000001, 0x0304001f,
4076 0x0010001a, 0x00000001, 0x09000000, 0x001000c2, 0x00000001, 0x00101406, 0x00000000, 0x80208406,
4077 0x00000041, 0x00000000, 0x00000006, 0x0a000000, 0x00100032, 0x00000002, 0x80208046, 0x00000041,
4078 0x00000000, 0x00000006, 0x00208ae6, 0x00000000, 0x00000006, 0x0700000f, 0x00100042, 0x00000001,
4079 0x00100046, 0x00000002, 0x00100ae6, 0x00000001, 0x0700000f, 0x00100082, 0x00000001, 0x00100046,
4080 0x00000002, 0x00100046, 0x00000002, 0x0700000e, 0x00100042, 0x00000001, 0x0010002a, 0x00000001,
4081 0x0010003a, 0x00000001, 0x0a00002d, 0x001000f2, 0x00000002, 0x00004002, 0x00000000, 0x00000000,
4082 0x00000000, 0x00000000, 0x00107e46, 0x00000003, 0x0a00002d, 0x001000f2, 0x00000003, 0x00004002,
4083 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00107e46, 0x00000003, 0x0700001d, 0x00100082,
4084 0x00000001, 0x0010002a, 0x00000001, 0x0010000a, 0x00000002, 0x0304001f, 0x0010003a, 0x00000001,
4085 0x05000036, 0x00100082, 0x00000001, 0x0010003a, 0x00000003, 0x05000036, 0x00100062, 0x00000002,
4086 0x00100ff6, 0x00000003, 0x05000036, 0x00100082, 0x00000002, 0x0010000a, 0x00000002, 0x08000036,
4087 0x00100032, 0x00000003, 0x00004002, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x01000030,
4088 0x08000050, 0x00100042, 0x00000003, 0x0010000a, 0x00000003, 0x0020800a, 0x00000000, 0x00000007,
4089 0x05000036, 0x00100022, 0x00000003, 0x00004001, 0x00000000, 0x03040003, 0x0010002a, 0x00000003,
4090 0x07000029, 0x00100042, 0x00000003, 0x0010000a, 0x00000003, 0x00004001, 0x00000001, 0x0700002d,
4091 0x001000f2, 0x00000004, 0x00100aa6, 0x00000003, 0x00107e46, 0x00000003, 0x0700001e, 0x00100042,
4092 0x00000003, 0x0010002a, 0x00000003, 0x00004001, 0x00000001, 0x0700002d, 0x001000f2, 0x00000005,
4093 0x00100aa6, 0x00000003, 0x00107e46, 0x00000003, 0x0700001d, 0x00100042, 0x00000003, 0x0010002a,
4094 0x00000001, 0x0010003a, 0x00000002, 0x0700001d, 0x00100022, 0x00000004, 0x0010000a, 0x00000004,
4095 0x0010002a, 0x00000001, 0x07000001, 0x00100042, 0x00000003, 0x0010002a, 0x00000003, 0x0010001a,
4096 0x00000004, 0x0304001f, 0x0010002a, 0x00000003, 0x08000000, 0x00100022, 0x00000004, 0x0010002a,
4097 0x00000001, 0x8010003a, 0x00000041, 0x00000002, 0x08000000, 0x00100042, 0x00000004, 0x8010003a,
4098 0x00000041, 0x00000002, 0x0010000a, 0x00000004, 0x0700000e, 0x00100022, 0x00000004, 0x0010001a,
4099 0x00000004, 0x0010002a, 0x00000004, 0x08000000, 0x00100042, 0x00000004, 0x8010001a, 0x00000041,
4100 0x00000002, 0x0010003a, 0x00000005, 0x09000032, 0x00100022, 0x00000004, 0x0010001a, 0x00000004,
4101 0x0010002a, 0x00000004, 0x0010001a, 0x00000002, 0x05000036, 0x00100042, 0x00000002, 0x0010003a,
4102 0x00000005, 0x05000036, 0x00100022, 0x00000003, 0x00004001, 0xffffffff, 0x05000036, 0x00100082,
4103 0x00000001, 0x0010001a, 0x00000004, 0x01000002, 0x01000015, 0x05000036, 0x00100022, 0x00000002,
4104 0x0010003a, 0x00000005, 0x05000036, 0x00100082, 0x00000002, 0x0010000a, 0x00000004, 0x0700001e,
4105 0x00100012, 0x00000003, 0x0010000a, 0x00000003, 0x00004001, 0x00000001, 0x05000036, 0x00100042,
4106 0x00000002, 0x0010003a, 0x00000005, 0x05000036, 0x00100032, 0x00000003, 0x00100086, 0x00000003,
4107 0x01000016, 0x09000037, 0x00100042, 0x00000001, 0x0010001a, 0x00000003, 0x0010003a, 0x00000001,
4108 0x0010002a, 0x00000002, 0x01000012, 0x05000036, 0x00100042, 0x00000001, 0x0010003a, 0x00000003,
4109 0x01000015, 0x08000038, 0x00100012, 0x00000001, 0x0010002a, 0x00000001, 0x0020801a, 0x00000000,
4110 0x00000005, 0x01000015, 0x0300001f, 0x0010001a, 0x00000001, 0x08000020, 0x00100022, 0x00000001,
4111 0x0020800a, 0x00000000, 0x00000005, 0x00004001, 0x00000002, 0x0304001f, 0x0010001a, 0x00000001,
4112 0x0900000f, 0x00100012, 0x00000002, 0x00208046, 0x00000000, 0x00000007, 0x00208046, 0x00000000,
4113 0x00000007, 0x0900000f, 0x00100022, 0x00000002, 0x00208ae6, 0x00000000, 0x00000007, 0x00208ae6,
4114 0x00000000, 0x00000007, 0x09000000, 0x001000c2, 0x00000001, 0x00208ea6, 0x00000000, 0x00000006,
4115 0x00208406, 0x00000000, 0x00000006, 0x08000000, 0x001000c2, 0x00000001, 0x80100ea6, 0x00000041,
4116 0x00000001, 0x00101406, 0x00000000, 0x0800000f, 0x00100012, 0x00000003, 0x00100ae6, 0x00000001,
4117 0x00208046, 0x00000000, 0x00000007, 0x0800000f, 0x00100022, 0x00000003, 0x00100ae6, 0x00000001,
4118 0x00208ae6, 0x00000000, 0x00000007, 0x0700000e, 0x001000c2, 0x00000001, 0x00100406, 0x00000003,
4119 0x00100406, 0x00000002, 0x0900000f, 0x00100012, 0x00000003, 0x00208ae6, 0x00000000, 0x00000006,
4120 0x00208046, 0x00000000, 0x00000007, 0x0900000f, 0x00100022, 0x00000003, 0x00208ae6, 0x00000000,
4121 0x00000006, 0x00208ae6, 0x00000000, 0x00000007, 0x0700000e, 0x00100032, 0x00000002, 0x00100046,
4122 0x00000003, 0x00100046, 0x00000002, 0x0700000f, 0x00100042, 0x00000002, 0x00100ae6, 0x00000001,
4123 0x00100ae6, 0x00000001, 0x0500004b, 0x00100042, 0x00000002, 0x0010002a, 0x00000002, 0x0700000f,
4124 0x00100042, 0x00000001, 0x00100ae6, 0x00000001, 0x00100046, 0x00000002, 0x0700000e, 0x00100042,
4125 0x00000001, 0x0010002a, 0x00000001, 0x0010002a, 0x00000002, 0x0700000f, 0x00100082, 0x00000001,
4126 0x00100046, 0x00000002, 0x00100046, 0x00000002, 0x07000000, 0x00100082, 0x00000001, 0x0010003a,
4127 0x00000001, 0x00004001, 0xbf800000, 0x0a000032, 0x00100082, 0x00000001, 0x0010002a, 0x00000001,
4128 0x0010002a, 0x00000001, 0x8010003a, 0x00000041, 0x00000001, 0x0500004b, 0x00100082, 0x00000001,
4129 0x0010003a, 0x00000001, 0x08000000, 0x00100042, 0x00000001, 0x0010003a, 0x00000001, 0x8010002a,
4130 0x00000041, 0x00000001, 0x0700000e, 0x00100042, 0x00000001, 0x0010002a, 0x00000002, 0x0010002a,
4131 0x00000001, 0x0a00002d, 0x001000f2, 0x00000002, 0x00004002, 0x00000000, 0x00000000, 0x00000000,
4132 0x00000000, 0x00107e46, 0x00000003, 0x0a00002d, 0x001000f2, 0x00000003, 0x00004002, 0x00000001,
4133 0x00000001, 0x00000001, 0x00000001, 0x00107e46, 0x00000003, 0x0700001d, 0x00100082, 0x00000001,
4134 0x0010002a, 0x00000001, 0x0010000a, 0x00000002, 0x0304001f, 0x0010003a, 0x00000001, 0x05000036,
4135 0x00100082, 0x00000001, 0x0010003a, 0x00000003, 0x05000036, 0x00100062, 0x00000002, 0x00100ff6,
4136 0x00000003, 0x05000036, 0x00100082, 0x00000002, 0x0010000a, 0x00000002, 0x08000036, 0x00100032,
4137 0x00000003, 0x00004002, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x01000030, 0x08000050,
4138 0x00100042, 0x00000003, 0x0010000a, 0x00000003, 0x0020800a, 0x00000000, 0x00000008, 0x05000036,
4139 0x00100022, 0x00000003, 0x00004001, 0x00000000, 0x03040003, 0x0010002a, 0x00000003, 0x07000029,
4140 0x00100042, 0x00000003, 0x0010000a, 0x00000003, 0x00004001, 0x00000001, 0x0700002d, 0x001000f2,
4141 0x00000004, 0x00100aa6, 0x00000003, 0x00107e46, 0x00000003, 0x0700001e, 0x00100042, 0x00000003,
4142 0x0010002a, 0x00000003, 0x00004001, 0x00000001, 0x0700002d, 0x001000f2, 0x00000005, 0x00100aa6,
4143 0x00000003, 0x00107e46, 0x00000003, 0x0700001d, 0x00100042, 0x00000003, 0x0010002a, 0x00000001,
4144 0x0010003a, 0x00000002, 0x0700001d, 0x00100022, 0x00000004, 0x0010000a, 0x00000004, 0x0010002a,
4145 0x00000001, 0x07000001, 0x00100042, 0x00000003, 0x0010002a, 0x00000003, 0x0010001a, 0x00000004,
4146 0x0304001f, 0x0010002a, 0x00000003, 0x08000000, 0x00100022, 0x00000004, 0x0010002a, 0x00000001,
4147 0x8010003a, 0x00000041, 0x00000002, 0x08000000, 0x00100042, 0x00000004, 0x8010003a, 0x00000041,
4148 0x00000002, 0x0010000a, 0x00000004, 0x0700000e, 0x00100022, 0x00000004, 0x0010001a, 0x00000004,
4149 0x0010002a, 0x00000004, 0x08000000, 0x00100042, 0x00000004, 0x8010001a, 0x00000041, 0x00000002,
4150 0x0010003a, 0x00000005, 0x09000032, 0x00100022, 0x00000004, 0x0010001a, 0x00000004, 0x0010002a,
4151 0x00000004, 0x0010001a, 0x00000002, 0x05000036, 0x00100042, 0x00000002, 0x0010003a, 0x00000005,
4152 0x05000036, 0x00100022, 0x00000003, 0x00004001, 0xffffffff, 0x05000036, 0x00100082, 0x00000001,
4153 0x0010001a, 0x00000004, 0x01000002, 0x01000015, 0x05000036, 0x00100022, 0x00000002, 0x0010003a,
4154 0x00000005, 0x05000036, 0x00100082, 0x00000002, 0x0010000a, 0x00000004, 0x0700001e, 0x00100012,
4155 0x00000003, 0x0010000a, 0x00000003, 0x00004001, 0x00000001, 0x05000036, 0x00100042, 0x00000002,
4156 0x0010003a, 0x00000005, 0x05000036, 0x00100032, 0x00000003, 0x00100086, 0x00000003, 0x01000016,
4157 0x09000037, 0x00100042, 0x00000001, 0x0010001a, 0x00000003, 0x0010003a, 0x00000001, 0x0010002a,
4158 0x00000002, 0x01000012, 0x05000036, 0x00100042, 0x00000001, 0x0010003a, 0x00000003, 0x01000015,
4159 0x08000038, 0x00100012, 0x00000001, 0x0010002a, 0x00000001, 0x0020801a, 0x00000000, 0x00000005,
4160 0x01000015, 0x0300001f, 0x0010001a, 0x00000001, 0x08000020, 0x00100022, 0x00000001, 0x0020800a,
4161 0x00000000, 0x00000005, 0x00004001, 0x00000003, 0x0304001f, 0x0010001a, 0x00000001, 0x0800000f,
4162 0x00100042, 0x00000001, 0x00101046, 0x00000000, 0x00208046, 0x00000000, 0x00000006, 0x08000000,
4163 0x00100012, 0x00000002, 0x0010002a, 0x00000001, 0x0020802a, 0x00000000, 0x00000006, 0x0800000f,
4164 0x00100042, 0x00000001, 0x00101046, 0x00000000, 0x00208046, 0x00000000, 0x00000007, 0x08000000,
4165 0x00100022, 0x00000002, 0x0010002a, 0x00000001, 0x0020802a, 0x00000000, 0x00000007, 0x09000045,
4166 0x001000f2, 0x00000002, 0x00100046, 0x00000002, 0x00107e46, 0x00000001, 0x00106000, 0x00000001,
4167 0x0a000037, 0x00100042, 0x00000001, 0x0020803a, 0x00000000, 0x00000007, 0x00004001, 0x3f800000,
4168 0x0010003a, 0x00000002, 0x08000038, 0x00100012, 0x00000001, 0x0010002a, 0x00000001, 0x0020801a,
4169 0x00000000, 0x00000005, 0x01000015, 0x0a000037, 0x00100012, 0x00000001, 0x0010001a, 0x00000001,
4170 0x0010000a, 0x00000001, 0x0020801a, 0x00000000, 0x00000005, 0x01000015, 0x01000015, 0x01000015,
4171 0x07000038, 0x001020f2, 0x00000000, 0x00100e46, 0x00000000, 0x00100006, 0x00000001, 0x01000012,
4172 0x05000036, 0x001020f2, 0x00000000, 0x00100e46, 0x00000000, 0x01000015, 0x0404001f, 0x0020800a,
4173 0x00000000, 0x00000000, 0x0500000b, 0x00100032, 0x00000000, 0x00101046, 0x00000001, 0x0500000c,
4174 0x001000c2, 0x00000000, 0x00101406, 0x00000001, 0x08000027, 0x00100012, 0x00000001, 0x0020801a,
4175 0x00000000, 0x00000000, 0x00004001, 0x00000000, 0x0500003b, 0x00100022, 0x00000001, 0x0010000a,
4176 0x00000001, 0x07000000, 0x001000c2, 0x00000001, 0x00101406, 0x00000001, 0x00101406, 0x00000001,
4177 0x07000038, 0x001000f2, 0x00000002, 0x00100d86, 0x00000000, 0x00100fa6, 0x00000001, 0x0a000032,
4178 0x00100032, 0x00000000, 0x00100aa6, 0x00000001, 0x00100086, 0x00000000, 0x801005d6, 0x00000041,
4179 0x00000000, 0x0700000f, 0x00100042, 0x00000000, 0x00100046, 0x00000000, 0x00101ae6, 0x00000001,
4180 0x07000031, 0x00100042, 0x00000000, 0x0010002a, 0x00000000, 0x00004001, 0x00000000, 0x07000001,
4181 0x00100042, 0x00000000, 0x0010001a, 0x00000001, 0x0010002a, 0x00000000, 0x0304000d, 0x0010002a,
4182 0x00000000, 0x07000038, 0x00100062, 0x00000000, 0x00100556, 0x00000000, 0x00101106, 0x00000003,
4183 0x09000032, 0x00100032, 0x00000000, 0x00101046, 0x00000002, 0x00100006, 0x00000000, 0x00100596,
4184 0x00000000, 0x0700000f, 0x00100012, 0x00000000, 0x00100046, 0x00000000, 0x00100046, 0x00000000,
4185 0x0500004b, 0x00100012, 0x00000000, 0x0010000a, 0x00000000, 0x07000038, 0x00100062, 0x00000000,
4186 0x00101106, 0x00000001, 0x00101106, 0x00000001, 0x0a000032, 0x00100082, 0x00000000, 0x0010100a,
4187 0x00000001, 0x0010100a, 0x00000001, 0x8010101a, 0x00000041, 0x00000001, 0x08000000, 0x00100012,
4188 0x00000000, 0x8010003a, 0x000000c1, 0x00000000, 0x0010000a, 0x00000000, 0x07000031, 0x00100012,
4189 0x00000000, 0x0010000a, 0x00000000, 0x00004001, 0x00000000, 0x07000001, 0x00100012, 0x00000000,
4190 0x0010001a, 0x00000001, 0x0010000a, 0x00000000, 0x0304000d, 0x0010000a, 0x00000000, 0x07000000,
4191 0x00100092, 0x00000000, 0x00100ea6, 0x00000002, 0x00100406, 0x00000002, 0x0700000f, 0x00100022,
4192 0x00000001, 0x001000c6, 0x00000000, 0x00101ae6, 0x00000001, 0x07000031, 0x00100022, 0x00000001,
4193 0x0010001a, 0x00000001, 0x00004001, 0x00000000, 0x07000001, 0x00100022, 0x00000001, 0x0010000a,
4194 0x00000001, 0x0010001a, 0x00000001, 0x0304000d, 0x0010001a, 0x00000001, 0x07000038, 0x00100062,
4195 0x00000001, 0x00100ff6, 0x00000000, 0x00101106, 0x00000003, 0x09000032, 0x00100092, 0x00000000,
4196 0x00101406, 0x00000002, 0x00100006, 0x00000000, 0x00100956, 0x00000001, 0x0700000f, 0x00100012,
4197 0x00000000, 0x001000c6, 0x00000000, 0x001000c6, 0x00000000, 0x0500004b, 0x00100012, 0x00000000,
4198 0x0010000a, 0x00000000, 0x07000000, 0x00100022, 0x00000000, 0x0010002a, 0x00000000, 0x0010001a,
4199 0x00000000, 0x07000000, 0x00100022, 0x00000000, 0x0010001a, 0x00000000, 0x00004001, 0xbf800000,
4200 0x08000000, 0x00100012, 0x00000000, 0x8010001a, 0x000000c1, 0x00000000, 0x0010000a, 0x00000000,
4201 0x07000031, 0x00100012, 0x00000000, 0x0010000a, 0x00000000, 0x00004001, 0x00000000, 0x07000001,
4202 0x00100012, 0x00000000, 0x0010000a, 0x00000001, 0x0010000a, 0x00000000, 0x0304000d, 0x0010000a,
4203 0x00000000, 0x01000012, 0x08000027, 0x00100012, 0x00000000, 0x0020801a, 0x00000000, 0x00000000,
4204 0x00004001, 0x00000000, 0x0500003b, 0x00100022, 0x00000000, 0x0010000a, 0x00000000, 0x07000038,
4205 0x001000c2, 0x00000000, 0x00101406, 0x00000001, 0x00101406, 0x00000001, 0x0a000032, 0x00100012,
4206 0x00000001, 0x0010100a, 0x00000001, 0x0010100a, 0x00000001, 0x8010101a, 0x00000041, 0x00000001,
4207 0x07000038, 0x00100012, 0x00000001, 0x0010000a, 0x00000001, 0x0010102a, 0x00000001, 0x07000031,
4208 0x00100012, 0x00000001, 0x0010000a, 0x00000001, 0x00004001, 0x00000000, 0x07000001, 0x00100022,
4209 0x00000000, 0x0010001a, 0x00000000, 0x0010000a, 0x00000001, 0x0304000d, 0x0010001a, 0x00000000,
4210 0x07000000, 0x00100022, 0x00000000, 0x0010003a, 0x00000000, 0x0010002a, 0x00000000, 0x07000000,
4211 0x00100022, 0x00000000, 0x0010001a, 0x00000000, 0x00004001, 0xbf800000, 0x07000038, 0x00100022,
4212 0x00000000, 0x0010001a, 0x00000000, 0x0010102a, 0x00000001, 0x07000031, 0x00100022, 0x00000000,
4213 0x0010001a, 0x00000000, 0x00004001, 0x00000000, 0x07000001, 0x00100012, 0x00000000, 0x0010000a,
4214 0x00000000, 0x0010001a, 0x00000000, 0x0304000d, 0x0010000a, 0x00000000, 0x01000015, 0x0100003e,
4216 static const struct shape_info
4218 enum d2d_shape_type shape_type;
4219 const D3D11_INPUT_ELEMENT_DESC *il_desc;
4220 unsigned int il_element_count;
4221 const void *vs_code;
4222 size_t vs_code_size;
4224 shape_info[] =
4226 {D2D_SHAPE_TYPE_OUTLINE, il_desc_outline, ARRAY_SIZE(il_desc_outline),
4227 vs_code_outline, sizeof(vs_code_outline)},
4228 {D2D_SHAPE_TYPE_BEZIER_OUTLINE, il_desc_curve_outline, ARRAY_SIZE(il_desc_curve_outline),
4229 vs_code_bezier_outline, sizeof(vs_code_bezier_outline)},
4230 {D2D_SHAPE_TYPE_ARC_OUTLINE, il_desc_curve_outline, ARRAY_SIZE(il_desc_curve_outline),
4231 vs_code_arc_outline, sizeof(vs_code_arc_outline)},
4232 {D2D_SHAPE_TYPE_TRIANGLE, il_desc_triangle, ARRAY_SIZE(il_desc_triangle),
4233 vs_code_triangle, sizeof(vs_code_triangle)},
4234 {D2D_SHAPE_TYPE_CURVE, il_desc_curve, ARRAY_SIZE(il_desc_curve),
4235 vs_code_curve, sizeof(vs_code_curve)},
4237 static const struct
4239 float x, y;
4241 quad[] =
4243 {-1.0f, 1.0f},
4244 {-1.0f, -1.0f},
4245 { 1.0f, 1.0f},
4246 { 1.0f, -1.0f},
4248 static const UINT16 indices[] = {0, 1, 2, 2, 1, 3};
4249 static const D3D_FEATURE_LEVEL feature_levels = D3D_FEATURE_LEVEL_10_0;
4251 render_target->ID2D1DeviceContext1_iface.lpVtbl = &d2d_device_context_vtbl;
4252 render_target->ID2D1GdiInteropRenderTarget_iface.lpVtbl = &d2d_gdi_interop_render_target_vtbl;
4253 render_target->IDWriteTextRenderer_iface.lpVtbl = &d2d_text_renderer_vtbl;
4254 render_target->IUnknown_iface.lpVtbl = &d2d_device_context_inner_unknown_vtbl;
4255 render_target->refcount = 1;
4256 ID2D1Device1_GetFactory(&device->ID2D1Device1_iface, &render_target->factory);
4257 render_target->device = device;
4258 ID2D1Device1_AddRef(&render_target->device->ID2D1Device1_iface);
4260 render_target->outer_unknown = outer_unknown ? outer_unknown : &render_target->IUnknown_iface;
4261 render_target->ops = ops;
4263 device_impl = unsafe_impl_from_ID2D1Device((ID2D1Device1 *)device);
4264 if (FAILED(hr = IDXGIDevice_QueryInterface(device_impl->dxgi_device,
4265 &IID_ID3D11Device1, (void **)&render_target->d3d_device)))
4267 WARN("Failed to query ID3D11Device1 interface, hr %#lx.\n", hr);
4268 goto err;
4271 if (FAILED(hr = ID3D11Device1_CreateDeviceContextState(render_target->d3d_device,
4272 0, &feature_levels, 1, D3D11_SDK_VERSION, &IID_ID3D11Device1, NULL,
4273 &render_target->d3d_state)))
4275 WARN("Failed to create device context state, hr %#lx.\n", hr);
4276 goto err;
4279 for (i = 0; i < ARRAY_SIZE(shape_info); ++i)
4281 const struct shape_info *si = &shape_info[i];
4283 if (FAILED(hr = ID3D11Device1_CreateInputLayout(render_target->d3d_device, si->il_desc, si->il_element_count,
4284 si->vs_code, si->vs_code_size, &render_target->shape_resources[si->shape_type].il)))
4286 WARN("Failed to create input layout for shape type %#x, hr %#lx.\n", si->shape_type, hr);
4287 goto err;
4290 if (FAILED(hr = ID3D11Device1_CreateVertexShader(render_target->d3d_device, si->vs_code,
4291 si->vs_code_size, NULL, &render_target->shape_resources[si->shape_type].vs)))
4293 WARN("Failed to create vertex shader for shape type %#x, hr %#lx.\n", si->shape_type, hr);
4294 goto err;
4299 buffer_desc.ByteWidth = sizeof(struct d2d_vs_cb);
4300 buffer_desc.Usage = D3D11_USAGE_DYNAMIC;
4301 buffer_desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
4302 buffer_desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
4303 buffer_desc.MiscFlags = 0;
4305 if (FAILED(hr = ID3D11Device1_CreateBuffer(render_target->d3d_device, &buffer_desc, NULL,
4306 &render_target->vs_cb)))
4308 WARN("Failed to create constant buffer, hr %#lx.\n", hr);
4309 goto err;
4312 if (FAILED(hr = ID3D11Device1_CreatePixelShader(render_target->d3d_device,
4313 ps_code, sizeof(ps_code), NULL, &render_target->ps)))
4315 WARN("Failed to create pixel shader, hr %#lx.\n", hr);
4316 goto err;
4319 buffer_desc.ByteWidth = sizeof(struct d2d_ps_cb);
4320 buffer_desc.Usage = D3D11_USAGE_DYNAMIC;
4321 buffer_desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
4322 buffer_desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
4323 buffer_desc.MiscFlags = 0;
4325 if (FAILED(hr = ID3D11Device1_CreateBuffer(render_target->d3d_device, &buffer_desc, NULL,
4326 &render_target->ps_cb)))
4328 WARN("Failed to create constant buffer, hr %#lx.\n", hr);
4329 goto err;
4332 buffer_desc.ByteWidth = sizeof(indices);
4333 buffer_desc.Usage = D3D11_USAGE_DEFAULT;
4334 buffer_desc.BindFlags = D3D11_BIND_INDEX_BUFFER;
4335 buffer_desc.CPUAccessFlags = 0;
4336 buffer_desc.MiscFlags = 0;
4338 buffer_data.pSysMem = indices;
4339 buffer_data.SysMemPitch = 0;
4340 buffer_data.SysMemSlicePitch = 0;
4342 if (FAILED(hr = ID3D11Device1_CreateBuffer(render_target->d3d_device,
4343 &buffer_desc, &buffer_data, &render_target->ib)))
4345 WARN("Failed to create clear index buffer, hr %#lx.\n", hr);
4346 goto err;
4349 buffer_desc.ByteWidth = sizeof(quad);
4350 buffer_desc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
4351 buffer_data.pSysMem = quad;
4353 render_target->vb_stride = sizeof(*quad);
4354 if (FAILED(hr = ID3D11Device1_CreateBuffer(render_target->d3d_device,
4355 &buffer_desc, &buffer_data, &render_target->vb)))
4357 WARN("Failed to create clear vertex buffer, hr %#lx.\n", hr);
4358 goto err;
4361 rs_desc.FillMode = D3D11_FILL_SOLID;
4362 rs_desc.CullMode = D3D11_CULL_NONE;
4363 rs_desc.FrontCounterClockwise = FALSE;
4364 rs_desc.DepthBias = 0;
4365 rs_desc.DepthBiasClamp = 0.0f;
4366 rs_desc.SlopeScaledDepthBias = 0.0f;
4367 rs_desc.DepthClipEnable = TRUE;
4368 rs_desc.ScissorEnable = TRUE;
4369 rs_desc.MultisampleEnable = FALSE;
4370 rs_desc.AntialiasedLineEnable = FALSE;
4371 if (FAILED(hr = ID3D11Device1_CreateRasterizerState(render_target->d3d_device, &rs_desc, &render_target->rs)))
4373 WARN("Failed to create clear rasteriser state, hr %#lx.\n", hr);
4374 goto err;
4377 if (FAILED(hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED,
4378 &IID_IDWriteFactory, (IUnknown **)&dwrite_factory)))
4380 ERR("Failed to create dwrite factory, hr %#lx.\n", hr);
4381 goto err;
4384 hr = IDWriteFactory_CreateRenderingParams(dwrite_factory, &render_target->default_text_rendering_params);
4385 IDWriteFactory_Release(dwrite_factory);
4386 if (FAILED(hr))
4388 ERR("Failed to create default text rendering parameters, hr %#lx.\n", hr);
4389 goto err;
4392 render_target->drawing_state.transform = identity;
4394 if (!d2d_clip_stack_init(&render_target->clip_stack))
4396 WARN("Failed to initialize clip stack.\n");
4397 hr = E_FAIL;
4398 goto err;
4401 render_target->desc.dpiX = 96.0f;
4402 render_target->desc.dpiY = 96.0f;
4404 return S_OK;
4406 err:
4407 if (render_target->default_text_rendering_params)
4408 IDWriteRenderingParams_Release(render_target->default_text_rendering_params);
4409 if (render_target->rs)
4410 ID3D11RasterizerState_Release(render_target->rs);
4411 if (render_target->vb)
4412 ID3D11Buffer_Release(render_target->vb);
4413 if (render_target->ib)
4414 ID3D11Buffer_Release(render_target->ib);
4415 if (render_target->ps_cb)
4416 ID3D11Buffer_Release(render_target->ps_cb);
4417 if (render_target->ps)
4418 ID3D11PixelShader_Release(render_target->ps);
4419 if (render_target->vs_cb)
4420 ID3D11Buffer_Release(render_target->vs_cb);
4421 for (i = 0; i < D2D_SHAPE_TYPE_COUNT; ++i)
4423 if (render_target->shape_resources[i].vs)
4424 ID3D11VertexShader_Release(render_target->shape_resources[i].vs);
4425 if (render_target->shape_resources[i].il)
4426 ID3D11InputLayout_Release(render_target->shape_resources[i].il);
4428 if (render_target->d3d_state)
4429 ID3DDeviceContextState_Release(render_target->d3d_state);
4430 if (render_target->d3d_device)
4431 ID3D11Device1_Release(render_target->d3d_device);
4432 ID2D1Device1_Release(&render_target->device->ID2D1Device1_iface);
4433 ID2D1Factory_Release(render_target->factory);
4434 return hr;
4437 HRESULT d2d_d3d_create_render_target(struct d2d_device *device, IDXGISurface *surface, IUnknown *outer_unknown,
4438 const struct d2d_device_context_ops *ops, const D2D1_RENDER_TARGET_PROPERTIES *desc, void **render_target)
4440 D2D1_BITMAP_PROPERTIES1 bitmap_desc;
4441 struct d2d_device_context *object;
4442 ID2D1Bitmap1 *bitmap;
4443 HRESULT hr;
4445 if (desc->type != D2D1_RENDER_TARGET_TYPE_DEFAULT && desc->type != D2D1_RENDER_TARGET_TYPE_HARDWARE)
4446 WARN("Ignoring render target type %#x.\n", desc->type);
4447 if (desc->usage != D2D1_RENDER_TARGET_USAGE_NONE)
4448 FIXME("Ignoring render target usage %#x.\n", desc->usage);
4449 if (desc->minLevel != D2D1_FEATURE_LEVEL_DEFAULT)
4450 WARN("Ignoring feature level %#x.\n", desc->minLevel);
4452 bitmap_desc.dpiX = desc->dpiX;
4453 bitmap_desc.dpiY = desc->dpiY;
4455 if (bitmap_desc.dpiX == 0.0f && bitmap_desc.dpiY == 0.0f)
4457 bitmap_desc.dpiX = 96.0f;
4458 bitmap_desc.dpiY = 96.0f;
4460 else if (bitmap_desc.dpiX <= 0.0f || bitmap_desc.dpiY <= 0.0f)
4461 return E_INVALIDARG;
4463 if (!(object = calloc(1, sizeof(*object))))
4464 return E_OUTOFMEMORY;
4466 if (FAILED(hr = d2d_device_context_init(object, device, outer_unknown, ops)))
4468 WARN("Failed to initialise render target, hr %#lx.\n", hr);
4469 free(object);
4470 return hr;
4473 ID2D1DeviceContext1_SetDpi(&object->ID2D1DeviceContext1_iface, bitmap_desc.dpiX, bitmap_desc.dpiY);
4475 if (surface)
4477 bitmap_desc.pixelFormat = desc->pixelFormat;
4478 bitmap_desc.bitmapOptions = D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW;
4479 if (desc->usage & D2D1_RENDER_TARGET_USAGE_GDI_COMPATIBLE)
4480 bitmap_desc.bitmapOptions |= D2D1_BITMAP_OPTIONS_GDI_COMPATIBLE;
4481 bitmap_desc.colorContext = NULL;
4483 if (FAILED(hr = ID2D1DeviceContext1_CreateBitmapFromDxgiSurface(&object->ID2D1DeviceContext1_iface,
4484 surface, &bitmap_desc, &bitmap)))
4486 WARN("Failed to create target bitmap, hr %#lx.\n", hr);
4487 IUnknown_Release(&object->IUnknown_iface);
4488 free(object);
4489 return hr;
4492 ID2D1DeviceContext1_SetTarget(&object->ID2D1DeviceContext1_iface, (ID2D1Image *)bitmap);
4493 ID2D1Bitmap1_Release(bitmap);
4495 else
4496 object->desc.pixelFormat = desc->pixelFormat;
4498 TRACE("Created render target %p.\n", object);
4499 *render_target = outer_unknown ? &object->IUnknown_iface : (IUnknown *)&object->ID2D1DeviceContext1_iface;
4501 return S_OK;
4504 static HRESULT WINAPI d2d_device_QueryInterface(ID2D1Device1 *iface, REFIID iid, void **out)
4506 TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
4508 if (IsEqualGUID(iid, &IID_ID2D1Device1)
4509 || IsEqualGUID(iid, &IID_ID2D1Device)
4510 || IsEqualGUID(iid, &IID_ID2D1Resource)
4511 || IsEqualGUID(iid, &IID_IUnknown))
4513 ID2D1Device1_AddRef(iface);
4514 *out = iface;
4515 return S_OK;
4518 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
4520 *out = NULL;
4521 return E_NOINTERFACE;
4524 static ULONG WINAPI d2d_device_AddRef(ID2D1Device1 *iface)
4526 struct d2d_device *device = impl_from_ID2D1Device(iface);
4527 ULONG refcount = InterlockedIncrement(&device->refcount);
4529 TRACE("%p increasing refcount to %lu.\n", iface, refcount);
4531 return refcount;
4534 static ULONG WINAPI d2d_device_Release(ID2D1Device1 *iface)
4536 struct d2d_device *device = impl_from_ID2D1Device(iface);
4537 ULONG refcount = InterlockedDecrement(&device->refcount);
4538 size_t i;
4540 TRACE("%p decreasing refcount to %lu.\n", iface, refcount);
4542 if (!refcount)
4544 IDXGIDevice_Release(device->dxgi_device);
4545 ID2D1Factory1_Release(device->factory);
4546 for (i = 0; i < device->shaders.count; ++i)
4547 IUnknown_Release(device->shaders.objects[i].shader);
4548 free(device->shaders.objects);
4549 free(device);
4552 return refcount;
4555 static void WINAPI d2d_device_GetFactory(ID2D1Device1 *iface, ID2D1Factory **factory)
4557 struct d2d_device *device = impl_from_ID2D1Device(iface);
4559 TRACE("iface %p, factory %p.\n", iface, factory);
4561 *factory = (ID2D1Factory *)device->factory;
4562 ID2D1Factory1_AddRef(device->factory);
4565 static HRESULT d2d_device_create_device_context(struct d2d_device *device,
4566 D2D1_DEVICE_CONTEXT_OPTIONS options, ID2D1DeviceContext1 **context)
4568 struct d2d_device_context *object;
4569 HRESULT hr;
4571 if (options)
4572 FIXME("Options are ignored %#x.\n", options);
4574 if (!(object = calloc(1, sizeof(*object))))
4575 return E_OUTOFMEMORY;
4577 if (FAILED(hr = d2d_device_context_init(object, device, NULL, NULL)))
4579 WARN("Failed to initialise device context, hr %#lx.\n", hr);
4580 free(object);
4581 return hr;
4584 TRACE("Created device context %p.\n", object);
4585 *context = &object->ID2D1DeviceContext1_iface;
4587 return S_OK;
4590 static HRESULT WINAPI d2d_device_CreateDeviceContext(ID2D1Device1 *iface, D2D1_DEVICE_CONTEXT_OPTIONS options,
4591 ID2D1DeviceContext **context)
4593 struct d2d_device *device = impl_from_ID2D1Device(iface);
4595 TRACE("iface %p, options %#x, context %p.\n", iface, options, context);
4597 return d2d_device_create_device_context(device, options, (ID2D1DeviceContext1 **)context);
4600 static HRESULT WINAPI d2d_device_CreatePrintControl(ID2D1Device1 *iface, IWICImagingFactory *wic_factory,
4601 IPrintDocumentPackageTarget *document_target, const D2D1_PRINT_CONTROL_PROPERTIES *desc,
4602 ID2D1PrintControl **print_control)
4604 FIXME("iface %p, wic_factory %p, document_target %p, desc %p, print_control %p stub!\n", iface, wic_factory,
4605 document_target, desc, print_control);
4607 return E_NOTIMPL;
4610 static void WINAPI d2d_device_SetMaximumTextureMemory(ID2D1Device1 *iface, UINT64 max_texture_memory)
4612 FIXME("iface %p, max_texture_memory %s stub!\n", iface, wine_dbgstr_longlong(max_texture_memory));
4615 static UINT64 WINAPI d2d_device_GetMaximumTextureMemory(ID2D1Device1 *iface)
4617 FIXME("iface %p stub!\n", iface);
4619 return 0;
4622 static HRESULT WINAPI d2d_device_ClearResources(ID2D1Device1 *iface, UINT msec_since_use)
4624 FIXME("iface %p, msec_since_use %u stub!\n", iface, msec_since_use);
4626 return E_NOTIMPL;
4629 static D2D1_RENDERING_PRIORITY WINAPI d2d_device_GetRenderingPriority(ID2D1Device1 *iface)
4631 FIXME("iface %p stub!\n", iface);
4633 return D2D1_RENDERING_PRIORITY_NORMAL;
4636 static void WINAPI d2d_device_SetRenderingPriority(ID2D1Device1 *iface, D2D1_RENDERING_PRIORITY priority)
4638 FIXME("iface %p, priority %#x stub!\n", iface, priority);
4641 static HRESULT WINAPI d2d_device_CreateDeviceContext1(ID2D1Device1 *iface, D2D1_DEVICE_CONTEXT_OPTIONS options,
4642 ID2D1DeviceContext1 **context)
4644 struct d2d_device *device = impl_from_ID2D1Device(iface);
4646 TRACE("iface %p, options %#x, context %p.\n", iface, options, context);
4648 return d2d_device_create_device_context(device, options, context);
4651 static const struct ID2D1Device1Vtbl d2d_device_vtbl =
4653 d2d_device_QueryInterface,
4654 d2d_device_AddRef,
4655 d2d_device_Release,
4656 d2d_device_GetFactory,
4657 d2d_device_CreateDeviceContext,
4658 d2d_device_CreatePrintControl,
4659 d2d_device_SetMaximumTextureMemory,
4660 d2d_device_GetMaximumTextureMemory,
4661 d2d_device_ClearResources,
4662 d2d_device_GetRenderingPriority,
4663 d2d_device_SetRenderingPriority,
4664 d2d_device_CreateDeviceContext1,
4667 struct d2d_device *unsafe_impl_from_ID2D1Device(ID2D1Device1 *iface)
4669 if (!iface)
4670 return NULL;
4671 assert(iface->lpVtbl == &d2d_device_vtbl);
4672 return CONTAINING_RECORD(iface, struct d2d_device, ID2D1Device1_iface);
4675 void d2d_device_init(struct d2d_device *device, ID2D1Factory1 *iface, IDXGIDevice *dxgi_device)
4677 device->ID2D1Device1_iface.lpVtbl = &d2d_device_vtbl;
4678 device->refcount = 1;
4679 device->factory = iface;
4680 ID2D1Factory1_AddRef(device->factory);
4681 device->dxgi_device = dxgi_device;
4682 IDXGIDevice_AddRef(device->dxgi_device);
4685 HRESULT d2d_device_add_shader(struct d2d_device *device, REFGUID shader_id, IUnknown *shader)
4687 struct d2d_shader *entry;
4689 if (!d2d_array_reserve((void **)&device->shaders.objects, &device->shaders.size,
4690 device->shaders.count + 1, sizeof(*device->shaders.objects)))
4692 WARN("Failed to resize shaders array.\n");
4693 return E_OUTOFMEMORY;
4696 entry = &device->shaders.objects[device->shaders.count++];
4697 entry->id = *shader_id;
4698 entry->shader = shader;
4699 IUnknown_AddRef(entry->shader);
4701 return S_OK;
4704 BOOL d2d_device_is_shader_loaded(struct d2d_device *device, REFGUID shader_id)
4706 size_t i;
4708 for (i = 0; i < device->shaders.count; ++i)
4710 if (IsEqualGUID(shader_id, &device->shaders.objects[i].id))
4711 return TRUE;
4714 return FALSE;