dbghelp: Remove DMT_ entries for .DBG and .PDB files.
[wine.git] / dlls / d2d1 / device.c
blobe5548878ee9aaabb6bd1d393624ce276ca63d120
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, interpolation_mode, image_rect, target_offset, NULL);
2549 ID2D1Bitmap_Release(bitmap);
2550 return;
2553 FIXME("Unhandled image %p.\n", image);
2556 static void STDMETHODCALLTYPE d2d_device_context_DrawGdiMetafile(ID2D1DeviceContext1 *iface,
2557 ID2D1GdiMetafile *metafile, const D2D1_POINT_2F *target_offset)
2559 FIXME("iface %p, metafile %p, target_offset %s stub!\n",
2560 iface, metafile, debug_d2d_point_2f(target_offset));
2563 static void STDMETHODCALLTYPE d2d_device_context_ID2D1DeviceContext_DrawBitmap(ID2D1DeviceContext1 *iface,
2564 ID2D1Bitmap *bitmap, const D2D1_RECT_F *dst_rect, float opacity, D2D1_INTERPOLATION_MODE interpolation_mode,
2565 const D2D1_RECT_F *src_rect, const D2D1_MATRIX_4X4_F *perspective_transform)
2567 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
2569 TRACE("iface %p, bitmap %p, dst_rect %s, opacity %.8e, interpolation_mode %#x, "
2570 "src_rect %s, perspective_transform %p.\n",
2571 iface, bitmap, debug_d2d_rect_f(dst_rect), opacity, interpolation_mode,
2572 debug_d2d_rect_f(src_rect), perspective_transform);
2574 if (context->target.type == D2D_TARGET_COMMAND_LIST)
2576 d2d_command_list_draw_bitmap(context->target.command_list, bitmap, dst_rect, opacity, interpolation_mode,
2577 src_rect, perspective_transform);
2579 else
2581 d2d_device_context_draw_bitmap(context, bitmap, dst_rect, opacity, interpolation_mode, src_rect,
2582 NULL, perspective_transform);
2586 static void STDMETHODCALLTYPE d2d_device_context_ID2D1DeviceContext_PushLayer(ID2D1DeviceContext1 *iface,
2587 const D2D1_LAYER_PARAMETERS1 *layer_parameters, ID2D1Layer *layer)
2589 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
2591 FIXME("iface %p, layer_parameters %p, layer %p stub!\n", iface, layer_parameters, layer);
2593 if (context->target.type == D2D_TARGET_COMMAND_LIST)
2594 d2d_command_list_push_layer(context->target.command_list, context, layer_parameters, layer);
2597 static HRESULT STDMETHODCALLTYPE d2d_device_context_InvalidateEffectInputRectangle(ID2D1DeviceContext1 *iface,
2598 ID2D1Effect *effect, UINT32 input, const D2D1_RECT_F *input_rect)
2600 FIXME("iface %p, effect %p, input %u, input_rect %s stub!\n",
2601 iface, effect, input, debug_d2d_rect_f(input_rect));
2603 return E_NOTIMPL;
2606 static HRESULT STDMETHODCALLTYPE d2d_device_context_GetEffectInvalidRectangleCount(ID2D1DeviceContext1 *iface,
2607 ID2D1Effect *effect, UINT32 *rect_count)
2609 FIXME("iface %p, effect %p, rect_count %p stub!\n", iface, effect, rect_count);
2611 return E_NOTIMPL;
2614 static HRESULT STDMETHODCALLTYPE d2d_device_context_GetEffectInvalidRectangles(ID2D1DeviceContext1 *iface,
2615 ID2D1Effect *effect, D2D1_RECT_F *rectangles, UINT32 rect_count)
2617 FIXME("iface %p, effect %p, rectangles %p, rect_count %u stub!\n", iface, effect, rectangles, rect_count);
2619 return E_NOTIMPL;
2622 static HRESULT STDMETHODCALLTYPE d2d_device_context_GetEffectRequiredInputRectangles(ID2D1DeviceContext1 *iface,
2623 ID2D1Effect *effect, const D2D1_RECT_F *image_rect, const D2D1_EFFECT_INPUT_DESCRIPTION *desc,
2624 D2D1_RECT_F *input_rect, UINT32 input_count)
2626 FIXME("iface %p, effect %p, image_rect %s, desc %p, input_rect %p, input_count %u stub!\n",
2627 iface, effect, debug_d2d_rect_f(image_rect), desc, input_rect, input_count);
2629 return E_NOTIMPL;
2632 static void STDMETHODCALLTYPE d2d_device_context_ID2D1DeviceContext_FillOpacityMask(ID2D1DeviceContext1 *iface,
2633 ID2D1Bitmap *mask, ID2D1Brush *brush, const D2D1_RECT_F *dst_rect, const D2D1_RECT_F *src_rect)
2635 struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
2637 FIXME("iface %p, mask %p, brush %p, dst_rect %s, src_rect %s stub!\n",
2638 iface, mask, brush, debug_d2d_rect_f(dst_rect), debug_d2d_rect_f(src_rect));
2640 if (FAILED(context->error.code))
2641 return;
2643 if (context->drawing_state.antialiasMode != D2D1_ANTIALIAS_MODE_ALIASED)
2645 d2d_device_context_set_error(context, D2DERR_WRONG_STATE);
2646 return;
2649 if (context->target.type == D2D_TARGET_COMMAND_LIST)
2650 d2d_command_list_fill_opacity_mask(context->target.command_list, context, mask, brush, dst_rect, src_rect);
2653 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateFilledGeometryRealization(ID2D1DeviceContext1 *iface,
2654 ID2D1Geometry *geometry, float tolerance, ID2D1GeometryRealization **realization)
2656 FIXME("iface %p, geometry %p, tolerance %.8e, realization %p stub!\n", iface, geometry, tolerance,
2657 realization);
2659 return E_NOTIMPL;
2662 static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateStrokedGeometryRealization(ID2D1DeviceContext1 *iface,
2663 ID2D1Geometry *geometry, float tolerance, float stroke_width, ID2D1StrokeStyle *stroke_style,
2664 ID2D1GeometryRealization **realization)
2666 FIXME("iface %p, geometry %p, tolerance %.8e, stroke_width %.8e, stroke_style %p, realization %p stub!\n",
2667 iface, geometry, tolerance, stroke_width, stroke_style, realization);
2669 return E_NOTIMPL;
2672 static void STDMETHODCALLTYPE d2d_device_context_DrawGeometryRealization(ID2D1DeviceContext1 *iface,
2673 ID2D1GeometryRealization *realization, ID2D1Brush *brush)
2675 FIXME("iface %p, realization %p, brush %p stub!\n", iface, realization, brush);
2678 static const struct ID2D1DeviceContext1Vtbl d2d_device_context_vtbl =
2680 d2d_device_context_QueryInterface,
2681 d2d_device_context_AddRef,
2682 d2d_device_context_Release,
2683 d2d_device_context_GetFactory,
2684 d2d_device_context_CreateBitmap,
2685 d2d_device_context_CreateBitmapFromWicBitmap,
2686 d2d_device_context_CreateSharedBitmap,
2687 d2d_device_context_CreateBitmapBrush,
2688 d2d_device_context_CreateSolidColorBrush,
2689 d2d_device_context_CreateGradientStopCollection,
2690 d2d_device_context_CreateLinearGradientBrush,
2691 d2d_device_context_CreateRadialGradientBrush,
2692 d2d_device_context_CreateCompatibleRenderTarget,
2693 d2d_device_context_CreateLayer,
2694 d2d_device_context_CreateMesh,
2695 d2d_device_context_DrawLine,
2696 d2d_device_context_DrawRectangle,
2697 d2d_device_context_FillRectangle,
2698 d2d_device_context_DrawRoundedRectangle,
2699 d2d_device_context_FillRoundedRectangle,
2700 d2d_device_context_DrawEllipse,
2701 d2d_device_context_FillEllipse,
2702 d2d_device_context_DrawGeometry,
2703 d2d_device_context_FillGeometry,
2704 d2d_device_context_FillMesh,
2705 d2d_device_context_FillOpacityMask,
2706 d2d_device_context_DrawBitmap,
2707 d2d_device_context_DrawText,
2708 d2d_device_context_DrawTextLayout,
2709 d2d_device_context_DrawGlyphRun,
2710 d2d_device_context_SetTransform,
2711 d2d_device_context_GetTransform,
2712 d2d_device_context_SetAntialiasMode,
2713 d2d_device_context_GetAntialiasMode,
2714 d2d_device_context_SetTextAntialiasMode,
2715 d2d_device_context_GetTextAntialiasMode,
2716 d2d_device_context_SetTextRenderingParams,
2717 d2d_device_context_GetTextRenderingParams,
2718 d2d_device_context_SetTags,
2719 d2d_device_context_GetTags,
2720 d2d_device_context_PushLayer,
2721 d2d_device_context_PopLayer,
2722 d2d_device_context_Flush,
2723 d2d_device_context_SaveDrawingState,
2724 d2d_device_context_RestoreDrawingState,
2725 d2d_device_context_PushAxisAlignedClip,
2726 d2d_device_context_PopAxisAlignedClip,
2727 d2d_device_context_Clear,
2728 d2d_device_context_BeginDraw,
2729 d2d_device_context_EndDraw,
2730 d2d_device_context_GetPixelFormat,
2731 d2d_device_context_SetDpi,
2732 d2d_device_context_GetDpi,
2733 d2d_device_context_GetSize,
2734 d2d_device_context_GetPixelSize,
2735 d2d_device_context_GetMaximumBitmapSize,
2736 d2d_device_context_IsSupported,
2737 d2d_device_context_ID2D1DeviceContext_CreateBitmap,
2738 d2d_device_context_ID2D1DeviceContext_CreateBitmapFromWicBitmap,
2739 d2d_device_context_CreateColorContext,
2740 d2d_device_context_CreateColorContextFromFilename,
2741 d2d_device_context_CreateColorContextFromWicColorContext,
2742 d2d_device_context_CreateBitmapFromDxgiSurface,
2743 d2d_device_context_CreateEffect,
2744 d2d_device_context_ID2D1DeviceContext_CreateGradientStopCollection,
2745 d2d_device_context_CreateImageBrush,
2746 d2d_device_context_ID2D1DeviceContext_CreateBitmapBrush,
2747 d2d_device_context_CreateCommandList,
2748 d2d_device_context_IsDxgiFormatSupported,
2749 d2d_device_context_IsBufferPrecisionSupported,
2750 d2d_device_context_GetImageLocalBounds,
2751 d2d_device_context_GetImageWorldBounds,
2752 d2d_device_context_GetGlyphRunWorldBounds,
2753 d2d_device_context_GetDevice,
2754 d2d_device_context_SetTarget,
2755 d2d_device_context_GetTarget,
2756 d2d_device_context_SetRenderingControls,
2757 d2d_device_context_GetRenderingControls,
2758 d2d_device_context_SetPrimitiveBlend,
2759 d2d_device_context_GetPrimitiveBlend,
2760 d2d_device_context_SetUnitMode,
2761 d2d_device_context_GetUnitMode,
2762 d2d_device_context_ID2D1DeviceContext_DrawGlyphRun,
2763 d2d_device_context_DrawImage,
2764 d2d_device_context_DrawGdiMetafile,
2765 d2d_device_context_ID2D1DeviceContext_DrawBitmap,
2766 d2d_device_context_ID2D1DeviceContext_PushLayer,
2767 d2d_device_context_InvalidateEffectInputRectangle,
2768 d2d_device_context_GetEffectInvalidRectangleCount,
2769 d2d_device_context_GetEffectInvalidRectangles,
2770 d2d_device_context_GetEffectRequiredInputRectangles,
2771 d2d_device_context_ID2D1DeviceContext_FillOpacityMask,
2772 d2d_device_context_CreateFilledGeometryRealization,
2773 d2d_device_context_CreateStrokedGeometryRealization,
2774 d2d_device_context_DrawGeometryRealization,
2777 static inline struct d2d_device_context *impl_from_IDWriteTextRenderer(IDWriteTextRenderer *iface)
2779 return CONTAINING_RECORD(iface, struct d2d_device_context, IDWriteTextRenderer_iface);
2782 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_QueryInterface(IDWriteTextRenderer *iface, REFIID iid, void **out)
2784 TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
2786 if (IsEqualGUID(iid, &IID_IDWriteTextRenderer)
2787 || IsEqualGUID(iid, &IID_IDWritePixelSnapping)
2788 || IsEqualGUID(iid, &IID_IUnknown))
2790 IDWriteTextRenderer_AddRef(iface);
2791 *out = iface;
2792 return S_OK;
2795 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
2797 *out = NULL;
2798 return E_NOINTERFACE;
2801 static ULONG STDMETHODCALLTYPE d2d_text_renderer_AddRef(IDWriteTextRenderer *iface)
2803 struct d2d_device_context *render_target = impl_from_IDWriteTextRenderer(iface);
2805 TRACE("iface %p.\n", iface);
2807 return d2d_device_context_AddRef(&render_target->ID2D1DeviceContext1_iface);
2810 static ULONG STDMETHODCALLTYPE d2d_text_renderer_Release(IDWriteTextRenderer *iface)
2812 struct d2d_device_context *render_target = impl_from_IDWriteTextRenderer(iface);
2814 TRACE("iface %p.\n", iface);
2816 return d2d_device_context_Release(&render_target->ID2D1DeviceContext1_iface);
2819 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_IsPixelSnappingDisabled(IDWriteTextRenderer *iface,
2820 void *ctx, BOOL *disabled)
2822 struct d2d_draw_text_layout_ctx *context = ctx;
2824 TRACE("iface %p, ctx %p, disabled %p.\n", iface, ctx, disabled);
2826 *disabled = context->options & D2D1_DRAW_TEXT_OPTIONS_NO_SNAP;
2828 return S_OK;
2831 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_GetCurrentTransform(IDWriteTextRenderer *iface,
2832 void *ctx, DWRITE_MATRIX *transform)
2834 struct d2d_device_context *render_target = impl_from_IDWriteTextRenderer(iface);
2836 TRACE("iface %p, ctx %p, transform %p.\n", iface, ctx, transform);
2838 d2d_device_context_GetTransform(&render_target->ID2D1DeviceContext1_iface, (D2D1_MATRIX_3X2_F *)transform);
2840 return S_OK;
2843 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_GetPixelsPerDip(IDWriteTextRenderer *iface, void *ctx, float *ppd)
2845 struct d2d_device_context *render_target = impl_from_IDWriteTextRenderer(iface);
2847 TRACE("iface %p, ctx %p, ppd %p.\n", iface, ctx, ppd);
2849 *ppd = render_target->desc.dpiY / 96.0f;
2851 return S_OK;
2854 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_DrawGlyphRun(IDWriteTextRenderer *iface, void *ctx,
2855 float baseline_origin_x, float baseline_origin_y, DWRITE_MEASURING_MODE measuring_mode,
2856 const DWRITE_GLYPH_RUN *glyph_run, const DWRITE_GLYPH_RUN_DESCRIPTION *glyph_run_desc, IUnknown *effect)
2858 struct d2d_device_context *render_target = impl_from_IDWriteTextRenderer(iface);
2859 D2D1_POINT_2F baseline_origin = {baseline_origin_x, baseline_origin_y};
2860 struct d2d_draw_text_layout_ctx *context = ctx;
2861 BOOL color_font = FALSE;
2862 ID2D1Brush *brush;
2864 TRACE("iface %p, ctx %p, baseline_origin_x %.8e, baseline_origin_y %.8e, "
2865 "measuring_mode %#x, glyph_run %p, glyph_run_desc %p, effect %p.\n",
2866 iface, ctx, baseline_origin_x, baseline_origin_y,
2867 measuring_mode, glyph_run, glyph_run_desc, effect);
2869 if (context->options & ~(D2D1_DRAW_TEXT_OPTIONS_NO_SNAP | D2D1_DRAW_TEXT_OPTIONS_ENABLE_COLOR_FONT))
2870 FIXME("Ignoring options %#x.\n", context->options);
2872 brush = d2d_draw_get_text_brush(context, effect);
2874 TRACE("%s\n", debugstr_wn(glyph_run_desc->string, glyph_run_desc->stringLength));
2876 if (context->options & D2D1_DRAW_TEXT_OPTIONS_ENABLE_COLOR_FONT)
2878 IDWriteFontFace2 *fontface;
2880 if (SUCCEEDED(IDWriteFontFace_QueryInterface(glyph_run->fontFace,
2881 &IID_IDWriteFontFace2, (void **)&fontface)))
2883 color_font = IDWriteFontFace2_IsColorFont(fontface);
2884 IDWriteFontFace2_Release(fontface);
2888 if (color_font)
2890 IDWriteColorGlyphRunEnumerator *layers;
2891 IDWriteFactory2 *dwrite_factory;
2892 HRESULT hr;
2894 if (FAILED(hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, &IID_IDWriteFactory2,
2895 (IUnknown **)&dwrite_factory)))
2897 ERR("Failed to create dwrite factory, hr %#lx.\n", hr);
2898 ID2D1Brush_Release(brush);
2899 return hr;
2902 hr = IDWriteFactory2_TranslateColorGlyphRun(dwrite_factory, baseline_origin_x, baseline_origin_y,
2903 glyph_run, glyph_run_desc, measuring_mode, (DWRITE_MATRIX *)&render_target->drawing_state.transform, 0, &layers);
2904 IDWriteFactory2_Release(dwrite_factory);
2905 if (FAILED(hr))
2907 ERR("Failed to create colour glyph run enumerator, hr %#lx.\n", hr);
2908 ID2D1Brush_Release(brush);
2909 return hr;
2912 for (;;)
2914 const DWRITE_COLOR_GLYPH_RUN *color_run;
2915 ID2D1Brush *color_brush;
2916 D2D1_POINT_2F origin;
2917 BOOL has_run = FALSE;
2919 if (FAILED(hr = IDWriteColorGlyphRunEnumerator_MoveNext(layers, &has_run)))
2921 ERR("Failed to switch colour glyph layer, hr %#lx.\n", hr);
2922 break;
2925 if (!has_run)
2926 break;
2928 if (FAILED(hr = IDWriteColorGlyphRunEnumerator_GetCurrentRun(layers, &color_run)))
2930 ERR("Failed to get current colour run, hr %#lx.\n", hr);
2931 break;
2934 if (color_run->paletteIndex == 0xffff)
2935 color_brush = brush;
2936 else
2938 if (FAILED(hr = d2d_device_context_CreateSolidColorBrush(&render_target->ID2D1DeviceContext1_iface,
2939 &color_run->runColor, NULL, (ID2D1SolidColorBrush **)&color_brush)))
2941 ERR("Failed to create solid colour brush, hr %#lx.\n", hr);
2942 break;
2946 origin.x = color_run->baselineOriginX;
2947 origin.y = color_run->baselineOriginY;
2948 d2d_device_context_draw_glyph_run(render_target, origin, &color_run->glyphRun,
2949 color_run->glyphRunDescription, color_brush, measuring_mode);
2951 if (color_brush != brush)
2952 ID2D1Brush_Release(color_brush);
2955 IDWriteColorGlyphRunEnumerator_Release(layers);
2957 else
2958 d2d_device_context_draw_glyph_run(render_target, baseline_origin, glyph_run, glyph_run_desc,
2959 brush, measuring_mode);
2961 ID2D1Brush_Release(brush);
2963 return S_OK;
2966 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_DrawUnderline(IDWriteTextRenderer *iface, void *ctx,
2967 float baseline_origin_x, float baseline_origin_y, const DWRITE_UNDERLINE *underline, IUnknown *effect)
2969 struct d2d_device_context *render_target = impl_from_IDWriteTextRenderer(iface);
2970 const D2D1_MATRIX_3X2_F *m = &render_target->drawing_state.transform;
2971 struct d2d_draw_text_layout_ctx *context = ctx;
2972 D2D1_ANTIALIAS_MODE prev_antialias_mode;
2973 D2D1_POINT_2F start, end;
2974 ID2D1Brush *brush;
2975 float thickness;
2977 TRACE("iface %p, ctx %p, baseline_origin_x %.8e, baseline_origin_y %.8e, underline %p, effect %p\n",
2978 iface, ctx, baseline_origin_x, baseline_origin_y, underline, effect);
2980 /* minimal thickness in DIPs that will result in at least 1 pixel thick line */
2981 thickness = max(96.0f / (render_target->desc.dpiY * sqrtf(m->_21 * m->_21 + m->_22 * m->_22)),
2982 underline->thickness);
2984 brush = d2d_draw_get_text_brush(context, effect);
2986 start.x = baseline_origin_x;
2987 start.y = baseline_origin_y + underline->offset + thickness / 2.0f;
2988 end.x = start.x + underline->width;
2989 end.y = start.y;
2990 prev_antialias_mode = d2d_device_context_set_aa_mode_from_text_aa_mode(render_target);
2991 d2d_device_context_DrawLine(&render_target->ID2D1DeviceContext1_iface, start, end, brush, thickness, NULL);
2992 render_target->drawing_state.antialiasMode = prev_antialias_mode;
2994 ID2D1Brush_Release(brush);
2996 return S_OK;
2999 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_DrawStrikethrough(IDWriteTextRenderer *iface, void *ctx,
3000 float baseline_origin_x, float baseline_origin_y, const DWRITE_STRIKETHROUGH *strikethrough, IUnknown *effect)
3002 struct d2d_device_context *render_target = impl_from_IDWriteTextRenderer(iface);
3003 const D2D1_MATRIX_3X2_F *m = &render_target->drawing_state.transform;
3004 struct d2d_draw_text_layout_ctx *context = ctx;
3005 D2D1_ANTIALIAS_MODE prev_antialias_mode;
3006 D2D1_POINT_2F start, end;
3007 ID2D1Brush *brush;
3008 float thickness;
3010 TRACE("iface %p, ctx %p, baseline_origin_x %.8e, baseline_origin_y %.8e, strikethrough %p, effect %p.\n",
3011 iface, ctx, baseline_origin_x, baseline_origin_y, strikethrough, effect);
3013 /* minimal thickness in DIPs that will result in at least 1 pixel thick line */
3014 thickness = max(96.0f / (render_target->desc.dpiY * sqrtf(m->_21 * m->_21 + m->_22 * m->_22)),
3015 strikethrough->thickness);
3017 brush = d2d_draw_get_text_brush(context, effect);
3019 start.x = baseline_origin_x;
3020 start.y = baseline_origin_y + strikethrough->offset + thickness / 2.0f;
3021 end.x = start.x + strikethrough->width;
3022 end.y = start.y;
3023 prev_antialias_mode = d2d_device_context_set_aa_mode_from_text_aa_mode(render_target);
3024 d2d_device_context_DrawLine(&render_target->ID2D1DeviceContext1_iface, start, end, brush, thickness, NULL);
3025 render_target->drawing_state.antialiasMode = prev_antialias_mode;
3027 ID2D1Brush_Release(brush);
3029 return S_OK;
3032 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_DrawInlineObject(IDWriteTextRenderer *iface, void *ctx,
3033 float origin_x, float origin_y, IDWriteInlineObject *object, BOOL is_sideways, BOOL is_rtl, IUnknown *effect)
3035 struct d2d_draw_text_layout_ctx *context = ctx;
3036 ID2D1Brush *brush;
3037 HRESULT hr;
3039 TRACE("iface %p, ctx %p, origin_x %.8e, origin_y %.8e, object %p, is_sideways %#x, is_rtl %#x, effect %p.\n",
3040 iface, ctx, origin_x, origin_y, object, is_sideways, is_rtl, effect);
3042 /* Inline objects may not pass effects all the way down, when using layout object internally for example.
3043 This is how default trimming sign object in DirectWrite works - it does not use effect passed to Draw(),
3044 and resulting DrawGlyphRun() is always called with NULL effect, however original effect is used and correct
3045 brush is selected at Direct2D level. */
3046 brush = context->brush;
3047 context->brush = d2d_draw_get_text_brush(context, effect);
3049 hr = IDWriteInlineObject_Draw(object, ctx, iface, origin_x, origin_y, is_sideways, is_rtl, effect);
3051 ID2D1Brush_Release(context->brush);
3052 context->brush = brush;
3054 return hr;
3057 static const struct IDWriteTextRendererVtbl d2d_text_renderer_vtbl =
3059 d2d_text_renderer_QueryInterface,
3060 d2d_text_renderer_AddRef,
3061 d2d_text_renderer_Release,
3062 d2d_text_renderer_IsPixelSnappingDisabled,
3063 d2d_text_renderer_GetCurrentTransform,
3064 d2d_text_renderer_GetPixelsPerDip,
3065 d2d_text_renderer_DrawGlyphRun,
3066 d2d_text_renderer_DrawUnderline,
3067 d2d_text_renderer_DrawStrikethrough,
3068 d2d_text_renderer_DrawInlineObject,
3071 static inline struct d2d_device_context *impl_from_ID2D1GdiInteropRenderTarget(ID2D1GdiInteropRenderTarget *iface)
3073 return CONTAINING_RECORD(iface, struct d2d_device_context, ID2D1GdiInteropRenderTarget_iface);
3076 static HRESULT STDMETHODCALLTYPE d2d_gdi_interop_render_target_QueryInterface(ID2D1GdiInteropRenderTarget *iface,
3077 REFIID iid, void **out)
3079 struct d2d_device_context *render_target = impl_from_ID2D1GdiInteropRenderTarget(iface);
3081 TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
3083 return IUnknown_QueryInterface(render_target->outer_unknown, iid, out);
3086 static ULONG STDMETHODCALLTYPE d2d_gdi_interop_render_target_AddRef(ID2D1GdiInteropRenderTarget *iface)
3088 struct d2d_device_context *render_target = impl_from_ID2D1GdiInteropRenderTarget(iface);
3090 TRACE("iface %p.\n", iface);
3092 return IUnknown_AddRef(render_target->outer_unknown);
3095 static ULONG STDMETHODCALLTYPE d2d_gdi_interop_render_target_Release(ID2D1GdiInteropRenderTarget *iface)
3097 struct d2d_device_context *render_target = impl_from_ID2D1GdiInteropRenderTarget(iface);
3099 TRACE("iface %p.\n", iface);
3101 return IUnknown_Release(render_target->outer_unknown);
3104 static HRESULT d2d_gdi_interop_get_surface(struct d2d_device_context *context, IDXGISurface1 **surface)
3106 ID3D11Resource *resource;
3107 HRESULT hr;
3109 if (context->target.type != D2D_TARGET_BITMAP)
3111 FIXME("Unimplemented for target type %u.\n", context->target.type);
3112 return E_NOTIMPL;
3115 if (!(context->target.bitmap->options & D2D1_BITMAP_OPTIONS_GDI_COMPATIBLE))
3116 return D2DERR_TARGET_NOT_GDI_COMPATIBLE;
3118 ID3D11RenderTargetView_GetResource(context->target.bitmap->rtv, &resource);
3119 hr = ID3D11Resource_QueryInterface(resource, &IID_IDXGISurface1, (void **)surface);
3120 ID3D11Resource_Release(resource);
3121 if (FAILED(hr))
3123 *surface = NULL;
3124 WARN("Failed to get DXGI surface, %#lx.\n", hr);
3125 return hr;
3128 return hr;
3131 static HRESULT STDMETHODCALLTYPE d2d_gdi_interop_render_target_GetDC(ID2D1GdiInteropRenderTarget *iface,
3132 D2D1_DC_INITIALIZE_MODE mode, HDC *dc)
3134 struct d2d_device_context *render_target = impl_from_ID2D1GdiInteropRenderTarget(iface);
3135 IDXGISurface1 *surface;
3136 HRESULT hr;
3138 TRACE("iface %p, mode %d, dc %p.\n", iface, mode, dc);
3140 *dc = NULL;
3142 if (render_target->target.hdc)
3143 return D2DERR_WRONG_STATE;
3145 if (FAILED(hr = d2d_gdi_interop_get_surface(render_target, &surface)))
3146 return hr;
3148 hr = IDXGISurface1_GetDC(surface, mode != D2D1_DC_INITIALIZE_MODE_COPY, &render_target->target.hdc);
3149 IDXGISurface1_Release(surface);
3151 if (SUCCEEDED(hr))
3152 *dc = render_target->target.hdc;
3154 return hr;
3157 static HRESULT STDMETHODCALLTYPE d2d_gdi_interop_render_target_ReleaseDC(ID2D1GdiInteropRenderTarget *iface,
3158 const RECT *update)
3160 struct d2d_device_context *render_target = impl_from_ID2D1GdiInteropRenderTarget(iface);
3161 IDXGISurface1 *surface;
3162 RECT update_rect;
3163 HRESULT hr;
3165 TRACE("iface %p, update rect %s.\n", iface, wine_dbgstr_rect(update));
3167 if (!render_target->target.hdc)
3168 return D2DERR_WRONG_STATE;
3170 if (FAILED(hr = d2d_gdi_interop_get_surface(render_target, &surface)))
3171 return hr;
3173 render_target->target.hdc = NULL;
3174 if (update)
3175 update_rect = *update;
3176 hr = IDXGISurface1_ReleaseDC(surface, update ? &update_rect : NULL);
3177 IDXGISurface1_Release(surface);
3179 return hr;
3182 static const struct ID2D1GdiInteropRenderTargetVtbl d2d_gdi_interop_render_target_vtbl =
3184 d2d_gdi_interop_render_target_QueryInterface,
3185 d2d_gdi_interop_render_target_AddRef,
3186 d2d_gdi_interop_render_target_Release,
3187 d2d_gdi_interop_render_target_GetDC,
3188 d2d_gdi_interop_render_target_ReleaseDC,
3191 static HRESULT d2d_device_context_init(struct d2d_device_context *render_target,
3192 struct d2d_device *device, IUnknown *outer_unknown, const struct d2d_device_context_ops *ops)
3194 D3D11_SUBRESOURCE_DATA buffer_data;
3195 struct d2d_device *device_impl;
3196 IDWriteFactory *dwrite_factory;
3197 D3D11_RASTERIZER_DESC rs_desc;
3198 D3D11_BUFFER_DESC buffer_desc;
3199 unsigned int i;
3200 HRESULT hr;
3202 static const D3D11_INPUT_ELEMENT_DESC il_desc_outline[] =
3204 {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0},
3205 {"PREV", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 8, D3D11_INPUT_PER_VERTEX_DATA, 0},
3206 {"NEXT", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 16, D3D11_INPUT_PER_VERTEX_DATA, 0},
3208 static const D3D11_INPUT_ELEMENT_DESC il_desc_curve_outline[] =
3210 {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0},
3211 {"P", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 8, D3D11_INPUT_PER_VERTEX_DATA, 0},
3212 {"P", 1, DXGI_FORMAT_R32G32_FLOAT, 0, 16, D3D11_INPUT_PER_VERTEX_DATA, 0},
3213 {"P", 2, DXGI_FORMAT_R32G32_FLOAT, 0, 24, D3D11_INPUT_PER_VERTEX_DATA, 0},
3214 {"PREV", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 32, D3D11_INPUT_PER_VERTEX_DATA, 0},
3215 {"NEXT", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 40, D3D11_INPUT_PER_VERTEX_DATA, 0},
3217 static const D3D11_INPUT_ELEMENT_DESC il_desc_triangle[] =
3219 {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0},
3221 static const D3D11_INPUT_ELEMENT_DESC il_desc_curve[] =
3223 {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0},
3224 {"TEXCOORD", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 8, D3D11_INPUT_PER_VERTEX_DATA, 0},
3226 static const DWORD vs_code_outline[] =
3228 #if 0
3229 float3x2 transform_geometry;
3230 float stroke_width;
3231 float4 transform_rtx;
3232 float4 transform_rty;
3234 struct output
3236 float2 p : WORLD_POSITION;
3237 float4 b : BEZIER;
3238 nointerpolation float2x2 stroke_transform : STROKE_TRANSFORM;
3239 float4 position : SV_POSITION;
3242 /* The lines PₚᵣₑᵥP₀ and P₀Pₙₑₓₜ, both offset by ±½w, intersect each other at:
3244 * Pᵢ = P₀ ± w · ½q⃑ᵢ.
3246 * Where:
3248 * q⃑ᵢ = q̂ₚᵣₑᵥ⊥ + tan(½θ) · -q̂ₚᵣₑᵥ
3249 * θ = ∠PₚᵣₑᵥP₀Pₙₑₓₜ
3250 * q⃑ₚᵣₑᵥ = P₀ - Pₚᵣₑᵥ */
3251 void main(float2 position : POSITION, float2 prev : PREV, float2 next : NEXT, out struct output o)
3253 float2 q_prev, q_next, v_p, q_i;
3254 float2x2 geom;
3255 float l;
3257 o.stroke_transform = float2x2(transform_rtx.xy, transform_rty.xy) * stroke_width * 0.5f;
3259 geom = float2x2(transform_geometry._11_21, transform_geometry._12_22);
3260 q_prev = normalize(mul(geom, prev));
3261 q_next = normalize(mul(geom, next));
3263 /* tan(½θ) = sin(θ) / (1 + cos(θ))
3264 * = (q̂ₚᵣₑᵥ⊥ · q̂ₙₑₓₜ) / (1 + (q̂ₚᵣₑᵥ · q̂ₙₑₓₜ)) */
3265 v_p = float2(-q_prev.y, q_prev.x);
3266 l = -dot(v_p, q_next) / (1.0f + dot(q_prev, q_next));
3267 q_i = l * q_prev + v_p;
3269 o.b = float4(0.0, 0.0, 0.0, 0.0);
3271 o.p = mul(float3(position, 1.0f), transform_geometry) + stroke_width * 0.5f * q_i;
3272 position = mul(float2x3(transform_rtx.xyz, transform_rty.xyz), float3(o.p, 1.0f))
3273 * float2(transform_rtx.w, transform_rty.w);
3274 o.position = float4(position + float2(-1.0f, 1.0f), 0.0f, 1.0f);
3276 #endif
3277 0x43425844, 0xfb16cd75, 0xf5ec3e80, 0xceacf250, 0x91d29d18, 0x00000001, 0x00000608, 0x00000003,
3278 0x0000002c, 0x00000098, 0x00000154, 0x4e475349, 0x00000064, 0x00000003, 0x00000008, 0x00000050,
3279 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000303, 0x00000059, 0x00000000, 0x00000000,
3280 0x00000003, 0x00000001, 0x00000303, 0x0000005e, 0x00000000, 0x00000000, 0x00000003, 0x00000002,
3281 0x00000303, 0x49534f50, 0x4e4f4954, 0x45525000, 0x454e0056, 0xab005458, 0x4e47534f, 0x000000b4,
3282 0x00000005, 0x00000008, 0x00000080, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000c03,
3283 0x0000008f, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x0000000f, 0x00000096, 0x00000000,
3284 0x00000000, 0x00000003, 0x00000002, 0x00000c03, 0x00000096, 0x00000001, 0x00000000, 0x00000003,
3285 0x00000003, 0x00000c03, 0x000000a7, 0x00000000, 0x00000001, 0x00000003, 0x00000004, 0x0000000f,
3286 0x4c524f57, 0x4f505f44, 0x49544953, 0x42004e4f, 0x45495a45, 0x54530052, 0x454b4f52, 0x4152545f,
3287 0x4f46534e, 0x53004d52, 0x4f505f56, 0x49544953, 0xab004e4f, 0x52444853, 0x000004ac, 0x00010040,
3288 0x0000012b, 0x04000059, 0x00208e46, 0x00000000, 0x00000004, 0x0300005f, 0x00101032, 0x00000000,
3289 0x0300005f, 0x00101032, 0x00000001, 0x0300005f, 0x00101032, 0x00000002, 0x03000065, 0x00102032,
3290 0x00000000, 0x03000065, 0x001020f2, 0x00000001, 0x03000065, 0x00102032, 0x00000002, 0x03000065,
3291 0x00102032, 0x00000003, 0x04000067, 0x001020f2, 0x00000004, 0x00000001, 0x02000068, 0x00000003,
3292 0x0800000f, 0x00100012, 0x00000000, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000002,
3293 0x0800000f, 0x00100022, 0x00000000, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000002,
3294 0x0700000f, 0x00100042, 0x00000000, 0x00100046, 0x00000000, 0x00100046, 0x00000000, 0x05000044,
3295 0x00100042, 0x00000000, 0x0010002a, 0x00000000, 0x07000038, 0x00100032, 0x00000000, 0x00100aa6,
3296 0x00000000, 0x00100046, 0x00000000, 0x0800000f, 0x00100012, 0x00000001, 0x00208046, 0x00000000,
3297 0x00000000, 0x00101046, 0x00000001, 0x0800000f, 0x00100022, 0x00000001, 0x00208046, 0x00000000,
3298 0x00000001, 0x00101046, 0x00000001, 0x0700000f, 0x00100042, 0x00000000, 0x00100046, 0x00000001,
3299 0x00100046, 0x00000001, 0x05000044, 0x00100042, 0x00000000, 0x0010002a, 0x00000000, 0x07000038,
3300 0x00100032, 0x00000001, 0x00100aa6, 0x00000000, 0x00100046, 0x00000001, 0x06000036, 0x001000c2,
3301 0x00000001, 0x80100556, 0x00000041, 0x00000001, 0x0700000f, 0x00100042, 0x00000000, 0x00100a26,
3302 0x00000001, 0x00100046, 0x00000000, 0x0700000f, 0x00100012, 0x00000000, 0x00100046, 0x00000001,
3303 0x00100046, 0x00000000, 0x07000000, 0x00100012, 0x00000000, 0x0010000a, 0x00000000, 0x00004001,
3304 0x3f800000, 0x0800000e, 0x00100012, 0x00000000, 0x8010002a, 0x00000041, 0x00000000, 0x0010000a,
3305 0x00000000, 0x09000032, 0x00100032, 0x00000000, 0x00100006, 0x00000000, 0x00100046, 0x00000001,
3306 0x00100f36, 0x00000001, 0x08000038, 0x00100042, 0x00000000, 0x0020803a, 0x00000000, 0x00000001,
3307 0x00004001, 0x3f000000, 0x05000036, 0x00100032, 0x00000001, 0x00101046, 0x00000000, 0x05000036,
3308 0x00100042, 0x00000001, 0x00004001, 0x3f800000, 0x08000010, 0x00100012, 0x00000002, 0x00100246,
3309 0x00000001, 0x00208246, 0x00000000, 0x00000000, 0x08000010, 0x00100022, 0x00000002, 0x00100246,
3310 0x00000001, 0x00208246, 0x00000000, 0x00000001, 0x09000032, 0x00100032, 0x00000000, 0x00100aa6,
3311 0x00000000, 0x00100046, 0x00000000, 0x00100046, 0x00000002, 0x05000036, 0x00102032, 0x00000000,
3312 0x00100046, 0x00000000, 0x08000036, 0x001020f2, 0x00000001, 0x00004002, 0x00000000, 0x00000000,
3313 0x00000000, 0x00000000, 0x06000036, 0x00100032, 0x00000001, 0x00208046, 0x00000000, 0x00000002,
3314 0x06000036, 0x001000c2, 0x00000001, 0x00208406, 0x00000000, 0x00000003, 0x08000038, 0x001000f2,
3315 0x00000001, 0x00100e46, 0x00000001, 0x00208ff6, 0x00000000, 0x00000001, 0x0a000038, 0x001000f2,
3316 0x00000001, 0x00100e46, 0x00000001, 0x00004002, 0x3f000000, 0x3f000000, 0x3f000000, 0x3f000000,
3317 0x05000036, 0x00102032, 0x00000002, 0x00100086, 0x00000001, 0x05000036, 0x00102032, 0x00000003,
3318 0x001005d6, 0x00000001, 0x05000036, 0x00100042, 0x00000000, 0x00004001, 0x3f800000, 0x08000010,
3319 0x00100082, 0x00000000, 0x00208246, 0x00000000, 0x00000002, 0x00100246, 0x00000000, 0x08000010,
3320 0x00100012, 0x00000000, 0x00208246, 0x00000000, 0x00000003, 0x00100246, 0x00000000, 0x08000038,
3321 0x00100022, 0x00000000, 0x0010000a, 0x00000000, 0x0020803a, 0x00000000, 0x00000003, 0x08000038,
3322 0x00100012, 0x00000000, 0x0010003a, 0x00000000, 0x0020803a, 0x00000000, 0x00000002, 0x0a000000,
3323 0x00102032, 0x00000004, 0x00100046, 0x00000000, 0x00004002, 0xbf800000, 0x3f800000, 0x00000000,
3324 0x00000000, 0x08000036, 0x001020c2, 0x00000004, 0x00004002, 0x00000000, 0x00000000, 0x00000000,
3325 0x3f800000, 0x0100003e,
3327 /* ⎡p0.x p0.y 1⎤
3328 * A = ⎢p1.x p1.y 1⎥
3329 * ⎣p2.x p2.y 1⎦
3331 * ⎡0 0⎤
3332 * B = ⎢½ 0⎥
3333 * ⎣1 1⎦
3335 * A' = ⎡p1.x-p0.x p1.y-p0.y⎤
3336 * ⎣p2.x-p0.x p2.y-p0.y⎦
3338 * B' = ⎡½ 0⎤
3339 * ⎣1 1⎦
3341 * A'T = B'
3342 * T = A'⁻¹B'
3344 static const DWORD vs_code_bezier_outline[] =
3346 #if 0
3347 float3x2 transform_geometry;
3348 float stroke_width;
3349 float4 transform_rtx;
3350 float4 transform_rty;
3352 struct output
3354 float2 p : WORLD_POSITION;
3355 float4 b : BEZIER;
3356 nointerpolation float2x2 stroke_transform : STROKE_TRANSFORM;
3357 float4 position : SV_POSITION;
3360 void main(float2 position : POSITION, float2 p0 : P0, float2 p1 : P1, float2 p2 : P2,
3361 float2 prev : PREV, float2 next : NEXT, out struct output o)
3363 float2 q_prev, q_next, v_p, q_i, p;
3364 float2x2 geom, rt;
3365 float l;
3367 geom = float2x2(transform_geometry._11_21, transform_geometry._12_22);
3368 rt = float2x2(transform_rtx.xy, transform_rty.xy);
3369 o.stroke_transform = rt * stroke_width * 0.5f;
3371 p = mul(geom, position);
3372 p0 = mul(geom, p0);
3373 p1 = mul(geom, p1);
3374 p2 = mul(geom, p2);
3376 p -= p0;
3377 p1 -= p0;
3378 p2 -= p0;
3380 q_prev = normalize(mul(geom, prev));
3381 q_next = normalize(mul(geom, next));
3383 v_p = float2(-q_prev.y, q_prev.x);
3384 l = -dot(v_p, q_next) / (1.0f + dot(q_prev, q_next));
3385 q_i = l * q_prev + v_p;
3386 p += 0.5f * stroke_width * q_i;
3388 v_p = mul(rt, p2);
3389 v_p = normalize(float2(-v_p.y, v_p.x));
3390 if (abs(dot(mul(rt, p1), v_p)) < 1.0f)
3392 o.b.xzw = float3(0.0f, 0.0f, 0.0f);
3393 o.b.y = dot(mul(rt, p), v_p);
3395 else
3397 o.b.zw = sign(dot(mul(rt, p1), v_p)) * v_p;
3398 v_p = -float2(-p.y, p.x) / dot(float2(-p1.y, p1.x), p2);
3399 o.b.x = dot(v_p, p1 - 0.5f * p2);
3400 o.b.y = dot(v_p, p1);
3403 o.p = mul(float3(position, 1.0f), transform_geometry) + 0.5f * stroke_width * q_i;
3404 position = mul(float2x3(transform_rtx.xyz, transform_rty.xyz), float3(o.p, 1.0f))
3405 * float2(transform_rtx.w, transform_rty.w);
3406 o.position = float4(position + float2(-1.0f, 1.0f), 0.0f, 1.0f);
3408 #endif
3409 0x43425844, 0x356a0c5f, 0x8e4ba153, 0xe52cf793, 0xa6b774ea, 0x00000001, 0x00000afc, 0x00000003,
3410 0x0000002c, 0x000000e4, 0x000001a0, 0x4e475349, 0x000000b0, 0x00000006, 0x00000008, 0x00000098,
3411 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000303, 0x000000a1, 0x00000000, 0x00000000,
3412 0x00000003, 0x00000001, 0x00000303, 0x000000a1, 0x00000001, 0x00000000, 0x00000003, 0x00000002,
3413 0x00000303, 0x000000a1, 0x00000002, 0x00000000, 0x00000003, 0x00000003, 0x00000303, 0x000000a3,
3414 0x00000000, 0x00000000, 0x00000003, 0x00000004, 0x00000303, 0x000000a8, 0x00000000, 0x00000000,
3415 0x00000003, 0x00000005, 0x00000303, 0x49534f50, 0x4e4f4954, 0x50005000, 0x00564552, 0x5458454e,
3416 0xababab00, 0x4e47534f, 0x000000b4, 0x00000005, 0x00000008, 0x00000080, 0x00000000, 0x00000000,
3417 0x00000003, 0x00000000, 0x00000c03, 0x0000008f, 0x00000000, 0x00000000, 0x00000003, 0x00000001,
3418 0x0000000f, 0x00000096, 0x00000000, 0x00000000, 0x00000003, 0x00000002, 0x00000c03, 0x00000096,
3419 0x00000001, 0x00000000, 0x00000003, 0x00000003, 0x00000c03, 0x000000a7, 0x00000000, 0x00000001,
3420 0x00000003, 0x00000004, 0x0000000f, 0x4c524f57, 0x4f505f44, 0x49544953, 0x42004e4f, 0x45495a45,
3421 0x54530052, 0x454b4f52, 0x4152545f, 0x4f46534e, 0x53004d52, 0x4f505f56, 0x49544953, 0xab004e4f,
3422 0x52444853, 0x00000954, 0x00010040, 0x00000255, 0x04000059, 0x00208e46, 0x00000000, 0x00000004,
3423 0x0300005f, 0x00101032, 0x00000000, 0x0300005f, 0x00101032, 0x00000001, 0x0300005f, 0x00101032,
3424 0x00000002, 0x0300005f, 0x00101032, 0x00000003, 0x0300005f, 0x00101032, 0x00000004, 0x0300005f,
3425 0x00101032, 0x00000005, 0x03000065, 0x00102032, 0x00000000, 0x03000065, 0x001020f2, 0x00000001,
3426 0x03000065, 0x00102032, 0x00000002, 0x03000065, 0x00102032, 0x00000003, 0x04000067, 0x001020f2,
3427 0x00000004, 0x00000001, 0x02000068, 0x00000006, 0x0800000f, 0x00100012, 0x00000000, 0x00208046,
3428 0x00000000, 0x00000000, 0x00101046, 0x00000005, 0x0800000f, 0x00100022, 0x00000000, 0x00208046,
3429 0x00000000, 0x00000001, 0x00101046, 0x00000005, 0x0700000f, 0x00100042, 0x00000000, 0x00100046,
3430 0x00000000, 0x00100046, 0x00000000, 0x05000044, 0x00100042, 0x00000000, 0x0010002a, 0x00000000,
3431 0x07000038, 0x00100032, 0x00000000, 0x00100aa6, 0x00000000, 0x00100046, 0x00000000, 0x0800000f,
3432 0x00100012, 0x00000001, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000004, 0x0800000f,
3433 0x00100022, 0x00000001, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000004, 0x0700000f,
3434 0x00100042, 0x00000000, 0x00100046, 0x00000001, 0x00100046, 0x00000001, 0x05000044, 0x00100042,
3435 0x00000000, 0x0010002a, 0x00000000, 0x07000038, 0x00100032, 0x00000001, 0x00100aa6, 0x00000000,
3436 0x00100046, 0x00000001, 0x06000036, 0x001000c2, 0x00000001, 0x80100556, 0x00000041, 0x00000001,
3437 0x0700000f, 0x00100042, 0x00000000, 0x00100a26, 0x00000001, 0x00100046, 0x00000000, 0x0700000f,
3438 0x00100012, 0x00000000, 0x00100046, 0x00000001, 0x00100046, 0x00000000, 0x07000000, 0x00100012,
3439 0x00000000, 0x0010000a, 0x00000000, 0x00004001, 0x3f800000, 0x0800000e, 0x00100012, 0x00000000,
3440 0x8010002a, 0x00000041, 0x00000000, 0x0010000a, 0x00000000, 0x09000032, 0x00100032, 0x00000000,
3441 0x00100006, 0x00000000, 0x00100046, 0x00000001, 0x00100f36, 0x00000001, 0x05000036, 0x00100032,
3442 0x00000001, 0x00101046, 0x00000000, 0x05000036, 0x00100042, 0x00000001, 0x00004001, 0x3f800000,
3443 0x08000010, 0x00100012, 0x00000002, 0x00100246, 0x00000001, 0x00208246, 0x00000000, 0x00000000,
3444 0x08000010, 0x00100022, 0x00000002, 0x00100246, 0x00000001, 0x00208246, 0x00000000, 0x00000001,
3445 0x08000038, 0x00100042, 0x00000000, 0x0020803a, 0x00000000, 0x00000001, 0x00004001, 0x3f000000,
3446 0x09000032, 0x00100032, 0x00000001, 0x00100aa6, 0x00000000, 0x00100046, 0x00000000, 0x00100046,
3447 0x00000002, 0x05000036, 0x00102032, 0x00000000, 0x00100046, 0x00000001, 0x0800000f, 0x00100012,
3448 0x00000002, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000000, 0x0800000f, 0x00100022,
3449 0x00000002, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000000, 0x0800000f, 0x00100012,
3450 0x00000003, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000001, 0x0800000f, 0x00100022,
3451 0x00000003, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000001, 0x08000000, 0x00100032,
3452 0x00000002, 0x00100046, 0x00000002, 0x80100046, 0x00000041, 0x00000003, 0x09000032, 0x00100032,
3453 0x00000000, 0x00100aa6, 0x00000000, 0x00100046, 0x00000000, 0x00100046, 0x00000002, 0x0800000f,
3454 0x00100012, 0x00000002, 0x00208046, 0x00000000, 0x00000002, 0x00100046, 0x00000000, 0x0800000f,
3455 0x00100022, 0x00000002, 0x00208046, 0x00000000, 0x00000003, 0x00100046, 0x00000000, 0x0800000f,
3456 0x00100012, 0x00000004, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000003, 0x0800000f,
3457 0x00100022, 0x00000004, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000003, 0x08000000,
3458 0x001000c2, 0x00000002, 0x80100406, 0x00000041, 0x00000003, 0x00100406, 0x00000004, 0x0800000f,
3459 0x00100082, 0x00000000, 0x00208046, 0x00000000, 0x00000003, 0x00100ae6, 0x00000002, 0x06000036,
3460 0x00100042, 0x00000003, 0x8010003a, 0x00000041, 0x00000000, 0x0800000f, 0x00100082, 0x00000003,
3461 0x00208046, 0x00000000, 0x00000002, 0x00100ae6, 0x00000002, 0x0700000f, 0x00100082, 0x00000000,
3462 0x00100ae6, 0x00000003, 0x00100ae6, 0x00000003, 0x05000044, 0x00100082, 0x00000000, 0x0010003a,
3463 0x00000000, 0x07000038, 0x001000c2, 0x00000003, 0x00100ff6, 0x00000000, 0x00100ea6, 0x00000003,
3464 0x0700000f, 0x00100022, 0x00000004, 0x00100046, 0x00000002, 0x00100ae6, 0x00000003, 0x06000036,
3465 0x00100042, 0x00000000, 0x8010001a, 0x00000041, 0x00000000, 0x0800000f, 0x00100012, 0x00000002,
3466 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000002, 0x0800000f, 0x00100022, 0x00000002,
3467 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000002, 0x08000000, 0x00100032, 0x00000005,
3468 0x80100046, 0x00000041, 0x00000003, 0x00100046, 0x00000002, 0x06000036, 0x00100042, 0x00000005,
3469 0x8010001a, 0x00000041, 0x00000005, 0x0700000f, 0x00100022, 0x00000000, 0x00100a26, 0x00000005,
3470 0x00100ae6, 0x00000002, 0x0d000032, 0x00100032, 0x00000002, 0x80100ae6, 0x00000041, 0x00000002,
3471 0x00004002, 0x3f000000, 0x3f000000, 0x00000000, 0x00000000, 0x00100046, 0x00000005, 0x0800000e,
3472 0x00100032, 0x00000000, 0x80100a26, 0x00000041, 0x00000000, 0x00100556, 0x00000000, 0x0700000f,
3473 0x00100012, 0x00000002, 0x00100046, 0x00000000, 0x00100046, 0x00000002, 0x0700000f, 0x00100022,
3474 0x00000002, 0x00100046, 0x00000000, 0x00100046, 0x00000005, 0x0800000f, 0x00100012, 0x00000000,
3475 0x00208046, 0x00000000, 0x00000002, 0x00100046, 0x00000005, 0x0800000f, 0x00100022, 0x00000000,
3476 0x00208046, 0x00000000, 0x00000003, 0x00100046, 0x00000005, 0x0700000f, 0x00100012, 0x00000000,
3477 0x00100046, 0x00000000, 0x00100ae6, 0x00000003, 0x07000031, 0x00100022, 0x00000000, 0x00004001,
3478 0x00000000, 0x0010000a, 0x00000000, 0x07000031, 0x00100042, 0x00000000, 0x0010000a, 0x00000000,
3479 0x00004001, 0x00000000, 0x08000031, 0x00100012, 0x00000000, 0x8010000a, 0x00000081, 0x00000000,
3480 0x00004001, 0x3f800000, 0x0800001e, 0x00100022, 0x00000000, 0x8010001a, 0x00000041, 0x00000000,
3481 0x0010002a, 0x00000000, 0x0500002b, 0x00100022, 0x00000000, 0x0010001a, 0x00000000, 0x07000038,
3482 0x001000c2, 0x00000002, 0x00100ea6, 0x00000003, 0x00100556, 0x00000000, 0x08000036, 0x001000d2,
3483 0x00000004, 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x09000037, 0x001020f2,
3484 0x00000001, 0x00100006, 0x00000000, 0x00100e46, 0x00000004, 0x00100e46, 0x00000002, 0x06000036,
3485 0x00100032, 0x00000000, 0x00208046, 0x00000000, 0x00000002, 0x06000036, 0x001000c2, 0x00000000,
3486 0x00208406, 0x00000000, 0x00000003, 0x08000038, 0x001000f2, 0x00000000, 0x00100e46, 0x00000000,
3487 0x00208ff6, 0x00000000, 0x00000001, 0x0a000038, 0x001000f2, 0x00000000, 0x00100e46, 0x00000000,
3488 0x00004002, 0x3f000000, 0x3f000000, 0x3f000000, 0x3f000000, 0x05000036, 0x00102032, 0x00000002,
3489 0x00100086, 0x00000000, 0x05000036, 0x00102032, 0x00000003, 0x001005d6, 0x00000000, 0x05000036,
3490 0x00100042, 0x00000001, 0x00004001, 0x3f800000, 0x08000010, 0x00100012, 0x00000000, 0x00208246,
3491 0x00000000, 0x00000002, 0x00100246, 0x00000001, 0x08000010, 0x00100022, 0x00000000, 0x00208246,
3492 0x00000000, 0x00000003, 0x00100246, 0x00000001, 0x08000038, 0x00100022, 0x00000001, 0x0010001a,
3493 0x00000000, 0x0020803a, 0x00000000, 0x00000003, 0x08000038, 0x00100012, 0x00000001, 0x0010000a,
3494 0x00000000, 0x0020803a, 0x00000000, 0x00000002, 0x0a000000, 0x00102032, 0x00000004, 0x00100046,
3495 0x00000001, 0x00004002, 0xbf800000, 0x3f800000, 0x00000000, 0x00000000, 0x08000036, 0x001020c2,
3496 0x00000004, 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, 0x0100003e,
3498 /* ⎡p0.x p0.y 1⎤
3499 * A = ⎢p1.x p1.y 1⎥
3500 * ⎣p2.x p2.y 1⎦
3502 * ⎡1 0⎤
3503 * B = ⎢1 1⎥
3504 * ⎣0 1⎦
3506 * A' = ⎡p1.x-p0.x p1.y-p0.y⎤
3507 * ⎣p2.x-p0.x p2.y-p0.y⎦
3509 * B' = ⎡ 0 1⎤
3510 * ⎣-1 1⎦
3512 * A'T = B'
3513 * T = A'⁻¹B' = (B'⁻¹A')⁻¹
3515 static const DWORD vs_code_arc_outline[] =
3517 #if 0
3518 float3x2 transform_geometry;
3519 float stroke_width;
3520 float4 transform_rtx;
3521 float4 transform_rty;
3523 struct output
3525 float2 p : WORLD_POSITION;
3526 float4 b : BEZIER;
3527 nointerpolation float2x2 stroke_transform : STROKE_TRANSFORM;
3528 float4 position : SV_POSITION;
3531 void main(float2 position : POSITION, float2 p0 : P0, float2 p1 : P1, float2 p2 : P2,
3532 float2 prev : PREV, float2 next : NEXT, out struct output o)
3534 float2 q_prev, q_next, v_p, q_i, p;
3535 float2x2 geom, rt, p_inv;
3536 float l;
3537 float a;
3538 float2 bc;
3540 geom = float2x2(transform_geometry._11_21, transform_geometry._12_22);
3541 rt = float2x2(transform_rtx.xy, transform_rty.xy);
3542 o.stroke_transform = rt * stroke_width * 0.5f;
3544 p = mul(geom, position);
3545 p0 = mul(geom, p0);
3546 p1 = mul(geom, p1);
3547 p2 = mul(geom, p2);
3549 p -= p0;
3550 p1 -= p0;
3551 p2 -= p0;
3553 q_prev = normalize(mul(geom, prev));
3554 q_next = normalize(mul(geom, next));
3556 v_p = float2(-q_prev.y, q_prev.x);
3557 l = -dot(v_p, q_next) / (1.0f + dot(q_prev, q_next));
3558 q_i = l * q_prev + v_p;
3559 p += 0.5f * stroke_width * q_i;
3561 p_inv = float2x2(p1.y, -p1.x, p2.y - p1.y, p1.x - p2.x) / (p1.x * p2.y - p2.x * p1.y);
3562 o.b.xy = mul(p_inv, p) + float2(1.0f, 0.0f);
3563 o.b.zw = 0.0f;
3565 o.p = mul(float3(position, 1.0f), transform_geometry) + 0.5f * stroke_width * q_i;
3566 position = mul(float2x3(transform_rtx.xyz, transform_rty.xyz), float3(o.p, 1.0f))
3567 * float2(transform_rtx.w, transform_rty.w);
3568 o.position = float4(position + float2(-1.0f, 1.0f), 0.0f, 1.0f);
3570 #endif
3571 0x43425844, 0xde1911bf, 0xfff8c893, 0xb0bfc24d, 0x78c9bbc4, 0x00000001, 0x00000924, 0x00000003,
3572 0x0000002c, 0x000000e4, 0x000001a0, 0x4e475349, 0x000000b0, 0x00000006, 0x00000008, 0x00000098,
3573 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000303, 0x000000a1, 0x00000000, 0x00000000,
3574 0x00000003, 0x00000001, 0x00000303, 0x000000a1, 0x00000001, 0x00000000, 0x00000003, 0x00000002,
3575 0x00000303, 0x000000a1, 0x00000002, 0x00000000, 0x00000003, 0x00000003, 0x00000303, 0x000000a3,
3576 0x00000000, 0x00000000, 0x00000003, 0x00000004, 0x00000303, 0x000000a8, 0x00000000, 0x00000000,
3577 0x00000003, 0x00000005, 0x00000303, 0x49534f50, 0x4e4f4954, 0x50005000, 0x00564552, 0x5458454e,
3578 0xababab00, 0x4e47534f, 0x000000b4, 0x00000005, 0x00000008, 0x00000080, 0x00000000, 0x00000000,
3579 0x00000003, 0x00000000, 0x00000c03, 0x0000008f, 0x00000000, 0x00000000, 0x00000003, 0x00000001,
3580 0x0000000f, 0x00000096, 0x00000000, 0x00000000, 0x00000003, 0x00000002, 0x00000c03, 0x00000096,
3581 0x00000001, 0x00000000, 0x00000003, 0x00000003, 0x00000c03, 0x000000a7, 0x00000000, 0x00000001,
3582 0x00000003, 0x00000004, 0x0000000f, 0x4c524f57, 0x4f505f44, 0x49544953, 0x42004e4f, 0x45495a45,
3583 0x54530052, 0x454b4f52, 0x4152545f, 0x4f46534e, 0x53004d52, 0x4f505f56, 0x49544953, 0xab004e4f,
3584 0x52444853, 0x0000077c, 0x00010040, 0x000001df, 0x04000059, 0x00208e46, 0x00000000, 0x00000004,
3585 0x0300005f, 0x00101032, 0x00000000, 0x0300005f, 0x00101032, 0x00000001, 0x0300005f, 0x00101032,
3586 0x00000002, 0x0300005f, 0x00101032, 0x00000003, 0x0300005f, 0x00101032, 0x00000004, 0x0300005f,
3587 0x00101032, 0x00000005, 0x03000065, 0x00102032, 0x00000000, 0x03000065, 0x001020f2, 0x00000001,
3588 0x03000065, 0x00102032, 0x00000002, 0x03000065, 0x00102032, 0x00000003, 0x04000067, 0x001020f2,
3589 0x00000004, 0x00000001, 0x02000068, 0x00000004, 0x0800000f, 0x00100012, 0x00000000, 0x00208046,
3590 0x00000000, 0x00000000, 0x00101046, 0x00000005, 0x0800000f, 0x00100022, 0x00000000, 0x00208046,
3591 0x00000000, 0x00000001, 0x00101046, 0x00000005, 0x0700000f, 0x00100042, 0x00000000, 0x00100046,
3592 0x00000000, 0x00100046, 0x00000000, 0x05000044, 0x00100042, 0x00000000, 0x0010002a, 0x00000000,
3593 0x07000038, 0x00100032, 0x00000000, 0x00100aa6, 0x00000000, 0x00100046, 0x00000000, 0x0800000f,
3594 0x00100012, 0x00000001, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000004, 0x0800000f,
3595 0x00100022, 0x00000001, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000004, 0x0700000f,
3596 0x00100042, 0x00000000, 0x00100046, 0x00000001, 0x00100046, 0x00000001, 0x05000044, 0x00100042,
3597 0x00000000, 0x0010002a, 0x00000000, 0x07000038, 0x00100032, 0x00000001, 0x00100aa6, 0x00000000,
3598 0x00100046, 0x00000001, 0x06000036, 0x001000c2, 0x00000001, 0x80100556, 0x00000041, 0x00000001,
3599 0x0700000f, 0x00100042, 0x00000000, 0x00100a26, 0x00000001, 0x00100046, 0x00000000, 0x0700000f,
3600 0x00100012, 0x00000000, 0x00100046, 0x00000001, 0x00100046, 0x00000000, 0x07000000, 0x00100012,
3601 0x00000000, 0x0010000a, 0x00000000, 0x00004001, 0x3f800000, 0x0800000e, 0x00100012, 0x00000000,
3602 0x8010002a, 0x00000041, 0x00000000, 0x0010000a, 0x00000000, 0x09000032, 0x00100032, 0x00000000,
3603 0x00100006, 0x00000000, 0x00100046, 0x00000001, 0x00100f36, 0x00000001, 0x05000036, 0x00100032,
3604 0x00000001, 0x00101046, 0x00000000, 0x05000036, 0x00100042, 0x00000001, 0x00004001, 0x3f800000,
3605 0x08000010, 0x00100012, 0x00000002, 0x00100246, 0x00000001, 0x00208246, 0x00000000, 0x00000000,
3606 0x08000010, 0x00100022, 0x00000002, 0x00100246, 0x00000001, 0x00208246, 0x00000000, 0x00000001,
3607 0x08000038, 0x00100042, 0x00000000, 0x0020803a, 0x00000000, 0x00000001, 0x00004001, 0x3f000000,
3608 0x09000032, 0x00100032, 0x00000001, 0x00100aa6, 0x00000000, 0x00100046, 0x00000000, 0x00100046,
3609 0x00000002, 0x05000036, 0x00102032, 0x00000000, 0x00100046, 0x00000001, 0x0800000f, 0x00100012,
3610 0x00000002, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000000, 0x0800000f, 0x00100022,
3611 0x00000002, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000000, 0x0800000f, 0x00100022,
3612 0x00000003, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000001, 0x0800000f, 0x00100012,
3613 0x00000003, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000001, 0x08000000, 0x00100032,
3614 0x00000002, 0x00100046, 0x00000002, 0x80100516, 0x00000041, 0x00000003, 0x09000032, 0x00100032,
3615 0x00000000, 0x00100aa6, 0x00000000, 0x00100046, 0x00000000, 0x00100046, 0x00000002, 0x0800000f,
3616 0x00100022, 0x00000002, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000003, 0x0800000f,
3617 0x00100012, 0x00000002, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000003, 0x08000000,
3618 0x001000c2, 0x00000000, 0x80100406, 0x00000041, 0x00000003, 0x00100406, 0x00000002, 0x0800000f,
3619 0x00100022, 0x00000002, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000002, 0x0800000f,
3620 0x00100012, 0x00000002, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000002, 0x08000000,
3621 0x00100032, 0x00000002, 0x80100046, 0x00000041, 0x00000003, 0x00100046, 0x00000002, 0x07000038,
3622 0x00100082, 0x00000001, 0x0010003a, 0x00000000, 0x0010000a, 0x00000002, 0x0a000032, 0x00100082,
3623 0x00000001, 0x0010001a, 0x00000002, 0x0010002a, 0x00000000, 0x8010003a, 0x00000041, 0x00000001,
3624 0x08000000, 0x00100042, 0x00000003, 0x0010002a, 0x00000000, 0x8010000a, 0x00000041, 0x00000002,
3625 0x08000000, 0x00100082, 0x00000003, 0x8010003a, 0x00000041, 0x00000000, 0x0010001a, 0x00000002,
3626 0x0a000038, 0x00100032, 0x00000003, 0x00100046, 0x00000002, 0x00004002, 0x3f800000, 0xbf800000,
3627 0x00000000, 0x00000000, 0x0700000e, 0x001000f2, 0x00000002, 0x00100e46, 0x00000003, 0x00100ff6,
3628 0x00000001, 0x0700000f, 0x00100012, 0x00000002, 0x00100046, 0x00000002, 0x00100046, 0x00000000,
3629 0x0700000f, 0x00100022, 0x00000002, 0x00100ae6, 0x00000002, 0x00100046, 0x00000000, 0x0a000000,
3630 0x00102032, 0x00000001, 0x00100046, 0x00000002, 0x00004002, 0x3f800000, 0x00000000, 0x00000000,
3631 0x00000000, 0x08000036, 0x001020c2, 0x00000001, 0x00004002, 0x00000000, 0x00000000, 0x00000000,
3632 0x00000000, 0x06000036, 0x00100032, 0x00000000, 0x00208046, 0x00000000, 0x00000002, 0x06000036,
3633 0x001000c2, 0x00000000, 0x00208406, 0x00000000, 0x00000003, 0x08000038, 0x001000f2, 0x00000000,
3634 0x00100e46, 0x00000000, 0x00208ff6, 0x00000000, 0x00000001, 0x0a000038, 0x001000f2, 0x00000000,
3635 0x00100e46, 0x00000000, 0x00004002, 0x3f000000, 0x3f000000, 0x3f000000, 0x3f000000, 0x05000036,
3636 0x00102032, 0x00000002, 0x00100086, 0x00000000, 0x05000036, 0x00102032, 0x00000003, 0x001005d6,
3637 0x00000000, 0x05000036, 0x00100042, 0x00000001, 0x00004001, 0x3f800000, 0x08000010, 0x00100012,
3638 0x00000000, 0x00208246, 0x00000000, 0x00000002, 0x00100246, 0x00000001, 0x08000010, 0x00100022,
3639 0x00000000, 0x00208246, 0x00000000, 0x00000003, 0x00100246, 0x00000001, 0x08000038, 0x00100022,
3640 0x00000001, 0x0010001a, 0x00000000, 0x0020803a, 0x00000000, 0x00000003, 0x08000038, 0x00100012,
3641 0x00000001, 0x0010000a, 0x00000000, 0x0020803a, 0x00000000, 0x00000002, 0x0a000000, 0x00102032,
3642 0x00000004, 0x00100046, 0x00000001, 0x00004002, 0xbf800000, 0x3f800000, 0x00000000, 0x00000000,
3643 0x08000036, 0x001020c2, 0x00000004, 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x3f800000,
3644 0x0100003e,
3646 static const DWORD vs_code_triangle[] =
3648 #if 0
3649 float3x2 transform_geometry;
3650 float4 transform_rtx;
3651 float4 transform_rty;
3653 struct output
3655 float2 p : WORLD_POSITION;
3656 float4 b : BEZIER;
3657 nointerpolation float2x2 stroke_transform : STROKE_TRANSFORM;
3658 float4 position : SV_POSITION;
3661 void main(float2 position : POSITION, out struct output o)
3663 o.p = mul(float3(position, 1.0f), transform_geometry);
3664 o.b = float4(1.0, 0.0, 1.0, 1.0);
3665 o.stroke_transform = float2x2(1.0, 0.0, 0.0, 1.0);
3666 position = mul(float2x3(transform_rtx.xyz, transform_rty.xyz), float3(o.p, 1.0f))
3667 * float2(transform_rtx.w, transform_rty.w);
3668 o.position = float4(position + float2(-1.0f, 1.0f), 0.0f, 1.0f);
3670 #endif
3671 0x43425844, 0xda43bf17, 0x06e6d155, 0xdbce2ae5, 0x8aed6fd8, 0x00000001, 0x0000034c, 0x00000003,
3672 0x0000002c, 0x00000060, 0x0000011c, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020,
3673 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000303, 0x49534f50, 0x4e4f4954, 0xababab00,
3674 0x4e47534f, 0x000000b4, 0x00000005, 0x00000008, 0x00000080, 0x00000000, 0x00000000, 0x00000003,
3675 0x00000000, 0x00000c03, 0x0000008f, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x0000000f,
3676 0x00000096, 0x00000000, 0x00000000, 0x00000003, 0x00000002, 0x00000c03, 0x00000096, 0x00000001,
3677 0x00000000, 0x00000003, 0x00000003, 0x00000c03, 0x000000a7, 0x00000000, 0x00000001, 0x00000003,
3678 0x00000004, 0x0000000f, 0x4c524f57, 0x4f505f44, 0x49544953, 0x42004e4f, 0x45495a45, 0x54530052,
3679 0x454b4f52, 0x4152545f, 0x4f46534e, 0x53004d52, 0x4f505f56, 0x49544953, 0xab004e4f, 0x52444853,
3680 0x00000228, 0x00010040, 0x0000008a, 0x04000059, 0x00208e46, 0x00000000, 0x00000004, 0x0300005f,
3681 0x00101032, 0x00000000, 0x03000065, 0x00102032, 0x00000000, 0x03000065, 0x001020f2, 0x00000001,
3682 0x03000065, 0x00102032, 0x00000002, 0x03000065, 0x00102032, 0x00000003, 0x04000067, 0x001020f2,
3683 0x00000004, 0x00000001, 0x02000068, 0x00000002, 0x05000036, 0x00100032, 0x00000000, 0x00101046,
3684 0x00000000, 0x05000036, 0x00100042, 0x00000000, 0x00004001, 0x3f800000, 0x08000010, 0x00100012,
3685 0x00000001, 0x00100246, 0x00000000, 0x00208246, 0x00000000, 0x00000000, 0x08000010, 0x00100022,
3686 0x00000001, 0x00100246, 0x00000000, 0x00208246, 0x00000000, 0x00000001, 0x05000036, 0x00102032,
3687 0x00000000, 0x00100046, 0x00000001, 0x08000036, 0x001020f2, 0x00000001, 0x00004002, 0x3f800000,
3688 0x00000000, 0x3f800000, 0x3f800000, 0x08000036, 0x00102032, 0x00000002, 0x00004002, 0x3f800000,
3689 0x00000000, 0x00000000, 0x00000000, 0x08000036, 0x00102032, 0x00000003, 0x00004002, 0x00000000,
3690 0x3f800000, 0x00000000, 0x00000000, 0x05000036, 0x00100042, 0x00000001, 0x00004001, 0x3f800000,
3691 0x08000010, 0x00100012, 0x00000000, 0x00208246, 0x00000000, 0x00000002, 0x00100246, 0x00000001,
3692 0x08000010, 0x00100022, 0x00000000, 0x00208246, 0x00000000, 0x00000003, 0x00100246, 0x00000001,
3693 0x08000038, 0x00100022, 0x00000001, 0x0010001a, 0x00000000, 0x0020803a, 0x00000000, 0x00000003,
3694 0x08000038, 0x00100012, 0x00000001, 0x0010000a, 0x00000000, 0x0020803a, 0x00000000, 0x00000002,
3695 0x0a000000, 0x00102032, 0x00000004, 0x00100046, 0x00000001, 0x00004002, 0xbf800000, 0x3f800000,
3696 0x00000000, 0x00000000, 0x08000036, 0x001020c2, 0x00000004, 0x00004002, 0x00000000, 0x00000000,
3697 0x00000000, 0x3f800000, 0x0100003e,
3699 static const DWORD vs_code_curve[] =
3701 #if 0
3702 float3x2 transform_geometry;
3703 float4 transform_rtx;
3704 float4 transform_rty;
3706 struct output
3708 float2 p : WORLD_POSITION;
3709 float4 b : BEZIER;
3710 nointerpolation float2x2 stroke_transform : STROKE_TRANSFORM;
3711 float4 position : SV_POSITION;
3714 void main(float2 position : POSITION, float3 texcoord : TEXCOORD0, out struct output o)
3716 o.p = mul(float3(position, 1.0f), transform_geometry);
3717 o.b = float4(texcoord, 1.0);
3718 o.stroke_transform = float2x2(1.0, 0.0, 0.0, 1.0);
3719 position = mul(float2x3(transform_rtx.xyz, transform_rty.xyz), float3(o.p, 1.0f))
3720 * float2(transform_rtx.w, transform_rty.w);
3721 o.position = float4(position + float2(-1.0f, 1.0f), 0.0f, 1.0f);
3723 #endif
3724 0x43425844, 0xedb7472a, 0x2c2ea147, 0x36710079, 0xffc2e907, 0x00000001, 0x00000380, 0x00000003,
3725 0x0000002c, 0x00000080, 0x0000013c, 0x4e475349, 0x0000004c, 0x00000002, 0x00000008, 0x00000038,
3726 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000303, 0x00000041, 0x00000000, 0x00000000,
3727 0x00000003, 0x00000001, 0x00000707, 0x49534f50, 0x4e4f4954, 0x58455400, 0x524f4f43, 0xabab0044,
3728 0x4e47534f, 0x000000b4, 0x00000005, 0x00000008, 0x00000080, 0x00000000, 0x00000000, 0x00000003,
3729 0x00000000, 0x00000c03, 0x0000008f, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x0000000f,
3730 0x00000096, 0x00000000, 0x00000000, 0x00000003, 0x00000002, 0x00000c03, 0x00000096, 0x00000001,
3731 0x00000000, 0x00000003, 0x00000003, 0x00000c03, 0x000000a7, 0x00000000, 0x00000001, 0x00000003,
3732 0x00000004, 0x0000000f, 0x4c524f57, 0x4f505f44, 0x49544953, 0x42004e4f, 0x45495a45, 0x54530052,
3733 0x454b4f52, 0x4152545f, 0x4f46534e, 0x53004d52, 0x4f505f56, 0x49544953, 0xab004e4f, 0x52444853,
3734 0x0000023c, 0x00010040, 0x0000008f, 0x04000059, 0x00208e46, 0x00000000, 0x00000004, 0x0300005f,
3735 0x00101032, 0x00000000, 0x0300005f, 0x00101072, 0x00000001, 0x03000065, 0x00102032, 0x00000000,
3736 0x03000065, 0x001020f2, 0x00000001, 0x03000065, 0x00102032, 0x00000002, 0x03000065, 0x00102032,
3737 0x00000003, 0x04000067, 0x001020f2, 0x00000004, 0x00000001, 0x02000068, 0x00000002, 0x05000036,
3738 0x00100032, 0x00000000, 0x00101046, 0x00000000, 0x05000036, 0x00100042, 0x00000000, 0x00004001,
3739 0x3f800000, 0x08000010, 0x00100012, 0x00000001, 0x00100246, 0x00000000, 0x00208246, 0x00000000,
3740 0x00000000, 0x08000010, 0x00100022, 0x00000001, 0x00100246, 0x00000000, 0x00208246, 0x00000000,
3741 0x00000001, 0x05000036, 0x00102032, 0x00000000, 0x00100046, 0x00000001, 0x05000036, 0x00102072,
3742 0x00000001, 0x00101246, 0x00000001, 0x05000036, 0x00102082, 0x00000001, 0x00004001, 0x3f800000,
3743 0x08000036, 0x00102032, 0x00000002, 0x00004002, 0x3f800000, 0x00000000, 0x00000000, 0x00000000,
3744 0x08000036, 0x00102032, 0x00000003, 0x00004002, 0x00000000, 0x3f800000, 0x00000000, 0x00000000,
3745 0x05000036, 0x00100042, 0x00000001, 0x00004001, 0x3f800000, 0x08000010, 0x00100012, 0x00000000,
3746 0x00208246, 0x00000000, 0x00000002, 0x00100246, 0x00000001, 0x08000010, 0x00100022, 0x00000000,
3747 0x00208246, 0x00000000, 0x00000003, 0x00100246, 0x00000001, 0x08000038, 0x00100022, 0x00000001,
3748 0x0010001a, 0x00000000, 0x0020803a, 0x00000000, 0x00000003, 0x08000038, 0x00100012, 0x00000001,
3749 0x0010000a, 0x00000000, 0x0020803a, 0x00000000, 0x00000002, 0x0a000000, 0x00102032, 0x00000004,
3750 0x00100046, 0x00000001, 0x00004002, 0xbf800000, 0x3f800000, 0x00000000, 0x00000000, 0x08000036,
3751 0x001020c2, 0x00000004, 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, 0x0100003e,
3753 static const DWORD ps_code[] =
3755 #if 0
3756 #define BRUSH_TYPE_SOLID 0
3757 #define BRUSH_TYPE_LINEAR 1
3758 #define BRUSH_TYPE_RADIAL 2
3759 #define BRUSH_TYPE_BITMAP 3
3760 #define BRUSH_TYPE_COUNT 4
3762 bool outline;
3763 bool is_arc;
3764 struct brush
3766 uint type;
3767 float opacity;
3768 float4 data[3];
3769 } colour_brush, opacity_brush;
3771 SamplerState s0, s1;
3772 Texture2D t0, t1;
3773 Buffer<float4> b0, b1;
3775 struct input
3777 float2 p : WORLD_POSITION;
3778 float4 b : BEZIER;
3779 nointerpolation float2x2 stroke_transform : STROKE_TRANSFORM;
3782 float4 sample_gradient(Buffer<float4> gradient, uint stop_count, float position)
3784 float4 c_low, c_high;
3785 float p_low, p_high;
3786 uint i;
3788 p_low = gradient.Load(0).x;
3789 c_low = gradient.Load(1);
3790 c_high = c_low;
3792 if (position < p_low)
3793 return c_low;
3795 for (i = 1; i < stop_count; ++i)
3797 p_high = gradient.Load(i * 2).x;
3798 c_high = gradient.Load(i * 2 + 1);
3800 if (position >= p_low && position <= p_high)
3801 return lerp(c_low, c_high, (position - p_low) / (p_high - p_low));
3803 p_low = p_high;
3804 c_low = c_high;
3807 return c_high;
3810 float4 brush_linear(struct brush brush, Buffer<float4> gradient, float2 position)
3812 float2 start, end, v_p, v_q;
3813 uint stop_count;
3814 float p;
3816 start = brush.data[0].xy;
3817 end = brush.data[0].zw;
3818 stop_count = asuint(brush.data[1].x);
3820 v_p = position - start;
3821 v_q = end - start;
3822 p = dot(v_q, v_p) / dot(v_q, v_q);
3824 return sample_gradient(gradient, stop_count, p);
3827 float4 brush_radial(struct brush brush, Buffer<float4> gradient, float2 position)
3829 float2 centre, offset, ra, rb, v_p, v_q, r;
3830 float b, c, l, t;
3831 uint stop_count;
3833 centre = brush.data[0].xy;
3834 offset = brush.data[0].zw;
3835 ra = brush.data[1].xy;
3836 rb = brush.data[1].zw;
3837 stop_count = asuint(brush.data[2].x);
3839 /* Project onto ra, rb. */
3840 r = float2(dot(ra, ra), dot(rb, rb));
3841 v_p = position - (centre + offset);
3842 v_p = float2(dot(v_p, ra), dot(v_p, rb)) / r;
3843 v_q = float2(dot(offset, ra), dot(offset, rb)) / r;
3845 /* ‖t·p̂ + q⃑‖ = 1
3846 * (t·p̂ + q⃑) · (t·p̂ + q⃑) = 1
3847 * t² + 2·(p̂·q⃑)·t + (q⃑·q⃑) = 1
3849 * b = p̂·q⃑
3850 * c = q⃑·q⃑ - 1
3851 * t = -b + √(b² - c) */
3852 l = length(v_p);
3853 b = dot(v_p, v_q) / l;
3854 c = dot(v_q, v_q) - 1.0;
3855 t = -b + sqrt(b * b - c);
3857 return sample_gradient(gradient, stop_count, l / t);
3860 float4 brush_bitmap(struct brush brush, Texture2D t, SamplerState s, float2 position)
3862 float3 transform[2];
3863 bool ignore_alpha;
3864 float2 texcoord;
3865 float4 colour;
3867 transform[0] = brush.data[0].xyz;
3868 transform[1] = brush.data[1].xyz;
3869 ignore_alpha = asuint(brush.data[1].w);
3871 texcoord.x = dot(position.xy, transform[0].xy) + transform[0].z;
3872 texcoord.y = dot(position.xy, transform[1].xy) + transform[1].z;
3873 colour = t.Sample(s, texcoord);
3874 if (ignore_alpha)
3875 colour.a = 1.0;
3876 return colour;
3879 float4 sample_brush(struct brush brush, Texture2D t, SamplerState s, Buffer<float4> b, float2 position)
3881 if (brush.type == BRUSH_TYPE_SOLID)
3882 return brush.data[0] * brush.opacity;
3883 if (brush.type == BRUSH_TYPE_LINEAR)
3884 return brush_linear(brush, b, position) * brush.opacity;
3885 if (brush.type == BRUSH_TYPE_RADIAL)
3886 return brush_radial(brush, b, position) * brush.opacity;
3887 if (brush.type == BRUSH_TYPE_BITMAP)
3888 return brush_bitmap(brush, t, s, position) * brush.opacity;
3889 return float4(0.0, 0.0, 0.0, brush.opacity);
3892 float4 main(struct input i) : SV_Target
3894 float4 colour;
3896 colour = sample_brush(colour_brush, t0, s0, b0, i.p);
3897 if (opacity_brush.type < BRUSH_TYPE_COUNT)
3898 colour *= sample_brush(opacity_brush, t1, s1, b1, i.p).a;
3900 if (outline)
3902 float2 du, dv, df;
3903 float4 uv;
3905 /* Evaluate the implicit form of the curve (u² - v = 0
3906 * for Béziers, u² + v² - 1 = 0 for arcs) in texture
3907 * space, using the screen-space partial derivatives
3908 * to convert the calculated distance to object space.
3910 * d(x, y) = |f(x, y)| / ‖∇f(x, y)‖
3911 * = |f(x, y)| / √((∂f/∂x)² + (∂f/∂y)²)
3913 * For Béziers:
3914 * f(x, y) = u(x, y)² - v(x, y)
3915 * ∂f/∂x = 2u · ∂u/∂x - ∂v/∂x
3916 * ∂f/∂y = 2u · ∂u/∂y - ∂v/∂y
3918 * For arcs:
3919 * f(x, y) = u(x, y)² + v(x, y)² - 1
3920 * ∂f/∂x = 2u · ∂u/∂x + 2v · ∂v/∂x
3921 * ∂f/∂y = 2u · ∂u/∂y + 2v · ∂v/∂y */
3922 uv = i.b;
3923 du = float2(ddx(uv.x), ddy(uv.x));
3924 dv = float2(ddx(uv.y), ddy(uv.y));
3926 if (!is_arc)
3928 df = 2.0f * uv.x * du - dv;
3930 clip(dot(df, uv.zw));
3931 clip(length(mul(i.stroke_transform, df)) - abs(uv.x * uv.x - uv.y));
3933 else
3935 df = 2.0f * uv.x * du + 2.0f * uv.y * dv;
3937 clip(dot(df, uv.zw));
3938 clip(length(mul(i.stroke_transform, df)) - abs(uv.x * uv.x + uv.y * uv.y - 1.0f));
3941 else
3943 /* Evaluate the implicit form of the curve in texture space.
3944 * "i.b.z" determines which side of the curve is shaded. */
3945 if (!is_arc)
3947 clip((i.b.x * i.b.x - i.b.y) * i.b.z);
3949 else
3951 clip((i.b.x * i.b.x + i.b.y * i.b.y - 1.0) * i.b.z);
3955 return colour;
3957 #endif
3958 0x43425844, 0xa8fee730, 0x92fa2196, 0xaf9f3eff, 0x888d4048, 0x00000001, 0x00002000, 0x00000003,
3959 0x0000002c, 0x000000c4, 0x000000f8, 0x4e475349, 0x00000090, 0x00000004, 0x00000008, 0x00000068,
3960 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000303, 0x00000077, 0x00000000, 0x00000000,
3961 0x00000003, 0x00000001, 0x00000f0f, 0x0000007e, 0x00000000, 0x00000000, 0x00000003, 0x00000002,
3962 0x00000303, 0x0000007e, 0x00000001, 0x00000000, 0x00000003, 0x00000003, 0x00000303, 0x4c524f57,
3963 0x4f505f44, 0x49544953, 0x42004e4f, 0x45495a45, 0x54530052, 0x454b4f52, 0x4152545f, 0x4f46534e,
3964 0xab004d52, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000,
3965 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x00001f00,
3966 0x00000040, 0x000007c0, 0x04000059, 0x00208e46, 0x00000000, 0x00000009, 0x0300005a, 0x00106000,
3967 0x00000000, 0x0300005a, 0x00106000, 0x00000001, 0x04001858, 0x00107000, 0x00000000, 0x00005555,
3968 0x04001858, 0x00107000, 0x00000001, 0x00005555, 0x04000858, 0x00107000, 0x00000002, 0x00005555,
3969 0x04000858, 0x00107000, 0x00000003, 0x00005555, 0x03001062, 0x00101032, 0x00000000, 0x03001062,
3970 0x001010f2, 0x00000001, 0x03000862, 0x00101032, 0x00000002, 0x03000862, 0x00101032, 0x00000003,
3971 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x0000000a, 0x09000038, 0x001000f2, 0x00000000,
3972 0x00208556, 0x00000000, 0x00000001, 0x00208e46, 0x00000000, 0x00000002, 0x0404001f, 0x0020800a,
3973 0x00000000, 0x00000001, 0x08000020, 0x00100012, 0x00000001, 0x0020800a, 0x00000000, 0x00000001,
3974 0x00004001, 0x00000001, 0x0304001f, 0x0010000a, 0x00000001, 0x09000000, 0x00100062, 0x00000001,
3975 0x00101106, 0x00000000, 0x80208106, 0x00000041, 0x00000000, 0x00000002, 0x0a000000, 0x00100032,
3976 0x00000002, 0x80208046, 0x00000041, 0x00000000, 0x00000002, 0x00208ae6, 0x00000000, 0x00000002,
3977 0x0700000f, 0x00100022, 0x00000001, 0x00100046, 0x00000002, 0x00100596, 0x00000001, 0x0700000f,
3978 0x00100042, 0x00000001, 0x00100046, 0x00000002, 0x00100046, 0x00000002, 0x0700000e, 0x00100022,
3979 0x00000001, 0x0010001a, 0x00000001, 0x0010002a, 0x00000001, 0x0a00002d, 0x001000f2, 0x00000002,
3980 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00107e46, 0x00000002, 0x0a00002d,
3981 0x001000f2, 0x00000003, 0x00004002, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00107e46,
3982 0x00000002, 0x0700001d, 0x00100042, 0x00000001, 0x0010001a, 0x00000001, 0x0010000a, 0x00000002,
3983 0x0304001f, 0x0010002a, 0x00000001, 0x05000036, 0x001000f2, 0x00000004, 0x00100e46, 0x00000003,
3984 0x05000036, 0x001000f2, 0x00000005, 0x00100e46, 0x00000003, 0x05000036, 0x001000f2, 0x00000006,
3985 0x00100e46, 0x00000003, 0x05000036, 0x00100042, 0x00000001, 0x0010000a, 0x00000002, 0x05000036,
3986 0x00100082, 0x00000001, 0x00004001, 0x00000001, 0x05000036, 0x00100022, 0x00000002, 0x00004001,
3987 0x00000000, 0x01000030, 0x08000050, 0x00100042, 0x00000002, 0x0010003a, 0x00000001, 0x0020800a,
3988 0x00000000, 0x00000003, 0x05000036, 0x00100022, 0x00000002, 0x00004001, 0x00000000, 0x03040003,
3989 0x0010002a, 0x00000002, 0x07000029, 0x00100042, 0x00000002, 0x0010003a, 0x00000001, 0x00004001,
3990 0x00000001, 0x0700002d, 0x001000f2, 0x00000007, 0x00100aa6, 0x00000002, 0x00107e46, 0x00000002,
3991 0x0700001e, 0x00100042, 0x00000002, 0x0010002a, 0x00000002, 0x00004001, 0x00000001, 0x0700002d,
3992 0x001000f2, 0x00000008, 0x00100aa6, 0x00000002, 0x00107e46, 0x00000002, 0x0700001d, 0x00100042,
3993 0x00000002, 0x0010001a, 0x00000001, 0x0010002a, 0x00000001, 0x0700001d, 0x00100082, 0x00000002,
3994 0x0010000a, 0x00000007, 0x0010001a, 0x00000001, 0x07000001, 0x00100042, 0x00000002, 0x0010003a,
3995 0x00000002, 0x0010002a, 0x00000002, 0x0304001f, 0x0010002a, 0x00000002, 0x08000000, 0x00100082,
3996 0x00000002, 0x8010002a, 0x00000041, 0x00000001, 0x0010001a, 0x00000001, 0x08000000, 0x00100022,
3997 0x00000007, 0x8010002a, 0x00000041, 0x00000001, 0x0010000a, 0x00000007, 0x0700000e, 0x00100082,
3998 0x00000002, 0x0010003a, 0x00000002, 0x0010001a, 0x00000007, 0x08000000, 0x001000f2, 0x00000009,
3999 0x80100e46, 0x00000041, 0x00000005, 0x00100e46, 0x00000008, 0x09000032, 0x001000f2, 0x00000009,
4000 0x00100ff6, 0x00000002, 0x00100e46, 0x00000009, 0x00100e46, 0x00000005, 0x05000036, 0x001000f2,
4001 0x00000006, 0x00100e46, 0x00000008, 0x05000036, 0x00100022, 0x00000002, 0x00004001, 0xffffffff,
4002 0x05000036, 0x001000f2, 0x00000004, 0x00100e46, 0x00000009, 0x01000002, 0x01000015, 0x05000036,
4003 0x001000f2, 0x00000005, 0x00100e46, 0x00000008, 0x05000036, 0x00100042, 0x00000001, 0x0010000a,
4004 0x00000007, 0x0700001e, 0x00100082, 0x00000001, 0x0010003a, 0x00000001, 0x00004001, 0x00000001,
4005 0x05000036, 0x001000f2, 0x00000006, 0x00100e46, 0x00000008, 0x05000036, 0x00100022, 0x00000002,
4006 0x0010002a, 0x00000002, 0x01000016, 0x09000037, 0x001000f2, 0x00000003, 0x00100556, 0x00000002,
4007 0x00100e46, 0x00000004, 0x00100e46, 0x00000006, 0x01000015, 0x08000038, 0x001000f2, 0x00000000,
4008 0x00100e46, 0x00000003, 0x00208556, 0x00000000, 0x00000001, 0x01000015, 0x0300001f, 0x0010000a,
4009 0x00000001, 0x08000020, 0x00100012, 0x00000001, 0x0020800a, 0x00000000, 0x00000001, 0x00004001,
4010 0x00000002, 0x0304001f, 0x0010000a, 0x00000001, 0x0900000f, 0x00100012, 0x00000002, 0x00208046,
4011 0x00000000, 0x00000003, 0x00208046, 0x00000000, 0x00000003, 0x0900000f, 0x00100022, 0x00000002,
4012 0x00208ae6, 0x00000000, 0x00000003, 0x00208ae6, 0x00000000, 0x00000003, 0x09000000, 0x00100062,
4013 0x00000001, 0x00208ba6, 0x00000000, 0x00000002, 0x00208106, 0x00000000, 0x00000002, 0x08000000,
4014 0x00100062, 0x00000001, 0x80100656, 0x00000041, 0x00000001, 0x00101106, 0x00000000, 0x0800000f,
4015 0x00100012, 0x00000003, 0x00100596, 0x00000001, 0x00208046, 0x00000000, 0x00000003, 0x0800000f,
4016 0x00100022, 0x00000003, 0x00100596, 0x00000001, 0x00208ae6, 0x00000000, 0x00000003, 0x0700000e,
4017 0x00100062, 0x00000001, 0x00100106, 0x00000003, 0x00100106, 0x00000002, 0x0900000f, 0x00100012,
4018 0x00000003, 0x00208ae6, 0x00000000, 0x00000002, 0x00208046, 0x00000000, 0x00000003, 0x0900000f,
4019 0x00100022, 0x00000003, 0x00208ae6, 0x00000000, 0x00000002, 0x00208ae6, 0x00000000, 0x00000003,
4020 0x0700000e, 0x00100032, 0x00000002, 0x00100046, 0x00000003, 0x00100046, 0x00000002, 0x0700000f,
4021 0x00100082, 0x00000001, 0x00100596, 0x00000001, 0x00100596, 0x00000001, 0x0500004b, 0x00100082,
4022 0x00000001, 0x0010003a, 0x00000001, 0x0700000f, 0x00100022, 0x00000001, 0x00100596, 0x00000001,
4023 0x00100046, 0x00000002, 0x0700000e, 0x00100022, 0x00000001, 0x0010001a, 0x00000001, 0x0010003a,
4024 0x00000001, 0x0700000f, 0x00100042, 0x00000001, 0x00100046, 0x00000002, 0x00100046, 0x00000002,
4025 0x07000000, 0x00100042, 0x00000001, 0x0010002a, 0x00000001, 0x00004001, 0xbf800000, 0x0a000032,
4026 0x00100042, 0x00000001, 0x0010001a, 0x00000001, 0x0010001a, 0x00000001, 0x8010002a, 0x00000041,
4027 0x00000001, 0x0500004b, 0x00100042, 0x00000001, 0x0010002a, 0x00000001, 0x08000000, 0x00100022,
4028 0x00000001, 0x0010002a, 0x00000001, 0x8010001a, 0x00000041, 0x00000001, 0x0700000e, 0x00100022,
4029 0x00000001, 0x0010003a, 0x00000001, 0x0010001a, 0x00000001, 0x0a00002d, 0x001000f2, 0x00000002,
4030 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00107e46, 0x00000002, 0x0a00002d,
4031 0x001000f2, 0x00000003, 0x00004002, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00107e46,
4032 0x00000002, 0x0700001d, 0x00100042, 0x00000001, 0x0010001a, 0x00000001, 0x0010000a, 0x00000002,
4033 0x0304001f, 0x0010002a, 0x00000001, 0x05000036, 0x001000f2, 0x00000004, 0x00100e46, 0x00000003,
4034 0x05000036, 0x001000f2, 0x00000005, 0x00100e46, 0x00000003, 0x05000036, 0x001000f2, 0x00000006,
4035 0x00100e46, 0x00000003, 0x05000036, 0x00100042, 0x00000001, 0x0010000a, 0x00000002, 0x05000036,
4036 0x00100082, 0x00000001, 0x00004001, 0x00000001, 0x05000036, 0x00100022, 0x00000002, 0x00004001,
4037 0x00000000, 0x01000030, 0x08000050, 0x00100042, 0x00000002, 0x0010003a, 0x00000001, 0x0020800a,
4038 0x00000000, 0x00000004, 0x05000036, 0x00100022, 0x00000002, 0x00004001, 0x00000000, 0x03040003,
4039 0x0010002a, 0x00000002, 0x07000029, 0x00100042, 0x00000002, 0x0010003a, 0x00000001, 0x00004001,
4040 0x00000001, 0x0700002d, 0x001000f2, 0x00000007, 0x00100aa6, 0x00000002, 0x00107e46, 0x00000002,
4041 0x0700001e, 0x00100042, 0x00000002, 0x0010002a, 0x00000002, 0x00004001, 0x00000001, 0x0700002d,
4042 0x001000f2, 0x00000008, 0x00100aa6, 0x00000002, 0x00107e46, 0x00000002, 0x0700001d, 0x00100042,
4043 0x00000002, 0x0010001a, 0x00000001, 0x0010002a, 0x00000001, 0x0700001d, 0x00100082, 0x00000002,
4044 0x0010000a, 0x00000007, 0x0010001a, 0x00000001, 0x07000001, 0x00100042, 0x00000002, 0x0010003a,
4045 0x00000002, 0x0010002a, 0x00000002, 0x0304001f, 0x0010002a, 0x00000002, 0x08000000, 0x00100082,
4046 0x00000002, 0x8010002a, 0x00000041, 0x00000001, 0x0010001a, 0x00000001, 0x08000000, 0x00100022,
4047 0x00000007, 0x8010002a, 0x00000041, 0x00000001, 0x0010000a, 0x00000007, 0x0700000e, 0x00100082,
4048 0x00000002, 0x0010003a, 0x00000002, 0x0010001a, 0x00000007, 0x08000000, 0x001000f2, 0x00000009,
4049 0x80100e46, 0x00000041, 0x00000005, 0x00100e46, 0x00000008, 0x09000032, 0x001000f2, 0x00000009,
4050 0x00100ff6, 0x00000002, 0x00100e46, 0x00000009, 0x00100e46, 0x00000005, 0x05000036, 0x001000f2,
4051 0x00000006, 0x00100e46, 0x00000008, 0x05000036, 0x00100022, 0x00000002, 0x00004001, 0xffffffff,
4052 0x05000036, 0x001000f2, 0x00000004, 0x00100e46, 0x00000009, 0x01000002, 0x01000015, 0x05000036,
4053 0x001000f2, 0x00000005, 0x00100e46, 0x00000008, 0x05000036, 0x00100042, 0x00000001, 0x0010000a,
4054 0x00000007, 0x0700001e, 0x00100082, 0x00000001, 0x0010003a, 0x00000001, 0x00004001, 0x00000001,
4055 0x05000036, 0x001000f2, 0x00000006, 0x00100e46, 0x00000008, 0x05000036, 0x00100022, 0x00000002,
4056 0x0010002a, 0x00000002, 0x01000016, 0x09000037, 0x001000f2, 0x00000003, 0x00100556, 0x00000002,
4057 0x00100e46, 0x00000004, 0x00100e46, 0x00000006, 0x01000015, 0x08000038, 0x001000f2, 0x00000000,
4058 0x00100e46, 0x00000003, 0x00208556, 0x00000000, 0x00000001, 0x01000015, 0x0300001f, 0x0010000a,
4059 0x00000001, 0x08000020, 0x00100012, 0x00000001, 0x0020800a, 0x00000000, 0x00000001, 0x00004001,
4060 0x00000003, 0x0304001f, 0x0010000a, 0x00000001, 0x0800000f, 0x00100022, 0x00000001, 0x00101046,
4061 0x00000000, 0x00208046, 0x00000000, 0x00000002, 0x08000000, 0x00100012, 0x00000002, 0x0010001a,
4062 0x00000001, 0x0020802a, 0x00000000, 0x00000002, 0x0800000f, 0x00100022, 0x00000001, 0x00101046,
4063 0x00000000, 0x00208046, 0x00000000, 0x00000003, 0x08000000, 0x00100022, 0x00000002, 0x0010001a,
4064 0x00000001, 0x0020802a, 0x00000000, 0x00000003, 0x09000045, 0x001000f2, 0x00000002, 0x00100046,
4065 0x00000002, 0x00107e46, 0x00000000, 0x00106000, 0x00000000, 0x0a000037, 0x00100082, 0x00000002,
4066 0x0020803a, 0x00000000, 0x00000003, 0x00004001, 0x3f800000, 0x0010003a, 0x00000002, 0x08000038,
4067 0x001000f2, 0x00000000, 0x00100e46, 0x00000002, 0x00208556, 0x00000000, 0x00000001, 0x01000015,
4068 0x05000036, 0x00100012, 0x00000002, 0x00004001, 0x00000000, 0x06000036, 0x00100082, 0x00000002,
4069 0x0020801a, 0x00000000, 0x00000001, 0x09000037, 0x001000f2, 0x00000000, 0x00100006, 0x00000001,
4070 0x00100e46, 0x00000000, 0x00100c06, 0x00000002, 0x01000015, 0x01000015, 0x01000015, 0x0800004f,
4071 0x00100012, 0x00000001, 0x0020800a, 0x00000000, 0x00000005, 0x00004001, 0x00000004, 0x0304001f,
4072 0x0010000a, 0x00000001, 0x09000038, 0x00100012, 0x00000001, 0x0020801a, 0x00000000, 0x00000005,
4073 0x0020803a, 0x00000000, 0x00000006, 0x0404001f, 0x0020800a, 0x00000000, 0x00000005, 0x08000020,
4074 0x00100022, 0x00000001, 0x0020800a, 0x00000000, 0x00000005, 0x00004001, 0x00000001, 0x0304001f,
4075 0x0010001a, 0x00000001, 0x09000000, 0x001000c2, 0x00000001, 0x00101406, 0x00000000, 0x80208406,
4076 0x00000041, 0x00000000, 0x00000006, 0x0a000000, 0x00100032, 0x00000002, 0x80208046, 0x00000041,
4077 0x00000000, 0x00000006, 0x00208ae6, 0x00000000, 0x00000006, 0x0700000f, 0x00100042, 0x00000001,
4078 0x00100046, 0x00000002, 0x00100ae6, 0x00000001, 0x0700000f, 0x00100082, 0x00000001, 0x00100046,
4079 0x00000002, 0x00100046, 0x00000002, 0x0700000e, 0x00100042, 0x00000001, 0x0010002a, 0x00000001,
4080 0x0010003a, 0x00000001, 0x0a00002d, 0x001000f2, 0x00000002, 0x00004002, 0x00000000, 0x00000000,
4081 0x00000000, 0x00000000, 0x00107e46, 0x00000003, 0x0a00002d, 0x001000f2, 0x00000003, 0x00004002,
4082 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00107e46, 0x00000003, 0x0700001d, 0x00100082,
4083 0x00000001, 0x0010002a, 0x00000001, 0x0010000a, 0x00000002, 0x0304001f, 0x0010003a, 0x00000001,
4084 0x05000036, 0x00100082, 0x00000001, 0x0010003a, 0x00000003, 0x05000036, 0x00100062, 0x00000002,
4085 0x00100ff6, 0x00000003, 0x05000036, 0x00100082, 0x00000002, 0x0010000a, 0x00000002, 0x08000036,
4086 0x00100032, 0x00000003, 0x00004002, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x01000030,
4087 0x08000050, 0x00100042, 0x00000003, 0x0010000a, 0x00000003, 0x0020800a, 0x00000000, 0x00000007,
4088 0x05000036, 0x00100022, 0x00000003, 0x00004001, 0x00000000, 0x03040003, 0x0010002a, 0x00000003,
4089 0x07000029, 0x00100042, 0x00000003, 0x0010000a, 0x00000003, 0x00004001, 0x00000001, 0x0700002d,
4090 0x001000f2, 0x00000004, 0x00100aa6, 0x00000003, 0x00107e46, 0x00000003, 0x0700001e, 0x00100042,
4091 0x00000003, 0x0010002a, 0x00000003, 0x00004001, 0x00000001, 0x0700002d, 0x001000f2, 0x00000005,
4092 0x00100aa6, 0x00000003, 0x00107e46, 0x00000003, 0x0700001d, 0x00100042, 0x00000003, 0x0010002a,
4093 0x00000001, 0x0010003a, 0x00000002, 0x0700001d, 0x00100022, 0x00000004, 0x0010000a, 0x00000004,
4094 0x0010002a, 0x00000001, 0x07000001, 0x00100042, 0x00000003, 0x0010002a, 0x00000003, 0x0010001a,
4095 0x00000004, 0x0304001f, 0x0010002a, 0x00000003, 0x08000000, 0x00100022, 0x00000004, 0x0010002a,
4096 0x00000001, 0x8010003a, 0x00000041, 0x00000002, 0x08000000, 0x00100042, 0x00000004, 0x8010003a,
4097 0x00000041, 0x00000002, 0x0010000a, 0x00000004, 0x0700000e, 0x00100022, 0x00000004, 0x0010001a,
4098 0x00000004, 0x0010002a, 0x00000004, 0x08000000, 0x00100042, 0x00000004, 0x8010001a, 0x00000041,
4099 0x00000002, 0x0010003a, 0x00000005, 0x09000032, 0x00100022, 0x00000004, 0x0010001a, 0x00000004,
4100 0x0010002a, 0x00000004, 0x0010001a, 0x00000002, 0x05000036, 0x00100042, 0x00000002, 0x0010003a,
4101 0x00000005, 0x05000036, 0x00100022, 0x00000003, 0x00004001, 0xffffffff, 0x05000036, 0x00100082,
4102 0x00000001, 0x0010001a, 0x00000004, 0x01000002, 0x01000015, 0x05000036, 0x00100022, 0x00000002,
4103 0x0010003a, 0x00000005, 0x05000036, 0x00100082, 0x00000002, 0x0010000a, 0x00000004, 0x0700001e,
4104 0x00100012, 0x00000003, 0x0010000a, 0x00000003, 0x00004001, 0x00000001, 0x05000036, 0x00100042,
4105 0x00000002, 0x0010003a, 0x00000005, 0x05000036, 0x00100032, 0x00000003, 0x00100086, 0x00000003,
4106 0x01000016, 0x09000037, 0x00100042, 0x00000001, 0x0010001a, 0x00000003, 0x0010003a, 0x00000001,
4107 0x0010002a, 0x00000002, 0x01000012, 0x05000036, 0x00100042, 0x00000001, 0x0010003a, 0x00000003,
4108 0x01000015, 0x08000038, 0x00100012, 0x00000001, 0x0010002a, 0x00000001, 0x0020801a, 0x00000000,
4109 0x00000005, 0x01000015, 0x0300001f, 0x0010001a, 0x00000001, 0x08000020, 0x00100022, 0x00000001,
4110 0x0020800a, 0x00000000, 0x00000005, 0x00004001, 0x00000002, 0x0304001f, 0x0010001a, 0x00000001,
4111 0x0900000f, 0x00100012, 0x00000002, 0x00208046, 0x00000000, 0x00000007, 0x00208046, 0x00000000,
4112 0x00000007, 0x0900000f, 0x00100022, 0x00000002, 0x00208ae6, 0x00000000, 0x00000007, 0x00208ae6,
4113 0x00000000, 0x00000007, 0x09000000, 0x001000c2, 0x00000001, 0x00208ea6, 0x00000000, 0x00000006,
4114 0x00208406, 0x00000000, 0x00000006, 0x08000000, 0x001000c2, 0x00000001, 0x80100ea6, 0x00000041,
4115 0x00000001, 0x00101406, 0x00000000, 0x0800000f, 0x00100012, 0x00000003, 0x00100ae6, 0x00000001,
4116 0x00208046, 0x00000000, 0x00000007, 0x0800000f, 0x00100022, 0x00000003, 0x00100ae6, 0x00000001,
4117 0x00208ae6, 0x00000000, 0x00000007, 0x0700000e, 0x001000c2, 0x00000001, 0x00100406, 0x00000003,
4118 0x00100406, 0x00000002, 0x0900000f, 0x00100012, 0x00000003, 0x00208ae6, 0x00000000, 0x00000006,
4119 0x00208046, 0x00000000, 0x00000007, 0x0900000f, 0x00100022, 0x00000003, 0x00208ae6, 0x00000000,
4120 0x00000006, 0x00208ae6, 0x00000000, 0x00000007, 0x0700000e, 0x00100032, 0x00000002, 0x00100046,
4121 0x00000003, 0x00100046, 0x00000002, 0x0700000f, 0x00100042, 0x00000002, 0x00100ae6, 0x00000001,
4122 0x00100ae6, 0x00000001, 0x0500004b, 0x00100042, 0x00000002, 0x0010002a, 0x00000002, 0x0700000f,
4123 0x00100042, 0x00000001, 0x00100ae6, 0x00000001, 0x00100046, 0x00000002, 0x0700000e, 0x00100042,
4124 0x00000001, 0x0010002a, 0x00000001, 0x0010002a, 0x00000002, 0x0700000f, 0x00100082, 0x00000001,
4125 0x00100046, 0x00000002, 0x00100046, 0x00000002, 0x07000000, 0x00100082, 0x00000001, 0x0010003a,
4126 0x00000001, 0x00004001, 0xbf800000, 0x0a000032, 0x00100082, 0x00000001, 0x0010002a, 0x00000001,
4127 0x0010002a, 0x00000001, 0x8010003a, 0x00000041, 0x00000001, 0x0500004b, 0x00100082, 0x00000001,
4128 0x0010003a, 0x00000001, 0x08000000, 0x00100042, 0x00000001, 0x0010003a, 0x00000001, 0x8010002a,
4129 0x00000041, 0x00000001, 0x0700000e, 0x00100042, 0x00000001, 0x0010002a, 0x00000002, 0x0010002a,
4130 0x00000001, 0x0a00002d, 0x001000f2, 0x00000002, 0x00004002, 0x00000000, 0x00000000, 0x00000000,
4131 0x00000000, 0x00107e46, 0x00000003, 0x0a00002d, 0x001000f2, 0x00000003, 0x00004002, 0x00000001,
4132 0x00000001, 0x00000001, 0x00000001, 0x00107e46, 0x00000003, 0x0700001d, 0x00100082, 0x00000001,
4133 0x0010002a, 0x00000001, 0x0010000a, 0x00000002, 0x0304001f, 0x0010003a, 0x00000001, 0x05000036,
4134 0x00100082, 0x00000001, 0x0010003a, 0x00000003, 0x05000036, 0x00100062, 0x00000002, 0x00100ff6,
4135 0x00000003, 0x05000036, 0x00100082, 0x00000002, 0x0010000a, 0x00000002, 0x08000036, 0x00100032,
4136 0x00000003, 0x00004002, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x01000030, 0x08000050,
4137 0x00100042, 0x00000003, 0x0010000a, 0x00000003, 0x0020800a, 0x00000000, 0x00000008, 0x05000036,
4138 0x00100022, 0x00000003, 0x00004001, 0x00000000, 0x03040003, 0x0010002a, 0x00000003, 0x07000029,
4139 0x00100042, 0x00000003, 0x0010000a, 0x00000003, 0x00004001, 0x00000001, 0x0700002d, 0x001000f2,
4140 0x00000004, 0x00100aa6, 0x00000003, 0x00107e46, 0x00000003, 0x0700001e, 0x00100042, 0x00000003,
4141 0x0010002a, 0x00000003, 0x00004001, 0x00000001, 0x0700002d, 0x001000f2, 0x00000005, 0x00100aa6,
4142 0x00000003, 0x00107e46, 0x00000003, 0x0700001d, 0x00100042, 0x00000003, 0x0010002a, 0x00000001,
4143 0x0010003a, 0x00000002, 0x0700001d, 0x00100022, 0x00000004, 0x0010000a, 0x00000004, 0x0010002a,
4144 0x00000001, 0x07000001, 0x00100042, 0x00000003, 0x0010002a, 0x00000003, 0x0010001a, 0x00000004,
4145 0x0304001f, 0x0010002a, 0x00000003, 0x08000000, 0x00100022, 0x00000004, 0x0010002a, 0x00000001,
4146 0x8010003a, 0x00000041, 0x00000002, 0x08000000, 0x00100042, 0x00000004, 0x8010003a, 0x00000041,
4147 0x00000002, 0x0010000a, 0x00000004, 0x0700000e, 0x00100022, 0x00000004, 0x0010001a, 0x00000004,
4148 0x0010002a, 0x00000004, 0x08000000, 0x00100042, 0x00000004, 0x8010001a, 0x00000041, 0x00000002,
4149 0x0010003a, 0x00000005, 0x09000032, 0x00100022, 0x00000004, 0x0010001a, 0x00000004, 0x0010002a,
4150 0x00000004, 0x0010001a, 0x00000002, 0x05000036, 0x00100042, 0x00000002, 0x0010003a, 0x00000005,
4151 0x05000036, 0x00100022, 0x00000003, 0x00004001, 0xffffffff, 0x05000036, 0x00100082, 0x00000001,
4152 0x0010001a, 0x00000004, 0x01000002, 0x01000015, 0x05000036, 0x00100022, 0x00000002, 0x0010003a,
4153 0x00000005, 0x05000036, 0x00100082, 0x00000002, 0x0010000a, 0x00000004, 0x0700001e, 0x00100012,
4154 0x00000003, 0x0010000a, 0x00000003, 0x00004001, 0x00000001, 0x05000036, 0x00100042, 0x00000002,
4155 0x0010003a, 0x00000005, 0x05000036, 0x00100032, 0x00000003, 0x00100086, 0x00000003, 0x01000016,
4156 0x09000037, 0x00100042, 0x00000001, 0x0010001a, 0x00000003, 0x0010003a, 0x00000001, 0x0010002a,
4157 0x00000002, 0x01000012, 0x05000036, 0x00100042, 0x00000001, 0x0010003a, 0x00000003, 0x01000015,
4158 0x08000038, 0x00100012, 0x00000001, 0x0010002a, 0x00000001, 0x0020801a, 0x00000000, 0x00000005,
4159 0x01000015, 0x0300001f, 0x0010001a, 0x00000001, 0x08000020, 0x00100022, 0x00000001, 0x0020800a,
4160 0x00000000, 0x00000005, 0x00004001, 0x00000003, 0x0304001f, 0x0010001a, 0x00000001, 0x0800000f,
4161 0x00100042, 0x00000001, 0x00101046, 0x00000000, 0x00208046, 0x00000000, 0x00000006, 0x08000000,
4162 0x00100012, 0x00000002, 0x0010002a, 0x00000001, 0x0020802a, 0x00000000, 0x00000006, 0x0800000f,
4163 0x00100042, 0x00000001, 0x00101046, 0x00000000, 0x00208046, 0x00000000, 0x00000007, 0x08000000,
4164 0x00100022, 0x00000002, 0x0010002a, 0x00000001, 0x0020802a, 0x00000000, 0x00000007, 0x09000045,
4165 0x001000f2, 0x00000002, 0x00100046, 0x00000002, 0x00107e46, 0x00000001, 0x00106000, 0x00000001,
4166 0x0a000037, 0x00100042, 0x00000001, 0x0020803a, 0x00000000, 0x00000007, 0x00004001, 0x3f800000,
4167 0x0010003a, 0x00000002, 0x08000038, 0x00100012, 0x00000001, 0x0010002a, 0x00000001, 0x0020801a,
4168 0x00000000, 0x00000005, 0x01000015, 0x0a000037, 0x00100012, 0x00000001, 0x0010001a, 0x00000001,
4169 0x0010000a, 0x00000001, 0x0020801a, 0x00000000, 0x00000005, 0x01000015, 0x01000015, 0x01000015,
4170 0x07000038, 0x001020f2, 0x00000000, 0x00100e46, 0x00000000, 0x00100006, 0x00000001, 0x01000012,
4171 0x05000036, 0x001020f2, 0x00000000, 0x00100e46, 0x00000000, 0x01000015, 0x0404001f, 0x0020800a,
4172 0x00000000, 0x00000000, 0x0500000b, 0x00100032, 0x00000000, 0x00101046, 0x00000001, 0x0500000c,
4173 0x001000c2, 0x00000000, 0x00101406, 0x00000001, 0x08000027, 0x00100012, 0x00000001, 0x0020801a,
4174 0x00000000, 0x00000000, 0x00004001, 0x00000000, 0x0500003b, 0x00100022, 0x00000001, 0x0010000a,
4175 0x00000001, 0x07000000, 0x001000c2, 0x00000001, 0x00101406, 0x00000001, 0x00101406, 0x00000001,
4176 0x07000038, 0x001000f2, 0x00000002, 0x00100d86, 0x00000000, 0x00100fa6, 0x00000001, 0x0a000032,
4177 0x00100032, 0x00000000, 0x00100aa6, 0x00000001, 0x00100086, 0x00000000, 0x801005d6, 0x00000041,
4178 0x00000000, 0x0700000f, 0x00100042, 0x00000000, 0x00100046, 0x00000000, 0x00101ae6, 0x00000001,
4179 0x07000031, 0x00100042, 0x00000000, 0x0010002a, 0x00000000, 0x00004001, 0x00000000, 0x07000001,
4180 0x00100042, 0x00000000, 0x0010001a, 0x00000001, 0x0010002a, 0x00000000, 0x0304000d, 0x0010002a,
4181 0x00000000, 0x07000038, 0x00100062, 0x00000000, 0x00100556, 0x00000000, 0x00101106, 0x00000003,
4182 0x09000032, 0x00100032, 0x00000000, 0x00101046, 0x00000002, 0x00100006, 0x00000000, 0x00100596,
4183 0x00000000, 0x0700000f, 0x00100012, 0x00000000, 0x00100046, 0x00000000, 0x00100046, 0x00000000,
4184 0x0500004b, 0x00100012, 0x00000000, 0x0010000a, 0x00000000, 0x07000038, 0x00100062, 0x00000000,
4185 0x00101106, 0x00000001, 0x00101106, 0x00000001, 0x0a000032, 0x00100082, 0x00000000, 0x0010100a,
4186 0x00000001, 0x0010100a, 0x00000001, 0x8010101a, 0x00000041, 0x00000001, 0x08000000, 0x00100012,
4187 0x00000000, 0x8010003a, 0x000000c1, 0x00000000, 0x0010000a, 0x00000000, 0x07000031, 0x00100012,
4188 0x00000000, 0x0010000a, 0x00000000, 0x00004001, 0x00000000, 0x07000001, 0x00100012, 0x00000000,
4189 0x0010001a, 0x00000001, 0x0010000a, 0x00000000, 0x0304000d, 0x0010000a, 0x00000000, 0x07000000,
4190 0x00100092, 0x00000000, 0x00100ea6, 0x00000002, 0x00100406, 0x00000002, 0x0700000f, 0x00100022,
4191 0x00000001, 0x001000c6, 0x00000000, 0x00101ae6, 0x00000001, 0x07000031, 0x00100022, 0x00000001,
4192 0x0010001a, 0x00000001, 0x00004001, 0x00000000, 0x07000001, 0x00100022, 0x00000001, 0x0010000a,
4193 0x00000001, 0x0010001a, 0x00000001, 0x0304000d, 0x0010001a, 0x00000001, 0x07000038, 0x00100062,
4194 0x00000001, 0x00100ff6, 0x00000000, 0x00101106, 0x00000003, 0x09000032, 0x00100092, 0x00000000,
4195 0x00101406, 0x00000002, 0x00100006, 0x00000000, 0x00100956, 0x00000001, 0x0700000f, 0x00100012,
4196 0x00000000, 0x001000c6, 0x00000000, 0x001000c6, 0x00000000, 0x0500004b, 0x00100012, 0x00000000,
4197 0x0010000a, 0x00000000, 0x07000000, 0x00100022, 0x00000000, 0x0010002a, 0x00000000, 0x0010001a,
4198 0x00000000, 0x07000000, 0x00100022, 0x00000000, 0x0010001a, 0x00000000, 0x00004001, 0xbf800000,
4199 0x08000000, 0x00100012, 0x00000000, 0x8010001a, 0x000000c1, 0x00000000, 0x0010000a, 0x00000000,
4200 0x07000031, 0x00100012, 0x00000000, 0x0010000a, 0x00000000, 0x00004001, 0x00000000, 0x07000001,
4201 0x00100012, 0x00000000, 0x0010000a, 0x00000001, 0x0010000a, 0x00000000, 0x0304000d, 0x0010000a,
4202 0x00000000, 0x01000012, 0x08000027, 0x00100012, 0x00000000, 0x0020801a, 0x00000000, 0x00000000,
4203 0x00004001, 0x00000000, 0x0500003b, 0x00100022, 0x00000000, 0x0010000a, 0x00000000, 0x07000038,
4204 0x001000c2, 0x00000000, 0x00101406, 0x00000001, 0x00101406, 0x00000001, 0x0a000032, 0x00100012,
4205 0x00000001, 0x0010100a, 0x00000001, 0x0010100a, 0x00000001, 0x8010101a, 0x00000041, 0x00000001,
4206 0x07000038, 0x00100012, 0x00000001, 0x0010000a, 0x00000001, 0x0010102a, 0x00000001, 0x07000031,
4207 0x00100012, 0x00000001, 0x0010000a, 0x00000001, 0x00004001, 0x00000000, 0x07000001, 0x00100022,
4208 0x00000000, 0x0010001a, 0x00000000, 0x0010000a, 0x00000001, 0x0304000d, 0x0010001a, 0x00000000,
4209 0x07000000, 0x00100022, 0x00000000, 0x0010003a, 0x00000000, 0x0010002a, 0x00000000, 0x07000000,
4210 0x00100022, 0x00000000, 0x0010001a, 0x00000000, 0x00004001, 0xbf800000, 0x07000038, 0x00100022,
4211 0x00000000, 0x0010001a, 0x00000000, 0x0010102a, 0x00000001, 0x07000031, 0x00100022, 0x00000000,
4212 0x0010001a, 0x00000000, 0x00004001, 0x00000000, 0x07000001, 0x00100012, 0x00000000, 0x0010000a,
4213 0x00000000, 0x0010001a, 0x00000000, 0x0304000d, 0x0010000a, 0x00000000, 0x01000015, 0x0100003e,
4215 static const struct shape_info
4217 enum d2d_shape_type shape_type;
4218 const D3D11_INPUT_ELEMENT_DESC *il_desc;
4219 unsigned int il_element_count;
4220 const void *vs_code;
4221 size_t vs_code_size;
4223 shape_info[] =
4225 {D2D_SHAPE_TYPE_OUTLINE, il_desc_outline, ARRAY_SIZE(il_desc_outline),
4226 vs_code_outline, sizeof(vs_code_outline)},
4227 {D2D_SHAPE_TYPE_BEZIER_OUTLINE, il_desc_curve_outline, ARRAY_SIZE(il_desc_curve_outline),
4228 vs_code_bezier_outline, sizeof(vs_code_bezier_outline)},
4229 {D2D_SHAPE_TYPE_ARC_OUTLINE, il_desc_curve_outline, ARRAY_SIZE(il_desc_curve_outline),
4230 vs_code_arc_outline, sizeof(vs_code_arc_outline)},
4231 {D2D_SHAPE_TYPE_TRIANGLE, il_desc_triangle, ARRAY_SIZE(il_desc_triangle),
4232 vs_code_triangle, sizeof(vs_code_triangle)},
4233 {D2D_SHAPE_TYPE_CURVE, il_desc_curve, ARRAY_SIZE(il_desc_curve),
4234 vs_code_curve, sizeof(vs_code_curve)},
4236 static const struct
4238 float x, y;
4240 quad[] =
4242 {-1.0f, 1.0f},
4243 {-1.0f, -1.0f},
4244 { 1.0f, 1.0f},
4245 { 1.0f, -1.0f},
4247 static const UINT16 indices[] = {0, 1, 2, 2, 1, 3};
4248 static const D3D_FEATURE_LEVEL feature_levels = D3D_FEATURE_LEVEL_10_0;
4250 render_target->ID2D1DeviceContext1_iface.lpVtbl = &d2d_device_context_vtbl;
4251 render_target->ID2D1GdiInteropRenderTarget_iface.lpVtbl = &d2d_gdi_interop_render_target_vtbl;
4252 render_target->IDWriteTextRenderer_iface.lpVtbl = &d2d_text_renderer_vtbl;
4253 render_target->IUnknown_iface.lpVtbl = &d2d_device_context_inner_unknown_vtbl;
4254 render_target->refcount = 1;
4255 ID2D1Device1_GetFactory(&device->ID2D1Device1_iface, &render_target->factory);
4256 render_target->device = device;
4257 ID2D1Device1_AddRef(&render_target->device->ID2D1Device1_iface);
4259 render_target->outer_unknown = outer_unknown ? outer_unknown : &render_target->IUnknown_iface;
4260 render_target->ops = ops;
4262 device_impl = unsafe_impl_from_ID2D1Device((ID2D1Device1 *)device);
4263 if (FAILED(hr = IDXGIDevice_QueryInterface(device_impl->dxgi_device,
4264 &IID_ID3D11Device1, (void **)&render_target->d3d_device)))
4266 WARN("Failed to query ID3D11Device1 interface, hr %#lx.\n", hr);
4267 goto err;
4270 if (FAILED(hr = ID3D11Device1_CreateDeviceContextState(render_target->d3d_device,
4271 0, &feature_levels, 1, D3D11_SDK_VERSION, &IID_ID3D11Device1, NULL,
4272 &render_target->d3d_state)))
4274 WARN("Failed to create device context state, hr %#lx.\n", hr);
4275 goto err;
4278 for (i = 0; i < ARRAY_SIZE(shape_info); ++i)
4280 const struct shape_info *si = &shape_info[i];
4282 if (FAILED(hr = ID3D11Device1_CreateInputLayout(render_target->d3d_device, si->il_desc, si->il_element_count,
4283 si->vs_code, si->vs_code_size, &render_target->shape_resources[si->shape_type].il)))
4285 WARN("Failed to create input layout for shape type %#x, hr %#lx.\n", si->shape_type, hr);
4286 goto err;
4289 if (FAILED(hr = ID3D11Device1_CreateVertexShader(render_target->d3d_device, si->vs_code,
4290 si->vs_code_size, NULL, &render_target->shape_resources[si->shape_type].vs)))
4292 WARN("Failed to create vertex shader for shape type %#x, hr %#lx.\n", si->shape_type, hr);
4293 goto err;
4298 buffer_desc.ByteWidth = sizeof(struct d2d_vs_cb);
4299 buffer_desc.Usage = D3D11_USAGE_DYNAMIC;
4300 buffer_desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
4301 buffer_desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
4302 buffer_desc.MiscFlags = 0;
4304 if (FAILED(hr = ID3D11Device1_CreateBuffer(render_target->d3d_device, &buffer_desc, NULL,
4305 &render_target->vs_cb)))
4307 WARN("Failed to create constant buffer, hr %#lx.\n", hr);
4308 goto err;
4311 if (FAILED(hr = ID3D11Device1_CreatePixelShader(render_target->d3d_device,
4312 ps_code, sizeof(ps_code), NULL, &render_target->ps)))
4314 WARN("Failed to create pixel shader, hr %#lx.\n", hr);
4315 goto err;
4318 buffer_desc.ByteWidth = sizeof(struct d2d_ps_cb);
4319 buffer_desc.Usage = D3D11_USAGE_DYNAMIC;
4320 buffer_desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
4321 buffer_desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
4322 buffer_desc.MiscFlags = 0;
4324 if (FAILED(hr = ID3D11Device1_CreateBuffer(render_target->d3d_device, &buffer_desc, NULL,
4325 &render_target->ps_cb)))
4327 WARN("Failed to create constant buffer, hr %#lx.\n", hr);
4328 goto err;
4331 buffer_desc.ByteWidth = sizeof(indices);
4332 buffer_desc.Usage = D3D11_USAGE_DEFAULT;
4333 buffer_desc.BindFlags = D3D11_BIND_INDEX_BUFFER;
4334 buffer_desc.CPUAccessFlags = 0;
4335 buffer_desc.MiscFlags = 0;
4337 buffer_data.pSysMem = indices;
4338 buffer_data.SysMemPitch = 0;
4339 buffer_data.SysMemSlicePitch = 0;
4341 if (FAILED(hr = ID3D11Device1_CreateBuffer(render_target->d3d_device,
4342 &buffer_desc, &buffer_data, &render_target->ib)))
4344 WARN("Failed to create clear index buffer, hr %#lx.\n", hr);
4345 goto err;
4348 buffer_desc.ByteWidth = sizeof(quad);
4349 buffer_desc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
4350 buffer_data.pSysMem = quad;
4352 render_target->vb_stride = sizeof(*quad);
4353 if (FAILED(hr = ID3D11Device1_CreateBuffer(render_target->d3d_device,
4354 &buffer_desc, &buffer_data, &render_target->vb)))
4356 WARN("Failed to create clear vertex buffer, hr %#lx.\n", hr);
4357 goto err;
4360 rs_desc.FillMode = D3D11_FILL_SOLID;
4361 rs_desc.CullMode = D3D11_CULL_NONE;
4362 rs_desc.FrontCounterClockwise = FALSE;
4363 rs_desc.DepthBias = 0;
4364 rs_desc.DepthBiasClamp = 0.0f;
4365 rs_desc.SlopeScaledDepthBias = 0.0f;
4366 rs_desc.DepthClipEnable = TRUE;
4367 rs_desc.ScissorEnable = TRUE;
4368 rs_desc.MultisampleEnable = FALSE;
4369 rs_desc.AntialiasedLineEnable = FALSE;
4370 if (FAILED(hr = ID3D11Device1_CreateRasterizerState(render_target->d3d_device, &rs_desc, &render_target->rs)))
4372 WARN("Failed to create clear rasteriser state, hr %#lx.\n", hr);
4373 goto err;
4376 if (FAILED(hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED,
4377 &IID_IDWriteFactory, (IUnknown **)&dwrite_factory)))
4379 ERR("Failed to create dwrite factory, hr %#lx.\n", hr);
4380 goto err;
4383 hr = IDWriteFactory_CreateRenderingParams(dwrite_factory, &render_target->default_text_rendering_params);
4384 IDWriteFactory_Release(dwrite_factory);
4385 if (FAILED(hr))
4387 ERR("Failed to create default text rendering parameters, hr %#lx.\n", hr);
4388 goto err;
4391 render_target->drawing_state.transform = identity;
4393 if (!d2d_clip_stack_init(&render_target->clip_stack))
4395 WARN("Failed to initialize clip stack.\n");
4396 hr = E_FAIL;
4397 goto err;
4400 render_target->desc.dpiX = 96.0f;
4401 render_target->desc.dpiY = 96.0f;
4403 return S_OK;
4405 err:
4406 if (render_target->default_text_rendering_params)
4407 IDWriteRenderingParams_Release(render_target->default_text_rendering_params);
4408 if (render_target->rs)
4409 ID3D11RasterizerState_Release(render_target->rs);
4410 if (render_target->vb)
4411 ID3D11Buffer_Release(render_target->vb);
4412 if (render_target->ib)
4413 ID3D11Buffer_Release(render_target->ib);
4414 if (render_target->ps_cb)
4415 ID3D11Buffer_Release(render_target->ps_cb);
4416 if (render_target->ps)
4417 ID3D11PixelShader_Release(render_target->ps);
4418 if (render_target->vs_cb)
4419 ID3D11Buffer_Release(render_target->vs_cb);
4420 for (i = 0; i < D2D_SHAPE_TYPE_COUNT; ++i)
4422 if (render_target->shape_resources[i].vs)
4423 ID3D11VertexShader_Release(render_target->shape_resources[i].vs);
4424 if (render_target->shape_resources[i].il)
4425 ID3D11InputLayout_Release(render_target->shape_resources[i].il);
4427 if (render_target->d3d_state)
4428 ID3DDeviceContextState_Release(render_target->d3d_state);
4429 if (render_target->d3d_device)
4430 ID3D11Device1_Release(render_target->d3d_device);
4431 ID2D1Device1_Release(&render_target->device->ID2D1Device1_iface);
4432 ID2D1Factory_Release(render_target->factory);
4433 return hr;
4436 HRESULT d2d_d3d_create_render_target(struct d2d_device *device, IDXGISurface *surface, IUnknown *outer_unknown,
4437 const struct d2d_device_context_ops *ops, const D2D1_RENDER_TARGET_PROPERTIES *desc, void **render_target)
4439 D2D1_BITMAP_PROPERTIES1 bitmap_desc;
4440 struct d2d_device_context *object;
4441 ID2D1Bitmap1 *bitmap;
4442 HRESULT hr;
4444 if (desc->type != D2D1_RENDER_TARGET_TYPE_DEFAULT && desc->type != D2D1_RENDER_TARGET_TYPE_HARDWARE)
4445 WARN("Ignoring render target type %#x.\n", desc->type);
4446 if (desc->usage != D2D1_RENDER_TARGET_USAGE_NONE)
4447 FIXME("Ignoring render target usage %#x.\n", desc->usage);
4448 if (desc->minLevel != D2D1_FEATURE_LEVEL_DEFAULT)
4449 WARN("Ignoring feature level %#x.\n", desc->minLevel);
4451 bitmap_desc.dpiX = desc->dpiX;
4452 bitmap_desc.dpiY = desc->dpiY;
4454 if (bitmap_desc.dpiX == 0.0f && bitmap_desc.dpiY == 0.0f)
4456 bitmap_desc.dpiX = 96.0f;
4457 bitmap_desc.dpiY = 96.0f;
4459 else if (bitmap_desc.dpiX <= 0.0f || bitmap_desc.dpiY <= 0.0f)
4460 return E_INVALIDARG;
4462 if (!(object = calloc(1, sizeof(*object))))
4463 return E_OUTOFMEMORY;
4465 if (FAILED(hr = d2d_device_context_init(object, device, outer_unknown, ops)))
4467 WARN("Failed to initialise render target, hr %#lx.\n", hr);
4468 free(object);
4469 return hr;
4472 ID2D1DeviceContext1_SetDpi(&object->ID2D1DeviceContext1_iface, bitmap_desc.dpiX, bitmap_desc.dpiY);
4474 if (surface)
4476 bitmap_desc.pixelFormat = desc->pixelFormat;
4477 bitmap_desc.bitmapOptions = D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW;
4478 if (desc->usage & D2D1_RENDER_TARGET_USAGE_GDI_COMPATIBLE)
4479 bitmap_desc.bitmapOptions |= D2D1_BITMAP_OPTIONS_GDI_COMPATIBLE;
4480 bitmap_desc.colorContext = NULL;
4482 if (FAILED(hr = ID2D1DeviceContext1_CreateBitmapFromDxgiSurface(&object->ID2D1DeviceContext1_iface,
4483 surface, &bitmap_desc, &bitmap)))
4485 WARN("Failed to create target bitmap, hr %#lx.\n", hr);
4486 IUnknown_Release(&object->IUnknown_iface);
4487 free(object);
4488 return hr;
4491 ID2D1DeviceContext1_SetTarget(&object->ID2D1DeviceContext1_iface, (ID2D1Image *)bitmap);
4492 ID2D1Bitmap1_Release(bitmap);
4494 else
4495 object->desc.pixelFormat = desc->pixelFormat;
4497 TRACE("Created render target %p.\n", object);
4498 *render_target = outer_unknown ? &object->IUnknown_iface : (IUnknown *)&object->ID2D1DeviceContext1_iface;
4500 return S_OK;
4503 static HRESULT WINAPI d2d_device_QueryInterface(ID2D1Device1 *iface, REFIID iid, void **out)
4505 TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
4507 if (IsEqualGUID(iid, &IID_ID2D1Device1)
4508 || IsEqualGUID(iid, &IID_ID2D1Device)
4509 || IsEqualGUID(iid, &IID_ID2D1Resource)
4510 || IsEqualGUID(iid, &IID_IUnknown))
4512 ID2D1Device1_AddRef(iface);
4513 *out = iface;
4514 return S_OK;
4517 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
4519 *out = NULL;
4520 return E_NOINTERFACE;
4523 static ULONG WINAPI d2d_device_AddRef(ID2D1Device1 *iface)
4525 struct d2d_device *device = impl_from_ID2D1Device(iface);
4526 ULONG refcount = InterlockedIncrement(&device->refcount);
4528 TRACE("%p increasing refcount to %lu.\n", iface, refcount);
4530 return refcount;
4533 static ULONG WINAPI d2d_device_Release(ID2D1Device1 *iface)
4535 struct d2d_device *device = impl_from_ID2D1Device(iface);
4536 ULONG refcount = InterlockedDecrement(&device->refcount);
4537 size_t i;
4539 TRACE("%p decreasing refcount to %lu.\n", iface, refcount);
4541 if (!refcount)
4543 IDXGIDevice_Release(device->dxgi_device);
4544 ID2D1Factory1_Release(device->factory);
4545 for (i = 0; i < device->shaders.count; ++i)
4546 IUnknown_Release(device->shaders.objects[i].shader);
4547 free(device->shaders.objects);
4548 free(device);
4551 return refcount;
4554 static void WINAPI d2d_device_GetFactory(ID2D1Device1 *iface, ID2D1Factory **factory)
4556 struct d2d_device *device = impl_from_ID2D1Device(iface);
4558 TRACE("iface %p, factory %p.\n", iface, factory);
4560 *factory = (ID2D1Factory *)device->factory;
4561 ID2D1Factory1_AddRef(device->factory);
4564 static HRESULT d2d_device_create_device_context(struct d2d_device *device,
4565 D2D1_DEVICE_CONTEXT_OPTIONS options, ID2D1DeviceContext1 **context)
4567 struct d2d_device_context *object;
4568 HRESULT hr;
4570 if (options)
4571 FIXME("Options are ignored %#x.\n", options);
4573 if (!(object = calloc(1, sizeof(*object))))
4574 return E_OUTOFMEMORY;
4576 if (FAILED(hr = d2d_device_context_init(object, device, NULL, NULL)))
4578 WARN("Failed to initialise device context, hr %#lx.\n", hr);
4579 free(object);
4580 return hr;
4583 TRACE("Created device context %p.\n", object);
4584 *context = &object->ID2D1DeviceContext1_iface;
4586 return S_OK;
4589 static HRESULT WINAPI d2d_device_CreateDeviceContext(ID2D1Device1 *iface, D2D1_DEVICE_CONTEXT_OPTIONS options,
4590 ID2D1DeviceContext **context)
4592 struct d2d_device *device = impl_from_ID2D1Device(iface);
4594 TRACE("iface %p, options %#x, context %p.\n", iface, options, context);
4596 return d2d_device_create_device_context(device, options, (ID2D1DeviceContext1 **)context);
4599 static HRESULT WINAPI d2d_device_CreatePrintControl(ID2D1Device1 *iface, IWICImagingFactory *wic_factory,
4600 IPrintDocumentPackageTarget *document_target, const D2D1_PRINT_CONTROL_PROPERTIES *desc,
4601 ID2D1PrintControl **print_control)
4603 FIXME("iface %p, wic_factory %p, document_target %p, desc %p, print_control %p stub!\n", iface, wic_factory,
4604 document_target, desc, print_control);
4606 return E_NOTIMPL;
4609 static void WINAPI d2d_device_SetMaximumTextureMemory(ID2D1Device1 *iface, UINT64 max_texture_memory)
4611 FIXME("iface %p, max_texture_memory %s stub!\n", iface, wine_dbgstr_longlong(max_texture_memory));
4614 static UINT64 WINAPI d2d_device_GetMaximumTextureMemory(ID2D1Device1 *iface)
4616 FIXME("iface %p stub!\n", iface);
4618 return 0;
4621 static HRESULT WINAPI d2d_device_ClearResources(ID2D1Device1 *iface, UINT msec_since_use)
4623 FIXME("iface %p, msec_since_use %u stub!\n", iface, msec_since_use);
4625 return E_NOTIMPL;
4628 static D2D1_RENDERING_PRIORITY WINAPI d2d_device_GetRenderingPriority(ID2D1Device1 *iface)
4630 FIXME("iface %p stub!\n", iface);
4632 return D2D1_RENDERING_PRIORITY_NORMAL;
4635 static void WINAPI d2d_device_SetRenderingPriority(ID2D1Device1 *iface, D2D1_RENDERING_PRIORITY priority)
4637 FIXME("iface %p, priority %#x stub!\n", iface, priority);
4640 static HRESULT WINAPI d2d_device_CreateDeviceContext1(ID2D1Device1 *iface, D2D1_DEVICE_CONTEXT_OPTIONS options,
4641 ID2D1DeviceContext1 **context)
4643 struct d2d_device *device = impl_from_ID2D1Device(iface);
4645 TRACE("iface %p, options %#x, context %p.\n", iface, options, context);
4647 return d2d_device_create_device_context(device, options, context);
4650 static const struct ID2D1Device1Vtbl d2d_device_vtbl =
4652 d2d_device_QueryInterface,
4653 d2d_device_AddRef,
4654 d2d_device_Release,
4655 d2d_device_GetFactory,
4656 d2d_device_CreateDeviceContext,
4657 d2d_device_CreatePrintControl,
4658 d2d_device_SetMaximumTextureMemory,
4659 d2d_device_GetMaximumTextureMemory,
4660 d2d_device_ClearResources,
4661 d2d_device_GetRenderingPriority,
4662 d2d_device_SetRenderingPriority,
4663 d2d_device_CreateDeviceContext1,
4666 struct d2d_device *unsafe_impl_from_ID2D1Device(ID2D1Device1 *iface)
4668 if (!iface)
4669 return NULL;
4670 assert(iface->lpVtbl == &d2d_device_vtbl);
4671 return CONTAINING_RECORD(iface, struct d2d_device, ID2D1Device1_iface);
4674 void d2d_device_init(struct d2d_device *device, ID2D1Factory1 *iface, IDXGIDevice *dxgi_device)
4676 device->ID2D1Device1_iface.lpVtbl = &d2d_device_vtbl;
4677 device->refcount = 1;
4678 device->factory = iface;
4679 ID2D1Factory1_AddRef(device->factory);
4680 device->dxgi_device = dxgi_device;
4681 IDXGIDevice_AddRef(device->dxgi_device);
4684 HRESULT d2d_device_add_shader(struct d2d_device *device, REFGUID shader_id, IUnknown *shader)
4686 struct d2d_shader *entry;
4688 if (!d2d_array_reserve((void **)&device->shaders.objects, &device->shaders.size,
4689 device->shaders.count + 1, sizeof(*device->shaders.objects)))
4691 WARN("Failed to resize shaders array.\n");
4692 return E_OUTOFMEMORY;
4695 entry = &device->shaders.objects[device->shaders.count++];
4696 entry->id = *shader_id;
4697 entry->shader = shader;
4698 IUnknown_AddRef(entry->shader);
4700 return S_OK;
4703 BOOL d2d_device_is_shader_loaded(struct d2d_device *device, REFGUID shader_id)
4705 size_t i;
4707 for (i = 0; i < device->shaders.count; ++i)
4709 if (IsEqualGUID(shader_id, &device->shaders.objects[i].id))
4710 return TRUE;
4713 return FALSE;