comctl32: Fix a typo in comment.
[wine.git] / dlls / d2d1 / render_target.c
blob0c44014ae182870b5324f9c8baaa0fc91743d9e3
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 = HeapAlloc(GetProcessHeap(), 0, 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 HeapFree(GetProcessHeap(), 0, 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 (stack->count == stack->size)
100 D2D1_RECT_F *new_stack;
101 unsigned int new_size;
103 if (stack->size > UINT_MAX / 2)
104 return FALSE;
106 new_size = stack->size * 2;
107 if (!(new_stack = HeapReAlloc(GetProcessHeap(), 0, stack->stack, new_size * sizeof(*stack->stack))))
108 return FALSE;
110 stack->stack = new_stack;
111 stack->size = new_size;
114 r = *rect;
115 if (stack->count)
116 d2d_rect_intersect(&r, &stack->stack[stack->count - 1]);
117 stack->stack[stack->count++] = r;
119 return TRUE;
122 static void d2d_clip_stack_pop(struct d2d_clip_stack *stack)
124 if (!stack->count)
125 return;
126 --stack->count;
129 static void d2d_rt_draw(struct d2d_d3d_render_target *render_target, enum d2d_shape_type shape_type,
130 ID3D10Buffer *ib, unsigned int index_count, ID3D10Buffer *vb, unsigned int vb_stride,
131 ID3D10Buffer *vs_cb, ID3D10Buffer *ps_cb, struct d2d_brush *brush, struct d2d_brush *opacity_brush)
133 struct d2d_shape_resources *shape_resources = &render_target->shape_resources[shape_type];
134 ID3D10Device *device = render_target->device;
135 D3D10_RECT scissor_rect;
136 unsigned int offset;
137 D3D10_VIEWPORT vp;
138 HRESULT hr;
140 static const float blend_factor[] = {1.0f, 1.0f, 1.0f, 1.0f};
142 vp.TopLeftX = 0;
143 vp.TopLeftY = 0;
144 vp.Width = render_target->pixel_size.width;
145 vp.Height = render_target->pixel_size.height;
146 vp.MinDepth = 0.0f;
147 vp.MaxDepth = 1.0f;
149 if (FAILED(hr = render_target->stateblock->lpVtbl->Capture(render_target->stateblock)))
151 WARN("Failed to capture stateblock, hr %#x.\n", hr);
152 return;
155 ID3D10Device_ClearState(device);
157 ID3D10Device_IASetInputLayout(device, shape_resources->il);
158 ID3D10Device_IASetPrimitiveTopology(device, D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
159 ID3D10Device_IASetIndexBuffer(device, ib, DXGI_FORMAT_R16_UINT, 0);
160 offset = 0;
161 ID3D10Device_IASetVertexBuffers(device, 0, 1, &vb, &vb_stride, &offset);
162 ID3D10Device_VSSetConstantBuffers(device, 0, 1, &vs_cb);
163 ID3D10Device_VSSetShader(device, shape_resources->vs);
164 ID3D10Device_PSSetConstantBuffers(device, 0, 1, &ps_cb);
165 ID3D10Device_PSSetShader(device, render_target->ps);
166 ID3D10Device_RSSetViewports(device, 1, &vp);
167 if (render_target->clip_stack.count)
169 const D2D1_RECT_F *clip_rect;
171 clip_rect = &render_target->clip_stack.stack[render_target->clip_stack.count - 1];
172 scissor_rect.left = ceilf(clip_rect->left - 0.5f);
173 scissor_rect.top = ceilf(clip_rect->top - 0.5f);
174 scissor_rect.right = ceilf(clip_rect->right - 0.5f);
175 scissor_rect.bottom = ceilf(clip_rect->bottom - 0.5f);
177 else
179 scissor_rect.left = 0.0f;
180 scissor_rect.top = 0.0f;
181 scissor_rect.right = render_target->pixel_size.width;
182 scissor_rect.bottom = render_target->pixel_size.height;
184 ID3D10Device_RSSetScissorRects(device, 1, &scissor_rect);
185 ID3D10Device_RSSetState(device, render_target->rs);
186 ID3D10Device_OMSetRenderTargets(device, 1, &render_target->view, NULL);
187 if (brush)
189 ID3D10Device_OMSetBlendState(device, render_target->bs, blend_factor, D3D10_DEFAULT_SAMPLE_MASK);
190 d2d_brush_bind_resources(brush, device, 0);
192 if (opacity_brush)
193 d2d_brush_bind_resources(opacity_brush, device, 1);
195 if (ib)
196 ID3D10Device_DrawIndexed(device, index_count, 0, 0);
197 else
198 ID3D10Device_Draw(device, index_count, 0);
200 if (FAILED(hr = render_target->stateblock->lpVtbl->Apply(render_target->stateblock)))
201 WARN("Failed to apply stateblock, hr %#x.\n", hr);
204 static inline struct d2d_d3d_render_target *impl_from_ID2D1RenderTarget(ID2D1RenderTarget *iface)
206 return CONTAINING_RECORD(iface, struct d2d_d3d_render_target, ID2D1RenderTarget_iface);
209 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_QueryInterface(ID2D1RenderTarget *iface, REFIID iid, void **out)
211 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
213 TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
215 if (IsEqualGUID(iid, &IID_ID2D1RenderTarget)
216 || IsEqualGUID(iid, &IID_ID2D1Resource)
217 || IsEqualGUID(iid, &IID_IUnknown))
219 ID2D1RenderTarget_AddRef(iface);
220 *out = iface;
221 return S_OK;
223 else if (IsEqualGUID(iid, &IID_ID2D1GdiInteropRenderTarget))
225 ID2D1GdiInteropRenderTarget_AddRef(&render_target->ID2D1GdiInteropRenderTarget_iface);
226 *out = &render_target->ID2D1GdiInteropRenderTarget_iface;
227 return S_OK;
230 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
232 *out = NULL;
233 return E_NOINTERFACE;
236 static ULONG STDMETHODCALLTYPE d2d_d3d_render_target_AddRef(ID2D1RenderTarget *iface)
238 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
239 ULONG refcount = InterlockedIncrement(&render_target->refcount);
241 TRACE("%p increasing refcount to %u.\n", iface, refcount);
243 return refcount;
246 static ULONG STDMETHODCALLTYPE d2d_d3d_render_target_Release(ID2D1RenderTarget *iface)
248 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
249 ULONG refcount = InterlockedDecrement(&render_target->refcount);
251 TRACE("%p decreasing refcount to %u.\n", iface, refcount);
253 if (!refcount)
255 unsigned int i;
257 d2d_clip_stack_cleanup(&render_target->clip_stack);
258 IDWriteRenderingParams_Release(render_target->default_text_rendering_params);
259 if (render_target->text_rendering_params)
260 IDWriteRenderingParams_Release(render_target->text_rendering_params);
261 ID3D10BlendState_Release(render_target->bs);
262 ID3D10RasterizerState_Release(render_target->rs);
263 ID3D10Buffer_Release(render_target->vb);
264 ID3D10Buffer_Release(render_target->ib);
265 ID3D10PixelShader_Release(render_target->ps);
266 for (i = 0; i < D2D_SHAPE_TYPE_COUNT; ++i)
268 ID3D10VertexShader_Release(render_target->shape_resources[i].vs);
269 ID3D10InputLayout_Release(render_target->shape_resources[i].il);
271 render_target->stateblock->lpVtbl->Release(render_target->stateblock);
272 ID3D10RenderTargetView_Release(render_target->view);
273 ID3D10Device_Release(render_target->device);
274 ID2D1Factory_Release(render_target->factory);
275 HeapFree(GetProcessHeap(), 0, render_target);
278 return refcount;
281 static void STDMETHODCALLTYPE d2d_d3d_render_target_GetFactory(ID2D1RenderTarget *iface, ID2D1Factory **factory)
283 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
285 TRACE("iface %p, factory %p.\n", iface, factory);
287 *factory = render_target->factory;
288 ID2D1Factory_AddRef(*factory);
291 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateBitmap(ID2D1RenderTarget *iface,
292 D2D1_SIZE_U size, const void *src_data, UINT32 pitch, const D2D1_BITMAP_PROPERTIES *desc, ID2D1Bitmap **bitmap)
294 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
295 struct d2d_bitmap *object;
296 HRESULT hr;
298 TRACE("iface %p, size {%u, %u}, src_data %p, pitch %u, desc %p, bitmap %p.\n",
299 iface, size.width, size.height, src_data, pitch, desc, bitmap);
301 if (SUCCEEDED(hr = d2d_bitmap_create(render_target->factory, render_target->device, size, src_data, pitch, desc, &object)))
302 *bitmap = &object->ID2D1Bitmap_iface;
304 return hr;
307 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateBitmapFromWicBitmap(ID2D1RenderTarget *iface,
308 IWICBitmapSource *bitmap_source, const D2D1_BITMAP_PROPERTIES *desc, ID2D1Bitmap **bitmap)
310 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
311 struct d2d_bitmap *object;
312 HRESULT hr;
314 TRACE("iface %p, bitmap_source %p, desc %p, bitmap %p.\n",
315 iface, bitmap_source, desc, bitmap);
317 if (SUCCEEDED(hr = d2d_bitmap_create_from_wic_bitmap(render_target->factory, render_target->device, bitmap_source,
318 desc, &object)))
319 *bitmap = &object->ID2D1Bitmap_iface;
321 return hr;
324 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateSharedBitmap(ID2D1RenderTarget *iface,
325 REFIID iid, void *data, const D2D1_BITMAP_PROPERTIES *desc, ID2D1Bitmap **bitmap)
327 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
328 struct d2d_bitmap *object;
329 HRESULT hr;
331 TRACE("iface %p, iid %s, data %p, desc %p, bitmap %p.\n",
332 iface, debugstr_guid(iid), data, desc, bitmap);
334 if (SUCCEEDED(hr = d2d_bitmap_create_shared(iface, render_target->device, iid, data, desc, &object)))
335 *bitmap = &object->ID2D1Bitmap_iface;
337 return hr;
340 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateBitmapBrush(ID2D1RenderTarget *iface,
341 ID2D1Bitmap *bitmap, const D2D1_BITMAP_BRUSH_PROPERTIES *bitmap_brush_desc,
342 const D2D1_BRUSH_PROPERTIES *brush_desc, ID2D1BitmapBrush **brush)
344 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
345 struct d2d_brush *object;
346 HRESULT hr;
348 TRACE("iface %p, bitmap %p, bitmap_brush_desc %p, brush_desc %p, brush %p.\n",
349 iface, bitmap, bitmap_brush_desc, brush_desc, brush);
351 if (SUCCEEDED(hr = d2d_bitmap_brush_create(render_target->factory, bitmap, bitmap_brush_desc, brush_desc, &object)))
352 *brush = (ID2D1BitmapBrush *)&object->ID2D1Brush_iface;
354 return hr;
357 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateSolidColorBrush(ID2D1RenderTarget *iface,
358 const D2D1_COLOR_F *color, const D2D1_BRUSH_PROPERTIES *desc, ID2D1SolidColorBrush **brush)
360 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
361 struct d2d_brush *object;
362 HRESULT hr;
364 TRACE("iface %p, color %p, desc %p, brush %p.\n", iface, color, desc, brush);
366 if (SUCCEEDED(hr = d2d_solid_color_brush_create(render_target->factory, color, desc, &object)))
367 *brush = (ID2D1SolidColorBrush *)&object->ID2D1Brush_iface;
369 return hr;
372 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateGradientStopCollection(ID2D1RenderTarget *iface,
373 const D2D1_GRADIENT_STOP *stops, UINT32 stop_count, D2D1_GAMMA gamma, D2D1_EXTEND_MODE extend_mode,
374 ID2D1GradientStopCollection **gradient)
376 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
377 struct d2d_gradient *object;
378 HRESULT hr;
380 TRACE("iface %p, stops %p, stop_count %u, gamma %#x, extend_mode %#x, gradient %p.\n",
381 iface, stops, stop_count, gamma, extend_mode, gradient);
383 if (SUCCEEDED(hr = d2d_gradient_create(render_target->factory, render_target->device,
384 stops, stop_count, gamma, extend_mode, &object)))
385 *gradient = &object->ID2D1GradientStopCollection_iface;
387 return hr;
390 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateLinearGradientBrush(ID2D1RenderTarget *iface,
391 const D2D1_LINEAR_GRADIENT_BRUSH_PROPERTIES *gradient_brush_desc, const D2D1_BRUSH_PROPERTIES *brush_desc,
392 ID2D1GradientStopCollection *gradient, ID2D1LinearGradientBrush **brush)
394 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
395 struct d2d_brush *object;
396 HRESULT hr;
398 TRACE("iface %p, gradient_brush_desc %p, brush_desc %p, gradient %p, brush %p.\n",
399 iface, gradient_brush_desc, brush_desc, gradient, brush);
401 if (SUCCEEDED(hr = d2d_linear_gradient_brush_create(render_target->factory, gradient_brush_desc, brush_desc,
402 gradient, &object)))
403 *brush = (ID2D1LinearGradientBrush *)&object->ID2D1Brush_iface;
405 return hr;
408 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateRadialGradientBrush(ID2D1RenderTarget *iface,
409 const D2D1_RADIAL_GRADIENT_BRUSH_PROPERTIES *gradient_brush_desc, const D2D1_BRUSH_PROPERTIES *brush_desc,
410 ID2D1GradientStopCollection *gradient, ID2D1RadialGradientBrush **brush)
412 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
413 struct d2d_brush *object;
414 HRESULT hr;
416 TRACE("iface %p, gradient_brush_desc %p, brush_desc %p, gradient %p, brush %p.\n",
417 iface, gradient_brush_desc, brush_desc, gradient, brush);
419 if (SUCCEEDED(hr = d2d_radial_gradient_brush_create(render_target->factory,
420 gradient_brush_desc, brush_desc, gradient, &object)))
421 *brush = (ID2D1RadialGradientBrush *)&object->ID2D1Brush_iface;
423 return hr;
426 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateCompatibleRenderTarget(ID2D1RenderTarget *iface,
427 const D2D1_SIZE_F *size, const D2D1_SIZE_U *pixel_size, const D2D1_PIXEL_FORMAT *format,
428 D2D1_COMPATIBLE_RENDER_TARGET_OPTIONS options, ID2D1BitmapRenderTarget **rt)
430 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
431 struct d2d_bitmap_render_target *object;
432 HRESULT hr;
434 TRACE("iface %p, size %p, pixel_size %p, format %p, options %#x, render_target %p.\n",
435 iface, size, pixel_size, format, options, rt);
437 if (!(object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object))))
438 return E_OUTOFMEMORY;
440 if (FAILED(hr = d2d_bitmap_render_target_init(object, render_target, size, pixel_size,
441 format, options)))
443 WARN("Failed to initialize render target, hr %#x.\n", hr);
444 HeapFree(GetProcessHeap(), 0, object);
445 return hr;
448 TRACE("Created render target %p.\n", object);
449 *rt = &object->ID2D1BitmapRenderTarget_iface;
451 return S_OK;
454 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateLayer(ID2D1RenderTarget *iface,
455 const D2D1_SIZE_F *size, ID2D1Layer **layer)
457 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
458 struct d2d_layer *object;
459 HRESULT hr;
461 TRACE("iface %p, size %p, layer %p.\n", iface, size, layer);
463 if (SUCCEEDED(hr = d2d_layer_create(render_target->factory, size, &object)))
464 *layer = &object->ID2D1Layer_iface;
466 return hr;
469 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateMesh(ID2D1RenderTarget *iface, ID2D1Mesh **mesh)
471 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
472 struct d2d_mesh *object;
473 HRESULT hr;
475 TRACE("iface %p, mesh %p.\n", iface, mesh);
477 if (SUCCEEDED(hr = d2d_mesh_create(render_target->factory, &object)))
478 *mesh = &object->ID2D1Mesh_iface;
480 return hr;
483 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawLine(ID2D1RenderTarget *iface,
484 D2D1_POINT_2F p0, D2D1_POINT_2F p1, ID2D1Brush *brush, float stroke_width, ID2D1StrokeStyle *stroke_style)
486 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
487 ID2D1PathGeometry *geometry;
488 ID2D1GeometrySink *sink;
489 HRESULT hr;
491 TRACE("iface %p, p0 {%.8e, %.8e}, p1 {%.8e, %.8e}, brush %p, stroke_width %.8e, stroke_style %p.\n",
492 iface, p0.x, p0.y, p1.x, p1.y, brush, stroke_width, stroke_style);
494 if (FAILED(hr = ID2D1Factory_CreatePathGeometry(render_target->factory, &geometry)))
496 WARN("Failed to create path geometry, %#x.\n", hr);
497 return;
500 if (FAILED(hr = ID2D1PathGeometry_Open(geometry, &sink)))
502 WARN("Open() failed, %#x.\n", hr);
503 ID2D1PathGeometry_Release(geometry);
504 return;
507 ID2D1GeometrySink_BeginFigure(sink, p0, D2D1_FIGURE_BEGIN_HOLLOW);
508 ID2D1GeometrySink_AddLine(sink, p1);
509 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_OPEN);
510 if (FAILED(hr = ID2D1GeometrySink_Close(sink)))
511 WARN("Close() failed, %#x.\n", hr);
512 ID2D1GeometrySink_Release(sink);
514 ID2D1RenderTarget_DrawGeometry(iface, (ID2D1Geometry *)geometry, brush, stroke_width, stroke_style);
515 ID2D1PathGeometry_Release(geometry);
518 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawRectangle(ID2D1RenderTarget *iface,
519 const D2D1_RECT_F *rect, ID2D1Brush *brush, float stroke_width, ID2D1StrokeStyle *stroke_style)
521 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
522 ID2D1RectangleGeometry *geometry;
523 HRESULT hr;
525 TRACE("iface %p, rect %s, brush %p, stroke_width %.8e, stroke_style %p.\n",
526 iface, debug_d2d_rect_f(rect), brush, stroke_width, stroke_style);
528 if (FAILED(hr = ID2D1Factory_CreateRectangleGeometry(render_target->factory, rect, &geometry)))
530 ERR("Failed to create geometry, hr %#x.\n", hr);
531 return;
534 ID2D1RenderTarget_DrawGeometry(iface, (ID2D1Geometry *)geometry, brush, stroke_width, stroke_style);
535 ID2D1RectangleGeometry_Release(geometry);
538 static void STDMETHODCALLTYPE d2d_d3d_render_target_FillRectangle(ID2D1RenderTarget *iface,
539 const D2D1_RECT_F *rect, ID2D1Brush *brush)
541 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
542 ID2D1RectangleGeometry *geometry;
543 HRESULT hr;
545 TRACE("iface %p, rect %s, brush %p.\n", iface, debug_d2d_rect_f(rect), brush);
547 if (FAILED(hr = ID2D1Factory_CreateRectangleGeometry(render_target->factory, rect, &geometry)))
549 ERR("Failed to create geometry, hr %#x.\n", hr);
550 return;
553 ID2D1RenderTarget_FillGeometry(iface, (ID2D1Geometry *)geometry, brush, NULL);
554 ID2D1RectangleGeometry_Release(geometry);
557 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawRoundedRectangle(ID2D1RenderTarget *iface,
558 const D2D1_ROUNDED_RECT *rect, ID2D1Brush *brush, float stroke_width, ID2D1StrokeStyle *stroke_style)
560 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
561 ID2D1RoundedRectangleGeometry *geometry;
562 HRESULT hr;
564 TRACE("iface %p, rect %p, brush %p, stroke_width %.8e, stroke_style %p.\n",
565 iface, rect, brush, stroke_width, stroke_style);
567 if (FAILED(hr = ID2D1Factory_CreateRoundedRectangleGeometry(render_target->factory, rect, &geometry)))
569 ERR("Failed to create geometry, hr %#x.\n", hr);
570 return;
573 ID2D1RenderTarget_DrawGeometry(iface, (ID2D1Geometry *)geometry, brush, stroke_width, stroke_style);
574 ID2D1RoundedRectangleGeometry_Release(geometry);
577 static void STDMETHODCALLTYPE d2d_d3d_render_target_FillRoundedRectangle(ID2D1RenderTarget *iface,
578 const D2D1_ROUNDED_RECT *rect, ID2D1Brush *brush)
580 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
581 ID2D1RoundedRectangleGeometry *geometry;
582 HRESULT hr;
584 TRACE("iface %p, rect %p, brush %p.\n", iface, rect, brush);
586 if (FAILED(hr = ID2D1Factory_CreateRoundedRectangleGeometry(render_target->factory, rect, &geometry)))
588 ERR("Failed to create geometry, hr %#x.\n", hr);
589 return;
592 ID2D1RenderTarget_FillGeometry(iface, (ID2D1Geometry *)geometry, brush, NULL);
593 ID2D1RoundedRectangleGeometry_Release(geometry);
596 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawEllipse(ID2D1RenderTarget *iface,
597 const D2D1_ELLIPSE *ellipse, ID2D1Brush *brush, float stroke_width, ID2D1StrokeStyle *stroke_style)
599 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
600 ID2D1EllipseGeometry *geometry;
601 HRESULT hr;
603 TRACE("iface %p, ellipse %p, brush %p, stroke_width %.8e, stroke_style %p.\n",
604 iface, ellipse, brush, stroke_width, stroke_style);
606 if (FAILED(hr = ID2D1Factory_CreateEllipseGeometry(render_target->factory, ellipse, &geometry)))
608 ERR("Failed to create geometry, hr %#x.\n", hr);
609 return;
612 ID2D1RenderTarget_DrawGeometry(iface, (ID2D1Geometry *)geometry, brush, stroke_width, stroke_style);
613 ID2D1EllipseGeometry_Release(geometry);
616 static void STDMETHODCALLTYPE d2d_d3d_render_target_FillEllipse(ID2D1RenderTarget *iface,
617 const D2D1_ELLIPSE *ellipse, ID2D1Brush *brush)
619 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
620 ID2D1EllipseGeometry *geometry;
621 HRESULT hr;
623 TRACE("iface %p, ellipse %p, brush %p.\n", iface, ellipse, brush);
625 if (FAILED(hr = ID2D1Factory_CreateEllipseGeometry(render_target->factory, ellipse, &geometry)))
627 ERR("Failed to create geometry, hr %#x.\n", hr);
628 return;
631 ID2D1RenderTarget_FillGeometry(iface, (ID2D1Geometry *)geometry, brush, NULL);
632 ID2D1EllipseGeometry_Release(geometry);
635 static void d2d_rt_draw_geometry(struct d2d_d3d_render_target *render_target,
636 const struct d2d_geometry *geometry, struct d2d_brush *brush, float stroke_width)
638 ID3D10Buffer *ib, *vb, *vs_cb, *ps_cb;
639 D3D10_SUBRESOURCE_DATA buffer_data;
640 D3D10_BUFFER_DESC buffer_desc;
641 const D2D1_MATRIX_3X2_F *w;
642 float tmp_x, tmp_y;
643 HRESULT hr;
644 struct
646 struct
648 float _11, _21, _31, pad0;
649 float _12, _22, _32, stroke_width;
650 } transform_geometry;
651 struct d2d_vec4 transform_rtx;
652 struct d2d_vec4 transform_rty;
653 } vs_cb_data;
655 vs_cb_data.transform_geometry._11 = geometry->transform._11;
656 vs_cb_data.transform_geometry._21 = geometry->transform._21;
657 vs_cb_data.transform_geometry._31 = geometry->transform._31;
658 vs_cb_data.transform_geometry.pad0 = 0.0f;
659 vs_cb_data.transform_geometry._12 = geometry->transform._12;
660 vs_cb_data.transform_geometry._22 = geometry->transform._22;
661 vs_cb_data.transform_geometry._32 = geometry->transform._32;
662 vs_cb_data.transform_geometry.stroke_width = stroke_width;
664 w = &render_target->drawing_state.transform;
666 tmp_x = render_target->desc.dpiX / 96.0f;
667 vs_cb_data.transform_rtx.x = w->_11 * tmp_x;
668 vs_cb_data.transform_rtx.y = w->_21 * tmp_x;
669 vs_cb_data.transform_rtx.z = w->_31 * tmp_x;
670 vs_cb_data.transform_rtx.w = 2.0f / render_target->pixel_size.width;
672 tmp_y = render_target->desc.dpiY / 96.0f;
673 vs_cb_data.transform_rty.x = w->_12 * tmp_y;
674 vs_cb_data.transform_rty.y = w->_22 * tmp_y;
675 vs_cb_data.transform_rty.z = w->_32 * tmp_y;
676 vs_cb_data.transform_rty.w = -2.0f / render_target->pixel_size.height;
678 buffer_desc.ByteWidth = sizeof(vs_cb_data);
679 buffer_desc.Usage = D3D10_USAGE_DEFAULT;
680 buffer_desc.BindFlags = D3D10_BIND_CONSTANT_BUFFER;
681 buffer_desc.CPUAccessFlags = 0;
682 buffer_desc.MiscFlags = 0;
684 buffer_data.pSysMem = &vs_cb_data;
685 buffer_data.SysMemPitch = 0;
686 buffer_data.SysMemSlicePitch = 0;
688 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device, &buffer_desc, &buffer_data, &vs_cb)))
690 WARN("Failed to create constant buffer, hr %#x.\n", hr);
691 return;
694 if (FAILED(hr = d2d_brush_get_ps_cb(brush, NULL, TRUE, render_target, &ps_cb)))
696 WARN("Failed to get ps constant buffer, hr %#x.\n", hr);
697 ID3D10Buffer_Release(vs_cb);
698 return;
701 if (geometry->outline.face_count)
703 buffer_desc.ByteWidth = geometry->outline.face_count * sizeof(*geometry->outline.faces);
704 buffer_desc.BindFlags = D3D10_BIND_INDEX_BUFFER;
705 buffer_data.pSysMem = geometry->outline.faces;
707 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device, &buffer_desc, &buffer_data, &ib)))
709 WARN("Failed to create index buffer, hr %#x.\n", hr);
710 goto done;
713 buffer_desc.ByteWidth = geometry->outline.vertex_count * sizeof(*geometry->outline.vertices);
714 buffer_desc.BindFlags = D3D10_BIND_VERTEX_BUFFER;
715 buffer_data.pSysMem = geometry->outline.vertices;
717 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device, &buffer_desc, &buffer_data, &vb)))
719 ERR("Failed to create vertex buffer, hr %#x.\n", hr);
720 ID3D10Buffer_Release(ib);
721 goto done;
724 d2d_rt_draw(render_target, D2D_SHAPE_TYPE_OUTLINE, ib, 3 * geometry->outline.face_count, vb,
725 sizeof(*geometry->outline.vertices), vs_cb, ps_cb, brush, NULL);
727 ID3D10Buffer_Release(vb);
728 ID3D10Buffer_Release(ib);
731 if (geometry->outline.bezier_face_count)
733 buffer_desc.ByteWidth = geometry->outline.bezier_face_count * sizeof(*geometry->outline.bezier_faces);
734 buffer_desc.BindFlags = D3D10_BIND_INDEX_BUFFER;
735 buffer_data.pSysMem = geometry->outline.bezier_faces;
737 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device, &buffer_desc, &buffer_data, &ib)))
739 WARN("Failed to create beziers index buffer, hr %#x.\n", hr);
740 goto done;
743 buffer_desc.ByteWidth = geometry->outline.bezier_count * sizeof(*geometry->outline.beziers);
744 buffer_desc.BindFlags = D3D10_BIND_VERTEX_BUFFER;
745 buffer_data.pSysMem = geometry->outline.beziers;
747 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device, &buffer_desc, &buffer_data, &vb)))
749 ERR("Failed to create beziers vertex buffer, hr %#x.\n", hr);
750 ID3D10Buffer_Release(ib);
751 goto done;
754 d2d_rt_draw(render_target, D2D_SHAPE_TYPE_BEZIER_OUTLINE, ib, 3 * geometry->outline.bezier_face_count, vb,
755 sizeof(*geometry->outline.beziers), vs_cb, ps_cb, brush, NULL);
757 ID3D10Buffer_Release(vb);
758 ID3D10Buffer_Release(ib);
761 done:
762 ID3D10Buffer_Release(ps_cb);
763 ID3D10Buffer_Release(vs_cb);
766 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawGeometry(ID2D1RenderTarget *iface,
767 ID2D1Geometry *geometry, ID2D1Brush *brush, float stroke_width, ID2D1StrokeStyle *stroke_style)
769 const struct d2d_geometry *geometry_impl = unsafe_impl_from_ID2D1Geometry(geometry);
770 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
771 struct d2d_brush *brush_impl = unsafe_impl_from_ID2D1Brush(brush);
773 TRACE("iface %p, geometry %p, brush %p, stroke_width %.8e, stroke_style %p.\n",
774 iface, geometry, brush, stroke_width, stroke_style);
776 if (stroke_style)
777 FIXME("Ignoring stroke style %p.\n", stroke_style);
779 d2d_rt_draw_geometry(render_target, geometry_impl, brush_impl, stroke_width);
782 static void d2d_rt_fill_geometry(struct d2d_d3d_render_target *render_target,
783 const struct d2d_geometry *geometry, struct d2d_brush *brush, struct d2d_brush *opacity_brush)
785 ID3D10Buffer *ib, *vb, *vs_cb, *ps_cb;
786 D3D10_SUBRESOURCE_DATA buffer_data;
787 D3D10_BUFFER_DESC buffer_desc;
788 D2D1_MATRIX_3X2_F *w;
789 float tmp_x, tmp_y;
790 HRESULT hr;
791 struct
793 struct
795 float _11, _21, _31, pad0;
796 float _12, _22, _32, pad1;
797 } transform_geometry;
798 struct d2d_vec4 transform_rtx;
799 struct d2d_vec4 transform_rty;
800 } vs_cb_data;
802 vs_cb_data.transform_geometry._11 = geometry->transform._11;
803 vs_cb_data.transform_geometry._21 = geometry->transform._21;
804 vs_cb_data.transform_geometry._31 = geometry->transform._31;
805 vs_cb_data.transform_geometry.pad0 = 0.0f;
806 vs_cb_data.transform_geometry._12 = geometry->transform._12;
807 vs_cb_data.transform_geometry._22 = geometry->transform._22;
808 vs_cb_data.transform_geometry._32 = geometry->transform._32;
809 vs_cb_data.transform_geometry.pad1 = 0.0f;
811 w = &render_target->drawing_state.transform;
813 tmp_x = render_target->desc.dpiX / 96.0f;
814 vs_cb_data.transform_rtx.x = w->_11 * tmp_x;
815 vs_cb_data.transform_rtx.y = w->_21 * tmp_x;
816 vs_cb_data.transform_rtx.z = w->_31 * tmp_x;
817 vs_cb_data.transform_rtx.w = 2.0f / render_target->pixel_size.width;
819 tmp_y = render_target->desc.dpiY / 96.0f;
820 vs_cb_data.transform_rty.x = w->_12 * tmp_y;
821 vs_cb_data.transform_rty.y = w->_22 * tmp_y;
822 vs_cb_data.transform_rty.z = w->_32 * tmp_y;
823 vs_cb_data.transform_rty.w = -2.0f / render_target->pixel_size.height;
825 buffer_desc.ByteWidth = sizeof(vs_cb_data);
826 buffer_desc.Usage = D3D10_USAGE_DEFAULT;
827 buffer_desc.BindFlags = D3D10_BIND_CONSTANT_BUFFER;
828 buffer_desc.CPUAccessFlags = 0;
829 buffer_desc.MiscFlags = 0;
831 buffer_data.pSysMem = &vs_cb_data;
832 buffer_data.SysMemPitch = 0;
833 buffer_data.SysMemSlicePitch = 0;
835 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device, &buffer_desc, &buffer_data, &vs_cb)))
837 WARN("Failed to create constant buffer, hr %#x.\n", hr);
838 return;
841 if (FAILED(hr = d2d_brush_get_ps_cb(brush, opacity_brush, FALSE, render_target, &ps_cb)))
843 WARN("Failed to get ps constant buffer, hr %#x.\n", hr);
844 ID3D10Buffer_Release(vs_cb);
845 return;
848 if (geometry->fill.face_count)
850 buffer_desc.ByteWidth = geometry->fill.face_count * sizeof(*geometry->fill.faces);
851 buffer_desc.BindFlags = D3D10_BIND_INDEX_BUFFER;
852 buffer_data.pSysMem = geometry->fill.faces;
854 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device, &buffer_desc, &buffer_data, &ib)))
856 WARN("Failed to create index buffer, hr %#x.\n", hr);
857 goto done;
860 buffer_desc.ByteWidth = geometry->fill.vertex_count * sizeof(*geometry->fill.vertices);
861 buffer_desc.BindFlags = D3D10_BIND_VERTEX_BUFFER;
862 buffer_data.pSysMem = geometry->fill.vertices;
864 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device, &buffer_desc, &buffer_data, &vb)))
866 ERR("Failed to create vertex buffer, hr %#x.\n", hr);
867 ID3D10Buffer_Release(ib);
868 goto done;
871 d2d_rt_draw(render_target, D2D_SHAPE_TYPE_TRIANGLE, ib, 3 * geometry->fill.face_count, vb,
872 sizeof(*geometry->fill.vertices), vs_cb, ps_cb, brush, opacity_brush);
874 ID3D10Buffer_Release(vb);
875 ID3D10Buffer_Release(ib);
878 if (geometry->fill.bezier_vertex_count)
880 buffer_desc.ByteWidth = geometry->fill.bezier_vertex_count * sizeof(*geometry->fill.bezier_vertices);
881 buffer_data.pSysMem = geometry->fill.bezier_vertices;
883 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device, &buffer_desc, &buffer_data, &vb)))
885 ERR("Failed to create beziers vertex buffer, hr %#x.\n", hr);
886 goto done;
889 d2d_rt_draw(render_target, D2D_SHAPE_TYPE_BEZIER, NULL, geometry->fill.bezier_vertex_count, vb,
890 sizeof(*geometry->fill.bezier_vertices), vs_cb, ps_cb, brush, opacity_brush);
892 ID3D10Buffer_Release(vb);
895 done:
896 ID3D10Buffer_Release(ps_cb);
897 ID3D10Buffer_Release(vs_cb);
900 static void STDMETHODCALLTYPE d2d_d3d_render_target_FillGeometry(ID2D1RenderTarget *iface,
901 ID2D1Geometry *geometry, ID2D1Brush *brush, ID2D1Brush *opacity_brush)
903 const struct d2d_geometry *geometry_impl = unsafe_impl_from_ID2D1Geometry(geometry);
904 struct d2d_brush *opacity_brush_impl = unsafe_impl_from_ID2D1Brush(opacity_brush);
905 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
906 struct d2d_brush *brush_impl = unsafe_impl_from_ID2D1Brush(brush);
908 TRACE("iface %p, geometry %p, brush %p, opacity_brush %p.\n", iface, geometry, brush, opacity_brush);
910 if (FAILED(render_target->error.code))
911 return;
913 if (opacity_brush && brush_impl->type != D2D_BRUSH_TYPE_BITMAP)
915 render_target->error.code = D2DERR_INCOMPATIBLE_BRUSH_TYPES;
916 render_target->error.tag1 = render_target->drawing_state.tag1;
917 render_target->error.tag2 = render_target->drawing_state.tag2;
918 return;
921 d2d_rt_fill_geometry(render_target, geometry_impl, brush_impl, opacity_brush_impl);
924 static void STDMETHODCALLTYPE d2d_d3d_render_target_FillMesh(ID2D1RenderTarget *iface,
925 ID2D1Mesh *mesh, ID2D1Brush *brush)
927 FIXME("iface %p, mesh %p, brush %p stub!\n", iface, mesh, brush);
930 static void STDMETHODCALLTYPE d2d_d3d_render_target_FillOpacityMask(ID2D1RenderTarget *iface,
931 ID2D1Bitmap *mask, ID2D1Brush *brush, D2D1_OPACITY_MASK_CONTENT content,
932 const D2D1_RECT_F *dst_rect, const D2D1_RECT_F *src_rect)
934 FIXME("iface %p, mask %p, brush %p, content %#x, dst_rect %s, src_rect %s stub!\n",
935 iface, mask, brush, content, debug_d2d_rect_f(dst_rect), debug_d2d_rect_f(src_rect));
938 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawBitmap(ID2D1RenderTarget *iface,
939 ID2D1Bitmap *bitmap, const D2D1_RECT_F *dst_rect, float opacity,
940 D2D1_BITMAP_INTERPOLATION_MODE interpolation_mode, const D2D1_RECT_F *src_rect)
942 D2D1_BITMAP_BRUSH_PROPERTIES bitmap_brush_desc;
943 D2D1_BRUSH_PROPERTIES brush_desc;
944 ID2D1BitmapBrush *brush;
945 D2D1_RECT_F s, d;
946 HRESULT hr;
948 TRACE("iface %p, bitmap %p, dst_rect %s, opacity %.8e, interpolation_mode %#x, src_rect %s.\n",
949 iface, bitmap, debug_d2d_rect_f(dst_rect), opacity, interpolation_mode, debug_d2d_rect_f(src_rect));
951 if (src_rect)
953 s = *src_rect;
955 else
957 D2D1_SIZE_F size;
959 size = ID2D1Bitmap_GetSize(bitmap);
960 s.left = 0.0f;
961 s.top = 0.0f;
962 s.right = size.width;
963 s.bottom = size.height;
966 if (dst_rect)
968 d = *dst_rect;
970 else
972 d.left = 0.0f;
973 d.top = 0.0f;
974 d.right = s.right - s.left;
975 d.bottom = s.bottom - s.top;
978 bitmap_brush_desc.extendModeX = D2D1_EXTEND_MODE_CLAMP;
979 bitmap_brush_desc.extendModeY = D2D1_EXTEND_MODE_CLAMP;
980 bitmap_brush_desc.interpolationMode = interpolation_mode;
982 brush_desc.opacity = opacity;
983 brush_desc.transform._11 = fabsf((d.right - d.left) / (s.right - s.left));
984 brush_desc.transform._21 = 0.0f;
985 brush_desc.transform._31 = min(d.left, d.right) - min(s.left, s.right) * brush_desc.transform._11;
986 brush_desc.transform._12 = 0.0f;
987 brush_desc.transform._22 = fabsf((d.bottom - d.top) / (s.bottom - s.top));
988 brush_desc.transform._32 = min(d.top, d.bottom) - min(s.top, s.bottom) * brush_desc.transform._22;
990 if (FAILED(hr = ID2D1RenderTarget_CreateBitmapBrush(iface, bitmap, &bitmap_brush_desc, &brush_desc, &brush)))
992 ERR("Failed to create bitmap brush, hr %#x.\n", hr);
993 return;
996 ID2D1RenderTarget_FillRectangle(iface, &d, (ID2D1Brush *)brush);
997 ID2D1BitmapBrush_Release(brush);
1000 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawText(ID2D1RenderTarget *iface,
1001 const WCHAR *string, UINT32 string_len, IDWriteTextFormat *text_format, const D2D1_RECT_F *layout_rect,
1002 ID2D1Brush *brush, D2D1_DRAW_TEXT_OPTIONS options, DWRITE_MEASURING_MODE measuring_mode)
1004 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1005 IDWriteTextLayout *text_layout;
1006 IDWriteFactory *dwrite_factory;
1007 D2D1_POINT_2F origin;
1008 HRESULT hr;
1010 TRACE("iface %p, string %s, string_len %u, text_format %p, layout_rect %s, "
1011 "brush %p, options %#x, measuring_mode %#x.\n",
1012 iface, debugstr_wn(string, string_len), string_len, text_format, debug_d2d_rect_f(layout_rect),
1013 brush, options, measuring_mode);
1015 if (FAILED(hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED,
1016 &IID_IDWriteFactory, (IUnknown **)&dwrite_factory)))
1018 ERR("Failed to create dwrite factory, hr %#x.\n", hr);
1019 return;
1022 if (measuring_mode == DWRITE_MEASURING_MODE_NATURAL)
1023 hr = IDWriteFactory_CreateTextLayout(dwrite_factory, string, string_len, text_format,
1024 layout_rect->right - layout_rect->left, layout_rect->bottom - layout_rect->top, &text_layout);
1025 else
1026 hr = IDWriteFactory_CreateGdiCompatibleTextLayout(dwrite_factory, string, string_len, text_format,
1027 layout_rect->right - layout_rect->left, layout_rect->bottom - layout_rect->top, render_target->desc.dpiX / 96.0f,
1028 (DWRITE_MATRIX*)&render_target->drawing_state.transform, measuring_mode == DWRITE_MEASURING_MODE_GDI_NATURAL, &text_layout);
1029 IDWriteFactory_Release(dwrite_factory);
1030 if (FAILED(hr))
1032 ERR("Failed to create text layout, hr %#x.\n", hr);
1033 return;
1036 d2d_point_set(&origin, layout_rect->left, layout_rect->top);
1037 ID2D1RenderTarget_DrawTextLayout(iface, origin, text_layout, brush, options);
1038 IDWriteTextLayout_Release(text_layout);
1041 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawTextLayout(ID2D1RenderTarget *iface,
1042 D2D1_POINT_2F origin, IDWriteTextLayout *layout, ID2D1Brush *brush, D2D1_DRAW_TEXT_OPTIONS options)
1044 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1045 struct d2d_draw_text_layout_ctx ctx;
1046 HRESULT hr;
1048 TRACE("iface %p, origin {%.8e, %.8e}, layout %p, brush %p, options %#x.\n",
1049 iface, origin.x, origin.y, layout, brush, options);
1051 ctx.brush = brush;
1052 ctx.options = options;
1054 if (FAILED(hr = IDWriteTextLayout_Draw(layout,
1055 &ctx, &render_target->IDWriteTextRenderer_iface, origin.x, origin.y)))
1056 FIXME("Failed to draw text layout, hr %#x.\n", hr);
1059 static D2D1_ANTIALIAS_MODE d2d_d3d_render_target_set_aa_mode_from_text_aa_mode(struct d2d_d3d_render_target *rt)
1061 D2D1_ANTIALIAS_MODE prev_antialias_mode = rt->drawing_state.antialiasMode;
1062 rt->drawing_state.antialiasMode = rt->drawing_state.textAntialiasMode == D2D1_TEXT_ANTIALIAS_MODE_ALIASED ?
1063 D2D1_ANTIALIAS_MODE_ALIASED : D2D1_ANTIALIAS_MODE_PER_PRIMITIVE;
1064 return prev_antialias_mode;
1067 static void d2d_rt_draw_glyph_run_outline(struct d2d_d3d_render_target *render_target,
1068 D2D1_POINT_2F baseline_origin, const DWRITE_GLYPH_RUN *glyph_run, ID2D1Brush *brush)
1070 D2D1_MATRIX_3X2_F *transform, prev_transform;
1071 D2D1_ANTIALIAS_MODE prev_antialias_mode;
1072 ID2D1PathGeometry *geometry;
1073 ID2D1GeometrySink *sink;
1074 HRESULT hr;
1076 if (FAILED(hr = ID2D1Factory_CreatePathGeometry(render_target->factory, &geometry)))
1078 ERR("Failed to create geometry, hr %#x.\n", hr);
1079 return;
1082 if (FAILED(hr = ID2D1PathGeometry_Open(geometry, &sink)))
1084 ERR("Failed to open geometry sink, hr %#x.\n", hr);
1085 ID2D1PathGeometry_Release(geometry);
1086 return;
1089 if (FAILED(hr = IDWriteFontFace_GetGlyphRunOutline(glyph_run->fontFace, glyph_run->fontEmSize,
1090 glyph_run->glyphIndices, glyph_run->glyphAdvances, glyph_run->glyphOffsets, glyph_run->glyphCount,
1091 glyph_run->isSideways, glyph_run->bidiLevel & 1, (IDWriteGeometrySink *)sink)))
1093 ERR("Failed to get glyph run outline, hr %#x.\n", hr);
1094 ID2D1GeometrySink_Release(sink);
1095 ID2D1PathGeometry_Release(geometry);
1096 return;
1099 if (FAILED(hr = ID2D1GeometrySink_Close(sink)))
1100 ERR("Failed to close geometry sink, hr %#x.\n", hr);
1101 ID2D1GeometrySink_Release(sink);
1103 transform = &render_target->drawing_state.transform;
1104 prev_transform = *transform;
1105 transform->_31 += baseline_origin.x * transform->_11 + baseline_origin.y * transform->_21;
1106 transform->_32 += baseline_origin.x * transform->_12 + baseline_origin.y * transform->_22;
1107 prev_antialias_mode = d2d_d3d_render_target_set_aa_mode_from_text_aa_mode(render_target);
1108 d2d_rt_fill_geometry(render_target, unsafe_impl_from_ID2D1Geometry((ID2D1Geometry *)geometry),
1109 unsafe_impl_from_ID2D1Brush(brush), NULL);
1110 render_target->drawing_state.antialiasMode = prev_antialias_mode;
1111 *transform = prev_transform;
1113 ID2D1PathGeometry_Release(geometry);
1116 static void d2d_rt_draw_glyph_run_bitmap(struct d2d_d3d_render_target *render_target,
1117 D2D1_POINT_2F baseline_origin, const DWRITE_GLYPH_RUN *glyph_run, ID2D1Brush *brush,
1118 float ppd, DWRITE_RENDERING_MODE rendering_mode, DWRITE_MEASURING_MODE measuring_mode,
1119 DWRITE_TEXT_ANTIALIAS_MODE antialias_mode)
1121 D2D1_MATRIX_3X2_F prev_transform, *transform;
1122 ID2D1RectangleGeometry *geometry = NULL;
1123 ID2D1BitmapBrush *opacity_brush = NULL;
1124 D2D1_BITMAP_PROPERTIES bitmap_desc;
1125 ID2D1Bitmap *opacity_bitmap = NULL;
1126 IDWriteGlyphRunAnalysis *analysis;
1127 DWRITE_TEXTURE_TYPE texture_type;
1128 D2D1_BRUSH_PROPERTIES brush_desc;
1129 IDWriteFactory2 *dwrite_factory;
1130 DWRITE_GLYPH_RUN scaled_run;
1131 void *opacity_values = NULL;
1132 size_t opacity_values_size;
1133 D2D1_SIZE_U bitmap_size;
1134 D2D1_RECT_F run_rect;
1135 RECT bounds;
1136 HRESULT hr;
1138 if (FAILED(hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED,
1139 &IID_IDWriteFactory2, (IUnknown **)&dwrite_factory)))
1141 ERR("Failed to create dwrite factory, hr %#x.\n", hr);
1142 return;
1145 scaled_run = *glyph_run;
1146 scaled_run.fontEmSize *= ppd;
1147 hr = IDWriteFactory2_CreateGlyphRunAnalysis(dwrite_factory, &scaled_run,
1148 (DWRITE_MATRIX *)&render_target->drawing_state.transform, rendering_mode, measuring_mode,
1149 DWRITE_GRID_FIT_MODE_DEFAULT, antialias_mode, baseline_origin.x,
1150 baseline_origin.y, &analysis);
1151 IDWriteFactory2_Release(dwrite_factory);
1152 if (FAILED(hr))
1154 ERR("Failed to create glyph run analysis, hr %#x.\n", hr);
1155 return;
1158 if (rendering_mode == DWRITE_RENDERING_MODE_ALIASED || antialias_mode == DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE)
1159 texture_type = DWRITE_TEXTURE_ALIASED_1x1;
1160 else
1161 texture_type = DWRITE_TEXTURE_CLEARTYPE_3x1;
1163 if (FAILED(hr = IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis, texture_type, &bounds)))
1165 ERR("Failed to get alpha texture bounds, hr %#x.\n", hr);
1166 goto done;
1169 d2d_size_set(&bitmap_size, bounds.right - bounds.left, bounds.bottom - bounds.top);
1170 if (!bitmap_size.width || !bitmap_size.height)
1172 /* Empty run, nothing to do. */
1173 goto done;
1176 if (texture_type == DWRITE_TEXTURE_CLEARTYPE_3x1)
1177 bitmap_size.width *= 3;
1178 opacity_values_size = bitmap_size.width * bitmap_size.height;
1179 if (!(opacity_values = HeapAlloc(GetProcessHeap(), 0, opacity_values_size)))
1181 ERR("Failed to allocate opacity values.\n");
1182 goto done;
1185 if (FAILED(hr = IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis,
1186 texture_type, &bounds, opacity_values, opacity_values_size)))
1188 ERR("Failed to create alpha texture, hr %#x.\n", hr);
1189 goto done;
1192 bitmap_desc.pixelFormat.format = DXGI_FORMAT_A8_UNORM;
1193 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
1194 bitmap_desc.dpiX = render_target->desc.dpiX;
1195 if (texture_type == DWRITE_TEXTURE_CLEARTYPE_3x1)
1196 bitmap_desc.dpiX *= 3.0f;
1197 bitmap_desc.dpiY = render_target->desc.dpiY;
1198 if (FAILED(hr = d2d_d3d_render_target_CreateBitmap(&render_target->ID2D1RenderTarget_iface,
1199 bitmap_size, opacity_values, bitmap_size.width, &bitmap_desc, &opacity_bitmap)))
1201 ERR("Failed to create opacity bitmap, hr %#x.\n", hr);
1202 goto done;
1205 brush_desc.opacity = 1.0f;
1206 brush_desc.transform._11 = 1.0f;
1207 brush_desc.transform._12 = 0.0f;
1208 brush_desc.transform._21 = 0.0f;
1209 brush_desc.transform._22 = 1.0f;
1210 brush_desc.transform._31 = bounds.left;
1211 brush_desc.transform._32 = bounds.top;
1212 if (FAILED(hr = d2d_d3d_render_target_CreateBitmapBrush(&render_target->ID2D1RenderTarget_iface,
1213 opacity_bitmap, NULL, &brush_desc, &opacity_brush)))
1215 ERR("Failed to create opacity bitmap brush, hr %#x.\n", hr);
1216 goto done;
1219 d2d_rect_set(&run_rect, bounds.left, bounds.top, bounds.right, bounds.bottom);
1220 if (FAILED(hr = ID2D1Factory_CreateRectangleGeometry(render_target->factory, &run_rect, &geometry)))
1222 ERR("Failed to create geometry, hr %#x.\n", hr);
1223 goto done;
1226 transform = &render_target->drawing_state.transform;
1227 prev_transform = *transform;
1228 *transform = identity;
1229 d2d_rt_fill_geometry(render_target, unsafe_impl_from_ID2D1Geometry((ID2D1Geometry *)geometry),
1230 unsafe_impl_from_ID2D1Brush(brush), unsafe_impl_from_ID2D1Brush((ID2D1Brush *)opacity_brush));
1231 *transform = prev_transform;
1233 done:
1234 if (geometry)
1235 ID2D1RectangleGeometry_Release(geometry);
1236 if (opacity_brush)
1237 ID2D1BitmapBrush_Release(opacity_brush);
1238 if (opacity_bitmap)
1239 ID2D1Bitmap_Release(opacity_bitmap);
1240 HeapFree(GetProcessHeap(), 0, opacity_values);
1241 IDWriteGlyphRunAnalysis_Release(analysis);
1244 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawGlyphRun(ID2D1RenderTarget *iface,
1245 D2D1_POINT_2F baseline_origin, const DWRITE_GLYPH_RUN *glyph_run, ID2D1Brush *brush,
1246 DWRITE_MEASURING_MODE measuring_mode)
1248 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1249 DWRITE_TEXT_ANTIALIAS_MODE antialias_mode = DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE;
1250 IDWriteRenderingParams *rendering_params;
1251 DWRITE_RENDERING_MODE rendering_mode;
1252 HRESULT hr;
1253 float ppd;
1255 TRACE("iface %p, baseline_origin {%.8e, %.8e}, glyph_run %p, brush %p, measuring_mode %#x.\n",
1256 iface, baseline_origin.x, baseline_origin.y, glyph_run, brush, measuring_mode);
1258 rendering_params = render_target->text_rendering_params ? render_target->text_rendering_params
1259 : render_target->default_text_rendering_params;
1261 rendering_mode = IDWriteRenderingParams_GetRenderingMode(rendering_params);
1263 switch (render_target->drawing_state.textAntialiasMode)
1265 case D2D1_TEXT_ANTIALIAS_MODE_ALIASED:
1266 if (rendering_mode == DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL
1267 || rendering_mode == DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC
1268 || rendering_mode == DWRITE_RENDERING_MODE_CLEARTYPE_GDI_NATURAL
1269 || rendering_mode == DWRITE_RENDERING_MODE_CLEARTYPE_GDI_CLASSIC)
1271 render_target->error.code = E_INVALIDARG;
1273 break;
1274 case D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE:
1275 if (rendering_mode == DWRITE_RENDERING_MODE_ALIASED
1276 || rendering_mode == DWRITE_RENDERING_MODE_OUTLINE)
1278 render_target->error.code = E_INVALIDARG;
1280 break;
1281 case D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE:
1282 if (rendering_mode == DWRITE_RENDERING_MODE_ALIASED)
1283 render_target->error.code = E_INVALIDARG;
1284 break;
1285 default:
1289 if (FAILED(render_target->error.code))
1290 return;
1292 rendering_mode = DWRITE_RENDERING_MODE_DEFAULT;
1293 switch (render_target->drawing_state.textAntialiasMode)
1295 case D2D1_TEXT_ANTIALIAS_MODE_DEFAULT:
1296 if (IDWriteRenderingParams_GetClearTypeLevel(rendering_params) > 0.0f)
1297 antialias_mode = DWRITE_TEXT_ANTIALIAS_MODE_CLEARTYPE;
1298 break;
1299 case D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE:
1300 antialias_mode = DWRITE_TEXT_ANTIALIAS_MODE_CLEARTYPE;
1301 break;
1302 case D2D1_TEXT_ANTIALIAS_MODE_ALIASED:
1303 rendering_mode = DWRITE_RENDERING_MODE_ALIASED;
1304 break;
1305 default:
1309 ppd = max(render_target->desc.dpiX, render_target->desc.dpiY) / 96.0f;
1310 if (rendering_mode == DWRITE_RENDERING_MODE_DEFAULT)
1312 if (FAILED(hr = IDWriteFontFace_GetRecommendedRenderingMode(glyph_run->fontFace, glyph_run->fontEmSize,
1313 ppd, measuring_mode, rendering_params, &rendering_mode)))
1315 ERR("Failed to get recommended rendering mode, hr %#x.\n", hr);
1316 rendering_mode = DWRITE_RENDERING_MODE_OUTLINE;
1320 if (rendering_mode == DWRITE_RENDERING_MODE_OUTLINE)
1321 d2d_rt_draw_glyph_run_outline(render_target, baseline_origin, glyph_run, brush);
1322 else
1323 d2d_rt_draw_glyph_run_bitmap(render_target, baseline_origin, glyph_run, brush,
1324 ppd, rendering_mode, measuring_mode, antialias_mode);
1327 static void STDMETHODCALLTYPE d2d_d3d_render_target_SetTransform(ID2D1RenderTarget *iface,
1328 const D2D1_MATRIX_3X2_F *transform)
1330 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1332 TRACE("iface %p, transform %p.\n", iface, transform);
1334 render_target->drawing_state.transform = *transform;
1337 static void STDMETHODCALLTYPE d2d_d3d_render_target_GetTransform(ID2D1RenderTarget *iface,
1338 D2D1_MATRIX_3X2_F *transform)
1340 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1342 TRACE("iface %p, transform %p.\n", iface, transform);
1344 *transform = render_target->drawing_state.transform;
1347 static void STDMETHODCALLTYPE d2d_d3d_render_target_SetAntialiasMode(ID2D1RenderTarget *iface,
1348 D2D1_ANTIALIAS_MODE antialias_mode)
1350 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1352 TRACE("iface %p, antialias_mode %#x stub!\n", iface, antialias_mode);
1354 render_target->drawing_state.antialiasMode = antialias_mode;
1357 static D2D1_ANTIALIAS_MODE STDMETHODCALLTYPE d2d_d3d_render_target_GetAntialiasMode(ID2D1RenderTarget *iface)
1359 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1361 TRACE("iface %p.\n", iface);
1363 return render_target->drawing_state.antialiasMode;
1366 static void STDMETHODCALLTYPE d2d_d3d_render_target_SetTextAntialiasMode(ID2D1RenderTarget *iface,
1367 D2D1_TEXT_ANTIALIAS_MODE antialias_mode)
1369 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1371 TRACE("iface %p, antialias_mode %#x.\n", iface, antialias_mode);
1373 render_target->drawing_state.textAntialiasMode = antialias_mode;
1376 static D2D1_TEXT_ANTIALIAS_MODE STDMETHODCALLTYPE d2d_d3d_render_target_GetTextAntialiasMode(ID2D1RenderTarget *iface)
1378 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1380 TRACE("iface %p.\n", iface);
1382 return render_target->drawing_state.textAntialiasMode;
1385 static void STDMETHODCALLTYPE d2d_d3d_render_target_SetTextRenderingParams(ID2D1RenderTarget *iface,
1386 IDWriteRenderingParams *text_rendering_params)
1388 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1390 TRACE("iface %p, text_rendering_params %p.\n", iface, text_rendering_params);
1392 if (text_rendering_params)
1393 IDWriteRenderingParams_AddRef(text_rendering_params);
1394 if (render_target->text_rendering_params)
1395 IDWriteRenderingParams_Release(render_target->text_rendering_params);
1396 render_target->text_rendering_params = text_rendering_params;
1399 static void STDMETHODCALLTYPE d2d_d3d_render_target_GetTextRenderingParams(ID2D1RenderTarget *iface,
1400 IDWriteRenderingParams **text_rendering_params)
1402 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1404 TRACE("iface %p, text_rendering_params %p.\n", iface, text_rendering_params);
1406 if ((*text_rendering_params = render_target->text_rendering_params))
1407 IDWriteRenderingParams_AddRef(*text_rendering_params);
1410 static void STDMETHODCALLTYPE d2d_d3d_render_target_SetTags(ID2D1RenderTarget *iface, D2D1_TAG tag1, D2D1_TAG tag2)
1412 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1414 TRACE("iface %p, tag1 %s, tag2 %s.\n", iface, wine_dbgstr_longlong(tag1), wine_dbgstr_longlong(tag2));
1416 render_target->drawing_state.tag1 = tag1;
1417 render_target->drawing_state.tag2 = tag2;
1420 static void STDMETHODCALLTYPE d2d_d3d_render_target_GetTags(ID2D1RenderTarget *iface, D2D1_TAG *tag1, D2D1_TAG *tag2)
1422 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1424 TRACE("iface %p, tag1 %p, tag2 %p.\n", iface, tag1, tag2);
1426 *tag1 = render_target->drawing_state.tag1;
1427 *tag2 = render_target->drawing_state.tag2;
1430 static void STDMETHODCALLTYPE d2d_d3d_render_target_PushLayer(ID2D1RenderTarget *iface,
1431 const D2D1_LAYER_PARAMETERS *layer_parameters, ID2D1Layer *layer)
1433 FIXME("iface %p, layer_parameters %p, layer %p stub!\n", iface, layer_parameters, layer);
1436 static void STDMETHODCALLTYPE d2d_d3d_render_target_PopLayer(ID2D1RenderTarget *iface)
1438 FIXME("iface %p stub!\n", iface);
1441 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_Flush(ID2D1RenderTarget *iface, D2D1_TAG *tag1, D2D1_TAG *tag2)
1443 FIXME("iface %p, tag1 %p, tag2 %p stub!\n", iface, tag1, tag2);
1445 return E_NOTIMPL;
1448 static void STDMETHODCALLTYPE d2d_d3d_render_target_SaveDrawingState(ID2D1RenderTarget *iface,
1449 ID2D1DrawingStateBlock *state_block)
1451 struct d2d_state_block *state_block_impl = unsafe_impl_from_ID2D1DrawingStateBlock(state_block);
1452 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1454 TRACE("iface %p, state_block %p.\n", iface, state_block);
1456 state_block_impl->drawing_state = render_target->drawing_state;
1457 if (render_target->text_rendering_params)
1458 IDWriteRenderingParams_AddRef(render_target->text_rendering_params);
1459 if (state_block_impl->text_rendering_params)
1460 IDWriteRenderingParams_Release(state_block_impl->text_rendering_params);
1461 state_block_impl->text_rendering_params = render_target->text_rendering_params;
1464 static void STDMETHODCALLTYPE d2d_d3d_render_target_RestoreDrawingState(ID2D1RenderTarget *iface,
1465 ID2D1DrawingStateBlock *state_block)
1467 struct d2d_state_block *state_block_impl = unsafe_impl_from_ID2D1DrawingStateBlock(state_block);
1468 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1470 TRACE("iface %p, state_block %p.\n", iface, state_block);
1472 render_target->drawing_state = state_block_impl->drawing_state;
1473 if (state_block_impl->text_rendering_params)
1474 IDWriteRenderingParams_AddRef(state_block_impl->text_rendering_params);
1475 if (render_target->text_rendering_params)
1476 IDWriteRenderingParams_Release(render_target->text_rendering_params);
1477 render_target->text_rendering_params = state_block_impl->text_rendering_params;
1480 static void STDMETHODCALLTYPE d2d_d3d_render_target_PushAxisAlignedClip(ID2D1RenderTarget *iface,
1481 const D2D1_RECT_F *clip_rect, D2D1_ANTIALIAS_MODE antialias_mode)
1483 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1484 D2D1_RECT_F transformed_rect;
1485 float x_scale, y_scale;
1486 D2D1_POINT_2F point;
1488 TRACE("iface %p, clip_rect %s, antialias_mode %#x.\n", iface, debug_d2d_rect_f(clip_rect), antialias_mode);
1490 if (antialias_mode != D2D1_ANTIALIAS_MODE_ALIASED)
1491 FIXME("Ignoring antialias_mode %#x.\n", antialias_mode);
1493 x_scale = render_target->desc.dpiX / 96.0f;
1494 y_scale = render_target->desc.dpiY / 96.0f;
1495 d2d_point_transform(&point, &render_target->drawing_state.transform,
1496 clip_rect->left * x_scale, clip_rect->top * y_scale);
1497 d2d_rect_set(&transformed_rect, point.x, point.y, point.x, point.y);
1498 d2d_point_transform(&point, &render_target->drawing_state.transform,
1499 clip_rect->left * x_scale, clip_rect->bottom * y_scale);
1500 d2d_rect_expand(&transformed_rect, &point);
1501 d2d_point_transform(&point, &render_target->drawing_state.transform,
1502 clip_rect->right * x_scale, clip_rect->top * y_scale);
1503 d2d_rect_expand(&transformed_rect, &point);
1504 d2d_point_transform(&point, &render_target->drawing_state.transform,
1505 clip_rect->right * x_scale, clip_rect->bottom * y_scale);
1506 d2d_rect_expand(&transformed_rect, &point);
1508 if (!d2d_clip_stack_push(&render_target->clip_stack, &transformed_rect))
1509 WARN("Failed to push clip rect.\n");
1512 static void STDMETHODCALLTYPE d2d_d3d_render_target_PopAxisAlignedClip(ID2D1RenderTarget *iface)
1514 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1516 TRACE("iface %p.\n", iface);
1518 d2d_clip_stack_pop(&render_target->clip_stack);
1521 static void STDMETHODCALLTYPE d2d_d3d_render_target_Clear(ID2D1RenderTarget *iface, const D2D1_COLOR_F *colour)
1523 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1524 D3D10_SUBRESOURCE_DATA buffer_data;
1525 struct d2d_ps_cb ps_cb_data = {0};
1526 D3D10_BUFFER_DESC buffer_desc;
1527 ID3D10Buffer *vs_cb, *ps_cb;
1528 D2D1_COLOR_F *c;
1529 HRESULT hr;
1531 static const struct
1533 struct
1535 float _11, _21, _31, pad0;
1536 float _12, _22, _32, pad1;
1537 } transform_geometry;
1538 struct d2d_vec4 transform_rtx;
1539 struct d2d_vec4 transform_rty;
1541 vs_cb_data =
1543 {1.0f, 0.0f, 0.0f, 0.0f,
1544 0.0f, 1.0f, 0.0f, 0.0f},
1545 {1.0f, 0.0f, 1.0f, 1.0f},
1546 {0.0f, 1.0f, 1.0f, -1.0f},
1549 TRACE("iface %p, colour %p.\n", iface, colour);
1551 buffer_desc.ByteWidth = sizeof(vs_cb_data);
1552 buffer_desc.Usage = D3D10_USAGE_DEFAULT;
1553 buffer_desc.BindFlags = D3D10_BIND_CONSTANT_BUFFER;
1554 buffer_desc.CPUAccessFlags = 0;
1555 buffer_desc.MiscFlags = 0;
1557 buffer_data.pSysMem = &vs_cb_data;
1558 buffer_data.SysMemPitch = 0;
1559 buffer_data.SysMemSlicePitch = 0;
1561 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device, &buffer_desc, &buffer_data, &vs_cb)))
1563 WARN("Failed to create constant buffer, hr %#x.\n", hr);
1564 return;
1567 ps_cb_data.outline = FALSE;
1568 ps_cb_data.colour_brush.type = D2D_BRUSH_TYPE_SOLID;
1569 ps_cb_data.colour_brush.opacity = 1.0f;
1570 c = &ps_cb_data.colour_brush.u.solid.colour;
1571 if (colour)
1572 *c = *colour;
1573 if (render_target->desc.pixelFormat.alphaMode == D2D1_ALPHA_MODE_IGNORE)
1574 c->a = 1.0f;
1575 c->r *= c->a;
1576 c->g *= c->a;
1577 c->b *= c->a;
1579 ps_cb_data.opacity_brush.type = D2D_BRUSH_TYPE_COUNT;
1581 buffer_desc.ByteWidth = sizeof(ps_cb_data);
1582 buffer_data.pSysMem = &ps_cb_data;
1584 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device, &buffer_desc, &buffer_data, &ps_cb)))
1586 WARN("Failed to create constant buffer, hr %#x.\n", hr);
1587 ID3D10Buffer_Release(vs_cb);
1588 return;
1591 d2d_rt_draw(render_target, D2D_SHAPE_TYPE_TRIANGLE, render_target->ib, 6,
1592 render_target->vb, render_target->vb_stride, vs_cb, ps_cb, NULL, NULL);
1594 ID3D10Buffer_Release(ps_cb);
1595 ID3D10Buffer_Release(vs_cb);
1598 static void STDMETHODCALLTYPE d2d_d3d_render_target_BeginDraw(ID2D1RenderTarget *iface)
1600 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1602 TRACE("iface %p.\n", iface);
1604 memset(&render_target->error, 0, sizeof(render_target->error));
1607 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_EndDraw(ID2D1RenderTarget *iface,
1608 D2D1_TAG *tag1, D2D1_TAG *tag2)
1610 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1612 TRACE("iface %p, tag1 %p, tag2 %p.\n", iface, tag1, tag2);
1614 if (tag1)
1615 *tag1 = render_target->error.tag1;
1616 if (tag2)
1617 *tag2 = render_target->error.tag2;
1619 return render_target->error.code;
1622 static D2D1_PIXEL_FORMAT * STDMETHODCALLTYPE d2d_d3d_render_target_GetPixelFormat(ID2D1RenderTarget *iface,
1623 D2D1_PIXEL_FORMAT *format)
1625 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1627 TRACE("iface %p, format %p.\n", iface, format);
1629 *format = render_target->desc.pixelFormat;
1630 return format;
1633 static void STDMETHODCALLTYPE d2d_d3d_render_target_SetDpi(ID2D1RenderTarget *iface, float dpi_x, float dpi_y)
1635 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1637 TRACE("iface %p, dpi_x %.8e, dpi_y %.8e.\n", iface, dpi_x, dpi_y);
1639 if (dpi_x == 0.0f && dpi_y == 0.0f)
1641 dpi_x = 96.0f;
1642 dpi_y = 96.0f;
1644 else if (dpi_x <= 0.0f || dpi_y <= 0.0f)
1645 return;
1647 render_target->desc.dpiX = dpi_x;
1648 render_target->desc.dpiY = dpi_y;
1651 static void STDMETHODCALLTYPE d2d_d3d_render_target_GetDpi(ID2D1RenderTarget *iface, float *dpi_x, float *dpi_y)
1653 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1655 TRACE("iface %p, dpi_x %p, dpi_y %p.\n", iface, dpi_x, dpi_y);
1657 *dpi_x = render_target->desc.dpiX;
1658 *dpi_y = render_target->desc.dpiY;
1661 static D2D1_SIZE_F * STDMETHODCALLTYPE d2d_d3d_render_target_GetSize(ID2D1RenderTarget *iface, D2D1_SIZE_F *size)
1663 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1665 TRACE("iface %p, size %p.\n", iface, size);
1667 size->width = render_target->pixel_size.width / (render_target->desc.dpiX / 96.0f);
1668 size->height = render_target->pixel_size.height / (render_target->desc.dpiY / 96.0f);
1669 return size;
1672 static D2D1_SIZE_U * STDMETHODCALLTYPE d2d_d3d_render_target_GetPixelSize(ID2D1RenderTarget *iface,
1673 D2D1_SIZE_U *pixel_size)
1675 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1677 TRACE("iface %p, pixel_size %p.\n", iface, pixel_size);
1679 *pixel_size = render_target->pixel_size;
1680 return pixel_size;
1683 static UINT32 STDMETHODCALLTYPE d2d_d3d_render_target_GetMaximumBitmapSize(ID2D1RenderTarget *iface)
1685 FIXME("iface %p stub!\n", iface);
1687 return 0;
1690 static BOOL STDMETHODCALLTYPE d2d_d3d_render_target_IsSupported(ID2D1RenderTarget *iface,
1691 const D2D1_RENDER_TARGET_PROPERTIES *desc)
1693 FIXME("iface %p, desc %p stub!\n", iface, desc);
1695 return FALSE;
1698 static const struct ID2D1RenderTargetVtbl d2d_d3d_render_target_vtbl =
1700 d2d_d3d_render_target_QueryInterface,
1701 d2d_d3d_render_target_AddRef,
1702 d2d_d3d_render_target_Release,
1703 d2d_d3d_render_target_GetFactory,
1704 d2d_d3d_render_target_CreateBitmap,
1705 d2d_d3d_render_target_CreateBitmapFromWicBitmap,
1706 d2d_d3d_render_target_CreateSharedBitmap,
1707 d2d_d3d_render_target_CreateBitmapBrush,
1708 d2d_d3d_render_target_CreateSolidColorBrush,
1709 d2d_d3d_render_target_CreateGradientStopCollection,
1710 d2d_d3d_render_target_CreateLinearGradientBrush,
1711 d2d_d3d_render_target_CreateRadialGradientBrush,
1712 d2d_d3d_render_target_CreateCompatibleRenderTarget,
1713 d2d_d3d_render_target_CreateLayer,
1714 d2d_d3d_render_target_CreateMesh,
1715 d2d_d3d_render_target_DrawLine,
1716 d2d_d3d_render_target_DrawRectangle,
1717 d2d_d3d_render_target_FillRectangle,
1718 d2d_d3d_render_target_DrawRoundedRectangle,
1719 d2d_d3d_render_target_FillRoundedRectangle,
1720 d2d_d3d_render_target_DrawEllipse,
1721 d2d_d3d_render_target_FillEllipse,
1722 d2d_d3d_render_target_DrawGeometry,
1723 d2d_d3d_render_target_FillGeometry,
1724 d2d_d3d_render_target_FillMesh,
1725 d2d_d3d_render_target_FillOpacityMask,
1726 d2d_d3d_render_target_DrawBitmap,
1727 d2d_d3d_render_target_DrawText,
1728 d2d_d3d_render_target_DrawTextLayout,
1729 d2d_d3d_render_target_DrawGlyphRun,
1730 d2d_d3d_render_target_SetTransform,
1731 d2d_d3d_render_target_GetTransform,
1732 d2d_d3d_render_target_SetAntialiasMode,
1733 d2d_d3d_render_target_GetAntialiasMode,
1734 d2d_d3d_render_target_SetTextAntialiasMode,
1735 d2d_d3d_render_target_GetTextAntialiasMode,
1736 d2d_d3d_render_target_SetTextRenderingParams,
1737 d2d_d3d_render_target_GetTextRenderingParams,
1738 d2d_d3d_render_target_SetTags,
1739 d2d_d3d_render_target_GetTags,
1740 d2d_d3d_render_target_PushLayer,
1741 d2d_d3d_render_target_PopLayer,
1742 d2d_d3d_render_target_Flush,
1743 d2d_d3d_render_target_SaveDrawingState,
1744 d2d_d3d_render_target_RestoreDrawingState,
1745 d2d_d3d_render_target_PushAxisAlignedClip,
1746 d2d_d3d_render_target_PopAxisAlignedClip,
1747 d2d_d3d_render_target_Clear,
1748 d2d_d3d_render_target_BeginDraw,
1749 d2d_d3d_render_target_EndDraw,
1750 d2d_d3d_render_target_GetPixelFormat,
1751 d2d_d3d_render_target_SetDpi,
1752 d2d_d3d_render_target_GetDpi,
1753 d2d_d3d_render_target_GetSize,
1754 d2d_d3d_render_target_GetPixelSize,
1755 d2d_d3d_render_target_GetMaximumBitmapSize,
1756 d2d_d3d_render_target_IsSupported,
1759 static inline struct d2d_d3d_render_target *impl_from_IDWriteTextRenderer(IDWriteTextRenderer *iface)
1761 return CONTAINING_RECORD(iface, struct d2d_d3d_render_target, IDWriteTextRenderer_iface);
1764 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_QueryInterface(IDWriteTextRenderer *iface, REFIID iid, void **out)
1766 TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
1768 if (IsEqualGUID(iid, &IID_IDWriteTextRenderer)
1769 || IsEqualGUID(iid, &IID_IDWritePixelSnapping)
1770 || IsEqualGUID(iid, &IID_IUnknown))
1772 IDWriteTextRenderer_AddRef(iface);
1773 *out = iface;
1774 return S_OK;
1777 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
1779 *out = NULL;
1780 return E_NOINTERFACE;
1783 static ULONG STDMETHODCALLTYPE d2d_text_renderer_AddRef(IDWriteTextRenderer *iface)
1785 struct d2d_d3d_render_target *render_target = impl_from_IDWriteTextRenderer(iface);
1787 TRACE("iface %p.\n", iface);
1789 return d2d_d3d_render_target_AddRef(&render_target->ID2D1RenderTarget_iface);
1792 static ULONG STDMETHODCALLTYPE d2d_text_renderer_Release(IDWriteTextRenderer *iface)
1794 struct d2d_d3d_render_target *render_target = impl_from_IDWriteTextRenderer(iface);
1796 TRACE("iface %p.\n", iface);
1798 return d2d_d3d_render_target_Release(&render_target->ID2D1RenderTarget_iface);
1801 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_IsPixelSnappingDisabled(IDWriteTextRenderer *iface,
1802 void *ctx, BOOL *disabled)
1804 struct d2d_draw_text_layout_ctx *context = ctx;
1806 TRACE("iface %p, ctx %p, disabled %p.\n", iface, ctx, disabled);
1808 *disabled = context->options & D2D1_DRAW_TEXT_OPTIONS_NO_SNAP;
1810 return S_OK;
1813 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_GetCurrentTransform(IDWriteTextRenderer *iface,
1814 void *ctx, DWRITE_MATRIX *transform)
1816 struct d2d_d3d_render_target *render_target = impl_from_IDWriteTextRenderer(iface);
1818 TRACE("iface %p, ctx %p, transform %p.\n", iface, ctx, transform);
1820 ID2D1RenderTarget_GetTransform(&render_target->ID2D1RenderTarget_iface, (D2D1_MATRIX_3X2_F *)transform);
1822 return S_OK;
1825 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_GetPixelsPerDip(IDWriteTextRenderer *iface, void *ctx, float *ppd)
1827 struct d2d_d3d_render_target *render_target = impl_from_IDWriteTextRenderer(iface);
1829 TRACE("iface %p, ctx %p, ppd %p.\n", iface, ctx, ppd);
1831 *ppd = render_target->desc.dpiY / 96.0f;
1833 return S_OK;
1836 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_DrawGlyphRun(IDWriteTextRenderer *iface, void *ctx,
1837 float baseline_origin_x, float baseline_origin_y, DWRITE_MEASURING_MODE measuring_mode,
1838 const DWRITE_GLYPH_RUN *glyph_run, const DWRITE_GLYPH_RUN_DESCRIPTION *desc, IUnknown *effect)
1840 struct d2d_d3d_render_target *render_target = impl_from_IDWriteTextRenderer(iface);
1841 D2D1_POINT_2F baseline_origin = {baseline_origin_x, baseline_origin_y};
1842 struct d2d_draw_text_layout_ctx *context = ctx;
1843 BOOL color_font = FALSE;
1844 ID2D1Brush *brush;
1846 TRACE("iface %p, ctx %p, baseline_origin_x %.8e, baseline_origin_y %.8e, "
1847 "measuring_mode %#x, glyph_run %p, desc %p, effect %p.\n",
1848 iface, ctx, baseline_origin_x, baseline_origin_y,
1849 measuring_mode, glyph_run, desc, effect);
1851 if (desc)
1852 WARN("Ignoring glyph run description %p.\n", desc);
1853 if (context->options & ~(D2D1_DRAW_TEXT_OPTIONS_NO_SNAP | D2D1_DRAW_TEXT_OPTIONS_ENABLE_COLOR_FONT))
1854 FIXME("Ignoring options %#x.\n", context->options);
1856 brush = d2d_draw_get_text_brush(context, effect);
1858 TRACE("%s\n", debugstr_wn(desc->string, desc->stringLength));
1860 if (context->options & D2D1_DRAW_TEXT_OPTIONS_ENABLE_COLOR_FONT)
1862 IDWriteFontFace2 *fontface;
1864 if (SUCCEEDED(IDWriteFontFace_QueryInterface(glyph_run->fontFace,
1865 &IID_IDWriteFontFace2, (void **)&fontface)))
1867 color_font = IDWriteFontFace2_IsColorFont(fontface);
1868 IDWriteFontFace2_Release(fontface);
1872 if (color_font)
1874 IDWriteColorGlyphRunEnumerator *layers;
1875 IDWriteFactory2 *dwrite_factory;
1876 HRESULT hr;
1878 if (FAILED(hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, &IID_IDWriteFactory2,
1879 (IUnknown **)&dwrite_factory)))
1881 ERR("Failed to create dwrite factory, hr %#x.\n", hr);
1882 ID2D1Brush_Release(brush);
1883 return hr;
1886 hr = IDWriteFactory2_TranslateColorGlyphRun(dwrite_factory, baseline_origin_x, baseline_origin_y,
1887 glyph_run, desc, measuring_mode, (DWRITE_MATRIX *)&render_target->drawing_state.transform, 0, &layers);
1888 IDWriteFactory2_Release(dwrite_factory);
1889 if (FAILED(hr))
1891 ERR("Failed to create color glyph run enumerator, hr %#x.\n", hr);
1892 ID2D1Brush_Release(brush);
1893 return hr;
1896 for (;;)
1898 const DWRITE_COLOR_GLYPH_RUN *color_run;
1899 ID2D1Brush *color_brush;
1900 D2D1_POINT_2F origin;
1901 BOOL has_run = FALSE;
1903 if (FAILED(hr = IDWriteColorGlyphRunEnumerator_MoveNext(layers, &has_run)))
1905 ERR("Failed to switch color glyph layer, hr %#x.\n", hr);
1906 break;
1909 if (!has_run)
1910 break;
1912 if (FAILED(hr = IDWriteColorGlyphRunEnumerator_GetCurrentRun(layers, &color_run)))
1914 ERR("Failed to get current color run, hr %#x.\n", hr);
1915 break;
1918 if (color_run->paletteIndex == 0xffff)
1919 color_brush = brush;
1920 else
1922 if (FAILED(hr = ID2D1RenderTarget_CreateSolidColorBrush(&render_target->ID2D1RenderTarget_iface,
1923 &color_run->runColor, NULL, (ID2D1SolidColorBrush **)&color_brush)))
1925 ERR("Failed to create solid color brush, hr %#x.\n", hr);
1926 break;
1930 origin.x = color_run->baselineOriginX;
1931 origin.y = color_run->baselineOriginY;
1932 ID2D1RenderTarget_DrawGlyphRun(&render_target->ID2D1RenderTarget_iface,
1933 origin, &color_run->glyphRun, color_brush, measuring_mode);
1935 if (color_brush != brush)
1936 ID2D1Brush_Release(color_brush);
1939 IDWriteColorGlyphRunEnumerator_Release(layers);
1941 else
1942 ID2D1RenderTarget_DrawGlyphRun(&render_target->ID2D1RenderTarget_iface,
1943 baseline_origin, glyph_run, brush, measuring_mode);
1945 ID2D1Brush_Release(brush);
1947 return S_OK;
1950 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_DrawUnderline(IDWriteTextRenderer *iface, void *ctx,
1951 float baseline_origin_x, float baseline_origin_y, const DWRITE_UNDERLINE *underline, IUnknown *effect)
1953 struct d2d_d3d_render_target *render_target = impl_from_IDWriteTextRenderer(iface);
1954 const D2D1_MATRIX_3X2_F *m = &render_target->drawing_state.transform;
1955 struct d2d_draw_text_layout_ctx *context = ctx;
1956 D2D1_ANTIALIAS_MODE prev_antialias_mode;
1957 D2D1_POINT_2F start, end;
1958 ID2D1Brush *brush;
1959 float thickness;
1961 TRACE("iface %p, ctx %p, baseline_origin_x %.8e, baseline_origin_y %.8e, underline %p, effect %p\n",
1962 iface, ctx, baseline_origin_x, baseline_origin_y, underline, effect);
1964 /* minimal thickness in DIPs that will result in at least 1 pixel thick line */
1965 thickness = max(96.0f / (render_target->desc.dpiY * sqrtf(m->_21 * m->_21 + m->_22 * m->_22)),
1966 underline->thickness);
1968 brush = d2d_draw_get_text_brush(context, effect);
1970 start.x = baseline_origin_x;
1971 start.y = baseline_origin_y + underline->offset + thickness / 2.0f;
1972 end.x = start.x + underline->width;
1973 end.y = start.y;
1974 prev_antialias_mode = d2d_d3d_render_target_set_aa_mode_from_text_aa_mode(render_target);
1975 d2d_d3d_render_target_DrawLine(&render_target->ID2D1RenderTarget_iface, start, end, brush, thickness, NULL);
1976 render_target->drawing_state.antialiasMode = prev_antialias_mode;
1978 ID2D1Brush_Release(brush);
1980 return S_OK;
1983 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_DrawStrikethrough(IDWriteTextRenderer *iface, void *ctx,
1984 float baseline_origin_x, float baseline_origin_y, const DWRITE_STRIKETHROUGH *strikethrough, IUnknown *effect)
1986 struct d2d_d3d_render_target *render_target = impl_from_IDWriteTextRenderer(iface);
1987 const D2D1_MATRIX_3X2_F *m = &render_target->drawing_state.transform;
1988 struct d2d_draw_text_layout_ctx *context = ctx;
1989 D2D1_ANTIALIAS_MODE prev_antialias_mode;
1990 D2D1_POINT_2F start, end;
1991 ID2D1Brush *brush;
1992 float thickness;
1994 TRACE("iface %p, ctx %p, baseline_origin_x %.8e, baseline_origin_y %.8e, strikethrough %p, effect %p.\n",
1995 iface, ctx, baseline_origin_x, baseline_origin_y, strikethrough, effect);
1997 /* minimal thickness in DIPs that will result in at least 1 pixel thick line */
1998 thickness = max(96.0f / (render_target->desc.dpiY * sqrtf(m->_21 * m->_21 + m->_22 * m->_22)),
1999 strikethrough->thickness);
2001 brush = d2d_draw_get_text_brush(context, effect);
2003 start.x = baseline_origin_x;
2004 start.y = baseline_origin_y + strikethrough->offset + thickness / 2.0f;
2005 end.x = start.x + strikethrough->width;
2006 end.y = start.y;
2007 prev_antialias_mode = d2d_d3d_render_target_set_aa_mode_from_text_aa_mode(render_target);
2008 d2d_d3d_render_target_DrawLine(&render_target->ID2D1RenderTarget_iface, start, end, brush, thickness, NULL);
2009 render_target->drawing_state.antialiasMode = prev_antialias_mode;
2011 ID2D1Brush_Release(brush);
2013 return S_OK;
2016 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_DrawInlineObject(IDWriteTextRenderer *iface, void *ctx,
2017 float origin_x, float origin_y, IDWriteInlineObject *object, BOOL is_sideways, BOOL is_rtl, IUnknown *effect)
2019 struct d2d_draw_text_layout_ctx *context = ctx;
2020 ID2D1Brush *brush;
2021 HRESULT hr;
2023 TRACE("iface %p, ctx %p, origin_x %.8e, origin_y %.8e, object %p, is_sideways %#x, is_rtl %#x, effect %p.\n",
2024 iface, ctx, origin_x, origin_y, object, is_sideways, is_rtl, effect);
2026 /* Inline objects may not pass effects all the way down, when using layout object internally for example.
2027 This is how default trimming sign object in DirectWrite works - it does not use effect passed to Draw(),
2028 and resulting DrawGlyphRun() is always called with NULL effect, however original effect is used and correct
2029 brush is selected at Direct2D level. */
2030 brush = context->brush;
2031 context->brush = d2d_draw_get_text_brush(context, effect);
2033 hr = IDWriteInlineObject_Draw(object, ctx, iface, origin_x, origin_y, is_sideways, is_rtl, effect);
2035 ID2D1Brush_Release(context->brush);
2036 context->brush = brush;
2038 return hr;
2041 static const struct IDWriteTextRendererVtbl d2d_text_renderer_vtbl =
2043 d2d_text_renderer_QueryInterface,
2044 d2d_text_renderer_AddRef,
2045 d2d_text_renderer_Release,
2046 d2d_text_renderer_IsPixelSnappingDisabled,
2047 d2d_text_renderer_GetCurrentTransform,
2048 d2d_text_renderer_GetPixelsPerDip,
2049 d2d_text_renderer_DrawGlyphRun,
2050 d2d_text_renderer_DrawUnderline,
2051 d2d_text_renderer_DrawStrikethrough,
2052 d2d_text_renderer_DrawInlineObject,
2055 static inline struct d2d_d3d_render_target *impl_from_ID2D1GdiInteropRenderTarget(ID2D1GdiInteropRenderTarget *iface)
2057 return CONTAINING_RECORD(iface, struct d2d_d3d_render_target, ID2D1GdiInteropRenderTarget_iface);
2060 static HRESULT STDMETHODCALLTYPE d2d_gdi_interop_render_target_QueryInterface(ID2D1GdiInteropRenderTarget *iface,
2061 REFIID iid, void **out)
2063 struct d2d_d3d_render_target *render_target = impl_from_ID2D1GdiInteropRenderTarget(iface);
2065 TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
2067 return IUnknown_QueryInterface(render_target->outer_unknown, iid, out);
2070 static ULONG STDMETHODCALLTYPE d2d_gdi_interop_render_target_AddRef(ID2D1GdiInteropRenderTarget *iface)
2072 struct d2d_d3d_render_target *render_target = impl_from_ID2D1GdiInteropRenderTarget(iface);
2074 TRACE("iface %p.\n", iface);
2076 return IUnknown_AddRef(render_target->outer_unknown);
2079 static ULONG STDMETHODCALLTYPE d2d_gdi_interop_render_target_Release(ID2D1GdiInteropRenderTarget *iface)
2081 struct d2d_d3d_render_target *render_target = impl_from_ID2D1GdiInteropRenderTarget(iface);
2083 TRACE("iface %p.\n", iface);
2085 return IUnknown_Release(render_target->outer_unknown);
2088 static HRESULT d2d_d3d_render_target_get_surface(struct d2d_d3d_render_target *render_target, IDXGISurface1 **surface)
2090 ID3D10Resource *resource;
2091 HRESULT hr;
2093 ID3D10RenderTargetView_GetResource(render_target->view, &resource);
2094 hr = ID3D10Resource_QueryInterface(resource, &IID_IDXGISurface1, (void **)surface);
2095 ID3D10Resource_Release(resource);
2096 if (FAILED(hr))
2098 *surface = NULL;
2099 WARN("Failed to get DXGI surface, %#x.\n", hr);
2100 return hr;
2103 return hr;
2106 static HRESULT STDMETHODCALLTYPE d2d_gdi_interop_render_target_GetDC(ID2D1GdiInteropRenderTarget *iface,
2107 D2D1_DC_INITIALIZE_MODE mode, HDC *dc)
2109 struct d2d_d3d_render_target *render_target = impl_from_ID2D1GdiInteropRenderTarget(iface);
2110 IDXGISurface1 *surface;
2111 HRESULT hr;
2113 TRACE("iface %p, mode %d, dc %p.\n", iface, mode, dc);
2115 if (FAILED(hr = d2d_d3d_render_target_get_surface(render_target, &surface)))
2116 return hr;
2118 hr = IDXGISurface1_GetDC(surface, mode != D2D1_DC_INITIALIZE_MODE_COPY, dc);
2119 IDXGISurface1_Release(surface);
2121 return hr;
2124 static HRESULT STDMETHODCALLTYPE d2d_gdi_interop_render_target_ReleaseDC(ID2D1GdiInteropRenderTarget *iface,
2125 const RECT *update)
2127 struct d2d_d3d_render_target *render_target = impl_from_ID2D1GdiInteropRenderTarget(iface);
2128 IDXGISurface1 *surface;
2129 RECT update_rect;
2130 HRESULT hr;
2132 TRACE("iface %p, update rect %s.\n", iface, wine_dbgstr_rect(update));
2134 if (FAILED(hr = d2d_d3d_render_target_get_surface(render_target, &surface)))
2135 return hr;
2137 if (update)
2138 update_rect = *update;
2139 hr = IDXGISurface1_ReleaseDC(surface, update ? &update_rect : NULL);
2140 IDXGISurface1_Release(surface);
2142 return hr;
2145 static const struct ID2D1GdiInteropRenderTargetVtbl d2d_gdi_interop_render_target_vtbl =
2147 d2d_gdi_interop_render_target_QueryInterface,
2148 d2d_gdi_interop_render_target_AddRef,
2149 d2d_gdi_interop_render_target_Release,
2150 d2d_gdi_interop_render_target_GetDC,
2151 d2d_gdi_interop_render_target_ReleaseDC,
2154 static HRESULT d2d_d3d_render_target_init(struct d2d_d3d_render_target *render_target, ID2D1Factory *factory,
2155 IDXGISurface *surface, IUnknown *outer_unknown, const D2D1_RENDER_TARGET_PROPERTIES *desc)
2157 D3D10_SUBRESOURCE_DATA buffer_data;
2158 D3D10_STATE_BLOCK_MASK state_mask;
2159 DXGI_SURFACE_DESC surface_desc;
2160 IDWriteFactory *dwrite_factory;
2161 D3D10_RASTERIZER_DESC rs_desc;
2162 D3D10_BUFFER_DESC buffer_desc;
2163 D3D10_BLEND_DESC blend_desc;
2164 ID3D10Resource *resource;
2165 unsigned int i;
2166 HRESULT hr;
2168 static const D3D10_INPUT_ELEMENT_DESC il_desc_outline[] =
2170 {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0},
2171 {"PREV", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 8, D3D10_INPUT_PER_VERTEX_DATA, 0},
2172 {"NEXT", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 16, D3D10_INPUT_PER_VERTEX_DATA, 0},
2174 static const D3D10_INPUT_ELEMENT_DESC il_desc_bezier_outline[] =
2176 {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0},
2177 {"P", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 8, D3D10_INPUT_PER_VERTEX_DATA, 0},
2178 {"P", 1, DXGI_FORMAT_R32G32_FLOAT, 0, 16, D3D10_INPUT_PER_VERTEX_DATA, 0},
2179 {"P", 2, DXGI_FORMAT_R32G32_FLOAT, 0, 24, D3D10_INPUT_PER_VERTEX_DATA, 0},
2180 {"PREV", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 32, D3D10_INPUT_PER_VERTEX_DATA, 0},
2181 {"NEXT", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 40, D3D10_INPUT_PER_VERTEX_DATA, 0},
2183 static const D3D10_INPUT_ELEMENT_DESC il_desc_triangle[] =
2185 {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0},
2187 static const D3D10_INPUT_ELEMENT_DESC il_desc_bezier[] =
2189 {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0},
2190 {"TEXCOORD", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 8, D3D10_INPUT_PER_VERTEX_DATA, 0},
2192 static const DWORD vs_code_outline[] =
2194 #if 0
2195 float3x2 transform_geometry;
2196 float stroke_width;
2197 float4 transform_rtx;
2198 float4 transform_rty;
2200 struct output
2202 float2 p : WORLD_POSITION;
2203 float4 b : BEZIER;
2204 nointerpolation float2x2 stroke_transform : STROKE_TRANSFORM;
2205 float4 position : SV_POSITION;
2208 /* The lines PₚᵣₑᵥP₀ and P₀Pₙₑₓₜ, both offset by ±½w, intersect each other at:
2210 * Pᵢ = P₀ ± w · ½q⃑ᵢ.
2212 * Where:
2214 * q⃑ᵢ = q̂ₚᵣₑᵥ⊥ + tan(½θ) · -q̂ₚᵣₑᵥ
2215 * θ = ∠PₚᵣₑᵥP₀Pₙₑₓₜ
2216 * q⃑ₚᵣₑᵥ = P₀ - Pₚᵣₑᵥ */
2217 void main(float2 position : POSITION, float2 prev : PREV, float2 next : NEXT, out struct output o)
2219 float2 q_prev, q_next, v_p, q_i;
2220 float2x2 geom;
2221 float l;
2223 o.stroke_transform = float2x2(transform_rtx.xy, transform_rty.xy) * stroke_width * 0.5f;
2225 geom = float2x2(transform_geometry._11_21, transform_geometry._12_22);
2226 q_prev = normalize(mul(geom, prev));
2227 q_next = normalize(mul(geom, next));
2229 /* tan(½θ) = sin(θ) / (1 + cos(θ))
2230 * = (q̂ₚᵣₑᵥ⊥ · q̂ₙₑₓₜ) / (1 + (q̂ₚᵣₑᵥ · q̂ₙₑₓₜ)) */
2231 v_p = float2(-q_prev.y, q_prev.x);
2232 l = -dot(v_p, q_next) / (1.0f + dot(q_prev, q_next));
2233 q_i = l * q_prev + v_p;
2235 o.b = float4(0.0, 0.0, 0.0, 0.0);
2237 o.p = mul(float3(position, 1.0f), transform_geometry) + stroke_width * 0.5f * q_i;
2238 position = mul(float2x3(transform_rtx.xyz, transform_rty.xyz), float3(o.p, 1.0f))
2239 * float2(transform_rtx.w, transform_rty.w);
2240 o.position = float4(position + float2(-1.0f, 1.0f), 0.0f, 1.0f);
2242 #endif
2243 0x43425844, 0xfb16cd75, 0xf5ec3e80, 0xceacf250, 0x91d29d18, 0x00000001, 0x00000608, 0x00000003,
2244 0x0000002c, 0x00000098, 0x00000154, 0x4e475349, 0x00000064, 0x00000003, 0x00000008, 0x00000050,
2245 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000303, 0x00000059, 0x00000000, 0x00000000,
2246 0x00000003, 0x00000001, 0x00000303, 0x0000005e, 0x00000000, 0x00000000, 0x00000003, 0x00000002,
2247 0x00000303, 0x49534f50, 0x4e4f4954, 0x45525000, 0x454e0056, 0xab005458, 0x4e47534f, 0x000000b4,
2248 0x00000005, 0x00000008, 0x00000080, 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000c03,
2249 0x0000008f, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x0000000f, 0x00000096, 0x00000000,
2250 0x00000000, 0x00000003, 0x00000002, 0x00000c03, 0x00000096, 0x00000001, 0x00000000, 0x00000003,
2251 0x00000003, 0x00000c03, 0x000000a7, 0x00000000, 0x00000001, 0x00000003, 0x00000004, 0x0000000f,
2252 0x4c524f57, 0x4f505f44, 0x49544953, 0x42004e4f, 0x45495a45, 0x54530052, 0x454b4f52, 0x4152545f,
2253 0x4f46534e, 0x53004d52, 0x4f505f56, 0x49544953, 0xab004e4f, 0x52444853, 0x000004ac, 0x00010040,
2254 0x0000012b, 0x04000059, 0x00208e46, 0x00000000, 0x00000004, 0x0300005f, 0x00101032, 0x00000000,
2255 0x0300005f, 0x00101032, 0x00000001, 0x0300005f, 0x00101032, 0x00000002, 0x03000065, 0x00102032,
2256 0x00000000, 0x03000065, 0x001020f2, 0x00000001, 0x03000065, 0x00102032, 0x00000002, 0x03000065,
2257 0x00102032, 0x00000003, 0x04000067, 0x001020f2, 0x00000004, 0x00000001, 0x02000068, 0x00000003,
2258 0x0800000f, 0x00100012, 0x00000000, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000002,
2259 0x0800000f, 0x00100022, 0x00000000, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000002,
2260 0x0700000f, 0x00100042, 0x00000000, 0x00100046, 0x00000000, 0x00100046, 0x00000000, 0x05000044,
2261 0x00100042, 0x00000000, 0x0010002a, 0x00000000, 0x07000038, 0x00100032, 0x00000000, 0x00100aa6,
2262 0x00000000, 0x00100046, 0x00000000, 0x0800000f, 0x00100012, 0x00000001, 0x00208046, 0x00000000,
2263 0x00000000, 0x00101046, 0x00000001, 0x0800000f, 0x00100022, 0x00000001, 0x00208046, 0x00000000,
2264 0x00000001, 0x00101046, 0x00000001, 0x0700000f, 0x00100042, 0x00000000, 0x00100046, 0x00000001,
2265 0x00100046, 0x00000001, 0x05000044, 0x00100042, 0x00000000, 0x0010002a, 0x00000000, 0x07000038,
2266 0x00100032, 0x00000001, 0x00100aa6, 0x00000000, 0x00100046, 0x00000001, 0x06000036, 0x001000c2,
2267 0x00000001, 0x80100556, 0x00000041, 0x00000001, 0x0700000f, 0x00100042, 0x00000000, 0x00100a26,
2268 0x00000001, 0x00100046, 0x00000000, 0x0700000f, 0x00100012, 0x00000000, 0x00100046, 0x00000001,
2269 0x00100046, 0x00000000, 0x07000000, 0x00100012, 0x00000000, 0x0010000a, 0x00000000, 0x00004001,
2270 0x3f800000, 0x0800000e, 0x00100012, 0x00000000, 0x8010002a, 0x00000041, 0x00000000, 0x0010000a,
2271 0x00000000, 0x09000032, 0x00100032, 0x00000000, 0x00100006, 0x00000000, 0x00100046, 0x00000001,
2272 0x00100f36, 0x00000001, 0x08000038, 0x00100042, 0x00000000, 0x0020803a, 0x00000000, 0x00000001,
2273 0x00004001, 0x3f000000, 0x05000036, 0x00100032, 0x00000001, 0x00101046, 0x00000000, 0x05000036,
2274 0x00100042, 0x00000001, 0x00004001, 0x3f800000, 0x08000010, 0x00100012, 0x00000002, 0x00100246,
2275 0x00000001, 0x00208246, 0x00000000, 0x00000000, 0x08000010, 0x00100022, 0x00000002, 0x00100246,
2276 0x00000001, 0x00208246, 0x00000000, 0x00000001, 0x09000032, 0x00100032, 0x00000000, 0x00100aa6,
2277 0x00000000, 0x00100046, 0x00000000, 0x00100046, 0x00000002, 0x05000036, 0x00102032, 0x00000000,
2278 0x00100046, 0x00000000, 0x08000036, 0x001020f2, 0x00000001, 0x00004002, 0x00000000, 0x00000000,
2279 0x00000000, 0x00000000, 0x06000036, 0x00100032, 0x00000001, 0x00208046, 0x00000000, 0x00000002,
2280 0x06000036, 0x001000c2, 0x00000001, 0x00208406, 0x00000000, 0x00000003, 0x08000038, 0x001000f2,
2281 0x00000001, 0x00100e46, 0x00000001, 0x00208ff6, 0x00000000, 0x00000001, 0x0a000038, 0x001000f2,
2282 0x00000001, 0x00100e46, 0x00000001, 0x00004002, 0x3f000000, 0x3f000000, 0x3f000000, 0x3f000000,
2283 0x05000036, 0x00102032, 0x00000002, 0x00100086, 0x00000001, 0x05000036, 0x00102032, 0x00000003,
2284 0x001005d6, 0x00000001, 0x05000036, 0x00100042, 0x00000000, 0x00004001, 0x3f800000, 0x08000010,
2285 0x00100082, 0x00000000, 0x00208246, 0x00000000, 0x00000002, 0x00100246, 0x00000000, 0x08000010,
2286 0x00100012, 0x00000000, 0x00208246, 0x00000000, 0x00000003, 0x00100246, 0x00000000, 0x08000038,
2287 0x00100022, 0x00000000, 0x0010000a, 0x00000000, 0x0020803a, 0x00000000, 0x00000003, 0x08000038,
2288 0x00100012, 0x00000000, 0x0010003a, 0x00000000, 0x0020803a, 0x00000000, 0x00000002, 0x0a000000,
2289 0x00102032, 0x00000004, 0x00100046, 0x00000000, 0x00004002, 0xbf800000, 0x3f800000, 0x00000000,
2290 0x00000000, 0x08000036, 0x001020c2, 0x00000004, 0x00004002, 0x00000000, 0x00000000, 0x00000000,
2291 0x3f800000, 0x0100003e,
2293 /* ⎡p0.x p0.y 1⎤
2294 * A = ⎢p1.x p1.y 1⎥
2295 * ⎣p2.x p2.y 1⎦
2297 * ⎡0 0⎤
2298 * B = ⎢½ 0⎥
2299 * ⎣1 1⎦
2301 * A' = ⎡p1.x-p0.x p1.y-p0.y⎤
2302 * ⎣p2.x-p0.x p2.y-p0.y⎦
2304 * B' = ⎡½ 0⎤
2305 * ⎣1 1⎦
2307 * A'T = B'
2308 * T = A'⁻¹B'
2310 static const DWORD vs_code_bezier_outline[] =
2312 #if 0
2313 float3x2 transform_geometry;
2314 float stroke_width;
2315 float4 transform_rtx;
2316 float4 transform_rty;
2318 struct output
2320 float2 p : WORLD_POSITION;
2321 float4 b : BEZIER;
2322 nointerpolation float2x2 stroke_transform : STROKE_TRANSFORM;
2323 float4 position : SV_POSITION;
2326 void main(float2 position : POSITION, float2 p0 : P0, float2 p1 : P1, float2 p2 : P2,
2327 float2 prev : PREV, float2 next : NEXT, out struct output o)
2329 float2 q_prev, q_next, v_p, q_i, p;
2330 float2x2 geom, rt;
2331 float l;
2333 geom = float2x2(transform_geometry._11_21, transform_geometry._12_22);
2334 rt = float2x2(transform_rtx.xy, transform_rty.xy);
2335 o.stroke_transform = rt * stroke_width * 0.5f;
2337 p = mul(geom, position);
2338 p0 = mul(geom, p0);
2339 p1 = mul(geom, p1);
2340 p2 = mul(geom, p2);
2342 p -= p0;
2343 p1 -= p0;
2344 p2 -= p0;
2346 q_prev = normalize(mul(geom, prev));
2347 q_next = normalize(mul(geom, next));
2349 v_p = float2(-q_prev.y, q_prev.x);
2350 l = -dot(v_p, q_next) / (1.0f + dot(q_prev, q_next));
2351 q_i = l * q_prev + v_p;
2352 p += stroke_width * q_i;
2354 v_p = mul(rt, p2);
2355 v_p = normalize(float2(-v_p.y, v_p.x));
2356 if (abs(dot(mul(rt, p1), v_p)) < 1.0f)
2358 o.b.xzw = float3(0.0f, 0.0f, 0.0f);
2359 o.b.y = dot(mul(rt, p), v_p);
2361 else
2363 o.b.zw = sign(dot(mul(rt, p1), v_p)) * v_p;
2364 v_p = -float2(-p.y, p.x) / dot(float2(-p1.y, p1.x), p2);
2365 o.b.x = dot(v_p, p1 - 0.5f * p2);
2366 o.b.y = dot(v_p, p1);
2369 o.p = mul(float3(position, 1.0f), transform_geometry) + stroke_width * q_i;
2370 position = mul(float2x3(transform_rtx.xyz, transform_rty.xyz), float3(o.p, 1.0f))
2371 * float2(transform_rtx.w, transform_rty.w);
2372 o.position = float4(position + float2(-1.0f, 1.0f), 0.0f, 1.0f);
2374 #endif
2375 0x43425844, 0x7ff88ce9, 0xd75cb064, 0x30396183, 0xca64489b, 0x00000001, 0x00000ae4, 0x00000003,
2376 0x0000002c, 0x000000e4, 0x000001a0, 0x4e475349, 0x000000b0, 0x00000006, 0x00000008, 0x00000098,
2377 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000303, 0x000000a1, 0x00000000, 0x00000000,
2378 0x00000003, 0x00000001, 0x00000303, 0x000000a1, 0x00000001, 0x00000000, 0x00000003, 0x00000002,
2379 0x00000303, 0x000000a1, 0x00000002, 0x00000000, 0x00000003, 0x00000003, 0x00000303, 0x000000a3,
2380 0x00000000, 0x00000000, 0x00000003, 0x00000004, 0x00000303, 0x000000a8, 0x00000000, 0x00000000,
2381 0x00000003, 0x00000005, 0x00000303, 0x49534f50, 0x4e4f4954, 0x50005000, 0x00564552, 0x5458454e,
2382 0xababab00, 0x4e47534f, 0x000000b4, 0x00000005, 0x00000008, 0x00000080, 0x00000000, 0x00000000,
2383 0x00000003, 0x00000000, 0x00000c03, 0x0000008f, 0x00000000, 0x00000000, 0x00000003, 0x00000001,
2384 0x0000000f, 0x00000096, 0x00000000, 0x00000000, 0x00000003, 0x00000002, 0x00000c03, 0x00000096,
2385 0x00000001, 0x00000000, 0x00000003, 0x00000003, 0x00000c03, 0x000000a7, 0x00000000, 0x00000001,
2386 0x00000003, 0x00000004, 0x0000000f, 0x4c524f57, 0x4f505f44, 0x49544953, 0x42004e4f, 0x45495a45,
2387 0x54530052, 0x454b4f52, 0x4152545f, 0x4f46534e, 0x53004d52, 0x4f505f56, 0x49544953, 0xab004e4f,
2388 0x52444853, 0x0000093c, 0x00010040, 0x0000024f, 0x04000059, 0x00208e46, 0x00000000, 0x00000004,
2389 0x0300005f, 0x00101032, 0x00000000, 0x0300005f, 0x00101032, 0x00000001, 0x0300005f, 0x00101032,
2390 0x00000002, 0x0300005f, 0x00101032, 0x00000003, 0x0300005f, 0x00101032, 0x00000004, 0x0300005f,
2391 0x00101032, 0x00000005, 0x03000065, 0x00102032, 0x00000000, 0x03000065, 0x001020f2, 0x00000001,
2392 0x03000065, 0x00102032, 0x00000002, 0x03000065, 0x00102032, 0x00000003, 0x04000067, 0x001020f2,
2393 0x00000004, 0x00000001, 0x02000068, 0x00000006, 0x0800000f, 0x00100012, 0x00000000, 0x00208046,
2394 0x00000000, 0x00000000, 0x00101046, 0x00000005, 0x0800000f, 0x00100022, 0x00000000, 0x00208046,
2395 0x00000000, 0x00000001, 0x00101046, 0x00000005, 0x0700000f, 0x00100042, 0x00000000, 0x00100046,
2396 0x00000000, 0x00100046, 0x00000000, 0x05000044, 0x00100042, 0x00000000, 0x0010002a, 0x00000000,
2397 0x07000038, 0x00100032, 0x00000000, 0x00100aa6, 0x00000000, 0x00100046, 0x00000000, 0x0800000f,
2398 0x00100012, 0x00000001, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000004, 0x0800000f,
2399 0x00100022, 0x00000001, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000004, 0x0700000f,
2400 0x00100042, 0x00000000, 0x00100046, 0x00000001, 0x00100046, 0x00000001, 0x05000044, 0x00100042,
2401 0x00000000, 0x0010002a, 0x00000000, 0x07000038, 0x00100032, 0x00000001, 0x00100aa6, 0x00000000,
2402 0x00100046, 0x00000001, 0x06000036, 0x001000c2, 0x00000001, 0x80100556, 0x00000041, 0x00000001,
2403 0x0700000f, 0x00100042, 0x00000000, 0x00100a26, 0x00000001, 0x00100046, 0x00000000, 0x0700000f,
2404 0x00100012, 0x00000000, 0x00100046, 0x00000001, 0x00100046, 0x00000000, 0x07000000, 0x00100012,
2405 0x00000000, 0x0010000a, 0x00000000, 0x00004001, 0x3f800000, 0x0800000e, 0x00100012, 0x00000000,
2406 0x8010002a, 0x00000041, 0x00000000, 0x0010000a, 0x00000000, 0x09000032, 0x00100032, 0x00000000,
2407 0x00100006, 0x00000000, 0x00100046, 0x00000001, 0x00100f36, 0x00000001, 0x05000036, 0x00100032,
2408 0x00000001, 0x00101046, 0x00000000, 0x05000036, 0x00100042, 0x00000001, 0x00004001, 0x3f800000,
2409 0x08000010, 0x00100012, 0x00000002, 0x00100246, 0x00000001, 0x00208246, 0x00000000, 0x00000000,
2410 0x08000010, 0x00100022, 0x00000002, 0x00100246, 0x00000001, 0x00208246, 0x00000000, 0x00000001,
2411 0x0a000032, 0x00100032, 0x00000001, 0x00208ff6, 0x00000000, 0x00000001, 0x00100046, 0x00000000,
2412 0x00100046, 0x00000002, 0x05000036, 0x00102032, 0x00000000, 0x00100046, 0x00000001, 0x0800000f,
2413 0x00100012, 0x00000002, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000000, 0x0800000f,
2414 0x00100022, 0x00000002, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000000, 0x0800000f,
2415 0x00100012, 0x00000003, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000001, 0x0800000f,
2416 0x00100022, 0x00000003, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000001, 0x08000000,
2417 0x001000c2, 0x00000000, 0x00100406, 0x00000002, 0x80100406, 0x00000041, 0x00000003, 0x0a000032,
2418 0x00100032, 0x00000000, 0x00208ff6, 0x00000000, 0x00000001, 0x00100046, 0x00000000, 0x00100ae6,
2419 0x00000000, 0x0800000f, 0x00100012, 0x00000002, 0x00208046, 0x00000000, 0x00000002, 0x00100046,
2420 0x00000000, 0x0800000f, 0x00100022, 0x00000002, 0x00208046, 0x00000000, 0x00000003, 0x00100046,
2421 0x00000000, 0x0800000f, 0x00100012, 0x00000004, 0x00208046, 0x00000000, 0x00000000, 0x00101046,
2422 0x00000003, 0x0800000f, 0x00100022, 0x00000004, 0x00208046, 0x00000000, 0x00000001, 0x00101046,
2423 0x00000003, 0x08000000, 0x001000c2, 0x00000002, 0x80100406, 0x00000041, 0x00000003, 0x00100406,
2424 0x00000004, 0x0800000f, 0x00100082, 0x00000000, 0x00208046, 0x00000000, 0x00000003, 0x00100ae6,
2425 0x00000002, 0x06000036, 0x00100042, 0x00000003, 0x8010003a, 0x00000041, 0x00000000, 0x0800000f,
2426 0x00100082, 0x00000003, 0x00208046, 0x00000000, 0x00000002, 0x00100ae6, 0x00000002, 0x0700000f,
2427 0x00100082, 0x00000000, 0x00100ae6, 0x00000003, 0x00100ae6, 0x00000003, 0x05000044, 0x00100082,
2428 0x00000000, 0x0010003a, 0x00000000, 0x07000038, 0x001000c2, 0x00000003, 0x00100ff6, 0x00000000,
2429 0x00100ea6, 0x00000003, 0x0700000f, 0x00100022, 0x00000004, 0x00100046, 0x00000002, 0x00100ae6,
2430 0x00000003, 0x06000036, 0x00100042, 0x00000000, 0x8010001a, 0x00000041, 0x00000000, 0x0800000f,
2431 0x00100012, 0x00000002, 0x00208046, 0x00000000, 0x00000000, 0x00101046, 0x00000002, 0x0800000f,
2432 0x00100022, 0x00000002, 0x00208046, 0x00000000, 0x00000001, 0x00101046, 0x00000002, 0x08000000,
2433 0x00100032, 0x00000005, 0x80100046, 0x00000041, 0x00000003, 0x00100046, 0x00000002, 0x06000036,
2434 0x00100042, 0x00000005, 0x8010001a, 0x00000041, 0x00000005, 0x0700000f, 0x00100022, 0x00000000,
2435 0x00100a26, 0x00000005, 0x00100ae6, 0x00000002, 0x0d000032, 0x00100032, 0x00000002, 0x80100ae6,
2436 0x00000041, 0x00000002, 0x00004002, 0x3f000000, 0x3f000000, 0x00000000, 0x00000000, 0x00100046,
2437 0x00000005, 0x0800000e, 0x00100032, 0x00000000, 0x80100a26, 0x00000041, 0x00000000, 0x00100556,
2438 0x00000000, 0x0700000f, 0x00100012, 0x00000002, 0x00100046, 0x00000000, 0x00100046, 0x00000002,
2439 0x0700000f, 0x00100022, 0x00000002, 0x00100046, 0x00000000, 0x00100046, 0x00000005, 0x0800000f,
2440 0x00100012, 0x00000000, 0x00208046, 0x00000000, 0x00000002, 0x00100046, 0x00000005, 0x0800000f,
2441 0x00100022, 0x00000000, 0x00208046, 0x00000000, 0x00000003, 0x00100046, 0x00000005, 0x0700000f,
2442 0x00100012, 0x00000000, 0x00100046, 0x00000000, 0x00100ae6, 0x00000003, 0x07000031, 0x00100022,
2443 0x00000000, 0x00004001, 0x00000000, 0x0010000a, 0x00000000, 0x07000031, 0x00100042, 0x00000000,
2444 0x0010000a, 0x00000000, 0x00004001, 0x00000000, 0x08000031, 0x00100012, 0x00000000, 0x8010000a,
2445 0x00000081, 0x00000000, 0x00004001, 0x3f800000, 0x0800001e, 0x00100022, 0x00000000, 0x8010001a,
2446 0x00000041, 0x00000000, 0x0010002a, 0x00000000, 0x0500002b, 0x00100022, 0x00000000, 0x0010001a,
2447 0x00000000, 0x07000038, 0x001000c2, 0x00000002, 0x00100ea6, 0x00000003, 0x00100556, 0x00000000,
2448 0x08000036, 0x001000d2, 0x00000004, 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
2449 0x09000037, 0x001020f2, 0x00000001, 0x00100006, 0x00000000, 0x00100e46, 0x00000004, 0x00100e46,
2450 0x00000002, 0x06000036, 0x00100032, 0x00000000, 0x00208046, 0x00000000, 0x00000002, 0x06000036,
2451 0x001000c2, 0x00000000, 0x00208406, 0x00000000, 0x00000003, 0x08000038, 0x001000f2, 0x00000000,
2452 0x00100e46, 0x00000000, 0x00208ff6, 0x00000000, 0x00000001, 0x0a000038, 0x001000f2, 0x00000000,
2453 0x00100e46, 0x00000000, 0x00004002, 0x3f000000, 0x3f000000, 0x3f000000, 0x3f000000, 0x05000036,
2454 0x00102032, 0x00000002, 0x00100086, 0x00000000, 0x05000036, 0x00102032, 0x00000003, 0x001005d6,
2455 0x00000000, 0x05000036, 0x00100042, 0x00000001, 0x00004001, 0x3f800000, 0x08000010, 0x00100012,
2456 0x00000000, 0x00208246, 0x00000000, 0x00000002, 0x00100246, 0x00000001, 0x08000010, 0x00100022,
2457 0x00000000, 0x00208246, 0x00000000, 0x00000003, 0x00100246, 0x00000001, 0x08000038, 0x00100022,
2458 0x00000001, 0x0010001a, 0x00000000, 0x0020803a, 0x00000000, 0x00000003, 0x08000038, 0x00100012,
2459 0x00000001, 0x0010000a, 0x00000000, 0x0020803a, 0x00000000, 0x00000002, 0x0a000000, 0x00102032,
2460 0x00000004, 0x00100046, 0x00000001, 0x00004002, 0xbf800000, 0x3f800000, 0x00000000, 0x00000000,
2461 0x08000036, 0x001020c2, 0x00000004, 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x3f800000,
2462 0x0100003e,
2464 static const DWORD vs_code_triangle[] =
2466 #if 0
2467 float3x2 transform_geometry;
2468 float4 transform_rtx;
2469 float4 transform_rty;
2471 struct output
2473 float2 p : WORLD_POSITION;
2474 float4 b : BEZIER;
2475 nointerpolation float2x2 stroke_transform : STROKE_TRANSFORM;
2476 float4 position : SV_POSITION;
2479 void main(float2 position : POSITION, out struct output o)
2481 o.p = mul(float3(position, 1.0f), transform_geometry);
2482 o.b = float4(1.0, 0.0, 1.0, 1.0);
2483 o.stroke_transform = float2x2(1.0, 0.0, 0.0, 1.0);
2484 position = mul(float2x3(transform_rtx.xyz, transform_rty.xyz), float3(o.p, 1.0f))
2485 * float2(transform_rtx.w, transform_rty.w);
2486 o.position = float4(position + float2(-1.0f, 1.0f), 0.0f, 1.0f);
2488 #endif
2489 0x43425844, 0xda43bf17, 0x06e6d155, 0xdbce2ae5, 0x8aed6fd8, 0x00000001, 0x0000034c, 0x00000003,
2490 0x0000002c, 0x00000060, 0x0000011c, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020,
2491 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000303, 0x49534f50, 0x4e4f4954, 0xababab00,
2492 0x4e47534f, 0x000000b4, 0x00000005, 0x00000008, 0x00000080, 0x00000000, 0x00000000, 0x00000003,
2493 0x00000000, 0x00000c03, 0x0000008f, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x0000000f,
2494 0x00000096, 0x00000000, 0x00000000, 0x00000003, 0x00000002, 0x00000c03, 0x00000096, 0x00000001,
2495 0x00000000, 0x00000003, 0x00000003, 0x00000c03, 0x000000a7, 0x00000000, 0x00000001, 0x00000003,
2496 0x00000004, 0x0000000f, 0x4c524f57, 0x4f505f44, 0x49544953, 0x42004e4f, 0x45495a45, 0x54530052,
2497 0x454b4f52, 0x4152545f, 0x4f46534e, 0x53004d52, 0x4f505f56, 0x49544953, 0xab004e4f, 0x52444853,
2498 0x00000228, 0x00010040, 0x0000008a, 0x04000059, 0x00208e46, 0x00000000, 0x00000004, 0x0300005f,
2499 0x00101032, 0x00000000, 0x03000065, 0x00102032, 0x00000000, 0x03000065, 0x001020f2, 0x00000001,
2500 0x03000065, 0x00102032, 0x00000002, 0x03000065, 0x00102032, 0x00000003, 0x04000067, 0x001020f2,
2501 0x00000004, 0x00000001, 0x02000068, 0x00000002, 0x05000036, 0x00100032, 0x00000000, 0x00101046,
2502 0x00000000, 0x05000036, 0x00100042, 0x00000000, 0x00004001, 0x3f800000, 0x08000010, 0x00100012,
2503 0x00000001, 0x00100246, 0x00000000, 0x00208246, 0x00000000, 0x00000000, 0x08000010, 0x00100022,
2504 0x00000001, 0x00100246, 0x00000000, 0x00208246, 0x00000000, 0x00000001, 0x05000036, 0x00102032,
2505 0x00000000, 0x00100046, 0x00000001, 0x08000036, 0x001020f2, 0x00000001, 0x00004002, 0x3f800000,
2506 0x00000000, 0x3f800000, 0x3f800000, 0x08000036, 0x00102032, 0x00000002, 0x00004002, 0x3f800000,
2507 0x00000000, 0x00000000, 0x00000000, 0x08000036, 0x00102032, 0x00000003, 0x00004002, 0x00000000,
2508 0x3f800000, 0x00000000, 0x00000000, 0x05000036, 0x00100042, 0x00000001, 0x00004001, 0x3f800000,
2509 0x08000010, 0x00100012, 0x00000000, 0x00208246, 0x00000000, 0x00000002, 0x00100246, 0x00000001,
2510 0x08000010, 0x00100022, 0x00000000, 0x00208246, 0x00000000, 0x00000003, 0x00100246, 0x00000001,
2511 0x08000038, 0x00100022, 0x00000001, 0x0010001a, 0x00000000, 0x0020803a, 0x00000000, 0x00000003,
2512 0x08000038, 0x00100012, 0x00000001, 0x0010000a, 0x00000000, 0x0020803a, 0x00000000, 0x00000002,
2513 0x0a000000, 0x00102032, 0x00000004, 0x00100046, 0x00000001, 0x00004002, 0xbf800000, 0x3f800000,
2514 0x00000000, 0x00000000, 0x08000036, 0x001020c2, 0x00000004, 0x00004002, 0x00000000, 0x00000000,
2515 0x00000000, 0x3f800000, 0x0100003e,
2517 static const DWORD vs_code_bezier[] =
2519 #if 0
2520 float3x2 transform_geometry;
2521 float4 transform_rtx;
2522 float4 transform_rty;
2524 struct output
2526 float2 p : WORLD_POSITION;
2527 float4 b : BEZIER;
2528 nointerpolation float2x2 stroke_transform : STROKE_TRANSFORM;
2529 float4 position : SV_POSITION;
2532 void main(float2 position : POSITION, float3 texcoord : TEXCOORD0, out struct output o)
2534 o.p = mul(float3(position, 1.0f), transform_geometry);
2535 o.b = float4(texcoord, 1.0);
2536 o.stroke_transform = float2x2(1.0, 0.0, 0.0, 1.0);
2537 position = mul(float2x3(transform_rtx.xyz, transform_rty.xyz), float3(o.p, 1.0f))
2538 * float2(transform_rtx.w, transform_rty.w);
2539 o.position = float4(position + float2(-1.0f, 1.0f), 0.0f, 1.0f);
2541 #endif
2542 0x43425844, 0xedb7472a, 0x2c2ea147, 0x36710079, 0xffc2e907, 0x00000001, 0x00000380, 0x00000003,
2543 0x0000002c, 0x00000080, 0x0000013c, 0x4e475349, 0x0000004c, 0x00000002, 0x00000008, 0x00000038,
2544 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000303, 0x00000041, 0x00000000, 0x00000000,
2545 0x00000003, 0x00000001, 0x00000707, 0x49534f50, 0x4e4f4954, 0x58455400, 0x524f4f43, 0xabab0044,
2546 0x4e47534f, 0x000000b4, 0x00000005, 0x00000008, 0x00000080, 0x00000000, 0x00000000, 0x00000003,
2547 0x00000000, 0x00000c03, 0x0000008f, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x0000000f,
2548 0x00000096, 0x00000000, 0x00000000, 0x00000003, 0x00000002, 0x00000c03, 0x00000096, 0x00000001,
2549 0x00000000, 0x00000003, 0x00000003, 0x00000c03, 0x000000a7, 0x00000000, 0x00000001, 0x00000003,
2550 0x00000004, 0x0000000f, 0x4c524f57, 0x4f505f44, 0x49544953, 0x42004e4f, 0x45495a45, 0x54530052,
2551 0x454b4f52, 0x4152545f, 0x4f46534e, 0x53004d52, 0x4f505f56, 0x49544953, 0xab004e4f, 0x52444853,
2552 0x0000023c, 0x00010040, 0x0000008f, 0x04000059, 0x00208e46, 0x00000000, 0x00000004, 0x0300005f,
2553 0x00101032, 0x00000000, 0x0300005f, 0x00101072, 0x00000001, 0x03000065, 0x00102032, 0x00000000,
2554 0x03000065, 0x001020f2, 0x00000001, 0x03000065, 0x00102032, 0x00000002, 0x03000065, 0x00102032,
2555 0x00000003, 0x04000067, 0x001020f2, 0x00000004, 0x00000001, 0x02000068, 0x00000002, 0x05000036,
2556 0x00100032, 0x00000000, 0x00101046, 0x00000000, 0x05000036, 0x00100042, 0x00000000, 0x00004001,
2557 0x3f800000, 0x08000010, 0x00100012, 0x00000001, 0x00100246, 0x00000000, 0x00208246, 0x00000000,
2558 0x00000000, 0x08000010, 0x00100022, 0x00000001, 0x00100246, 0x00000000, 0x00208246, 0x00000000,
2559 0x00000001, 0x05000036, 0x00102032, 0x00000000, 0x00100046, 0x00000001, 0x05000036, 0x00102072,
2560 0x00000001, 0x00101246, 0x00000001, 0x05000036, 0x00102082, 0x00000001, 0x00004001, 0x3f800000,
2561 0x08000036, 0x00102032, 0x00000002, 0x00004002, 0x3f800000, 0x00000000, 0x00000000, 0x00000000,
2562 0x08000036, 0x00102032, 0x00000003, 0x00004002, 0x00000000, 0x3f800000, 0x00000000, 0x00000000,
2563 0x05000036, 0x00100042, 0x00000001, 0x00004001, 0x3f800000, 0x08000010, 0x00100012, 0x00000000,
2564 0x00208246, 0x00000000, 0x00000002, 0x00100246, 0x00000001, 0x08000010, 0x00100022, 0x00000000,
2565 0x00208246, 0x00000000, 0x00000003, 0x00100246, 0x00000001, 0x08000038, 0x00100022, 0x00000001,
2566 0x0010001a, 0x00000000, 0x0020803a, 0x00000000, 0x00000003, 0x08000038, 0x00100012, 0x00000001,
2567 0x0010000a, 0x00000000, 0x0020803a, 0x00000000, 0x00000002, 0x0a000000, 0x00102032, 0x00000004,
2568 0x00100046, 0x00000001, 0x00004002, 0xbf800000, 0x3f800000, 0x00000000, 0x00000000, 0x08000036,
2569 0x001020c2, 0x00000004, 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, 0x0100003e,
2571 static const DWORD ps_code[] =
2573 #if 0
2574 #define BRUSH_TYPE_SOLID 0
2575 #define BRUSH_TYPE_LINEAR 1
2576 #define BRUSH_TYPE_RADIAL 2
2577 #define BRUSH_TYPE_BITMAP 3
2578 #define BRUSH_TYPE_COUNT 4
2580 bool outline;
2581 struct brush
2583 uint type;
2584 float opacity;
2585 float4 data[3];
2586 } colour_brush, opacity_brush;
2588 SamplerState s0, s1;
2589 Texture2D t0, t1;
2590 Buffer<float4> b0, b1;
2592 struct input
2594 float2 p : WORLD_POSITION;
2595 float4 b : BEZIER;
2596 nointerpolation float2x2 stroke_transform : STROKE_TRANSFORM;
2599 float4 sample_gradient(Buffer<float4> gradient, uint stop_count, float position)
2601 float4 c_low, c_high;
2602 float p_low, p_high;
2603 uint i;
2605 p_low = gradient.Load(0).x;
2606 c_low = gradient.Load(1);
2607 c_high = c_low;
2609 if (position < p_low)
2610 return c_low;
2612 for (i = 1; i < stop_count; ++i)
2614 p_high = gradient.Load(i * 2).x;
2615 c_high = gradient.Load(i * 2 + 1);
2617 if (position >= p_low && position <= p_high)
2618 return lerp(c_low, c_high, (position - p_low) / (p_high - p_low));
2620 p_low = p_high;
2621 c_low = c_high;
2624 return c_high;
2627 float4 brush_linear(struct brush brush, Buffer<float4> gradient, float2 position)
2629 float2 start, end, v_p, v_q;
2630 uint stop_count;
2631 float p;
2633 start = brush.data[0].xy;
2634 end = brush.data[0].zw;
2635 stop_count = asuint(brush.data[1].x);
2637 v_p = position - start;
2638 v_q = end - start;
2639 p = dot(v_q, v_p) / dot(v_q, v_q);
2641 return sample_gradient(gradient, stop_count, p);
2644 float4 brush_radial(struct brush brush, Buffer<float4> gradient, float2 position)
2646 float2 centre, offset, ra, rb, v_p, v_q, r;
2647 float b, c, l, t;
2648 uint stop_count;
2650 centre = brush.data[0].xy;
2651 offset = brush.data[0].zw;
2652 ra = brush.data[1].xy;
2653 rb = brush.data[1].zw;
2654 stop_count = asuint(brush.data[2].x);
2656 /* Project onto ra, rb. */
2657 r = float2(dot(ra, ra), dot(rb, rb));
2658 v_p = position - (centre + offset);
2659 v_p = float2(dot(v_p, ra), dot(v_p, rb)) / r;
2660 v_q = float2(dot(offset, ra), dot(offset, rb)) / r;
2662 /* ‖t·p̂ + q⃑‖ = 1
2663 * (t·p̂ + q⃑) · (t·p̂ + q⃑) = 1
2664 * t² + 2·(p̂·q⃑)·t + (q⃑·q⃑) = 1
2666 * b = p̂·q⃑
2667 * c = q⃑·q⃑ - 1
2668 * t = -b + √(b² - c) */
2669 l = length(v_p);
2670 b = dot(v_p, v_q) / l;
2671 c = dot(v_q, v_q) - 1.0;
2672 t = -b + sqrt(b * b - c);
2674 return sample_gradient(gradient, stop_count, l / t);
2677 float4 brush_bitmap(struct brush brush, Texture2D t, SamplerState s, float2 position)
2679 float3 transform[2];
2680 bool ignore_alpha;
2681 float2 texcoord;
2682 float4 colour;
2684 transform[0] = brush.data[0].xyz;
2685 transform[1] = brush.data[1].xyz;
2686 ignore_alpha = asuint(brush.data[1].w);
2688 texcoord.x = dot(position.xy, transform[0].xy) + transform[0].z;
2689 texcoord.y = dot(position.xy, transform[1].xy) + transform[1].z;
2690 colour = t.Sample(s, texcoord);
2691 if (ignore_alpha)
2692 colour.a = 1.0;
2693 return colour;
2696 float4 sample_brush(struct brush brush, Texture2D t, SamplerState s, Buffer<float4> b, float2 position)
2698 if (brush.type == BRUSH_TYPE_SOLID)
2699 return brush.data[0] * brush.opacity;
2700 if (brush.type == BRUSH_TYPE_LINEAR)
2701 return brush_linear(brush, b, position) * brush.opacity;
2702 if (brush.type == BRUSH_TYPE_RADIAL)
2703 return brush_radial(brush, b, position) * brush.opacity;
2704 if (brush.type == BRUSH_TYPE_BITMAP)
2705 return brush_bitmap(brush, t, s, position) * brush.opacity;
2706 return float4(0.0, 0.0, 0.0, brush.opacity);
2709 float4 main(struct input i) : SV_Target
2711 float4 colour;
2713 colour = sample_brush(colour_brush, t0, s0, b0, i.p);
2714 if (opacity_brush.type < BRUSH_TYPE_COUNT)
2715 colour *= sample_brush(opacity_brush, t1, s1, b1, i.p).a;
2717 if (outline)
2719 float2 du, dv, df;
2720 float4 uv;
2722 /* Evaluate the implicit form of the curve (u² - v = 0) in texture space,
2723 * using the screen-space partial derivatives to convert the calculated
2724 * distance to object space.
2726 * d(x, y) = |f(x, y)| / ‖∇f(x, y)‖
2727 * = |f(x, y)| / √((∂f/∂x)² + (∂f/∂y)²)
2728 * f(x, y) = u(x, y)² - v(x, y)
2729 * ∂f/∂x = 2u · ∂u/∂x - ∂v/∂x
2730 * ∂f/∂y = 2u · ∂u/∂y - ∂v/∂y */
2731 uv = i.b;
2732 du = float2(ddx(uv.x), ddy(uv.x));
2733 dv = float2(ddx(uv.y), ddy(uv.y));
2734 df = 2.0f * uv.x * du - dv;
2736 clip(dot(df, uv.zw));
2737 clip(length(mul(i.stroke_transform, df)) - abs(uv.x * uv.x - uv.y));
2739 else
2741 /* Evaluate the implicit form of the curve in texture space.
2742 * "i.b.z" determines which side of the curve is shaded. */
2743 clip((i.b.x * i.b.x - i.b.y) * i.b.z);
2746 return colour;
2748 #endif
2749 0x43425844, 0xf3cbb8bd, 0x5f286454, 0x139976a7, 0x6817e876, 0x00000001, 0x00001d18, 0x00000003,
2750 0x0000002c, 0x000000c4, 0x000000f8, 0x4e475349, 0x00000090, 0x00000004, 0x00000008, 0x00000068,
2751 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000303, 0x00000077, 0x00000000, 0x00000000,
2752 0x00000003, 0x00000001, 0x00000f0f, 0x0000007e, 0x00000000, 0x00000000, 0x00000003, 0x00000002,
2753 0x00000303, 0x0000007e, 0x00000001, 0x00000000, 0x00000003, 0x00000003, 0x00000303, 0x4c524f57,
2754 0x4f505f44, 0x49544953, 0x42004e4f, 0x45495a45, 0x54530052, 0x454b4f52, 0x4152545f, 0x4f46534e,
2755 0xab004d52, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000,
2756 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x00001c18,
2757 0x00000040, 0x00000706, 0x04000059, 0x00208e46, 0x00000000, 0x00000009, 0x0300005a, 0x00106000,
2758 0x00000000, 0x0300005a, 0x00106000, 0x00000001, 0x04001858, 0x00107000, 0x00000000, 0x00005555,
2759 0x04001858, 0x00107000, 0x00000001, 0x00005555, 0x04000858, 0x00107000, 0x00000002, 0x00005555,
2760 0x04000858, 0x00107000, 0x00000003, 0x00005555, 0x03001062, 0x00101032, 0x00000000, 0x03001062,
2761 0x001010f2, 0x00000001, 0x03000862, 0x00101032, 0x00000002, 0x03000862, 0x00101032, 0x00000003,
2762 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x0000000a, 0x09000038, 0x001000f2, 0x00000000,
2763 0x00208556, 0x00000000, 0x00000001, 0x00208e46, 0x00000000, 0x00000002, 0x0404001f, 0x0020800a,
2764 0x00000000, 0x00000001, 0x08000020, 0x00100012, 0x00000001, 0x0020800a, 0x00000000, 0x00000001,
2765 0x00004001, 0x00000001, 0x0304001f, 0x0010000a, 0x00000001, 0x09000000, 0x00100062, 0x00000001,
2766 0x00101106, 0x00000000, 0x80208106, 0x00000041, 0x00000000, 0x00000002, 0x0a000000, 0x00100032,
2767 0x00000002, 0x80208046, 0x00000041, 0x00000000, 0x00000002, 0x00208ae6, 0x00000000, 0x00000002,
2768 0x0700000f, 0x00100022, 0x00000001, 0x00100046, 0x00000002, 0x00100596, 0x00000001, 0x0700000f,
2769 0x00100042, 0x00000001, 0x00100046, 0x00000002, 0x00100046, 0x00000002, 0x0700000e, 0x00100022,
2770 0x00000001, 0x0010001a, 0x00000001, 0x0010002a, 0x00000001, 0x0a00002d, 0x001000f2, 0x00000002,
2771 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00107e46, 0x00000002, 0x0a00002d,
2772 0x001000f2, 0x00000003, 0x00004002, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00107e46,
2773 0x00000002, 0x0700001d, 0x00100042, 0x00000001, 0x0010001a, 0x00000001, 0x0010000a, 0x00000002,
2774 0x0304001f, 0x0010002a, 0x00000001, 0x05000036, 0x001000f2, 0x00000004, 0x00100e46, 0x00000003,
2775 0x05000036, 0x001000f2, 0x00000005, 0x00100e46, 0x00000003, 0x05000036, 0x001000f2, 0x00000006,
2776 0x00100e46, 0x00000003, 0x05000036, 0x00100042, 0x00000001, 0x0010000a, 0x00000002, 0x05000036,
2777 0x00100082, 0x00000001, 0x00004001, 0x00000001, 0x05000036, 0x00100022, 0x00000002, 0x00004001,
2778 0x00000000, 0x01000030, 0x08000050, 0x00100042, 0x00000002, 0x0010003a, 0x00000001, 0x0020800a,
2779 0x00000000, 0x00000003, 0x05000036, 0x00100022, 0x00000002, 0x00004001, 0x00000000, 0x03040003,
2780 0x0010002a, 0x00000002, 0x07000029, 0x00100042, 0x00000002, 0x0010003a, 0x00000001, 0x00004001,
2781 0x00000001, 0x0700002d, 0x001000f2, 0x00000007, 0x00100aa6, 0x00000002, 0x00107e46, 0x00000002,
2782 0x0700001e, 0x00100042, 0x00000002, 0x0010002a, 0x00000002, 0x00004001, 0x00000001, 0x0700002d,
2783 0x001000f2, 0x00000008, 0x00100aa6, 0x00000002, 0x00107e46, 0x00000002, 0x0700001d, 0x00100042,
2784 0x00000002, 0x0010001a, 0x00000001, 0x0010002a, 0x00000001, 0x0700001d, 0x00100082, 0x00000002,
2785 0x0010000a, 0x00000007, 0x0010001a, 0x00000001, 0x07000001, 0x00100042, 0x00000002, 0x0010003a,
2786 0x00000002, 0x0010002a, 0x00000002, 0x0304001f, 0x0010002a, 0x00000002, 0x08000000, 0x00100082,
2787 0x00000002, 0x8010002a, 0x00000041, 0x00000001, 0x0010001a, 0x00000001, 0x08000000, 0x00100022,
2788 0x00000007, 0x8010002a, 0x00000041, 0x00000001, 0x0010000a, 0x00000007, 0x0700000e, 0x00100082,
2789 0x00000002, 0x0010003a, 0x00000002, 0x0010001a, 0x00000007, 0x08000000, 0x001000f2, 0x00000009,
2790 0x80100e46, 0x00000041, 0x00000005, 0x00100e46, 0x00000008, 0x09000032, 0x001000f2, 0x00000009,
2791 0x00100ff6, 0x00000002, 0x00100e46, 0x00000009, 0x00100e46, 0x00000005, 0x05000036, 0x001000f2,
2792 0x00000006, 0x00100e46, 0x00000008, 0x05000036, 0x00100022, 0x00000002, 0x00004001, 0xffffffff,
2793 0x05000036, 0x001000f2, 0x00000004, 0x00100e46, 0x00000009, 0x01000002, 0x01000015, 0x05000036,
2794 0x001000f2, 0x00000005, 0x00100e46, 0x00000008, 0x05000036, 0x00100042, 0x00000001, 0x0010000a,
2795 0x00000007, 0x0700001e, 0x00100082, 0x00000001, 0x0010003a, 0x00000001, 0x00004001, 0x00000001,
2796 0x05000036, 0x001000f2, 0x00000006, 0x00100e46, 0x00000008, 0x05000036, 0x00100022, 0x00000002,
2797 0x0010002a, 0x00000002, 0x01000016, 0x09000037, 0x001000f2, 0x00000003, 0x00100556, 0x00000002,
2798 0x00100e46, 0x00000004, 0x00100e46, 0x00000006, 0x01000015, 0x08000038, 0x001000f2, 0x00000000,
2799 0x00100e46, 0x00000003, 0x00208556, 0x00000000, 0x00000001, 0x01000015, 0x0300001f, 0x0010000a,
2800 0x00000001, 0x08000020, 0x00100012, 0x00000001, 0x0020800a, 0x00000000, 0x00000001, 0x00004001,
2801 0x00000002, 0x0304001f, 0x0010000a, 0x00000001, 0x0900000f, 0x00100012, 0x00000002, 0x00208046,
2802 0x00000000, 0x00000003, 0x00208046, 0x00000000, 0x00000003, 0x0900000f, 0x00100022, 0x00000002,
2803 0x00208ae6, 0x00000000, 0x00000003, 0x00208ae6, 0x00000000, 0x00000003, 0x09000000, 0x00100062,
2804 0x00000001, 0x00208ba6, 0x00000000, 0x00000002, 0x00208106, 0x00000000, 0x00000002, 0x08000000,
2805 0x00100062, 0x00000001, 0x80100656, 0x00000041, 0x00000001, 0x00101106, 0x00000000, 0x0800000f,
2806 0x00100012, 0x00000003, 0x00100596, 0x00000001, 0x00208046, 0x00000000, 0x00000003, 0x0800000f,
2807 0x00100022, 0x00000003, 0x00100596, 0x00000001, 0x00208ae6, 0x00000000, 0x00000003, 0x0700000e,
2808 0x00100062, 0x00000001, 0x00100106, 0x00000003, 0x00100106, 0x00000002, 0x0900000f, 0x00100012,
2809 0x00000003, 0x00208ae6, 0x00000000, 0x00000002, 0x00208046, 0x00000000, 0x00000003, 0x0900000f,
2810 0x00100022, 0x00000003, 0x00208ae6, 0x00000000, 0x00000002, 0x00208ae6, 0x00000000, 0x00000003,
2811 0x0700000e, 0x00100032, 0x00000002, 0x00100046, 0x00000003, 0x00100046, 0x00000002, 0x0700000f,
2812 0x00100082, 0x00000001, 0x00100596, 0x00000001, 0x00100596, 0x00000001, 0x0500004b, 0x00100082,
2813 0x00000001, 0x0010003a, 0x00000001, 0x0700000f, 0x00100022, 0x00000001, 0x00100596, 0x00000001,
2814 0x00100046, 0x00000002, 0x0700000e, 0x00100022, 0x00000001, 0x0010001a, 0x00000001, 0x0010003a,
2815 0x00000001, 0x0700000f, 0x00100042, 0x00000001, 0x00100046, 0x00000002, 0x00100046, 0x00000002,
2816 0x07000000, 0x00100042, 0x00000001, 0x0010002a, 0x00000001, 0x00004001, 0xbf800000, 0x0a000032,
2817 0x00100042, 0x00000001, 0x0010001a, 0x00000001, 0x0010001a, 0x00000001, 0x8010002a, 0x00000041,
2818 0x00000001, 0x0500004b, 0x00100042, 0x00000001, 0x0010002a, 0x00000001, 0x08000000, 0x00100022,
2819 0x00000001, 0x0010002a, 0x00000001, 0x8010001a, 0x00000041, 0x00000001, 0x0700000e, 0x00100022,
2820 0x00000001, 0x0010003a, 0x00000001, 0x0010001a, 0x00000001, 0x0a00002d, 0x001000f2, 0x00000002,
2821 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00107e46, 0x00000002, 0x0a00002d,
2822 0x001000f2, 0x00000003, 0x00004002, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00107e46,
2823 0x00000002, 0x0700001d, 0x00100042, 0x00000001, 0x0010001a, 0x00000001, 0x0010000a, 0x00000002,
2824 0x0304001f, 0x0010002a, 0x00000001, 0x05000036, 0x001000f2, 0x00000004, 0x00100e46, 0x00000003,
2825 0x05000036, 0x001000f2, 0x00000005, 0x00100e46, 0x00000003, 0x05000036, 0x001000f2, 0x00000006,
2826 0x00100e46, 0x00000003, 0x05000036, 0x00100042, 0x00000001, 0x0010000a, 0x00000002, 0x05000036,
2827 0x00100082, 0x00000001, 0x00004001, 0x00000001, 0x05000036, 0x00100022, 0x00000002, 0x00004001,
2828 0x00000000, 0x01000030, 0x08000050, 0x00100042, 0x00000002, 0x0010003a, 0x00000001, 0x0020800a,
2829 0x00000000, 0x00000004, 0x05000036, 0x00100022, 0x00000002, 0x00004001, 0x00000000, 0x03040003,
2830 0x0010002a, 0x00000002, 0x07000029, 0x00100042, 0x00000002, 0x0010003a, 0x00000001, 0x00004001,
2831 0x00000001, 0x0700002d, 0x001000f2, 0x00000007, 0x00100aa6, 0x00000002, 0x00107e46, 0x00000002,
2832 0x0700001e, 0x00100042, 0x00000002, 0x0010002a, 0x00000002, 0x00004001, 0x00000001, 0x0700002d,
2833 0x001000f2, 0x00000008, 0x00100aa6, 0x00000002, 0x00107e46, 0x00000002, 0x0700001d, 0x00100042,
2834 0x00000002, 0x0010001a, 0x00000001, 0x0010002a, 0x00000001, 0x0700001d, 0x00100082, 0x00000002,
2835 0x0010000a, 0x00000007, 0x0010001a, 0x00000001, 0x07000001, 0x00100042, 0x00000002, 0x0010003a,
2836 0x00000002, 0x0010002a, 0x00000002, 0x0304001f, 0x0010002a, 0x00000002, 0x08000000, 0x00100082,
2837 0x00000002, 0x8010002a, 0x00000041, 0x00000001, 0x0010001a, 0x00000001, 0x08000000, 0x00100022,
2838 0x00000007, 0x8010002a, 0x00000041, 0x00000001, 0x0010000a, 0x00000007, 0x0700000e, 0x00100082,
2839 0x00000002, 0x0010003a, 0x00000002, 0x0010001a, 0x00000007, 0x08000000, 0x001000f2, 0x00000009,
2840 0x80100e46, 0x00000041, 0x00000005, 0x00100e46, 0x00000008, 0x09000032, 0x001000f2, 0x00000009,
2841 0x00100ff6, 0x00000002, 0x00100e46, 0x00000009, 0x00100e46, 0x00000005, 0x05000036, 0x001000f2,
2842 0x00000006, 0x00100e46, 0x00000008, 0x05000036, 0x00100022, 0x00000002, 0x00004001, 0xffffffff,
2843 0x05000036, 0x001000f2, 0x00000004, 0x00100e46, 0x00000009, 0x01000002, 0x01000015, 0x05000036,
2844 0x001000f2, 0x00000005, 0x00100e46, 0x00000008, 0x05000036, 0x00100042, 0x00000001, 0x0010000a,
2845 0x00000007, 0x0700001e, 0x00100082, 0x00000001, 0x0010003a, 0x00000001, 0x00004001, 0x00000001,
2846 0x05000036, 0x001000f2, 0x00000006, 0x00100e46, 0x00000008, 0x05000036, 0x00100022, 0x00000002,
2847 0x0010002a, 0x00000002, 0x01000016, 0x09000037, 0x001000f2, 0x00000003, 0x00100556, 0x00000002,
2848 0x00100e46, 0x00000004, 0x00100e46, 0x00000006, 0x01000015, 0x08000038, 0x001000f2, 0x00000000,
2849 0x00100e46, 0x00000003, 0x00208556, 0x00000000, 0x00000001, 0x01000015, 0x0300001f, 0x0010000a,
2850 0x00000001, 0x08000020, 0x00100012, 0x00000001, 0x0020800a, 0x00000000, 0x00000001, 0x00004001,
2851 0x00000003, 0x0304001f, 0x0010000a, 0x00000001, 0x0800000f, 0x00100022, 0x00000001, 0x00101046,
2852 0x00000000, 0x00208046, 0x00000000, 0x00000002, 0x08000000, 0x00100012, 0x00000002, 0x0010001a,
2853 0x00000001, 0x0020802a, 0x00000000, 0x00000002, 0x0800000f, 0x00100022, 0x00000001, 0x00101046,
2854 0x00000000, 0x00208046, 0x00000000, 0x00000003, 0x08000000, 0x00100022, 0x00000002, 0x0010001a,
2855 0x00000001, 0x0020802a, 0x00000000, 0x00000003, 0x09000045, 0x001000f2, 0x00000002, 0x00100046,
2856 0x00000002, 0x00107e46, 0x00000000, 0x00106000, 0x00000000, 0x0a000037, 0x00100082, 0x00000002,
2857 0x0020803a, 0x00000000, 0x00000003, 0x00004001, 0x3f800000, 0x0010003a, 0x00000002, 0x08000038,
2858 0x001000f2, 0x00000000, 0x00100e46, 0x00000002, 0x00208556, 0x00000000, 0x00000001, 0x01000015,
2859 0x05000036, 0x00100012, 0x00000002, 0x00004001, 0x00000000, 0x06000036, 0x00100082, 0x00000002,
2860 0x0020801a, 0x00000000, 0x00000001, 0x09000037, 0x001000f2, 0x00000000, 0x00100006, 0x00000001,
2861 0x00100e46, 0x00000000, 0x00100c06, 0x00000002, 0x01000015, 0x01000015, 0x01000015, 0x0800004f,
2862 0x00100012, 0x00000001, 0x0020800a, 0x00000000, 0x00000005, 0x00004001, 0x00000004, 0x0304001f,
2863 0x0010000a, 0x00000001, 0x09000038, 0x00100012, 0x00000001, 0x0020801a, 0x00000000, 0x00000005,
2864 0x0020803a, 0x00000000, 0x00000006, 0x0404001f, 0x0020800a, 0x00000000, 0x00000005, 0x08000020,
2865 0x00100022, 0x00000001, 0x0020800a, 0x00000000, 0x00000005, 0x00004001, 0x00000001, 0x0304001f,
2866 0x0010001a, 0x00000001, 0x09000000, 0x001000c2, 0x00000001, 0x00101406, 0x00000000, 0x80208406,
2867 0x00000041, 0x00000000, 0x00000006, 0x0a000000, 0x00100032, 0x00000002, 0x80208046, 0x00000041,
2868 0x00000000, 0x00000006, 0x00208ae6, 0x00000000, 0x00000006, 0x0700000f, 0x00100042, 0x00000001,
2869 0x00100046, 0x00000002, 0x00100ae6, 0x00000001, 0x0700000f, 0x00100082, 0x00000001, 0x00100046,
2870 0x00000002, 0x00100046, 0x00000002, 0x0700000e, 0x00100042, 0x00000001, 0x0010002a, 0x00000001,
2871 0x0010003a, 0x00000001, 0x0a00002d, 0x001000f2, 0x00000002, 0x00004002, 0x00000000, 0x00000000,
2872 0x00000000, 0x00000000, 0x00107e46, 0x00000003, 0x0a00002d, 0x001000f2, 0x00000003, 0x00004002,
2873 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00107e46, 0x00000003, 0x0700001d, 0x00100082,
2874 0x00000001, 0x0010002a, 0x00000001, 0x0010000a, 0x00000002, 0x0304001f, 0x0010003a, 0x00000001,
2875 0x05000036, 0x00100082, 0x00000001, 0x0010003a, 0x00000003, 0x05000036, 0x00100062, 0x00000002,
2876 0x00100ff6, 0x00000003, 0x05000036, 0x00100082, 0x00000002, 0x0010000a, 0x00000002, 0x08000036,
2877 0x00100032, 0x00000003, 0x00004002, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x01000030,
2878 0x08000050, 0x00100042, 0x00000003, 0x0010000a, 0x00000003, 0x0020800a, 0x00000000, 0x00000007,
2879 0x05000036, 0x00100022, 0x00000003, 0x00004001, 0x00000000, 0x03040003, 0x0010002a, 0x00000003,
2880 0x07000029, 0x00100042, 0x00000003, 0x0010000a, 0x00000003, 0x00004001, 0x00000001, 0x0700002d,
2881 0x001000f2, 0x00000004, 0x00100aa6, 0x00000003, 0x00107e46, 0x00000003, 0x0700001e, 0x00100042,
2882 0x00000003, 0x0010002a, 0x00000003, 0x00004001, 0x00000001, 0x0700002d, 0x001000f2, 0x00000005,
2883 0x00100aa6, 0x00000003, 0x00107e46, 0x00000003, 0x0700001d, 0x00100042, 0x00000003, 0x0010002a,
2884 0x00000001, 0x0010003a, 0x00000002, 0x0700001d, 0x00100022, 0x00000004, 0x0010000a, 0x00000004,
2885 0x0010002a, 0x00000001, 0x07000001, 0x00100042, 0x00000003, 0x0010002a, 0x00000003, 0x0010001a,
2886 0x00000004, 0x0304001f, 0x0010002a, 0x00000003, 0x08000000, 0x00100022, 0x00000004, 0x0010002a,
2887 0x00000001, 0x8010003a, 0x00000041, 0x00000002, 0x08000000, 0x00100042, 0x00000004, 0x8010003a,
2888 0x00000041, 0x00000002, 0x0010000a, 0x00000004, 0x0700000e, 0x00100022, 0x00000004, 0x0010001a,
2889 0x00000004, 0x0010002a, 0x00000004, 0x08000000, 0x00100042, 0x00000004, 0x8010001a, 0x00000041,
2890 0x00000002, 0x0010003a, 0x00000005, 0x09000032, 0x00100022, 0x00000004, 0x0010001a, 0x00000004,
2891 0x0010002a, 0x00000004, 0x0010001a, 0x00000002, 0x05000036, 0x00100042, 0x00000002, 0x0010003a,
2892 0x00000005, 0x05000036, 0x00100022, 0x00000003, 0x00004001, 0xffffffff, 0x05000036, 0x00100082,
2893 0x00000001, 0x0010001a, 0x00000004, 0x01000002, 0x01000015, 0x05000036, 0x00100022, 0x00000002,
2894 0x0010003a, 0x00000005, 0x05000036, 0x00100082, 0x00000002, 0x0010000a, 0x00000004, 0x0700001e,
2895 0x00100012, 0x00000003, 0x0010000a, 0x00000003, 0x00004001, 0x00000001, 0x05000036, 0x00100042,
2896 0x00000002, 0x0010003a, 0x00000005, 0x05000036, 0x00100032, 0x00000003, 0x00100086, 0x00000003,
2897 0x01000016, 0x09000037, 0x00100042, 0x00000001, 0x0010001a, 0x00000003, 0x0010003a, 0x00000001,
2898 0x0010002a, 0x00000002, 0x01000012, 0x05000036, 0x00100042, 0x00000001, 0x0010003a, 0x00000003,
2899 0x01000015, 0x08000038, 0x00100012, 0x00000001, 0x0010002a, 0x00000001, 0x0020801a, 0x00000000,
2900 0x00000005, 0x01000015, 0x0300001f, 0x0010001a, 0x00000001, 0x08000020, 0x00100022, 0x00000001,
2901 0x0020800a, 0x00000000, 0x00000005, 0x00004001, 0x00000002, 0x0304001f, 0x0010001a, 0x00000001,
2902 0x0900000f, 0x00100012, 0x00000002, 0x00208046, 0x00000000, 0x00000007, 0x00208046, 0x00000000,
2903 0x00000007, 0x0900000f, 0x00100022, 0x00000002, 0x00208ae6, 0x00000000, 0x00000007, 0x00208ae6,
2904 0x00000000, 0x00000007, 0x09000000, 0x001000c2, 0x00000001, 0x00208ea6, 0x00000000, 0x00000006,
2905 0x00208406, 0x00000000, 0x00000006, 0x08000000, 0x001000c2, 0x00000001, 0x80100ea6, 0x00000041,
2906 0x00000001, 0x00101406, 0x00000000, 0x0800000f, 0x00100012, 0x00000003, 0x00100ae6, 0x00000001,
2907 0x00208046, 0x00000000, 0x00000007, 0x0800000f, 0x00100022, 0x00000003, 0x00100ae6, 0x00000001,
2908 0x00208ae6, 0x00000000, 0x00000007, 0x0700000e, 0x001000c2, 0x00000001, 0x00100406, 0x00000003,
2909 0x00100406, 0x00000002, 0x0900000f, 0x00100012, 0x00000003, 0x00208ae6, 0x00000000, 0x00000006,
2910 0x00208046, 0x00000000, 0x00000007, 0x0900000f, 0x00100022, 0x00000003, 0x00208ae6, 0x00000000,
2911 0x00000006, 0x00208ae6, 0x00000000, 0x00000007, 0x0700000e, 0x00100032, 0x00000002, 0x00100046,
2912 0x00000003, 0x00100046, 0x00000002, 0x0700000f, 0x00100042, 0x00000002, 0x00100ae6, 0x00000001,
2913 0x00100ae6, 0x00000001, 0x0500004b, 0x00100042, 0x00000002, 0x0010002a, 0x00000002, 0x0700000f,
2914 0x00100042, 0x00000001, 0x00100ae6, 0x00000001, 0x00100046, 0x00000002, 0x0700000e, 0x00100042,
2915 0x00000001, 0x0010002a, 0x00000001, 0x0010002a, 0x00000002, 0x0700000f, 0x00100082, 0x00000001,
2916 0x00100046, 0x00000002, 0x00100046, 0x00000002, 0x07000000, 0x00100082, 0x00000001, 0x0010003a,
2917 0x00000001, 0x00004001, 0xbf800000, 0x0a000032, 0x00100082, 0x00000001, 0x0010002a, 0x00000001,
2918 0x0010002a, 0x00000001, 0x8010003a, 0x00000041, 0x00000001, 0x0500004b, 0x00100082, 0x00000001,
2919 0x0010003a, 0x00000001, 0x08000000, 0x00100042, 0x00000001, 0x0010003a, 0x00000001, 0x8010002a,
2920 0x00000041, 0x00000001, 0x0700000e, 0x00100042, 0x00000001, 0x0010002a, 0x00000002, 0x0010002a,
2921 0x00000001, 0x0a00002d, 0x001000f2, 0x00000002, 0x00004002, 0x00000000, 0x00000000, 0x00000000,
2922 0x00000000, 0x00107e46, 0x00000003, 0x0a00002d, 0x001000f2, 0x00000003, 0x00004002, 0x00000001,
2923 0x00000001, 0x00000001, 0x00000001, 0x00107e46, 0x00000003, 0x0700001d, 0x00100082, 0x00000001,
2924 0x0010002a, 0x00000001, 0x0010000a, 0x00000002, 0x0304001f, 0x0010003a, 0x00000001, 0x05000036,
2925 0x00100082, 0x00000001, 0x0010003a, 0x00000003, 0x05000036, 0x00100062, 0x00000002, 0x00100ff6,
2926 0x00000003, 0x05000036, 0x00100082, 0x00000002, 0x0010000a, 0x00000002, 0x08000036, 0x00100032,
2927 0x00000003, 0x00004002, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x01000030, 0x08000050,
2928 0x00100042, 0x00000003, 0x0010000a, 0x00000003, 0x0020800a, 0x00000000, 0x00000008, 0x05000036,
2929 0x00100022, 0x00000003, 0x00004001, 0x00000000, 0x03040003, 0x0010002a, 0x00000003, 0x07000029,
2930 0x00100042, 0x00000003, 0x0010000a, 0x00000003, 0x00004001, 0x00000001, 0x0700002d, 0x001000f2,
2931 0x00000004, 0x00100aa6, 0x00000003, 0x00107e46, 0x00000003, 0x0700001e, 0x00100042, 0x00000003,
2932 0x0010002a, 0x00000003, 0x00004001, 0x00000001, 0x0700002d, 0x001000f2, 0x00000005, 0x00100aa6,
2933 0x00000003, 0x00107e46, 0x00000003, 0x0700001d, 0x00100042, 0x00000003, 0x0010002a, 0x00000001,
2934 0x0010003a, 0x00000002, 0x0700001d, 0x00100022, 0x00000004, 0x0010000a, 0x00000004, 0x0010002a,
2935 0x00000001, 0x07000001, 0x00100042, 0x00000003, 0x0010002a, 0x00000003, 0x0010001a, 0x00000004,
2936 0x0304001f, 0x0010002a, 0x00000003, 0x08000000, 0x00100022, 0x00000004, 0x0010002a, 0x00000001,
2937 0x8010003a, 0x00000041, 0x00000002, 0x08000000, 0x00100042, 0x00000004, 0x8010003a, 0x00000041,
2938 0x00000002, 0x0010000a, 0x00000004, 0x0700000e, 0x00100022, 0x00000004, 0x0010001a, 0x00000004,
2939 0x0010002a, 0x00000004, 0x08000000, 0x00100042, 0x00000004, 0x8010001a, 0x00000041, 0x00000002,
2940 0x0010003a, 0x00000005, 0x09000032, 0x00100022, 0x00000004, 0x0010001a, 0x00000004, 0x0010002a,
2941 0x00000004, 0x0010001a, 0x00000002, 0x05000036, 0x00100042, 0x00000002, 0x0010003a, 0x00000005,
2942 0x05000036, 0x00100022, 0x00000003, 0x00004001, 0xffffffff, 0x05000036, 0x00100082, 0x00000001,
2943 0x0010001a, 0x00000004, 0x01000002, 0x01000015, 0x05000036, 0x00100022, 0x00000002, 0x0010003a,
2944 0x00000005, 0x05000036, 0x00100082, 0x00000002, 0x0010000a, 0x00000004, 0x0700001e, 0x00100012,
2945 0x00000003, 0x0010000a, 0x00000003, 0x00004001, 0x00000001, 0x05000036, 0x00100042, 0x00000002,
2946 0x0010003a, 0x00000005, 0x05000036, 0x00100032, 0x00000003, 0x00100086, 0x00000003, 0x01000016,
2947 0x09000037, 0x00100042, 0x00000001, 0x0010001a, 0x00000003, 0x0010003a, 0x00000001, 0x0010002a,
2948 0x00000002, 0x01000012, 0x05000036, 0x00100042, 0x00000001, 0x0010003a, 0x00000003, 0x01000015,
2949 0x08000038, 0x00100012, 0x00000001, 0x0010002a, 0x00000001, 0x0020801a, 0x00000000, 0x00000005,
2950 0x01000015, 0x0300001f, 0x0010001a, 0x00000001, 0x08000020, 0x00100022, 0x00000001, 0x0020800a,
2951 0x00000000, 0x00000005, 0x00004001, 0x00000003, 0x0304001f, 0x0010001a, 0x00000001, 0x0800000f,
2952 0x00100042, 0x00000001, 0x00101046, 0x00000000, 0x00208046, 0x00000000, 0x00000006, 0x08000000,
2953 0x00100012, 0x00000002, 0x0010002a, 0x00000001, 0x0020802a, 0x00000000, 0x00000006, 0x0800000f,
2954 0x00100042, 0x00000001, 0x00101046, 0x00000000, 0x00208046, 0x00000000, 0x00000007, 0x08000000,
2955 0x00100022, 0x00000002, 0x0010002a, 0x00000001, 0x0020802a, 0x00000000, 0x00000007, 0x09000045,
2956 0x001000f2, 0x00000002, 0x00100046, 0x00000002, 0x00107e46, 0x00000001, 0x00106000, 0x00000001,
2957 0x0a000037, 0x00100042, 0x00000001, 0x0020803a, 0x00000000, 0x00000007, 0x00004001, 0x3f800000,
2958 0x0010003a, 0x00000002, 0x08000038, 0x00100012, 0x00000001, 0x0010002a, 0x00000001, 0x0020801a,
2959 0x00000000, 0x00000005, 0x01000015, 0x0a000037, 0x00100012, 0x00000001, 0x0010001a, 0x00000001,
2960 0x0010000a, 0x00000001, 0x0020801a, 0x00000000, 0x00000005, 0x01000015, 0x01000015, 0x01000015,
2961 0x07000038, 0x001020f2, 0x00000000, 0x00100e46, 0x00000000, 0x00100006, 0x00000001, 0x01000012,
2962 0x05000036, 0x001020f2, 0x00000000, 0x00100e46, 0x00000000, 0x01000015, 0x08000027, 0x00100012,
2963 0x00000000, 0x0020800a, 0x00000000, 0x00000000, 0x00004001, 0x00000000, 0x0500003b, 0x00100022,
2964 0x00000000, 0x0010000a, 0x00000000, 0x0500000b, 0x00100032, 0x00000001, 0x00101046, 0x00000001,
2965 0x0500000c, 0x001000c2, 0x00000001, 0x00101406, 0x00000001, 0x07000000, 0x00100042, 0x00000000,
2966 0x0010100a, 0x00000001, 0x0010100a, 0x00000001, 0x0a000032, 0x001000c2, 0x00000000, 0x00100aa6,
2967 0x00000000, 0x00100806, 0x00000001, 0x80100d56, 0x00000041, 0x00000001, 0x0700000f, 0x00100012,
2968 0x00000001, 0x00100ae6, 0x00000000, 0x00101ae6, 0x00000001, 0x07000031, 0x00100012, 0x00000001,
2969 0x0010000a, 0x00000001, 0x00004001, 0x00000000, 0x07000001, 0x00100012, 0x00000001, 0x0010000a,
2970 0x00000000, 0x0010000a, 0x00000001, 0x0304000d, 0x0010000a, 0x00000001, 0x07000038, 0x00100032,
2971 0x00000001, 0x00100ff6, 0x00000000, 0x00101046, 0x00000003, 0x09000032, 0x001000c2, 0x00000000,
2972 0x00101406, 0x00000002, 0x00100aa6, 0x00000000, 0x00100406, 0x00000001, 0x0700000f, 0x00100042,
2973 0x00000000, 0x00100ae6, 0x00000000, 0x00100ae6, 0x00000000, 0x0500004b, 0x00100042, 0x00000000,
2974 0x0010002a, 0x00000000, 0x0a000032, 0x00100082, 0x00000000, 0x0010100a, 0x00000001, 0x0010100a,
2975 0x00000001, 0x8010101a, 0x00000041, 0x00000001, 0x08000000, 0x00100042, 0x00000000, 0x8010003a,
2976 0x000000c1, 0x00000000, 0x0010002a, 0x00000000, 0x07000031, 0x00100042, 0x00000000, 0x0010002a,
2977 0x00000000, 0x00004001, 0x00000000, 0x07000001, 0x00100012, 0x00000000, 0x0010000a, 0x00000000,
2978 0x0010002a, 0x00000000, 0x0304000d, 0x0010000a, 0x00000000, 0x07000038, 0x00100012, 0x00000000,
2979 0x0010003a, 0x00000000, 0x0010102a, 0x00000001, 0x07000031, 0x00100012, 0x00000000, 0x0010000a,
2980 0x00000000, 0x00004001, 0x00000000, 0x07000001, 0x00100012, 0x00000000, 0x0010001a, 0x00000000,
2981 0x0010000a, 0x00000000, 0x0304000d, 0x0010000a, 0x00000000, 0x0100003e,
2983 static const struct shape_info
2985 enum d2d_shape_type shape_type;
2986 const D3D10_INPUT_ELEMENT_DESC *il_desc;
2987 unsigned int il_element_count;
2988 const void *vs_code;
2989 size_t vs_code_size;
2991 shape_info[] =
2993 {D2D_SHAPE_TYPE_OUTLINE, il_desc_outline, ARRAY_SIZE(il_desc_outline),
2994 vs_code_outline, sizeof(vs_code_outline)},
2995 {D2D_SHAPE_TYPE_BEZIER_OUTLINE, il_desc_bezier_outline, ARRAY_SIZE(il_desc_bezier_outline),
2996 vs_code_bezier_outline, sizeof(vs_code_bezier_outline)},
2997 {D2D_SHAPE_TYPE_TRIANGLE, il_desc_triangle, ARRAY_SIZE(il_desc_triangle),
2998 vs_code_triangle, sizeof(vs_code_triangle)},
2999 {D2D_SHAPE_TYPE_BEZIER, il_desc_bezier, ARRAY_SIZE(il_desc_bezier),
3000 vs_code_bezier, sizeof(vs_code_bezier)},
3002 static const struct
3004 float x, y;
3006 quad[] =
3008 {-1.0f, 1.0f},
3009 {-1.0f, -1.0f},
3010 { 1.0f, 1.0f},
3011 { 1.0f, -1.0f},
3013 static const UINT16 indices[] = {0, 1, 2, 2, 1, 3};
3014 float dpi_x, dpi_y;
3016 dpi_x = desc->dpiX;
3017 dpi_y = desc->dpiY;
3019 if (dpi_x == 0.0f && dpi_y == 0.0f)
3021 dpi_x = 96.0f;
3022 dpi_y = 96.0f;
3024 else if (dpi_x <= 0.0f || dpi_y <= 0.0f)
3025 return E_INVALIDARG;
3027 if (desc->type != D2D1_RENDER_TARGET_TYPE_DEFAULT && desc->type != D2D1_RENDER_TARGET_TYPE_HARDWARE)
3028 WARN("Ignoring render target type %#x.\n", desc->type);
3029 if (desc->usage != D2D1_RENDER_TARGET_USAGE_NONE)
3030 FIXME("Ignoring render target usage %#x.\n", desc->usage);
3031 if (desc->minLevel != D2D1_FEATURE_LEVEL_DEFAULT)
3032 WARN("Ignoring feature level %#x.\n", desc->minLevel);
3034 render_target->ID2D1RenderTarget_iface.lpVtbl = &d2d_d3d_render_target_vtbl;
3035 render_target->ID2D1GdiInteropRenderTarget_iface.lpVtbl = &d2d_gdi_interop_render_target_vtbl;
3036 render_target->IDWriteTextRenderer_iface.lpVtbl = &d2d_text_renderer_vtbl;
3037 render_target->refcount = 1;
3038 render_target->factory = factory;
3039 ID2D1Factory_AddRef(render_target->factory);
3041 render_target->outer_unknown = outer_unknown ? outer_unknown :
3042 (IUnknown *)&render_target->ID2D1RenderTarget_iface;
3044 if (FAILED(hr = IDXGISurface_GetDevice(surface, &IID_ID3D10Device, (void **)&render_target->device)))
3046 WARN("Failed to get device interface, hr %#x.\n", hr);
3047 ID2D1Factory_Release(render_target->factory);
3048 return hr;
3051 if (FAILED(hr = IDXGISurface_QueryInterface(surface, &IID_ID3D10Resource, (void **)&resource)))
3053 WARN("Failed to get ID3D10Resource interface, hr %#x.\n", hr);
3054 goto err;
3057 hr = ID3D10Device_CreateRenderTargetView(render_target->device, resource, NULL, &render_target->view);
3058 ID3D10Resource_Release(resource);
3059 if (FAILED(hr))
3061 WARN("Failed to create rendertarget view, hr %#x.\n", hr);
3062 goto err;
3065 if (FAILED(hr = D3D10StateBlockMaskEnableAll(&state_mask)))
3067 WARN("Failed to create stateblock mask, hr %#x.\n", hr);
3068 goto err;
3071 if (FAILED(hr = D3D10CreateStateBlock(render_target->device, &state_mask, &render_target->stateblock)))
3073 WARN("Failed to create stateblock, hr %#x.\n", hr);
3074 goto err;
3077 for (i = 0; i < ARRAY_SIZE(shape_info); ++i)
3079 const struct shape_info *si = &shape_info[i];
3081 if (FAILED(hr = ID3D10Device_CreateInputLayout(render_target->device, si->il_desc, si->il_element_count,
3082 si->vs_code, si->vs_code_size, &render_target->shape_resources[si->shape_type].il)))
3084 WARN("Failed to create input layout for shape type %#x, hr %#x.\n", si->shape_type, hr);
3085 goto err;
3088 if (FAILED(hr = ID3D10Device_CreateVertexShader(render_target->device, si->vs_code,
3089 si->vs_code_size, &render_target->shape_resources[si->shape_type].vs)))
3091 WARN("Failed to create vertex shader for shape type %#x, hr %#x.\n", si->shape_type, hr);
3092 goto err;
3097 if (FAILED(hr = ID3D10Device_CreatePixelShader(render_target->device,
3098 ps_code, sizeof(ps_code), &render_target->ps)))
3100 WARN("Failed to create pixel shader, hr %#x.\n", hr);
3101 goto err;
3104 buffer_desc.ByteWidth = sizeof(indices);
3105 buffer_desc.Usage = D3D10_USAGE_DEFAULT;
3106 buffer_desc.BindFlags = D3D10_BIND_INDEX_BUFFER;
3107 buffer_desc.CPUAccessFlags = 0;
3108 buffer_desc.MiscFlags = 0;
3110 buffer_data.pSysMem = indices;
3111 buffer_data.SysMemPitch = 0;
3112 buffer_data.SysMemSlicePitch = 0;
3114 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device,
3115 &buffer_desc, &buffer_data, &render_target->ib)))
3117 WARN("Failed to create clear index buffer, hr %#x.\n", hr);
3118 goto err;
3121 buffer_desc.ByteWidth = sizeof(quad);
3122 buffer_desc.BindFlags = D3D10_BIND_VERTEX_BUFFER;
3123 buffer_data.pSysMem = quad;
3125 render_target->vb_stride = sizeof(*quad);
3126 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device,
3127 &buffer_desc, &buffer_data, &render_target->vb)))
3129 WARN("Failed to create clear vertex buffer, hr %#x.\n", hr);
3130 goto err;
3133 rs_desc.FillMode = D3D10_FILL_SOLID;
3134 rs_desc.CullMode = D3D10_CULL_NONE;
3135 rs_desc.FrontCounterClockwise = FALSE;
3136 rs_desc.DepthBias = 0;
3137 rs_desc.DepthBiasClamp = 0.0f;
3138 rs_desc.SlopeScaledDepthBias = 0.0f;
3139 rs_desc.DepthClipEnable = TRUE;
3140 rs_desc.ScissorEnable = TRUE;
3141 rs_desc.MultisampleEnable = FALSE;
3142 rs_desc.AntialiasedLineEnable = FALSE;
3143 if (FAILED(hr = ID3D10Device_CreateRasterizerState(render_target->device, &rs_desc, &render_target->rs)))
3145 WARN("Failed to create clear rasterizer state, hr %#x.\n", hr);
3146 goto err;
3149 memset(&blend_desc, 0, sizeof(blend_desc));
3150 blend_desc.BlendEnable[0] = TRUE;
3151 blend_desc.SrcBlend = D3D10_BLEND_ONE;
3152 blend_desc.DestBlend = D3D10_BLEND_INV_SRC_ALPHA;
3153 blend_desc.BlendOp = D3D10_BLEND_OP_ADD;
3154 if (desc->pixelFormat.alphaMode == D2D1_ALPHA_MODE_IGNORE)
3156 blend_desc.SrcBlendAlpha = D3D10_BLEND_ZERO;
3157 blend_desc.DestBlendAlpha = D3D10_BLEND_ONE;
3159 else
3161 blend_desc.SrcBlendAlpha = D3D10_BLEND_ONE;
3162 blend_desc.DestBlendAlpha = D3D10_BLEND_INV_SRC_ALPHA;
3164 blend_desc.BlendOpAlpha = D3D10_BLEND_OP_ADD;
3165 blend_desc.RenderTargetWriteMask[0] = D3D10_COLOR_WRITE_ENABLE_ALL;
3166 if (FAILED(hr = ID3D10Device_CreateBlendState(render_target->device, &blend_desc, &render_target->bs)))
3168 WARN("Failed to create blend state, hr %#x.\n", hr);
3169 goto err;
3172 if (FAILED(hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED,
3173 &IID_IDWriteFactory, (IUnknown **)&dwrite_factory)))
3175 ERR("Failed to create dwrite factory, hr %#x.\n", hr);
3176 goto err;
3179 hr = IDWriteFactory_CreateRenderingParams(dwrite_factory, &render_target->default_text_rendering_params);
3180 IDWriteFactory_Release(dwrite_factory);
3181 if (FAILED(hr))
3183 ERR("Failed to create default text rendering parameters, hr %#x.\n", hr);
3184 goto err;
3187 if (FAILED(hr = IDXGISurface_GetDesc(surface, &surface_desc)))
3189 WARN("Failed to get surface desc, hr %#x.\n", hr);
3190 goto err;
3193 render_target->desc.pixelFormat = desc->pixelFormat;
3194 render_target->pixel_size.width = surface_desc.Width;
3195 render_target->pixel_size.height = surface_desc.Height;
3196 render_target->drawing_state.transform = identity;
3198 if (!d2d_clip_stack_init(&render_target->clip_stack))
3200 WARN("Failed to initialize clip stack.\n");
3201 hr = E_FAIL;
3202 goto err;
3205 render_target->desc.dpiX = dpi_x;
3206 render_target->desc.dpiY = dpi_y;
3208 return S_OK;
3210 err:
3211 if (render_target->default_text_rendering_params)
3212 IDWriteRenderingParams_Release(render_target->default_text_rendering_params);
3213 if (render_target->bs)
3214 ID3D10BlendState_Release(render_target->bs);
3215 if (render_target->rs)
3216 ID3D10RasterizerState_Release(render_target->rs);
3217 if (render_target->vb)
3218 ID3D10Buffer_Release(render_target->vb);
3219 if (render_target->ib)
3220 ID3D10Buffer_Release(render_target->ib);
3221 if (render_target->ps)
3222 ID3D10PixelShader_Release(render_target->ps);
3223 for (i = 0; i < D2D_SHAPE_TYPE_COUNT; ++i)
3225 if (render_target->shape_resources[i].vs)
3226 ID3D10VertexShader_Release(render_target->shape_resources[i].vs);
3227 if (render_target->shape_resources[i].il)
3228 ID3D10InputLayout_Release(render_target->shape_resources[i].il);
3230 if (render_target->stateblock)
3231 render_target->stateblock->lpVtbl->Release(render_target->stateblock);
3232 if (render_target->view)
3233 ID3D10RenderTargetView_Release(render_target->view);
3234 if (render_target->device)
3235 ID3D10Device_Release(render_target->device);
3236 ID2D1Factory_Release(render_target->factory);
3237 return hr;
3240 HRESULT d2d_d3d_create_render_target(ID2D1Factory *factory, IDXGISurface *surface, IUnknown *outer_unknown,
3241 const D2D1_RENDER_TARGET_PROPERTIES *desc, ID2D1RenderTarget **render_target)
3243 struct d2d_d3d_render_target *object;
3244 HRESULT hr;
3246 if (!(object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object))))
3247 return E_OUTOFMEMORY;
3249 if (FAILED(hr = d2d_d3d_render_target_init(object, factory, surface, outer_unknown, desc)))
3251 WARN("Failed to initialize render target, hr %#x.\n", hr);
3252 HeapFree(GetProcessHeap(), 0, object);
3253 return hr;
3256 TRACE("Created render target %p.\n", object);
3257 *render_target = &object->ID2D1RenderTarget_iface;
3259 return S_OK;
3262 HRESULT d2d_d3d_render_target_create_rtv(ID2D1RenderTarget *iface, IDXGISurface1 *surface)
3264 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
3265 DXGI_SURFACE_DESC surface_desc;
3266 ID3D10RenderTargetView *view;
3267 ID3D10Resource *resource;
3268 HRESULT hr;
3270 if (!surface)
3272 ID3D10RenderTargetView_Release(render_target->view);
3273 render_target->view = NULL;
3274 return S_OK;
3277 if (FAILED(hr = IDXGISurface1_GetDesc(surface, &surface_desc)))
3279 WARN("Failed to get surface desc, hr %#x.\n", hr);
3280 return hr;
3283 if (FAILED(hr = IDXGISurface1_QueryInterface(surface, &IID_ID3D10Resource, (void **)&resource)))
3285 WARN("Failed to get ID3D10Resource interface, hr %#x.\n", hr);
3286 return hr;
3289 hr = ID3D10Device_CreateRenderTargetView(render_target->device, resource, NULL, &view);
3290 ID3D10Resource_Release(resource);
3291 if (FAILED(hr))
3293 WARN("Failed to create rendertarget view, hr %#x.\n", hr);
3294 return hr;
3297 render_target->pixel_size.width = surface_desc.Width;
3298 render_target->pixel_size.height = surface_desc.Height;
3299 if (render_target->view)
3300 ID3D10RenderTargetView_Release(render_target->view);
3301 render_target->view = view;
3303 return S_OK;