mstask: Implement ITask::DeleteTrigger().
[wine.git] / dlls / d2d1 / render_target.c
blob7afbc84ec564f57b91241a74b84db16d8413cdcd
1 /*
2 * Copyright 2014 Henri Verbeet for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 #include "config.h"
20 #include "wine/port.h"
22 #include "d2d1_private.h"
24 WINE_DEFAULT_DEBUG_CHANNEL(d2d);
26 #define INITIAL_CLIP_STACK_SIZE 4
28 static const D2D1_MATRIX_3X2_F identity =
30 1.0f, 0.0f,
31 0.0f, 1.0f,
32 0.0f, 0.0f,
35 struct d2d_draw_text_layout_ctx
37 ID2D1Brush *brush;
38 D2D1_DRAW_TEXT_OPTIONS options;
41 static ID2D1Brush *d2d_draw_get_text_brush(struct d2d_draw_text_layout_ctx *context, IUnknown *effect)
43 ID2D1Brush *brush = NULL;
45 if (effect && SUCCEEDED(IUnknown_QueryInterface(effect, &IID_ID2D1Brush, (void**)&brush)))
46 return brush;
48 ID2D1Brush_AddRef(context->brush);
49 return context->brush;
52 static void d2d_rect_intersect(D2D1_RECT_F *dst, const D2D1_RECT_F *src)
54 if (src->left > dst->left)
55 dst->left = src->left;
56 if (src->top > dst->top)
57 dst->top = src->top;
58 if (src->right < dst->right)
59 dst->right = src->right;
60 if (src->bottom < dst->bottom)
61 dst->bottom = src->bottom;
64 static void d2d_rect_set(D2D1_RECT_F *dst, float left, float top, float right, float bottom)
66 dst->left = left;
67 dst->top = top;
68 dst->right = right;
69 dst->bottom = bottom;
72 static void d2d_size_set(D2D1_SIZE_U *dst, float width, float height)
74 dst->width = width;
75 dst->height = height;
78 static BOOL d2d_clip_stack_init(struct d2d_clip_stack *stack)
80 if (!(stack->stack = heap_alloc(INITIAL_CLIP_STACK_SIZE * sizeof(*stack->stack))))
81 return FALSE;
83 stack->size = INITIAL_CLIP_STACK_SIZE;
84 stack->count = 0;
86 return TRUE;
89 static void d2d_clip_stack_cleanup(struct d2d_clip_stack *stack)
91 heap_free(stack->stack);
94 static BOOL d2d_clip_stack_push(struct d2d_clip_stack *stack, const D2D1_RECT_F *rect)
96 D2D1_RECT_F r;
98 if (!d2d_array_reserve((void **)&stack->stack, &stack->size, stack->count + 1, sizeof(*stack->stack)))
99 return FALSE;
101 r = *rect;
102 if (stack->count)
103 d2d_rect_intersect(&r, &stack->stack[stack->count - 1]);
104 stack->stack[stack->count++] = r;
106 return TRUE;
109 static void d2d_clip_stack_pop(struct d2d_clip_stack *stack)
111 if (!stack->count)
112 return;
113 --stack->count;
116 static void d2d_rt_draw(struct d2d_d3d_render_target *render_target, enum d2d_shape_type shape_type,
117 ID3D10Buffer *ib, unsigned int index_count, ID3D10Buffer *vb, unsigned int vb_stride,
118 ID3D10Buffer *vs_cb, ID3D10Buffer *ps_cb, struct d2d_brush *brush, struct d2d_brush *opacity_brush)
120 struct d2d_shape_resources *shape_resources = &render_target->shape_resources[shape_type];
121 ID3D10Device *device = render_target->device;
122 D3D10_RECT scissor_rect;
123 unsigned int offset;
124 D3D10_VIEWPORT vp;
125 HRESULT hr;
127 static const float blend_factor[] = {1.0f, 1.0f, 1.0f, 1.0f};
129 vp.TopLeftX = 0;
130 vp.TopLeftY = 0;
131 vp.Width = render_target->pixel_size.width;
132 vp.Height = render_target->pixel_size.height;
133 vp.MinDepth = 0.0f;
134 vp.MaxDepth = 1.0f;
136 if (FAILED(hr = render_target->stateblock->lpVtbl->Capture(render_target->stateblock)))
138 WARN("Failed to capture stateblock, hr %#x.\n", hr);
139 return;
142 ID3D10Device_ClearState(device);
144 ID3D10Device_IASetInputLayout(device, shape_resources->il);
145 ID3D10Device_IASetPrimitiveTopology(device, D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
146 ID3D10Device_IASetIndexBuffer(device, ib, DXGI_FORMAT_R16_UINT, 0);
147 offset = 0;
148 ID3D10Device_IASetVertexBuffers(device, 0, 1, &vb, &vb_stride, &offset);
149 ID3D10Device_VSSetConstantBuffers(device, 0, 1, &vs_cb);
150 ID3D10Device_VSSetShader(device, shape_resources->vs);
151 ID3D10Device_PSSetConstantBuffers(device, 0, 1, &ps_cb);
152 ID3D10Device_PSSetShader(device, render_target->ps);
153 ID3D10Device_RSSetViewports(device, 1, &vp);
154 if (render_target->clip_stack.count)
156 const D2D1_RECT_F *clip_rect;
158 clip_rect = &render_target->clip_stack.stack[render_target->clip_stack.count - 1];
159 scissor_rect.left = ceilf(clip_rect->left - 0.5f);
160 scissor_rect.top = ceilf(clip_rect->top - 0.5f);
161 scissor_rect.right = ceilf(clip_rect->right - 0.5f);
162 scissor_rect.bottom = ceilf(clip_rect->bottom - 0.5f);
164 else
166 scissor_rect.left = 0.0f;
167 scissor_rect.top = 0.0f;
168 scissor_rect.right = render_target->pixel_size.width;
169 scissor_rect.bottom = render_target->pixel_size.height;
171 ID3D10Device_RSSetScissorRects(device, 1, &scissor_rect);
172 ID3D10Device_RSSetState(device, render_target->rs);
173 ID3D10Device_OMSetRenderTargets(device, 1, &render_target->view, NULL);
174 if (brush)
176 ID3D10Device_OMSetBlendState(device, render_target->bs, blend_factor, D3D10_DEFAULT_SAMPLE_MASK);
177 d2d_brush_bind_resources(brush, device, 0);
179 if (opacity_brush)
180 d2d_brush_bind_resources(opacity_brush, device, 1);
182 if (ib)
183 ID3D10Device_DrawIndexed(device, index_count, 0, 0);
184 else
185 ID3D10Device_Draw(device, index_count, 0);
187 if (FAILED(hr = render_target->stateblock->lpVtbl->Apply(render_target->stateblock)))
188 WARN("Failed to apply stateblock, hr %#x.\n", hr);
191 static inline struct d2d_d3d_render_target *impl_from_ID2D1RenderTarget(ID2D1RenderTarget *iface)
193 return CONTAINING_RECORD(iface, struct d2d_d3d_render_target, ID2D1RenderTarget_iface);
196 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_QueryInterface(ID2D1RenderTarget *iface, REFIID iid, void **out)
198 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
200 TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
202 if (IsEqualGUID(iid, &IID_ID2D1RenderTarget)
203 || IsEqualGUID(iid, &IID_ID2D1Resource)
204 || IsEqualGUID(iid, &IID_IUnknown))
206 ID2D1RenderTarget_AddRef(iface);
207 *out = iface;
208 return S_OK;
210 else if (IsEqualGUID(iid, &IID_ID2D1GdiInteropRenderTarget))
212 ID2D1GdiInteropRenderTarget_AddRef(&render_target->ID2D1GdiInteropRenderTarget_iface);
213 *out = &render_target->ID2D1GdiInteropRenderTarget_iface;
214 return S_OK;
217 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
219 *out = NULL;
220 return E_NOINTERFACE;
223 static ULONG STDMETHODCALLTYPE d2d_d3d_render_target_AddRef(ID2D1RenderTarget *iface)
225 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
226 ULONG refcount = InterlockedIncrement(&render_target->refcount);
228 TRACE("%p increasing refcount to %u.\n", iface, refcount);
230 return refcount;
233 static ULONG STDMETHODCALLTYPE d2d_d3d_render_target_Release(ID2D1RenderTarget *iface)
235 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
236 ULONG refcount = InterlockedDecrement(&render_target->refcount);
238 TRACE("%p decreasing refcount to %u.\n", iface, refcount);
240 if (!refcount)
242 unsigned int i;
244 d2d_clip_stack_cleanup(&render_target->clip_stack);
245 IDWriteRenderingParams_Release(render_target->default_text_rendering_params);
246 if (render_target->text_rendering_params)
247 IDWriteRenderingParams_Release(render_target->text_rendering_params);
248 ID3D10BlendState_Release(render_target->bs);
249 ID3D10RasterizerState_Release(render_target->rs);
250 ID3D10Buffer_Release(render_target->vb);
251 ID3D10Buffer_Release(render_target->ib);
252 ID3D10PixelShader_Release(render_target->ps);
253 for (i = 0; i < D2D_SHAPE_TYPE_COUNT; ++i)
255 ID3D10VertexShader_Release(render_target->shape_resources[i].vs);
256 ID3D10InputLayout_Release(render_target->shape_resources[i].il);
258 render_target->stateblock->lpVtbl->Release(render_target->stateblock);
259 ID3D10RenderTargetView_Release(render_target->view);
260 ID3D10Device_Release(render_target->device);
261 ID2D1Factory_Release(render_target->factory);
262 heap_free(render_target);
265 return refcount;
268 static void STDMETHODCALLTYPE d2d_d3d_render_target_GetFactory(ID2D1RenderTarget *iface, ID2D1Factory **factory)
270 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
272 TRACE("iface %p, factory %p.\n", iface, factory);
274 *factory = render_target->factory;
275 ID2D1Factory_AddRef(*factory);
278 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateBitmap(ID2D1RenderTarget *iface,
279 D2D1_SIZE_U size, const void *src_data, UINT32 pitch, const D2D1_BITMAP_PROPERTIES *desc, ID2D1Bitmap **bitmap)
281 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
282 struct d2d_bitmap *object;
283 HRESULT hr;
285 TRACE("iface %p, size {%u, %u}, src_data %p, pitch %u, desc %p, bitmap %p.\n",
286 iface, size.width, size.height, src_data, pitch, desc, bitmap);
288 if (SUCCEEDED(hr = d2d_bitmap_create(render_target->factory, render_target->device, size, src_data, pitch, desc, &object)))
289 *bitmap = &object->ID2D1Bitmap_iface;
291 return hr;
294 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateBitmapFromWicBitmap(ID2D1RenderTarget *iface,
295 IWICBitmapSource *bitmap_source, const D2D1_BITMAP_PROPERTIES *desc, ID2D1Bitmap **bitmap)
297 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
298 struct d2d_bitmap *object;
299 HRESULT hr;
301 TRACE("iface %p, bitmap_source %p, desc %p, bitmap %p.\n",
302 iface, bitmap_source, desc, bitmap);
304 if (SUCCEEDED(hr = d2d_bitmap_create_from_wic_bitmap(render_target->factory, render_target->device, bitmap_source,
305 desc, &object)))
306 *bitmap = &object->ID2D1Bitmap_iface;
308 return hr;
311 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateSharedBitmap(ID2D1RenderTarget *iface,
312 REFIID iid, void *data, const D2D1_BITMAP_PROPERTIES *desc, ID2D1Bitmap **bitmap)
314 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
315 struct d2d_bitmap *object;
316 HRESULT hr;
318 TRACE("iface %p, iid %s, data %p, desc %p, bitmap %p.\n",
319 iface, debugstr_guid(iid), data, desc, bitmap);
321 if (SUCCEEDED(hr = d2d_bitmap_create_shared(iface, render_target->device, iid, data, desc, &object)))
322 *bitmap = &object->ID2D1Bitmap_iface;
324 return hr;
327 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateBitmapBrush(ID2D1RenderTarget *iface,
328 ID2D1Bitmap *bitmap, const D2D1_BITMAP_BRUSH_PROPERTIES *bitmap_brush_desc,
329 const D2D1_BRUSH_PROPERTIES *brush_desc, ID2D1BitmapBrush **brush)
331 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
332 struct d2d_brush *object;
333 HRESULT hr;
335 TRACE("iface %p, bitmap %p, bitmap_brush_desc %p, brush_desc %p, brush %p.\n",
336 iface, bitmap, bitmap_brush_desc, brush_desc, brush);
338 if (SUCCEEDED(hr = d2d_bitmap_brush_create(render_target->factory, bitmap, bitmap_brush_desc, brush_desc, &object)))
339 *brush = (ID2D1BitmapBrush *)&object->ID2D1Brush_iface;
341 return hr;
344 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateSolidColorBrush(ID2D1RenderTarget *iface,
345 const D2D1_COLOR_F *color, const D2D1_BRUSH_PROPERTIES *desc, ID2D1SolidColorBrush **brush)
347 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
348 struct d2d_brush *object;
349 HRESULT hr;
351 TRACE("iface %p, color %p, desc %p, brush %p.\n", iface, color, desc, brush);
353 if (SUCCEEDED(hr = d2d_solid_color_brush_create(render_target->factory, color, desc, &object)))
354 *brush = (ID2D1SolidColorBrush *)&object->ID2D1Brush_iface;
356 return hr;
359 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateGradientStopCollection(ID2D1RenderTarget *iface,
360 const D2D1_GRADIENT_STOP *stops, UINT32 stop_count, D2D1_GAMMA gamma, D2D1_EXTEND_MODE extend_mode,
361 ID2D1GradientStopCollection **gradient)
363 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
364 struct d2d_gradient *object;
365 HRESULT hr;
367 TRACE("iface %p, stops %p, stop_count %u, gamma %#x, extend_mode %#x, gradient %p.\n",
368 iface, stops, stop_count, gamma, extend_mode, gradient);
370 if (SUCCEEDED(hr = d2d_gradient_create(render_target->factory, render_target->device,
371 stops, stop_count, gamma, extend_mode, &object)))
372 *gradient = &object->ID2D1GradientStopCollection_iface;
374 return hr;
377 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateLinearGradientBrush(ID2D1RenderTarget *iface,
378 const D2D1_LINEAR_GRADIENT_BRUSH_PROPERTIES *gradient_brush_desc, const D2D1_BRUSH_PROPERTIES *brush_desc,
379 ID2D1GradientStopCollection *gradient, ID2D1LinearGradientBrush **brush)
381 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
382 struct d2d_brush *object;
383 HRESULT hr;
385 TRACE("iface %p, gradient_brush_desc %p, brush_desc %p, gradient %p, brush %p.\n",
386 iface, gradient_brush_desc, brush_desc, gradient, brush);
388 if (SUCCEEDED(hr = d2d_linear_gradient_brush_create(render_target->factory, gradient_brush_desc, brush_desc,
389 gradient, &object)))
390 *brush = (ID2D1LinearGradientBrush *)&object->ID2D1Brush_iface;
392 return hr;
395 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateRadialGradientBrush(ID2D1RenderTarget *iface,
396 const D2D1_RADIAL_GRADIENT_BRUSH_PROPERTIES *gradient_brush_desc, const D2D1_BRUSH_PROPERTIES *brush_desc,
397 ID2D1GradientStopCollection *gradient, ID2D1RadialGradientBrush **brush)
399 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
400 struct d2d_brush *object;
401 HRESULT hr;
403 TRACE("iface %p, gradient_brush_desc %p, brush_desc %p, gradient %p, brush %p.\n",
404 iface, gradient_brush_desc, brush_desc, gradient, brush);
406 if (SUCCEEDED(hr = d2d_radial_gradient_brush_create(render_target->factory,
407 gradient_brush_desc, brush_desc, gradient, &object)))
408 *brush = (ID2D1RadialGradientBrush *)&object->ID2D1Brush_iface;
410 return hr;
413 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateCompatibleRenderTarget(ID2D1RenderTarget *iface,
414 const D2D1_SIZE_F *size, const D2D1_SIZE_U *pixel_size, const D2D1_PIXEL_FORMAT *format,
415 D2D1_COMPATIBLE_RENDER_TARGET_OPTIONS options, ID2D1BitmapRenderTarget **rt)
417 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
418 struct d2d_bitmap_render_target *object;
419 HRESULT hr;
421 TRACE("iface %p, size %p, pixel_size %p, format %p, options %#x, render_target %p.\n",
422 iface, size, pixel_size, format, options, rt);
424 if (!(object = heap_alloc_zero(sizeof(*object))))
425 return E_OUTOFMEMORY;
427 if (FAILED(hr = d2d_bitmap_render_target_init(object, render_target, size, pixel_size,
428 format, options)))
430 WARN("Failed to initialize render target, hr %#x.\n", hr);
431 heap_free(object);
432 return hr;
435 TRACE("Created render target %p.\n", object);
436 *rt = &object->ID2D1BitmapRenderTarget_iface;
438 return S_OK;
441 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateLayer(ID2D1RenderTarget *iface,
442 const D2D1_SIZE_F *size, ID2D1Layer **layer)
444 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
445 struct d2d_layer *object;
446 HRESULT hr;
448 TRACE("iface %p, size %p, layer %p.\n", iface, size, layer);
450 if (SUCCEEDED(hr = d2d_layer_create(render_target->factory, size, &object)))
451 *layer = &object->ID2D1Layer_iface;
453 return hr;
456 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateMesh(ID2D1RenderTarget *iface, ID2D1Mesh **mesh)
458 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
459 struct d2d_mesh *object;
460 HRESULT hr;
462 TRACE("iface %p, mesh %p.\n", iface, mesh);
464 if (SUCCEEDED(hr = d2d_mesh_create(render_target->factory, &object)))
465 *mesh = &object->ID2D1Mesh_iface;
467 return hr;
470 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawLine(ID2D1RenderTarget *iface,
471 D2D1_POINT_2F p0, D2D1_POINT_2F p1, ID2D1Brush *brush, float stroke_width, ID2D1StrokeStyle *stroke_style)
473 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
474 ID2D1PathGeometry *geometry;
475 ID2D1GeometrySink *sink;
476 HRESULT hr;
478 TRACE("iface %p, p0 {%.8e, %.8e}, p1 {%.8e, %.8e}, brush %p, stroke_width %.8e, stroke_style %p.\n",
479 iface, p0.x, p0.y, p1.x, p1.y, brush, stroke_width, stroke_style);
481 if (FAILED(hr = ID2D1Factory_CreatePathGeometry(render_target->factory, &geometry)))
483 WARN("Failed to create path geometry, %#x.\n", hr);
484 return;
487 if (FAILED(hr = ID2D1PathGeometry_Open(geometry, &sink)))
489 WARN("Open() failed, %#x.\n", hr);
490 ID2D1PathGeometry_Release(geometry);
491 return;
494 ID2D1GeometrySink_BeginFigure(sink, p0, D2D1_FIGURE_BEGIN_HOLLOW);
495 ID2D1GeometrySink_AddLine(sink, p1);
496 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_OPEN);
497 if (FAILED(hr = ID2D1GeometrySink_Close(sink)))
498 WARN("Close() failed, %#x.\n", hr);
499 ID2D1GeometrySink_Release(sink);
501 ID2D1RenderTarget_DrawGeometry(iface, (ID2D1Geometry *)geometry, brush, stroke_width, stroke_style);
502 ID2D1PathGeometry_Release(geometry);
505 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawRectangle(ID2D1RenderTarget *iface,
506 const D2D1_RECT_F *rect, ID2D1Brush *brush, float stroke_width, ID2D1StrokeStyle *stroke_style)
508 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
509 ID2D1RectangleGeometry *geometry;
510 HRESULT hr;
512 TRACE("iface %p, rect %s, brush %p, stroke_width %.8e, stroke_style %p.\n",
513 iface, debug_d2d_rect_f(rect), brush, stroke_width, stroke_style);
515 if (FAILED(hr = ID2D1Factory_CreateRectangleGeometry(render_target->factory, rect, &geometry)))
517 ERR("Failed to create geometry, hr %#x.\n", hr);
518 return;
521 ID2D1RenderTarget_DrawGeometry(iface, (ID2D1Geometry *)geometry, brush, stroke_width, stroke_style);
522 ID2D1RectangleGeometry_Release(geometry);
525 static void STDMETHODCALLTYPE d2d_d3d_render_target_FillRectangle(ID2D1RenderTarget *iface,
526 const D2D1_RECT_F *rect, ID2D1Brush *brush)
528 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
529 ID2D1RectangleGeometry *geometry;
530 HRESULT hr;
532 TRACE("iface %p, rect %s, brush %p.\n", iface, debug_d2d_rect_f(rect), brush);
534 if (FAILED(hr = ID2D1Factory_CreateRectangleGeometry(render_target->factory, rect, &geometry)))
536 ERR("Failed to create geometry, hr %#x.\n", hr);
537 return;
540 ID2D1RenderTarget_FillGeometry(iface, (ID2D1Geometry *)geometry, brush, NULL);
541 ID2D1RectangleGeometry_Release(geometry);
544 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawRoundedRectangle(ID2D1RenderTarget *iface,
545 const D2D1_ROUNDED_RECT *rect, ID2D1Brush *brush, float stroke_width, ID2D1StrokeStyle *stroke_style)
547 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
548 ID2D1RoundedRectangleGeometry *geometry;
549 HRESULT hr;
551 TRACE("iface %p, rect %p, brush %p, stroke_width %.8e, stroke_style %p.\n",
552 iface, rect, brush, stroke_width, stroke_style);
554 if (FAILED(hr = ID2D1Factory_CreateRoundedRectangleGeometry(render_target->factory, rect, &geometry)))
556 ERR("Failed to create geometry, hr %#x.\n", hr);
557 return;
560 ID2D1RenderTarget_DrawGeometry(iface, (ID2D1Geometry *)geometry, brush, stroke_width, stroke_style);
561 ID2D1RoundedRectangleGeometry_Release(geometry);
564 static void STDMETHODCALLTYPE d2d_d3d_render_target_FillRoundedRectangle(ID2D1RenderTarget *iface,
565 const D2D1_ROUNDED_RECT *rect, ID2D1Brush *brush)
567 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
568 ID2D1RoundedRectangleGeometry *geometry;
569 HRESULT hr;
571 TRACE("iface %p, rect %p, brush %p.\n", iface, rect, brush);
573 if (FAILED(hr = ID2D1Factory_CreateRoundedRectangleGeometry(render_target->factory, rect, &geometry)))
575 ERR("Failed to create geometry, hr %#x.\n", hr);
576 return;
579 ID2D1RenderTarget_FillGeometry(iface, (ID2D1Geometry *)geometry, brush, NULL);
580 ID2D1RoundedRectangleGeometry_Release(geometry);
583 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawEllipse(ID2D1RenderTarget *iface,
584 const D2D1_ELLIPSE *ellipse, ID2D1Brush *brush, float stroke_width, ID2D1StrokeStyle *stroke_style)
586 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
587 ID2D1EllipseGeometry *geometry;
588 HRESULT hr;
590 TRACE("iface %p, ellipse %p, brush %p, stroke_width %.8e, stroke_style %p.\n",
591 iface, ellipse, brush, stroke_width, stroke_style);
593 if (FAILED(hr = ID2D1Factory_CreateEllipseGeometry(render_target->factory, ellipse, &geometry)))
595 ERR("Failed to create geometry, hr %#x.\n", hr);
596 return;
599 ID2D1RenderTarget_DrawGeometry(iface, (ID2D1Geometry *)geometry, brush, stroke_width, stroke_style);
600 ID2D1EllipseGeometry_Release(geometry);
603 static void STDMETHODCALLTYPE d2d_d3d_render_target_FillEllipse(ID2D1RenderTarget *iface,
604 const D2D1_ELLIPSE *ellipse, ID2D1Brush *brush)
606 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
607 ID2D1EllipseGeometry *geometry;
608 HRESULT hr;
610 TRACE("iface %p, ellipse %p, brush %p.\n", iface, ellipse, brush);
612 if (FAILED(hr = ID2D1Factory_CreateEllipseGeometry(render_target->factory, ellipse, &geometry)))
614 ERR("Failed to create geometry, hr %#x.\n", hr);
615 return;
618 ID2D1RenderTarget_FillGeometry(iface, (ID2D1Geometry *)geometry, brush, NULL);
619 ID2D1EllipseGeometry_Release(geometry);
622 static void d2d_rt_draw_geometry(struct d2d_d3d_render_target *render_target,
623 const struct d2d_geometry *geometry, struct d2d_brush *brush, float stroke_width)
625 ID3D10Buffer *ib, *vb, *vs_cb, *ps_cb;
626 D3D10_SUBRESOURCE_DATA buffer_data;
627 D3D10_BUFFER_DESC buffer_desc;
628 const D2D1_MATRIX_3X2_F *w;
629 float tmp_x, tmp_y;
630 HRESULT hr;
631 struct
633 struct
635 float _11, _21, _31, pad0;
636 float _12, _22, _32, stroke_width;
637 } transform_geometry;
638 struct d2d_vec4 transform_rtx;
639 struct d2d_vec4 transform_rty;
640 } vs_cb_data;
642 vs_cb_data.transform_geometry._11 = geometry->transform._11;
643 vs_cb_data.transform_geometry._21 = geometry->transform._21;
644 vs_cb_data.transform_geometry._31 = geometry->transform._31;
645 vs_cb_data.transform_geometry.pad0 = 0.0f;
646 vs_cb_data.transform_geometry._12 = geometry->transform._12;
647 vs_cb_data.transform_geometry._22 = geometry->transform._22;
648 vs_cb_data.transform_geometry._32 = geometry->transform._32;
649 vs_cb_data.transform_geometry.stroke_width = stroke_width;
651 w = &render_target->drawing_state.transform;
653 tmp_x = render_target->desc.dpiX / 96.0f;
654 vs_cb_data.transform_rtx.x = w->_11 * tmp_x;
655 vs_cb_data.transform_rtx.y = w->_21 * tmp_x;
656 vs_cb_data.transform_rtx.z = w->_31 * tmp_x;
657 vs_cb_data.transform_rtx.w = 2.0f / render_target->pixel_size.width;
659 tmp_y = render_target->desc.dpiY / 96.0f;
660 vs_cb_data.transform_rty.x = w->_12 * tmp_y;
661 vs_cb_data.transform_rty.y = w->_22 * tmp_y;
662 vs_cb_data.transform_rty.z = w->_32 * tmp_y;
663 vs_cb_data.transform_rty.w = -2.0f / render_target->pixel_size.height;
665 buffer_desc.ByteWidth = sizeof(vs_cb_data);
666 buffer_desc.Usage = D3D10_USAGE_DEFAULT;
667 buffer_desc.BindFlags = D3D10_BIND_CONSTANT_BUFFER;
668 buffer_desc.CPUAccessFlags = 0;
669 buffer_desc.MiscFlags = 0;
671 buffer_data.pSysMem = &vs_cb_data;
672 buffer_data.SysMemPitch = 0;
673 buffer_data.SysMemSlicePitch = 0;
675 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device, &buffer_desc, &buffer_data, &vs_cb)))
677 WARN("Failed to create constant buffer, hr %#x.\n", hr);
678 return;
681 if (FAILED(hr = d2d_brush_get_ps_cb(brush, NULL, TRUE, render_target, &ps_cb)))
683 WARN("Failed to get ps constant buffer, hr %#x.\n", hr);
684 ID3D10Buffer_Release(vs_cb);
685 return;
688 if (geometry->outline.face_count)
690 buffer_desc.ByteWidth = geometry->outline.face_count * sizeof(*geometry->outline.faces);
691 buffer_desc.BindFlags = D3D10_BIND_INDEX_BUFFER;
692 buffer_data.pSysMem = geometry->outline.faces;
694 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device, &buffer_desc, &buffer_data, &ib)))
696 WARN("Failed to create index buffer, hr %#x.\n", hr);
697 goto done;
700 buffer_desc.ByteWidth = geometry->outline.vertex_count * sizeof(*geometry->outline.vertices);
701 buffer_desc.BindFlags = D3D10_BIND_VERTEX_BUFFER;
702 buffer_data.pSysMem = geometry->outline.vertices;
704 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device, &buffer_desc, &buffer_data, &vb)))
706 ERR("Failed to create vertex buffer, hr %#x.\n", hr);
707 ID3D10Buffer_Release(ib);
708 goto done;
711 d2d_rt_draw(render_target, D2D_SHAPE_TYPE_OUTLINE, ib, 3 * geometry->outline.face_count, vb,
712 sizeof(*geometry->outline.vertices), vs_cb, ps_cb, brush, NULL);
714 ID3D10Buffer_Release(vb);
715 ID3D10Buffer_Release(ib);
718 if (geometry->outline.bezier_face_count)
720 buffer_desc.ByteWidth = geometry->outline.bezier_face_count * sizeof(*geometry->outline.bezier_faces);
721 buffer_desc.BindFlags = D3D10_BIND_INDEX_BUFFER;
722 buffer_data.pSysMem = geometry->outline.bezier_faces;
724 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device, &buffer_desc, &buffer_data, &ib)))
726 WARN("Failed to create beziers index buffer, hr %#x.\n", hr);
727 goto done;
730 buffer_desc.ByteWidth = geometry->outline.bezier_count * sizeof(*geometry->outline.beziers);
731 buffer_desc.BindFlags = D3D10_BIND_VERTEX_BUFFER;
732 buffer_data.pSysMem = geometry->outline.beziers;
734 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device, &buffer_desc, &buffer_data, &vb)))
736 ERR("Failed to create beziers vertex buffer, hr %#x.\n", hr);
737 ID3D10Buffer_Release(ib);
738 goto done;
741 d2d_rt_draw(render_target, D2D_SHAPE_TYPE_BEZIER_OUTLINE, ib, 3 * geometry->outline.bezier_face_count, vb,
742 sizeof(*geometry->outline.beziers), vs_cb, ps_cb, brush, NULL);
744 ID3D10Buffer_Release(vb);
745 ID3D10Buffer_Release(ib);
748 done:
749 ID3D10Buffer_Release(ps_cb);
750 ID3D10Buffer_Release(vs_cb);
753 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawGeometry(ID2D1RenderTarget *iface,
754 ID2D1Geometry *geometry, ID2D1Brush *brush, float stroke_width, ID2D1StrokeStyle *stroke_style)
756 const struct d2d_geometry *geometry_impl = unsafe_impl_from_ID2D1Geometry(geometry);
757 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
758 struct d2d_brush *brush_impl = unsafe_impl_from_ID2D1Brush(brush);
760 TRACE("iface %p, geometry %p, brush %p, stroke_width %.8e, stroke_style %p.\n",
761 iface, geometry, brush, stroke_width, stroke_style);
763 if (stroke_style)
764 FIXME("Ignoring stroke style %p.\n", stroke_style);
766 d2d_rt_draw_geometry(render_target, geometry_impl, brush_impl, stroke_width);
769 static void d2d_rt_fill_geometry(struct d2d_d3d_render_target *render_target,
770 const struct d2d_geometry *geometry, struct d2d_brush *brush, struct d2d_brush *opacity_brush)
772 ID3D10Buffer *ib, *vb, *vs_cb, *ps_cb;
773 D3D10_SUBRESOURCE_DATA buffer_data;
774 D3D10_BUFFER_DESC buffer_desc;
775 D2D1_MATRIX_3X2_F *w;
776 float tmp_x, tmp_y;
777 HRESULT hr;
778 struct
780 struct
782 float _11, _21, _31, pad0;
783 float _12, _22, _32, pad1;
784 } transform_geometry;
785 struct d2d_vec4 transform_rtx;
786 struct d2d_vec4 transform_rty;
787 } vs_cb_data;
789 vs_cb_data.transform_geometry._11 = geometry->transform._11;
790 vs_cb_data.transform_geometry._21 = geometry->transform._21;
791 vs_cb_data.transform_geometry._31 = geometry->transform._31;
792 vs_cb_data.transform_geometry.pad0 = 0.0f;
793 vs_cb_data.transform_geometry._12 = geometry->transform._12;
794 vs_cb_data.transform_geometry._22 = geometry->transform._22;
795 vs_cb_data.transform_geometry._32 = geometry->transform._32;
796 vs_cb_data.transform_geometry.pad1 = 0.0f;
798 w = &render_target->drawing_state.transform;
800 tmp_x = render_target->desc.dpiX / 96.0f;
801 vs_cb_data.transform_rtx.x = w->_11 * tmp_x;
802 vs_cb_data.transform_rtx.y = w->_21 * tmp_x;
803 vs_cb_data.transform_rtx.z = w->_31 * tmp_x;
804 vs_cb_data.transform_rtx.w = 2.0f / render_target->pixel_size.width;
806 tmp_y = render_target->desc.dpiY / 96.0f;
807 vs_cb_data.transform_rty.x = w->_12 * tmp_y;
808 vs_cb_data.transform_rty.y = w->_22 * tmp_y;
809 vs_cb_data.transform_rty.z = w->_32 * tmp_y;
810 vs_cb_data.transform_rty.w = -2.0f / render_target->pixel_size.height;
812 buffer_desc.ByteWidth = sizeof(vs_cb_data);
813 buffer_desc.Usage = D3D10_USAGE_DEFAULT;
814 buffer_desc.BindFlags = D3D10_BIND_CONSTANT_BUFFER;
815 buffer_desc.CPUAccessFlags = 0;
816 buffer_desc.MiscFlags = 0;
818 buffer_data.pSysMem = &vs_cb_data;
819 buffer_data.SysMemPitch = 0;
820 buffer_data.SysMemSlicePitch = 0;
822 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device, &buffer_desc, &buffer_data, &vs_cb)))
824 WARN("Failed to create constant buffer, hr %#x.\n", hr);
825 return;
828 if (FAILED(hr = d2d_brush_get_ps_cb(brush, opacity_brush, FALSE, render_target, &ps_cb)))
830 WARN("Failed to get ps constant buffer, hr %#x.\n", hr);
831 ID3D10Buffer_Release(vs_cb);
832 return;
835 if (geometry->fill.face_count)
837 buffer_desc.ByteWidth = geometry->fill.face_count * sizeof(*geometry->fill.faces);
838 buffer_desc.BindFlags = D3D10_BIND_INDEX_BUFFER;
839 buffer_data.pSysMem = geometry->fill.faces;
841 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device, &buffer_desc, &buffer_data, &ib)))
843 WARN("Failed to create index buffer, hr %#x.\n", hr);
844 goto done;
847 buffer_desc.ByteWidth = geometry->fill.vertex_count * sizeof(*geometry->fill.vertices);
848 buffer_desc.BindFlags = D3D10_BIND_VERTEX_BUFFER;
849 buffer_data.pSysMem = geometry->fill.vertices;
851 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device, &buffer_desc, &buffer_data, &vb)))
853 ERR("Failed to create vertex buffer, hr %#x.\n", hr);
854 ID3D10Buffer_Release(ib);
855 goto done;
858 d2d_rt_draw(render_target, D2D_SHAPE_TYPE_TRIANGLE, ib, 3 * geometry->fill.face_count, vb,
859 sizeof(*geometry->fill.vertices), vs_cb, ps_cb, brush, opacity_brush);
861 ID3D10Buffer_Release(vb);
862 ID3D10Buffer_Release(ib);
865 if (geometry->fill.bezier_vertex_count)
867 buffer_desc.ByteWidth = geometry->fill.bezier_vertex_count * sizeof(*geometry->fill.bezier_vertices);
868 buffer_data.pSysMem = geometry->fill.bezier_vertices;
870 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device, &buffer_desc, &buffer_data, &vb)))
872 ERR("Failed to create beziers vertex buffer, hr %#x.\n", hr);
873 goto done;
876 d2d_rt_draw(render_target, D2D_SHAPE_TYPE_BEZIER, NULL, geometry->fill.bezier_vertex_count, vb,
877 sizeof(*geometry->fill.bezier_vertices), vs_cb, ps_cb, brush, opacity_brush);
879 ID3D10Buffer_Release(vb);
882 done:
883 ID3D10Buffer_Release(ps_cb);
884 ID3D10Buffer_Release(vs_cb);
887 static void STDMETHODCALLTYPE d2d_d3d_render_target_FillGeometry(ID2D1RenderTarget *iface,
888 ID2D1Geometry *geometry, ID2D1Brush *brush, ID2D1Brush *opacity_brush)
890 const struct d2d_geometry *geometry_impl = unsafe_impl_from_ID2D1Geometry(geometry);
891 struct d2d_brush *opacity_brush_impl = unsafe_impl_from_ID2D1Brush(opacity_brush);
892 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
893 struct d2d_brush *brush_impl = unsafe_impl_from_ID2D1Brush(brush);
895 TRACE("iface %p, geometry %p, brush %p, opacity_brush %p.\n", iface, geometry, brush, opacity_brush);
897 if (FAILED(render_target->error.code))
898 return;
900 if (opacity_brush && brush_impl->type != D2D_BRUSH_TYPE_BITMAP)
902 render_target->error.code = D2DERR_INCOMPATIBLE_BRUSH_TYPES;
903 render_target->error.tag1 = render_target->drawing_state.tag1;
904 render_target->error.tag2 = render_target->drawing_state.tag2;
905 return;
908 d2d_rt_fill_geometry(render_target, geometry_impl, brush_impl, opacity_brush_impl);
911 static void STDMETHODCALLTYPE d2d_d3d_render_target_FillMesh(ID2D1RenderTarget *iface,
912 ID2D1Mesh *mesh, ID2D1Brush *brush)
914 FIXME("iface %p, mesh %p, brush %p stub!\n", iface, mesh, brush);
917 static void STDMETHODCALLTYPE d2d_d3d_render_target_FillOpacityMask(ID2D1RenderTarget *iface,
918 ID2D1Bitmap *mask, ID2D1Brush *brush, D2D1_OPACITY_MASK_CONTENT content,
919 const D2D1_RECT_F *dst_rect, const D2D1_RECT_F *src_rect)
921 FIXME("iface %p, mask %p, brush %p, content %#x, dst_rect %s, src_rect %s stub!\n",
922 iface, mask, brush, content, debug_d2d_rect_f(dst_rect), debug_d2d_rect_f(src_rect));
925 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawBitmap(ID2D1RenderTarget *iface,
926 ID2D1Bitmap *bitmap, const D2D1_RECT_F *dst_rect, float opacity,
927 D2D1_BITMAP_INTERPOLATION_MODE interpolation_mode, const D2D1_RECT_F *src_rect)
929 D2D1_BITMAP_BRUSH_PROPERTIES bitmap_brush_desc;
930 D2D1_BRUSH_PROPERTIES brush_desc;
931 ID2D1BitmapBrush *brush;
932 D2D1_RECT_F s, d;
933 HRESULT hr;
935 TRACE("iface %p, bitmap %p, dst_rect %s, opacity %.8e, interpolation_mode %#x, src_rect %s.\n",
936 iface, bitmap, debug_d2d_rect_f(dst_rect), opacity, interpolation_mode, debug_d2d_rect_f(src_rect));
938 if (src_rect)
940 s = *src_rect;
942 else
944 D2D1_SIZE_F size;
946 size = ID2D1Bitmap_GetSize(bitmap);
947 s.left = 0.0f;
948 s.top = 0.0f;
949 s.right = size.width;
950 s.bottom = size.height;
953 if (dst_rect)
955 d = *dst_rect;
957 else
959 d.left = 0.0f;
960 d.top = 0.0f;
961 d.right = s.right - s.left;
962 d.bottom = s.bottom - s.top;
965 bitmap_brush_desc.extendModeX = D2D1_EXTEND_MODE_CLAMP;
966 bitmap_brush_desc.extendModeY = D2D1_EXTEND_MODE_CLAMP;
967 bitmap_brush_desc.interpolationMode = interpolation_mode;
969 brush_desc.opacity = opacity;
970 brush_desc.transform._11 = fabsf((d.right - d.left) / (s.right - s.left));
971 brush_desc.transform._21 = 0.0f;
972 brush_desc.transform._31 = min(d.left, d.right) - min(s.left, s.right) * brush_desc.transform._11;
973 brush_desc.transform._12 = 0.0f;
974 brush_desc.transform._22 = fabsf((d.bottom - d.top) / (s.bottom - s.top));
975 brush_desc.transform._32 = min(d.top, d.bottom) - min(s.top, s.bottom) * brush_desc.transform._22;
977 if (FAILED(hr = ID2D1RenderTarget_CreateBitmapBrush(iface, bitmap, &bitmap_brush_desc, &brush_desc, &brush)))
979 ERR("Failed to create bitmap brush, hr %#x.\n", hr);
980 return;
983 ID2D1RenderTarget_FillRectangle(iface, &d, (ID2D1Brush *)brush);
984 ID2D1BitmapBrush_Release(brush);
987 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawText(ID2D1RenderTarget *iface,
988 const WCHAR *string, UINT32 string_len, IDWriteTextFormat *text_format, const D2D1_RECT_F *layout_rect,
989 ID2D1Brush *brush, D2D1_DRAW_TEXT_OPTIONS options, DWRITE_MEASURING_MODE measuring_mode)
991 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
992 IDWriteTextLayout *text_layout;
993 IDWriteFactory *dwrite_factory;
994 D2D1_POINT_2F origin;
995 HRESULT hr;
997 TRACE("iface %p, string %s, string_len %u, text_format %p, layout_rect %s, "
998 "brush %p, options %#x, measuring_mode %#x.\n",
999 iface, debugstr_wn(string, string_len), string_len, text_format, debug_d2d_rect_f(layout_rect),
1000 brush, options, measuring_mode);
1002 if (FAILED(hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED,
1003 &IID_IDWriteFactory, (IUnknown **)&dwrite_factory)))
1005 ERR("Failed to create dwrite factory, hr %#x.\n", hr);
1006 return;
1009 if (measuring_mode == DWRITE_MEASURING_MODE_NATURAL)
1010 hr = IDWriteFactory_CreateTextLayout(dwrite_factory, string, string_len, text_format,
1011 layout_rect->right - layout_rect->left, layout_rect->bottom - layout_rect->top, &text_layout);
1012 else
1013 hr = IDWriteFactory_CreateGdiCompatibleTextLayout(dwrite_factory, string, string_len, text_format,
1014 layout_rect->right - layout_rect->left, layout_rect->bottom - layout_rect->top, render_target->desc.dpiX / 96.0f,
1015 (DWRITE_MATRIX*)&render_target->drawing_state.transform, measuring_mode == DWRITE_MEASURING_MODE_GDI_NATURAL, &text_layout);
1016 IDWriteFactory_Release(dwrite_factory);
1017 if (FAILED(hr))
1019 ERR("Failed to create text layout, hr %#x.\n", hr);
1020 return;
1023 d2d_point_set(&origin, layout_rect->left, layout_rect->top);
1024 ID2D1RenderTarget_DrawTextLayout(iface, origin, text_layout, brush, options);
1025 IDWriteTextLayout_Release(text_layout);
1028 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawTextLayout(ID2D1RenderTarget *iface,
1029 D2D1_POINT_2F origin, IDWriteTextLayout *layout, ID2D1Brush *brush, D2D1_DRAW_TEXT_OPTIONS options)
1031 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1032 struct d2d_draw_text_layout_ctx ctx;
1033 HRESULT hr;
1035 TRACE("iface %p, origin {%.8e, %.8e}, layout %p, brush %p, options %#x.\n",
1036 iface, origin.x, origin.y, layout, brush, options);
1038 ctx.brush = brush;
1039 ctx.options = options;
1041 if (FAILED(hr = IDWriteTextLayout_Draw(layout,
1042 &ctx, &render_target->IDWriteTextRenderer_iface, origin.x, origin.y)))
1043 FIXME("Failed to draw text layout, hr %#x.\n", hr);
1046 static D2D1_ANTIALIAS_MODE d2d_d3d_render_target_set_aa_mode_from_text_aa_mode(struct d2d_d3d_render_target *rt)
1048 D2D1_ANTIALIAS_MODE prev_antialias_mode = rt->drawing_state.antialiasMode;
1049 rt->drawing_state.antialiasMode = rt->drawing_state.textAntialiasMode == D2D1_TEXT_ANTIALIAS_MODE_ALIASED ?
1050 D2D1_ANTIALIAS_MODE_ALIASED : D2D1_ANTIALIAS_MODE_PER_PRIMITIVE;
1051 return prev_antialias_mode;
1054 static void d2d_rt_draw_glyph_run_outline(struct d2d_d3d_render_target *render_target,
1055 D2D1_POINT_2F baseline_origin, const DWRITE_GLYPH_RUN *glyph_run, ID2D1Brush *brush)
1057 D2D1_MATRIX_3X2_F *transform, prev_transform;
1058 D2D1_ANTIALIAS_MODE prev_antialias_mode;
1059 ID2D1PathGeometry *geometry;
1060 ID2D1GeometrySink *sink;
1061 HRESULT hr;
1063 if (FAILED(hr = ID2D1Factory_CreatePathGeometry(render_target->factory, &geometry)))
1065 ERR("Failed to create geometry, hr %#x.\n", hr);
1066 return;
1069 if (FAILED(hr = ID2D1PathGeometry_Open(geometry, &sink)))
1071 ERR("Failed to open geometry sink, hr %#x.\n", hr);
1072 ID2D1PathGeometry_Release(geometry);
1073 return;
1076 if (FAILED(hr = IDWriteFontFace_GetGlyphRunOutline(glyph_run->fontFace, glyph_run->fontEmSize,
1077 glyph_run->glyphIndices, glyph_run->glyphAdvances, glyph_run->glyphOffsets, glyph_run->glyphCount,
1078 glyph_run->isSideways, glyph_run->bidiLevel & 1, (IDWriteGeometrySink *)sink)))
1080 ERR("Failed to get glyph run outline, hr %#x.\n", hr);
1081 ID2D1GeometrySink_Release(sink);
1082 ID2D1PathGeometry_Release(geometry);
1083 return;
1086 if (FAILED(hr = ID2D1GeometrySink_Close(sink)))
1087 ERR("Failed to close geometry sink, hr %#x.\n", hr);
1088 ID2D1GeometrySink_Release(sink);
1090 transform = &render_target->drawing_state.transform;
1091 prev_transform = *transform;
1092 transform->_31 += baseline_origin.x * transform->_11 + baseline_origin.y * transform->_21;
1093 transform->_32 += baseline_origin.x * transform->_12 + baseline_origin.y * transform->_22;
1094 prev_antialias_mode = d2d_d3d_render_target_set_aa_mode_from_text_aa_mode(render_target);
1095 d2d_rt_fill_geometry(render_target, unsafe_impl_from_ID2D1Geometry((ID2D1Geometry *)geometry),
1096 unsafe_impl_from_ID2D1Brush(brush), NULL);
1097 render_target->drawing_state.antialiasMode = prev_antialias_mode;
1098 *transform = prev_transform;
1100 ID2D1PathGeometry_Release(geometry);
1103 static void d2d_rt_draw_glyph_run_bitmap(struct d2d_d3d_render_target *render_target,
1104 D2D1_POINT_2F baseline_origin, const DWRITE_GLYPH_RUN *glyph_run, ID2D1Brush *brush,
1105 float ppd, DWRITE_RENDERING_MODE rendering_mode, DWRITE_MEASURING_MODE measuring_mode,
1106 DWRITE_TEXT_ANTIALIAS_MODE antialias_mode)
1108 D2D1_MATRIX_3X2_F prev_transform, *transform;
1109 ID2D1RectangleGeometry *geometry = NULL;
1110 ID2D1BitmapBrush *opacity_brush = NULL;
1111 D2D1_BITMAP_PROPERTIES bitmap_desc;
1112 ID2D1Bitmap *opacity_bitmap = NULL;
1113 IDWriteGlyphRunAnalysis *analysis;
1114 DWRITE_TEXTURE_TYPE texture_type;
1115 D2D1_BRUSH_PROPERTIES brush_desc;
1116 IDWriteFactory2 *dwrite_factory;
1117 DWRITE_GLYPH_RUN scaled_run;
1118 void *opacity_values = NULL;
1119 size_t opacity_values_size;
1120 D2D1_SIZE_U bitmap_size;
1121 D2D1_RECT_F run_rect;
1122 RECT bounds;
1123 HRESULT hr;
1125 if (FAILED(hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED,
1126 &IID_IDWriteFactory2, (IUnknown **)&dwrite_factory)))
1128 ERR("Failed to create dwrite factory, hr %#x.\n", hr);
1129 return;
1132 scaled_run = *glyph_run;
1133 scaled_run.fontEmSize *= ppd;
1134 hr = IDWriteFactory2_CreateGlyphRunAnalysis(dwrite_factory, &scaled_run,
1135 (DWRITE_MATRIX *)&render_target->drawing_state.transform, rendering_mode, measuring_mode,
1136 DWRITE_GRID_FIT_MODE_DEFAULT, antialias_mode, baseline_origin.x,
1137 baseline_origin.y, &analysis);
1138 IDWriteFactory2_Release(dwrite_factory);
1139 if (FAILED(hr))
1141 ERR("Failed to create glyph run analysis, hr %#x.\n", hr);
1142 return;
1145 if (rendering_mode == DWRITE_RENDERING_MODE_ALIASED || antialias_mode == DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE)
1146 texture_type = DWRITE_TEXTURE_ALIASED_1x1;
1147 else
1148 texture_type = DWRITE_TEXTURE_CLEARTYPE_3x1;
1150 if (FAILED(hr = IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis, texture_type, &bounds)))
1152 ERR("Failed to get alpha texture bounds, hr %#x.\n", hr);
1153 goto done;
1156 d2d_size_set(&bitmap_size, bounds.right - bounds.left, bounds.bottom - bounds.top);
1157 if (!bitmap_size.width || !bitmap_size.height)
1159 /* Empty run, nothing to do. */
1160 goto done;
1163 if (texture_type == DWRITE_TEXTURE_CLEARTYPE_3x1)
1164 bitmap_size.width *= 3;
1165 if (!(opacity_values = heap_calloc(bitmap_size.height, bitmap_size.width)))
1167 ERR("Failed to allocate opacity values.\n");
1168 goto done;
1170 opacity_values_size = bitmap_size.height * bitmap_size.width;
1172 if (FAILED(hr = IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis,
1173 texture_type, &bounds, opacity_values, opacity_values_size)))
1175 ERR("Failed to create alpha texture, hr %#x.\n", hr);
1176 goto done;
1179 bitmap_desc.pixelFormat.format = DXGI_FORMAT_A8_UNORM;
1180 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
1181 bitmap_desc.dpiX = render_target->desc.dpiX;
1182 if (texture_type == DWRITE_TEXTURE_CLEARTYPE_3x1)
1183 bitmap_desc.dpiX *= 3.0f;
1184 bitmap_desc.dpiY = render_target->desc.dpiY;
1185 if (FAILED(hr = d2d_d3d_render_target_CreateBitmap(&render_target->ID2D1RenderTarget_iface,
1186 bitmap_size, opacity_values, bitmap_size.width, &bitmap_desc, &opacity_bitmap)))
1188 ERR("Failed to create opacity bitmap, hr %#x.\n", hr);
1189 goto done;
1192 brush_desc.opacity = 1.0f;
1193 brush_desc.transform._11 = 1.0f;
1194 brush_desc.transform._12 = 0.0f;
1195 brush_desc.transform._21 = 0.0f;
1196 brush_desc.transform._22 = 1.0f;
1197 brush_desc.transform._31 = bounds.left;
1198 brush_desc.transform._32 = bounds.top;
1199 if (FAILED(hr = d2d_d3d_render_target_CreateBitmapBrush(&render_target->ID2D1RenderTarget_iface,
1200 opacity_bitmap, NULL, &brush_desc, &opacity_brush)))
1202 ERR("Failed to create opacity bitmap brush, hr %#x.\n", hr);
1203 goto done;
1206 d2d_rect_set(&run_rect, bounds.left, bounds.top, bounds.right, bounds.bottom);
1207 if (FAILED(hr = ID2D1Factory_CreateRectangleGeometry(render_target->factory, &run_rect, &geometry)))
1209 ERR("Failed to create geometry, hr %#x.\n", hr);
1210 goto done;
1213 transform = &render_target->drawing_state.transform;
1214 prev_transform = *transform;
1215 *transform = identity;
1216 d2d_rt_fill_geometry(render_target, unsafe_impl_from_ID2D1Geometry((ID2D1Geometry *)geometry),
1217 unsafe_impl_from_ID2D1Brush(brush), unsafe_impl_from_ID2D1Brush((ID2D1Brush *)opacity_brush));
1218 *transform = prev_transform;
1220 done:
1221 if (geometry)
1222 ID2D1RectangleGeometry_Release(geometry);
1223 if (opacity_brush)
1224 ID2D1BitmapBrush_Release(opacity_brush);
1225 if (opacity_bitmap)
1226 ID2D1Bitmap_Release(opacity_bitmap);
1227 heap_free(opacity_values);
1228 IDWriteGlyphRunAnalysis_Release(analysis);
1231 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawGlyphRun(ID2D1RenderTarget *iface,
1232 D2D1_POINT_2F baseline_origin, const DWRITE_GLYPH_RUN *glyph_run, ID2D1Brush *brush,
1233 DWRITE_MEASURING_MODE measuring_mode)
1235 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1236 DWRITE_TEXT_ANTIALIAS_MODE antialias_mode = DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE;
1237 IDWriteRenderingParams *rendering_params;
1238 DWRITE_RENDERING_MODE rendering_mode;
1239 HRESULT hr;
1240 float ppd;
1242 TRACE("iface %p, baseline_origin {%.8e, %.8e}, glyph_run %p, brush %p, measuring_mode %#x.\n",
1243 iface, baseline_origin.x, baseline_origin.y, glyph_run, brush, measuring_mode);
1245 rendering_params = render_target->text_rendering_params ? render_target->text_rendering_params
1246 : render_target->default_text_rendering_params;
1248 rendering_mode = IDWriteRenderingParams_GetRenderingMode(rendering_params);
1250 switch (render_target->drawing_state.textAntialiasMode)
1252 case D2D1_TEXT_ANTIALIAS_MODE_ALIASED:
1253 if (rendering_mode == DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL
1254 || rendering_mode == DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC
1255 || rendering_mode == DWRITE_RENDERING_MODE_CLEARTYPE_GDI_NATURAL
1256 || rendering_mode == DWRITE_RENDERING_MODE_CLEARTYPE_GDI_CLASSIC)
1258 render_target->error.code = E_INVALIDARG;
1260 break;
1261 case D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE:
1262 if (rendering_mode == DWRITE_RENDERING_MODE_ALIASED
1263 || rendering_mode == DWRITE_RENDERING_MODE_OUTLINE)
1265 render_target->error.code = E_INVALIDARG;
1267 break;
1268 case D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE:
1269 if (rendering_mode == DWRITE_RENDERING_MODE_ALIASED)
1270 render_target->error.code = E_INVALIDARG;
1271 break;
1272 default:
1276 if (FAILED(render_target->error.code))
1277 return;
1279 rendering_mode = DWRITE_RENDERING_MODE_DEFAULT;
1280 switch (render_target->drawing_state.textAntialiasMode)
1282 case D2D1_TEXT_ANTIALIAS_MODE_DEFAULT:
1283 if (IDWriteRenderingParams_GetClearTypeLevel(rendering_params) > 0.0f)
1284 antialias_mode = DWRITE_TEXT_ANTIALIAS_MODE_CLEARTYPE;
1285 break;
1286 case D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE:
1287 antialias_mode = DWRITE_TEXT_ANTIALIAS_MODE_CLEARTYPE;
1288 break;
1289 case D2D1_TEXT_ANTIALIAS_MODE_ALIASED:
1290 rendering_mode = DWRITE_RENDERING_MODE_ALIASED;
1291 break;
1292 default:
1296 ppd = max(render_target->desc.dpiX, render_target->desc.dpiY) / 96.0f;
1297 if (rendering_mode == DWRITE_RENDERING_MODE_DEFAULT)
1299 if (FAILED(hr = IDWriteFontFace_GetRecommendedRenderingMode(glyph_run->fontFace, glyph_run->fontEmSize,
1300 ppd, measuring_mode, rendering_params, &rendering_mode)))
1302 ERR("Failed to get recommended rendering mode, hr %#x.\n", hr);
1303 rendering_mode = DWRITE_RENDERING_MODE_OUTLINE;
1307 if (rendering_mode == DWRITE_RENDERING_MODE_OUTLINE)
1308 d2d_rt_draw_glyph_run_outline(render_target, baseline_origin, glyph_run, brush);
1309 else
1310 d2d_rt_draw_glyph_run_bitmap(render_target, baseline_origin, glyph_run, brush,
1311 ppd, rendering_mode, measuring_mode, antialias_mode);
1314 static void STDMETHODCALLTYPE d2d_d3d_render_target_SetTransform(ID2D1RenderTarget *iface,
1315 const D2D1_MATRIX_3X2_F *transform)
1317 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1319 TRACE("iface %p, transform %p.\n", iface, transform);
1321 render_target->drawing_state.transform = *transform;
1324 static void STDMETHODCALLTYPE d2d_d3d_render_target_GetTransform(ID2D1RenderTarget *iface,
1325 D2D1_MATRIX_3X2_F *transform)
1327 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1329 TRACE("iface %p, transform %p.\n", iface, transform);
1331 *transform = render_target->drawing_state.transform;
1334 static void STDMETHODCALLTYPE d2d_d3d_render_target_SetAntialiasMode(ID2D1RenderTarget *iface,
1335 D2D1_ANTIALIAS_MODE antialias_mode)
1337 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1339 TRACE("iface %p, antialias_mode %#x stub!\n", iface, antialias_mode);
1341 render_target->drawing_state.antialiasMode = antialias_mode;
1344 static D2D1_ANTIALIAS_MODE STDMETHODCALLTYPE d2d_d3d_render_target_GetAntialiasMode(ID2D1RenderTarget *iface)
1346 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1348 TRACE("iface %p.\n", iface);
1350 return render_target->drawing_state.antialiasMode;
1353 static void STDMETHODCALLTYPE d2d_d3d_render_target_SetTextAntialiasMode(ID2D1RenderTarget *iface,
1354 D2D1_TEXT_ANTIALIAS_MODE antialias_mode)
1356 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1358 TRACE("iface %p, antialias_mode %#x.\n", iface, antialias_mode);
1360 render_target->drawing_state.textAntialiasMode = antialias_mode;
1363 static D2D1_TEXT_ANTIALIAS_MODE STDMETHODCALLTYPE d2d_d3d_render_target_GetTextAntialiasMode(ID2D1RenderTarget *iface)
1365 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1367 TRACE("iface %p.\n", iface);
1369 return render_target->drawing_state.textAntialiasMode;
1372 static void STDMETHODCALLTYPE d2d_d3d_render_target_SetTextRenderingParams(ID2D1RenderTarget *iface,
1373 IDWriteRenderingParams *text_rendering_params)
1375 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1377 TRACE("iface %p, text_rendering_params %p.\n", iface, text_rendering_params);
1379 if (text_rendering_params)
1380 IDWriteRenderingParams_AddRef(text_rendering_params);
1381 if (render_target->text_rendering_params)
1382 IDWriteRenderingParams_Release(render_target->text_rendering_params);
1383 render_target->text_rendering_params = text_rendering_params;
1386 static void STDMETHODCALLTYPE d2d_d3d_render_target_GetTextRenderingParams(ID2D1RenderTarget *iface,
1387 IDWriteRenderingParams **text_rendering_params)
1389 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1391 TRACE("iface %p, text_rendering_params %p.\n", iface, text_rendering_params);
1393 if ((*text_rendering_params = render_target->text_rendering_params))
1394 IDWriteRenderingParams_AddRef(*text_rendering_params);
1397 static void STDMETHODCALLTYPE d2d_d3d_render_target_SetTags(ID2D1RenderTarget *iface, D2D1_TAG tag1, D2D1_TAG tag2)
1399 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1401 TRACE("iface %p, tag1 %s, tag2 %s.\n", iface, wine_dbgstr_longlong(tag1), wine_dbgstr_longlong(tag2));
1403 render_target->drawing_state.tag1 = tag1;
1404 render_target->drawing_state.tag2 = tag2;
1407 static void STDMETHODCALLTYPE d2d_d3d_render_target_GetTags(ID2D1RenderTarget *iface, D2D1_TAG *tag1, D2D1_TAG *tag2)
1409 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1411 TRACE("iface %p, tag1 %p, tag2 %p.\n", iface, tag1, tag2);
1413 *tag1 = render_target->drawing_state.tag1;
1414 *tag2 = render_target->drawing_state.tag2;
1417 static void STDMETHODCALLTYPE d2d_d3d_render_target_PushLayer(ID2D1RenderTarget *iface,
1418 const D2D1_LAYER_PARAMETERS *layer_parameters, ID2D1Layer *layer)
1420 FIXME("iface %p, layer_parameters %p, layer %p stub!\n", iface, layer_parameters, layer);
1423 static void STDMETHODCALLTYPE d2d_d3d_render_target_PopLayer(ID2D1RenderTarget *iface)
1425 FIXME("iface %p stub!\n", iface);
1428 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_Flush(ID2D1RenderTarget *iface, D2D1_TAG *tag1, D2D1_TAG *tag2)
1430 FIXME("iface %p, tag1 %p, tag2 %p stub!\n", iface, tag1, tag2);
1432 return E_NOTIMPL;
1435 static void STDMETHODCALLTYPE d2d_d3d_render_target_SaveDrawingState(ID2D1RenderTarget *iface,
1436 ID2D1DrawingStateBlock *state_block)
1438 struct d2d_state_block *state_block_impl = unsafe_impl_from_ID2D1DrawingStateBlock(state_block);
1439 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1441 TRACE("iface %p, state_block %p.\n", iface, state_block);
1443 state_block_impl->drawing_state = render_target->drawing_state;
1444 if (render_target->text_rendering_params)
1445 IDWriteRenderingParams_AddRef(render_target->text_rendering_params);
1446 if (state_block_impl->text_rendering_params)
1447 IDWriteRenderingParams_Release(state_block_impl->text_rendering_params);
1448 state_block_impl->text_rendering_params = render_target->text_rendering_params;
1451 static void STDMETHODCALLTYPE d2d_d3d_render_target_RestoreDrawingState(ID2D1RenderTarget *iface,
1452 ID2D1DrawingStateBlock *state_block)
1454 struct d2d_state_block *state_block_impl = unsafe_impl_from_ID2D1DrawingStateBlock(state_block);
1455 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1457 TRACE("iface %p, state_block %p.\n", iface, state_block);
1459 render_target->drawing_state = state_block_impl->drawing_state;
1460 if (state_block_impl->text_rendering_params)
1461 IDWriteRenderingParams_AddRef(state_block_impl->text_rendering_params);
1462 if (render_target->text_rendering_params)
1463 IDWriteRenderingParams_Release(render_target->text_rendering_params);
1464 render_target->text_rendering_params = state_block_impl->text_rendering_params;
1467 static void STDMETHODCALLTYPE d2d_d3d_render_target_PushAxisAlignedClip(ID2D1RenderTarget *iface,
1468 const D2D1_RECT_F *clip_rect, D2D1_ANTIALIAS_MODE antialias_mode)
1470 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1471 D2D1_RECT_F transformed_rect;
1472 float x_scale, y_scale;
1473 D2D1_POINT_2F point;
1475 TRACE("iface %p, clip_rect %s, antialias_mode %#x.\n", iface, debug_d2d_rect_f(clip_rect), antialias_mode);
1477 if (antialias_mode != D2D1_ANTIALIAS_MODE_ALIASED)
1478 FIXME("Ignoring antialias_mode %#x.\n", antialias_mode);
1480 x_scale = render_target->desc.dpiX / 96.0f;
1481 y_scale = render_target->desc.dpiY / 96.0f;
1482 d2d_point_transform(&point, &render_target->drawing_state.transform,
1483 clip_rect->left * x_scale, clip_rect->top * y_scale);
1484 d2d_rect_set(&transformed_rect, point.x, point.y, point.x, point.y);
1485 d2d_point_transform(&point, &render_target->drawing_state.transform,
1486 clip_rect->left * x_scale, clip_rect->bottom * y_scale);
1487 d2d_rect_expand(&transformed_rect, &point);
1488 d2d_point_transform(&point, &render_target->drawing_state.transform,
1489 clip_rect->right * x_scale, clip_rect->top * y_scale);
1490 d2d_rect_expand(&transformed_rect, &point);
1491 d2d_point_transform(&point, &render_target->drawing_state.transform,
1492 clip_rect->right * x_scale, clip_rect->bottom * y_scale);
1493 d2d_rect_expand(&transformed_rect, &point);
1495 if (!d2d_clip_stack_push(&render_target->clip_stack, &transformed_rect))
1496 WARN("Failed to push clip rect.\n");
1499 static void STDMETHODCALLTYPE d2d_d3d_render_target_PopAxisAlignedClip(ID2D1RenderTarget *iface)
1501 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1503 TRACE("iface %p.\n", iface);
1505 d2d_clip_stack_pop(&render_target->clip_stack);
1508 static void STDMETHODCALLTYPE d2d_d3d_render_target_Clear(ID2D1RenderTarget *iface, const D2D1_COLOR_F *colour)
1510 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1511 D3D10_SUBRESOURCE_DATA buffer_data;
1512 struct d2d_ps_cb ps_cb_data = {0};
1513 D3D10_BUFFER_DESC buffer_desc;
1514 ID3D10Buffer *vs_cb, *ps_cb;
1515 D2D1_COLOR_F *c;
1516 HRESULT hr;
1518 static const struct
1520 struct
1522 float _11, _21, _31, pad0;
1523 float _12, _22, _32, pad1;
1524 } transform_geometry;
1525 struct d2d_vec4 transform_rtx;
1526 struct d2d_vec4 transform_rty;
1528 vs_cb_data =
1530 {1.0f, 0.0f, 0.0f, 0.0f,
1531 0.0f, 1.0f, 0.0f, 0.0f},
1532 {1.0f, 0.0f, 1.0f, 1.0f},
1533 {0.0f, 1.0f, 1.0f, -1.0f},
1536 TRACE("iface %p, colour %p.\n", iface, colour);
1538 buffer_desc.ByteWidth = sizeof(vs_cb_data);
1539 buffer_desc.Usage = D3D10_USAGE_DEFAULT;
1540 buffer_desc.BindFlags = D3D10_BIND_CONSTANT_BUFFER;
1541 buffer_desc.CPUAccessFlags = 0;
1542 buffer_desc.MiscFlags = 0;
1544 buffer_data.pSysMem = &vs_cb_data;
1545 buffer_data.SysMemPitch = 0;
1546 buffer_data.SysMemSlicePitch = 0;
1548 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device, &buffer_desc, &buffer_data, &vs_cb)))
1550 WARN("Failed to create constant buffer, hr %#x.\n", hr);
1551 return;
1554 ps_cb_data.outline = FALSE;
1555 ps_cb_data.colour_brush.type = D2D_BRUSH_TYPE_SOLID;
1556 ps_cb_data.colour_brush.opacity = 1.0f;
1557 c = &ps_cb_data.colour_brush.u.solid.colour;
1558 if (colour)
1559 *c = *colour;
1560 if (render_target->desc.pixelFormat.alphaMode == D2D1_ALPHA_MODE_IGNORE)
1561 c->a = 1.0f;
1562 c->r *= c->a;
1563 c->g *= c->a;
1564 c->b *= c->a;
1566 ps_cb_data.opacity_brush.type = D2D_BRUSH_TYPE_COUNT;
1568 buffer_desc.ByteWidth = sizeof(ps_cb_data);
1569 buffer_data.pSysMem = &ps_cb_data;
1571 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device, &buffer_desc, &buffer_data, &ps_cb)))
1573 WARN("Failed to create constant buffer, hr %#x.\n", hr);
1574 ID3D10Buffer_Release(vs_cb);
1575 return;
1578 d2d_rt_draw(render_target, D2D_SHAPE_TYPE_TRIANGLE, render_target->ib, 6,
1579 render_target->vb, render_target->vb_stride, vs_cb, ps_cb, NULL, NULL);
1581 ID3D10Buffer_Release(ps_cb);
1582 ID3D10Buffer_Release(vs_cb);
1585 static void STDMETHODCALLTYPE d2d_d3d_render_target_BeginDraw(ID2D1RenderTarget *iface)
1587 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1589 TRACE("iface %p.\n", iface);
1591 memset(&render_target->error, 0, sizeof(render_target->error));
1594 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_EndDraw(ID2D1RenderTarget *iface,
1595 D2D1_TAG *tag1, D2D1_TAG *tag2)
1597 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1599 TRACE("iface %p, tag1 %p, tag2 %p.\n", iface, tag1, tag2);
1601 if (tag1)
1602 *tag1 = render_target->error.tag1;
1603 if (tag2)
1604 *tag2 = render_target->error.tag2;
1606 return render_target->error.code;
1609 static D2D1_PIXEL_FORMAT * STDMETHODCALLTYPE d2d_d3d_render_target_GetPixelFormat(ID2D1RenderTarget *iface,
1610 D2D1_PIXEL_FORMAT *format)
1612 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1614 TRACE("iface %p, format %p.\n", iface, format);
1616 *format = render_target->desc.pixelFormat;
1617 return format;
1620 static void STDMETHODCALLTYPE d2d_d3d_render_target_SetDpi(ID2D1RenderTarget *iface, float dpi_x, float dpi_y)
1622 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1624 TRACE("iface %p, dpi_x %.8e, dpi_y %.8e.\n", iface, dpi_x, dpi_y);
1626 if (dpi_x == 0.0f && dpi_y == 0.0f)
1628 dpi_x = 96.0f;
1629 dpi_y = 96.0f;
1631 else if (dpi_x <= 0.0f || dpi_y <= 0.0f)
1632 return;
1634 render_target->desc.dpiX = dpi_x;
1635 render_target->desc.dpiY = dpi_y;
1638 static void STDMETHODCALLTYPE d2d_d3d_render_target_GetDpi(ID2D1RenderTarget *iface, float *dpi_x, float *dpi_y)
1640 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1642 TRACE("iface %p, dpi_x %p, dpi_y %p.\n", iface, dpi_x, dpi_y);
1644 *dpi_x = render_target->desc.dpiX;
1645 *dpi_y = render_target->desc.dpiY;
1648 static D2D1_SIZE_F * STDMETHODCALLTYPE d2d_d3d_render_target_GetSize(ID2D1RenderTarget *iface, D2D1_SIZE_F *size)
1650 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1652 TRACE("iface %p, size %p.\n", iface, size);
1654 size->width = render_target->pixel_size.width / (render_target->desc.dpiX / 96.0f);
1655 size->height = render_target->pixel_size.height / (render_target->desc.dpiY / 96.0f);
1656 return size;
1659 static D2D1_SIZE_U * STDMETHODCALLTYPE d2d_d3d_render_target_GetPixelSize(ID2D1RenderTarget *iface,
1660 D2D1_SIZE_U *pixel_size)
1662 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1664 TRACE("iface %p, pixel_size %p.\n", iface, pixel_size);
1666 *pixel_size = render_target->pixel_size;
1667 return pixel_size;
1670 static UINT32 STDMETHODCALLTYPE d2d_d3d_render_target_GetMaximumBitmapSize(ID2D1RenderTarget *iface)
1672 FIXME("iface %p stub!\n", iface);
1674 return 0;
1677 static BOOL STDMETHODCALLTYPE d2d_d3d_render_target_IsSupported(ID2D1RenderTarget *iface,
1678 const D2D1_RENDER_TARGET_PROPERTIES *desc)
1680 FIXME("iface %p, desc %p stub!\n", iface, desc);
1682 return FALSE;
1685 static const struct ID2D1RenderTargetVtbl d2d_d3d_render_target_vtbl =
1687 d2d_d3d_render_target_QueryInterface,
1688 d2d_d3d_render_target_AddRef,
1689 d2d_d3d_render_target_Release,
1690 d2d_d3d_render_target_GetFactory,
1691 d2d_d3d_render_target_CreateBitmap,
1692 d2d_d3d_render_target_CreateBitmapFromWicBitmap,
1693 d2d_d3d_render_target_CreateSharedBitmap,
1694 d2d_d3d_render_target_CreateBitmapBrush,
1695 d2d_d3d_render_target_CreateSolidColorBrush,
1696 d2d_d3d_render_target_CreateGradientStopCollection,
1697 d2d_d3d_render_target_CreateLinearGradientBrush,
1698 d2d_d3d_render_target_CreateRadialGradientBrush,
1699 d2d_d3d_render_target_CreateCompatibleRenderTarget,
1700 d2d_d3d_render_target_CreateLayer,
1701 d2d_d3d_render_target_CreateMesh,
1702 d2d_d3d_render_target_DrawLine,
1703 d2d_d3d_render_target_DrawRectangle,
1704 d2d_d3d_render_target_FillRectangle,
1705 d2d_d3d_render_target_DrawRoundedRectangle,
1706 d2d_d3d_render_target_FillRoundedRectangle,
1707 d2d_d3d_render_target_DrawEllipse,
1708 d2d_d3d_render_target_FillEllipse,
1709 d2d_d3d_render_target_DrawGeometry,
1710 d2d_d3d_render_target_FillGeometry,
1711 d2d_d3d_render_target_FillMesh,
1712 d2d_d3d_render_target_FillOpacityMask,
1713 d2d_d3d_render_target_DrawBitmap,
1714 d2d_d3d_render_target_DrawText,
1715 d2d_d3d_render_target_DrawTextLayout,
1716 d2d_d3d_render_target_DrawGlyphRun,
1717 d2d_d3d_render_target_SetTransform,
1718 d2d_d3d_render_target_GetTransform,
1719 d2d_d3d_render_target_SetAntialiasMode,
1720 d2d_d3d_render_target_GetAntialiasMode,
1721 d2d_d3d_render_target_SetTextAntialiasMode,
1722 d2d_d3d_render_target_GetTextAntialiasMode,
1723 d2d_d3d_render_target_SetTextRenderingParams,
1724 d2d_d3d_render_target_GetTextRenderingParams,
1725 d2d_d3d_render_target_SetTags,
1726 d2d_d3d_render_target_GetTags,
1727 d2d_d3d_render_target_PushLayer,
1728 d2d_d3d_render_target_PopLayer,
1729 d2d_d3d_render_target_Flush,
1730 d2d_d3d_render_target_SaveDrawingState,
1731 d2d_d3d_render_target_RestoreDrawingState,
1732 d2d_d3d_render_target_PushAxisAlignedClip,
1733 d2d_d3d_render_target_PopAxisAlignedClip,
1734 d2d_d3d_render_target_Clear,
1735 d2d_d3d_render_target_BeginDraw,
1736 d2d_d3d_render_target_EndDraw,
1737 d2d_d3d_render_target_GetPixelFormat,
1738 d2d_d3d_render_target_SetDpi,
1739 d2d_d3d_render_target_GetDpi,
1740 d2d_d3d_render_target_GetSize,
1741 d2d_d3d_render_target_GetPixelSize,
1742 d2d_d3d_render_target_GetMaximumBitmapSize,
1743 d2d_d3d_render_target_IsSupported,
1746 static inline struct d2d_d3d_render_target *impl_from_IDWriteTextRenderer(IDWriteTextRenderer *iface)
1748 return CONTAINING_RECORD(iface, struct d2d_d3d_render_target, IDWriteTextRenderer_iface);
1751 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_QueryInterface(IDWriteTextRenderer *iface, REFIID iid, void **out)
1753 TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
1755 if (IsEqualGUID(iid, &IID_IDWriteTextRenderer)
1756 || IsEqualGUID(iid, &IID_IDWritePixelSnapping)
1757 || IsEqualGUID(iid, &IID_IUnknown))
1759 IDWriteTextRenderer_AddRef(iface);
1760 *out = iface;
1761 return S_OK;
1764 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
1766 *out = NULL;
1767 return E_NOINTERFACE;
1770 static ULONG STDMETHODCALLTYPE d2d_text_renderer_AddRef(IDWriteTextRenderer *iface)
1772 struct d2d_d3d_render_target *render_target = impl_from_IDWriteTextRenderer(iface);
1774 TRACE("iface %p.\n", iface);
1776 return d2d_d3d_render_target_AddRef(&render_target->ID2D1RenderTarget_iface);
1779 static ULONG STDMETHODCALLTYPE d2d_text_renderer_Release(IDWriteTextRenderer *iface)
1781 struct d2d_d3d_render_target *render_target = impl_from_IDWriteTextRenderer(iface);
1783 TRACE("iface %p.\n", iface);
1785 return d2d_d3d_render_target_Release(&render_target->ID2D1RenderTarget_iface);
1788 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_IsPixelSnappingDisabled(IDWriteTextRenderer *iface,
1789 void *ctx, BOOL *disabled)
1791 struct d2d_draw_text_layout_ctx *context = ctx;
1793 TRACE("iface %p, ctx %p, disabled %p.\n", iface, ctx, disabled);
1795 *disabled = context->options & D2D1_DRAW_TEXT_OPTIONS_NO_SNAP;
1797 return S_OK;
1800 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_GetCurrentTransform(IDWriteTextRenderer *iface,
1801 void *ctx, DWRITE_MATRIX *transform)
1803 struct d2d_d3d_render_target *render_target = impl_from_IDWriteTextRenderer(iface);
1805 TRACE("iface %p, ctx %p, transform %p.\n", iface, ctx, transform);
1807 ID2D1RenderTarget_GetTransform(&render_target->ID2D1RenderTarget_iface, (D2D1_MATRIX_3X2_F *)transform);
1809 return S_OK;
1812 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_GetPixelsPerDip(IDWriteTextRenderer *iface, void *ctx, float *ppd)
1814 struct d2d_d3d_render_target *render_target = impl_from_IDWriteTextRenderer(iface);
1816 TRACE("iface %p, ctx %p, ppd %p.\n", iface, ctx, ppd);
1818 *ppd = render_target->desc.dpiY / 96.0f;
1820 return S_OK;
1823 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_DrawGlyphRun(IDWriteTextRenderer *iface, void *ctx,
1824 float baseline_origin_x, float baseline_origin_y, DWRITE_MEASURING_MODE measuring_mode,
1825 const DWRITE_GLYPH_RUN *glyph_run, const DWRITE_GLYPH_RUN_DESCRIPTION *desc, IUnknown *effect)
1827 struct d2d_d3d_render_target *render_target = impl_from_IDWriteTextRenderer(iface);
1828 D2D1_POINT_2F baseline_origin = {baseline_origin_x, baseline_origin_y};
1829 struct d2d_draw_text_layout_ctx *context = ctx;
1830 BOOL color_font = FALSE;
1831 ID2D1Brush *brush;
1833 TRACE("iface %p, ctx %p, baseline_origin_x %.8e, baseline_origin_y %.8e, "
1834 "measuring_mode %#x, glyph_run %p, desc %p, effect %p.\n",
1835 iface, ctx, baseline_origin_x, baseline_origin_y,
1836 measuring_mode, glyph_run, desc, effect);
1838 if (desc)
1839 WARN("Ignoring glyph run description %p.\n", desc);
1840 if (context->options & ~(D2D1_DRAW_TEXT_OPTIONS_NO_SNAP | D2D1_DRAW_TEXT_OPTIONS_ENABLE_COLOR_FONT))
1841 FIXME("Ignoring options %#x.\n", context->options);
1843 brush = d2d_draw_get_text_brush(context, effect);
1845 TRACE("%s\n", debugstr_wn(desc->string, desc->stringLength));
1847 if (context->options & D2D1_DRAW_TEXT_OPTIONS_ENABLE_COLOR_FONT)
1849 IDWriteFontFace2 *fontface;
1851 if (SUCCEEDED(IDWriteFontFace_QueryInterface(glyph_run->fontFace,
1852 &IID_IDWriteFontFace2, (void **)&fontface)))
1854 color_font = IDWriteFontFace2_IsColorFont(fontface);
1855 IDWriteFontFace2_Release(fontface);
1859 if (color_font)
1861 IDWriteColorGlyphRunEnumerator *layers;
1862 IDWriteFactory2 *dwrite_factory;
1863 HRESULT hr;
1865 if (FAILED(hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, &IID_IDWriteFactory2,
1866 (IUnknown **)&dwrite_factory)))
1868 ERR("Failed to create dwrite factory, hr %#x.\n", hr);
1869 ID2D1Brush_Release(brush);
1870 return hr;
1873 hr = IDWriteFactory2_TranslateColorGlyphRun(dwrite_factory, baseline_origin_x, baseline_origin_y,
1874 glyph_run, desc, measuring_mode, (DWRITE_MATRIX *)&render_target->drawing_state.transform, 0, &layers);
1875 IDWriteFactory2_Release(dwrite_factory);
1876 if (FAILED(hr))
1878 ERR("Failed to create color glyph run enumerator, hr %#x.\n", hr);
1879 ID2D1Brush_Release(brush);
1880 return hr;
1883 for (;;)
1885 const DWRITE_COLOR_GLYPH_RUN *color_run;
1886 ID2D1Brush *color_brush;
1887 D2D1_POINT_2F origin;
1888 BOOL has_run = FALSE;
1890 if (FAILED(hr = IDWriteColorGlyphRunEnumerator_MoveNext(layers, &has_run)))
1892 ERR("Failed to switch color glyph layer, hr %#x.\n", hr);
1893 break;
1896 if (!has_run)
1897 break;
1899 if (FAILED(hr = IDWriteColorGlyphRunEnumerator_GetCurrentRun(layers, &color_run)))
1901 ERR("Failed to get current color run, hr %#x.\n", hr);
1902 break;
1905 if (color_run->paletteIndex == 0xffff)
1906 color_brush = brush;
1907 else
1909 if (FAILED(hr = ID2D1RenderTarget_CreateSolidColorBrush(&render_target->ID2D1RenderTarget_iface,
1910 &color_run->runColor, NULL, (ID2D1SolidColorBrush **)&color_brush)))
1912 ERR("Failed to create solid color brush, hr %#x.\n", hr);
1913 break;
1917 origin.x = color_run->baselineOriginX;
1918 origin.y = color_run->baselineOriginY;
1919 ID2D1RenderTarget_DrawGlyphRun(&render_target->ID2D1RenderTarget_iface,
1920 origin, &color_run->glyphRun, color_brush, measuring_mode);
1922 if (color_brush != brush)
1923 ID2D1Brush_Release(color_brush);
1926 IDWriteColorGlyphRunEnumerator_Release(layers);
1928 else
1929 ID2D1RenderTarget_DrawGlyphRun(&render_target->ID2D1RenderTarget_iface,
1930 baseline_origin, glyph_run, brush, measuring_mode);
1932 ID2D1Brush_Release(brush);
1934 return S_OK;
1937 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_DrawUnderline(IDWriteTextRenderer *iface, void *ctx,
1938 float baseline_origin_x, float baseline_origin_y, const DWRITE_UNDERLINE *underline, IUnknown *effect)
1940 struct d2d_d3d_render_target *render_target = impl_from_IDWriteTextRenderer(iface);
1941 const D2D1_MATRIX_3X2_F *m = &render_target->drawing_state.transform;
1942 struct d2d_draw_text_layout_ctx *context = ctx;
1943 D2D1_ANTIALIAS_MODE prev_antialias_mode;
1944 D2D1_POINT_2F start, end;
1945 ID2D1Brush *brush;
1946 float thickness;
1948 TRACE("iface %p, ctx %p, baseline_origin_x %.8e, baseline_origin_y %.8e, underline %p, effect %p\n",
1949 iface, ctx, baseline_origin_x, baseline_origin_y, underline, effect);
1951 /* minimal thickness in DIPs that will result in at least 1 pixel thick line */
1952 thickness = max(96.0f / (render_target->desc.dpiY * sqrtf(m->_21 * m->_21 + m->_22 * m->_22)),
1953 underline->thickness);
1955 brush = d2d_draw_get_text_brush(context, effect);
1957 start.x = baseline_origin_x;
1958 start.y = baseline_origin_y + underline->offset + thickness / 2.0f;
1959 end.x = start.x + underline->width;
1960 end.y = start.y;
1961 prev_antialias_mode = d2d_d3d_render_target_set_aa_mode_from_text_aa_mode(render_target);
1962 d2d_d3d_render_target_DrawLine(&render_target->ID2D1RenderTarget_iface, start, end, brush, thickness, NULL);
1963 render_target->drawing_state.antialiasMode = prev_antialias_mode;
1965 ID2D1Brush_Release(brush);
1967 return S_OK;
1970 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_DrawStrikethrough(IDWriteTextRenderer *iface, void *ctx,
1971 float baseline_origin_x, float baseline_origin_y, const DWRITE_STRIKETHROUGH *strikethrough, IUnknown *effect)
1973 struct d2d_d3d_render_target *render_target = impl_from_IDWriteTextRenderer(iface);
1974 const D2D1_MATRIX_3X2_F *m = &render_target->drawing_state.transform;
1975 struct d2d_draw_text_layout_ctx *context = ctx;
1976 D2D1_ANTIALIAS_MODE prev_antialias_mode;
1977 D2D1_POINT_2F start, end;
1978 ID2D1Brush *brush;
1979 float thickness;
1981 TRACE("iface %p, ctx %p, baseline_origin_x %.8e, baseline_origin_y %.8e, strikethrough %p, effect %p.\n",
1982 iface, ctx, baseline_origin_x, baseline_origin_y, strikethrough, effect);
1984 /* minimal thickness in DIPs that will result in at least 1 pixel thick line */
1985 thickness = max(96.0f / (render_target->desc.dpiY * sqrtf(m->_21 * m->_21 + m->_22 * m->_22)),
1986 strikethrough->thickness);
1988 brush = d2d_draw_get_text_brush(context, effect);
1990 start.x = baseline_origin_x;
1991 start.y = baseline_origin_y + strikethrough->offset + thickness / 2.0f;
1992 end.x = start.x + strikethrough->width;
1993 end.y = start.y;
1994 prev_antialias_mode = d2d_d3d_render_target_set_aa_mode_from_text_aa_mode(render_target);
1995 d2d_d3d_render_target_DrawLine(&render_target->ID2D1RenderTarget_iface, start, end, brush, thickness, NULL);
1996 render_target->drawing_state.antialiasMode = prev_antialias_mode;
1998 ID2D1Brush_Release(brush);
2000 return S_OK;
2003 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_DrawInlineObject(IDWriteTextRenderer *iface, void *ctx,
2004 float origin_x, float origin_y, IDWriteInlineObject *object, BOOL is_sideways, BOOL is_rtl, IUnknown *effect)
2006 struct d2d_draw_text_layout_ctx *context = ctx;
2007 ID2D1Brush *brush;
2008 HRESULT hr;
2010 TRACE("iface %p, ctx %p, origin_x %.8e, origin_y %.8e, object %p, is_sideways %#x, is_rtl %#x, effect %p.\n",
2011 iface, ctx, origin_x, origin_y, object, is_sideways, is_rtl, effect);
2013 /* Inline objects may not pass effects all the way down, when using layout object internally for example.
2014 This is how default trimming sign object in DirectWrite works - it does not use effect passed to Draw(),
2015 and resulting DrawGlyphRun() is always called with NULL effect, however original effect is used and correct
2016 brush is selected at Direct2D level. */
2017 brush = context->brush;
2018 context->brush = d2d_draw_get_text_brush(context, effect);
2020 hr = IDWriteInlineObject_Draw(object, ctx, iface, origin_x, origin_y, is_sideways, is_rtl, effect);
2022 ID2D1Brush_Release(context->brush);
2023 context->brush = brush;
2025 return hr;
2028 static const struct IDWriteTextRendererVtbl d2d_text_renderer_vtbl =
2030 d2d_text_renderer_QueryInterface,
2031 d2d_text_renderer_AddRef,
2032 d2d_text_renderer_Release,
2033 d2d_text_renderer_IsPixelSnappingDisabled,
2034 d2d_text_renderer_GetCurrentTransform,
2035 d2d_text_renderer_GetPixelsPerDip,
2036 d2d_text_renderer_DrawGlyphRun,
2037 d2d_text_renderer_DrawUnderline,
2038 d2d_text_renderer_DrawStrikethrough,
2039 d2d_text_renderer_DrawInlineObject,
2042 static inline struct d2d_d3d_render_target *impl_from_ID2D1GdiInteropRenderTarget(ID2D1GdiInteropRenderTarget *iface)
2044 return CONTAINING_RECORD(iface, struct d2d_d3d_render_target, ID2D1GdiInteropRenderTarget_iface);
2047 static HRESULT STDMETHODCALLTYPE d2d_gdi_interop_render_target_QueryInterface(ID2D1GdiInteropRenderTarget *iface,
2048 REFIID iid, void **out)
2050 struct d2d_d3d_render_target *render_target = impl_from_ID2D1GdiInteropRenderTarget(iface);
2052 TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
2054 return IUnknown_QueryInterface(render_target->outer_unknown, iid, out);
2057 static ULONG STDMETHODCALLTYPE d2d_gdi_interop_render_target_AddRef(ID2D1GdiInteropRenderTarget *iface)
2059 struct d2d_d3d_render_target *render_target = impl_from_ID2D1GdiInteropRenderTarget(iface);
2061 TRACE("iface %p.\n", iface);
2063 return IUnknown_AddRef(render_target->outer_unknown);
2066 static ULONG STDMETHODCALLTYPE d2d_gdi_interop_render_target_Release(ID2D1GdiInteropRenderTarget *iface)
2068 struct d2d_d3d_render_target *render_target = impl_from_ID2D1GdiInteropRenderTarget(iface);
2070 TRACE("iface %p.\n", iface);
2072 return IUnknown_Release(render_target->outer_unknown);
2075 static HRESULT d2d_d3d_render_target_get_surface(struct d2d_d3d_render_target *render_target, IDXGISurface1 **surface)
2077 ID3D10Resource *resource;
2078 HRESULT hr;
2080 ID3D10RenderTargetView_GetResource(render_target->view, &resource);
2081 hr = ID3D10Resource_QueryInterface(resource, &IID_IDXGISurface1, (void **)surface);
2082 ID3D10Resource_Release(resource);
2083 if (FAILED(hr))
2085 *surface = NULL;
2086 WARN("Failed to get DXGI surface, %#x.\n", hr);
2087 return hr;
2090 return hr;
2093 static HRESULT STDMETHODCALLTYPE d2d_gdi_interop_render_target_GetDC(ID2D1GdiInteropRenderTarget *iface,
2094 D2D1_DC_INITIALIZE_MODE mode, HDC *dc)
2096 struct d2d_d3d_render_target *render_target = impl_from_ID2D1GdiInteropRenderTarget(iface);
2097 IDXGISurface1 *surface;
2098 HRESULT hr;
2100 TRACE("iface %p, mode %d, dc %p.\n", iface, mode, dc);
2102 if (FAILED(hr = d2d_d3d_render_target_get_surface(render_target, &surface)))
2103 return hr;
2105 hr = IDXGISurface1_GetDC(surface, mode != D2D1_DC_INITIALIZE_MODE_COPY, dc);
2106 IDXGISurface1_Release(surface);
2108 return hr;
2111 static HRESULT STDMETHODCALLTYPE d2d_gdi_interop_render_target_ReleaseDC(ID2D1GdiInteropRenderTarget *iface,
2112 const RECT *update)
2114 struct d2d_d3d_render_target *render_target = impl_from_ID2D1GdiInteropRenderTarget(iface);
2115 IDXGISurface1 *surface;
2116 RECT update_rect;
2117 HRESULT hr;
2119 TRACE("iface %p, update rect %s.\n", iface, wine_dbgstr_rect(update));
2121 if (FAILED(hr = d2d_d3d_render_target_get_surface(render_target, &surface)))
2122 return hr;
2124 if (update)
2125 update_rect = *update;
2126 hr = IDXGISurface1_ReleaseDC(surface, update ? &update_rect : NULL);
2127 IDXGISurface1_Release(surface);
2129 return hr;
2132 static const struct ID2D1GdiInteropRenderTargetVtbl d2d_gdi_interop_render_target_vtbl =
2134 d2d_gdi_interop_render_target_QueryInterface,
2135 d2d_gdi_interop_render_target_AddRef,
2136 d2d_gdi_interop_render_target_Release,
2137 d2d_gdi_interop_render_target_GetDC,
2138 d2d_gdi_interop_render_target_ReleaseDC,
2141 static HRESULT d2d_d3d_render_target_init(struct d2d_d3d_render_target *render_target, ID2D1Factory *factory,
2142 IDXGISurface *surface, IUnknown *outer_unknown, const D2D1_RENDER_TARGET_PROPERTIES *desc)
2144 D3D10_SUBRESOURCE_DATA buffer_data;
2145 D3D10_STATE_BLOCK_MASK state_mask;
2146 DXGI_SURFACE_DESC surface_desc;
2147 IDWriteFactory *dwrite_factory;
2148 D3D10_RASTERIZER_DESC rs_desc;
2149 D3D10_BUFFER_DESC buffer_desc;
2150 D3D10_BLEND_DESC blend_desc;
2151 ID3D10Resource *resource;
2152 unsigned int i;
2153 HRESULT hr;
2155 static const D3D10_INPUT_ELEMENT_DESC il_desc_outline[] =
2157 {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0},
2158 {"PREV", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 8, D3D10_INPUT_PER_VERTEX_DATA, 0},
2159 {"NEXT", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 16, D3D10_INPUT_PER_VERTEX_DATA, 0},
2161 static const D3D10_INPUT_ELEMENT_DESC il_desc_bezier_outline[] =
2163 {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0},
2164 {"P", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 8, D3D10_INPUT_PER_VERTEX_DATA, 0},
2165 {"P", 1, DXGI_FORMAT_R32G32_FLOAT, 0, 16, D3D10_INPUT_PER_VERTEX_DATA, 0},
2166 {"P", 2, DXGI_FORMAT_R32G32_FLOAT, 0, 24, D3D10_INPUT_PER_VERTEX_DATA, 0},
2167 {"PREV", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 32, D3D10_INPUT_PER_VERTEX_DATA, 0},
2168 {"NEXT", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 40, D3D10_INPUT_PER_VERTEX_DATA, 0},
2170 static const D3D10_INPUT_ELEMENT_DESC il_desc_triangle[] =
2172 {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0},
2174 static const D3D10_INPUT_ELEMENT_DESC il_desc_bezier[] =
2176 {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0},
2177 {"TEXCOORD", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 8, D3D10_INPUT_PER_VERTEX_DATA, 0},
2179 static const DWORD vs_code_outline[] =
2181 #if 0
2182 float3x2 transform_geometry;
2183 float stroke_width;
2184 float4 transform_rtx;
2185 float4 transform_rty;
2187 struct output
2189 float2 p : WORLD_POSITION;
2190 float4 b : BEZIER;
2191 nointerpolation float2x2 stroke_transform : STROKE_TRANSFORM;
2192 float4 position : SV_POSITION;
2195 /* The lines PₚᵣₑᵥP₀ and P₀Pₙₑₓₜ, both offset by ±½w, intersect each other at:
2197 * Pᵢ = P₀ ± w · ½q⃑ᵢ.
2199 * Where:
2201 * q⃑ᵢ = q̂ₚᵣₑᵥ⊥ + tan(½θ) · -q̂ₚᵣₑᵥ
2202 * θ = ∠PₚᵣₑᵥP₀Pₙₑₓₜ
2203 * q⃑ₚᵣₑᵥ = P₀ - Pₚᵣₑᵥ */
2204 void main(float2 position : POSITION, float2 prev : PREV, float2 next : NEXT, out struct output o)
2206 float2 q_prev, q_next, v_p, q_i;
2207 float2x2 geom;
2208 float l;
2210 o.stroke_transform = float2x2(transform_rtx.xy, transform_rty.xy) * stroke_width * 0.5f;
2212 geom = float2x2(transform_geometry._11_21, transform_geometry._12_22);
2213 q_prev = normalize(mul(geom, prev));
2214 q_next = normalize(mul(geom, next));
2216 /* tan(½θ) = sin(θ) / (1 + cos(θ))
2217 * = (q̂ₚᵣₑᵥ⊥ · q̂ₙₑₓₜ) / (1 + (q̂ₚᵣₑᵥ · q̂ₙₑₓₜ)) */
2218 v_p = float2(-q_prev.y, q_prev.x);
2219 l = -dot(v_p, q_next) / (1.0f + dot(q_prev, q_next));
2220 q_i = l * q_prev + v_p;
2222 o.b = float4(0.0, 0.0, 0.0, 0.0);
2224 o.p = mul(float3(position, 1.0f), transform_geometry) + stroke_width * 0.5f * q_i;
2225 position = mul(float2x3(transform_rtx.xyz, transform_rty.xyz), float3(o.p, 1.0f))
2226 * float2(transform_rtx.w, transform_rty.w);
2227 o.position = float4(position + float2(-1.0f, 1.0f), 0.0f, 1.0f);
2229 #endif
2230 0x43425844, 0xfb16cd75, 0xf5ec3e80, 0xceacf250, 0x91d29d18, 0x00000001, 0x00000608, 0x00000003,
2231 0x0000002c, 0x00000098, 0x00000154, 0x4e475349, 0x00000064, 0x00000003, 0x00000008, 0x00000050,
2232 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000303, 0x00000059, 0x00000000, 0x00000000,
2233 0x00000003, 0x00000001, 0x00000303, 0x0000005e, 0x00000000, 0x00000000, 0x00000003, 0x00000002,
2234 0x00000303, 0x49534f50, 0x4e4f4954, 0x45525000, 0x454e0056, 0xab005458, 0x4e47534f, 0x000000b4,
2235 0x00000005, 0x00000008, 0x00000080, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000c03,
2236 0x0000008f, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x0000000f, 0x00000096, 0x00000000,
2237 0x00000000, 0x00000003, 0x00000002, 0x00000c03, 0x00000096, 0x00000001, 0x00000000, 0x00000003,
2238 0x00000003, 0x00000c03, 0x000000a7, 0x00000000, 0x00000001, 0x00000003, 0x00000004, 0x0000000f,
2239 0x4c524f57, 0x4f505f44, 0x49544953, 0x42004e4f, 0x45495a45, 0x54530052, 0x454b4f52, 0x4152545f,
2240 0x4f46534e, 0x53004d52, 0x4f505f56, 0x49544953, 0xab004e4f, 0x52444853, 0x000004ac, 0x00010040,
2241 0x0000012b, 0x04000059, 0x00208e46, 0x00000000, 0x00000004, 0x0300005f, 0x00101032, 0x00000000,
2242 0x0300005f, 0x00101032, 0x00000001, 0x0300005f, 0x00101032, 0x00000002, 0x03000065, 0x00102032,
2243 0x00000000, 0x03000065, 0x001020f2, 0x00000001, 0x03000065, 0x00102032, 0x00000002, 0x03000065,
2244 0x00102032, 0x00000003, 0x04000067, 0x001020f2, 0x00000004, 0x00000001, 0x02000068, 0x00000003,
2245 0x0800000f, 0x00100012, 0x00000000, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000002,
2246 0x0800000f, 0x00100022, 0x00000000, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000002,
2247 0x0700000f, 0x00100042, 0x00000000, 0x00100046, 0x00000000, 0x00100046, 0x00000000, 0x05000044,
2248 0x00100042, 0x00000000, 0x0010002a, 0x00000000, 0x07000038, 0x00100032, 0x00000000, 0x00100aa6,
2249 0x00000000, 0x00100046, 0x00000000, 0x0800000f, 0x00100012, 0x00000001, 0x00208046, 0x00000000,
2250 0x00000000, 0x00101046, 0x00000001, 0x0800000f, 0x00100022, 0x00000001, 0x00208046, 0x00000000,
2251 0x00000001, 0x00101046, 0x00000001, 0x0700000f, 0x00100042, 0x00000000, 0x00100046, 0x00000001,
2252 0x00100046, 0x00000001, 0x05000044, 0x00100042, 0x00000000, 0x0010002a, 0x00000000, 0x07000038,
2253 0x00100032, 0x00000001, 0x00100aa6, 0x00000000, 0x00100046, 0x00000001, 0x06000036, 0x001000c2,
2254 0x00000001, 0x80100556, 0x00000041, 0x00000001, 0x0700000f, 0x00100042, 0x00000000, 0x00100a26,
2255 0x00000001, 0x00100046, 0x00000000, 0x0700000f, 0x00100012, 0x00000000, 0x00100046, 0x00000001,
2256 0x00100046, 0x00000000, 0x07000000, 0x00100012, 0x00000000, 0x0010000a, 0x00000000, 0x00004001,
2257 0x3f800000, 0x0800000e, 0x00100012, 0x00000000, 0x8010002a, 0x00000041, 0x00000000, 0x0010000a,
2258 0x00000000, 0x09000032, 0x00100032, 0x00000000, 0x00100006, 0x00000000, 0x00100046, 0x00000001,
2259 0x00100f36, 0x00000001, 0x08000038, 0x00100042, 0x00000000, 0x0020803a, 0x00000000, 0x00000001,
2260 0x00004001, 0x3f000000, 0x05000036, 0x00100032, 0x00000001, 0x00101046, 0x00000000, 0x05000036,
2261 0x00100042, 0x00000001, 0x00004001, 0x3f800000, 0x08000010, 0x00100012, 0x00000002, 0x00100246,
2262 0x00000001, 0x00208246, 0x00000000, 0x00000000, 0x08000010, 0x00100022, 0x00000002, 0x00100246,
2263 0x00000001, 0x00208246, 0x00000000, 0x00000001, 0x09000032, 0x00100032, 0x00000000, 0x00100aa6,
2264 0x00000000, 0x00100046, 0x00000000, 0x00100046, 0x00000002, 0x05000036, 0x00102032, 0x00000000,
2265 0x00100046, 0x00000000, 0x08000036, 0x001020f2, 0x00000001, 0x00004002, 0x00000000, 0x00000000,
2266 0x00000000, 0x00000000, 0x06000036, 0x00100032, 0x00000001, 0x00208046, 0x00000000, 0x00000002,
2267 0x06000036, 0x001000c2, 0x00000001, 0x00208406, 0x00000000, 0x00000003, 0x08000038, 0x001000f2,
2268 0x00000001, 0x00100e46, 0x00000001, 0x00208ff6, 0x00000000, 0x00000001, 0x0a000038, 0x001000f2,
2269 0x00000001, 0x00100e46, 0x00000001, 0x00004002, 0x3f000000, 0x3f000000, 0x3f000000, 0x3f000000,
2270 0x05000036, 0x00102032, 0x00000002, 0x00100086, 0x00000001, 0x05000036, 0x00102032, 0x00000003,
2271 0x001005d6, 0x00000001, 0x05000036, 0x00100042, 0x00000000, 0x00004001, 0x3f800000, 0x08000010,
2272 0x00100082, 0x00000000, 0x00208246, 0x00000000, 0x00000002, 0x00100246, 0x00000000, 0x08000010,
2273 0x00100012, 0x00000000, 0x00208246, 0x00000000, 0x00000003, 0x00100246, 0x00000000, 0x08000038,
2274 0x00100022, 0x00000000, 0x0010000a, 0x00000000, 0x0020803a, 0x00000000, 0x00000003, 0x08000038,
2275 0x00100012, 0x00000000, 0x0010003a, 0x00000000, 0x0020803a, 0x00000000, 0x00000002, 0x0a000000,
2276 0x00102032, 0x00000004, 0x00100046, 0x00000000, 0x00004002, 0xbf800000, 0x3f800000, 0x00000000,
2277 0x00000000, 0x08000036, 0x001020c2, 0x00000004, 0x00004002, 0x00000000, 0x00000000, 0x00000000,
2278 0x3f800000, 0x0100003e,
2280 /* ⎡p0.x p0.y 1⎤
2281 * A = ⎢p1.x p1.y 1⎥
2282 * ⎣p2.x p2.y 1⎦
2284 * ⎡0 0⎤
2285 * B = ⎢½ 0⎥
2286 * ⎣1 1⎦
2288 * A' = ⎡p1.x-p0.x p1.y-p0.y⎤
2289 * ⎣p2.x-p0.x p2.y-p0.y⎦
2291 * B' = ⎡½ 0⎤
2292 * ⎣1 1⎦
2294 * A'T = B'
2295 * T = A'⁻¹B'
2297 static const DWORD vs_code_bezier_outline[] =
2299 #if 0
2300 float3x2 transform_geometry;
2301 float stroke_width;
2302 float4 transform_rtx;
2303 float4 transform_rty;
2305 struct output
2307 float2 p : WORLD_POSITION;
2308 float4 b : BEZIER;
2309 nointerpolation float2x2 stroke_transform : STROKE_TRANSFORM;
2310 float4 position : SV_POSITION;
2313 void main(float2 position : POSITION, float2 p0 : P0, float2 p1 : P1, float2 p2 : P2,
2314 float2 prev : PREV, float2 next : NEXT, out struct output o)
2316 float2 q_prev, q_next, v_p, q_i, p;
2317 float2x2 geom, rt;
2318 float l;
2320 geom = float2x2(transform_geometry._11_21, transform_geometry._12_22);
2321 rt = float2x2(transform_rtx.xy, transform_rty.xy);
2322 o.stroke_transform = rt * stroke_width * 0.5f;
2324 p = mul(geom, position);
2325 p0 = mul(geom, p0);
2326 p1 = mul(geom, p1);
2327 p2 = mul(geom, p2);
2329 p -= p0;
2330 p1 -= p0;
2331 p2 -= p0;
2333 q_prev = normalize(mul(geom, prev));
2334 q_next = normalize(mul(geom, next));
2336 v_p = float2(-q_prev.y, q_prev.x);
2337 l = -dot(v_p, q_next) / (1.0f + dot(q_prev, q_next));
2338 q_i = l * q_prev + v_p;
2339 p += stroke_width * q_i;
2341 v_p = mul(rt, p2);
2342 v_p = normalize(float2(-v_p.y, v_p.x));
2343 if (abs(dot(mul(rt, p1), v_p)) < 1.0f)
2345 o.b.xzw = float3(0.0f, 0.0f, 0.0f);
2346 o.b.y = dot(mul(rt, p), v_p);
2348 else
2350 o.b.zw = sign(dot(mul(rt, p1), v_p)) * v_p;
2351 v_p = -float2(-p.y, p.x) / dot(float2(-p1.y, p1.x), p2);
2352 o.b.x = dot(v_p, p1 - 0.5f * p2);
2353 o.b.y = dot(v_p, p1);
2356 o.p = mul(float3(position, 1.0f), transform_geometry) + stroke_width * q_i;
2357 position = mul(float2x3(transform_rtx.xyz, transform_rty.xyz), float3(o.p, 1.0f))
2358 * float2(transform_rtx.w, transform_rty.w);
2359 o.position = float4(position + float2(-1.0f, 1.0f), 0.0f, 1.0f);
2361 #endif
2362 0x43425844, 0x7ff88ce9, 0xd75cb064, 0x30396183, 0xca64489b, 0x00000001, 0x00000ae4, 0x00000003,
2363 0x0000002c, 0x000000e4, 0x000001a0, 0x4e475349, 0x000000b0, 0x00000006, 0x00000008, 0x00000098,
2364 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000303, 0x000000a1, 0x00000000, 0x00000000,
2365 0x00000003, 0x00000001, 0x00000303, 0x000000a1, 0x00000001, 0x00000000, 0x00000003, 0x00000002,
2366 0x00000303, 0x000000a1, 0x00000002, 0x00000000, 0x00000003, 0x00000003, 0x00000303, 0x000000a3,
2367 0x00000000, 0x00000000, 0x00000003, 0x00000004, 0x00000303, 0x000000a8, 0x00000000, 0x00000000,
2368 0x00000003, 0x00000005, 0x00000303, 0x49534f50, 0x4e4f4954, 0x50005000, 0x00564552, 0x5458454e,
2369 0xababab00, 0x4e47534f, 0x000000b4, 0x00000005, 0x00000008, 0x00000080, 0x00000000, 0x00000000,
2370 0x00000003, 0x00000000, 0x00000c03, 0x0000008f, 0x00000000, 0x00000000, 0x00000003, 0x00000001,
2371 0x0000000f, 0x00000096, 0x00000000, 0x00000000, 0x00000003, 0x00000002, 0x00000c03, 0x00000096,
2372 0x00000001, 0x00000000, 0x00000003, 0x00000003, 0x00000c03, 0x000000a7, 0x00000000, 0x00000001,
2373 0x00000003, 0x00000004, 0x0000000f, 0x4c524f57, 0x4f505f44, 0x49544953, 0x42004e4f, 0x45495a45,
2374 0x54530052, 0x454b4f52, 0x4152545f, 0x4f46534e, 0x53004d52, 0x4f505f56, 0x49544953, 0xab004e4f,
2375 0x52444853, 0x0000093c, 0x00010040, 0x0000024f, 0x04000059, 0x00208e46, 0x00000000, 0x00000004,
2376 0x0300005f, 0x00101032, 0x00000000, 0x0300005f, 0x00101032, 0x00000001, 0x0300005f, 0x00101032,
2377 0x00000002, 0x0300005f, 0x00101032, 0x00000003, 0x0300005f, 0x00101032, 0x00000004, 0x0300005f,
2378 0x00101032, 0x00000005, 0x03000065, 0x00102032, 0x00000000, 0x03000065, 0x001020f2, 0x00000001,
2379 0x03000065, 0x00102032, 0x00000002, 0x03000065, 0x00102032, 0x00000003, 0x04000067, 0x001020f2,
2380 0x00000004, 0x00000001, 0x02000068, 0x00000006, 0x0800000f, 0x00100012, 0x00000000, 0x00208046,
2381 0x00000000, 0x00000000, 0x00101046, 0x00000005, 0x0800000f, 0x00100022, 0x00000000, 0x00208046,
2382 0x00000000, 0x00000001, 0x00101046, 0x00000005, 0x0700000f, 0x00100042, 0x00000000, 0x00100046,
2383 0x00000000, 0x00100046, 0x00000000, 0x05000044, 0x00100042, 0x00000000, 0x0010002a, 0x00000000,
2384 0x07000038, 0x00100032, 0x00000000, 0x00100aa6, 0x00000000, 0x00100046, 0x00000000, 0x0800000f,
2385 0x00100012, 0x00000001, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000004, 0x0800000f,
2386 0x00100022, 0x00000001, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000004, 0x0700000f,
2387 0x00100042, 0x00000000, 0x00100046, 0x00000001, 0x00100046, 0x00000001, 0x05000044, 0x00100042,
2388 0x00000000, 0x0010002a, 0x00000000, 0x07000038, 0x00100032, 0x00000001, 0x00100aa6, 0x00000000,
2389 0x00100046, 0x00000001, 0x06000036, 0x001000c2, 0x00000001, 0x80100556, 0x00000041, 0x00000001,
2390 0x0700000f, 0x00100042, 0x00000000, 0x00100a26, 0x00000001, 0x00100046, 0x00000000, 0x0700000f,
2391 0x00100012, 0x00000000, 0x00100046, 0x00000001, 0x00100046, 0x00000000, 0x07000000, 0x00100012,
2392 0x00000000, 0x0010000a, 0x00000000, 0x00004001, 0x3f800000, 0x0800000e, 0x00100012, 0x00000000,
2393 0x8010002a, 0x00000041, 0x00000000, 0x0010000a, 0x00000000, 0x09000032, 0x00100032, 0x00000000,
2394 0x00100006, 0x00000000, 0x00100046, 0x00000001, 0x00100f36, 0x00000001, 0x05000036, 0x00100032,
2395 0x00000001, 0x00101046, 0x00000000, 0x05000036, 0x00100042, 0x00000001, 0x00004001, 0x3f800000,
2396 0x08000010, 0x00100012, 0x00000002, 0x00100246, 0x00000001, 0x00208246, 0x00000000, 0x00000000,
2397 0x08000010, 0x00100022, 0x00000002, 0x00100246, 0x00000001, 0x00208246, 0x00000000, 0x00000001,
2398 0x0a000032, 0x00100032, 0x00000001, 0x00208ff6, 0x00000000, 0x00000001, 0x00100046, 0x00000000,
2399 0x00100046, 0x00000002, 0x05000036, 0x00102032, 0x00000000, 0x00100046, 0x00000001, 0x0800000f,
2400 0x00100012, 0x00000002, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000000, 0x0800000f,
2401 0x00100022, 0x00000002, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000000, 0x0800000f,
2402 0x00100012, 0x00000003, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000001, 0x0800000f,
2403 0x00100022, 0x00000003, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000001, 0x08000000,
2404 0x001000c2, 0x00000000, 0x00100406, 0x00000002, 0x80100406, 0x00000041, 0x00000003, 0x0a000032,
2405 0x00100032, 0x00000000, 0x00208ff6, 0x00000000, 0x00000001, 0x00100046, 0x00000000, 0x00100ae6,
2406 0x00000000, 0x0800000f, 0x00100012, 0x00000002, 0x00208046, 0x00000000, 0x00000002, 0x00100046,
2407 0x00000000, 0x0800000f, 0x00100022, 0x00000002, 0x00208046, 0x00000000, 0x00000003, 0x00100046,
2408 0x00000000, 0x0800000f, 0x00100012, 0x00000004, 0x00208046, 0x00000000, 0x00000000, 0x00101046,
2409 0x00000003, 0x0800000f, 0x00100022, 0x00000004, 0x00208046, 0x00000000, 0x00000001, 0x00101046,
2410 0x00000003, 0x08000000, 0x001000c2, 0x00000002, 0x80100406, 0x00000041, 0x00000003, 0x00100406,
2411 0x00000004, 0x0800000f, 0x00100082, 0x00000000, 0x00208046, 0x00000000, 0x00000003, 0x00100ae6,
2412 0x00000002, 0x06000036, 0x00100042, 0x00000003, 0x8010003a, 0x00000041, 0x00000000, 0x0800000f,
2413 0x00100082, 0x00000003, 0x00208046, 0x00000000, 0x00000002, 0x00100ae6, 0x00000002, 0x0700000f,
2414 0x00100082, 0x00000000, 0x00100ae6, 0x00000003, 0x00100ae6, 0x00000003, 0x05000044, 0x00100082,
2415 0x00000000, 0x0010003a, 0x00000000, 0x07000038, 0x001000c2, 0x00000003, 0x00100ff6, 0x00000000,
2416 0x00100ea6, 0x00000003, 0x0700000f, 0x00100022, 0x00000004, 0x00100046, 0x00000002, 0x00100ae6,
2417 0x00000003, 0x06000036, 0x00100042, 0x00000000, 0x8010001a, 0x00000041, 0x00000000, 0x0800000f,
2418 0x00100012, 0x00000002, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000002, 0x0800000f,
2419 0x00100022, 0x00000002, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000002, 0x08000000,
2420 0x00100032, 0x00000005, 0x80100046, 0x00000041, 0x00000003, 0x00100046, 0x00000002, 0x06000036,
2421 0x00100042, 0x00000005, 0x8010001a, 0x00000041, 0x00000005, 0x0700000f, 0x00100022, 0x00000000,
2422 0x00100a26, 0x00000005, 0x00100ae6, 0x00000002, 0x0d000032, 0x00100032, 0x00000002, 0x80100ae6,
2423 0x00000041, 0x00000002, 0x00004002, 0x3f000000, 0x3f000000, 0x00000000, 0x00000000, 0x00100046,
2424 0x00000005, 0x0800000e, 0x00100032, 0x00000000, 0x80100a26, 0x00000041, 0x00000000, 0x00100556,
2425 0x00000000, 0x0700000f, 0x00100012, 0x00000002, 0x00100046, 0x00000000, 0x00100046, 0x00000002,
2426 0x0700000f, 0x00100022, 0x00000002, 0x00100046, 0x00000000, 0x00100046, 0x00000005, 0x0800000f,
2427 0x00100012, 0x00000000, 0x00208046, 0x00000000, 0x00000002, 0x00100046, 0x00000005, 0x0800000f,
2428 0x00100022, 0x00000000, 0x00208046, 0x00000000, 0x00000003, 0x00100046, 0x00000005, 0x0700000f,
2429 0x00100012, 0x00000000, 0x00100046, 0x00000000, 0x00100ae6, 0x00000003, 0x07000031, 0x00100022,
2430 0x00000000, 0x00004001, 0x00000000, 0x0010000a, 0x00000000, 0x07000031, 0x00100042, 0x00000000,
2431 0x0010000a, 0x00000000, 0x00004001, 0x00000000, 0x08000031, 0x00100012, 0x00000000, 0x8010000a,
2432 0x00000081, 0x00000000, 0x00004001, 0x3f800000, 0x0800001e, 0x00100022, 0x00000000, 0x8010001a,
2433 0x00000041, 0x00000000, 0x0010002a, 0x00000000, 0x0500002b, 0x00100022, 0x00000000, 0x0010001a,
2434 0x00000000, 0x07000038, 0x001000c2, 0x00000002, 0x00100ea6, 0x00000003, 0x00100556, 0x00000000,
2435 0x08000036, 0x001000d2, 0x00000004, 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
2436 0x09000037, 0x001020f2, 0x00000001, 0x00100006, 0x00000000, 0x00100e46, 0x00000004, 0x00100e46,
2437 0x00000002, 0x06000036, 0x00100032, 0x00000000, 0x00208046, 0x00000000, 0x00000002, 0x06000036,
2438 0x001000c2, 0x00000000, 0x00208406, 0x00000000, 0x00000003, 0x08000038, 0x001000f2, 0x00000000,
2439 0x00100e46, 0x00000000, 0x00208ff6, 0x00000000, 0x00000001, 0x0a000038, 0x001000f2, 0x00000000,
2440 0x00100e46, 0x00000000, 0x00004002, 0x3f000000, 0x3f000000, 0x3f000000, 0x3f000000, 0x05000036,
2441 0x00102032, 0x00000002, 0x00100086, 0x00000000, 0x05000036, 0x00102032, 0x00000003, 0x001005d6,
2442 0x00000000, 0x05000036, 0x00100042, 0x00000001, 0x00004001, 0x3f800000, 0x08000010, 0x00100012,
2443 0x00000000, 0x00208246, 0x00000000, 0x00000002, 0x00100246, 0x00000001, 0x08000010, 0x00100022,
2444 0x00000000, 0x00208246, 0x00000000, 0x00000003, 0x00100246, 0x00000001, 0x08000038, 0x00100022,
2445 0x00000001, 0x0010001a, 0x00000000, 0x0020803a, 0x00000000, 0x00000003, 0x08000038, 0x00100012,
2446 0x00000001, 0x0010000a, 0x00000000, 0x0020803a, 0x00000000, 0x00000002, 0x0a000000, 0x00102032,
2447 0x00000004, 0x00100046, 0x00000001, 0x00004002, 0xbf800000, 0x3f800000, 0x00000000, 0x00000000,
2448 0x08000036, 0x001020c2, 0x00000004, 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x3f800000,
2449 0x0100003e,
2451 static const DWORD vs_code_triangle[] =
2453 #if 0
2454 float3x2 transform_geometry;
2455 float4 transform_rtx;
2456 float4 transform_rty;
2458 struct output
2460 float2 p : WORLD_POSITION;
2461 float4 b : BEZIER;
2462 nointerpolation float2x2 stroke_transform : STROKE_TRANSFORM;
2463 float4 position : SV_POSITION;
2466 void main(float2 position : POSITION, out struct output o)
2468 o.p = mul(float3(position, 1.0f), transform_geometry);
2469 o.b = float4(1.0, 0.0, 1.0, 1.0);
2470 o.stroke_transform = float2x2(1.0, 0.0, 0.0, 1.0);
2471 position = mul(float2x3(transform_rtx.xyz, transform_rty.xyz), float3(o.p, 1.0f))
2472 * float2(transform_rtx.w, transform_rty.w);
2473 o.position = float4(position + float2(-1.0f, 1.0f), 0.0f, 1.0f);
2475 #endif
2476 0x43425844, 0xda43bf17, 0x06e6d155, 0xdbce2ae5, 0x8aed6fd8, 0x00000001, 0x0000034c, 0x00000003,
2477 0x0000002c, 0x00000060, 0x0000011c, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020,
2478 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000303, 0x49534f50, 0x4e4f4954, 0xababab00,
2479 0x4e47534f, 0x000000b4, 0x00000005, 0x00000008, 0x00000080, 0x00000000, 0x00000000, 0x00000003,
2480 0x00000000, 0x00000c03, 0x0000008f, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x0000000f,
2481 0x00000096, 0x00000000, 0x00000000, 0x00000003, 0x00000002, 0x00000c03, 0x00000096, 0x00000001,
2482 0x00000000, 0x00000003, 0x00000003, 0x00000c03, 0x000000a7, 0x00000000, 0x00000001, 0x00000003,
2483 0x00000004, 0x0000000f, 0x4c524f57, 0x4f505f44, 0x49544953, 0x42004e4f, 0x45495a45, 0x54530052,
2484 0x454b4f52, 0x4152545f, 0x4f46534e, 0x53004d52, 0x4f505f56, 0x49544953, 0xab004e4f, 0x52444853,
2485 0x00000228, 0x00010040, 0x0000008a, 0x04000059, 0x00208e46, 0x00000000, 0x00000004, 0x0300005f,
2486 0x00101032, 0x00000000, 0x03000065, 0x00102032, 0x00000000, 0x03000065, 0x001020f2, 0x00000001,
2487 0x03000065, 0x00102032, 0x00000002, 0x03000065, 0x00102032, 0x00000003, 0x04000067, 0x001020f2,
2488 0x00000004, 0x00000001, 0x02000068, 0x00000002, 0x05000036, 0x00100032, 0x00000000, 0x00101046,
2489 0x00000000, 0x05000036, 0x00100042, 0x00000000, 0x00004001, 0x3f800000, 0x08000010, 0x00100012,
2490 0x00000001, 0x00100246, 0x00000000, 0x00208246, 0x00000000, 0x00000000, 0x08000010, 0x00100022,
2491 0x00000001, 0x00100246, 0x00000000, 0x00208246, 0x00000000, 0x00000001, 0x05000036, 0x00102032,
2492 0x00000000, 0x00100046, 0x00000001, 0x08000036, 0x001020f2, 0x00000001, 0x00004002, 0x3f800000,
2493 0x00000000, 0x3f800000, 0x3f800000, 0x08000036, 0x00102032, 0x00000002, 0x00004002, 0x3f800000,
2494 0x00000000, 0x00000000, 0x00000000, 0x08000036, 0x00102032, 0x00000003, 0x00004002, 0x00000000,
2495 0x3f800000, 0x00000000, 0x00000000, 0x05000036, 0x00100042, 0x00000001, 0x00004001, 0x3f800000,
2496 0x08000010, 0x00100012, 0x00000000, 0x00208246, 0x00000000, 0x00000002, 0x00100246, 0x00000001,
2497 0x08000010, 0x00100022, 0x00000000, 0x00208246, 0x00000000, 0x00000003, 0x00100246, 0x00000001,
2498 0x08000038, 0x00100022, 0x00000001, 0x0010001a, 0x00000000, 0x0020803a, 0x00000000, 0x00000003,
2499 0x08000038, 0x00100012, 0x00000001, 0x0010000a, 0x00000000, 0x0020803a, 0x00000000, 0x00000002,
2500 0x0a000000, 0x00102032, 0x00000004, 0x00100046, 0x00000001, 0x00004002, 0xbf800000, 0x3f800000,
2501 0x00000000, 0x00000000, 0x08000036, 0x001020c2, 0x00000004, 0x00004002, 0x00000000, 0x00000000,
2502 0x00000000, 0x3f800000, 0x0100003e,
2504 static const DWORD vs_code_bezier[] =
2506 #if 0
2507 float3x2 transform_geometry;
2508 float4 transform_rtx;
2509 float4 transform_rty;
2511 struct output
2513 float2 p : WORLD_POSITION;
2514 float4 b : BEZIER;
2515 nointerpolation float2x2 stroke_transform : STROKE_TRANSFORM;
2516 float4 position : SV_POSITION;
2519 void main(float2 position : POSITION, float3 texcoord : TEXCOORD0, out struct output o)
2521 o.p = mul(float3(position, 1.0f), transform_geometry);
2522 o.b = float4(texcoord, 1.0);
2523 o.stroke_transform = float2x2(1.0, 0.0, 0.0, 1.0);
2524 position = mul(float2x3(transform_rtx.xyz, transform_rty.xyz), float3(o.p, 1.0f))
2525 * float2(transform_rtx.w, transform_rty.w);
2526 o.position = float4(position + float2(-1.0f, 1.0f), 0.0f, 1.0f);
2528 #endif
2529 0x43425844, 0xedb7472a, 0x2c2ea147, 0x36710079, 0xffc2e907, 0x00000001, 0x00000380, 0x00000003,
2530 0x0000002c, 0x00000080, 0x0000013c, 0x4e475349, 0x0000004c, 0x00000002, 0x00000008, 0x00000038,
2531 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000303, 0x00000041, 0x00000000, 0x00000000,
2532 0x00000003, 0x00000001, 0x00000707, 0x49534f50, 0x4e4f4954, 0x58455400, 0x524f4f43, 0xabab0044,
2533 0x4e47534f, 0x000000b4, 0x00000005, 0x00000008, 0x00000080, 0x00000000, 0x00000000, 0x00000003,
2534 0x00000000, 0x00000c03, 0x0000008f, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x0000000f,
2535 0x00000096, 0x00000000, 0x00000000, 0x00000003, 0x00000002, 0x00000c03, 0x00000096, 0x00000001,
2536 0x00000000, 0x00000003, 0x00000003, 0x00000c03, 0x000000a7, 0x00000000, 0x00000001, 0x00000003,
2537 0x00000004, 0x0000000f, 0x4c524f57, 0x4f505f44, 0x49544953, 0x42004e4f, 0x45495a45, 0x54530052,
2538 0x454b4f52, 0x4152545f, 0x4f46534e, 0x53004d52, 0x4f505f56, 0x49544953, 0xab004e4f, 0x52444853,
2539 0x0000023c, 0x00010040, 0x0000008f, 0x04000059, 0x00208e46, 0x00000000, 0x00000004, 0x0300005f,
2540 0x00101032, 0x00000000, 0x0300005f, 0x00101072, 0x00000001, 0x03000065, 0x00102032, 0x00000000,
2541 0x03000065, 0x001020f2, 0x00000001, 0x03000065, 0x00102032, 0x00000002, 0x03000065, 0x00102032,
2542 0x00000003, 0x04000067, 0x001020f2, 0x00000004, 0x00000001, 0x02000068, 0x00000002, 0x05000036,
2543 0x00100032, 0x00000000, 0x00101046, 0x00000000, 0x05000036, 0x00100042, 0x00000000, 0x00004001,
2544 0x3f800000, 0x08000010, 0x00100012, 0x00000001, 0x00100246, 0x00000000, 0x00208246, 0x00000000,
2545 0x00000000, 0x08000010, 0x00100022, 0x00000001, 0x00100246, 0x00000000, 0x00208246, 0x00000000,
2546 0x00000001, 0x05000036, 0x00102032, 0x00000000, 0x00100046, 0x00000001, 0x05000036, 0x00102072,
2547 0x00000001, 0x00101246, 0x00000001, 0x05000036, 0x00102082, 0x00000001, 0x00004001, 0x3f800000,
2548 0x08000036, 0x00102032, 0x00000002, 0x00004002, 0x3f800000, 0x00000000, 0x00000000, 0x00000000,
2549 0x08000036, 0x00102032, 0x00000003, 0x00004002, 0x00000000, 0x3f800000, 0x00000000, 0x00000000,
2550 0x05000036, 0x00100042, 0x00000001, 0x00004001, 0x3f800000, 0x08000010, 0x00100012, 0x00000000,
2551 0x00208246, 0x00000000, 0x00000002, 0x00100246, 0x00000001, 0x08000010, 0x00100022, 0x00000000,
2552 0x00208246, 0x00000000, 0x00000003, 0x00100246, 0x00000001, 0x08000038, 0x00100022, 0x00000001,
2553 0x0010001a, 0x00000000, 0x0020803a, 0x00000000, 0x00000003, 0x08000038, 0x00100012, 0x00000001,
2554 0x0010000a, 0x00000000, 0x0020803a, 0x00000000, 0x00000002, 0x0a000000, 0x00102032, 0x00000004,
2555 0x00100046, 0x00000001, 0x00004002, 0xbf800000, 0x3f800000, 0x00000000, 0x00000000, 0x08000036,
2556 0x001020c2, 0x00000004, 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, 0x0100003e,
2558 static const DWORD ps_code[] =
2560 #if 0
2561 #define BRUSH_TYPE_SOLID 0
2562 #define BRUSH_TYPE_LINEAR 1
2563 #define BRUSH_TYPE_RADIAL 2
2564 #define BRUSH_TYPE_BITMAP 3
2565 #define BRUSH_TYPE_COUNT 4
2567 bool outline;
2568 struct brush
2570 uint type;
2571 float opacity;
2572 float4 data[3];
2573 } colour_brush, opacity_brush;
2575 SamplerState s0, s1;
2576 Texture2D t0, t1;
2577 Buffer<float4> b0, b1;
2579 struct input
2581 float2 p : WORLD_POSITION;
2582 float4 b : BEZIER;
2583 nointerpolation float2x2 stroke_transform : STROKE_TRANSFORM;
2586 float4 sample_gradient(Buffer<float4> gradient, uint stop_count, float position)
2588 float4 c_low, c_high;
2589 float p_low, p_high;
2590 uint i;
2592 p_low = gradient.Load(0).x;
2593 c_low = gradient.Load(1);
2594 c_high = c_low;
2596 if (position < p_low)
2597 return c_low;
2599 for (i = 1; i < stop_count; ++i)
2601 p_high = gradient.Load(i * 2).x;
2602 c_high = gradient.Load(i * 2 + 1);
2604 if (position >= p_low && position <= p_high)
2605 return lerp(c_low, c_high, (position - p_low) / (p_high - p_low));
2607 p_low = p_high;
2608 c_low = c_high;
2611 return c_high;
2614 float4 brush_linear(struct brush brush, Buffer<float4> gradient, float2 position)
2616 float2 start, end, v_p, v_q;
2617 uint stop_count;
2618 float p;
2620 start = brush.data[0].xy;
2621 end = brush.data[0].zw;
2622 stop_count = asuint(brush.data[1].x);
2624 v_p = position - start;
2625 v_q = end - start;
2626 p = dot(v_q, v_p) / dot(v_q, v_q);
2628 return sample_gradient(gradient, stop_count, p);
2631 float4 brush_radial(struct brush brush, Buffer<float4> gradient, float2 position)
2633 float2 centre, offset, ra, rb, v_p, v_q, r;
2634 float b, c, l, t;
2635 uint stop_count;
2637 centre = brush.data[0].xy;
2638 offset = brush.data[0].zw;
2639 ra = brush.data[1].xy;
2640 rb = brush.data[1].zw;
2641 stop_count = asuint(brush.data[2].x);
2643 /* Project onto ra, rb. */
2644 r = float2(dot(ra, ra), dot(rb, rb));
2645 v_p = position - (centre + offset);
2646 v_p = float2(dot(v_p, ra), dot(v_p, rb)) / r;
2647 v_q = float2(dot(offset, ra), dot(offset, rb)) / r;
2649 /* ‖t·p̂ + q⃑‖ = 1
2650 * (t·p̂ + q⃑) · (t·p̂ + q⃑) = 1
2651 * t² + 2·(p̂·q⃑)·t + (q⃑·q⃑) = 1
2653 * b = p̂·q⃑
2654 * c = q⃑·q⃑ - 1
2655 * t = -b + √(b² - c) */
2656 l = length(v_p);
2657 b = dot(v_p, v_q) / l;
2658 c = dot(v_q, v_q) - 1.0;
2659 t = -b + sqrt(b * b - c);
2661 return sample_gradient(gradient, stop_count, l / t);
2664 float4 brush_bitmap(struct brush brush, Texture2D t, SamplerState s, float2 position)
2666 float3 transform[2];
2667 bool ignore_alpha;
2668 float2 texcoord;
2669 float4 colour;
2671 transform[0] = brush.data[0].xyz;
2672 transform[1] = brush.data[1].xyz;
2673 ignore_alpha = asuint(brush.data[1].w);
2675 texcoord.x = dot(position.xy, transform[0].xy) + transform[0].z;
2676 texcoord.y = dot(position.xy, transform[1].xy) + transform[1].z;
2677 colour = t.Sample(s, texcoord);
2678 if (ignore_alpha)
2679 colour.a = 1.0;
2680 return colour;
2683 float4 sample_brush(struct brush brush, Texture2D t, SamplerState s, Buffer<float4> b, float2 position)
2685 if (brush.type == BRUSH_TYPE_SOLID)
2686 return brush.data[0] * brush.opacity;
2687 if (brush.type == BRUSH_TYPE_LINEAR)
2688 return brush_linear(brush, b, position) * brush.opacity;
2689 if (brush.type == BRUSH_TYPE_RADIAL)
2690 return brush_radial(brush, b, position) * brush.opacity;
2691 if (brush.type == BRUSH_TYPE_BITMAP)
2692 return brush_bitmap(brush, t, s, position) * brush.opacity;
2693 return float4(0.0, 0.0, 0.0, brush.opacity);
2696 float4 main(struct input i) : SV_Target
2698 float4 colour;
2700 colour = sample_brush(colour_brush, t0, s0, b0, i.p);
2701 if (opacity_brush.type < BRUSH_TYPE_COUNT)
2702 colour *= sample_brush(opacity_brush, t1, s1, b1, i.p).a;
2704 if (outline)
2706 float2 du, dv, df;
2707 float4 uv;
2709 /* Evaluate the implicit form of the curve (u² - v = 0) in texture space,
2710 * using the screen-space partial derivatives to convert the calculated
2711 * distance to object space.
2713 * d(x, y) = |f(x, y)| / ‖∇f(x, y)‖
2714 * = |f(x, y)| / √((∂f/∂x)² + (∂f/∂y)²)
2715 * f(x, y) = u(x, y)² - v(x, y)
2716 * ∂f/∂x = 2u · ∂u/∂x - ∂v/∂x
2717 * ∂f/∂y = 2u · ∂u/∂y - ∂v/∂y */
2718 uv = i.b;
2719 du = float2(ddx(uv.x), ddy(uv.x));
2720 dv = float2(ddx(uv.y), ddy(uv.y));
2721 df = 2.0f * uv.x * du - dv;
2723 clip(dot(df, uv.zw));
2724 clip(length(mul(i.stroke_transform, df)) - abs(uv.x * uv.x - uv.y));
2726 else
2728 /* Evaluate the implicit form of the curve in texture space.
2729 * "i.b.z" determines which side of the curve is shaded. */
2730 clip((i.b.x * i.b.x - i.b.y) * i.b.z);
2733 return colour;
2735 #endif
2736 0x43425844, 0xf3cbb8bd, 0x5f286454, 0x139976a7, 0x6817e876, 0x00000001, 0x00001d18, 0x00000003,
2737 0x0000002c, 0x000000c4, 0x000000f8, 0x4e475349, 0x00000090, 0x00000004, 0x00000008, 0x00000068,
2738 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000303, 0x00000077, 0x00000000, 0x00000000,
2739 0x00000003, 0x00000001, 0x00000f0f, 0x0000007e, 0x00000000, 0x00000000, 0x00000003, 0x00000002,
2740 0x00000303, 0x0000007e, 0x00000001, 0x00000000, 0x00000003, 0x00000003, 0x00000303, 0x4c524f57,
2741 0x4f505f44, 0x49544953, 0x42004e4f, 0x45495a45, 0x54530052, 0x454b4f52, 0x4152545f, 0x4f46534e,
2742 0xab004d52, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000,
2743 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x00001c18,
2744 0x00000040, 0x00000706, 0x04000059, 0x00208e46, 0x00000000, 0x00000009, 0x0300005a, 0x00106000,
2745 0x00000000, 0x0300005a, 0x00106000, 0x00000001, 0x04001858, 0x00107000, 0x00000000, 0x00005555,
2746 0x04001858, 0x00107000, 0x00000001, 0x00005555, 0x04000858, 0x00107000, 0x00000002, 0x00005555,
2747 0x04000858, 0x00107000, 0x00000003, 0x00005555, 0x03001062, 0x00101032, 0x00000000, 0x03001062,
2748 0x001010f2, 0x00000001, 0x03000862, 0x00101032, 0x00000002, 0x03000862, 0x00101032, 0x00000003,
2749 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x0000000a, 0x09000038, 0x001000f2, 0x00000000,
2750 0x00208556, 0x00000000, 0x00000001, 0x00208e46, 0x00000000, 0x00000002, 0x0404001f, 0x0020800a,
2751 0x00000000, 0x00000001, 0x08000020, 0x00100012, 0x00000001, 0x0020800a, 0x00000000, 0x00000001,
2752 0x00004001, 0x00000001, 0x0304001f, 0x0010000a, 0x00000001, 0x09000000, 0x00100062, 0x00000001,
2753 0x00101106, 0x00000000, 0x80208106, 0x00000041, 0x00000000, 0x00000002, 0x0a000000, 0x00100032,
2754 0x00000002, 0x80208046, 0x00000041, 0x00000000, 0x00000002, 0x00208ae6, 0x00000000, 0x00000002,
2755 0x0700000f, 0x00100022, 0x00000001, 0x00100046, 0x00000002, 0x00100596, 0x00000001, 0x0700000f,
2756 0x00100042, 0x00000001, 0x00100046, 0x00000002, 0x00100046, 0x00000002, 0x0700000e, 0x00100022,
2757 0x00000001, 0x0010001a, 0x00000001, 0x0010002a, 0x00000001, 0x0a00002d, 0x001000f2, 0x00000002,
2758 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00107e46, 0x00000002, 0x0a00002d,
2759 0x001000f2, 0x00000003, 0x00004002, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00107e46,
2760 0x00000002, 0x0700001d, 0x00100042, 0x00000001, 0x0010001a, 0x00000001, 0x0010000a, 0x00000002,
2761 0x0304001f, 0x0010002a, 0x00000001, 0x05000036, 0x001000f2, 0x00000004, 0x00100e46, 0x00000003,
2762 0x05000036, 0x001000f2, 0x00000005, 0x00100e46, 0x00000003, 0x05000036, 0x001000f2, 0x00000006,
2763 0x00100e46, 0x00000003, 0x05000036, 0x00100042, 0x00000001, 0x0010000a, 0x00000002, 0x05000036,
2764 0x00100082, 0x00000001, 0x00004001, 0x00000001, 0x05000036, 0x00100022, 0x00000002, 0x00004001,
2765 0x00000000, 0x01000030, 0x08000050, 0x00100042, 0x00000002, 0x0010003a, 0x00000001, 0x0020800a,
2766 0x00000000, 0x00000003, 0x05000036, 0x00100022, 0x00000002, 0x00004001, 0x00000000, 0x03040003,
2767 0x0010002a, 0x00000002, 0x07000029, 0x00100042, 0x00000002, 0x0010003a, 0x00000001, 0x00004001,
2768 0x00000001, 0x0700002d, 0x001000f2, 0x00000007, 0x00100aa6, 0x00000002, 0x00107e46, 0x00000002,
2769 0x0700001e, 0x00100042, 0x00000002, 0x0010002a, 0x00000002, 0x00004001, 0x00000001, 0x0700002d,
2770 0x001000f2, 0x00000008, 0x00100aa6, 0x00000002, 0x00107e46, 0x00000002, 0x0700001d, 0x00100042,
2771 0x00000002, 0x0010001a, 0x00000001, 0x0010002a, 0x00000001, 0x0700001d, 0x00100082, 0x00000002,
2772 0x0010000a, 0x00000007, 0x0010001a, 0x00000001, 0x07000001, 0x00100042, 0x00000002, 0x0010003a,
2773 0x00000002, 0x0010002a, 0x00000002, 0x0304001f, 0x0010002a, 0x00000002, 0x08000000, 0x00100082,
2774 0x00000002, 0x8010002a, 0x00000041, 0x00000001, 0x0010001a, 0x00000001, 0x08000000, 0x00100022,
2775 0x00000007, 0x8010002a, 0x00000041, 0x00000001, 0x0010000a, 0x00000007, 0x0700000e, 0x00100082,
2776 0x00000002, 0x0010003a, 0x00000002, 0x0010001a, 0x00000007, 0x08000000, 0x001000f2, 0x00000009,
2777 0x80100e46, 0x00000041, 0x00000005, 0x00100e46, 0x00000008, 0x09000032, 0x001000f2, 0x00000009,
2778 0x00100ff6, 0x00000002, 0x00100e46, 0x00000009, 0x00100e46, 0x00000005, 0x05000036, 0x001000f2,
2779 0x00000006, 0x00100e46, 0x00000008, 0x05000036, 0x00100022, 0x00000002, 0x00004001, 0xffffffff,
2780 0x05000036, 0x001000f2, 0x00000004, 0x00100e46, 0x00000009, 0x01000002, 0x01000015, 0x05000036,
2781 0x001000f2, 0x00000005, 0x00100e46, 0x00000008, 0x05000036, 0x00100042, 0x00000001, 0x0010000a,
2782 0x00000007, 0x0700001e, 0x00100082, 0x00000001, 0x0010003a, 0x00000001, 0x00004001, 0x00000001,
2783 0x05000036, 0x001000f2, 0x00000006, 0x00100e46, 0x00000008, 0x05000036, 0x00100022, 0x00000002,
2784 0x0010002a, 0x00000002, 0x01000016, 0x09000037, 0x001000f2, 0x00000003, 0x00100556, 0x00000002,
2785 0x00100e46, 0x00000004, 0x00100e46, 0x00000006, 0x01000015, 0x08000038, 0x001000f2, 0x00000000,
2786 0x00100e46, 0x00000003, 0x00208556, 0x00000000, 0x00000001, 0x01000015, 0x0300001f, 0x0010000a,
2787 0x00000001, 0x08000020, 0x00100012, 0x00000001, 0x0020800a, 0x00000000, 0x00000001, 0x00004001,
2788 0x00000002, 0x0304001f, 0x0010000a, 0x00000001, 0x0900000f, 0x00100012, 0x00000002, 0x00208046,
2789 0x00000000, 0x00000003, 0x00208046, 0x00000000, 0x00000003, 0x0900000f, 0x00100022, 0x00000002,
2790 0x00208ae6, 0x00000000, 0x00000003, 0x00208ae6, 0x00000000, 0x00000003, 0x09000000, 0x00100062,
2791 0x00000001, 0x00208ba6, 0x00000000, 0x00000002, 0x00208106, 0x00000000, 0x00000002, 0x08000000,
2792 0x00100062, 0x00000001, 0x80100656, 0x00000041, 0x00000001, 0x00101106, 0x00000000, 0x0800000f,
2793 0x00100012, 0x00000003, 0x00100596, 0x00000001, 0x00208046, 0x00000000, 0x00000003, 0x0800000f,
2794 0x00100022, 0x00000003, 0x00100596, 0x00000001, 0x00208ae6, 0x00000000, 0x00000003, 0x0700000e,
2795 0x00100062, 0x00000001, 0x00100106, 0x00000003, 0x00100106, 0x00000002, 0x0900000f, 0x00100012,
2796 0x00000003, 0x00208ae6, 0x00000000, 0x00000002, 0x00208046, 0x00000000, 0x00000003, 0x0900000f,
2797 0x00100022, 0x00000003, 0x00208ae6, 0x00000000, 0x00000002, 0x00208ae6, 0x00000000, 0x00000003,
2798 0x0700000e, 0x00100032, 0x00000002, 0x00100046, 0x00000003, 0x00100046, 0x00000002, 0x0700000f,
2799 0x00100082, 0x00000001, 0x00100596, 0x00000001, 0x00100596, 0x00000001, 0x0500004b, 0x00100082,
2800 0x00000001, 0x0010003a, 0x00000001, 0x0700000f, 0x00100022, 0x00000001, 0x00100596, 0x00000001,
2801 0x00100046, 0x00000002, 0x0700000e, 0x00100022, 0x00000001, 0x0010001a, 0x00000001, 0x0010003a,
2802 0x00000001, 0x0700000f, 0x00100042, 0x00000001, 0x00100046, 0x00000002, 0x00100046, 0x00000002,
2803 0x07000000, 0x00100042, 0x00000001, 0x0010002a, 0x00000001, 0x00004001, 0xbf800000, 0x0a000032,
2804 0x00100042, 0x00000001, 0x0010001a, 0x00000001, 0x0010001a, 0x00000001, 0x8010002a, 0x00000041,
2805 0x00000001, 0x0500004b, 0x00100042, 0x00000001, 0x0010002a, 0x00000001, 0x08000000, 0x00100022,
2806 0x00000001, 0x0010002a, 0x00000001, 0x8010001a, 0x00000041, 0x00000001, 0x0700000e, 0x00100022,
2807 0x00000001, 0x0010003a, 0x00000001, 0x0010001a, 0x00000001, 0x0a00002d, 0x001000f2, 0x00000002,
2808 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00107e46, 0x00000002, 0x0a00002d,
2809 0x001000f2, 0x00000003, 0x00004002, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00107e46,
2810 0x00000002, 0x0700001d, 0x00100042, 0x00000001, 0x0010001a, 0x00000001, 0x0010000a, 0x00000002,
2811 0x0304001f, 0x0010002a, 0x00000001, 0x05000036, 0x001000f2, 0x00000004, 0x00100e46, 0x00000003,
2812 0x05000036, 0x001000f2, 0x00000005, 0x00100e46, 0x00000003, 0x05000036, 0x001000f2, 0x00000006,
2813 0x00100e46, 0x00000003, 0x05000036, 0x00100042, 0x00000001, 0x0010000a, 0x00000002, 0x05000036,
2814 0x00100082, 0x00000001, 0x00004001, 0x00000001, 0x05000036, 0x00100022, 0x00000002, 0x00004001,
2815 0x00000000, 0x01000030, 0x08000050, 0x00100042, 0x00000002, 0x0010003a, 0x00000001, 0x0020800a,
2816 0x00000000, 0x00000004, 0x05000036, 0x00100022, 0x00000002, 0x00004001, 0x00000000, 0x03040003,
2817 0x0010002a, 0x00000002, 0x07000029, 0x00100042, 0x00000002, 0x0010003a, 0x00000001, 0x00004001,
2818 0x00000001, 0x0700002d, 0x001000f2, 0x00000007, 0x00100aa6, 0x00000002, 0x00107e46, 0x00000002,
2819 0x0700001e, 0x00100042, 0x00000002, 0x0010002a, 0x00000002, 0x00004001, 0x00000001, 0x0700002d,
2820 0x001000f2, 0x00000008, 0x00100aa6, 0x00000002, 0x00107e46, 0x00000002, 0x0700001d, 0x00100042,
2821 0x00000002, 0x0010001a, 0x00000001, 0x0010002a, 0x00000001, 0x0700001d, 0x00100082, 0x00000002,
2822 0x0010000a, 0x00000007, 0x0010001a, 0x00000001, 0x07000001, 0x00100042, 0x00000002, 0x0010003a,
2823 0x00000002, 0x0010002a, 0x00000002, 0x0304001f, 0x0010002a, 0x00000002, 0x08000000, 0x00100082,
2824 0x00000002, 0x8010002a, 0x00000041, 0x00000001, 0x0010001a, 0x00000001, 0x08000000, 0x00100022,
2825 0x00000007, 0x8010002a, 0x00000041, 0x00000001, 0x0010000a, 0x00000007, 0x0700000e, 0x00100082,
2826 0x00000002, 0x0010003a, 0x00000002, 0x0010001a, 0x00000007, 0x08000000, 0x001000f2, 0x00000009,
2827 0x80100e46, 0x00000041, 0x00000005, 0x00100e46, 0x00000008, 0x09000032, 0x001000f2, 0x00000009,
2828 0x00100ff6, 0x00000002, 0x00100e46, 0x00000009, 0x00100e46, 0x00000005, 0x05000036, 0x001000f2,
2829 0x00000006, 0x00100e46, 0x00000008, 0x05000036, 0x00100022, 0x00000002, 0x00004001, 0xffffffff,
2830 0x05000036, 0x001000f2, 0x00000004, 0x00100e46, 0x00000009, 0x01000002, 0x01000015, 0x05000036,
2831 0x001000f2, 0x00000005, 0x00100e46, 0x00000008, 0x05000036, 0x00100042, 0x00000001, 0x0010000a,
2832 0x00000007, 0x0700001e, 0x00100082, 0x00000001, 0x0010003a, 0x00000001, 0x00004001, 0x00000001,
2833 0x05000036, 0x001000f2, 0x00000006, 0x00100e46, 0x00000008, 0x05000036, 0x00100022, 0x00000002,
2834 0x0010002a, 0x00000002, 0x01000016, 0x09000037, 0x001000f2, 0x00000003, 0x00100556, 0x00000002,
2835 0x00100e46, 0x00000004, 0x00100e46, 0x00000006, 0x01000015, 0x08000038, 0x001000f2, 0x00000000,
2836 0x00100e46, 0x00000003, 0x00208556, 0x00000000, 0x00000001, 0x01000015, 0x0300001f, 0x0010000a,
2837 0x00000001, 0x08000020, 0x00100012, 0x00000001, 0x0020800a, 0x00000000, 0x00000001, 0x00004001,
2838 0x00000003, 0x0304001f, 0x0010000a, 0x00000001, 0x0800000f, 0x00100022, 0x00000001, 0x00101046,
2839 0x00000000, 0x00208046, 0x00000000, 0x00000002, 0x08000000, 0x00100012, 0x00000002, 0x0010001a,
2840 0x00000001, 0x0020802a, 0x00000000, 0x00000002, 0x0800000f, 0x00100022, 0x00000001, 0x00101046,
2841 0x00000000, 0x00208046, 0x00000000, 0x00000003, 0x08000000, 0x00100022, 0x00000002, 0x0010001a,
2842 0x00000001, 0x0020802a, 0x00000000, 0x00000003, 0x09000045, 0x001000f2, 0x00000002, 0x00100046,
2843 0x00000002, 0x00107e46, 0x00000000, 0x00106000, 0x00000000, 0x0a000037, 0x00100082, 0x00000002,
2844 0x0020803a, 0x00000000, 0x00000003, 0x00004001, 0x3f800000, 0x0010003a, 0x00000002, 0x08000038,
2845 0x001000f2, 0x00000000, 0x00100e46, 0x00000002, 0x00208556, 0x00000000, 0x00000001, 0x01000015,
2846 0x05000036, 0x00100012, 0x00000002, 0x00004001, 0x00000000, 0x06000036, 0x00100082, 0x00000002,
2847 0x0020801a, 0x00000000, 0x00000001, 0x09000037, 0x001000f2, 0x00000000, 0x00100006, 0x00000001,
2848 0x00100e46, 0x00000000, 0x00100c06, 0x00000002, 0x01000015, 0x01000015, 0x01000015, 0x0800004f,
2849 0x00100012, 0x00000001, 0x0020800a, 0x00000000, 0x00000005, 0x00004001, 0x00000004, 0x0304001f,
2850 0x0010000a, 0x00000001, 0x09000038, 0x00100012, 0x00000001, 0x0020801a, 0x00000000, 0x00000005,
2851 0x0020803a, 0x00000000, 0x00000006, 0x0404001f, 0x0020800a, 0x00000000, 0x00000005, 0x08000020,
2852 0x00100022, 0x00000001, 0x0020800a, 0x00000000, 0x00000005, 0x00004001, 0x00000001, 0x0304001f,
2853 0x0010001a, 0x00000001, 0x09000000, 0x001000c2, 0x00000001, 0x00101406, 0x00000000, 0x80208406,
2854 0x00000041, 0x00000000, 0x00000006, 0x0a000000, 0x00100032, 0x00000002, 0x80208046, 0x00000041,
2855 0x00000000, 0x00000006, 0x00208ae6, 0x00000000, 0x00000006, 0x0700000f, 0x00100042, 0x00000001,
2856 0x00100046, 0x00000002, 0x00100ae6, 0x00000001, 0x0700000f, 0x00100082, 0x00000001, 0x00100046,
2857 0x00000002, 0x00100046, 0x00000002, 0x0700000e, 0x00100042, 0x00000001, 0x0010002a, 0x00000001,
2858 0x0010003a, 0x00000001, 0x0a00002d, 0x001000f2, 0x00000002, 0x00004002, 0x00000000, 0x00000000,
2859 0x00000000, 0x00000000, 0x00107e46, 0x00000003, 0x0a00002d, 0x001000f2, 0x00000003, 0x00004002,
2860 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00107e46, 0x00000003, 0x0700001d, 0x00100082,
2861 0x00000001, 0x0010002a, 0x00000001, 0x0010000a, 0x00000002, 0x0304001f, 0x0010003a, 0x00000001,
2862 0x05000036, 0x00100082, 0x00000001, 0x0010003a, 0x00000003, 0x05000036, 0x00100062, 0x00000002,
2863 0x00100ff6, 0x00000003, 0x05000036, 0x00100082, 0x00000002, 0x0010000a, 0x00000002, 0x08000036,
2864 0x00100032, 0x00000003, 0x00004002, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x01000030,
2865 0x08000050, 0x00100042, 0x00000003, 0x0010000a, 0x00000003, 0x0020800a, 0x00000000, 0x00000007,
2866 0x05000036, 0x00100022, 0x00000003, 0x00004001, 0x00000000, 0x03040003, 0x0010002a, 0x00000003,
2867 0x07000029, 0x00100042, 0x00000003, 0x0010000a, 0x00000003, 0x00004001, 0x00000001, 0x0700002d,
2868 0x001000f2, 0x00000004, 0x00100aa6, 0x00000003, 0x00107e46, 0x00000003, 0x0700001e, 0x00100042,
2869 0x00000003, 0x0010002a, 0x00000003, 0x00004001, 0x00000001, 0x0700002d, 0x001000f2, 0x00000005,
2870 0x00100aa6, 0x00000003, 0x00107e46, 0x00000003, 0x0700001d, 0x00100042, 0x00000003, 0x0010002a,
2871 0x00000001, 0x0010003a, 0x00000002, 0x0700001d, 0x00100022, 0x00000004, 0x0010000a, 0x00000004,
2872 0x0010002a, 0x00000001, 0x07000001, 0x00100042, 0x00000003, 0x0010002a, 0x00000003, 0x0010001a,
2873 0x00000004, 0x0304001f, 0x0010002a, 0x00000003, 0x08000000, 0x00100022, 0x00000004, 0x0010002a,
2874 0x00000001, 0x8010003a, 0x00000041, 0x00000002, 0x08000000, 0x00100042, 0x00000004, 0x8010003a,
2875 0x00000041, 0x00000002, 0x0010000a, 0x00000004, 0x0700000e, 0x00100022, 0x00000004, 0x0010001a,
2876 0x00000004, 0x0010002a, 0x00000004, 0x08000000, 0x00100042, 0x00000004, 0x8010001a, 0x00000041,
2877 0x00000002, 0x0010003a, 0x00000005, 0x09000032, 0x00100022, 0x00000004, 0x0010001a, 0x00000004,
2878 0x0010002a, 0x00000004, 0x0010001a, 0x00000002, 0x05000036, 0x00100042, 0x00000002, 0x0010003a,
2879 0x00000005, 0x05000036, 0x00100022, 0x00000003, 0x00004001, 0xffffffff, 0x05000036, 0x00100082,
2880 0x00000001, 0x0010001a, 0x00000004, 0x01000002, 0x01000015, 0x05000036, 0x00100022, 0x00000002,
2881 0x0010003a, 0x00000005, 0x05000036, 0x00100082, 0x00000002, 0x0010000a, 0x00000004, 0x0700001e,
2882 0x00100012, 0x00000003, 0x0010000a, 0x00000003, 0x00004001, 0x00000001, 0x05000036, 0x00100042,
2883 0x00000002, 0x0010003a, 0x00000005, 0x05000036, 0x00100032, 0x00000003, 0x00100086, 0x00000003,
2884 0x01000016, 0x09000037, 0x00100042, 0x00000001, 0x0010001a, 0x00000003, 0x0010003a, 0x00000001,
2885 0x0010002a, 0x00000002, 0x01000012, 0x05000036, 0x00100042, 0x00000001, 0x0010003a, 0x00000003,
2886 0x01000015, 0x08000038, 0x00100012, 0x00000001, 0x0010002a, 0x00000001, 0x0020801a, 0x00000000,
2887 0x00000005, 0x01000015, 0x0300001f, 0x0010001a, 0x00000001, 0x08000020, 0x00100022, 0x00000001,
2888 0x0020800a, 0x00000000, 0x00000005, 0x00004001, 0x00000002, 0x0304001f, 0x0010001a, 0x00000001,
2889 0x0900000f, 0x00100012, 0x00000002, 0x00208046, 0x00000000, 0x00000007, 0x00208046, 0x00000000,
2890 0x00000007, 0x0900000f, 0x00100022, 0x00000002, 0x00208ae6, 0x00000000, 0x00000007, 0x00208ae6,
2891 0x00000000, 0x00000007, 0x09000000, 0x001000c2, 0x00000001, 0x00208ea6, 0x00000000, 0x00000006,
2892 0x00208406, 0x00000000, 0x00000006, 0x08000000, 0x001000c2, 0x00000001, 0x80100ea6, 0x00000041,
2893 0x00000001, 0x00101406, 0x00000000, 0x0800000f, 0x00100012, 0x00000003, 0x00100ae6, 0x00000001,
2894 0x00208046, 0x00000000, 0x00000007, 0x0800000f, 0x00100022, 0x00000003, 0x00100ae6, 0x00000001,
2895 0x00208ae6, 0x00000000, 0x00000007, 0x0700000e, 0x001000c2, 0x00000001, 0x00100406, 0x00000003,
2896 0x00100406, 0x00000002, 0x0900000f, 0x00100012, 0x00000003, 0x00208ae6, 0x00000000, 0x00000006,
2897 0x00208046, 0x00000000, 0x00000007, 0x0900000f, 0x00100022, 0x00000003, 0x00208ae6, 0x00000000,
2898 0x00000006, 0x00208ae6, 0x00000000, 0x00000007, 0x0700000e, 0x00100032, 0x00000002, 0x00100046,
2899 0x00000003, 0x00100046, 0x00000002, 0x0700000f, 0x00100042, 0x00000002, 0x00100ae6, 0x00000001,
2900 0x00100ae6, 0x00000001, 0x0500004b, 0x00100042, 0x00000002, 0x0010002a, 0x00000002, 0x0700000f,
2901 0x00100042, 0x00000001, 0x00100ae6, 0x00000001, 0x00100046, 0x00000002, 0x0700000e, 0x00100042,
2902 0x00000001, 0x0010002a, 0x00000001, 0x0010002a, 0x00000002, 0x0700000f, 0x00100082, 0x00000001,
2903 0x00100046, 0x00000002, 0x00100046, 0x00000002, 0x07000000, 0x00100082, 0x00000001, 0x0010003a,
2904 0x00000001, 0x00004001, 0xbf800000, 0x0a000032, 0x00100082, 0x00000001, 0x0010002a, 0x00000001,
2905 0x0010002a, 0x00000001, 0x8010003a, 0x00000041, 0x00000001, 0x0500004b, 0x00100082, 0x00000001,
2906 0x0010003a, 0x00000001, 0x08000000, 0x00100042, 0x00000001, 0x0010003a, 0x00000001, 0x8010002a,
2907 0x00000041, 0x00000001, 0x0700000e, 0x00100042, 0x00000001, 0x0010002a, 0x00000002, 0x0010002a,
2908 0x00000001, 0x0a00002d, 0x001000f2, 0x00000002, 0x00004002, 0x00000000, 0x00000000, 0x00000000,
2909 0x00000000, 0x00107e46, 0x00000003, 0x0a00002d, 0x001000f2, 0x00000003, 0x00004002, 0x00000001,
2910 0x00000001, 0x00000001, 0x00000001, 0x00107e46, 0x00000003, 0x0700001d, 0x00100082, 0x00000001,
2911 0x0010002a, 0x00000001, 0x0010000a, 0x00000002, 0x0304001f, 0x0010003a, 0x00000001, 0x05000036,
2912 0x00100082, 0x00000001, 0x0010003a, 0x00000003, 0x05000036, 0x00100062, 0x00000002, 0x00100ff6,
2913 0x00000003, 0x05000036, 0x00100082, 0x00000002, 0x0010000a, 0x00000002, 0x08000036, 0x00100032,
2914 0x00000003, 0x00004002, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x01000030, 0x08000050,
2915 0x00100042, 0x00000003, 0x0010000a, 0x00000003, 0x0020800a, 0x00000000, 0x00000008, 0x05000036,
2916 0x00100022, 0x00000003, 0x00004001, 0x00000000, 0x03040003, 0x0010002a, 0x00000003, 0x07000029,
2917 0x00100042, 0x00000003, 0x0010000a, 0x00000003, 0x00004001, 0x00000001, 0x0700002d, 0x001000f2,
2918 0x00000004, 0x00100aa6, 0x00000003, 0x00107e46, 0x00000003, 0x0700001e, 0x00100042, 0x00000003,
2919 0x0010002a, 0x00000003, 0x00004001, 0x00000001, 0x0700002d, 0x001000f2, 0x00000005, 0x00100aa6,
2920 0x00000003, 0x00107e46, 0x00000003, 0x0700001d, 0x00100042, 0x00000003, 0x0010002a, 0x00000001,
2921 0x0010003a, 0x00000002, 0x0700001d, 0x00100022, 0x00000004, 0x0010000a, 0x00000004, 0x0010002a,
2922 0x00000001, 0x07000001, 0x00100042, 0x00000003, 0x0010002a, 0x00000003, 0x0010001a, 0x00000004,
2923 0x0304001f, 0x0010002a, 0x00000003, 0x08000000, 0x00100022, 0x00000004, 0x0010002a, 0x00000001,
2924 0x8010003a, 0x00000041, 0x00000002, 0x08000000, 0x00100042, 0x00000004, 0x8010003a, 0x00000041,
2925 0x00000002, 0x0010000a, 0x00000004, 0x0700000e, 0x00100022, 0x00000004, 0x0010001a, 0x00000004,
2926 0x0010002a, 0x00000004, 0x08000000, 0x00100042, 0x00000004, 0x8010001a, 0x00000041, 0x00000002,
2927 0x0010003a, 0x00000005, 0x09000032, 0x00100022, 0x00000004, 0x0010001a, 0x00000004, 0x0010002a,
2928 0x00000004, 0x0010001a, 0x00000002, 0x05000036, 0x00100042, 0x00000002, 0x0010003a, 0x00000005,
2929 0x05000036, 0x00100022, 0x00000003, 0x00004001, 0xffffffff, 0x05000036, 0x00100082, 0x00000001,
2930 0x0010001a, 0x00000004, 0x01000002, 0x01000015, 0x05000036, 0x00100022, 0x00000002, 0x0010003a,
2931 0x00000005, 0x05000036, 0x00100082, 0x00000002, 0x0010000a, 0x00000004, 0x0700001e, 0x00100012,
2932 0x00000003, 0x0010000a, 0x00000003, 0x00004001, 0x00000001, 0x05000036, 0x00100042, 0x00000002,
2933 0x0010003a, 0x00000005, 0x05000036, 0x00100032, 0x00000003, 0x00100086, 0x00000003, 0x01000016,
2934 0x09000037, 0x00100042, 0x00000001, 0x0010001a, 0x00000003, 0x0010003a, 0x00000001, 0x0010002a,
2935 0x00000002, 0x01000012, 0x05000036, 0x00100042, 0x00000001, 0x0010003a, 0x00000003, 0x01000015,
2936 0x08000038, 0x00100012, 0x00000001, 0x0010002a, 0x00000001, 0x0020801a, 0x00000000, 0x00000005,
2937 0x01000015, 0x0300001f, 0x0010001a, 0x00000001, 0x08000020, 0x00100022, 0x00000001, 0x0020800a,
2938 0x00000000, 0x00000005, 0x00004001, 0x00000003, 0x0304001f, 0x0010001a, 0x00000001, 0x0800000f,
2939 0x00100042, 0x00000001, 0x00101046, 0x00000000, 0x00208046, 0x00000000, 0x00000006, 0x08000000,
2940 0x00100012, 0x00000002, 0x0010002a, 0x00000001, 0x0020802a, 0x00000000, 0x00000006, 0x0800000f,
2941 0x00100042, 0x00000001, 0x00101046, 0x00000000, 0x00208046, 0x00000000, 0x00000007, 0x08000000,
2942 0x00100022, 0x00000002, 0x0010002a, 0x00000001, 0x0020802a, 0x00000000, 0x00000007, 0x09000045,
2943 0x001000f2, 0x00000002, 0x00100046, 0x00000002, 0x00107e46, 0x00000001, 0x00106000, 0x00000001,
2944 0x0a000037, 0x00100042, 0x00000001, 0x0020803a, 0x00000000, 0x00000007, 0x00004001, 0x3f800000,
2945 0x0010003a, 0x00000002, 0x08000038, 0x00100012, 0x00000001, 0x0010002a, 0x00000001, 0x0020801a,
2946 0x00000000, 0x00000005, 0x01000015, 0x0a000037, 0x00100012, 0x00000001, 0x0010001a, 0x00000001,
2947 0x0010000a, 0x00000001, 0x0020801a, 0x00000000, 0x00000005, 0x01000015, 0x01000015, 0x01000015,
2948 0x07000038, 0x001020f2, 0x00000000, 0x00100e46, 0x00000000, 0x00100006, 0x00000001, 0x01000012,
2949 0x05000036, 0x001020f2, 0x00000000, 0x00100e46, 0x00000000, 0x01000015, 0x08000027, 0x00100012,
2950 0x00000000, 0x0020800a, 0x00000000, 0x00000000, 0x00004001, 0x00000000, 0x0500003b, 0x00100022,
2951 0x00000000, 0x0010000a, 0x00000000, 0x0500000b, 0x00100032, 0x00000001, 0x00101046, 0x00000001,
2952 0x0500000c, 0x001000c2, 0x00000001, 0x00101406, 0x00000001, 0x07000000, 0x00100042, 0x00000000,
2953 0x0010100a, 0x00000001, 0x0010100a, 0x00000001, 0x0a000032, 0x001000c2, 0x00000000, 0x00100aa6,
2954 0x00000000, 0x00100806, 0x00000001, 0x80100d56, 0x00000041, 0x00000001, 0x0700000f, 0x00100012,
2955 0x00000001, 0x00100ae6, 0x00000000, 0x00101ae6, 0x00000001, 0x07000031, 0x00100012, 0x00000001,
2956 0x0010000a, 0x00000001, 0x00004001, 0x00000000, 0x07000001, 0x00100012, 0x00000001, 0x0010000a,
2957 0x00000000, 0x0010000a, 0x00000001, 0x0304000d, 0x0010000a, 0x00000001, 0x07000038, 0x00100032,
2958 0x00000001, 0x00100ff6, 0x00000000, 0x00101046, 0x00000003, 0x09000032, 0x001000c2, 0x00000000,
2959 0x00101406, 0x00000002, 0x00100aa6, 0x00000000, 0x00100406, 0x00000001, 0x0700000f, 0x00100042,
2960 0x00000000, 0x00100ae6, 0x00000000, 0x00100ae6, 0x00000000, 0x0500004b, 0x00100042, 0x00000000,
2961 0x0010002a, 0x00000000, 0x0a000032, 0x00100082, 0x00000000, 0x0010100a, 0x00000001, 0x0010100a,
2962 0x00000001, 0x8010101a, 0x00000041, 0x00000001, 0x08000000, 0x00100042, 0x00000000, 0x8010003a,
2963 0x000000c1, 0x00000000, 0x0010002a, 0x00000000, 0x07000031, 0x00100042, 0x00000000, 0x0010002a,
2964 0x00000000, 0x00004001, 0x00000000, 0x07000001, 0x00100012, 0x00000000, 0x0010000a, 0x00000000,
2965 0x0010002a, 0x00000000, 0x0304000d, 0x0010000a, 0x00000000, 0x07000038, 0x00100012, 0x00000000,
2966 0x0010003a, 0x00000000, 0x0010102a, 0x00000001, 0x07000031, 0x00100012, 0x00000000, 0x0010000a,
2967 0x00000000, 0x00004001, 0x00000000, 0x07000001, 0x00100012, 0x00000000, 0x0010001a, 0x00000000,
2968 0x0010000a, 0x00000000, 0x0304000d, 0x0010000a, 0x00000000, 0x0100003e,
2970 static const struct shape_info
2972 enum d2d_shape_type shape_type;
2973 const D3D10_INPUT_ELEMENT_DESC *il_desc;
2974 unsigned int il_element_count;
2975 const void *vs_code;
2976 size_t vs_code_size;
2978 shape_info[] =
2980 {D2D_SHAPE_TYPE_OUTLINE, il_desc_outline, ARRAY_SIZE(il_desc_outline),
2981 vs_code_outline, sizeof(vs_code_outline)},
2982 {D2D_SHAPE_TYPE_BEZIER_OUTLINE, il_desc_bezier_outline, ARRAY_SIZE(il_desc_bezier_outline),
2983 vs_code_bezier_outline, sizeof(vs_code_bezier_outline)},
2984 {D2D_SHAPE_TYPE_TRIANGLE, il_desc_triangle, ARRAY_SIZE(il_desc_triangle),
2985 vs_code_triangle, sizeof(vs_code_triangle)},
2986 {D2D_SHAPE_TYPE_BEZIER, il_desc_bezier, ARRAY_SIZE(il_desc_bezier),
2987 vs_code_bezier, sizeof(vs_code_bezier)},
2989 static const struct
2991 float x, y;
2993 quad[] =
2995 {-1.0f, 1.0f},
2996 {-1.0f, -1.0f},
2997 { 1.0f, 1.0f},
2998 { 1.0f, -1.0f},
3000 static const UINT16 indices[] = {0, 1, 2, 2, 1, 3};
3001 float dpi_x, dpi_y;
3003 dpi_x = desc->dpiX;
3004 dpi_y = desc->dpiY;
3006 if (dpi_x == 0.0f && dpi_y == 0.0f)
3008 dpi_x = 96.0f;
3009 dpi_y = 96.0f;
3011 else if (dpi_x <= 0.0f || dpi_y <= 0.0f)
3012 return E_INVALIDARG;
3014 if (desc->type != D2D1_RENDER_TARGET_TYPE_DEFAULT && desc->type != D2D1_RENDER_TARGET_TYPE_HARDWARE)
3015 WARN("Ignoring render target type %#x.\n", desc->type);
3016 if (desc->usage != D2D1_RENDER_TARGET_USAGE_NONE)
3017 FIXME("Ignoring render target usage %#x.\n", desc->usage);
3018 if (desc->minLevel != D2D1_FEATURE_LEVEL_DEFAULT)
3019 WARN("Ignoring feature level %#x.\n", desc->minLevel);
3021 render_target->ID2D1RenderTarget_iface.lpVtbl = &d2d_d3d_render_target_vtbl;
3022 render_target->ID2D1GdiInteropRenderTarget_iface.lpVtbl = &d2d_gdi_interop_render_target_vtbl;
3023 render_target->IDWriteTextRenderer_iface.lpVtbl = &d2d_text_renderer_vtbl;
3024 render_target->refcount = 1;
3025 render_target->factory = factory;
3026 ID2D1Factory_AddRef(render_target->factory);
3028 render_target->outer_unknown = outer_unknown ? outer_unknown :
3029 (IUnknown *)&render_target->ID2D1RenderTarget_iface;
3031 if (FAILED(hr = IDXGISurface_GetDevice(surface, &IID_ID3D10Device, (void **)&render_target->device)))
3033 WARN("Failed to get device interface, hr %#x.\n", hr);
3034 ID2D1Factory_Release(render_target->factory);
3035 return hr;
3038 if (FAILED(hr = IDXGISurface_QueryInterface(surface, &IID_ID3D10Resource, (void **)&resource)))
3040 WARN("Failed to get ID3D10Resource interface, hr %#x.\n", hr);
3041 goto err;
3044 hr = ID3D10Device_CreateRenderTargetView(render_target->device, resource, NULL, &render_target->view);
3045 ID3D10Resource_Release(resource);
3046 if (FAILED(hr))
3048 WARN("Failed to create rendertarget view, hr %#x.\n", hr);
3049 goto err;
3052 if (FAILED(hr = D3D10StateBlockMaskEnableAll(&state_mask)))
3054 WARN("Failed to create stateblock mask, hr %#x.\n", hr);
3055 goto err;
3058 if (FAILED(hr = D3D10CreateStateBlock(render_target->device, &state_mask, &render_target->stateblock)))
3060 WARN("Failed to create stateblock, hr %#x.\n", hr);
3061 goto err;
3064 for (i = 0; i < ARRAY_SIZE(shape_info); ++i)
3066 const struct shape_info *si = &shape_info[i];
3068 if (FAILED(hr = ID3D10Device_CreateInputLayout(render_target->device, si->il_desc, si->il_element_count,
3069 si->vs_code, si->vs_code_size, &render_target->shape_resources[si->shape_type].il)))
3071 WARN("Failed to create input layout for shape type %#x, hr %#x.\n", si->shape_type, hr);
3072 goto err;
3075 if (FAILED(hr = ID3D10Device_CreateVertexShader(render_target->device, si->vs_code,
3076 si->vs_code_size, &render_target->shape_resources[si->shape_type].vs)))
3078 WARN("Failed to create vertex shader for shape type %#x, hr %#x.\n", si->shape_type, hr);
3079 goto err;
3084 if (FAILED(hr = ID3D10Device_CreatePixelShader(render_target->device,
3085 ps_code, sizeof(ps_code), &render_target->ps)))
3087 WARN("Failed to create pixel shader, hr %#x.\n", hr);
3088 goto err;
3091 buffer_desc.ByteWidth = sizeof(indices);
3092 buffer_desc.Usage = D3D10_USAGE_DEFAULT;
3093 buffer_desc.BindFlags = D3D10_BIND_INDEX_BUFFER;
3094 buffer_desc.CPUAccessFlags = 0;
3095 buffer_desc.MiscFlags = 0;
3097 buffer_data.pSysMem = indices;
3098 buffer_data.SysMemPitch = 0;
3099 buffer_data.SysMemSlicePitch = 0;
3101 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device,
3102 &buffer_desc, &buffer_data, &render_target->ib)))
3104 WARN("Failed to create clear index buffer, hr %#x.\n", hr);
3105 goto err;
3108 buffer_desc.ByteWidth = sizeof(quad);
3109 buffer_desc.BindFlags = D3D10_BIND_VERTEX_BUFFER;
3110 buffer_data.pSysMem = quad;
3112 render_target->vb_stride = sizeof(*quad);
3113 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device,
3114 &buffer_desc, &buffer_data, &render_target->vb)))
3116 WARN("Failed to create clear vertex buffer, hr %#x.\n", hr);
3117 goto err;
3120 rs_desc.FillMode = D3D10_FILL_SOLID;
3121 rs_desc.CullMode = D3D10_CULL_NONE;
3122 rs_desc.FrontCounterClockwise = FALSE;
3123 rs_desc.DepthBias = 0;
3124 rs_desc.DepthBiasClamp = 0.0f;
3125 rs_desc.SlopeScaledDepthBias = 0.0f;
3126 rs_desc.DepthClipEnable = TRUE;
3127 rs_desc.ScissorEnable = TRUE;
3128 rs_desc.MultisampleEnable = FALSE;
3129 rs_desc.AntialiasedLineEnable = FALSE;
3130 if (FAILED(hr = ID3D10Device_CreateRasterizerState(render_target->device, &rs_desc, &render_target->rs)))
3132 WARN("Failed to create clear rasterizer state, hr %#x.\n", hr);
3133 goto err;
3136 memset(&blend_desc, 0, sizeof(blend_desc));
3137 blend_desc.BlendEnable[0] = TRUE;
3138 blend_desc.SrcBlend = D3D10_BLEND_ONE;
3139 blend_desc.DestBlend = D3D10_BLEND_INV_SRC_ALPHA;
3140 blend_desc.BlendOp = D3D10_BLEND_OP_ADD;
3141 if (desc->pixelFormat.alphaMode == D2D1_ALPHA_MODE_IGNORE)
3143 blend_desc.SrcBlendAlpha = D3D10_BLEND_ZERO;
3144 blend_desc.DestBlendAlpha = D3D10_BLEND_ONE;
3146 else
3148 blend_desc.SrcBlendAlpha = D3D10_BLEND_ONE;
3149 blend_desc.DestBlendAlpha = D3D10_BLEND_INV_SRC_ALPHA;
3151 blend_desc.BlendOpAlpha = D3D10_BLEND_OP_ADD;
3152 blend_desc.RenderTargetWriteMask[0] = D3D10_COLOR_WRITE_ENABLE_ALL;
3153 if (FAILED(hr = ID3D10Device_CreateBlendState(render_target->device, &blend_desc, &render_target->bs)))
3155 WARN("Failed to create blend state, hr %#x.\n", hr);
3156 goto err;
3159 if (FAILED(hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED,
3160 &IID_IDWriteFactory, (IUnknown **)&dwrite_factory)))
3162 ERR("Failed to create dwrite factory, hr %#x.\n", hr);
3163 goto err;
3166 hr = IDWriteFactory_CreateRenderingParams(dwrite_factory, &render_target->default_text_rendering_params);
3167 IDWriteFactory_Release(dwrite_factory);
3168 if (FAILED(hr))
3170 ERR("Failed to create default text rendering parameters, hr %#x.\n", hr);
3171 goto err;
3174 if (FAILED(hr = IDXGISurface_GetDesc(surface, &surface_desc)))
3176 WARN("Failed to get surface desc, hr %#x.\n", hr);
3177 goto err;
3180 render_target->desc.pixelFormat = desc->pixelFormat;
3181 render_target->pixel_size.width = surface_desc.Width;
3182 render_target->pixel_size.height = surface_desc.Height;
3183 render_target->drawing_state.transform = identity;
3185 if (!d2d_clip_stack_init(&render_target->clip_stack))
3187 WARN("Failed to initialize clip stack.\n");
3188 hr = E_FAIL;
3189 goto err;
3192 render_target->desc.dpiX = dpi_x;
3193 render_target->desc.dpiY = dpi_y;
3195 return S_OK;
3197 err:
3198 if (render_target->default_text_rendering_params)
3199 IDWriteRenderingParams_Release(render_target->default_text_rendering_params);
3200 if (render_target->bs)
3201 ID3D10BlendState_Release(render_target->bs);
3202 if (render_target->rs)
3203 ID3D10RasterizerState_Release(render_target->rs);
3204 if (render_target->vb)
3205 ID3D10Buffer_Release(render_target->vb);
3206 if (render_target->ib)
3207 ID3D10Buffer_Release(render_target->ib);
3208 if (render_target->ps)
3209 ID3D10PixelShader_Release(render_target->ps);
3210 for (i = 0; i < D2D_SHAPE_TYPE_COUNT; ++i)
3212 if (render_target->shape_resources[i].vs)
3213 ID3D10VertexShader_Release(render_target->shape_resources[i].vs);
3214 if (render_target->shape_resources[i].il)
3215 ID3D10InputLayout_Release(render_target->shape_resources[i].il);
3217 if (render_target->stateblock)
3218 render_target->stateblock->lpVtbl->Release(render_target->stateblock);
3219 if (render_target->view)
3220 ID3D10RenderTargetView_Release(render_target->view);
3221 if (render_target->device)
3222 ID3D10Device_Release(render_target->device);
3223 ID2D1Factory_Release(render_target->factory);
3224 return hr;
3227 HRESULT d2d_d3d_create_render_target(ID2D1Factory *factory, IDXGISurface *surface, IUnknown *outer_unknown,
3228 const D2D1_RENDER_TARGET_PROPERTIES *desc, ID2D1RenderTarget **render_target)
3230 struct d2d_d3d_render_target *object;
3231 HRESULT hr;
3233 if (!(object = heap_alloc_zero(sizeof(*object))))
3234 return E_OUTOFMEMORY;
3236 if (FAILED(hr = d2d_d3d_render_target_init(object, factory, surface, outer_unknown, desc)))
3238 WARN("Failed to initialize render target, hr %#x.\n", hr);
3239 heap_free(object);
3240 return hr;
3243 TRACE("Created render target %p.\n", object);
3244 *render_target = &object->ID2D1RenderTarget_iface;
3246 return S_OK;
3249 HRESULT d2d_d3d_render_target_create_rtv(ID2D1RenderTarget *iface, IDXGISurface1 *surface)
3251 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
3252 DXGI_SURFACE_DESC surface_desc;
3253 ID3D10RenderTargetView *view;
3254 ID3D10Resource *resource;
3255 HRESULT hr;
3257 if (!surface)
3259 ID3D10RenderTargetView_Release(render_target->view);
3260 render_target->view = NULL;
3261 return S_OK;
3264 if (FAILED(hr = IDXGISurface1_GetDesc(surface, &surface_desc)))
3266 WARN("Failed to get surface desc, hr %#x.\n", hr);
3267 return hr;
3270 if (FAILED(hr = IDXGISurface1_QueryInterface(surface, &IID_ID3D10Resource, (void **)&resource)))
3272 WARN("Failed to get ID3D10Resource interface, hr %#x.\n", hr);
3273 return hr;
3276 hr = ID3D10Device_CreateRenderTargetView(render_target->device, resource, NULL, &view);
3277 ID3D10Resource_Release(resource);
3278 if (FAILED(hr))
3280 WARN("Failed to create rendertarget view, hr %#x.\n", hr);
3281 return hr;
3284 render_target->pixel_size.width = surface_desc.Width;
3285 render_target->pixel_size.height = surface_desc.Height;
3286 if (render_target->view)
3287 ID3D10RenderTargetView_Release(render_target->view);
3288 render_target->view = view;
3290 return S_OK;