wined3d: Record sampler usage for WINED3DSIH_LD_RAW.
[wine.git] / dlls / d2d1 / render_target.c
blobf9e2e3a9349e2b0fceba37480f6f7d32b35145b7
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 struct d2d_draw_text_layout_ctx
30 ID2D1Brush *brush;
31 D2D1_DRAW_TEXT_OPTIONS options;
34 static ID2D1Brush *d2d_draw_get_text_brush(struct d2d_draw_text_layout_ctx *context, IUnknown *effect)
36 ID2D1Brush *brush = NULL;
38 if (effect && SUCCEEDED(IUnknown_QueryInterface(effect, &IID_ID2D1Brush, (void**)&brush)))
39 return brush;
41 ID2D1Brush_AddRef(context->brush);
42 return context->brush;
45 static void d2d_rect_expand(D2D1_RECT_F *dst, const D2D1_POINT_2F *point)
47 if (point->x < dst->left)
48 dst->left = point->x;
49 if (point->y < dst->top)
50 dst->top = point->y;
51 if (point->x > dst->right)
52 dst->right = point->x;
53 if (point->y > dst->bottom)
54 dst->bottom = point->y;
57 static void d2d_rect_intersect(D2D1_RECT_F *dst, const D2D1_RECT_F *src)
59 if (src->left > dst->left)
60 dst->left = src->left;
61 if (src->top > dst->top)
62 dst->top = src->top;
63 if (src->right < dst->right)
64 dst->right = src->right;
65 if (src->bottom < dst->bottom)
66 dst->bottom = src->bottom;
69 static void d2d_rect_set(D2D1_RECT_F *dst, float left, float top, float right, float bottom)
71 dst->left = left;
72 dst->top = top;
73 dst->right = right;
74 dst->bottom = bottom;
77 static void d2d_size_set(D2D1_SIZE_U *dst, float width, float height)
79 dst->width = width;
80 dst->height = height;
83 static BOOL d2d_clip_stack_init(struct d2d_clip_stack *stack)
85 if (!(stack->stack = HeapAlloc(GetProcessHeap(), 0, INITIAL_CLIP_STACK_SIZE * sizeof(*stack->stack))))
86 return FALSE;
88 stack->size = INITIAL_CLIP_STACK_SIZE;
89 stack->count = 0;
91 return TRUE;
94 static void d2d_clip_stack_cleanup(struct d2d_clip_stack *stack)
96 HeapFree(GetProcessHeap(), 0, stack->stack);
99 static BOOL d2d_clip_stack_push(struct d2d_clip_stack *stack, const D2D1_RECT_F *rect)
101 D2D1_RECT_F r;
103 if (stack->count == stack->size)
105 D2D1_RECT_F *new_stack;
106 unsigned int new_size;
108 if (stack->size > UINT_MAX / 2)
109 return FALSE;
111 new_size = stack->size * 2;
112 if (!(new_stack = HeapReAlloc(GetProcessHeap(), 0, stack->stack, new_size * sizeof(*stack->stack))))
113 return FALSE;
115 stack->stack = new_stack;
116 stack->size = new_size;
119 r = *rect;
120 if (stack->count)
121 d2d_rect_intersect(&r, &stack->stack[stack->count - 1]);
122 stack->stack[stack->count++] = r;
124 return TRUE;
127 static void d2d_clip_stack_pop(struct d2d_clip_stack *stack)
129 if (!stack->count)
130 return;
131 --stack->count;
134 static void d2d_rt_draw(struct d2d_d3d_render_target *render_target, enum d2d_shape_type shape_type,
135 ID3D10Buffer *ib, unsigned int index_count, ID3D10Buffer *vb, unsigned int vb_stride,
136 ID3D10Buffer *vs_cb, ID3D10Buffer *ps_cb, struct d2d_brush *brush, struct d2d_brush *opacity_brush)
138 struct d2d_shape_resources *shape_resources = &render_target->shape_resources[shape_type];
139 ID3D10Device *device = render_target->device;
140 D3D10_RECT scissor_rect;
141 unsigned int offset;
142 D3D10_VIEWPORT vp;
143 HRESULT hr;
145 vp.TopLeftX = 0;
146 vp.TopLeftY = 0;
147 vp.Width = render_target->pixel_size.width;
148 vp.Height = render_target->pixel_size.height;
149 vp.MinDepth = 0.0f;
150 vp.MaxDepth = 1.0f;
152 if (FAILED(hr = render_target->stateblock->lpVtbl->Capture(render_target->stateblock)))
154 WARN("Failed to capture stateblock, hr %#x.\n", hr);
155 return;
158 ID3D10Device_ClearState(device);
160 ID3D10Device_IASetInputLayout(device, shape_resources->il);
161 ID3D10Device_IASetPrimitiveTopology(device, D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
162 ID3D10Device_IASetIndexBuffer(device, ib, DXGI_FORMAT_R16_UINT, 0);
163 offset = 0;
164 ID3D10Device_IASetVertexBuffers(device, 0, 1, &vb, &vb_stride, &offset);
165 ID3D10Device_VSSetConstantBuffers(device, 0, 1, &vs_cb);
166 ID3D10Device_VSSetShader(device, shape_resources->vs);
167 ID3D10Device_PSSetConstantBuffers(device, 0, 1, &ps_cb);
168 ID3D10Device_RSSetViewports(device, 1, &vp);
169 if (render_target->clip_stack.count)
171 const D2D1_RECT_F *clip_rect;
173 clip_rect = &render_target->clip_stack.stack[render_target->clip_stack.count - 1];
174 scissor_rect.left = clip_rect->left + 0.5f;
175 scissor_rect.top = clip_rect->top + 0.5f;
176 scissor_rect.right = clip_rect->right + 0.5f;
177 scissor_rect.bottom = clip_rect->bottom + 0.5f;
179 else
181 scissor_rect.left = 0.0f;
182 scissor_rect.top = 0.0f;
183 scissor_rect.right = render_target->pixel_size.width;
184 scissor_rect.bottom = render_target->pixel_size.height;
186 ID3D10Device_RSSetScissorRects(device, 1, &scissor_rect);
187 ID3D10Device_RSSetState(device, render_target->rs);
188 ID3D10Device_OMSetRenderTargets(device, 1, &render_target->view, NULL);
189 if (brush)
190 d2d_brush_bind_resources(brush, opacity_brush, render_target, shape_type);
191 else
192 ID3D10Device_PSSetShader(device, shape_resources->ps[D2D_BRUSH_TYPE_SOLID][D2D_BRUSH_TYPE_COUNT]);
194 if (ib)
195 ID3D10Device_DrawIndexed(device, index_count, 0, 0);
196 else
197 ID3D10Device_Draw(device, index_count, 0);
199 if (FAILED(hr = render_target->stateblock->lpVtbl->Apply(render_target->stateblock)))
200 WARN("Failed to apply stateblock, hr %#x.\n", hr);
203 static inline struct d2d_d3d_render_target *impl_from_ID2D1RenderTarget(ID2D1RenderTarget *iface)
205 return CONTAINING_RECORD(iface, struct d2d_d3d_render_target, ID2D1RenderTarget_iface);
208 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_QueryInterface(ID2D1RenderTarget *iface, REFIID iid, void **out)
210 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
212 TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
214 if (IsEqualGUID(iid, &IID_ID2D1RenderTarget)
215 || IsEqualGUID(iid, &IID_ID2D1Resource)
216 || IsEqualGUID(iid, &IID_IUnknown))
218 ID2D1RenderTarget_AddRef(iface);
219 *out = iface;
220 return S_OK;
222 else if (IsEqualGUID(iid, &IID_ID2D1GdiInteropRenderTarget))
224 ID2D1GdiInteropRenderTarget_AddRef(&render_target->ID2D1GdiInteropRenderTarget_iface);
225 *out = &render_target->ID2D1GdiInteropRenderTarget_iface;
226 return S_OK;
229 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
231 *out = NULL;
232 return E_NOINTERFACE;
235 static ULONG STDMETHODCALLTYPE d2d_d3d_render_target_AddRef(ID2D1RenderTarget *iface)
237 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
238 ULONG refcount = InterlockedIncrement(&render_target->refcount);
240 TRACE("%p increasing refcount to %u.\n", iface, refcount);
242 return refcount;
245 static ULONG STDMETHODCALLTYPE d2d_d3d_render_target_Release(ID2D1RenderTarget *iface)
247 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
248 ULONG refcount = InterlockedDecrement(&render_target->refcount);
250 TRACE("%p decreasing refcount to %u.\n", iface, refcount);
252 if (!refcount)
254 unsigned int i, j, k;
256 d2d_clip_stack_cleanup(&render_target->clip_stack);
257 IDWriteRenderingParams_Release(render_target->default_text_rendering_params);
258 if (render_target->text_rendering_params)
259 IDWriteRenderingParams_Release(render_target->text_rendering_params);
260 ID3D10BlendState_Release(render_target->bs);
261 ID3D10RasterizerState_Release(render_target->rs);
262 ID3D10Buffer_Release(render_target->vb);
263 ID3D10Buffer_Release(render_target->ib);
264 for (i = 0; i < D2D_SHAPE_TYPE_COUNT; ++i)
266 for (j = 0; j < D2D_BRUSH_TYPE_COUNT; ++j)
268 for (k = 0; k < D2D_BRUSH_TYPE_COUNT + 1; ++k)
270 if (render_target->shape_resources[i].ps[j][k])
271 ID3D10PixelShader_Release(render_target->shape_resources[i].ps[j][k]);
274 ID3D10VertexShader_Release(render_target->shape_resources[i].vs);
275 ID3D10InputLayout_Release(render_target->shape_resources[i].il);
277 render_target->stateblock->lpVtbl->Release(render_target->stateblock);
278 ID3D10RenderTargetView_Release(render_target->view);
279 ID3D10Device_Release(render_target->device);
280 ID2D1Factory_Release(render_target->factory);
281 HeapFree(GetProcessHeap(), 0, render_target);
284 return refcount;
287 static void STDMETHODCALLTYPE d2d_d3d_render_target_GetFactory(ID2D1RenderTarget *iface, ID2D1Factory **factory)
289 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
291 TRACE("iface %p, factory %p.\n", iface, factory);
293 *factory = render_target->factory;
294 ID2D1Factory_AddRef(*factory);
297 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateBitmap(ID2D1RenderTarget *iface,
298 D2D1_SIZE_U size, const void *src_data, UINT32 pitch, const D2D1_BITMAP_PROPERTIES *desc, ID2D1Bitmap **bitmap)
300 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
301 struct d2d_bitmap *object;
302 HRESULT hr;
304 TRACE("iface %p, size {%u, %u}, src_data %p, pitch %u, desc %p, bitmap %p.\n",
305 iface, size.width, size.height, src_data, pitch, desc, bitmap);
307 if (SUCCEEDED(hr = d2d_bitmap_create(render_target->factory, render_target->device, size, src_data, pitch, desc, &object)))
308 *bitmap = &object->ID2D1Bitmap_iface;
310 return hr;
313 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateBitmapFromWicBitmap(ID2D1RenderTarget *iface,
314 IWICBitmapSource *bitmap_source, const D2D1_BITMAP_PROPERTIES *desc, ID2D1Bitmap **bitmap)
316 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
317 struct d2d_bitmap *object;
318 HRESULT hr;
320 TRACE("iface %p, bitmap_source %p, desc %p, bitmap %p.\n",
321 iface, bitmap_source, desc, bitmap);
323 if (SUCCEEDED(hr = d2d_bitmap_create_from_wic_bitmap(render_target->factory, render_target->device, bitmap_source,
324 desc, &object)))
325 *bitmap = &object->ID2D1Bitmap_iface;
327 return hr;
330 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateSharedBitmap(ID2D1RenderTarget *iface,
331 REFIID iid, void *data, const D2D1_BITMAP_PROPERTIES *desc, ID2D1Bitmap **bitmap)
333 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
334 struct d2d_bitmap *object;
335 HRESULT hr;
337 TRACE("iface %p, iid %s, data %p, desc %p, bitmap %p.\n",
338 iface, debugstr_guid(iid), data, desc, bitmap);
340 if (SUCCEEDED(hr = d2d_bitmap_create_shared(iface, render_target->device, iid, data, desc, &object)))
341 *bitmap = &object->ID2D1Bitmap_iface;
343 return hr;
346 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateBitmapBrush(ID2D1RenderTarget *iface,
347 ID2D1Bitmap *bitmap, const D2D1_BITMAP_BRUSH_PROPERTIES *bitmap_brush_desc,
348 const D2D1_BRUSH_PROPERTIES *brush_desc, ID2D1BitmapBrush **brush)
350 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
351 struct d2d_brush *object;
352 HRESULT hr;
354 TRACE("iface %p, bitmap %p, bitmap_brush_desc %p, brush_desc %p, brush %p.\n",
355 iface, bitmap, bitmap_brush_desc, brush_desc, brush);
357 if (SUCCEEDED(hr = d2d_bitmap_brush_create(render_target->factory, bitmap, bitmap_brush_desc, brush_desc, &object)))
358 *brush = (ID2D1BitmapBrush *)&object->ID2D1Brush_iface;
360 return hr;
363 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateSolidColorBrush(ID2D1RenderTarget *iface,
364 const D2D1_COLOR_F *color, const D2D1_BRUSH_PROPERTIES *desc, ID2D1SolidColorBrush **brush)
366 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
367 struct d2d_brush *object;
368 HRESULT hr;
370 TRACE("iface %p, color %p, desc %p, brush %p.\n", iface, color, desc, brush);
372 if (SUCCEEDED(hr = d2d_solid_color_brush_create(render_target->factory, color, desc, &object)))
373 *brush = (ID2D1SolidColorBrush *)&object->ID2D1Brush_iface;
375 return hr;
378 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateGradientStopCollection(ID2D1RenderTarget *iface,
379 const D2D1_GRADIENT_STOP *stops, UINT32 stop_count, D2D1_GAMMA gamma, D2D1_EXTEND_MODE extend_mode,
380 ID2D1GradientStopCollection **gradient)
382 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
383 struct d2d_gradient *object;
384 HRESULT hr;
386 TRACE("iface %p, stops %p, stop_count %u, gamma %#x, extend_mode %#x, gradient %p.\n",
387 iface, stops, stop_count, gamma, extend_mode, gradient);
389 if (SUCCEEDED(hr = d2d_gradient_create(render_target->factory, stops, stop_count, gamma, extend_mode, &object)))
390 *gradient = &object->ID2D1GradientStopCollection_iface;
392 return hr;
395 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateLinearGradientBrush(ID2D1RenderTarget *iface,
396 const D2D1_LINEAR_GRADIENT_BRUSH_PROPERTIES *gradient_brush_desc, const D2D1_BRUSH_PROPERTIES *brush_desc,
397 ID2D1GradientStopCollection *gradient, ID2D1LinearGradientBrush **brush)
399 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
400 struct d2d_brush *object;
401 HRESULT hr;
403 TRACE("iface %p, gradient_brush_desc %p, brush_desc %p, gradient %p, brush %p.\n",
404 iface, gradient_brush_desc, brush_desc, gradient, brush);
406 if (SUCCEEDED(hr = d2d_linear_gradient_brush_create(render_target->factory, gradient_brush_desc, brush_desc,
407 gradient, &object)))
408 *brush = (ID2D1LinearGradientBrush *)&object->ID2D1Brush_iface;
410 return hr;
413 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateRadialGradientBrush(ID2D1RenderTarget *iface,
414 const D2D1_RADIAL_GRADIENT_BRUSH_PROPERTIES *gradient_brush_desc, const D2D1_BRUSH_PROPERTIES *brush_desc,
415 ID2D1GradientStopCollection *gradient, ID2D1RadialGradientBrush **brush)
417 FIXME("iface %p, gradient_brush_desc %p, brush_desc %p, gradient %p, brush %p stub!\n",
418 iface, gradient_brush_desc, brush_desc, gradient, brush);
420 return E_NOTIMPL;
423 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateCompatibleRenderTarget(ID2D1RenderTarget *iface,
424 const D2D1_SIZE_F *size, const D2D1_SIZE_U *pixel_size, const D2D1_PIXEL_FORMAT *format,
425 D2D1_COMPATIBLE_RENDER_TARGET_OPTIONS options, ID2D1BitmapRenderTarget **rt)
427 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
428 struct d2d_bitmap_render_target *object;
429 HRESULT hr;
431 TRACE("iface %p, size %p, pixel_size %p, format %p, options %#x, render_target %p.\n",
432 iface, size, pixel_size, format, options, rt);
434 if (!(object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object))))
435 return E_OUTOFMEMORY;
437 if (FAILED(hr = d2d_bitmap_render_target_init(object, render_target, size, pixel_size,
438 format, options)))
440 WARN("Failed to initialize render target, hr %#x.\n", hr);
441 HeapFree(GetProcessHeap(), 0, object);
442 return hr;
445 TRACE("Created render target %p.\n", object);
446 *rt = &object->ID2D1BitmapRenderTarget_iface;
448 return S_OK;
451 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateLayer(ID2D1RenderTarget *iface,
452 const D2D1_SIZE_F *size, ID2D1Layer **layer)
454 FIXME("iface %p, size %p, layer %p stub!\n", iface, size, layer);
456 return E_NOTIMPL;
459 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateMesh(ID2D1RenderTarget *iface, ID2D1Mesh **mesh)
461 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
462 struct d2d_mesh *object;
463 HRESULT hr;
465 TRACE("iface %p, mesh %p.\n", iface, mesh);
467 if (SUCCEEDED(hr = d2d_mesh_create(render_target->factory, &object)))
468 *mesh = &object->ID2D1Mesh_iface;
470 return hr;
473 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawLine(ID2D1RenderTarget *iface,
474 D2D1_POINT_2F p0, D2D1_POINT_2F p1, ID2D1Brush *brush, float stroke_width, ID2D1StrokeStyle *stroke_style)
476 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
477 ID2D1PathGeometry *geometry;
478 ID2D1GeometrySink *sink;
479 HRESULT hr;
481 TRACE("iface %p, p0 {%.8e, %.8e}, p1 {%.8e, %.8e}, brush %p, stroke_width %.8e, stroke_style %p.\n",
482 iface, p0.x, p0.y, p1.x, p1.y, brush, stroke_width, stroke_style);
484 if (FAILED(hr = ID2D1Factory_CreatePathGeometry(render_target->factory, &geometry)))
486 WARN("Failed to create path geometry, %#x.\n", hr);
487 return;
490 if (FAILED(hr = ID2D1PathGeometry_Open(geometry, &sink)))
492 WARN("Open() failed, %#x.\n", hr);
493 ID2D1PathGeometry_Release(geometry);
494 return;
497 ID2D1GeometrySink_BeginFigure(sink, p0, D2D1_FIGURE_BEGIN_FILLED);
498 ID2D1GeometrySink_AddLine(sink, p1);
499 ID2D1GeometrySink_EndFigure(sink, D2D1_FIGURE_END_CLOSED);
500 if (FAILED(hr = ID2D1GeometrySink_Close(sink)))
501 WARN("Close() failed, %#x.\n", hr);
502 ID2D1GeometrySink_Release(sink);
504 ID2D1RenderTarget_DrawGeometry(iface, (ID2D1Geometry *)geometry, brush, stroke_width, stroke_style);
505 ID2D1PathGeometry_Release(geometry);
508 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawRectangle(ID2D1RenderTarget *iface,
509 const D2D1_RECT_F *rect, ID2D1Brush *brush, float stroke_width, ID2D1StrokeStyle *stroke_style)
511 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
512 ID2D1RectangleGeometry *geometry;
513 HRESULT hr;
515 TRACE("iface %p, rect %p, brush %p, stroke_width %.8e, stroke_style %p.\n",
516 iface, rect, brush, stroke_width, stroke_style);
518 if (FAILED(hr = ID2D1Factory_CreateRectangleGeometry(render_target->factory, rect, &geometry)))
520 ERR("Failed to create geometry, hr %#x.\n", hr);
521 return;
524 ID2D1RenderTarget_DrawGeometry(iface, (ID2D1Geometry *)geometry, brush, stroke_width, stroke_style);
525 ID2D1RectangleGeometry_Release(geometry);
528 static void STDMETHODCALLTYPE d2d_d3d_render_target_FillRectangle(ID2D1RenderTarget *iface,
529 const D2D1_RECT_F *rect, ID2D1Brush *brush)
531 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
532 ID2D1RectangleGeometry *geometry;
533 HRESULT hr;
535 TRACE("iface %p, rect %p, brush %p.\n", iface, rect, brush);
537 if (FAILED(hr = ID2D1Factory_CreateRectangleGeometry(render_target->factory, rect, &geometry)))
539 ERR("Failed to create geometry, hr %#x.\n", hr);
540 return;
543 ID2D1RenderTarget_FillGeometry(iface, (ID2D1Geometry *)geometry, brush, NULL);
544 ID2D1RectangleGeometry_Release(geometry);
547 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawRoundedRectangle(ID2D1RenderTarget *iface,
548 const D2D1_ROUNDED_RECT *rect, ID2D1Brush *brush, float stroke_width, ID2D1StrokeStyle *stroke_style)
550 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
551 ID2D1RoundedRectangleGeometry *geometry;
552 HRESULT hr;
554 TRACE("iface %p, rect %p, brush %p, stroke_width %.8e, stroke_style %p.\n",
555 iface, rect, brush, stroke_width, stroke_style);
557 if (FAILED(hr = ID2D1Factory_CreateRoundedRectangleGeometry(render_target->factory, rect, &geometry)))
559 ERR("Failed to create geometry, hr %#x.\n", hr);
560 return;
563 ID2D1RenderTarget_DrawGeometry(iface, (ID2D1Geometry *)geometry, brush, stroke_width, stroke_style);
564 ID2D1RoundedRectangleGeometry_Release(geometry);
567 static void STDMETHODCALLTYPE d2d_d3d_render_target_FillRoundedRectangle(ID2D1RenderTarget *iface,
568 const D2D1_ROUNDED_RECT *rect, ID2D1Brush *brush)
570 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
571 ID2D1RoundedRectangleGeometry *geometry;
572 HRESULT hr;
574 TRACE("iface %p, rect %p, brush %p.\n", iface, rect, brush);
576 if (FAILED(hr = ID2D1Factory_CreateRoundedRectangleGeometry(render_target->factory, rect, &geometry)))
578 ERR("Failed to create geometry, hr %#x.\n", hr);
579 return;
582 ID2D1RenderTarget_FillGeometry(iface, (ID2D1Geometry *)geometry, brush, NULL);
583 ID2D1RoundedRectangleGeometry_Release(geometry);
586 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawEllipse(ID2D1RenderTarget *iface,
587 const D2D1_ELLIPSE *ellipse, ID2D1Brush *brush, float stroke_width, ID2D1StrokeStyle *stroke_style)
589 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
590 ID2D1EllipseGeometry *geometry;
591 HRESULT hr;
593 TRACE("iface %p, ellipse %p, brush %p, stroke_width %.8e, stroke_style %p.\n",
594 iface, ellipse, brush, stroke_width, stroke_style);
596 if (FAILED(hr = ID2D1Factory_CreateEllipseGeometry(render_target->factory, ellipse, &geometry)))
598 ERR("Failed to create geometry, hr %#x.\n", hr);
599 return;
602 ID2D1RenderTarget_DrawGeometry(iface, (ID2D1Geometry *)geometry, brush, stroke_width, stroke_style);
603 ID2D1EllipseGeometry_Release(geometry);
606 static void STDMETHODCALLTYPE d2d_d3d_render_target_FillEllipse(ID2D1RenderTarget *iface,
607 const D2D1_ELLIPSE *ellipse, ID2D1Brush *brush)
609 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
610 ID2D1EllipseGeometry *geometry;
611 HRESULT hr;
613 TRACE("iface %p, ellipse %p, brush %p.\n", iface, ellipse, brush);
615 if (FAILED(hr = ID2D1Factory_CreateEllipseGeometry(render_target->factory, ellipse, &geometry)))
617 ERR("Failed to create geometry, hr %#x.\n", hr);
618 return;
621 ID2D1RenderTarget_FillGeometry(iface, (ID2D1Geometry *)geometry, brush, NULL);
622 ID2D1EllipseGeometry_Release(geometry);
625 static void d2d_rt_draw_geometry(struct d2d_d3d_render_target *render_target,
626 const struct d2d_geometry *geometry, struct d2d_brush *brush, float stroke_width)
628 ID3D10Buffer *ib, *vb, *vs_cb, *ps_cb;
629 D3D10_SUBRESOURCE_DATA buffer_data;
630 D3D10_BUFFER_DESC buffer_desc;
631 const D2D1_MATRIX_3X2_F *w;
632 float tmp_x, tmp_y;
633 HRESULT hr;
634 struct
636 struct
638 float _11, _21, _31, pad0;
639 float _12, _22, _32, stroke_width;
640 } transform_geometry;
641 struct d2d_vec4 transform_rtx;
642 struct d2d_vec4 transform_rty;
643 } vs_cb_data;
645 vs_cb_data.transform_geometry._11 = geometry->transform._11;
646 vs_cb_data.transform_geometry._21 = geometry->transform._21;
647 vs_cb_data.transform_geometry._31 = geometry->transform._31;
648 vs_cb_data.transform_geometry.pad0 = 0.0f;
649 vs_cb_data.transform_geometry._12 = geometry->transform._12;
650 vs_cb_data.transform_geometry._22 = geometry->transform._22;
651 vs_cb_data.transform_geometry._32 = geometry->transform._32;
652 vs_cb_data.transform_geometry.stroke_width = stroke_width;
654 w = &render_target->drawing_state.transform;
656 tmp_x = render_target->desc.dpiX / 96.0f;
657 vs_cb_data.transform_rtx.x = w->_11 * tmp_x;
658 vs_cb_data.transform_rtx.y = w->_21 * tmp_x;
659 vs_cb_data.transform_rtx.z = w->_31 * tmp_x;
660 vs_cb_data.transform_rtx.w = 2.0f / render_target->pixel_size.width;
662 tmp_y = render_target->desc.dpiY / 96.0f;
663 vs_cb_data.transform_rty.x = w->_12 * tmp_y;
664 vs_cb_data.transform_rty.y = w->_22 * tmp_y;
665 vs_cb_data.transform_rty.z = w->_32 * tmp_y;
666 vs_cb_data.transform_rty.w = -2.0f / render_target->pixel_size.height;
668 buffer_desc.ByteWidth = sizeof(vs_cb_data);
669 buffer_desc.Usage = D3D10_USAGE_DEFAULT;
670 buffer_desc.BindFlags = D3D10_BIND_CONSTANT_BUFFER;
671 buffer_desc.CPUAccessFlags = 0;
672 buffer_desc.MiscFlags = 0;
674 buffer_data.pSysMem = &vs_cb_data;
675 buffer_data.SysMemPitch = 0;
676 buffer_data.SysMemSlicePitch = 0;
678 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device, &buffer_desc, &buffer_data, &vs_cb)))
680 WARN("Failed to create constant buffer, hr %#x.\n", hr);
681 return;
684 if (FAILED(hr = d2d_brush_get_ps_cb(brush, NULL, render_target, &ps_cb)))
686 WARN("Failed to get ps constant buffer, hr %#x.\n", hr);
687 ID3D10Buffer_Release(vs_cb);
688 return;
691 if (geometry->outline.face_count)
693 buffer_desc.ByteWidth = geometry->outline.face_count * sizeof(*geometry->outline.faces);
694 buffer_desc.BindFlags = D3D10_BIND_INDEX_BUFFER;
695 buffer_data.pSysMem = geometry->outline.faces;
697 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device, &buffer_desc, &buffer_data, &ib)))
699 WARN("Failed to create index buffer, hr %#x.\n", hr);
700 goto done;
703 buffer_desc.ByteWidth = geometry->outline.vertex_count * sizeof(*geometry->outline.vertices);
704 buffer_desc.BindFlags = D3D10_BIND_VERTEX_BUFFER;
705 buffer_data.pSysMem = geometry->outline.vertices;
707 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device, &buffer_desc, &buffer_data, &vb)))
709 ERR("Failed to create vertex buffer, hr %#x.\n", hr);
710 ID3D10Buffer_Release(ib);
711 goto done;
714 d2d_rt_draw(render_target, D2D_SHAPE_TYPE_OUTLINE, ib, 3 * geometry->outline.face_count, vb,
715 sizeof(*geometry->outline.vertices), vs_cb, ps_cb, brush, NULL);
717 ID3D10Buffer_Release(vb);
718 ID3D10Buffer_Release(ib);
721 done:
722 ID3D10Buffer_Release(ps_cb);
723 ID3D10Buffer_Release(vs_cb);
726 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawGeometry(ID2D1RenderTarget *iface,
727 ID2D1Geometry *geometry, ID2D1Brush *brush, float stroke_width, ID2D1StrokeStyle *stroke_style)
729 const struct d2d_geometry *geometry_impl = unsafe_impl_from_ID2D1Geometry(geometry);
730 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
731 struct d2d_brush *brush_impl = unsafe_impl_from_ID2D1Brush(brush);
733 TRACE("iface %p, geometry %p, brush %p, stroke_width %.8e, stroke_style %p.\n",
734 iface, geometry, brush, stroke_width, stroke_style);
736 if (stroke_style)
737 FIXME("Ignoring stoke style %p.\n", stroke_style);
739 d2d_rt_draw_geometry(render_target, geometry_impl, brush_impl, stroke_width);
742 static void d2d_rt_fill_geometry(struct d2d_d3d_render_target *render_target,
743 const struct d2d_geometry *geometry, struct d2d_brush *brush, struct d2d_brush *opacity_brush)
745 ID3D10Buffer *ib, *vb, *vs_cb, *ps_cb;
746 D3D10_SUBRESOURCE_DATA buffer_data;
747 D3D10_BUFFER_DESC buffer_desc;
748 D2D1_MATRIX_3X2_F w, g;
749 float tmp_x, tmp_y;
750 HRESULT hr;
751 struct
753 float _11, _21, _31, pad0;
754 float _12, _22, _32, pad1;
755 } transform;
757 tmp_x = (2.0f * render_target->desc.dpiX) / (96.0f * render_target->pixel_size.width);
758 tmp_y = -(2.0f * render_target->desc.dpiY) / (96.0f * render_target->pixel_size.height);
759 w = render_target->drawing_state.transform;
760 w._11 *= tmp_x;
761 w._21 *= tmp_x;
762 w._31 = w._31 * tmp_x - 1.0f;
763 w._12 *= tmp_y;
764 w._22 *= tmp_y;
765 w._32 = w._32 * tmp_y + 1.0f;
767 g = geometry->transform;
768 d2d_matrix_multiply(&g, &w);
770 transform._11 = g._11;
771 transform._21 = g._21;
772 transform._31 = g._31;
773 transform.pad0 = 0.0f;
774 transform._12 = g._12;
775 transform._22 = g._22;
776 transform._32 = g._32;
777 transform.pad1 = 0.0f;
779 buffer_desc.ByteWidth = sizeof(transform);
780 buffer_desc.Usage = D3D10_USAGE_DEFAULT;
781 buffer_desc.BindFlags = D3D10_BIND_CONSTANT_BUFFER;
782 buffer_desc.CPUAccessFlags = 0;
783 buffer_desc.MiscFlags = 0;
785 buffer_data.pSysMem = &transform;
786 buffer_data.SysMemPitch = 0;
787 buffer_data.SysMemSlicePitch = 0;
789 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device, &buffer_desc, &buffer_data, &vs_cb)))
791 WARN("Failed to create constant buffer, hr %#x.\n", hr);
792 return;
795 if (FAILED(hr = d2d_brush_get_ps_cb(brush, opacity_brush, render_target, &ps_cb)))
797 WARN("Failed to get ps constant buffer, hr %#x.\n", hr);
798 ID3D10Buffer_Release(vs_cb);
799 return;
802 if (geometry->fill.face_count)
804 buffer_desc.ByteWidth = geometry->fill.face_count * sizeof(*geometry->fill.faces);
805 buffer_desc.BindFlags = D3D10_BIND_INDEX_BUFFER;
806 buffer_data.pSysMem = geometry->fill.faces;
808 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device, &buffer_desc, &buffer_data, &ib)))
810 WARN("Failed to create index buffer, hr %#x.\n", hr);
811 goto done;
814 buffer_desc.ByteWidth = geometry->fill.vertex_count * sizeof(*geometry->fill.vertices);
815 buffer_desc.BindFlags = D3D10_BIND_VERTEX_BUFFER;
816 buffer_data.pSysMem = geometry->fill.vertices;
818 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device, &buffer_desc, &buffer_data, &vb)))
820 ERR("Failed to create vertex buffer, hr %#x.\n", hr);
821 ID3D10Buffer_Release(ib);
822 goto done;
825 d2d_rt_draw(render_target, D2D_SHAPE_TYPE_TRIANGLE, ib, 3 * geometry->fill.face_count, vb,
826 sizeof(*geometry->fill.vertices), vs_cb, ps_cb, brush, opacity_brush);
828 ID3D10Buffer_Release(vb);
829 ID3D10Buffer_Release(ib);
832 if (geometry->fill.bezier_vertex_count)
834 buffer_desc.ByteWidth = geometry->fill.bezier_vertex_count * sizeof(*geometry->fill.bezier_vertices);
835 buffer_data.pSysMem = geometry->fill.bezier_vertices;
837 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device, &buffer_desc, &buffer_data, &vb)))
839 ERR("Failed to create beziers vertex buffer, hr %#x.\n", hr);
840 goto done;
843 d2d_rt_draw(render_target, D2D_SHAPE_TYPE_BEZIER, NULL, geometry->fill.bezier_vertex_count, vb,
844 sizeof(*geometry->fill.bezier_vertices), vs_cb, ps_cb, brush, opacity_brush);
846 ID3D10Buffer_Release(vb);
849 done:
850 ID3D10Buffer_Release(ps_cb);
851 ID3D10Buffer_Release(vs_cb);
854 static void STDMETHODCALLTYPE d2d_d3d_render_target_FillGeometry(ID2D1RenderTarget *iface,
855 ID2D1Geometry *geometry, ID2D1Brush *brush, ID2D1Brush *opacity_brush)
857 const struct d2d_geometry *geometry_impl = unsafe_impl_from_ID2D1Geometry(geometry);
858 struct d2d_brush *opacity_brush_impl = unsafe_impl_from_ID2D1Brush(opacity_brush);
859 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
860 struct d2d_brush *brush_impl = unsafe_impl_from_ID2D1Brush(brush);
862 TRACE("iface %p, geometry %p, brush %p, opacity_brush %p.\n", iface, geometry, brush, opacity_brush);
864 if (FAILED(render_target->error.code))
865 return;
867 if (opacity_brush && brush_impl->type != D2D_BRUSH_TYPE_BITMAP)
869 render_target->error.code = D2DERR_INCOMPATIBLE_BRUSH_TYPES;
870 render_target->error.tag1 = render_target->drawing_state.tag1;
871 render_target->error.tag2 = render_target->drawing_state.tag2;
872 return;
875 d2d_rt_fill_geometry(render_target, geometry_impl, brush_impl, opacity_brush_impl);
878 static void STDMETHODCALLTYPE d2d_d3d_render_target_FillMesh(ID2D1RenderTarget *iface,
879 ID2D1Mesh *mesh, ID2D1Brush *brush)
881 FIXME("iface %p, mesh %p, brush %p stub!\n", iface, mesh, brush);
884 static void STDMETHODCALLTYPE d2d_d3d_render_target_FillOpacityMask(ID2D1RenderTarget *iface,
885 ID2D1Bitmap *mask, ID2D1Brush *brush, D2D1_OPACITY_MASK_CONTENT content,
886 const D2D1_RECT_F *dst_rect, const D2D1_RECT_F *src_rect)
888 FIXME("iface %p, mask %p, brush %p, content %#x, dst_rect %p, src_rect %p stub!\n",
889 iface, mask, brush, content, dst_rect, src_rect);
892 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawBitmap(ID2D1RenderTarget *iface,
893 ID2D1Bitmap *bitmap, const D2D1_RECT_F *dst_rect, float opacity,
894 D2D1_BITMAP_INTERPOLATION_MODE interpolation_mode, const D2D1_RECT_F *src_rect)
896 D2D1_BITMAP_BRUSH_PROPERTIES bitmap_brush_desc;
897 D2D1_BRUSH_PROPERTIES brush_desc;
898 ID2D1BitmapBrush *brush;
899 D2D1_RECT_F s, d;
900 HRESULT hr;
902 TRACE("iface %p, bitmap %p, dst_rect %p, opacity %.8e, interpolation_mode %#x, src_rect %p.\n",
903 iface, bitmap, dst_rect, opacity, interpolation_mode, src_rect);
905 if (src_rect)
907 s = *src_rect;
909 else
911 D2D1_SIZE_F size;
913 size = ID2D1Bitmap_GetSize(bitmap);
914 s.left = 0.0f;
915 s.top = 0.0f;
916 s.right = size.width;
917 s.bottom = size.height;
920 if (dst_rect)
922 d = *dst_rect;
924 else
926 d.left = 0.0f;
927 d.top = 0.0f;
928 d.right = s.right - s.left;
929 d.bottom = s.bottom - s.top;
932 bitmap_brush_desc.extendModeX = D2D1_EXTEND_MODE_CLAMP;
933 bitmap_brush_desc.extendModeY = D2D1_EXTEND_MODE_CLAMP;
934 bitmap_brush_desc.interpolationMode = interpolation_mode;
936 brush_desc.opacity = opacity;
937 brush_desc.transform._11 = fabsf((d.right - d.left) / (s.right - s.left));
938 brush_desc.transform._21 = 0.0f;
939 brush_desc.transform._31 = min(d.left, d.right) - min(s.left, s.right) * brush_desc.transform._11;
940 brush_desc.transform._12 = 0.0f;
941 brush_desc.transform._22 = fabsf((d.bottom - d.top) / (s.bottom - s.top));
942 brush_desc.transform._32 = min(d.top, d.bottom) - min(s.top, s.bottom) * brush_desc.transform._22;
944 if (FAILED(hr = ID2D1RenderTarget_CreateBitmapBrush(iface, bitmap, &bitmap_brush_desc, &brush_desc, &brush)))
946 ERR("Failed to create bitmap brush, hr %#x.\n", hr);
947 return;
950 ID2D1RenderTarget_FillRectangle(iface, &d, (ID2D1Brush *)brush);
951 ID2D1BitmapBrush_Release(brush);
954 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawText(ID2D1RenderTarget *iface,
955 const WCHAR *string, UINT32 string_len, IDWriteTextFormat *text_format, const D2D1_RECT_F *layout_rect,
956 ID2D1Brush *brush, D2D1_DRAW_TEXT_OPTIONS options, DWRITE_MEASURING_MODE measuring_mode)
958 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
959 IDWriteTextLayout *text_layout;
960 IDWriteFactory *dwrite_factory;
961 D2D1_POINT_2F origin;
962 HRESULT hr;
964 TRACE("iface %p, string %s, string_len %u, text_format %p, layout_rect %p, "
965 "brush %p, options %#x, measuring_mode %#x.\n",
966 iface, debugstr_wn(string, string_len), string_len, text_format, layout_rect,
967 brush, options, measuring_mode);
969 if (FAILED(hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED,
970 &IID_IDWriteFactory, (IUnknown **)&dwrite_factory)))
972 ERR("Failed to create dwrite factory, hr %#x.\n", hr);
973 return;
976 if (measuring_mode == DWRITE_MEASURING_MODE_NATURAL)
977 hr = IDWriteFactory_CreateTextLayout(dwrite_factory, string, string_len, text_format,
978 layout_rect->right - layout_rect->left, layout_rect->bottom - layout_rect->top, &text_layout);
979 else
980 hr = IDWriteFactory_CreateGdiCompatibleTextLayout(dwrite_factory, string, string_len, text_format,
981 layout_rect->right - layout_rect->left, layout_rect->bottom - layout_rect->top, render_target->desc.dpiX / 96.0f,
982 (DWRITE_MATRIX*)&render_target->drawing_state.transform, measuring_mode == DWRITE_MEASURING_MODE_GDI_NATURAL, &text_layout);
983 IDWriteFactory_Release(dwrite_factory);
984 if (FAILED(hr))
986 ERR("Failed to create text layout, hr %#x.\n", hr);
987 return;
990 d2d_point_set(&origin, layout_rect->left, layout_rect->top);
991 ID2D1RenderTarget_DrawTextLayout(iface, origin, text_layout, brush, options);
992 IDWriteTextLayout_Release(text_layout);
995 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawTextLayout(ID2D1RenderTarget *iface,
996 D2D1_POINT_2F origin, IDWriteTextLayout *layout, ID2D1Brush *brush, D2D1_DRAW_TEXT_OPTIONS options)
998 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
999 struct d2d_draw_text_layout_ctx ctx;
1000 HRESULT hr;
1002 TRACE("iface %p, origin {%.8e, %.8e}, layout %p, brush %p, options %#x.\n",
1003 iface, origin.x, origin.y, layout, brush, options);
1005 ctx.brush = brush;
1006 ctx.options = options;
1008 if (FAILED(hr = IDWriteTextLayout_Draw(layout,
1009 &ctx, &render_target->IDWriteTextRenderer_iface, origin.x, origin.y)))
1010 FIXME("Failed to draw text layout, hr %#x.\n", hr);
1013 static void d2d_rt_draw_glyph_run_outline(struct d2d_d3d_render_target *render_target,
1014 D2D1_POINT_2F baseline_origin, const DWRITE_GLYPH_RUN *glyph_run, ID2D1Brush *brush)
1016 D2D1_MATRIX_3X2_F *transform, prev_transform;
1017 ID2D1PathGeometry *geometry;
1018 ID2D1GeometrySink *sink;
1019 HRESULT hr;
1021 if (FAILED(hr = ID2D1Factory_CreatePathGeometry(render_target->factory, &geometry)))
1023 ERR("Failed to create geometry, hr %#x.\n", hr);
1024 return;
1027 if (FAILED(hr = ID2D1PathGeometry_Open(geometry, &sink)))
1029 ERR("Failed to open geometry sink, hr %#x.\n", hr);
1030 ID2D1PathGeometry_Release(geometry);
1031 return;
1034 if (FAILED(hr = IDWriteFontFace_GetGlyphRunOutline(glyph_run->fontFace, glyph_run->fontEmSize,
1035 glyph_run->glyphIndices, glyph_run->glyphAdvances, glyph_run->glyphOffsets, glyph_run->glyphCount,
1036 glyph_run->isSideways, glyph_run->bidiLevel & 1, (IDWriteGeometrySink *)sink)))
1038 ERR("Failed to get glyph run outline, hr %#x.\n", hr);
1039 ID2D1GeometrySink_Release(sink);
1040 ID2D1PathGeometry_Release(geometry);
1041 return;
1044 if (FAILED(hr = ID2D1GeometrySink_Close(sink)))
1045 ERR("Failed to close geometry sink, hr %#x.\n", hr);
1046 ID2D1GeometrySink_Release(sink);
1048 transform = &render_target->drawing_state.transform;
1049 prev_transform = *transform;
1050 transform->_31 += baseline_origin.x * transform->_11 + baseline_origin.y * transform->_21;
1051 transform->_32 += baseline_origin.x * transform->_12 + baseline_origin.y * transform->_22;
1052 d2d_rt_fill_geometry(render_target, unsafe_impl_from_ID2D1Geometry((ID2D1Geometry *)geometry),
1053 unsafe_impl_from_ID2D1Brush(brush), NULL);
1054 *transform = prev_transform;
1056 ID2D1PathGeometry_Release(geometry);
1059 static void d2d_rt_draw_glyph_run_bitmap(struct d2d_d3d_render_target *render_target,
1060 D2D1_POINT_2F baseline_origin, const DWRITE_GLYPH_RUN *glyph_run, ID2D1Brush *brush,
1061 float ppd, DWRITE_RENDERING_MODE rendering_mode, DWRITE_MEASURING_MODE measuring_mode)
1063 ID2D1RectangleGeometry *geometry = NULL;
1064 ID2D1BitmapBrush *opacity_brush = NULL;
1065 D2D1_BITMAP_PROPERTIES bitmap_desc;
1066 ID2D1Bitmap *opacity_bitmap = NULL;
1067 IDWriteGlyphRunAnalysis *analysis;
1068 DWRITE_TEXTURE_TYPE texture_type;
1069 D2D1_BRUSH_PROPERTIES brush_desc;
1070 IDWriteFactory *dwrite_factory;
1071 void *opacity_values = NULL;
1072 size_t opacity_values_size;
1073 D2D1_SIZE_U bitmap_size;
1074 D2D1_RECT_F run_rect;
1075 RECT bounds;
1076 HRESULT hr;
1078 if (FAILED(hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED,
1079 &IID_IDWriteFactory, (IUnknown **)&dwrite_factory)))
1081 ERR("Failed to create dwrite factory, hr %#x.\n", hr);
1082 return;
1085 hr = IDWriteFactory_CreateGlyphRunAnalysis(dwrite_factory, glyph_run, ppd, NULL,
1086 rendering_mode, measuring_mode, baseline_origin.x, baseline_origin.y, &analysis);
1087 IDWriteFactory_Release(dwrite_factory);
1088 if (FAILED(hr))
1090 ERR("Failed to create glyph run analysis, hr %#x.\n", hr);
1091 return;
1094 if (rendering_mode == DWRITE_RENDERING_MODE_ALIASED)
1095 texture_type = DWRITE_TEXTURE_ALIASED_1x1;
1096 else
1097 texture_type = DWRITE_TEXTURE_CLEARTYPE_3x1;
1099 if (FAILED(hr = IDWriteGlyphRunAnalysis_GetAlphaTextureBounds(analysis, texture_type, &bounds)))
1101 ERR("Failed to get alpha texture bounds, hr %#x.\n", hr);
1102 goto done;
1105 d2d_size_set(&bitmap_size, bounds.right - bounds.left, bounds.bottom - bounds.top);
1106 if (!bitmap_size.width || !bitmap_size.height)
1108 /* Empty run, nothing to do. */
1109 goto done;
1112 if (texture_type == DWRITE_TEXTURE_CLEARTYPE_3x1)
1113 bitmap_size.width *= 3;
1114 opacity_values_size = bitmap_size.width * bitmap_size.height;
1115 if (!(opacity_values = HeapAlloc(GetProcessHeap(), 0, opacity_values_size)))
1117 ERR("Failed to allocate opacity values.\n");
1118 goto done;
1121 if (FAILED(hr = IDWriteGlyphRunAnalysis_CreateAlphaTexture(analysis,
1122 texture_type, &bounds, opacity_values, opacity_values_size)))
1124 ERR("Failed to create alpha texture, hr %#x.\n", hr);
1125 goto done;
1128 bitmap_desc.pixelFormat.format = DXGI_FORMAT_A8_UNORM;
1129 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
1130 bitmap_desc.dpiX = render_target->desc.dpiX;
1131 if (texture_type == DWRITE_TEXTURE_CLEARTYPE_3x1)
1132 bitmap_desc.dpiX *= 3.0f;
1133 bitmap_desc.dpiY = render_target->desc.dpiY;
1134 if (FAILED(hr = d2d_d3d_render_target_CreateBitmap(&render_target->ID2D1RenderTarget_iface,
1135 bitmap_size, opacity_values, bitmap_size.width, &bitmap_desc, &opacity_bitmap)))
1137 ERR("Failed to create opacity bitmap, hr %#x.\n", hr);
1138 goto done;
1141 brush_desc.opacity = 1.0f;
1142 brush_desc.transform._11 = 1.0f;
1143 brush_desc.transform._12 = 0.0f;
1144 brush_desc.transform._21 = 0.0f;
1145 brush_desc.transform._22 = 1.0f;
1146 brush_desc.transform._31 = bounds.left;
1147 brush_desc.transform._32 = bounds.top;
1148 if (FAILED(hr = d2d_d3d_render_target_CreateBitmapBrush(&render_target->ID2D1RenderTarget_iface,
1149 opacity_bitmap, NULL, &brush_desc, &opacity_brush)))
1151 ERR("Failed to create opacity bitmap brush, hr %#x.\n", hr);
1152 goto done;
1155 d2d_rect_set(&run_rect, bounds.left, bounds.top, bounds.right, bounds.bottom);
1156 if (FAILED(hr = ID2D1Factory_CreateRectangleGeometry(render_target->factory, &run_rect, &geometry)))
1158 ERR("Failed to create geometry, hr %#x.\n", hr);
1159 goto done;
1162 d2d_rt_fill_geometry(render_target, unsafe_impl_from_ID2D1Geometry((ID2D1Geometry *)geometry),
1163 unsafe_impl_from_ID2D1Brush(brush), unsafe_impl_from_ID2D1Brush((ID2D1Brush *)opacity_brush));
1165 done:
1166 if (geometry)
1167 ID2D1RectangleGeometry_Release(geometry);
1168 if (opacity_brush)
1169 ID2D1BitmapBrush_Release(opacity_brush);
1170 if (opacity_bitmap)
1171 ID2D1Bitmap_Release(opacity_bitmap);
1172 HeapFree(GetProcessHeap(), 0, opacity_values);
1173 IDWriteGlyphRunAnalysis_Release(analysis);
1176 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawGlyphRun(ID2D1RenderTarget *iface,
1177 D2D1_POINT_2F baseline_origin, const DWRITE_GLYPH_RUN *glyph_run, ID2D1Brush *brush,
1178 DWRITE_MEASURING_MODE measuring_mode)
1180 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1181 IDWriteRenderingParams *rendering_params;
1182 DWRITE_RENDERING_MODE rendering_mode;
1183 HRESULT hr;
1184 float ppd;
1186 TRACE("iface %p, baseline_origin {%.8e, %.8e}, glyph_run %p, brush %p, measuring_mode %#x.\n",
1187 iface, baseline_origin.x, baseline_origin.y, glyph_run, brush, measuring_mode);
1189 if (FAILED(render_target->error.code))
1190 return;
1192 if (render_target->drawing_state.textAntialiasMode != D2D1_TEXT_ANTIALIAS_MODE_DEFAULT)
1193 FIXME("Ignoring text antialiasing mode %#x.\n", render_target->drawing_state.textAntialiasMode);
1195 ppd = max(render_target->desc.dpiX, render_target->desc.dpiY) / 96.0f;
1196 rendering_params = render_target->text_rendering_params ? render_target->text_rendering_params
1197 : render_target->default_text_rendering_params;
1198 if (FAILED(hr = IDWriteFontFace_GetRecommendedRenderingMode(glyph_run->fontFace, glyph_run->fontEmSize,
1199 ppd, measuring_mode, rendering_params, &rendering_mode)))
1201 ERR("Failed to get recommended rendering mode, hr %#x.\n", hr);
1202 rendering_mode = DWRITE_RENDERING_MODE_OUTLINE;
1205 if (rendering_mode == DWRITE_RENDERING_MODE_OUTLINE)
1206 d2d_rt_draw_glyph_run_outline(render_target, baseline_origin, glyph_run, brush);
1207 else
1208 d2d_rt_draw_glyph_run_bitmap(render_target, baseline_origin, glyph_run, brush,
1209 ppd, rendering_mode, measuring_mode);
1212 static void STDMETHODCALLTYPE d2d_d3d_render_target_SetTransform(ID2D1RenderTarget *iface,
1213 const D2D1_MATRIX_3X2_F *transform)
1215 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1217 TRACE("iface %p, transform %p.\n", iface, transform);
1219 render_target->drawing_state.transform = *transform;
1222 static void STDMETHODCALLTYPE d2d_d3d_render_target_GetTransform(ID2D1RenderTarget *iface,
1223 D2D1_MATRIX_3X2_F *transform)
1225 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1227 TRACE("iface %p, transform %p.\n", iface, transform);
1229 *transform = render_target->drawing_state.transform;
1232 static void STDMETHODCALLTYPE d2d_d3d_render_target_SetAntialiasMode(ID2D1RenderTarget *iface,
1233 D2D1_ANTIALIAS_MODE antialias_mode)
1235 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1237 TRACE("iface %p, antialias_mode %#x stub!\n", iface, antialias_mode);
1239 render_target->drawing_state.antialiasMode = antialias_mode;
1242 static D2D1_ANTIALIAS_MODE STDMETHODCALLTYPE d2d_d3d_render_target_GetAntialiasMode(ID2D1RenderTarget *iface)
1244 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1246 TRACE("iface %p.\n", iface);
1248 return render_target->drawing_state.antialiasMode;
1251 static void STDMETHODCALLTYPE d2d_d3d_render_target_SetTextAntialiasMode(ID2D1RenderTarget *iface,
1252 D2D1_TEXT_ANTIALIAS_MODE antialias_mode)
1254 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1256 TRACE("iface %p, antialias_mode %#x.\n", iface, antialias_mode);
1258 render_target->drawing_state.textAntialiasMode = antialias_mode;
1261 static D2D1_TEXT_ANTIALIAS_MODE STDMETHODCALLTYPE d2d_d3d_render_target_GetTextAntialiasMode(ID2D1RenderTarget *iface)
1263 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1265 TRACE("iface %p.\n", iface);
1267 return render_target->drawing_state.textAntialiasMode;
1270 static void STDMETHODCALLTYPE d2d_d3d_render_target_SetTextRenderingParams(ID2D1RenderTarget *iface,
1271 IDWriteRenderingParams *text_rendering_params)
1273 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1275 TRACE("iface %p, text_rendering_params %p.\n", iface, text_rendering_params);
1277 if (text_rendering_params)
1278 IDWriteRenderingParams_AddRef(text_rendering_params);
1279 if (render_target->text_rendering_params)
1280 IDWriteRenderingParams_Release(render_target->text_rendering_params);
1281 render_target->text_rendering_params = text_rendering_params;
1284 static void STDMETHODCALLTYPE d2d_d3d_render_target_GetTextRenderingParams(ID2D1RenderTarget *iface,
1285 IDWriteRenderingParams **text_rendering_params)
1287 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1289 TRACE("iface %p, text_rendering_params %p.\n", iface, text_rendering_params);
1291 if ((*text_rendering_params = render_target->text_rendering_params))
1292 IDWriteRenderingParams_AddRef(*text_rendering_params);
1295 static void STDMETHODCALLTYPE d2d_d3d_render_target_SetTags(ID2D1RenderTarget *iface, D2D1_TAG tag1, D2D1_TAG tag2)
1297 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1299 TRACE("iface %p, tag1 %s, tag2 %s.\n", iface, wine_dbgstr_longlong(tag1), wine_dbgstr_longlong(tag2));
1301 render_target->drawing_state.tag1 = tag1;
1302 render_target->drawing_state.tag2 = tag2;
1305 static void STDMETHODCALLTYPE d2d_d3d_render_target_GetTags(ID2D1RenderTarget *iface, D2D1_TAG *tag1, D2D1_TAG *tag2)
1307 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1309 TRACE("iface %p, tag1 %p, tag2 %p.\n", iface, tag1, tag2);
1311 *tag1 = render_target->drawing_state.tag1;
1312 *tag2 = render_target->drawing_state.tag2;
1315 static void STDMETHODCALLTYPE d2d_d3d_render_target_PushLayer(ID2D1RenderTarget *iface,
1316 const D2D1_LAYER_PARAMETERS *layer_parameters, ID2D1Layer *layer)
1318 FIXME("iface %p, layer_parameters %p, layer %p stub!\n", iface, layer_parameters, layer);
1321 static void STDMETHODCALLTYPE d2d_d3d_render_target_PopLayer(ID2D1RenderTarget *iface)
1323 FIXME("iface %p stub!\n", iface);
1326 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_Flush(ID2D1RenderTarget *iface, D2D1_TAG *tag1, D2D1_TAG *tag2)
1328 FIXME("iface %p, tag1 %p, tag2 %p stub!\n", iface, tag1, tag2);
1330 return E_NOTIMPL;
1333 static void STDMETHODCALLTYPE d2d_d3d_render_target_SaveDrawingState(ID2D1RenderTarget *iface,
1334 ID2D1DrawingStateBlock *state_block)
1336 struct d2d_state_block *state_block_impl = unsafe_impl_from_ID2D1DrawingStateBlock(state_block);
1337 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1339 TRACE("iface %p, state_block %p.\n", iface, state_block);
1341 state_block_impl->drawing_state = render_target->drawing_state;
1342 if (render_target->text_rendering_params)
1343 IDWriteRenderingParams_AddRef(render_target->text_rendering_params);
1344 if (state_block_impl->text_rendering_params)
1345 IDWriteRenderingParams_Release(state_block_impl->text_rendering_params);
1346 state_block_impl->text_rendering_params = render_target->text_rendering_params;
1349 static void STDMETHODCALLTYPE d2d_d3d_render_target_RestoreDrawingState(ID2D1RenderTarget *iface,
1350 ID2D1DrawingStateBlock *state_block)
1352 struct d2d_state_block *state_block_impl = unsafe_impl_from_ID2D1DrawingStateBlock(state_block);
1353 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1355 TRACE("iface %p, state_block %p.\n", iface, state_block);
1357 render_target->drawing_state = state_block_impl->drawing_state;
1358 if (state_block_impl->text_rendering_params)
1359 IDWriteRenderingParams_AddRef(state_block_impl->text_rendering_params);
1360 if (render_target->text_rendering_params)
1361 IDWriteRenderingParams_Release(render_target->text_rendering_params);
1362 render_target->text_rendering_params = state_block_impl->text_rendering_params;
1365 static void STDMETHODCALLTYPE d2d_d3d_render_target_PushAxisAlignedClip(ID2D1RenderTarget *iface,
1366 const D2D1_RECT_F *clip_rect, D2D1_ANTIALIAS_MODE antialias_mode)
1368 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1369 D2D1_RECT_F transformed_rect;
1370 float x_scale, y_scale;
1371 D2D1_POINT_2F point;
1373 TRACE("iface %p, clip_rect %p, antialias_mode %#x.\n", iface, clip_rect, antialias_mode);
1375 if (antialias_mode != D2D1_ANTIALIAS_MODE_ALIASED)
1376 FIXME("Ignoring antialias_mode %#x.\n", antialias_mode);
1378 x_scale = render_target->desc.dpiX / 96.0f;
1379 y_scale = render_target->desc.dpiY / 96.0f;
1380 d2d_point_transform(&point, &render_target->drawing_state.transform,
1381 clip_rect->left * x_scale, clip_rect->top * y_scale);
1382 d2d_rect_set(&transformed_rect, point.x, point.y, point.x, point.y);
1383 d2d_point_transform(&point, &render_target->drawing_state.transform,
1384 clip_rect->left * x_scale, clip_rect->bottom * y_scale);
1385 d2d_rect_expand(&transformed_rect, &point);
1386 d2d_point_transform(&point, &render_target->drawing_state.transform,
1387 clip_rect->right * x_scale, clip_rect->top * y_scale);
1388 d2d_rect_expand(&transformed_rect, &point);
1389 d2d_point_transform(&point, &render_target->drawing_state.transform,
1390 clip_rect->right * x_scale, clip_rect->bottom * y_scale);
1391 d2d_rect_expand(&transformed_rect, &point);
1393 if (!d2d_clip_stack_push(&render_target->clip_stack, &transformed_rect))
1394 WARN("Failed to push clip rect.\n");
1397 static void STDMETHODCALLTYPE d2d_d3d_render_target_PopAxisAlignedClip(ID2D1RenderTarget *iface)
1399 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1401 TRACE("iface %p.\n", iface);
1403 d2d_clip_stack_pop(&render_target->clip_stack);
1406 static void STDMETHODCALLTYPE d2d_d3d_render_target_Clear(ID2D1RenderTarget *iface, const D2D1_COLOR_F *color)
1408 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1409 D2D1_COLOR_F c = {0.0f, 0.0f, 0.0f, 0.0f};
1410 D3D10_SUBRESOURCE_DATA buffer_data;
1411 D3D10_BUFFER_DESC buffer_desc;
1412 ID3D10Buffer *vs_cb, *ps_cb;
1413 HRESULT hr;
1415 static const float transform[] =
1417 1.0f, 0.0f, 0.0f, 0.0f,
1418 0.0f, -1.0f, 0.0f, 0.0f,
1421 TRACE("iface %p, color %p.\n", iface, color);
1423 buffer_desc.ByteWidth = sizeof(transform);
1424 buffer_desc.Usage = D3D10_USAGE_DEFAULT;
1425 buffer_desc.BindFlags = D3D10_BIND_CONSTANT_BUFFER;
1426 buffer_desc.CPUAccessFlags = 0;
1427 buffer_desc.MiscFlags = 0;
1429 buffer_data.pSysMem = transform;
1430 buffer_data.SysMemPitch = 0;
1431 buffer_data.SysMemSlicePitch = 0;
1433 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device, &buffer_desc, &buffer_data, &vs_cb)))
1435 WARN("Failed to create constant buffer, hr %#x.\n", hr);
1436 return;
1439 if (color)
1440 c = *color;
1441 if (render_target->desc.pixelFormat.alphaMode == D2D1_ALPHA_MODE_IGNORE)
1442 c.a = 1.0f;
1443 c.r *= c.a;
1444 c.g *= c.a;
1445 c.b *= c.a;
1446 buffer_desc.ByteWidth = sizeof(c);
1447 buffer_data.pSysMem = &c;
1449 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device, &buffer_desc, &buffer_data, &ps_cb)))
1451 WARN("Failed to create constant buffer, hr %#x.\n", hr);
1452 ID3D10Buffer_Release(vs_cb);
1453 return;
1456 d2d_rt_draw(render_target, D2D_SHAPE_TYPE_TRIANGLE, render_target->ib, 6,
1457 render_target->vb, render_target->vb_stride, vs_cb, ps_cb, NULL, NULL);
1459 ID3D10Buffer_Release(ps_cb);
1460 ID3D10Buffer_Release(vs_cb);
1463 static void STDMETHODCALLTYPE d2d_d3d_render_target_BeginDraw(ID2D1RenderTarget *iface)
1465 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1467 TRACE("iface %p.\n", iface);
1469 memset(&render_target->error, 0, sizeof(render_target->error));
1472 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_EndDraw(ID2D1RenderTarget *iface,
1473 D2D1_TAG *tag1, D2D1_TAG *tag2)
1475 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1477 TRACE("iface %p, tag1 %p, tag2 %p.\n", iface, tag1, tag2);
1479 if (tag1)
1480 *tag1 = render_target->error.tag1;
1481 if (tag2)
1482 *tag2 = render_target->error.tag2;
1484 return render_target->error.code;
1487 static D2D1_PIXEL_FORMAT * STDMETHODCALLTYPE d2d_d3d_render_target_GetPixelFormat(ID2D1RenderTarget *iface,
1488 D2D1_PIXEL_FORMAT *format)
1490 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1492 TRACE("iface %p, format %p.\n", iface, format);
1494 *format = render_target->desc.pixelFormat;
1495 return format;
1498 static void STDMETHODCALLTYPE d2d_d3d_render_target_SetDpi(ID2D1RenderTarget *iface, float dpi_x, float dpi_y)
1500 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1502 TRACE("iface %p, dpi_x %.8e, dpi_y %.8e.\n", iface, dpi_x, dpi_y);
1504 if (dpi_x == 0.0f && dpi_y == 0.0f)
1506 dpi_x = 96.0f;
1507 dpi_y = 96.0f;
1509 else if (dpi_x <= 0.0f || dpi_y <= 0.0f)
1510 return;
1512 render_target->desc.dpiX = dpi_x;
1513 render_target->desc.dpiY = dpi_y;
1516 static void STDMETHODCALLTYPE d2d_d3d_render_target_GetDpi(ID2D1RenderTarget *iface, float *dpi_x, float *dpi_y)
1518 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1520 TRACE("iface %p, dpi_x %p, dpi_y %p.\n", iface, dpi_x, dpi_y);
1522 *dpi_x = render_target->desc.dpiX;
1523 *dpi_y = render_target->desc.dpiY;
1526 static D2D1_SIZE_F * STDMETHODCALLTYPE d2d_d3d_render_target_GetSize(ID2D1RenderTarget *iface, D2D1_SIZE_F *size)
1528 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1530 TRACE("iface %p, size %p.\n", iface, size);
1532 size->width = render_target->pixel_size.width / (render_target->desc.dpiX / 96.0f);
1533 size->height = render_target->pixel_size.height / (render_target->desc.dpiY / 96.0f);
1534 return size;
1537 static D2D1_SIZE_U * STDMETHODCALLTYPE d2d_d3d_render_target_GetPixelSize(ID2D1RenderTarget *iface,
1538 D2D1_SIZE_U *pixel_size)
1540 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1542 TRACE("iface %p, pixel_size %p.\n", iface, pixel_size);
1544 *pixel_size = render_target->pixel_size;
1545 return pixel_size;
1548 static UINT32 STDMETHODCALLTYPE d2d_d3d_render_target_GetMaximumBitmapSize(ID2D1RenderTarget *iface)
1550 FIXME("iface %p stub!\n", iface);
1552 return 0;
1555 static BOOL STDMETHODCALLTYPE d2d_d3d_render_target_IsSupported(ID2D1RenderTarget *iface,
1556 const D2D1_RENDER_TARGET_PROPERTIES *desc)
1558 FIXME("iface %p, desc %p stub!\n", iface, desc);
1560 return FALSE;
1563 static const struct ID2D1RenderTargetVtbl d2d_d3d_render_target_vtbl =
1565 d2d_d3d_render_target_QueryInterface,
1566 d2d_d3d_render_target_AddRef,
1567 d2d_d3d_render_target_Release,
1568 d2d_d3d_render_target_GetFactory,
1569 d2d_d3d_render_target_CreateBitmap,
1570 d2d_d3d_render_target_CreateBitmapFromWicBitmap,
1571 d2d_d3d_render_target_CreateSharedBitmap,
1572 d2d_d3d_render_target_CreateBitmapBrush,
1573 d2d_d3d_render_target_CreateSolidColorBrush,
1574 d2d_d3d_render_target_CreateGradientStopCollection,
1575 d2d_d3d_render_target_CreateLinearGradientBrush,
1576 d2d_d3d_render_target_CreateRadialGradientBrush,
1577 d2d_d3d_render_target_CreateCompatibleRenderTarget,
1578 d2d_d3d_render_target_CreateLayer,
1579 d2d_d3d_render_target_CreateMesh,
1580 d2d_d3d_render_target_DrawLine,
1581 d2d_d3d_render_target_DrawRectangle,
1582 d2d_d3d_render_target_FillRectangle,
1583 d2d_d3d_render_target_DrawRoundedRectangle,
1584 d2d_d3d_render_target_FillRoundedRectangle,
1585 d2d_d3d_render_target_DrawEllipse,
1586 d2d_d3d_render_target_FillEllipse,
1587 d2d_d3d_render_target_DrawGeometry,
1588 d2d_d3d_render_target_FillGeometry,
1589 d2d_d3d_render_target_FillMesh,
1590 d2d_d3d_render_target_FillOpacityMask,
1591 d2d_d3d_render_target_DrawBitmap,
1592 d2d_d3d_render_target_DrawText,
1593 d2d_d3d_render_target_DrawTextLayout,
1594 d2d_d3d_render_target_DrawGlyphRun,
1595 d2d_d3d_render_target_SetTransform,
1596 d2d_d3d_render_target_GetTransform,
1597 d2d_d3d_render_target_SetAntialiasMode,
1598 d2d_d3d_render_target_GetAntialiasMode,
1599 d2d_d3d_render_target_SetTextAntialiasMode,
1600 d2d_d3d_render_target_GetTextAntialiasMode,
1601 d2d_d3d_render_target_SetTextRenderingParams,
1602 d2d_d3d_render_target_GetTextRenderingParams,
1603 d2d_d3d_render_target_SetTags,
1604 d2d_d3d_render_target_GetTags,
1605 d2d_d3d_render_target_PushLayer,
1606 d2d_d3d_render_target_PopLayer,
1607 d2d_d3d_render_target_Flush,
1608 d2d_d3d_render_target_SaveDrawingState,
1609 d2d_d3d_render_target_RestoreDrawingState,
1610 d2d_d3d_render_target_PushAxisAlignedClip,
1611 d2d_d3d_render_target_PopAxisAlignedClip,
1612 d2d_d3d_render_target_Clear,
1613 d2d_d3d_render_target_BeginDraw,
1614 d2d_d3d_render_target_EndDraw,
1615 d2d_d3d_render_target_GetPixelFormat,
1616 d2d_d3d_render_target_SetDpi,
1617 d2d_d3d_render_target_GetDpi,
1618 d2d_d3d_render_target_GetSize,
1619 d2d_d3d_render_target_GetPixelSize,
1620 d2d_d3d_render_target_GetMaximumBitmapSize,
1621 d2d_d3d_render_target_IsSupported,
1624 static inline struct d2d_d3d_render_target *impl_from_IDWriteTextRenderer(IDWriteTextRenderer *iface)
1626 return CONTAINING_RECORD(iface, struct d2d_d3d_render_target, IDWriteTextRenderer_iface);
1629 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_QueryInterface(IDWriteTextRenderer *iface, REFIID iid, void **out)
1631 TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
1633 if (IsEqualGUID(iid, &IID_IDWriteTextRenderer)
1634 || IsEqualGUID(iid, &IID_IDWritePixelSnapping)
1635 || IsEqualGUID(iid, &IID_IUnknown))
1637 IDWriteTextRenderer_AddRef(iface);
1638 *out = iface;
1639 return S_OK;
1642 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
1644 *out = NULL;
1645 return E_NOINTERFACE;
1648 static ULONG STDMETHODCALLTYPE d2d_text_renderer_AddRef(IDWriteTextRenderer *iface)
1650 struct d2d_d3d_render_target *render_target = impl_from_IDWriteTextRenderer(iface);
1652 TRACE("iface %p.\n", iface);
1654 return d2d_d3d_render_target_AddRef(&render_target->ID2D1RenderTarget_iface);
1657 static ULONG STDMETHODCALLTYPE d2d_text_renderer_Release(IDWriteTextRenderer *iface)
1659 struct d2d_d3d_render_target *render_target = impl_from_IDWriteTextRenderer(iface);
1661 TRACE("iface %p.\n", iface);
1663 return d2d_d3d_render_target_Release(&render_target->ID2D1RenderTarget_iface);
1666 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_IsPixelSnappingDisabled(IDWriteTextRenderer *iface,
1667 void *ctx, BOOL *disabled)
1669 struct d2d_draw_text_layout_ctx *context = ctx;
1671 TRACE("iface %p, ctx %p, disabled %p.\n", iface, ctx, disabled);
1673 *disabled = context->options & D2D1_DRAW_TEXT_OPTIONS_NO_SNAP;
1675 return S_OK;
1678 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_GetCurrentTransform(IDWriteTextRenderer *iface,
1679 void *ctx, DWRITE_MATRIX *transform)
1681 struct d2d_d3d_render_target *render_target = impl_from_IDWriteTextRenderer(iface);
1683 TRACE("iface %p, ctx %p, transform %p.\n", iface, ctx, transform);
1685 ID2D1RenderTarget_GetTransform(&render_target->ID2D1RenderTarget_iface, (D2D1_MATRIX_3X2_F *)transform);
1687 return S_OK;
1690 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_GetPixelsPerDip(IDWriteTextRenderer *iface, void *ctx, float *ppd)
1692 struct d2d_d3d_render_target *render_target = impl_from_IDWriteTextRenderer(iface);
1694 TRACE("iface %p, ctx %p, ppd %p.\n", iface, ctx, ppd);
1696 *ppd = render_target->desc.dpiY / 96.0f;
1698 return S_OK;
1701 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_DrawGlyphRun(IDWriteTextRenderer *iface, void *ctx,
1702 float baseline_origin_x, float baseline_origin_y, DWRITE_MEASURING_MODE measuring_mode,
1703 const DWRITE_GLYPH_RUN *glyph_run, const DWRITE_GLYPH_RUN_DESCRIPTION *desc, IUnknown *effect)
1705 struct d2d_d3d_render_target *render_target = impl_from_IDWriteTextRenderer(iface);
1706 D2D1_POINT_2F baseline_origin = {baseline_origin_x, baseline_origin_y};
1707 struct d2d_draw_text_layout_ctx *context = ctx;
1708 BOOL color_font = FALSE;
1709 ID2D1Brush *brush;
1711 TRACE("iface %p, ctx %p, baseline_origin_x %.8e, baseline_origin_y %.8e, "
1712 "measuring_mode %#x, glyph_run %p, desc %p, effect %p.\n",
1713 iface, ctx, baseline_origin_x, baseline_origin_y,
1714 measuring_mode, glyph_run, desc, effect);
1716 if (desc)
1717 WARN("Ignoring glyph run description %p.\n", desc);
1718 if (context->options & ~(D2D1_DRAW_TEXT_OPTIONS_NO_SNAP | D2D1_DRAW_TEXT_OPTIONS_ENABLE_COLOR_FONT))
1719 FIXME("Ignoring options %#x.\n", context->options);
1721 brush = d2d_draw_get_text_brush(context, effect);
1723 TRACE("%s\n", debugstr_wn(desc->string, desc->stringLength));
1725 if (context->options & D2D1_DRAW_TEXT_OPTIONS_ENABLE_COLOR_FONT)
1727 IDWriteFontFace2 *fontface;
1729 if (SUCCEEDED(IDWriteFontFace_QueryInterface(glyph_run->fontFace,
1730 &IID_IDWriteFontFace2, (void **)&fontface)))
1732 color_font = IDWriteFontFace2_IsColorFont(fontface);
1733 IDWriteFontFace2_Release(fontface);
1737 if (color_font)
1739 IDWriteColorGlyphRunEnumerator *layers;
1740 IDWriteFactory2 *dwrite_factory;
1741 HRESULT hr;
1743 if (FAILED(hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, &IID_IDWriteFactory2,
1744 (IUnknown **)&dwrite_factory)))
1746 ERR("Failed to create dwrite factory, hr %#x.\n", hr);
1747 ID2D1Brush_Release(brush);
1748 return hr;
1751 hr = IDWriteFactory2_TranslateColorGlyphRun(dwrite_factory, baseline_origin_x, baseline_origin_y,
1752 glyph_run, desc, measuring_mode, (DWRITE_MATRIX *)&render_target->drawing_state.transform, 0, &layers);
1753 IDWriteFactory2_Release(dwrite_factory);
1754 if (FAILED(hr))
1756 ERR("Failed to create color glyph run enumerator, hr %#x.\n", hr);
1757 ID2D1Brush_Release(brush);
1758 return hr;
1761 for (;;)
1763 const DWRITE_COLOR_GLYPH_RUN *color_run;
1764 ID2D1Brush *color_brush;
1765 D2D1_POINT_2F origin;
1766 BOOL has_run = FALSE;
1768 if (FAILED(hr = IDWriteColorGlyphRunEnumerator_MoveNext(layers, &has_run)))
1770 ERR("Failed to switch color glyph layer, hr %#x.\n", hr);
1771 break;
1774 if (!has_run)
1775 break;
1777 if (FAILED(hr = IDWriteColorGlyphRunEnumerator_GetCurrentRun(layers, &color_run)))
1779 ERR("Failed to get current color run, hr %#x.\n", hr);
1780 break;
1783 if (color_run->paletteIndex == 0xffff)
1784 color_brush = brush;
1785 else
1787 if (FAILED(hr = ID2D1RenderTarget_CreateSolidColorBrush(&render_target->ID2D1RenderTarget_iface,
1788 &color_run->runColor, NULL, (ID2D1SolidColorBrush **)&color_brush)))
1790 ERR("Failed to create solid color brush, hr %#x.\n", hr);
1791 break;
1795 origin.x = color_run->baselineOriginX;
1796 origin.y = color_run->baselineOriginY;
1797 ID2D1RenderTarget_DrawGlyphRun(&render_target->ID2D1RenderTarget_iface,
1798 origin, &color_run->glyphRun, color_brush, measuring_mode);
1800 if (color_brush != brush)
1801 ID2D1Brush_Release(color_brush);
1804 IDWriteColorGlyphRunEnumerator_Release(layers);
1806 else
1807 ID2D1RenderTarget_DrawGlyphRun(&render_target->ID2D1RenderTarget_iface,
1808 baseline_origin, glyph_run, brush, measuring_mode);
1810 ID2D1Brush_Release(brush);
1812 return S_OK;
1815 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_DrawUnderline(IDWriteTextRenderer *iface, void *ctx,
1816 float baseline_origin_x, float baseline_origin_y, const DWRITE_UNDERLINE *underline, IUnknown *effect)
1818 struct d2d_d3d_render_target *render_target = impl_from_IDWriteTextRenderer(iface);
1819 const D2D1_MATRIX_3X2_F *m = &render_target->drawing_state.transform;
1820 struct d2d_draw_text_layout_ctx *context = ctx;
1821 float min_thickness;
1822 ID2D1Brush *brush;
1823 D2D1_RECT_F rect;
1825 TRACE("iface %p, ctx %p, baseline_origin_x %.8e, baseline_origin_y %.8e, underline %p, effect %p\n",
1826 iface, ctx, baseline_origin_x, baseline_origin_y, underline, effect);
1828 /* minimal thickness in DIPs that will result in at least 1 pixel thick line */
1829 min_thickness = 96.0f / (render_target->desc.dpiY * sqrtf(m->_21 * m->_21 + m->_22 * m->_22));
1831 rect.left = baseline_origin_x;
1832 rect.top = baseline_origin_y + underline->offset;
1833 rect.right = baseline_origin_x + underline->width;
1834 rect.bottom = baseline_origin_y + underline->offset + max(underline->thickness, min_thickness);
1836 brush = d2d_draw_get_text_brush(context, effect);
1838 ID2D1RenderTarget_FillRectangle(&render_target->ID2D1RenderTarget_iface, &rect, brush);
1840 ID2D1Brush_Release(brush);
1842 return S_OK;
1845 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_DrawStrikethrough(IDWriteTextRenderer *iface, void *ctx,
1846 float baseline_origin_x, float baseline_origin_y, const DWRITE_STRIKETHROUGH *strikethrough, IUnknown *effect)
1848 FIXME("iface %p, ctx %p, baseline_origin_x %.8e, baseline_origin_y %.8e, strikethrough %p, effect %p stub!\n",
1849 iface, ctx, baseline_origin_x, baseline_origin_y, strikethrough, effect);
1851 return E_NOTIMPL;
1854 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_DrawInlineObject(IDWriteTextRenderer *iface, void *ctx,
1855 float origin_x, float origin_y, IDWriteInlineObject *object, BOOL is_sideways, BOOL is_rtl, IUnknown *effect)
1857 TRACE("iface %p, ctx %p, origin_x %.8e, origin_y %.8e, object %p, is_sideways %#x, is_rtl %#x, effect %p.\n",
1858 iface, ctx, origin_x, origin_y, object, is_sideways, is_rtl, effect);
1860 return IDWriteInlineObject_Draw(object, ctx, iface, origin_x, origin_y, is_sideways, is_rtl, effect);
1863 static const struct IDWriteTextRendererVtbl d2d_text_renderer_vtbl =
1865 d2d_text_renderer_QueryInterface,
1866 d2d_text_renderer_AddRef,
1867 d2d_text_renderer_Release,
1868 d2d_text_renderer_IsPixelSnappingDisabled,
1869 d2d_text_renderer_GetCurrentTransform,
1870 d2d_text_renderer_GetPixelsPerDip,
1871 d2d_text_renderer_DrawGlyphRun,
1872 d2d_text_renderer_DrawUnderline,
1873 d2d_text_renderer_DrawStrikethrough,
1874 d2d_text_renderer_DrawInlineObject,
1877 static inline struct d2d_d3d_render_target *impl_from_ID2D1GdiInteropRenderTarget(ID2D1GdiInteropRenderTarget *iface)
1879 return CONTAINING_RECORD(iface, struct d2d_d3d_render_target, ID2D1GdiInteropRenderTarget_iface);
1882 static HRESULT STDMETHODCALLTYPE d2d_gdi_interop_render_target_QueryInterface(ID2D1GdiInteropRenderTarget *iface,
1883 REFIID iid, void **out)
1885 struct d2d_d3d_render_target *render_target = impl_from_ID2D1GdiInteropRenderTarget(iface);
1887 TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
1889 return IUnknown_QueryInterface(render_target->outer_unknown, iid, out);
1892 static ULONG STDMETHODCALLTYPE d2d_gdi_interop_render_target_AddRef(ID2D1GdiInteropRenderTarget *iface)
1894 struct d2d_d3d_render_target *render_target = impl_from_ID2D1GdiInteropRenderTarget(iface);
1896 TRACE("iface %p.\n", iface);
1898 return IUnknown_AddRef(render_target->outer_unknown);
1901 static ULONG STDMETHODCALLTYPE d2d_gdi_interop_render_target_Release(ID2D1GdiInteropRenderTarget *iface)
1903 struct d2d_d3d_render_target *render_target = impl_from_ID2D1GdiInteropRenderTarget(iface);
1905 TRACE("iface %p.\n", iface);
1907 return IUnknown_Release(render_target->outer_unknown);
1910 static HRESULT d2d_d3d_render_target_get_surface(struct d2d_d3d_render_target *render_target, IDXGISurface1 **surface)
1912 ID3D10Resource *resource;
1913 HRESULT hr;
1915 ID3D10RenderTargetView_GetResource(render_target->view, &resource);
1916 hr = ID3D10Resource_QueryInterface(resource, &IID_IDXGISurface1, (void **)surface);
1917 ID3D10Resource_Release(resource);
1918 if (FAILED(hr))
1920 *surface = NULL;
1921 WARN("Failed to get DXGI surface, %#x.\n", hr);
1922 return hr;
1925 return hr;
1928 static HRESULT STDMETHODCALLTYPE d2d_gdi_interop_render_target_GetDC(ID2D1GdiInteropRenderTarget *iface,
1929 D2D1_DC_INITIALIZE_MODE mode, HDC *dc)
1931 struct d2d_d3d_render_target *render_target = impl_from_ID2D1GdiInteropRenderTarget(iface);
1932 IDXGISurface1 *surface;
1933 HRESULT hr;
1935 TRACE("iface %p, mode %d, dc %p.\n", iface, mode, dc);
1937 if (FAILED(hr = d2d_d3d_render_target_get_surface(render_target, &surface)))
1938 return hr;
1940 hr = IDXGISurface1_GetDC(surface, mode != D2D1_DC_INITIALIZE_MODE_COPY, dc);
1941 IDXGISurface1_Release(surface);
1943 return hr;
1946 static HRESULT STDMETHODCALLTYPE d2d_gdi_interop_render_target_ReleaseDC(ID2D1GdiInteropRenderTarget *iface,
1947 const RECT *update)
1949 struct d2d_d3d_render_target *render_target = impl_from_ID2D1GdiInteropRenderTarget(iface);
1950 IDXGISurface1 *surface;
1951 RECT update_rect;
1952 HRESULT hr;
1954 TRACE("iface %p, update rect %s.\n", iface, wine_dbgstr_rect(update));
1956 if (FAILED(hr = d2d_d3d_render_target_get_surface(render_target, &surface)))
1957 return hr;
1959 if (update)
1960 update_rect = *update;
1961 hr = IDXGISurface1_ReleaseDC(surface, update ? &update_rect : NULL);
1962 IDXGISurface1_Release(surface);
1964 return hr;
1967 static const struct ID2D1GdiInteropRenderTargetVtbl d2d_gdi_interop_render_target_vtbl =
1969 d2d_gdi_interop_render_target_QueryInterface,
1970 d2d_gdi_interop_render_target_AddRef,
1971 d2d_gdi_interop_render_target_Release,
1972 d2d_gdi_interop_render_target_GetDC,
1973 d2d_gdi_interop_render_target_ReleaseDC,
1976 static HRESULT d2d_d3d_render_target_init(struct d2d_d3d_render_target *render_target, ID2D1Factory *factory,
1977 IDXGISurface *surface, IUnknown *outer_unknown, const D2D1_RENDER_TARGET_PROPERTIES *desc)
1979 D3D10_SUBRESOURCE_DATA buffer_data;
1980 D3D10_STATE_BLOCK_MASK state_mask;
1981 DXGI_SURFACE_DESC surface_desc;
1982 IDWriteFactory *dwrite_factory;
1983 D3D10_RASTERIZER_DESC rs_desc;
1984 D3D10_BUFFER_DESC buffer_desc;
1985 D3D10_BLEND_DESC blend_desc;
1986 ID3D10Resource *resource;
1987 unsigned int i, j, k;
1988 HRESULT hr;
1990 static const D3D10_INPUT_ELEMENT_DESC il_desc_outline[] =
1992 {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0},
1993 {"PREV", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 8, D3D10_INPUT_PER_VERTEX_DATA, 0},
1994 {"NEXT", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 16, D3D10_INPUT_PER_VERTEX_DATA, 0},
1996 static const D3D10_INPUT_ELEMENT_DESC il_desc_triangle[] =
1998 {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0},
2000 static const D3D10_INPUT_ELEMENT_DESC il_desc_bezier[] =
2002 {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0},
2003 {"TEXCOORD", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 8, D3D10_INPUT_PER_VERTEX_DATA, 0},
2005 static const DWORD vs_code_outline[] =
2007 #if 0
2008 float3x2 transform_geometry;
2009 float stroke_width;
2010 float4 transform_rtx;
2011 float4 transform_rty;
2013 /* The lines PₚᵣₑᵥP₀ and P₀Pₙₑₓₜ, both offset by ±½w, intersect each other at:
2015 * Pᵢ = P₀ ± w · ½q⃑ᵢ.
2017 * Where:
2019 * q⃑ᵢ = q̂ₚᵣₑᵥ⊥ + tan(½θ) · -q̂ₚᵣₑᵥ
2020 * θ = ∠PₚᵣₑᵥP₀Pₙₑₓₜ
2021 * q⃑ₚᵣₑᵥ = P₀ - Pₚᵣₑᵥ */
2022 float4 main(float2 position : POSITION, float2 prev : PREV, float2 next : NEXT) : SV_POSITION
2024 float2 q_prev, q_next, v_p, q_i;
2025 float l;
2027 q_prev = float2(dot(prev, transform_geometry._11_21), dot(prev, transform_geometry._12_22));
2028 q_prev = normalize(q_prev);
2030 q_next = float2(dot(next, transform_geometry._11_21), dot(next, transform_geometry._12_22));
2031 q_next = normalize(q_next);
2033 /* tan(½θ) = sin(θ) / (1 + cos(θ))
2034 * = (q̂ₚᵣₑᵥ⊥ · q̂ₙₑₓₜ) / (1 + (q̂ₚᵣₑᵥ · q̂ₙₑₓₜ)) */
2035 v_p = float2(-q_prev.y, q_prev.x);
2036 l = -dot(v_p, q_next) / (1.0f + dot(q_prev, q_next));
2037 q_i = l * q_prev + v_p;
2038 position = mul(float3(position, 1.0f), transform_geometry) + stroke_width * 0.5f * q_i;
2040 return float4(mul(float2x3(transform_rtx.xyz * transform_rtx.w, transform_rty.xyz * transform_rty.w),
2041 float3(position.xy, 1.0f)) + float2(-1.0f, 1.0f), 0.0f, 1.0f);
2043 #endif
2044 0x43425844, 0xe88f7af5, 0x480b101b, 0xfd80f66b, 0xd878e0b8, 0x00000001, 0x0000047c, 0x00000003,
2045 0x0000002c, 0x00000098, 0x000000cc, 0x4e475349, 0x00000064, 0x00000003, 0x00000008, 0x00000050,
2046 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000303, 0x00000059, 0x00000000, 0x00000000,
2047 0x00000003, 0x00000001, 0x00000303, 0x0000005e, 0x00000000, 0x00000000, 0x00000003, 0x00000002,
2048 0x00000303, 0x49534f50, 0x4e4f4954, 0x45525000, 0x454e0056, 0xab005458, 0x4e47534f, 0x0000002c,
2049 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f,
2050 0x505f5653, 0x5449534f, 0x004e4f49, 0x52444853, 0x000003a8, 0x00010040, 0x000000ea, 0x04000059,
2051 0x00208e46, 0x00000000, 0x00000004, 0x0300005f, 0x00101032, 0x00000000, 0x0300005f, 0x00101032,
2052 0x00000001, 0x0300005f, 0x00101032, 0x00000002, 0x04000067, 0x001020f2, 0x00000000, 0x00000001,
2053 0x02000068, 0x00000003, 0x0800000f, 0x00100012, 0x00000000, 0x00101046, 0x00000002, 0x00208046,
2054 0x00000000, 0x00000000, 0x0800000f, 0x00100022, 0x00000000, 0x00101046, 0x00000002, 0x00208046,
2055 0x00000000, 0x00000001, 0x0700000f, 0x00100042, 0x00000000, 0x00100046, 0x00000000, 0x00100046,
2056 0x00000000, 0x05000044, 0x00100042, 0x00000000, 0x0010002a, 0x00000000, 0x07000038, 0x00100032,
2057 0x00000000, 0x00100aa6, 0x00000000, 0x00100046, 0x00000000, 0x0800000f, 0x00100012, 0x00000001,
2058 0x00101046, 0x00000001, 0x00208046, 0x00000000, 0x00000000, 0x0800000f, 0x00100022, 0x00000001,
2059 0x00101046, 0x00000001, 0x00208046, 0x00000000, 0x00000001, 0x0700000f, 0x00100042, 0x00000000,
2060 0x00100046, 0x00000001, 0x00100046, 0x00000001, 0x05000044, 0x00100042, 0x00000000, 0x0010002a,
2061 0x00000000, 0x07000038, 0x00100032, 0x00000001, 0x00100aa6, 0x00000000, 0x00100046, 0x00000001,
2062 0x06000036, 0x001000c2, 0x00000001, 0x80100556, 0x00000041, 0x00000001, 0x0700000f, 0x00100042,
2063 0x00000000, 0x00100a26, 0x00000001, 0x00100046, 0x00000000, 0x0700000f, 0x00100012, 0x00000000,
2064 0x00100046, 0x00000001, 0x00100046, 0x00000000, 0x07000000, 0x00100012, 0x00000000, 0x0010000a,
2065 0x00000000, 0x00004001, 0x3f800000, 0x0800000e, 0x00100012, 0x00000000, 0x8010002a, 0x00000041,
2066 0x00000000, 0x0010000a, 0x00000000, 0x09000032, 0x00100032, 0x00000000, 0x00100006, 0x00000000,
2067 0x00100046, 0x00000001, 0x00100f36, 0x00000001, 0x08000038, 0x00100042, 0x00000000, 0x0020803a,
2068 0x00000000, 0x00000001, 0x00004001, 0x3f000000, 0x05000036, 0x00100032, 0x00000001, 0x00101046,
2069 0x00000000, 0x05000036, 0x00100042, 0x00000001, 0x00004001, 0x3f800000, 0x08000010, 0x00100012,
2070 0x00000002, 0x00100246, 0x00000001, 0x00208246, 0x00000000, 0x00000000, 0x08000010, 0x00100022,
2071 0x00000002, 0x00100246, 0x00000001, 0x00208246, 0x00000000, 0x00000001, 0x09000032, 0x00100032,
2072 0x00000000, 0x00100aa6, 0x00000000, 0x00100046, 0x00000000, 0x00100046, 0x00000002, 0x09000038,
2073 0x00100072, 0x00000001, 0x00208ff6, 0x00000000, 0x00000002, 0x00208246, 0x00000000, 0x00000002,
2074 0x05000036, 0x00100042, 0x00000000, 0x00004001, 0x3f800000, 0x07000010, 0x00100012, 0x00000001,
2075 0x00100246, 0x00000001, 0x00100246, 0x00000000, 0x09000038, 0x00100072, 0x00000002, 0x00208ff6,
2076 0x00000000, 0x00000003, 0x00208246, 0x00000000, 0x00000003, 0x07000010, 0x00100022, 0x00000001,
2077 0x00100246, 0x00000002, 0x00100246, 0x00000000, 0x0a000000, 0x00102032, 0x00000000, 0x00100046,
2078 0x00000001, 0x00004002, 0xbf800000, 0x3f800000, 0x00000000, 0x00000000, 0x08000036, 0x001020c2,
2079 0x00000000, 0x00004002, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, 0x0100003e,
2081 static const DWORD vs_code_triangle[] =
2083 /* float3x2 transform;
2085 * float4 main(float4 position : POSITION) : SV_POSITION
2087 * return float4(mul(position.xyw, transform), position.zw);
2088 * } */
2089 0x43425844, 0x0add3194, 0x205f74ec, 0xab527fe7, 0xbe6ad704, 0x00000001, 0x00000128, 0x00000003,
2090 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020,
2091 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000f0f, 0x49534f50, 0x4e4f4954, 0xababab00,
2092 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000001, 0x00000003,
2093 0x00000000, 0x0000000f, 0x505f5653, 0x5449534f, 0x004e4f49, 0x52444853, 0x0000008c, 0x00010040,
2094 0x00000023, 0x04000059, 0x00208e46, 0x00000000, 0x00000002, 0x0300005f, 0x001010f2, 0x00000000,
2095 0x04000067, 0x001020f2, 0x00000000, 0x00000001, 0x08000010, 0x00102012, 0x00000000, 0x00101346,
2096 0x00000000, 0x00208246, 0x00000000, 0x00000000, 0x08000010, 0x00102022, 0x00000000, 0x00101346,
2097 0x00000000, 0x00208246, 0x00000000, 0x00000001, 0x05000036, 0x001020c2, 0x00000000, 0x00101ea6,
2098 0x00000000, 0x0100003e,
2100 static const DWORD vs_code_bezier[] =
2102 #if 0
2103 float3x2 transform;
2105 float4 main(float4 position : POSITION,
2106 inout float3 texcoord : TEXCOORD0) : SV_POSITION
2108 return float4(mul(position.xyw, transform), position.zw);
2110 #endif
2111 0x43425844, 0x5e578adb, 0x093f7e27, 0x50d478af, 0xec3dfa4f, 0x00000001, 0x00000198, 0x00000003,
2112 0x0000002c, 0x00000080, 0x000000d8, 0x4e475349, 0x0000004c, 0x00000002, 0x00000008, 0x00000038,
2113 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000f0f, 0x00000041, 0x00000000, 0x00000000,
2114 0x00000003, 0x00000001, 0x00000707, 0x49534f50, 0x4e4f4954, 0x58455400, 0x524f4f43, 0xabab0044,
2115 0x4e47534f, 0x00000050, 0x00000002, 0x00000008, 0x00000038, 0x00000000, 0x00000001, 0x00000003,
2116 0x00000000, 0x0000000f, 0x00000044, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x00000807,
2117 0x505f5653, 0x5449534f, 0x004e4f49, 0x43584554, 0x44524f4f, 0xababab00, 0x52444853, 0x000000b8,
2118 0x00010040, 0x0000002e, 0x04000059, 0x00208e46, 0x00000000, 0x00000002, 0x0300005f, 0x001010f2,
2119 0x00000000, 0x0300005f, 0x00101072, 0x00000001, 0x04000067, 0x001020f2, 0x00000000, 0x00000001,
2120 0x03000065, 0x00102072, 0x00000001, 0x08000010, 0x00102012, 0x00000000, 0x00101346, 0x00000000,
2121 0x00208246, 0x00000000, 0x00000000, 0x08000010, 0x00102022, 0x00000000, 0x00101346, 0x00000000,
2122 0x00208246, 0x00000000, 0x00000001, 0x05000036, 0x001020c2, 0x00000000, 0x00101ea6, 0x00000000,
2123 0x05000036, 0x00102072, 0x00000001, 0x00101246, 0x00000001, 0x0100003e,
2125 static const DWORD ps_code_triangle_solid[] =
2127 /* float4 color;
2129 * float4 main(float4 position : SV_POSITION) : SV_Target
2131 * return color;
2132 * } */
2133 0x43425844, 0x88eefcfd, 0x93d6fd47, 0x173c242f, 0x0106d07a, 0x00000001, 0x000000dc, 0x00000003,
2134 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020,
2135 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x505f5653, 0x5449534f, 0x004e4f49,
2136 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003,
2137 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x00000040, 0x00000040,
2138 0x00000010, 0x04000059, 0x00208e46, 0x00000000, 0x00000001, 0x03000065, 0x001020f2, 0x00000000,
2139 0x06000036, 0x001020f2, 0x00000000, 0x00208e46, 0x00000000, 0x00000000, 0x0100003e,
2141 static const DWORD ps_code_triangle_solid_bitmap[] =
2143 #if 0
2144 float4 color;
2146 float3x2 transform;
2147 float opacity;
2148 bool ignore_alpha;
2150 SamplerState s;
2151 Texture2D t;
2153 float4 main(float4 position : SV_POSITION) : SV_Target
2155 float2 texcoord;
2156 float4 ret;
2158 texcoord.x = position.x * transform._11 + position.y * transform._21 + transform._31;
2159 texcoord.y = position.x * transform._12 + position.y * transform._22 + transform._32;
2160 ret = t.Sample(s, texcoord) * opacity;
2161 if (ignore_alpha)
2162 ret.a = opacity;
2164 return color * ret.a;
2166 #endif
2167 0x43425844, 0x2260a2ae, 0x81907b3e, 0xcaf27063, 0xccb83ef2, 0x00000001, 0x00000208, 0x00000003,
2168 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020,
2169 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000030f, 0x505f5653, 0x5449534f, 0x004e4f49,
2170 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003,
2171 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x0000016c, 0x00000040,
2172 0x0000005b, 0x04000059, 0x00208e46, 0x00000000, 0x00000004, 0x0300005a, 0x00106000, 0x00000000,
2173 0x04001858, 0x00107000, 0x00000000, 0x00005555, 0x04002064, 0x00101032, 0x00000000, 0x00000001,
2174 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000001, 0x0800000f, 0x00100012, 0x00000000,
2175 0x00101046, 0x00000000, 0x00208046, 0x00000000, 0x00000001, 0x08000000, 0x00100012, 0x00000000,
2176 0x0010000a, 0x00000000, 0x0020802a, 0x00000000, 0x00000001, 0x0800000f, 0x00100042, 0x00000000,
2177 0x00101046, 0x00000000, 0x00208046, 0x00000000, 0x00000002, 0x08000000, 0x00100022, 0x00000000,
2178 0x0010002a, 0x00000000, 0x0020802a, 0x00000000, 0x00000002, 0x09000045, 0x001000f2, 0x00000000,
2179 0x00100046, 0x00000000, 0x00107e46, 0x00000000, 0x00106000, 0x00000000, 0x08000038, 0x00100012,
2180 0x00000000, 0x0010003a, 0x00000000, 0x0020803a, 0x00000000, 0x00000002, 0x0b000037, 0x00100012,
2181 0x00000000, 0x0020800a, 0x00000000, 0x00000003, 0x0020803a, 0x00000000, 0x00000002, 0x0010000a,
2182 0x00000000, 0x08000038, 0x001020f2, 0x00000000, 0x00100006, 0x00000000, 0x00208e46, 0x00000000,
2183 0x00000000, 0x0100003e,
2185 static const DWORD ps_code_triangle_bitmap[] =
2187 #if 0
2188 float3x2 transform;
2189 float opacity;
2190 bool ignore_alpha;
2192 SamplerState s;
2193 Texture2D t;
2195 float4 main(float4 position : SV_POSITION) : SV_Target
2197 float2 texcoord;
2198 float4 ret;
2200 texcoord.x = position.x * transform._11 + position.y * transform._21 + transform._31;
2201 texcoord.y = position.x * transform._12 + position.y * transform._22 + transform._32;
2202 ret = t.Sample(s, texcoord) * opacity;
2203 if (ignore_alpha)
2204 ret.a = opacity;
2206 return ret;
2208 #endif
2209 0x43425844, 0xf5bb1e01, 0xe3386963, 0xcaa095bd, 0xea2887de, 0x00000001, 0x000001fc, 0x00000003,
2210 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020,
2211 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000030f, 0x505f5653, 0x5449534f, 0x004e4f49,
2212 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003,
2213 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x00000160, 0x00000040,
2214 0x00000058, 0x04000059, 0x00208e46, 0x00000000, 0x00000003, 0x0300005a, 0x00106000, 0x00000000,
2215 0x04001858, 0x00107000, 0x00000000, 0x00005555, 0x04002064, 0x00101032, 0x00000000, 0x00000001,
2216 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000001, 0x0800000f, 0x00100012, 0x00000000,
2217 0x00101046, 0x00000000, 0x00208046, 0x00000000, 0x00000000, 0x08000000, 0x00100012, 0x00000000,
2218 0x0010000a, 0x00000000, 0x0020802a, 0x00000000, 0x00000000, 0x0800000f, 0x00100042, 0x00000000,
2219 0x00101046, 0x00000000, 0x00208046, 0x00000000, 0x00000001, 0x08000000, 0x00100022, 0x00000000,
2220 0x0010002a, 0x00000000, 0x0020802a, 0x00000000, 0x00000001, 0x09000045, 0x001000f2, 0x00000000,
2221 0x00100046, 0x00000000, 0x00107e46, 0x00000000, 0x00106000, 0x00000000, 0x08000038, 0x001000f2,
2222 0x00000000, 0x00100e46, 0x00000000, 0x00208ff6, 0x00000000, 0x00000001, 0x0b000037, 0x00102082,
2223 0x00000000, 0x0020800a, 0x00000000, 0x00000002, 0x0020803a, 0x00000000, 0x00000001, 0x0010003a,
2224 0x00000000, 0x05000036, 0x00102072, 0x00000000, 0x00100246, 0x00000000, 0x0100003e,
2226 static const DWORD ps_code_triangle_bitmap_solid[] =
2228 #if 0
2229 float3x2 transform;
2230 float opacity;
2231 bool ignore_alpha;
2233 float4 color;
2235 SamplerState s;
2236 Texture2D t;
2238 float4 main(float4 position : SV_POSITION) : SV_Target
2240 float2 texcoord;
2241 float4 ret;
2243 texcoord.x = position.x * transform._11 + position.y * transform._21 + transform._31;
2244 texcoord.y = position.x * transform._12 + position.y * transform._22 + transform._32;
2245 ret = t.Sample(s, texcoord) * opacity;
2246 if (ignore_alpha)
2247 ret.a = opacity;
2249 return ret * color.a;
2251 #endif
2252 0x43425844, 0x45447736, 0x63a6dd80, 0x1778fc71, 0x1e6d322e, 0x00000001, 0x00000208, 0x00000003,
2253 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020,
2254 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000030f, 0x505f5653, 0x5449534f, 0x004e4f49,
2255 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003,
2256 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x0000016c, 0x00000040,
2257 0x0000005b, 0x04000059, 0x00208e46, 0x00000000, 0x00000004, 0x0300005a, 0x00106000, 0x00000000,
2258 0x04001858, 0x00107000, 0x00000000, 0x00005555, 0x04002064, 0x00101032, 0x00000000, 0x00000001,
2259 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000001, 0x0800000f, 0x00100012, 0x00000000,
2260 0x00101046, 0x00000000, 0x00208046, 0x00000000, 0x00000000, 0x08000000, 0x00100012, 0x00000000,
2261 0x0010000a, 0x00000000, 0x0020802a, 0x00000000, 0x00000000, 0x0800000f, 0x00100042, 0x00000000,
2262 0x00101046, 0x00000000, 0x00208046, 0x00000000, 0x00000001, 0x08000000, 0x00100022, 0x00000000,
2263 0x0010002a, 0x00000000, 0x0020802a, 0x00000000, 0x00000001, 0x09000045, 0x001000f2, 0x00000000,
2264 0x00100046, 0x00000000, 0x00107e46, 0x00000000, 0x00106000, 0x00000000, 0x08000038, 0x001000f2,
2265 0x00000000, 0x00100e46, 0x00000000, 0x00208ff6, 0x00000000, 0x00000001, 0x0b000037, 0x00100082,
2266 0x00000000, 0x0020800a, 0x00000000, 0x00000002, 0x0020803a, 0x00000000, 0x00000001, 0x0010003a,
2267 0x00000000, 0x08000038, 0x001020f2, 0x00000000, 0x00100e46, 0x00000000, 0x00208ff6, 0x00000000,
2268 0x00000003, 0x0100003e,
2270 static const DWORD ps_code_triangle_bitmap_bitmap[] =
2272 #if 0
2273 struct brush
2275 float3x2 transform;
2276 float opacity;
2277 bool ignore_alpha;
2278 } brush0, brush1;
2280 SamplerState s0, s1;
2281 Texture2D t0, t1;
2283 float4 main(float4 position : SV_POSITION) : SV_Target
2285 float2 texcoord;
2286 float opacity;
2287 float4 ret;
2289 texcoord.x = position.x * brush0.transform._11 + position.y * brush0.transform._21 + brush0.transform._31;
2290 texcoord.y = position.x * brush0.transform._12 + position.y * brush0.transform._22 + brush0.transform._32;
2291 ret = t0.Sample(s0, texcoord) * brush0.opacity;
2292 if (brush0.ignore_alpha)
2293 ret.a = brush0.opacity;
2295 texcoord.x = position.x * brush1.transform._11 + position.y * brush1.transform._21 + brush1.transform._31;
2296 texcoord.y = position.x * brush1.transform._12 + position.y * brush1.transform._22 + brush1.transform._32;
2297 opacity = t1.Sample(s1, texcoord).a * brush1.opacity;
2298 if (brush1.ignore_alpha)
2299 opacity = brush1.opacity;
2301 return ret * opacity;
2303 #endif
2304 0x43425844, 0x8eee6bfc, 0x57b72708, 0xa0f7c086, 0x867c11ec, 0x00000001, 0x00000310, 0x00000003,
2305 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020,
2306 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000030f, 0x505f5653, 0x5449534f, 0x004e4f49,
2307 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003,
2308 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x00000274, 0x00000040,
2309 0x0000009d, 0x04000059, 0x00208e46, 0x00000000, 0x00000006, 0x0300005a, 0x00106000, 0x00000000,
2310 0x0300005a, 0x00106000, 0x00000001, 0x04001858, 0x00107000, 0x00000000, 0x00005555, 0x04001858,
2311 0x00107000, 0x00000001, 0x00005555, 0x04002064, 0x00101032, 0x00000000, 0x00000001, 0x03000065,
2312 0x001020f2, 0x00000000, 0x02000068, 0x00000002, 0x0800000f, 0x00100012, 0x00000000, 0x00101046,
2313 0x00000000, 0x00208046, 0x00000000, 0x00000003, 0x08000000, 0x00100012, 0x00000000, 0x0010000a,
2314 0x00000000, 0x0020802a, 0x00000000, 0x00000003, 0x0800000f, 0x00100042, 0x00000000, 0x00101046,
2315 0x00000000, 0x00208046, 0x00000000, 0x00000004, 0x08000000, 0x00100022, 0x00000000, 0x0010002a,
2316 0x00000000, 0x0020802a, 0x00000000, 0x00000004, 0x09000045, 0x001000f2, 0x00000000, 0x00100046,
2317 0x00000000, 0x00107e46, 0x00000001, 0x00106000, 0x00000001, 0x08000038, 0x00100012, 0x00000000,
2318 0x0010003a, 0x00000000, 0x0020803a, 0x00000000, 0x00000004, 0x0b000037, 0x00100012, 0x00000000,
2319 0x0020800a, 0x00000000, 0x00000005, 0x0020803a, 0x00000000, 0x00000004, 0x0010000a, 0x00000000,
2320 0x0800000f, 0x00100022, 0x00000000, 0x00101046, 0x00000000, 0x00208046, 0x00000000, 0x00000000,
2321 0x08000000, 0x00100012, 0x00000001, 0x0010001a, 0x00000000, 0x0020802a, 0x00000000, 0x00000000,
2322 0x0800000f, 0x00100022, 0x00000000, 0x00101046, 0x00000000, 0x00208046, 0x00000000, 0x00000001,
2323 0x08000000, 0x00100022, 0x00000001, 0x0010001a, 0x00000000, 0x0020802a, 0x00000000, 0x00000001,
2324 0x09000045, 0x001000f2, 0x00000001, 0x00100046, 0x00000001, 0x00107e46, 0x00000000, 0x00106000,
2325 0x00000000, 0x08000038, 0x001000f2, 0x00000001, 0x00100e46, 0x00000001, 0x00208ff6, 0x00000000,
2326 0x00000001, 0x0b000037, 0x00100082, 0x00000001, 0x0020800a, 0x00000000, 0x00000002, 0x0020803a,
2327 0x00000000, 0x00000001, 0x0010003a, 0x00000001, 0x07000038, 0x001020f2, 0x00000000, 0x00100006,
2328 0x00000000, 0x00100e46, 0x00000001, 0x0100003e,
2330 /* The basic idea here is to evaluate the implicit form of the curve in
2331 * texture space. "t.z" determines which side of the curve is shaded. */
2332 static const DWORD ps_code_bezier_solid[] =
2334 #if 0
2335 float4 color;
2337 float4 main(float4 position : SV_POSITION, float3 t : TEXCOORD0) : SV_Target
2339 clip((t.x * t.x - t.y) * t.z);
2340 return color;
2342 #endif
2343 0x43425844, 0x66075f9e, 0x2ffe405b, 0xb551ee63, 0xa0d9f457, 0x00000001, 0x00000180, 0x00000003,
2344 0x0000002c, 0x00000084, 0x000000b8, 0x4e475349, 0x00000050, 0x00000002, 0x00000008, 0x00000038,
2345 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x00000044, 0x00000000, 0x00000000,
2346 0x00000003, 0x00000001, 0x00000707, 0x505f5653, 0x5449534f, 0x004e4f49, 0x43584554, 0x44524f4f,
2347 0xababab00, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000,
2348 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x000000c0,
2349 0x00000040, 0x00000030, 0x04000059, 0x00208e46, 0x00000000, 0x00000001, 0x03001062, 0x00101072,
2350 0x00000001, 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000001, 0x0a000032, 0x00100012,
2351 0x00000000, 0x0010100a, 0x00000001, 0x0010100a, 0x00000001, 0x8010101a, 0x00000041, 0x00000001,
2352 0x07000038, 0x00100012, 0x00000000, 0x0010000a, 0x00000000, 0x0010102a, 0x00000001, 0x07000031,
2353 0x00100012, 0x00000000, 0x0010000a, 0x00000000, 0x00004001, 0x00000000, 0x0304000d, 0x0010000a,
2354 0x00000000, 0x06000036, 0x001020f2, 0x00000000, 0x00208e46, 0x00000000, 0x00000000, 0x0100003e,
2356 static const struct brush_shader
2358 const void *byte_code;
2359 size_t byte_code_size;
2360 enum d2d_shape_type shape_type;
2361 enum d2d_brush_type brush_type;
2362 enum d2d_brush_type opacity_brush_type;
2364 brush_shaders[] =
2366 {ps_code_triangle_solid, sizeof(ps_code_triangle_solid),
2367 D2D_SHAPE_TYPE_TRIANGLE, D2D_BRUSH_TYPE_SOLID, D2D_BRUSH_TYPE_COUNT},
2368 {ps_code_triangle_solid_bitmap, sizeof(ps_code_triangle_solid_bitmap),
2369 D2D_SHAPE_TYPE_TRIANGLE, D2D_BRUSH_TYPE_SOLID, D2D_BRUSH_TYPE_BITMAP},
2370 {ps_code_triangle_bitmap, sizeof(ps_code_triangle_bitmap),
2371 D2D_SHAPE_TYPE_TRIANGLE, D2D_BRUSH_TYPE_BITMAP, D2D_BRUSH_TYPE_COUNT},
2372 {ps_code_triangle_bitmap_solid, sizeof(ps_code_triangle_bitmap_solid),
2373 D2D_SHAPE_TYPE_TRIANGLE, D2D_BRUSH_TYPE_BITMAP, D2D_BRUSH_TYPE_SOLID},
2374 {ps_code_triangle_bitmap_bitmap, sizeof(ps_code_triangle_bitmap_bitmap),
2375 D2D_SHAPE_TYPE_TRIANGLE, D2D_BRUSH_TYPE_BITMAP, D2D_BRUSH_TYPE_BITMAP},
2376 {ps_code_bezier_solid, sizeof(ps_code_bezier_solid),
2377 D2D_SHAPE_TYPE_BEZIER, D2D_BRUSH_TYPE_SOLID, D2D_BRUSH_TYPE_COUNT},
2379 static const struct
2381 float x, y;
2383 quad[] =
2385 {-1.0f, 1.0f},
2386 {-1.0f, -1.0f},
2387 { 1.0f, 1.0f},
2388 { 1.0f, -1.0f},
2390 static const UINT16 indices[] = {0, 1, 2, 2, 1, 3};
2391 static const D2D1_MATRIX_3X2_F identity =
2393 1.0f, 0.0f,
2394 0.0f, 1.0f,
2395 0.0f, 0.0f,
2397 float dpi_x, dpi_y;
2399 dpi_x = desc->dpiX;
2400 dpi_y = desc->dpiY;
2402 if (dpi_x == 0.0f && dpi_y == 0.0f)
2404 dpi_x = 96.0f;
2405 dpi_y = 96.0f;
2407 else if (dpi_x <= 0.0f || dpi_y <= 0.0f)
2408 return E_INVALIDARG;
2410 if (desc->type != D2D1_RENDER_TARGET_TYPE_DEFAULT && desc->type != D2D1_RENDER_TARGET_TYPE_HARDWARE)
2411 WARN("Ignoring render target type %#x.\n", desc->type);
2412 if (desc->usage != D2D1_RENDER_TARGET_USAGE_NONE)
2413 FIXME("Ignoring render target usage %#x.\n", desc->usage);
2414 if (desc->minLevel != D2D1_FEATURE_LEVEL_DEFAULT)
2415 WARN("Ignoring feature level %#x.\n", desc->minLevel);
2417 render_target->ID2D1RenderTarget_iface.lpVtbl = &d2d_d3d_render_target_vtbl;
2418 render_target->ID2D1GdiInteropRenderTarget_iface.lpVtbl = &d2d_gdi_interop_render_target_vtbl;
2419 render_target->IDWriteTextRenderer_iface.lpVtbl = &d2d_text_renderer_vtbl;
2420 render_target->refcount = 1;
2421 render_target->factory = factory;
2422 ID2D1Factory_AddRef(render_target->factory);
2424 render_target->outer_unknown = outer_unknown ? outer_unknown :
2425 (IUnknown *)&render_target->ID2D1RenderTarget_iface;
2427 if (FAILED(hr = IDXGISurface_GetDevice(surface, &IID_ID3D10Device, (void **)&render_target->device)))
2429 WARN("Failed to get device interface, hr %#x.\n", hr);
2430 ID2D1Factory_Release(render_target->factory);
2431 return hr;
2434 if (FAILED(hr = IDXGISurface_QueryInterface(surface, &IID_ID3D10Resource, (void **)&resource)))
2436 WARN("Failed to get ID3D10Resource interface, hr %#x.\n", hr);
2437 goto err;
2440 hr = ID3D10Device_CreateRenderTargetView(render_target->device, resource, NULL, &render_target->view);
2441 ID3D10Resource_Release(resource);
2442 if (FAILED(hr))
2444 WARN("Failed to create rendertarget view, hr %#x.\n", hr);
2445 goto err;
2448 if (FAILED(hr = D3D10StateBlockMaskEnableAll(&state_mask)))
2450 WARN("Failed to create stateblock mask, hr %#x.\n", hr);
2451 goto err;
2454 if (FAILED(hr = D3D10CreateStateBlock(render_target->device, &state_mask, &render_target->stateblock)))
2456 WARN("Failed to create stateblock, hr %#x.\n", hr);
2457 goto err;
2460 if (FAILED(hr = ID3D10Device_CreateInputLayout(render_target->device, il_desc_outline,
2461 sizeof(il_desc_outline) / sizeof(*il_desc_outline), vs_code_outline, sizeof(vs_code_outline),
2462 &render_target->shape_resources[D2D_SHAPE_TYPE_OUTLINE].il)))
2464 WARN("Failed to create outline input layout, hr %#x.\n", hr);
2465 goto err;
2468 if (FAILED(hr = ID3D10Device_CreateInputLayout(render_target->device, il_desc_triangle,
2469 sizeof(il_desc_triangle) / sizeof(*il_desc_triangle), vs_code_triangle, sizeof(vs_code_triangle),
2470 &render_target->shape_resources[D2D_SHAPE_TYPE_TRIANGLE].il)))
2472 WARN("Failed to create triangle input layout, hr %#x.\n", hr);
2473 goto err;
2476 if (FAILED(hr = ID3D10Device_CreateInputLayout(render_target->device, il_desc_bezier,
2477 sizeof(il_desc_bezier) / sizeof(*il_desc_bezier), vs_code_bezier, sizeof(vs_code_bezier),
2478 &render_target->shape_resources[D2D_SHAPE_TYPE_BEZIER].il)))
2480 WARN("Failed to create bezier input layout, hr %#x.\n", hr);
2481 goto err;
2484 if (FAILED(hr = ID3D10Device_CreateVertexShader(render_target->device, vs_code_outline,
2485 sizeof(vs_code_outline), &render_target->shape_resources[D2D_SHAPE_TYPE_OUTLINE].vs)))
2487 WARN("Failed to create outline vertex shader, hr %#x.\n", hr);
2488 goto err;
2491 if (FAILED(hr = ID3D10Device_CreateVertexShader(render_target->device, vs_code_triangle,
2492 sizeof(vs_code_triangle), &render_target->shape_resources[D2D_SHAPE_TYPE_TRIANGLE].vs)))
2494 WARN("Failed to create triangle vertex shader, hr %#x.\n", hr);
2495 goto err;
2498 if (FAILED(hr = ID3D10Device_CreateVertexShader(render_target->device, vs_code_bezier,
2499 sizeof(vs_code_bezier), &render_target->shape_resources[D2D_SHAPE_TYPE_BEZIER].vs)))
2501 WARN("Failed to create bezier vertex shader, hr %#x.\n", hr);
2502 goto err;
2505 for (i = 0; i < sizeof(brush_shaders) / sizeof(*brush_shaders); ++i)
2507 const struct brush_shader *bs = &brush_shaders[i];
2508 if (FAILED(hr = ID3D10Device_CreatePixelShader(render_target->device, bs->byte_code, bs->byte_code_size,
2509 &render_target->shape_resources[bs->shape_type].ps[bs->brush_type][bs->opacity_brush_type])))
2511 WARN("Failed to create pixel shader for shape type %#x and brush types %#x/%#x.\n",
2512 bs->shape_type, bs->brush_type, bs->opacity_brush_type);
2513 goto err;
2517 for (j = 0; j < D2D_BRUSH_TYPE_COUNT; ++j)
2519 for (k = 0; k < D2D_BRUSH_TYPE_COUNT + 1; ++k)
2521 struct d2d_shape_resources *outline = &render_target->shape_resources[D2D_SHAPE_TYPE_OUTLINE];
2522 struct d2d_shape_resources *triangle = &render_target->shape_resources[D2D_SHAPE_TYPE_TRIANGLE];
2524 if (triangle->ps[j][k])
2525 ID3D10PixelShader_AddRef(outline->ps[j][k] = triangle->ps[j][k]);
2529 buffer_desc.ByteWidth = sizeof(indices);
2530 buffer_desc.Usage = D3D10_USAGE_DEFAULT;
2531 buffer_desc.BindFlags = D3D10_BIND_INDEX_BUFFER;
2532 buffer_desc.CPUAccessFlags = 0;
2533 buffer_desc.MiscFlags = 0;
2535 buffer_data.pSysMem = indices;
2536 buffer_data.SysMemPitch = 0;
2537 buffer_data.SysMemSlicePitch = 0;
2539 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device,
2540 &buffer_desc, &buffer_data, &render_target->ib)))
2542 WARN("Failed to create clear index buffer, hr %#x.\n", hr);
2543 goto err;
2546 buffer_desc.ByteWidth = sizeof(quad);
2547 buffer_desc.BindFlags = D3D10_BIND_VERTEX_BUFFER;
2548 buffer_data.pSysMem = quad;
2550 render_target->vb_stride = sizeof(*quad);
2551 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device,
2552 &buffer_desc, &buffer_data, &render_target->vb)))
2554 WARN("Failed to create clear vertex buffer, hr %#x.\n", hr);
2555 goto err;
2558 rs_desc.FillMode = D3D10_FILL_SOLID;
2559 rs_desc.CullMode = D3D10_CULL_NONE;
2560 rs_desc.FrontCounterClockwise = FALSE;
2561 rs_desc.DepthBias = 0;
2562 rs_desc.DepthBiasClamp = 0.0f;
2563 rs_desc.SlopeScaledDepthBias = 0.0f;
2564 rs_desc.DepthClipEnable = TRUE;
2565 rs_desc.ScissorEnable = TRUE;
2566 rs_desc.MultisampleEnable = FALSE;
2567 rs_desc.AntialiasedLineEnable = FALSE;
2568 if (FAILED(hr = ID3D10Device_CreateRasterizerState(render_target->device, &rs_desc, &render_target->rs)))
2570 WARN("Failed to create clear rasterizer state, hr %#x.\n", hr);
2571 goto err;
2574 memset(&blend_desc, 0, sizeof(blend_desc));
2575 blend_desc.BlendEnable[0] = TRUE;
2576 blend_desc.SrcBlend = D3D10_BLEND_ONE;
2577 blend_desc.DestBlend = D3D10_BLEND_INV_SRC_ALPHA;
2578 blend_desc.BlendOp = D3D10_BLEND_OP_ADD;
2579 if (desc->pixelFormat.alphaMode == D2D1_ALPHA_MODE_IGNORE)
2581 blend_desc.SrcBlendAlpha = D3D10_BLEND_ZERO;
2582 blend_desc.DestBlendAlpha = D3D10_BLEND_ONE;
2584 else
2586 blend_desc.SrcBlendAlpha = D3D10_BLEND_ONE;
2587 blend_desc.DestBlendAlpha = D3D10_BLEND_INV_SRC_ALPHA;
2589 blend_desc.BlendOpAlpha = D3D10_BLEND_OP_ADD;
2590 blend_desc.RenderTargetWriteMask[0] = D3D10_COLOR_WRITE_ENABLE_ALL;
2591 if (FAILED(hr = ID3D10Device_CreateBlendState(render_target->device, &blend_desc, &render_target->bs)))
2593 WARN("Failed to create blend state, hr %#x.\n", hr);
2594 goto err;
2597 if (FAILED(hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED,
2598 &IID_IDWriteFactory, (IUnknown **)&dwrite_factory)))
2600 ERR("Failed to create dwrite factory, hr %#x.\n", hr);
2601 goto err;
2604 hr = IDWriteFactory_CreateRenderingParams(dwrite_factory, &render_target->default_text_rendering_params);
2605 IDWriteFactory_Release(dwrite_factory);
2606 if (FAILED(hr))
2608 ERR("Failed to create default text rendering parameters, hr %#x.\n", hr);
2609 goto err;
2612 if (FAILED(hr = IDXGISurface_GetDesc(surface, &surface_desc)))
2614 WARN("Failed to get surface desc, hr %#x.\n", hr);
2615 goto err;
2618 render_target->desc.pixelFormat = desc->pixelFormat;
2619 render_target->pixel_size.width = surface_desc.Width;
2620 render_target->pixel_size.height = surface_desc.Height;
2621 render_target->drawing_state.transform = identity;
2623 if (!d2d_clip_stack_init(&render_target->clip_stack))
2625 WARN("Failed to initialize clip stack.\n");
2626 hr = E_FAIL;
2627 goto err;
2630 render_target->desc.dpiX = dpi_x;
2631 render_target->desc.dpiY = dpi_y;
2633 return S_OK;
2635 err:
2636 if (render_target->default_text_rendering_params)
2637 IDWriteRenderingParams_Release(render_target->default_text_rendering_params);
2638 if (render_target->bs)
2639 ID3D10BlendState_Release(render_target->bs);
2640 if (render_target->rs)
2641 ID3D10RasterizerState_Release(render_target->rs);
2642 if (render_target->vb)
2643 ID3D10Buffer_Release(render_target->vb);
2644 if (render_target->ib)
2645 ID3D10Buffer_Release(render_target->ib);
2646 for (i = 0; i < D2D_SHAPE_TYPE_COUNT; ++i)
2648 for (j = 0; j < D2D_BRUSH_TYPE_COUNT; ++j)
2650 for (k = 0; k < D2D_BRUSH_TYPE_COUNT + 1; ++k)
2652 if (render_target->shape_resources[i].ps[j][k])
2653 ID3D10PixelShader_Release(render_target->shape_resources[i].ps[j][k]);
2656 if (render_target->shape_resources[i].vs)
2657 ID3D10VertexShader_Release(render_target->shape_resources[i].vs);
2658 if (render_target->shape_resources[i].il)
2659 ID3D10InputLayout_Release(render_target->shape_resources[i].il);
2661 if (render_target->stateblock)
2662 render_target->stateblock->lpVtbl->Release(render_target->stateblock);
2663 if (render_target->view)
2664 ID3D10RenderTargetView_Release(render_target->view);
2665 if (render_target->device)
2666 ID3D10Device_Release(render_target->device);
2667 ID2D1Factory_Release(render_target->factory);
2668 return hr;
2671 HRESULT d2d_d3d_create_render_target(ID2D1Factory *factory, IDXGISurface *surface, IUnknown *outer_unknown,
2672 const D2D1_RENDER_TARGET_PROPERTIES *desc, ID2D1RenderTarget **render_target)
2674 struct d2d_d3d_render_target *object;
2675 HRESULT hr;
2677 if (!(object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object))))
2678 return E_OUTOFMEMORY;
2680 if (FAILED(hr = d2d_d3d_render_target_init(object, factory, surface, outer_unknown, desc)))
2682 WARN("Failed to initialize render target, hr %#x.\n", hr);
2683 HeapFree(GetProcessHeap(), 0, object);
2684 return hr;
2687 TRACE("Created render target %p.\n", object);
2688 *render_target = &object->ID2D1RenderTarget_iface;
2690 return S_OK;
2693 HRESULT d2d_d3d_render_target_create_rtv(ID2D1RenderTarget *iface, IDXGISurface1 *surface)
2695 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
2696 DXGI_SURFACE_DESC surface_desc;
2697 ID3D10RenderTargetView *view;
2698 ID3D10Resource *resource;
2699 HRESULT hr;
2701 if (!surface)
2703 ID3D10RenderTargetView_Release(render_target->view);
2704 render_target->view = NULL;
2705 return S_OK;
2708 if (FAILED(hr = IDXGISurface1_GetDesc(surface, &surface_desc)))
2710 WARN("Failed to get surface desc, hr %#x.\n", hr);
2711 return hr;
2714 if (FAILED(hr = IDXGISurface1_QueryInterface(surface, &IID_ID3D10Resource, (void **)&resource)))
2716 WARN("Failed to get ID3D10Resource interface, hr %#x.\n", hr);
2717 return hr;
2720 hr = ID3D10Device_CreateRenderTargetView(render_target->device, resource, NULL, &view);
2721 ID3D10Resource_Release(resource);
2722 if (FAILED(hr))
2724 WARN("Failed to create rendertarget view, hr %#x.\n", hr);
2725 return hr;
2728 render_target->pixel_size.width = surface_desc.Width;
2729 render_target->pixel_size.height = surface_desc.Height;
2730 if (render_target->view)
2731 ID3D10RenderTargetView_Release(render_target->view);
2732 render_target->view = view;
2734 return S_OK;