d2d1: Add a pixel shader for triangle/solid/bitmap draws.
[wine.git] / dlls / d2d1 / render_target.c
blob9142bf14c0e560cf1aaaf54823dc11b54662deec
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"
23 #include "wincodec.h"
25 WINE_DEFAULT_DEBUG_CHANNEL(d2d);
27 #define INITIAL_CLIP_STACK_SIZE 4
29 struct d2d_draw_text_layout_ctx
31 ID2D1Brush *brush;
32 D2D1_DRAW_TEXT_OPTIONS options;
35 static void d2d_point_set(D2D1_POINT_2F *dst, float x, float y)
37 dst->x = x;
38 dst->y = y;
41 static void d2d_point_transform(D2D1_POINT_2F *dst, const D2D1_MATRIX_3X2_F *matrix, float x, float y)
43 dst->x = x * matrix->_11 + y * matrix->_21 + matrix->_31;
44 dst->y = x * matrix->_12 + y * matrix->_22 + matrix->_32;
47 static void d2d_rect_expand(D2D1_RECT_F *dst, const D2D1_POINT_2F *point)
49 if (point->x < dst->left)
50 dst->left = point->x;
51 if (point->y < dst->top)
52 dst->top = point->y;
53 if (point->x > dst->right)
54 dst->right = point->x;
55 if (point->y > dst->bottom)
56 dst->bottom = point->y;
59 static void d2d_rect_intersect(D2D1_RECT_F *dst, const D2D1_RECT_F *src)
61 if (src->left > dst->left)
62 dst->left = src->left;
63 if (src->top > dst->top)
64 dst->top = src->top;
65 if (src->right < dst->right)
66 dst->right = src->right;
67 if (src->bottom < dst->bottom)
68 dst->bottom = src->bottom;
71 static void d2d_rect_set(D2D1_RECT_F *dst, float left, float top, float right, float bottom)
73 dst->left = left;
74 dst->top = top;
75 dst->right = right;
76 dst->bottom = bottom;
79 static BOOL d2d_clip_stack_init(struct d2d_clip_stack *stack)
81 if (!(stack->stack = HeapAlloc(GetProcessHeap(), 0, INITIAL_CLIP_STACK_SIZE * sizeof(*stack->stack))))
82 return FALSE;
84 stack->size = INITIAL_CLIP_STACK_SIZE;
85 stack->count = 0;
87 return TRUE;
90 static void d2d_clip_stack_cleanup(struct d2d_clip_stack *stack)
92 HeapFree(GetProcessHeap(), 0, stack->stack);
95 static BOOL d2d_clip_stack_push(struct d2d_clip_stack *stack, const D2D1_RECT_F *rect)
97 D2D1_RECT_F r;
99 if (stack->count == stack->size)
101 D2D1_RECT_F *new_stack;
102 unsigned int new_size;
104 if (stack->size > UINT_MAX / 2)
105 return FALSE;
107 new_size = stack->size * 2;
108 if (!(new_stack = HeapReAlloc(GetProcessHeap(), 0, stack->stack, new_size * sizeof(*stack->stack))))
109 return FALSE;
111 stack->stack = new_stack;
112 stack->size = new_size;
115 r = *rect;
116 if (stack->count)
117 d2d_rect_intersect(&r, &stack->stack[stack->count - 1]);
118 stack->stack[stack->count++] = r;
120 return TRUE;
123 static void d2d_clip_stack_pop(struct d2d_clip_stack *stack)
125 if (!stack->count)
126 return;
127 --stack->count;
130 static void d2d_rt_draw(struct d2d_d3d_render_target *render_target, enum d2d_shape_type shape_type,
131 ID3D10Buffer *ib, unsigned int index_count, ID3D10Buffer *vb, unsigned int vb_stride,
132 ID3D10Buffer *vs_cb, ID3D10Buffer *ps_cb, struct d2d_brush *brush, struct d2d_brush *opacity_brush)
134 struct d2d_shape_resources *shape_resources = &render_target->shape_resources[shape_type];
135 ID3D10Device *device = render_target->device;
136 D3D10_RECT scissor_rect;
137 unsigned int offset;
138 D3D10_VIEWPORT vp;
139 HRESULT hr;
141 vp.TopLeftX = 0;
142 vp.TopLeftY = 0;
143 vp.Width = render_target->pixel_size.width;
144 vp.Height = render_target->pixel_size.height;
145 vp.MinDepth = 0.0f;
146 vp.MaxDepth = 1.0f;
148 if (FAILED(hr = render_target->stateblock->lpVtbl->Capture(render_target->stateblock)))
150 WARN("Failed to capture stateblock, hr %#x.\n", hr);
151 return;
154 ID3D10Device_ClearState(device);
156 ID3D10Device_IASetInputLayout(device, shape_resources->il);
157 ID3D10Device_IASetPrimitiveTopology(device, D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
158 ID3D10Device_IASetIndexBuffer(device, ib, DXGI_FORMAT_R16_UINT, 0);
159 offset = 0;
160 ID3D10Device_IASetVertexBuffers(device, 0, 1, &vb, &vb_stride, &offset);
161 ID3D10Device_VSSetConstantBuffers(device, 0, 1, &vs_cb);
162 ID3D10Device_VSSetShader(device, shape_resources->vs);
163 ID3D10Device_PSSetConstantBuffers(device, 0, 1, &ps_cb);
164 ID3D10Device_RSSetViewports(device, 1, &vp);
165 if (render_target->clip_stack.count)
167 const D2D1_RECT_F *clip_rect;
169 clip_rect = &render_target->clip_stack.stack[render_target->clip_stack.count - 1];
170 scissor_rect.left = clip_rect->left + 0.5f;
171 scissor_rect.top = clip_rect->top + 0.5f;
172 scissor_rect.right = clip_rect->right + 0.5f;
173 scissor_rect.bottom = clip_rect->bottom + 0.5f;
175 else
177 scissor_rect.left = 0.0f;
178 scissor_rect.top = 0.0f;
179 scissor_rect.right = render_target->pixel_size.width;
180 scissor_rect.bottom = render_target->pixel_size.height;
182 ID3D10Device_RSSetScissorRects(device, 1, &scissor_rect);
183 ID3D10Device_RSSetState(device, render_target->rs);
184 ID3D10Device_OMSetRenderTargets(device, 1, &render_target->view, NULL);
185 if (brush)
186 d2d_brush_bind_resources(brush, opacity_brush, render_target, shape_type);
187 else
188 ID3D10Device_PSSetShader(device, shape_resources->ps[D2D_BRUSH_TYPE_SOLID][D2D_BRUSH_TYPE_COUNT]);
190 if (ib)
191 ID3D10Device_DrawIndexed(device, index_count, 0, 0);
192 else
193 ID3D10Device_Draw(device, index_count, 0);
195 if (FAILED(hr = render_target->stateblock->lpVtbl->Apply(render_target->stateblock)))
196 WARN("Failed to apply stateblock, hr %#x.\n", hr);
199 static inline struct d2d_d3d_render_target *impl_from_ID2D1RenderTarget(ID2D1RenderTarget *iface)
201 return CONTAINING_RECORD(iface, struct d2d_d3d_render_target, ID2D1RenderTarget_iface);
204 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_QueryInterface(ID2D1RenderTarget *iface, REFIID iid, void **out)
206 TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
208 if (IsEqualGUID(iid, &IID_ID2D1RenderTarget)
209 || IsEqualGUID(iid, &IID_ID2D1Resource)
210 || IsEqualGUID(iid, &IID_IUnknown))
212 ID2D1RenderTarget_AddRef(iface);
213 *out = iface;
214 return S_OK;
217 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
219 *out = NULL;
220 return E_NOINTERFACE;
223 static ULONG STDMETHODCALLTYPE d2d_d3d_render_target_AddRef(ID2D1RenderTarget *iface)
225 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
226 ULONG refcount = InterlockedIncrement(&render_target->refcount);
228 TRACE("%p increasing refcount to %u.\n", iface, refcount);
230 return refcount;
233 static ULONG STDMETHODCALLTYPE d2d_d3d_render_target_Release(ID2D1RenderTarget *iface)
235 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
236 ULONG refcount = InterlockedDecrement(&render_target->refcount);
238 TRACE("%p decreasing refcount to %u.\n", iface, refcount);
240 if (!refcount)
242 unsigned int i, j, k;
244 d2d_clip_stack_cleanup(&render_target->clip_stack);
245 if (render_target->text_rendering_params)
246 IDWriteRenderingParams_Release(render_target->text_rendering_params);
247 ID3D10BlendState_Release(render_target->bs);
248 ID3D10RasterizerState_Release(render_target->rs);
249 ID3D10Buffer_Release(render_target->vb);
250 ID3D10Buffer_Release(render_target->ib);
251 for (i = 0; i < D2D_SHAPE_TYPE_COUNT; ++i)
253 for (j = 0; j < D2D_BRUSH_TYPE_COUNT; ++j)
255 for (k = 0; k < D2D_BRUSH_TYPE_COUNT + 1; ++k)
257 if (render_target->shape_resources[i].ps[j][k])
258 ID3D10PixelShader_Release(render_target->shape_resources[i].ps[j][k]);
261 ID3D10VertexShader_Release(render_target->shape_resources[i].vs);
262 ID3D10InputLayout_Release(render_target->shape_resources[i].il);
264 render_target->stateblock->lpVtbl->Release(render_target->stateblock);
265 ID3D10RenderTargetView_Release(render_target->view);
266 ID3D10Device_Release(render_target->device);
267 ID2D1Factory_Release(render_target->factory);
268 HeapFree(GetProcessHeap(), 0, render_target);
271 return refcount;
274 static void STDMETHODCALLTYPE d2d_d3d_render_target_GetFactory(ID2D1RenderTarget *iface, ID2D1Factory **factory)
276 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
278 TRACE("iface %p, factory %p.\n", iface, factory);
280 *factory = render_target->factory;
281 ID2D1Factory_AddRef(*factory);
284 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateBitmap(ID2D1RenderTarget *iface,
285 D2D1_SIZE_U size, const void *src_data, UINT32 pitch, const D2D1_BITMAP_PROPERTIES *desc, ID2D1Bitmap **bitmap)
287 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
288 struct d2d_bitmap *object;
289 HRESULT hr;
291 TRACE("iface %p, size {%u, %u}, src_data %p, pitch %u, desc %p, bitmap %p.\n",
292 iface, size.width, size.height, src_data, pitch, desc, bitmap);
294 if (!(object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object))))
295 return E_OUTOFMEMORY;
297 if (FAILED(hr = d2d_bitmap_init_memory(object, render_target, size, src_data, pitch, desc)))
299 WARN("Failed to initialize bitmap, hr %#x.\n", hr);
300 HeapFree(GetProcessHeap(), 0, object);
301 return hr;
304 TRACE("Created bitmap %p.\n", object);
305 *bitmap = &object->ID2D1Bitmap_iface;
307 return S_OK;
310 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateBitmapFromWicBitmap(ID2D1RenderTarget *iface,
311 IWICBitmapSource *bitmap_source, const D2D1_BITMAP_PROPERTIES *desc, ID2D1Bitmap **bitmap)
313 const D2D1_PIXEL_FORMAT *d2d_format;
314 D2D1_BITMAP_PROPERTIES bitmap_desc;
315 WICPixelFormatGUID wic_format;
316 unsigned int bpp, data_size;
317 D2D1_SIZE_U size;
318 unsigned int i;
319 WICRect rect;
320 UINT32 pitch;
321 HRESULT hr;
322 void *data;
324 static const struct
326 const WICPixelFormatGUID *wic;
327 D2D1_PIXEL_FORMAT d2d;
329 format_lookup[] =
331 {&GUID_WICPixelFormat32bppPBGRA, {DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_PREMULTIPLIED}},
332 {&GUID_WICPixelFormat32bppBGR, {DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_IGNORE}},
335 TRACE("iface %p, bitmap_source %p, desc %p, bitmap %p.\n",
336 iface, bitmap_source, desc, bitmap);
338 if (FAILED(hr = IWICBitmapSource_GetSize(bitmap_source, &size.width, &size.height)))
340 WARN("Failed to get bitmap size, hr %#x.\n", hr);
341 return hr;
344 if (!desc)
346 bitmap_desc.pixelFormat.format = DXGI_FORMAT_UNKNOWN;
347 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_UNKNOWN;
348 bitmap_desc.dpiX = 0.0f;
349 bitmap_desc.dpiY = 0.0f;
351 else
353 bitmap_desc = *desc;
356 if (FAILED(hr = IWICBitmapSource_GetPixelFormat(bitmap_source, &wic_format)))
358 WARN("Failed to get bitmap format, hr %#x.\n", hr);
359 return hr;
362 for (i = 0, d2d_format = NULL; i < sizeof(format_lookup) / sizeof(*format_lookup); ++i)
364 if (IsEqualGUID(&wic_format, format_lookup[i].wic))
366 d2d_format = &format_lookup[i].d2d;
367 break;
371 if (!d2d_format)
373 WARN("Unsupported WIC bitmap format %s.\n", debugstr_guid(&wic_format));
374 return D2DERR_UNSUPPORTED_PIXEL_FORMAT;
377 if (bitmap_desc.pixelFormat.format == DXGI_FORMAT_UNKNOWN)
378 bitmap_desc.pixelFormat.format = d2d_format->format;
379 if (bitmap_desc.pixelFormat.alphaMode == D2D1_ALPHA_MODE_UNKNOWN)
380 bitmap_desc.pixelFormat.alphaMode = d2d_format->alphaMode;
382 switch (bitmap_desc.pixelFormat.format)
384 case DXGI_FORMAT_B8G8R8A8_UNORM:
385 bpp = 4;
386 break;
388 default:
389 FIXME("Unhandled format %#x.\n", bitmap_desc.pixelFormat.format);
390 return D2DERR_UNSUPPORTED_PIXEL_FORMAT;
393 pitch = ((bpp * size.width) + 15) & ~15;
394 data_size = pitch * size.height;
395 if (!(data = HeapAlloc(GetProcessHeap(), 0, data_size)))
396 return E_OUTOFMEMORY;
398 rect.X = 0;
399 rect.Y = 0;
400 rect.Width = size.width;
401 rect.Height = size.height;
402 if (FAILED(hr = IWICBitmapSource_CopyPixels(bitmap_source, &rect, pitch, data_size, data)))
404 WARN("Failed to copy bitmap pixels, hr %#x.\n", hr);
405 HeapFree(GetProcessHeap(), 0, data);
406 return hr;
409 hr = d2d_d3d_render_target_CreateBitmap(iface, size, data, pitch, &bitmap_desc, bitmap);
411 HeapFree(GetProcessHeap(), 0, data);
413 return hr;
416 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateSharedBitmap(ID2D1RenderTarget *iface,
417 REFIID iid, void *data, const D2D1_BITMAP_PROPERTIES *desc, ID2D1Bitmap **bitmap)
419 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
420 struct d2d_bitmap *object;
421 HRESULT hr;
423 TRACE("iface %p, iid %s, data %p, desc %p, bitmap %p.\n",
424 iface, debugstr_guid(iid), data, desc, bitmap);
426 if (!(object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object))))
427 return E_OUTOFMEMORY;
429 if (FAILED(hr = d2d_bitmap_init_shared(object, render_target, iid, data, desc)))
431 WARN("Failed to initialize bitmap, hr %#x.\n", hr);
432 HeapFree(GetProcessHeap(), 0, object);
433 return hr;
436 TRACE("Created bitmap %p.\n", object);
437 *bitmap = &object->ID2D1Bitmap_iface;
439 return S_OK;
442 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateBitmapBrush(ID2D1RenderTarget *iface,
443 ID2D1Bitmap *bitmap, const D2D1_BITMAP_BRUSH_PROPERTIES *bitmap_brush_desc,
444 const D2D1_BRUSH_PROPERTIES *brush_desc, ID2D1BitmapBrush **brush)
446 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
447 struct d2d_brush *object;
449 TRACE("iface %p, bitmap %p, bitmap_brush_desc %p, brush_desc %p, brush %p.\n",
450 iface, bitmap, bitmap_brush_desc, brush_desc, brush);
452 if (!(object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object))))
453 return E_OUTOFMEMORY;
455 d2d_bitmap_brush_init(object, render_target->factory, bitmap, bitmap_brush_desc, brush_desc);
457 TRACE("Created brush %p.\n", object);
458 *brush = (ID2D1BitmapBrush *)&object->ID2D1Brush_iface;
460 return S_OK;
463 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateSolidColorBrush(ID2D1RenderTarget *iface,
464 const D2D1_COLOR_F *color, const D2D1_BRUSH_PROPERTIES *desc, ID2D1SolidColorBrush **brush)
466 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
467 struct d2d_brush *object;
469 TRACE("iface %p, color %p, desc %p, brush %p.\n", iface, color, desc, brush);
471 if (!(object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object))))
472 return E_OUTOFMEMORY;
474 d2d_solid_color_brush_init(object, render_target->factory, color, desc);
476 TRACE("Created brush %p.\n", object);
477 *brush = (ID2D1SolidColorBrush *)&object->ID2D1Brush_iface;
479 return S_OK;
482 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateGradientStopCollection(ID2D1RenderTarget *iface,
483 const D2D1_GRADIENT_STOP *stops, UINT32 stop_count, D2D1_GAMMA gamma, D2D1_EXTEND_MODE extend_mode,
484 ID2D1GradientStopCollection **gradient)
486 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
487 struct d2d_gradient *object;
488 HRESULT hr;
490 TRACE("iface %p, stops %p, stop_count %u, gamma %#x, extend_mode %#x, gradient %p.\n",
491 iface, stops, stop_count, gamma, extend_mode, gradient);
493 if (!(object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object))))
494 return E_OUTOFMEMORY;
496 if (FAILED(hr = d2d_gradient_init(object, render_target->factory, stops, stop_count, gamma, extend_mode)))
498 WARN("Failed to initialize gradient, hr %#x.\n", hr);
499 HeapFree(GetProcessHeap(), 0, object);
500 return hr;
503 TRACE("Created gradient %p.\n", object);
504 *gradient = &object->ID2D1GradientStopCollection_iface;
506 return S_OK;
509 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateLinearGradientBrush(ID2D1RenderTarget *iface,
510 const D2D1_LINEAR_GRADIENT_BRUSH_PROPERTIES *gradient_brush_desc, const D2D1_BRUSH_PROPERTIES *brush_desc,
511 ID2D1GradientStopCollection *gradient, ID2D1LinearGradientBrush **brush)
513 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
514 struct d2d_brush *object;
516 TRACE("iface %p, gradient_brush_desc %p, brush_desc %p, gradient %p, brush %p.\n",
517 iface, gradient_brush_desc, brush_desc, gradient, brush);
519 if (!(object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object))))
520 return E_OUTOFMEMORY;
522 d2d_linear_gradient_brush_init(object, render_target->factory, gradient_brush_desc, brush_desc, gradient);
524 TRACE("Created brush %p.\n", object);
525 *brush = (ID2D1LinearGradientBrush *)&object->ID2D1Brush_iface;
527 return S_OK;
530 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateRadialGradientBrush(ID2D1RenderTarget *iface,
531 const D2D1_RADIAL_GRADIENT_BRUSH_PROPERTIES *gradient_brush_desc, const D2D1_BRUSH_PROPERTIES *brush_desc,
532 ID2D1GradientStopCollection *gradient, ID2D1RadialGradientBrush **brush)
534 FIXME("iface %p, gradient_brush_desc %p, brush_desc %p, gradient %p, brush %p stub!\n",
535 iface, gradient_brush_desc, brush_desc, gradient, brush);
537 return E_NOTIMPL;
540 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateCompatibleRenderTarget(ID2D1RenderTarget *iface,
541 const D2D1_SIZE_F *size, const D2D1_SIZE_U *pixel_size, const D2D1_PIXEL_FORMAT *format,
542 D2D1_COMPATIBLE_RENDER_TARGET_OPTIONS options, ID2D1BitmapRenderTarget **render_target)
544 FIXME("iface %p, size %p, pixel_size %p, format %p, options %#x, render_target %p stub!\n",
545 iface, size, pixel_size, format, options, render_target);
547 return E_NOTIMPL;
550 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateLayer(ID2D1RenderTarget *iface,
551 const D2D1_SIZE_F *size, ID2D1Layer **layer)
553 FIXME("iface %p, size %p, layer %p stub!\n", iface, size, layer);
555 return E_NOTIMPL;
558 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateMesh(ID2D1RenderTarget *iface, ID2D1Mesh **mesh)
560 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
561 struct d2d_mesh *object;
563 TRACE("iface %p, mesh %p.\n", iface, mesh);
565 if (!(object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object))))
566 return E_OUTOFMEMORY;
568 d2d_mesh_init(object, render_target->factory);
570 TRACE("Created mesh %p.\n", object);
571 *mesh = &object->ID2D1Mesh_iface;
573 return S_OK;
576 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawLine(ID2D1RenderTarget *iface,
577 D2D1_POINT_2F p0, D2D1_POINT_2F p1, ID2D1Brush *brush, float stroke_width, ID2D1StrokeStyle *stroke_style)
579 FIXME("iface %p, p0 {%.8e, %.8e}, p1 {%.8e, %.8e}, brush %p, stroke_width %.8e, stroke_style %p stub!\n",
580 iface, p0.x, p0.y, p1.x, p1.y, brush, stroke_width, stroke_style);
583 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawRectangle(ID2D1RenderTarget *iface,
584 const D2D1_RECT_F *rect, ID2D1Brush *brush, float stroke_width, ID2D1StrokeStyle *stroke_style)
586 FIXME("iface %p, rect %p, brush %p, stroke_width %.8e, stroke_style %p stub!\n",
587 iface, rect, brush, stroke_width, stroke_style);
590 static void STDMETHODCALLTYPE d2d_d3d_render_target_FillRectangle(ID2D1RenderTarget *iface,
591 const D2D1_RECT_F *rect, ID2D1Brush *brush)
593 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
594 ID2D1RectangleGeometry *geometry;
595 HRESULT hr;
597 TRACE("iface %p, rect %p, brush %p.\n", iface, rect, brush);
599 if (FAILED(hr = ID2D1Factory_CreateRectangleGeometry(render_target->factory, rect, &geometry)))
601 ERR("Failed to create geometry, hr %#x.\n", hr);
602 return;
605 ID2D1RenderTarget_FillGeometry(iface, (ID2D1Geometry *)geometry, brush, NULL);
606 ID2D1RectangleGeometry_Release(geometry);
609 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawRoundedRectangle(ID2D1RenderTarget *iface,
610 const D2D1_ROUNDED_RECT *rect, ID2D1Brush *brush, float stroke_width, ID2D1StrokeStyle *stroke_style)
612 FIXME("iface %p, rect %p, brush %p, stroke_width %.8e, stroke_style %p stub!\n",
613 iface, rect, brush, stroke_width, stroke_style);
616 static void STDMETHODCALLTYPE d2d_d3d_render_target_FillRoundedRectangle(ID2D1RenderTarget *iface,
617 const D2D1_ROUNDED_RECT *rect, ID2D1Brush *brush)
619 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
620 ID2D1RoundedRectangleGeometry *geometry;
621 HRESULT hr;
623 TRACE("iface %p, rect %p, brush %p.\n", iface, rect, brush);
625 if (FAILED(hr = ID2D1Factory_CreateRoundedRectangleGeometry(render_target->factory, rect, &geometry)))
627 ERR("Failed to create geometry, hr %#x.\n", hr);
628 return;
631 ID2D1RenderTarget_FillGeometry(iface, (ID2D1Geometry *)geometry, brush, NULL);
632 ID2D1RoundedRectangleGeometry_Release(geometry);
635 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawEllipse(ID2D1RenderTarget *iface,
636 const D2D1_ELLIPSE *ellipse, ID2D1Brush *brush, float stroke_width, ID2D1StrokeStyle *stroke_style)
638 FIXME("iface %p, ellipse %p, brush %p, stroke_width %.8e, stroke_style %p stub!\n",
639 iface, ellipse, brush, stroke_width, stroke_style);
642 static void STDMETHODCALLTYPE d2d_d3d_render_target_FillEllipse(ID2D1RenderTarget *iface,
643 const D2D1_ELLIPSE *ellipse, ID2D1Brush *brush)
645 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
646 ID2D1EllipseGeometry *geometry;
647 HRESULT hr;
649 TRACE("iface %p, ellipse %p, brush %p.\n", iface, ellipse, brush);
651 if (FAILED(hr = ID2D1Factory_CreateEllipseGeometry(render_target->factory, ellipse, &geometry)))
653 ERR("Failed to create geometry, hr %#x.\n", hr);
654 return;
657 ID2D1RenderTarget_FillGeometry(iface, (ID2D1Geometry *)geometry, brush, NULL);
658 ID2D1EllipseGeometry_Release(geometry);
661 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawGeometry(ID2D1RenderTarget *iface,
662 ID2D1Geometry *geometry, ID2D1Brush *brush, float stroke_width, ID2D1StrokeStyle *stroke_style)
664 FIXME("iface %p, geometry %p, brush %p, stroke_width %.8e, stroke_style %p stub!\n",
665 iface, geometry, brush, stroke_width, stroke_style);
668 static void STDMETHODCALLTYPE d2d_d3d_render_target_FillGeometry(ID2D1RenderTarget *iface,
669 ID2D1Geometry *geometry, ID2D1Brush *brush, ID2D1Brush *opacity_brush)
671 struct d2d_brush *opacity_brush_impl = unsafe_impl_from_ID2D1Brush(opacity_brush);
672 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
673 struct d2d_brush *brush_impl = unsafe_impl_from_ID2D1Brush(brush);
674 const struct d2d_geometry *geometry_impl;
675 ID3D10Buffer *ib, *vb, *vs_cb, *ps_cb;
676 D3D10_SUBRESOURCE_DATA buffer_data;
677 D3D10_BUFFER_DESC buffer_desc;
678 D2D1_MATRIX_3X2_F w, g;
679 float tmp_x, tmp_y;
680 HRESULT hr;
681 struct
683 float _11, _21, _31, pad0;
684 float _12, _22, _32, pad1;
685 } transform;
687 TRACE("iface %p, geometry %p, brush %p, opacity_brush %p.\n", iface, geometry, brush, opacity_brush);
689 if (FAILED(render_target->error.code))
690 return;
692 if (opacity_brush && brush_impl->type != D2D_BRUSH_TYPE_BITMAP)
694 render_target->error.code = D2DERR_INCOMPATIBLE_BRUSH_TYPES;
695 render_target->error.tag1 = render_target->drawing_state.tag1;
696 render_target->error.tag2 = render_target->drawing_state.tag2;
697 return;
700 geometry_impl = unsafe_impl_from_ID2D1Geometry(geometry);
702 tmp_x = (2.0f * render_target->dpi_x) / (96.0f * render_target->pixel_size.width);
703 tmp_y = -(2.0f * render_target->dpi_y) / (96.0f * render_target->pixel_size.height);
704 w = render_target->drawing_state.transform;
705 w._11 *= tmp_x;
706 w._21 *= tmp_x;
707 w._31 = w._31 * tmp_x - 1.0f;
708 w._12 *= tmp_y;
709 w._22 *= tmp_y;
710 w._32 = w._32 * tmp_y + 1.0f;
712 g = geometry_impl->transform;
713 d2d_matrix_multiply(&g, &w);
715 transform._11 = g._11;
716 transform._21 = g._21;
717 transform._31 = g._31;
718 transform.pad0 = 0.0f;
719 transform._12 = g._12;
720 transform._22 = g._22;
721 transform._32 = g._32;
722 transform.pad1 = 0.0f;
724 buffer_desc.ByteWidth = sizeof(transform);
725 buffer_desc.Usage = D3D10_USAGE_DEFAULT;
726 buffer_desc.BindFlags = D3D10_BIND_CONSTANT_BUFFER;
727 buffer_desc.CPUAccessFlags = 0;
728 buffer_desc.MiscFlags = 0;
730 buffer_data.pSysMem = &transform;
731 buffer_data.SysMemPitch = 0;
732 buffer_data.SysMemSlicePitch = 0;
734 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device, &buffer_desc, &buffer_data, &vs_cb)))
736 WARN("Failed to create constant buffer, hr %#x.\n", hr);
737 return;
740 if (FAILED(hr = d2d_brush_get_ps_cb(brush_impl, opacity_brush_impl, render_target, &ps_cb)))
742 WARN("Failed to get ps constant buffer, hr %#x.\n", hr);
743 ID3D10Buffer_Release(vs_cb);
744 return;
747 if (geometry_impl->face_count)
749 buffer_desc.ByteWidth = geometry_impl->face_count * sizeof(*geometry_impl->faces);
750 buffer_desc.BindFlags = D3D10_BIND_INDEX_BUFFER;
751 buffer_data.pSysMem = geometry_impl->faces;
753 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device, &buffer_desc, &buffer_data, &ib)))
755 WARN("Failed to create index buffer, hr %#x.\n", hr);
756 goto done;
759 buffer_desc.ByteWidth = geometry_impl->vertex_count * sizeof(*geometry_impl->vertices);
760 buffer_desc.BindFlags = D3D10_BIND_VERTEX_BUFFER;
761 buffer_data.pSysMem = geometry_impl->vertices;
763 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device, &buffer_desc, &buffer_data, &vb)))
765 ERR("Failed to create vertex buffer, hr %#x.\n", hr);
766 ID3D10Buffer_Release(ib);
767 goto done;
770 d2d_rt_draw(render_target, D2D_SHAPE_TYPE_TRIANGLE, ib, 3 * geometry_impl->face_count, vb,
771 sizeof(*geometry_impl->vertices), vs_cb, ps_cb, brush_impl, opacity_brush_impl);
773 ID3D10Buffer_Release(vb);
774 ID3D10Buffer_Release(ib);
777 if (geometry_impl->bezier_count)
779 buffer_desc.ByteWidth = geometry_impl->bezier_count * sizeof(*geometry_impl->beziers);
780 buffer_data.pSysMem = geometry_impl->beziers;
782 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device, &buffer_desc, &buffer_data, &vb)))
784 ERR("Failed to create beziers vertex buffer, hr %#x.\n", hr);
785 goto done;
788 d2d_rt_draw(render_target, D2D_SHAPE_TYPE_BEZIER, NULL, 3 * geometry_impl->bezier_count, vb,
789 sizeof(*geometry_impl->beziers->v), vs_cb, ps_cb, brush_impl, opacity_brush_impl);
791 ID3D10Buffer_Release(vb);
794 done:
795 ID3D10Buffer_Release(ps_cb);
796 ID3D10Buffer_Release(vs_cb);
799 static void STDMETHODCALLTYPE d2d_d3d_render_target_FillMesh(ID2D1RenderTarget *iface,
800 ID2D1Mesh *mesh, ID2D1Brush *brush)
802 FIXME("iface %p, mesh %p, brush %p stub!\n", iface, mesh, brush);
805 static void STDMETHODCALLTYPE d2d_d3d_render_target_FillOpacityMask(ID2D1RenderTarget *iface,
806 ID2D1Bitmap *mask, ID2D1Brush *brush, D2D1_OPACITY_MASK_CONTENT content,
807 const D2D1_RECT_F *dst_rect, const D2D1_RECT_F *src_rect)
809 FIXME("iface %p, mask %p, brush %p, content %#x, dst_rect %p, src_rect %p stub!\n",
810 iface, mask, brush, content, dst_rect, src_rect);
813 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawBitmap(ID2D1RenderTarget *iface,
814 ID2D1Bitmap *bitmap, const D2D1_RECT_F *dst_rect, float opacity,
815 D2D1_BITMAP_INTERPOLATION_MODE interpolation_mode, const D2D1_RECT_F *src_rect)
817 D2D1_BITMAP_BRUSH_PROPERTIES bitmap_brush_desc;
818 D2D1_BRUSH_PROPERTIES brush_desc;
819 ID2D1BitmapBrush *brush;
820 D2D1_RECT_F s, d;
821 HRESULT hr;
823 TRACE("iface %p, bitmap %p, dst_rect %p, opacity %.8e, interpolation_mode %#x, src_rect %p.\n",
824 iface, bitmap, dst_rect, opacity, interpolation_mode, src_rect);
826 if (src_rect)
828 s = *src_rect;
830 else
832 D2D1_SIZE_F size;
834 size = ID2D1Bitmap_GetSize(bitmap);
835 s.left = 0.0f;
836 s.top = 0.0f;
837 s.right = size.width;
838 s.bottom = size.height;
841 if (dst_rect)
843 d = *dst_rect;
845 else
847 d.left = 0.0f;
848 d.top = 0.0f;
849 d.right = s.right - s.left;
850 d.bottom = s.bottom - s.top;
853 bitmap_brush_desc.extendModeX = D2D1_EXTEND_MODE_CLAMP;
854 bitmap_brush_desc.extendModeY = D2D1_EXTEND_MODE_CLAMP;
855 bitmap_brush_desc.interpolationMode = interpolation_mode;
857 brush_desc.opacity = opacity;
858 brush_desc.transform._11 = fabsf((d.right - d.left) / (s.right - s.left));
859 brush_desc.transform._21 = 0.0f;
860 brush_desc.transform._31 = min(d.left, d.right) - min(s.left, s.right) * brush_desc.transform._11;
861 brush_desc.transform._12 = 0.0f;
862 brush_desc.transform._22 = fabsf((d.bottom - d.top) / (s.bottom - s.top));
863 brush_desc.transform._32 = min(d.top, d.bottom) - min(s.top, s.bottom) * brush_desc.transform._22;
865 if (FAILED(hr = ID2D1RenderTarget_CreateBitmapBrush(iface, bitmap, &bitmap_brush_desc, &brush_desc, &brush)))
867 ERR("Failed to create bitmap brush, hr %#x.\n", hr);
868 return;
871 ID2D1RenderTarget_FillRectangle(iface, &d, (ID2D1Brush *)brush);
872 ID2D1BitmapBrush_Release(brush);
875 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawText(ID2D1RenderTarget *iface,
876 const WCHAR *string, UINT32 string_len, IDWriteTextFormat *text_format, const D2D1_RECT_F *layout_rect,
877 ID2D1Brush *brush, D2D1_DRAW_TEXT_OPTIONS options, DWRITE_MEASURING_MODE measuring_mode)
879 IDWriteTextLayout *text_layout;
880 IDWriteFactory *dwrite_factory;
881 D2D1_POINT_2F origin;
882 HRESULT hr;
884 TRACE("iface %p, string %s, string_len %u, text_format %p, layout_rect %p, "
885 "brush %p, options %#x, measuring_mode %#x.\n",
886 iface, debugstr_wn(string, string_len), string_len, text_format, layout_rect,
887 brush, options, measuring_mode);
889 if (measuring_mode != DWRITE_MEASURING_MODE_NATURAL)
890 FIXME("Ignoring measuring mode %#x.\n", measuring_mode);
892 if (FAILED(hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED,
893 &IID_IDWriteFactory, (IUnknown **)&dwrite_factory)))
895 ERR("Failed to create dwrite factory, hr %#x.\n", hr);
896 return;
899 hr = IDWriteFactory_CreateTextLayout(dwrite_factory, string, string_len, text_format,
900 layout_rect->right - layout_rect->left, layout_rect->bottom - layout_rect->top, &text_layout);
901 IDWriteFactory_Release(dwrite_factory);
902 if (FAILED(hr))
904 ERR("Failed to create text layout, hr %#x.\n", hr);
905 return;
908 d2d_point_set(&origin, layout_rect->left, layout_rect->top);
909 ID2D1RenderTarget_DrawTextLayout(iface, origin, text_layout, brush, options);
910 IDWriteTextLayout_Release(text_layout);
913 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawTextLayout(ID2D1RenderTarget *iface,
914 D2D1_POINT_2F origin, IDWriteTextLayout *layout, ID2D1Brush *brush, D2D1_DRAW_TEXT_OPTIONS options)
916 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
917 struct d2d_draw_text_layout_ctx ctx;
918 HRESULT hr;
920 TRACE("iface %p, origin {%.8e, %.8e}, layout %p, brush %p, options %#x.\n",
921 iface, origin.x, origin.y, layout, brush, options);
923 ctx.brush = brush;
924 ctx.options = options;
926 if (FAILED(hr = IDWriteTextLayout_Draw(layout,
927 &ctx, &render_target->IDWriteTextRenderer_iface, origin.x, origin.y)))
928 FIXME("Failed to draw text layout, hr %#x.\n", hr);
931 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawGlyphRun(ID2D1RenderTarget *iface,
932 D2D1_POINT_2F baseline_origin, const DWRITE_GLYPH_RUN *glyph_run, ID2D1Brush *brush,
933 DWRITE_MEASURING_MODE measuring_mode)
935 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
936 D2D1_MATRIX_3X2_F *transform, prev_transform;
937 ID2D1PathGeometry *geometry;
938 ID2D1GeometrySink *sink;
939 HRESULT hr;
941 TRACE("iface %p, baseline_origin {%.8e, %.8e}, glyph_run %p, brush %p, measuring_mode %#x.\n",
942 iface, baseline_origin.x, baseline_origin.y, glyph_run, brush, measuring_mode);
944 if (measuring_mode)
945 FIXME("Ignoring measuring mode %#x.\n", measuring_mode);
946 if (render_target->text_rendering_params)
947 FIXME("Ignoring text rendering parameters %p.\n", render_target->text_rendering_params);
948 if (render_target->drawing_state.textAntialiasMode != D2D1_TEXT_ANTIALIAS_MODE_ALIASED)
949 FIXME("Ignoring text antialiasing mode %#x.\n", render_target->drawing_state.textAntialiasMode);
951 if (FAILED(hr = ID2D1Factory_CreatePathGeometry(render_target->factory, &geometry)))
953 ERR("Failed to create geometry, hr %#x.\n", hr);
954 return;
957 if (FAILED(hr = ID2D1PathGeometry_Open(geometry, &sink)))
959 ERR("Failed to open geometry sink, hr %#x.\n", hr);
960 ID2D1PathGeometry_Release(geometry);
961 return;
964 if (FAILED(hr = IDWriteFontFace_GetGlyphRunOutline(glyph_run->fontFace, glyph_run->fontEmSize,
965 glyph_run->glyphIndices, glyph_run->glyphAdvances, glyph_run->glyphOffsets, glyph_run->glyphCount,
966 glyph_run->isSideways, glyph_run->bidiLevel & 1, (IDWriteGeometrySink *)sink)))
968 ERR("Failed to get glyph run outline, hr %#x.\n", hr);
969 ID2D1GeometrySink_Release(sink);
970 ID2D1PathGeometry_Release(geometry);
971 return;
974 if (FAILED(hr = ID2D1GeometrySink_Close(sink)))
975 ERR("Failed to close geometry sink, hr %#x.\n", hr);
976 ID2D1GeometrySink_Release(sink);
978 transform = &render_target->drawing_state.transform;
979 prev_transform = *transform;
980 transform->_31 += baseline_origin.x * transform->_11 + baseline_origin.y * transform->_21;
981 transform->_32 += baseline_origin.x * transform->_12 + baseline_origin.y * transform->_22;
982 ID2D1RenderTarget_FillGeometry(iface, (ID2D1Geometry *)geometry, brush, NULL);
983 *transform = prev_transform;
985 ID2D1PathGeometry_Release(geometry);
988 static void STDMETHODCALLTYPE d2d_d3d_render_target_SetTransform(ID2D1RenderTarget *iface,
989 const D2D1_MATRIX_3X2_F *transform)
991 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
993 TRACE("iface %p, transform %p.\n", iface, transform);
995 render_target->drawing_state.transform = *transform;
998 static void STDMETHODCALLTYPE d2d_d3d_render_target_GetTransform(ID2D1RenderTarget *iface,
999 D2D1_MATRIX_3X2_F *transform)
1001 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1003 TRACE("iface %p, transform %p.\n", iface, transform);
1005 *transform = render_target->drawing_state.transform;
1008 static void STDMETHODCALLTYPE d2d_d3d_render_target_SetAntialiasMode(ID2D1RenderTarget *iface,
1009 D2D1_ANTIALIAS_MODE antialias_mode)
1011 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1013 TRACE("iface %p, antialias_mode %#x stub!\n", iface, antialias_mode);
1015 render_target->drawing_state.antialiasMode = antialias_mode;
1018 static D2D1_ANTIALIAS_MODE STDMETHODCALLTYPE d2d_d3d_render_target_GetAntialiasMode(ID2D1RenderTarget *iface)
1020 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1022 TRACE("iface %p.\n", iface);
1024 return render_target->drawing_state.antialiasMode;
1027 static void STDMETHODCALLTYPE d2d_d3d_render_target_SetTextAntialiasMode(ID2D1RenderTarget *iface,
1028 D2D1_TEXT_ANTIALIAS_MODE antialias_mode)
1030 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1032 TRACE("iface %p, antialias_mode %#x.\n", iface, antialias_mode);
1034 render_target->drawing_state.textAntialiasMode = antialias_mode;
1037 static D2D1_TEXT_ANTIALIAS_MODE STDMETHODCALLTYPE d2d_d3d_render_target_GetTextAntialiasMode(ID2D1RenderTarget *iface)
1039 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1041 TRACE("iface %p.\n", iface);
1043 return render_target->drawing_state.textAntialiasMode;
1046 static void STDMETHODCALLTYPE d2d_d3d_render_target_SetTextRenderingParams(ID2D1RenderTarget *iface,
1047 IDWriteRenderingParams *text_rendering_params)
1049 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1051 TRACE("iface %p, text_rendering_params %p.\n", iface, text_rendering_params);
1053 if (text_rendering_params)
1054 IDWriteRenderingParams_AddRef(text_rendering_params);
1055 if (render_target->text_rendering_params)
1056 IDWriteRenderingParams_Release(render_target->text_rendering_params);
1057 render_target->text_rendering_params = text_rendering_params;
1060 static void STDMETHODCALLTYPE d2d_d3d_render_target_GetTextRenderingParams(ID2D1RenderTarget *iface,
1061 IDWriteRenderingParams **text_rendering_params)
1063 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1065 TRACE("iface %p, text_rendering_params %p.\n", iface, text_rendering_params);
1067 if ((*text_rendering_params = render_target->text_rendering_params))
1068 IDWriteRenderingParams_AddRef(*text_rendering_params);
1071 static void STDMETHODCALLTYPE d2d_d3d_render_target_SetTags(ID2D1RenderTarget *iface, D2D1_TAG tag1, D2D1_TAG tag2)
1073 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1075 TRACE("iface %p, tag1 %s, tag2 %s.\n", iface, wine_dbgstr_longlong(tag1), wine_dbgstr_longlong(tag2));
1077 render_target->drawing_state.tag1 = tag1;
1078 render_target->drawing_state.tag2 = tag2;
1081 static void STDMETHODCALLTYPE d2d_d3d_render_target_GetTags(ID2D1RenderTarget *iface, D2D1_TAG *tag1, D2D1_TAG *tag2)
1083 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1085 TRACE("iface %p, tag1 %p, tag2 %p.\n", iface, tag1, tag2);
1087 *tag1 = render_target->drawing_state.tag1;
1088 *tag2 = render_target->drawing_state.tag2;
1091 static void STDMETHODCALLTYPE d2d_d3d_render_target_PushLayer(ID2D1RenderTarget *iface,
1092 const D2D1_LAYER_PARAMETERS *layer_parameters, ID2D1Layer *layer)
1094 FIXME("iface %p, layer_parameters %p, layer %p stub!\n", iface, layer_parameters, layer);
1097 static void STDMETHODCALLTYPE d2d_d3d_render_target_PopLayer(ID2D1RenderTarget *iface)
1099 FIXME("iface %p stub!\n", iface);
1102 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_Flush(ID2D1RenderTarget *iface, D2D1_TAG *tag1, D2D1_TAG *tag2)
1104 FIXME("iface %p, tag1 %p, tag2 %p stub!\n", iface, tag1, tag2);
1106 return E_NOTIMPL;
1109 static void STDMETHODCALLTYPE d2d_d3d_render_target_SaveDrawingState(ID2D1RenderTarget *iface,
1110 ID2D1DrawingStateBlock *state_block)
1112 struct d2d_state_block *state_block_impl = unsafe_impl_from_ID2D1DrawingStateBlock(state_block);
1113 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1115 TRACE("iface %p, state_block %p.\n", iface, state_block);
1117 state_block_impl->drawing_state = render_target->drawing_state;
1118 if (render_target->text_rendering_params)
1119 IDWriteRenderingParams_AddRef(render_target->text_rendering_params);
1120 if (state_block_impl->text_rendering_params)
1121 IDWriteRenderingParams_Release(state_block_impl->text_rendering_params);
1122 state_block_impl->text_rendering_params = render_target->text_rendering_params;
1125 static void STDMETHODCALLTYPE d2d_d3d_render_target_RestoreDrawingState(ID2D1RenderTarget *iface,
1126 ID2D1DrawingStateBlock *state_block)
1128 struct d2d_state_block *state_block_impl = unsafe_impl_from_ID2D1DrawingStateBlock(state_block);
1129 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1131 TRACE("iface %p, state_block %p.\n", iface, state_block);
1133 render_target->drawing_state = state_block_impl->drawing_state;
1134 if (state_block_impl->text_rendering_params)
1135 IDWriteRenderingParams_AddRef(state_block_impl->text_rendering_params);
1136 if (render_target->text_rendering_params)
1137 IDWriteRenderingParams_Release(render_target->text_rendering_params);
1138 render_target->text_rendering_params = state_block_impl->text_rendering_params;
1141 static void STDMETHODCALLTYPE d2d_d3d_render_target_PushAxisAlignedClip(ID2D1RenderTarget *iface,
1142 const D2D1_RECT_F *clip_rect, D2D1_ANTIALIAS_MODE antialias_mode)
1144 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1145 D2D1_RECT_F transformed_rect;
1146 float x_scale, y_scale;
1147 D2D1_POINT_2F point;
1149 TRACE("iface %p, clip_rect %p, antialias_mode %#x.\n", iface, clip_rect, antialias_mode);
1151 if (antialias_mode != D2D1_ANTIALIAS_MODE_ALIASED)
1152 FIXME("Ignoring antialias_mode %#x.\n", antialias_mode);
1154 x_scale = render_target->dpi_x / 96.0f;
1155 y_scale = render_target->dpi_y / 96.0f;
1156 d2d_point_transform(&point, &render_target->drawing_state.transform,
1157 clip_rect->left * x_scale, clip_rect->top * y_scale);
1158 d2d_rect_set(&transformed_rect, point.x, point.y, point.x, point.y);
1159 d2d_point_transform(&point, &render_target->drawing_state.transform,
1160 clip_rect->left * x_scale, clip_rect->bottom * y_scale);
1161 d2d_rect_expand(&transformed_rect, &point);
1162 d2d_point_transform(&point, &render_target->drawing_state.transform,
1163 clip_rect->right * x_scale, clip_rect->top * y_scale);
1164 d2d_rect_expand(&transformed_rect, &point);
1165 d2d_point_transform(&point, &render_target->drawing_state.transform,
1166 clip_rect->right * x_scale, clip_rect->bottom * y_scale);
1167 d2d_rect_expand(&transformed_rect, &point);
1169 if (!d2d_clip_stack_push(&render_target->clip_stack, &transformed_rect))
1170 WARN("Failed to push clip rect.\n");
1173 static void STDMETHODCALLTYPE d2d_d3d_render_target_PopAxisAlignedClip(ID2D1RenderTarget *iface)
1175 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1177 TRACE("iface %p.\n", iface);
1179 d2d_clip_stack_pop(&render_target->clip_stack);
1182 static void STDMETHODCALLTYPE d2d_d3d_render_target_Clear(ID2D1RenderTarget *iface, const D2D1_COLOR_F *color)
1184 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1185 D2D1_COLOR_F c = {0.0f, 0.0f, 0.0f, 0.0f};
1186 D3D10_SUBRESOURCE_DATA buffer_data;
1187 D3D10_BUFFER_DESC buffer_desc;
1188 ID3D10Buffer *vs_cb, *ps_cb;
1189 HRESULT hr;
1191 static const float transform[] =
1193 1.0f, 0.0f, 0.0f, 0.0f,
1194 0.0f, -1.0f, 0.0f, 0.0f,
1197 TRACE("iface %p, color %p.\n", iface, color);
1199 buffer_desc.ByteWidth = sizeof(transform);
1200 buffer_desc.Usage = D3D10_USAGE_DEFAULT;
1201 buffer_desc.BindFlags = D3D10_BIND_CONSTANT_BUFFER;
1202 buffer_desc.CPUAccessFlags = 0;
1203 buffer_desc.MiscFlags = 0;
1205 buffer_data.pSysMem = transform;
1206 buffer_data.SysMemPitch = 0;
1207 buffer_data.SysMemSlicePitch = 0;
1209 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device, &buffer_desc, &buffer_data, &vs_cb)))
1211 WARN("Failed to create constant buffer, hr %#x.\n", hr);
1212 return;
1215 if (color)
1216 c = *color;
1217 if (render_target->format.alphaMode == D2D1_ALPHA_MODE_IGNORE)
1218 c.a = 1.0f;
1219 c.r *= c.a;
1220 c.g *= c.a;
1221 c.b *= c.a;
1222 buffer_desc.ByteWidth = sizeof(c);
1223 buffer_data.pSysMem = &c;
1225 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device, &buffer_desc, &buffer_data, &ps_cb)))
1227 WARN("Failed to create constant buffer, hr %#x.\n", hr);
1228 ID3D10Buffer_Release(vs_cb);
1229 return;
1232 d2d_rt_draw(render_target, D2D_SHAPE_TYPE_TRIANGLE, render_target->ib, 6,
1233 render_target->vb, render_target->vb_stride, vs_cb, ps_cb, NULL, NULL);
1235 ID3D10Buffer_Release(ps_cb);
1236 ID3D10Buffer_Release(vs_cb);
1239 static void STDMETHODCALLTYPE d2d_d3d_render_target_BeginDraw(ID2D1RenderTarget *iface)
1241 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1243 TRACE("iface %p.\n", iface);
1245 memset(&render_target->error, 0, sizeof(render_target->error));
1248 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_EndDraw(ID2D1RenderTarget *iface,
1249 D2D1_TAG *tag1, D2D1_TAG *tag2)
1251 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1253 TRACE("iface %p, tag1 %p, tag2 %p.\n", iface, tag1, tag2);
1255 if (tag1)
1256 *tag1 = render_target->error.tag1;
1257 if (tag2)
1258 *tag1 = render_target->error.tag2;
1260 return render_target->error.code;
1263 static D2D1_PIXEL_FORMAT * STDMETHODCALLTYPE d2d_d3d_render_target_GetPixelFormat(ID2D1RenderTarget *iface,
1264 D2D1_PIXEL_FORMAT *format)
1266 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1268 TRACE("iface %p, format %p.\n", iface, format);
1270 *format = render_target->format;
1271 return format;
1274 static void STDMETHODCALLTYPE d2d_d3d_render_target_SetDpi(ID2D1RenderTarget *iface, float dpi_x, float dpi_y)
1276 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1278 TRACE("iface %p, dpi_x %.8e, dpi_y %.8e.\n", iface, dpi_x, dpi_y);
1280 if (dpi_x == 0.0f && dpi_y == 0.0f)
1282 dpi_x = 96.0f;
1283 dpi_y = 96.0f;
1286 render_target->dpi_x = dpi_x;
1287 render_target->dpi_y = dpi_y;
1290 static void STDMETHODCALLTYPE d2d_d3d_render_target_GetDpi(ID2D1RenderTarget *iface, float *dpi_x, float *dpi_y)
1292 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1294 TRACE("iface %p, dpi_x %p, dpi_y %p.\n", iface, dpi_x, dpi_y);
1296 *dpi_x = render_target->dpi_x;
1297 *dpi_y = render_target->dpi_y;
1300 static D2D1_SIZE_F * STDMETHODCALLTYPE d2d_d3d_render_target_GetSize(ID2D1RenderTarget *iface, D2D1_SIZE_F *size)
1302 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1304 TRACE("iface %p, size %p.\n", iface, size);
1306 size->width = render_target->pixel_size.width / (render_target->dpi_x / 96.0f);
1307 size->height = render_target->pixel_size.height / (render_target->dpi_y / 96.0f);
1308 return size;
1311 static D2D1_SIZE_U * STDMETHODCALLTYPE d2d_d3d_render_target_GetPixelSize(ID2D1RenderTarget *iface,
1312 D2D1_SIZE_U *pixel_size)
1314 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1316 TRACE("iface %p, pixel_size %p.\n", iface, pixel_size);
1318 *pixel_size = render_target->pixel_size;
1319 return pixel_size;
1322 static UINT32 STDMETHODCALLTYPE d2d_d3d_render_target_GetMaximumBitmapSize(ID2D1RenderTarget *iface)
1324 FIXME("iface %p stub!\n", iface);
1326 return 0;
1329 static BOOL STDMETHODCALLTYPE d2d_d3d_render_target_IsSupported(ID2D1RenderTarget *iface,
1330 const D2D1_RENDER_TARGET_PROPERTIES *desc)
1332 FIXME("iface %p, desc %p stub!\n", iface, desc);
1334 return FALSE;
1337 static const struct ID2D1RenderTargetVtbl d2d_d3d_render_target_vtbl =
1339 d2d_d3d_render_target_QueryInterface,
1340 d2d_d3d_render_target_AddRef,
1341 d2d_d3d_render_target_Release,
1342 d2d_d3d_render_target_GetFactory,
1343 d2d_d3d_render_target_CreateBitmap,
1344 d2d_d3d_render_target_CreateBitmapFromWicBitmap,
1345 d2d_d3d_render_target_CreateSharedBitmap,
1346 d2d_d3d_render_target_CreateBitmapBrush,
1347 d2d_d3d_render_target_CreateSolidColorBrush,
1348 d2d_d3d_render_target_CreateGradientStopCollection,
1349 d2d_d3d_render_target_CreateLinearGradientBrush,
1350 d2d_d3d_render_target_CreateRadialGradientBrush,
1351 d2d_d3d_render_target_CreateCompatibleRenderTarget,
1352 d2d_d3d_render_target_CreateLayer,
1353 d2d_d3d_render_target_CreateMesh,
1354 d2d_d3d_render_target_DrawLine,
1355 d2d_d3d_render_target_DrawRectangle,
1356 d2d_d3d_render_target_FillRectangle,
1357 d2d_d3d_render_target_DrawRoundedRectangle,
1358 d2d_d3d_render_target_FillRoundedRectangle,
1359 d2d_d3d_render_target_DrawEllipse,
1360 d2d_d3d_render_target_FillEllipse,
1361 d2d_d3d_render_target_DrawGeometry,
1362 d2d_d3d_render_target_FillGeometry,
1363 d2d_d3d_render_target_FillMesh,
1364 d2d_d3d_render_target_FillOpacityMask,
1365 d2d_d3d_render_target_DrawBitmap,
1366 d2d_d3d_render_target_DrawText,
1367 d2d_d3d_render_target_DrawTextLayout,
1368 d2d_d3d_render_target_DrawGlyphRun,
1369 d2d_d3d_render_target_SetTransform,
1370 d2d_d3d_render_target_GetTransform,
1371 d2d_d3d_render_target_SetAntialiasMode,
1372 d2d_d3d_render_target_GetAntialiasMode,
1373 d2d_d3d_render_target_SetTextAntialiasMode,
1374 d2d_d3d_render_target_GetTextAntialiasMode,
1375 d2d_d3d_render_target_SetTextRenderingParams,
1376 d2d_d3d_render_target_GetTextRenderingParams,
1377 d2d_d3d_render_target_SetTags,
1378 d2d_d3d_render_target_GetTags,
1379 d2d_d3d_render_target_PushLayer,
1380 d2d_d3d_render_target_PopLayer,
1381 d2d_d3d_render_target_Flush,
1382 d2d_d3d_render_target_SaveDrawingState,
1383 d2d_d3d_render_target_RestoreDrawingState,
1384 d2d_d3d_render_target_PushAxisAlignedClip,
1385 d2d_d3d_render_target_PopAxisAlignedClip,
1386 d2d_d3d_render_target_Clear,
1387 d2d_d3d_render_target_BeginDraw,
1388 d2d_d3d_render_target_EndDraw,
1389 d2d_d3d_render_target_GetPixelFormat,
1390 d2d_d3d_render_target_SetDpi,
1391 d2d_d3d_render_target_GetDpi,
1392 d2d_d3d_render_target_GetSize,
1393 d2d_d3d_render_target_GetPixelSize,
1394 d2d_d3d_render_target_GetMaximumBitmapSize,
1395 d2d_d3d_render_target_IsSupported,
1398 static inline struct d2d_d3d_render_target *impl_from_IDWriteTextRenderer(IDWriteTextRenderer *iface)
1400 return CONTAINING_RECORD(iface, struct d2d_d3d_render_target, IDWriteTextRenderer_iface);
1403 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_QueryInterface(IDWriteTextRenderer *iface, REFIID iid, void **out)
1405 TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
1407 if (IsEqualGUID(iid, &IID_IDWriteTextRenderer)
1408 || IsEqualGUID(iid, &IID_IDWritePixelSnapping)
1409 || IsEqualGUID(iid, &IID_IUnknown))
1411 IDWriteTextRenderer_AddRef(iface);
1412 *out = iface;
1413 return S_OK;
1416 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
1418 *out = NULL;
1419 return E_NOINTERFACE;
1422 static ULONG STDMETHODCALLTYPE d2d_text_renderer_AddRef(IDWriteTextRenderer *iface)
1424 struct d2d_d3d_render_target *render_target = impl_from_IDWriteTextRenderer(iface);
1426 TRACE("iface %p.\n", iface);
1428 return d2d_d3d_render_target_AddRef(&render_target->ID2D1RenderTarget_iface);
1431 static ULONG STDMETHODCALLTYPE d2d_text_renderer_Release(IDWriteTextRenderer *iface)
1433 struct d2d_d3d_render_target *render_target = impl_from_IDWriteTextRenderer(iface);
1435 TRACE("iface %p.\n", iface);
1437 return d2d_d3d_render_target_Release(&render_target->ID2D1RenderTarget_iface);
1440 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_IsPixelSnappingDisabled(IDWriteTextRenderer *iface,
1441 void *ctx, BOOL *disabled)
1443 struct d2d_draw_text_layout_ctx *context = ctx;
1445 TRACE("iface %p, ctx %p, disabled %p.\n", iface, ctx, disabled);
1447 *disabled = context->options & D2D1_DRAW_TEXT_OPTIONS_NO_SNAP;
1449 return S_OK;
1452 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_GetCurrentTransform(IDWriteTextRenderer *iface,
1453 void *ctx, DWRITE_MATRIX *transform)
1455 struct d2d_d3d_render_target *render_target = impl_from_IDWriteTextRenderer(iface);
1457 TRACE("iface %p, ctx %p, transform %p.\n", iface, ctx, transform);
1459 ID2D1RenderTarget_GetTransform(&render_target->ID2D1RenderTarget_iface, (D2D1_MATRIX_3X2_F *)transform);
1461 return S_OK;
1464 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_GetPixelsPerDip(IDWriteTextRenderer *iface, void *ctx, float *ppd)
1466 struct d2d_d3d_render_target *render_target = impl_from_IDWriteTextRenderer(iface);
1468 TRACE("iface %p, ctx %p, ppd %p.\n", iface, ctx, ppd);
1470 *ppd = render_target->dpi_y / 96.0f;
1472 return S_OK;
1475 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_DrawGlyphRun(IDWriteTextRenderer *iface, void *ctx,
1476 float baseline_origin_x, float baseline_origin_y, DWRITE_MEASURING_MODE measuring_mode,
1477 const DWRITE_GLYPH_RUN *glyph_run, const DWRITE_GLYPH_RUN_DESCRIPTION *desc, IUnknown *effect)
1479 struct d2d_d3d_render_target *render_target = impl_from_IDWriteTextRenderer(iface);
1480 D2D1_POINT_2F baseline_origin = {baseline_origin_x, baseline_origin_y};
1481 struct d2d_draw_text_layout_ctx *context = ctx;
1483 TRACE("iface %p, ctx %p, baseline_origin_x %.8e, baseline_origin_y %.8e, "
1484 "measuring_mode %#x, glyph_run %p, desc %p, effect %p.\n",
1485 iface, ctx, baseline_origin_x, baseline_origin_y,
1486 measuring_mode, glyph_run, desc, effect);
1488 if (desc)
1489 WARN("Ignoring glyph run description %p.\n", desc);
1490 if (effect)
1491 FIXME("Ignoring effect %p.\n", effect);
1492 if (context->options & ~D2D1_DRAW_TEXT_OPTIONS_NO_SNAP)
1493 FIXME("Ignoring options %#x.\n", context->options);
1495 TRACE("%s\n", debugstr_wn(desc->string, desc->stringLength));
1496 ID2D1RenderTarget_DrawGlyphRun(&render_target->ID2D1RenderTarget_iface,
1497 baseline_origin, glyph_run, context->brush, measuring_mode);
1499 return S_OK;
1502 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_DrawUnderline(IDWriteTextRenderer *iface, void *ctx,
1503 float baseline_origin_x, float baseline_origin_y, const DWRITE_UNDERLINE *underline, IUnknown *effect)
1505 FIXME("iface %p, ctx %p, baseline_origin_x %.8e, baseline_origin_y %.8e, underline %p, effect %p stub!\n",
1506 iface, ctx, baseline_origin_x, baseline_origin_y, underline, effect);
1508 return E_NOTIMPL;
1511 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_DrawStrikethrough(IDWriteTextRenderer *iface, void *ctx,
1512 float baseline_origin_x, float baseline_origin_y, const DWRITE_STRIKETHROUGH *strikethrough, IUnknown *effect)
1514 FIXME("iface %p, ctx %p, baseline_origin_x %.8e, baseline_origin_y %.8e, strikethrough %p, effect %p stub!\n",
1515 iface, ctx, baseline_origin_x, baseline_origin_y, strikethrough, effect);
1517 return E_NOTIMPL;
1520 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_DrawInlineObject(IDWriteTextRenderer *iface, void *ctx,
1521 float origin_x, float origin_y, IDWriteInlineObject *object, BOOL is_sideways, BOOL is_rtl, IUnknown *effect)
1523 TRACE("iface %p, ctx %p, origin_x %.8e, origin_y %.8e, object %p, is_sideways %#x, is_rtl %#x, effect %p.\n",
1524 iface, ctx, origin_x, origin_y, object, is_sideways, is_rtl, effect);
1526 return IDWriteInlineObject_Draw(object, ctx, iface, origin_x, origin_y, is_sideways, is_rtl, effect);
1529 static const struct IDWriteTextRendererVtbl d2d_text_renderer_vtbl =
1531 d2d_text_renderer_QueryInterface,
1532 d2d_text_renderer_AddRef,
1533 d2d_text_renderer_Release,
1534 d2d_text_renderer_IsPixelSnappingDisabled,
1535 d2d_text_renderer_GetCurrentTransform,
1536 d2d_text_renderer_GetPixelsPerDip,
1537 d2d_text_renderer_DrawGlyphRun,
1538 d2d_text_renderer_DrawUnderline,
1539 d2d_text_renderer_DrawStrikethrough,
1540 d2d_text_renderer_DrawInlineObject,
1543 HRESULT d2d_d3d_render_target_init(struct d2d_d3d_render_target *render_target, ID2D1Factory *factory,
1544 IDXGISurface *surface, const D2D1_RENDER_TARGET_PROPERTIES *desc)
1546 D3D10_SUBRESOURCE_DATA buffer_data;
1547 D3D10_STATE_BLOCK_MASK state_mask;
1548 DXGI_SURFACE_DESC surface_desc;
1549 D3D10_RASTERIZER_DESC rs_desc;
1550 D3D10_BUFFER_DESC buffer_desc;
1551 D3D10_BLEND_DESC blend_desc;
1552 ID3D10Resource *resource;
1553 unsigned int i, j, k;
1554 HRESULT hr;
1556 static const D3D10_INPUT_ELEMENT_DESC il_desc_triangle[] =
1558 {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0},
1560 static const D3D10_INPUT_ELEMENT_DESC il_desc_bezier[] =
1562 {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0},
1563 {"TEXCOORD", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 8, D3D10_INPUT_PER_VERTEX_DATA, 0},
1565 static const DWORD vs_code_triangle[] =
1567 /* float3x2 transform;
1569 * float4 main(float4 position : POSITION) : SV_POSITION
1571 * return float4(mul(position.xyw, transform), position.zw);
1572 * } */
1573 0x43425844, 0x0add3194, 0x205f74ec, 0xab527fe7, 0xbe6ad704, 0x00000001, 0x00000128, 0x00000003,
1574 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020,
1575 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000f0f, 0x49534f50, 0x4e4f4954, 0xababab00,
1576 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000001, 0x00000003,
1577 0x00000000, 0x0000000f, 0x505f5653, 0x5449534f, 0x004e4f49, 0x52444853, 0x0000008c, 0x00010040,
1578 0x00000023, 0x04000059, 0x00208e46, 0x00000000, 0x00000002, 0x0300005f, 0x001010f2, 0x00000000,
1579 0x04000067, 0x001020f2, 0x00000000, 0x00000001, 0x08000010, 0x00102012, 0x00000000, 0x00101346,
1580 0x00000000, 0x00208246, 0x00000000, 0x00000000, 0x08000010, 0x00102022, 0x00000000, 0x00101346,
1581 0x00000000, 0x00208246, 0x00000000, 0x00000001, 0x05000036, 0x001020c2, 0x00000000, 0x00101ea6,
1582 0x00000000, 0x0100003e,
1584 static const DWORD vs_code_bezier[] =
1586 #if 0
1587 float3x2 transform;
1589 float4 main(float4 position : POSITION,
1590 inout float3 texcoord : TEXCOORD0) : SV_POSITION
1592 return float4(mul(position.xyw, transform), position.zw);
1594 #endif
1595 0x43425844, 0x5e578adb, 0x093f7e27, 0x50d478af, 0xec3dfa4f, 0x00000001, 0x00000198, 0x00000003,
1596 0x0000002c, 0x00000080, 0x000000d8, 0x4e475349, 0x0000004c, 0x00000002, 0x00000008, 0x00000038,
1597 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000f0f, 0x00000041, 0x00000000, 0x00000000,
1598 0x00000003, 0x00000001, 0x00000707, 0x49534f50, 0x4e4f4954, 0x58455400, 0x524f4f43, 0xabab0044,
1599 0x4e47534f, 0x00000050, 0x00000002, 0x00000008, 0x00000038, 0x00000000, 0x00000001, 0x00000003,
1600 0x00000000, 0x0000000f, 0x00000044, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x00000807,
1601 0x505f5653, 0x5449534f, 0x004e4f49, 0x43584554, 0x44524f4f, 0xababab00, 0x52444853, 0x000000b8,
1602 0x00010040, 0x0000002e, 0x04000059, 0x00208e46, 0x00000000, 0x00000002, 0x0300005f, 0x001010f2,
1603 0x00000000, 0x0300005f, 0x00101072, 0x00000001, 0x04000067, 0x001020f2, 0x00000000, 0x00000001,
1604 0x03000065, 0x00102072, 0x00000001, 0x08000010, 0x00102012, 0x00000000, 0x00101346, 0x00000000,
1605 0x00208246, 0x00000000, 0x00000000, 0x08000010, 0x00102022, 0x00000000, 0x00101346, 0x00000000,
1606 0x00208246, 0x00000000, 0x00000001, 0x05000036, 0x001020c2, 0x00000000, 0x00101ea6, 0x00000000,
1607 0x05000036, 0x00102072, 0x00000001, 0x00101246, 0x00000001, 0x0100003e,
1609 static const DWORD ps_code_triangle_solid[] =
1611 /* float4 color;
1613 * float4 main(float4 position : SV_POSITION) : SV_Target
1615 * return color;
1616 * } */
1617 0x43425844, 0x88eefcfd, 0x93d6fd47, 0x173c242f, 0x0106d07a, 0x00000001, 0x000000dc, 0x00000003,
1618 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020,
1619 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x505f5653, 0x5449534f, 0x004e4f49,
1620 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003,
1621 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x00000040, 0x00000040,
1622 0x00000010, 0x04000059, 0x00208e46, 0x00000000, 0x00000001, 0x03000065, 0x001020f2, 0x00000000,
1623 0x06000036, 0x001020f2, 0x00000000, 0x00208e46, 0x00000000, 0x00000000, 0x0100003e,
1625 static const DWORD ps_code_triangle_solid_bitmap[] =
1627 #if 0
1628 float4 color;
1630 float3x2 transform;
1631 float opacity;
1632 bool ignore_alpha;
1634 SamplerState s;
1635 Texture2D t;
1637 float4 main(float4 position : SV_POSITION) : SV_Target
1639 float2 texcoord;
1640 float4 ret;
1642 texcoord.x = position.x * transform._11 + position.y * transform._21 + transform._31;
1643 texcoord.y = position.x * transform._12 + position.y * transform._22 + transform._32;
1644 ret = t.Sample(s, texcoord) * opacity;
1645 if (ignore_alpha)
1646 ret.a = opacity;
1648 return color * ret.a;
1650 #endif
1651 0x43425844, 0x2260a2ae, 0x81907b3e, 0xcaf27063, 0xccb83ef2, 0x00000001, 0x00000208, 0x00000003,
1652 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020,
1653 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000030f, 0x505f5653, 0x5449534f, 0x004e4f49,
1654 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003,
1655 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x0000016c, 0x00000040,
1656 0x0000005b, 0x04000059, 0x00208e46, 0x00000000, 0x00000004, 0x0300005a, 0x00106000, 0x00000000,
1657 0x04001858, 0x00107000, 0x00000000, 0x00005555, 0x04002064, 0x00101032, 0x00000000, 0x00000001,
1658 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000001, 0x0800000f, 0x00100012, 0x00000000,
1659 0x00101046, 0x00000000, 0x00208046, 0x00000000, 0x00000001, 0x08000000, 0x00100012, 0x00000000,
1660 0x0010000a, 0x00000000, 0x0020802a, 0x00000000, 0x00000001, 0x0800000f, 0x00100042, 0x00000000,
1661 0x00101046, 0x00000000, 0x00208046, 0x00000000, 0x00000002, 0x08000000, 0x00100022, 0x00000000,
1662 0x0010002a, 0x00000000, 0x0020802a, 0x00000000, 0x00000002, 0x09000045, 0x001000f2, 0x00000000,
1663 0x00100046, 0x00000000, 0x00107e46, 0x00000000, 0x00106000, 0x00000000, 0x08000038, 0x00100012,
1664 0x00000000, 0x0010003a, 0x00000000, 0x0020803a, 0x00000000, 0x00000002, 0x0b000037, 0x00100012,
1665 0x00000000, 0x0020800a, 0x00000000, 0x00000003, 0x0020803a, 0x00000000, 0x00000002, 0x0010000a,
1666 0x00000000, 0x08000038, 0x001020f2, 0x00000000, 0x00100006, 0x00000000, 0x00208e46, 0x00000000,
1667 0x00000000, 0x0100003e,
1669 static const DWORD ps_code_triangle_bitmap[] =
1671 #if 0
1672 float3x2 transform;
1673 float opacity;
1674 bool ignore_alpha;
1676 SamplerState s;
1677 Texture2D t;
1679 float4 main(float4 position : SV_POSITION) : SV_Target
1681 float2 texcoord;
1682 float4 ret;
1684 texcoord.x = position.x * transform._11 + position.y * transform._21 + transform._31;
1685 texcoord.y = position.x * transform._12 + position.y * transform._22 + transform._32;
1686 ret = t.Sample(s, texcoord) * opacity;
1687 if (ignore_alpha)
1688 ret.a = opacity;
1690 return ret;
1692 #endif
1693 0x43425844, 0xf5bb1e01, 0xe3386963, 0xcaa095bd, 0xea2887de, 0x00000001, 0x000001fc, 0x00000003,
1694 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020,
1695 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000030f, 0x505f5653, 0x5449534f, 0x004e4f49,
1696 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003,
1697 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x00000160, 0x00000040,
1698 0x00000058, 0x04000059, 0x00208e46, 0x00000000, 0x00000003, 0x0300005a, 0x00106000, 0x00000000,
1699 0x04001858, 0x00107000, 0x00000000, 0x00005555, 0x04002064, 0x00101032, 0x00000000, 0x00000001,
1700 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000001, 0x0800000f, 0x00100012, 0x00000000,
1701 0x00101046, 0x00000000, 0x00208046, 0x00000000, 0x00000000, 0x08000000, 0x00100012, 0x00000000,
1702 0x0010000a, 0x00000000, 0x0020802a, 0x00000000, 0x00000000, 0x0800000f, 0x00100042, 0x00000000,
1703 0x00101046, 0x00000000, 0x00208046, 0x00000000, 0x00000001, 0x08000000, 0x00100022, 0x00000000,
1704 0x0010002a, 0x00000000, 0x0020802a, 0x00000000, 0x00000001, 0x09000045, 0x001000f2, 0x00000000,
1705 0x00100046, 0x00000000, 0x00107e46, 0x00000000, 0x00106000, 0x00000000, 0x08000038, 0x001000f2,
1706 0x00000000, 0x00100e46, 0x00000000, 0x00208ff6, 0x00000000, 0x00000001, 0x0b000037, 0x00102082,
1707 0x00000000, 0x0020800a, 0x00000000, 0x00000002, 0x0020803a, 0x00000000, 0x00000001, 0x0010003a,
1708 0x00000000, 0x05000036, 0x00102072, 0x00000000, 0x00100246, 0x00000000, 0x0100003e,
1710 static const DWORD ps_code_triangle_bitmap_solid[] =
1712 #if 0
1713 float3x2 transform;
1714 float opacity;
1715 bool ignore_alpha;
1717 float4 color;
1719 SamplerState s;
1720 Texture2D t;
1722 float4 main(float4 position : SV_POSITION) : SV_Target
1724 float2 texcoord;
1725 float4 ret;
1727 texcoord.x = position.x * transform._11 + position.y * transform._21 + transform._31;
1728 texcoord.y = position.x * transform._12 + position.y * transform._22 + transform._32;
1729 ret = t.Sample(s, texcoord) * opacity;
1730 if (ignore_alpha)
1731 ret.a = opacity;
1733 return ret * color.a;
1735 #endif
1736 0x43425844, 0x45447736, 0x63a6dd80, 0x1778fc71, 0x1e6d322e, 0x00000001, 0x00000208, 0x00000003,
1737 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020,
1738 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000030f, 0x505f5653, 0x5449534f, 0x004e4f49,
1739 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003,
1740 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x0000016c, 0x00000040,
1741 0x0000005b, 0x04000059, 0x00208e46, 0x00000000, 0x00000004, 0x0300005a, 0x00106000, 0x00000000,
1742 0x04001858, 0x00107000, 0x00000000, 0x00005555, 0x04002064, 0x00101032, 0x00000000, 0x00000001,
1743 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000001, 0x0800000f, 0x00100012, 0x00000000,
1744 0x00101046, 0x00000000, 0x00208046, 0x00000000, 0x00000000, 0x08000000, 0x00100012, 0x00000000,
1745 0x0010000a, 0x00000000, 0x0020802a, 0x00000000, 0x00000000, 0x0800000f, 0x00100042, 0x00000000,
1746 0x00101046, 0x00000000, 0x00208046, 0x00000000, 0x00000001, 0x08000000, 0x00100022, 0x00000000,
1747 0x0010002a, 0x00000000, 0x0020802a, 0x00000000, 0x00000001, 0x09000045, 0x001000f2, 0x00000000,
1748 0x00100046, 0x00000000, 0x00107e46, 0x00000000, 0x00106000, 0x00000000, 0x08000038, 0x001000f2,
1749 0x00000000, 0x00100e46, 0x00000000, 0x00208ff6, 0x00000000, 0x00000001, 0x0b000037, 0x00100082,
1750 0x00000000, 0x0020800a, 0x00000000, 0x00000002, 0x0020803a, 0x00000000, 0x00000001, 0x0010003a,
1751 0x00000000, 0x08000038, 0x001020f2, 0x00000000, 0x00100e46, 0x00000000, 0x00208ff6, 0x00000000,
1752 0x00000003, 0x0100003e,
1754 static const DWORD ps_code_triangle_bitmap_bitmap[] =
1756 #if 0
1757 struct brush
1759 float3x2 transform;
1760 float opacity;
1761 bool ignore_alpha;
1762 } brush0, brush1;
1764 SamplerState s0, s1;
1765 Texture2D t0, t1;
1767 float4 main(float4 position : SV_POSITION) : SV_Target
1769 float2 texcoord;
1770 float opacity;
1771 float4 ret;
1773 texcoord.x = position.x * brush0.transform._11 + position.y * brush0.transform._21 + brush0.transform._31;
1774 texcoord.y = position.x * brush0.transform._12 + position.y * brush0.transform._22 + brush0.transform._32;
1775 ret = t0.Sample(s0, texcoord) * brush0.opacity;
1776 if (brush0.ignore_alpha)
1777 ret.a = brush0.opacity;
1779 texcoord.x = position.x * brush1.transform._11 + position.y * brush1.transform._21 + brush1.transform._31;
1780 texcoord.y = position.x * brush1.transform._12 + position.y * brush1.transform._22 + brush1.transform._32;
1781 opacity = t1.Sample(s1, texcoord).a * brush1.opacity;
1782 if (brush1.ignore_alpha)
1783 opacity = brush1.opacity;
1785 return ret * opacity;
1787 #endif
1788 0x43425844, 0x8eee6bfc, 0x57b72708, 0xa0f7c086, 0x867c11ec, 0x00000001, 0x00000310, 0x00000003,
1789 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020,
1790 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000030f, 0x505f5653, 0x5449534f, 0x004e4f49,
1791 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003,
1792 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x00000274, 0x00000040,
1793 0x0000009d, 0x04000059, 0x00208e46, 0x00000000, 0x00000006, 0x0300005a, 0x00106000, 0x00000000,
1794 0x0300005a, 0x00106000, 0x00000001, 0x04001858, 0x00107000, 0x00000000, 0x00005555, 0x04001858,
1795 0x00107000, 0x00000001, 0x00005555, 0x04002064, 0x00101032, 0x00000000, 0x00000001, 0x03000065,
1796 0x001020f2, 0x00000000, 0x02000068, 0x00000002, 0x0800000f, 0x00100012, 0x00000000, 0x00101046,
1797 0x00000000, 0x00208046, 0x00000000, 0x00000003, 0x08000000, 0x00100012, 0x00000000, 0x0010000a,
1798 0x00000000, 0x0020802a, 0x00000000, 0x00000003, 0x0800000f, 0x00100042, 0x00000000, 0x00101046,
1799 0x00000000, 0x00208046, 0x00000000, 0x00000004, 0x08000000, 0x00100022, 0x00000000, 0x0010002a,
1800 0x00000000, 0x0020802a, 0x00000000, 0x00000004, 0x09000045, 0x001000f2, 0x00000000, 0x00100046,
1801 0x00000000, 0x00107e46, 0x00000001, 0x00106000, 0x00000001, 0x08000038, 0x00100012, 0x00000000,
1802 0x0010003a, 0x00000000, 0x0020803a, 0x00000000, 0x00000004, 0x0b000037, 0x00100012, 0x00000000,
1803 0x0020800a, 0x00000000, 0x00000005, 0x0020803a, 0x00000000, 0x00000004, 0x0010000a, 0x00000000,
1804 0x0800000f, 0x00100022, 0x00000000, 0x00101046, 0x00000000, 0x00208046, 0x00000000, 0x00000000,
1805 0x08000000, 0x00100012, 0x00000001, 0x0010001a, 0x00000000, 0x0020802a, 0x00000000, 0x00000000,
1806 0x0800000f, 0x00100022, 0x00000000, 0x00101046, 0x00000000, 0x00208046, 0x00000000, 0x00000001,
1807 0x08000000, 0x00100022, 0x00000001, 0x0010001a, 0x00000000, 0x0020802a, 0x00000000, 0x00000001,
1808 0x09000045, 0x001000f2, 0x00000001, 0x00100046, 0x00000001, 0x00107e46, 0x00000000, 0x00106000,
1809 0x00000000, 0x08000038, 0x001000f2, 0x00000001, 0x00100e46, 0x00000001, 0x00208ff6, 0x00000000,
1810 0x00000001, 0x0b000037, 0x00100082, 0x00000001, 0x0020800a, 0x00000000, 0x00000002, 0x0020803a,
1811 0x00000000, 0x00000001, 0x0010003a, 0x00000001, 0x07000038, 0x001020f2, 0x00000000, 0x00100006,
1812 0x00000000, 0x00100e46, 0x00000001, 0x0100003e,
1814 /* The basic idea here is to evaluate the implicit form of the curve in
1815 * texture space. "t.z" determines which side of the curve is shaded. */
1816 static const DWORD ps_code_bezier_solid[] =
1818 #if 0
1819 float4 color;
1821 float4 main(float4 position : SV_POSITION, float3 t : TEXCOORD0) : SV_Target
1823 clip((t.x * t.x - t.y) * t.z);
1824 return color;
1826 #endif
1827 0x43425844, 0x66075f9e, 0x2ffe405b, 0xb551ee63, 0xa0d9f457, 0x00000001, 0x00000180, 0x00000003,
1828 0x0000002c, 0x00000084, 0x000000b8, 0x4e475349, 0x00000050, 0x00000002, 0x00000008, 0x00000038,
1829 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x00000044, 0x00000000, 0x00000000,
1830 0x00000003, 0x00000001, 0x00000707, 0x505f5653, 0x5449534f, 0x004e4f49, 0x43584554, 0x44524f4f,
1831 0xababab00, 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000,
1832 0x00000003, 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x000000c0,
1833 0x00000040, 0x00000030, 0x04000059, 0x00208e46, 0x00000000, 0x00000001, 0x03001062, 0x00101072,
1834 0x00000001, 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000001, 0x0a000032, 0x00100012,
1835 0x00000000, 0x0010100a, 0x00000001, 0x0010100a, 0x00000001, 0x8010101a, 0x00000041, 0x00000001,
1836 0x07000038, 0x00100012, 0x00000000, 0x0010000a, 0x00000000, 0x0010102a, 0x00000001, 0x07000031,
1837 0x00100012, 0x00000000, 0x0010000a, 0x00000000, 0x00004001, 0x00000000, 0x0304000d, 0x0010000a,
1838 0x00000000, 0x06000036, 0x001020f2, 0x00000000, 0x00208e46, 0x00000000, 0x00000000, 0x0100003e,
1840 static const struct brush_shader
1842 const void *byte_code;
1843 size_t byte_code_size;
1844 enum d2d_shape_type shape_type;
1845 enum d2d_brush_type brush_type;
1846 enum d2d_brush_type opacity_brush_type;
1848 brush_shaders[] =
1850 {ps_code_triangle_solid, sizeof(ps_code_triangle_solid),
1851 D2D_SHAPE_TYPE_TRIANGLE, D2D_BRUSH_TYPE_SOLID, D2D_BRUSH_TYPE_COUNT},
1852 {ps_code_triangle_solid_bitmap, sizeof(ps_code_triangle_solid_bitmap),
1853 D2D_SHAPE_TYPE_TRIANGLE, D2D_BRUSH_TYPE_SOLID, D2D_BRUSH_TYPE_BITMAP},
1854 {ps_code_triangle_bitmap, sizeof(ps_code_triangle_bitmap),
1855 D2D_SHAPE_TYPE_TRIANGLE, D2D_BRUSH_TYPE_BITMAP, D2D_BRUSH_TYPE_COUNT},
1856 {ps_code_triangle_bitmap_solid, sizeof(ps_code_triangle_bitmap_solid),
1857 D2D_SHAPE_TYPE_TRIANGLE, D2D_BRUSH_TYPE_BITMAP, D2D_BRUSH_TYPE_SOLID},
1858 {ps_code_triangle_bitmap_bitmap, sizeof(ps_code_triangle_bitmap_bitmap),
1859 D2D_SHAPE_TYPE_TRIANGLE, D2D_BRUSH_TYPE_BITMAP, D2D_BRUSH_TYPE_BITMAP},
1860 {ps_code_bezier_solid, sizeof(ps_code_bezier_solid),
1861 D2D_SHAPE_TYPE_BEZIER, D2D_BRUSH_TYPE_SOLID, D2D_BRUSH_TYPE_COUNT},
1863 static const struct
1865 float x, y;
1867 quad[] =
1869 {-1.0f, 1.0f},
1870 {-1.0f, -1.0f},
1871 { 1.0f, 1.0f},
1872 { 1.0f, -1.0f},
1874 static const UINT16 indices[] = {0, 1, 2, 2, 1, 3};
1875 static const D2D1_MATRIX_3X2_F identity =
1877 1.0f, 0.0f,
1878 0.0f, 1.0f,
1879 0.0f, 0.0f,
1882 if (desc->type != D2D1_RENDER_TARGET_TYPE_DEFAULT && desc->type != D2D1_RENDER_TARGET_TYPE_HARDWARE)
1883 WARN("Ignoring render target type %#x.\n", desc->type);
1884 if (desc->usage != D2D1_RENDER_TARGET_USAGE_NONE)
1885 FIXME("Ignoring render target usage %#x.\n", desc->usage);
1886 if (desc->minLevel != D2D1_FEATURE_LEVEL_DEFAULT)
1887 WARN("Ignoring feature level %#x.\n", desc->minLevel);
1889 render_target->ID2D1RenderTarget_iface.lpVtbl = &d2d_d3d_render_target_vtbl;
1890 render_target->IDWriteTextRenderer_iface.lpVtbl = &d2d_text_renderer_vtbl;
1891 render_target->refcount = 1;
1892 render_target->factory = factory;
1893 ID2D1Factory_AddRef(render_target->factory);
1895 if (FAILED(hr = IDXGISurface_GetDevice(surface, &IID_ID3D10Device, (void **)&render_target->device)))
1897 WARN("Failed to get device interface, hr %#x.\n", hr);
1898 ID2D1Factory_Release(render_target->factory);
1899 return hr;
1902 if (FAILED(hr = IDXGISurface_QueryInterface(surface, &IID_ID3D10Resource, (void **)&resource)))
1904 WARN("Failed to get ID3D10Resource interface, hr %#x.\n", hr);
1905 goto err;
1908 hr = ID3D10Device_CreateRenderTargetView(render_target->device, resource, NULL, &render_target->view);
1909 ID3D10Resource_Release(resource);
1910 if (FAILED(hr))
1912 WARN("Failed to create rendertarget view, hr %#x.\n", hr);
1913 goto err;
1916 if (FAILED(hr = D3D10StateBlockMaskEnableAll(&state_mask)))
1918 WARN("Failed to create stateblock mask, hr %#x.\n", hr);
1919 goto err;
1922 if (FAILED(hr = D3D10CreateStateBlock(render_target->device, &state_mask, &render_target->stateblock)))
1924 WARN("Failed to create stateblock, hr %#x.\n", hr);
1925 goto err;
1928 if (FAILED(hr = ID3D10Device_CreateInputLayout(render_target->device, il_desc_triangle,
1929 sizeof(il_desc_triangle) / sizeof(*il_desc_triangle), vs_code_triangle, sizeof(vs_code_triangle),
1930 &render_target->shape_resources[D2D_SHAPE_TYPE_TRIANGLE].il)))
1932 WARN("Failed to create triangle input layout, hr %#x.\n", hr);
1933 goto err;
1936 if (FAILED(hr = ID3D10Device_CreateInputLayout(render_target->device, il_desc_bezier,
1937 sizeof(il_desc_bezier) / sizeof(*il_desc_bezier), vs_code_bezier, sizeof(vs_code_bezier),
1938 &render_target->shape_resources[D2D_SHAPE_TYPE_BEZIER].il)))
1940 WARN("Failed to create bezier input layout, hr %#x.\n", hr);
1941 goto err;
1944 if (FAILED(hr = ID3D10Device_CreateVertexShader(render_target->device, vs_code_triangle,
1945 sizeof(vs_code_triangle), &render_target->shape_resources[D2D_SHAPE_TYPE_TRIANGLE].vs)))
1947 WARN("Failed to create triangle vertex shader, hr %#x.\n", hr);
1948 goto err;
1951 if (FAILED(hr = ID3D10Device_CreateVertexShader(render_target->device, vs_code_bezier,
1952 sizeof(vs_code_bezier), &render_target->shape_resources[D2D_SHAPE_TYPE_BEZIER].vs)))
1954 WARN("Failed to create bezier vertex shader, hr %#x.\n", hr);
1955 goto err;
1958 for (i = 0; i < sizeof(brush_shaders) / sizeof(*brush_shaders); ++i)
1960 const struct brush_shader *bs = &brush_shaders[i];
1961 if (FAILED(hr = ID3D10Device_CreatePixelShader(render_target->device, bs->byte_code, bs->byte_code_size,
1962 &render_target->shape_resources[bs->shape_type].ps[bs->brush_type][bs->opacity_brush_type])))
1964 WARN("Failed to create pixel shader for shape type %#x and brush types %#x/%#x.\n",
1965 bs->shape_type, bs->brush_type, bs->opacity_brush_type);
1966 goto err;
1970 buffer_desc.ByteWidth = sizeof(indices);
1971 buffer_desc.Usage = D3D10_USAGE_DEFAULT;
1972 buffer_desc.BindFlags = D3D10_BIND_INDEX_BUFFER;
1973 buffer_desc.CPUAccessFlags = 0;
1974 buffer_desc.MiscFlags = 0;
1976 buffer_data.pSysMem = indices;
1977 buffer_data.SysMemPitch = 0;
1978 buffer_data.SysMemSlicePitch = 0;
1980 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device,
1981 &buffer_desc, &buffer_data, &render_target->ib)))
1983 WARN("Failed to create clear index buffer, hr %#x.\n", hr);
1984 goto err;
1987 buffer_desc.ByteWidth = sizeof(quad);
1988 buffer_desc.BindFlags = D3D10_BIND_VERTEX_BUFFER;
1989 buffer_data.pSysMem = quad;
1991 render_target->vb_stride = sizeof(*quad);
1992 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device,
1993 &buffer_desc, &buffer_data, &render_target->vb)))
1995 WARN("Failed to create clear vertex buffer, hr %#x.\n", hr);
1996 goto err;
1999 rs_desc.FillMode = D3D10_FILL_SOLID;
2000 rs_desc.CullMode = D3D10_CULL_NONE;
2001 rs_desc.FrontCounterClockwise = FALSE;
2002 rs_desc.DepthBias = 0;
2003 rs_desc.DepthBiasClamp = 0.0f;
2004 rs_desc.SlopeScaledDepthBias = 0.0f;
2005 rs_desc.DepthClipEnable = TRUE;
2006 rs_desc.ScissorEnable = TRUE;
2007 rs_desc.MultisampleEnable = FALSE;
2008 rs_desc.AntialiasedLineEnable = FALSE;
2009 if (FAILED(hr = ID3D10Device_CreateRasterizerState(render_target->device, &rs_desc, &render_target->rs)))
2011 WARN("Failed to create clear rasterizer state, hr %#x.\n", hr);
2012 goto err;
2015 memset(&blend_desc, 0, sizeof(blend_desc));
2016 blend_desc.BlendEnable[0] = TRUE;
2017 blend_desc.SrcBlend = D3D10_BLEND_ONE;
2018 blend_desc.DestBlend = D3D10_BLEND_INV_SRC_ALPHA;
2019 blend_desc.BlendOp = D3D10_BLEND_OP_ADD;
2020 if (desc->pixelFormat.alphaMode == D2D1_ALPHA_MODE_IGNORE)
2022 blend_desc.SrcBlendAlpha = D3D10_BLEND_ZERO;
2023 blend_desc.DestBlendAlpha = D3D10_BLEND_ONE;
2025 else
2027 blend_desc.SrcBlendAlpha = D3D10_BLEND_ONE;
2028 blend_desc.DestBlendAlpha = D3D10_BLEND_INV_SRC_ALPHA;
2030 blend_desc.BlendOpAlpha = D3D10_BLEND_OP_ADD;
2031 blend_desc.RenderTargetWriteMask[0] = D3D10_COLOR_WRITE_ENABLE_ALL;
2032 if (FAILED(hr = ID3D10Device_CreateBlendState(render_target->device, &blend_desc, &render_target->bs)))
2034 WARN("Failed to create blend state, hr %#x.\n", hr);
2035 goto err;
2038 if (FAILED(hr = IDXGISurface_GetDesc(surface, &surface_desc)))
2040 WARN("Failed to get surface desc, hr %#x.\n", hr);
2041 goto err;
2044 render_target->format = desc->pixelFormat;
2045 render_target->pixel_size.width = surface_desc.Width;
2046 render_target->pixel_size.height = surface_desc.Height;
2047 render_target->drawing_state.transform = identity;
2049 if (!d2d_clip_stack_init(&render_target->clip_stack))
2051 WARN("Failed to initialize clip stack.\n");
2052 hr = E_FAIL;
2053 goto err;
2056 render_target->dpi_x = desc->dpiX;
2057 render_target->dpi_y = desc->dpiY;
2059 if (render_target->dpi_x == 0.0f && render_target->dpi_y == 0.0f)
2061 render_target->dpi_x = 96.0f;
2062 render_target->dpi_y = 96.0f;
2065 return S_OK;
2067 err:
2068 if (render_target->bs)
2069 ID3D10BlendState_Release(render_target->bs);
2070 if (render_target->rs)
2071 ID3D10RasterizerState_Release(render_target->rs);
2072 if (render_target->vb)
2073 ID3D10Buffer_Release(render_target->vb);
2074 if (render_target->ib)
2075 ID3D10Buffer_Release(render_target->ib);
2076 for (i = 0; i < D2D_SHAPE_TYPE_COUNT; ++i)
2078 for (j = 0; j < D2D_BRUSH_TYPE_COUNT; ++j)
2080 for (k = 0; k < D2D_BRUSH_TYPE_COUNT + 1; ++k)
2082 if (render_target->shape_resources[i].ps[j][k])
2083 ID3D10PixelShader_Release(render_target->shape_resources[i].ps[j][k]);
2086 if (render_target->shape_resources[i].vs)
2087 ID3D10VertexShader_Release(render_target->shape_resources[i].vs);
2088 if (render_target->shape_resources[i].il)
2089 ID3D10InputLayout_Release(render_target->shape_resources[i].il);
2091 if (render_target->stateblock)
2092 render_target->stateblock->lpVtbl->Release(render_target->stateblock);
2093 if (render_target->view)
2094 ID3D10RenderTargetView_Release(render_target->view);
2095 if (render_target->device)
2096 ID3D10Device_Release(render_target->device);
2097 ID2D1Factory_Release(render_target->factory);
2098 return hr;