wined3d: Shadow format flags in wined3d_rendertarget_view.
[wine.git] / dlls / d2d1 / render_target.c
blobcdf82bf35c51e4a5896695ccbbb0638a491fb368
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_matrix_multiply(D2D_MATRIX_3X2_F *a, const D2D_MATRIX_3X2_F *b)
37 D2D_MATRIX_3X2_F tmp = *a;
39 a->_11 = tmp._11 * b->_11 + tmp._12 * b->_21;
40 a->_12 = tmp._11 * b->_12 + tmp._12 * b->_22;
41 a->_21 = tmp._21 * b->_11 + tmp._22 * b->_21;
42 a->_22 = tmp._21 * b->_12 + tmp._22 * b->_22;
43 a->_31 = tmp._31 * b->_11 + tmp._32 * b->_21 + b->_31;
44 a->_32 = tmp._31 * b->_12 + tmp._32 * b->_22 + b->_32;
47 static void d2d_point_transform(D2D1_POINT_2F *dst, const D2D1_MATRIX_3X2_F *matrix, float x, float y)
49 dst->x = x * matrix->_11 + y * matrix->_21 + matrix->_31;
50 dst->y = x * matrix->_12 + y * matrix->_22 + matrix->_32;
53 static void d2d_rect_expand(D2D1_RECT_F *dst, const D2D1_POINT_2F *point)
55 if (point->x < dst->left)
56 dst->left = point->x;
57 if (point->y < dst->top)
58 dst->top = point->y;
59 if (point->x > dst->right)
60 dst->right = point->x;
61 if (point->y > dst->bottom)
62 dst->bottom = point->y;
65 static void d2d_rect_intersect(D2D1_RECT_F *dst, const D2D1_RECT_F *src)
67 if (src->left > dst->left)
68 dst->left = src->left;
69 if (src->top > dst->top)
70 dst->top = src->top;
71 if (src->right < dst->right)
72 dst->right = src->right;
73 if (src->bottom < dst->bottom)
74 dst->bottom = src->bottom;
77 static void d2d_rect_set(D2D1_RECT_F *dst, float left, float top, float right, float bottom)
79 dst->left = left;
80 dst->top = top;
81 dst->right = right;
82 dst->bottom = bottom;
85 static BOOL d2d_clip_stack_init(struct d2d_clip_stack *stack)
87 if (!(stack->stack = HeapAlloc(GetProcessHeap(), 0, INITIAL_CLIP_STACK_SIZE * sizeof(*stack->stack))))
88 return FALSE;
90 stack->size = INITIAL_CLIP_STACK_SIZE;
91 stack->count = 0;
93 return TRUE;
96 static void d2d_clip_stack_cleanup(struct d2d_clip_stack *stack)
98 HeapFree(GetProcessHeap(), 0, stack->stack);
101 static BOOL d2d_clip_stack_push(struct d2d_clip_stack *stack, const D2D1_RECT_F *rect)
103 D2D1_RECT_F r;
105 if (stack->count == stack->size)
107 D2D1_RECT_F *new_stack;
108 unsigned int new_size;
110 if (stack->size > UINT_MAX / 2)
111 return FALSE;
113 new_size = stack->size * 2;
114 if (!(new_stack = HeapReAlloc(GetProcessHeap(), 0, stack->stack, new_size * sizeof(*stack->stack))))
115 return FALSE;
117 stack->stack = new_stack;
118 stack->size = new_size;
121 r = *rect;
122 if (stack->count)
123 d2d_rect_intersect(&r, &stack->stack[stack->count - 1]);
124 stack->stack[stack->count++] = r;
126 return TRUE;
129 static void d2d_clip_stack_pop(struct d2d_clip_stack *stack)
131 if (!stack->count)
132 return;
133 --stack->count;
136 static void d2d_draw(struct d2d_d3d_render_target *render_target, ID3D10Buffer *vs_cb,
137 ID3D10PixelShader *ps, ID3D10Buffer *ps_cb, struct d2d_brush *brush)
139 ID3D10Device *device = render_target->device;
140 unsigned int offset;
141 D3D10_VIEWPORT vp;
142 HRESULT hr;
143 static const float blend_factor[] = {1.0f, 1.0f, 1.0f, 1.0f};
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, render_target->il);
161 ID3D10Device_IASetPrimitiveTopology(device, D3D10_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
162 offset = 0;
163 ID3D10Device_IASetVertexBuffers(device, 0, 1, &render_target->vb,
164 &render_target->vb_stride, &offset);
165 ID3D10Device_VSSetConstantBuffers(device, 0, 1, &vs_cb);
166 ID3D10Device_VSSetShader(device, render_target->vs);
167 ID3D10Device_PSSetConstantBuffers(device, 0, 1, &ps_cb);
168 ID3D10Device_PSSetShader(device, ps);
169 ID3D10Device_RSSetViewports(device, 1, &vp);
170 if (render_target->clip_stack.count)
172 const D2D1_RECT_F *clip_rect;
173 D3D10_RECT scissor_rect;
175 clip_rect = &render_target->clip_stack.stack[render_target->clip_stack.count - 1];
176 scissor_rect.left = clip_rect->left + 0.5f;
177 scissor_rect.top = clip_rect->top + 0.5f;
178 scissor_rect.right = clip_rect->right + 0.5f;
179 scissor_rect.bottom = clip_rect->bottom + 0.5f;
180 ID3D10Device_RSSetScissorRects(device, 1, &scissor_rect);
181 ID3D10Device_RSSetState(device, render_target->rs);
183 ID3D10Device_OMSetRenderTargets(device, 1, &render_target->view, NULL);
184 if (brush)
186 ID3D10Device_OMSetBlendState(device, render_target->bs, blend_factor, D3D10_DEFAULT_SAMPLE_MASK);
187 d2d_brush_bind_resources(brush, device);
190 ID3D10Device_Draw(device, 4, 0);
192 if (FAILED(hr = render_target->stateblock->lpVtbl->Apply(render_target->stateblock)))
193 WARN("Failed to apply stateblock, hr %#x.\n", hr);
196 static inline struct d2d_d3d_render_target *impl_from_ID2D1RenderTarget(ID2D1RenderTarget *iface)
198 return CONTAINING_RECORD(iface, struct d2d_d3d_render_target, ID2D1RenderTarget_iface);
201 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_QueryInterface(ID2D1RenderTarget *iface, REFIID iid, void **out)
203 TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
205 if (IsEqualGUID(iid, &IID_ID2D1RenderTarget)
206 || IsEqualGUID(iid, &IID_ID2D1Resource)
207 || IsEqualGUID(iid, &IID_IUnknown))
209 ID2D1RenderTarget_AddRef(iface);
210 *out = iface;
211 return S_OK;
214 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
216 *out = NULL;
217 return E_NOINTERFACE;
220 static ULONG STDMETHODCALLTYPE d2d_d3d_render_target_AddRef(ID2D1RenderTarget *iface)
222 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
223 ULONG refcount = InterlockedIncrement(&render_target->refcount);
225 TRACE("%p increasing refcount to %u.\n", iface, refcount);
227 return refcount;
230 static ULONG STDMETHODCALLTYPE d2d_d3d_render_target_Release(ID2D1RenderTarget *iface)
232 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
233 ULONG refcount = InterlockedDecrement(&render_target->refcount);
235 TRACE("%p decreasing refcount to %u.\n", iface, refcount);
237 if (!refcount)
239 d2d_clip_stack_cleanup(&render_target->clip_stack);
240 if (render_target->text_rendering_params)
241 IDWriteRenderingParams_Release(render_target->text_rendering_params);
242 ID3D10PixelShader_Release(render_target->rect_bitmap_ps);
243 ID3D10PixelShader_Release(render_target->rect_solid_ps);
244 ID3D10BlendState_Release(render_target->bs);
245 ID3D10RasterizerState_Release(render_target->rs);
246 ID3D10VertexShader_Release(render_target->vs);
247 ID3D10Buffer_Release(render_target->vb);
248 ID3D10InputLayout_Release(render_target->il);
249 render_target->stateblock->lpVtbl->Release(render_target->stateblock);
250 ID3D10RenderTargetView_Release(render_target->view);
251 ID3D10Device_Release(render_target->device);
252 ID2D1Factory_Release(render_target->factory);
253 HeapFree(GetProcessHeap(), 0, render_target);
256 return refcount;
259 static void STDMETHODCALLTYPE d2d_d3d_render_target_GetFactory(ID2D1RenderTarget *iface, ID2D1Factory **factory)
261 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
263 TRACE("iface %p, factory %p.\n", iface, factory);
265 *factory = render_target->factory;
266 ID2D1Factory_AddRef(*factory);
269 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateBitmap(ID2D1RenderTarget *iface,
270 D2D1_SIZE_U size, const void *src_data, UINT32 pitch, const D2D1_BITMAP_PROPERTIES *desc, ID2D1Bitmap **bitmap)
272 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
273 struct d2d_bitmap *object;
274 HRESULT hr;
276 TRACE("iface %p, size {%u, %u}, src_data %p, pitch %u, desc %p, bitmap %p.\n",
277 iface, size.width, size.height, src_data, pitch, desc, bitmap);
279 if (!(object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object))))
280 return E_OUTOFMEMORY;
282 if (FAILED(hr = d2d_bitmap_init(object, render_target, size, src_data, pitch, desc)))
284 WARN("Failed to initialize bitmap, hr %#x.\n", hr);
285 HeapFree(GetProcessHeap(), 0, object);
286 return hr;
289 TRACE("Created bitmap %p.\n", object);
290 *bitmap = &object->ID2D1Bitmap_iface;
292 return S_OK;
295 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateBitmapFromWicBitmap(ID2D1RenderTarget *iface,
296 IWICBitmapSource *bitmap_source, const D2D1_BITMAP_PROPERTIES *desc, ID2D1Bitmap **bitmap)
298 D2D1_BITMAP_PROPERTIES bitmap_desc;
299 unsigned int bpp, data_size;
300 D2D1_SIZE_U size;
301 WICRect rect;
302 UINT32 pitch;
303 HRESULT hr;
304 void *data;
306 TRACE("iface %p, bitmap_source %p, desc %p, bitmap %p.\n",
307 iface, bitmap_source, desc, bitmap);
309 if (FAILED(hr = IWICBitmapSource_GetSize(bitmap_source, &size.width, &size.height)))
311 WARN("Failed to get bitmap size, hr %#x.\n", hr);
312 return hr;
315 if (!desc)
317 bitmap_desc.pixelFormat.format = DXGI_FORMAT_UNKNOWN;
318 bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_UNKNOWN;
319 bitmap_desc.dpiX = 0.0f;
320 bitmap_desc.dpiY = 0.0f;
322 else
324 bitmap_desc = *desc;
327 if (bitmap_desc.pixelFormat.format == DXGI_FORMAT_UNKNOWN)
329 WICPixelFormatGUID wic_format;
331 if (FAILED(hr = IWICBitmapSource_GetPixelFormat(bitmap_source, &wic_format)))
333 WARN("Failed to get bitmap format, hr %#x.\n", hr);
334 return hr;
337 if (IsEqualGUID(&wic_format, &GUID_WICPixelFormat32bppPBGRA)
338 || IsEqualGUID(&wic_format, &GUID_WICPixelFormat32bppBGR))
340 bitmap_desc.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM;
342 else
344 WARN("Unsupported WIC bitmap format %s.\n", debugstr_guid(&wic_format));
345 return D2DERR_UNSUPPORTED_PIXEL_FORMAT;
349 switch (bitmap_desc.pixelFormat.format)
351 case DXGI_FORMAT_B8G8R8A8_UNORM:
352 bpp = 4;
353 break;
355 default:
356 FIXME("Unhandled format %#x.\n", bitmap_desc.pixelFormat.format);
357 return D2DERR_UNSUPPORTED_PIXEL_FORMAT;
360 pitch = ((bpp * size.width) + 15) & ~15;
361 data_size = pitch * size.height;
362 if (!(data = HeapAlloc(GetProcessHeap(), 0, data_size)))
363 return E_OUTOFMEMORY;
365 rect.X = 0;
366 rect.Y = 0;
367 rect.Width = size.width;
368 rect.Height = size.height;
369 if (FAILED(hr = IWICBitmapSource_CopyPixels(bitmap_source, &rect, pitch, data_size, data)))
371 WARN("Failed to copy bitmap pixels, hr %#x.\n", hr);
372 HeapFree(GetProcessHeap(), 0, data);
373 return hr;
376 hr = d2d_d3d_render_target_CreateBitmap(iface, size, data, pitch, &bitmap_desc, bitmap);
378 HeapFree(GetProcessHeap(), 0, data);
380 return hr;
383 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateSharedBitmap(ID2D1RenderTarget *iface,
384 REFIID iid, void *data, const D2D1_BITMAP_PROPERTIES *desc, ID2D1Bitmap **bitmap)
386 FIXME("iface %p, iid %s, data %p, desc %p, bitmap %p stub!\n",
387 iface, debugstr_guid(iid), data, desc, bitmap);
389 return E_NOTIMPL;
392 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateBitmapBrush(ID2D1RenderTarget *iface,
393 ID2D1Bitmap *bitmap, const D2D1_BITMAP_BRUSH_PROPERTIES *bitmap_brush_desc,
394 const D2D1_BRUSH_PROPERTIES *brush_desc, ID2D1BitmapBrush **brush)
396 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
397 struct d2d_brush *object;
398 HRESULT hr;
400 TRACE("iface %p, bitmap %p, bitmap_brush_desc %p, brush_desc %p, brush %p.\n",
401 iface, bitmap, bitmap_brush_desc, brush_desc, brush);
403 if (!(object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object))))
404 return E_OUTOFMEMORY;
406 if (FAILED(hr = d2d_bitmap_brush_init(object, render_target, bitmap, bitmap_brush_desc, brush_desc)))
408 WARN("Failed to initialize brush, hr %#x.\n", hr);
409 HeapFree(GetProcessHeap(), 0, object);
410 return hr;
413 TRACE("Created brush %p.\n", object);
414 *brush = (ID2D1BitmapBrush *)&object->ID2D1Brush_iface;
416 return S_OK;
419 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateSolidColorBrush(ID2D1RenderTarget *iface,
420 const D2D1_COLOR_F *color, const D2D1_BRUSH_PROPERTIES *desc, ID2D1SolidColorBrush **brush)
422 struct d2d_brush *object;
424 TRACE("iface %p, color %p, desc %p, brush %p.\n", iface, color, desc, brush);
426 if (!(object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object))))
427 return E_OUTOFMEMORY;
429 d2d_solid_color_brush_init(object, iface, color, desc);
431 TRACE("Created brush %p.\n", object);
432 *brush = (ID2D1SolidColorBrush *)&object->ID2D1Brush_iface;
434 return S_OK;
437 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateGradientStopCollection(ID2D1RenderTarget *iface,
438 const D2D1_GRADIENT_STOP *stops, UINT32 stop_count, D2D1_GAMMA gamma, D2D1_EXTEND_MODE extend_mode,
439 ID2D1GradientStopCollection **gradient)
441 struct d2d_gradient *object;
442 HRESULT hr;
444 TRACE("iface %p, stops %p, stop_count %u, gamma %#x, extend_mode %#x, gradient %p.\n",
445 iface, stops, stop_count, gamma, extend_mode, gradient);
447 if (!(object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object))))
448 return E_OUTOFMEMORY;
450 if (FAILED(hr = d2d_gradient_init(object, iface, stops, stop_count, gamma, extend_mode)))
452 WARN("Failed to initialize gradient, hr %#x.\n", hr);
453 HeapFree(GetProcessHeap(), 0, object);
454 return hr;
457 TRACE("Created gradient %p.\n", object);
458 *gradient = &object->ID2D1GradientStopCollection_iface;
460 return S_OK;
463 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateLinearGradientBrush(ID2D1RenderTarget *iface,
464 const D2D1_LINEAR_GRADIENT_BRUSH_PROPERTIES *gradient_brush_desc, const D2D1_BRUSH_PROPERTIES *brush_desc,
465 ID2D1GradientStopCollection *gradient, ID2D1LinearGradientBrush **brush)
467 struct d2d_brush *object;
469 TRACE("iface %p, gradient_brush_desc %p, brush_desc %p, gradient %p, brush %p.\n",
470 iface, gradient_brush_desc, brush_desc, gradient, brush);
472 if (!(object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object))))
473 return E_OUTOFMEMORY;
475 d2d_linear_gradient_brush_init(object, iface, gradient_brush_desc, brush_desc, gradient);
477 TRACE("Created brush %p.\n", object);
478 *brush = (ID2D1LinearGradientBrush *)&object->ID2D1Brush_iface;
480 return S_OK;
483 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateRadialGradientBrush(ID2D1RenderTarget *iface,
484 const D2D1_RADIAL_GRADIENT_BRUSH_PROPERTIES *gradient_brush_desc, const D2D1_BRUSH_PROPERTIES *brush_desc,
485 ID2D1GradientStopCollection *gradient, ID2D1RadialGradientBrush **brush)
487 FIXME("iface %p, gradient_brush_desc %p, brush_desc %p, gradient %p, brush %p stub!\n",
488 iface, gradient_brush_desc, brush_desc, gradient, brush);
490 return E_NOTIMPL;
493 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateCompatibleRenderTarget(ID2D1RenderTarget *iface,
494 const D2D1_SIZE_F *size, const D2D1_SIZE_U *pixel_size, const D2D1_PIXEL_FORMAT *format,
495 D2D1_COMPATIBLE_RENDER_TARGET_OPTIONS options, ID2D1BitmapRenderTarget **render_target)
497 FIXME("iface %p, size %p, pixel_size %p, format %p, options %#x, render_target %p stub!\n",
498 iface, size, pixel_size, format, options, render_target);
500 return E_NOTIMPL;
503 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateLayer(ID2D1RenderTarget *iface,
504 const D2D1_SIZE_F *size, ID2D1Layer **layer)
506 FIXME("iface %p, size %p, layer %p stub!\n", iface, size, layer);
508 return E_NOTIMPL;
511 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_CreateMesh(ID2D1RenderTarget *iface, ID2D1Mesh **mesh)
513 struct d2d_mesh *object;
515 TRACE("iface %p, mesh %p.\n", iface, mesh);
517 if (!(object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object))))
518 return E_OUTOFMEMORY;
520 d2d_mesh_init(object);
522 TRACE("Created mesh %p.\n", object);
523 *mesh = &object->ID2D1Mesh_iface;
525 return S_OK;
528 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawLine(ID2D1RenderTarget *iface,
529 D2D1_POINT_2F p0, D2D1_POINT_2F p1, ID2D1Brush *brush, float stroke_width, ID2D1StrokeStyle *stroke_style)
531 FIXME("iface %p, p0 {%.8e, %.8e}, p1 {%.8e, %.8e}, brush %p, stroke_width %.8e, stroke_style %p stub!\n",
532 iface, p0.x, p0.y, p1.x, p1.y, brush, stroke_width, stroke_style);
535 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawRectangle(ID2D1RenderTarget *iface,
536 const D2D1_RECT_F *rect, ID2D1Brush *brush, float stroke_width, ID2D1StrokeStyle *stroke_style)
538 FIXME("iface %p, rect %p, brush %p, stroke_width %.8e, stroke_style %p stub!\n",
539 iface, rect, brush, stroke_width, stroke_style);
542 static void STDMETHODCALLTYPE d2d_d3d_render_target_FillRectangle(ID2D1RenderTarget *iface,
543 const D2D1_RECT_F *rect, ID2D1Brush *brush)
545 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
546 struct d2d_brush *brush_impl = unsafe_impl_from_ID2D1Brush(brush);
547 D3D10_SUBRESOURCE_DATA buffer_data;
548 D3D10_BUFFER_DESC buffer_desc;
549 ID3D10Buffer *vs_cb, *ps_cb;
550 ID3D10PixelShader *ps;
551 D2D1_COLOR_F color;
552 float tmp_x, tmp_y;
553 HRESULT hr;
554 struct
556 float _11, _21, _31, pad0;
557 float _12, _22, _32, pad1;
558 } transform;
560 TRACE("iface %p, rect %p, brush %p.\n", iface, rect, brush);
562 if (brush_impl->type != D2D_BRUSH_TYPE_SOLID
563 && brush_impl->type != D2D_BRUSH_TYPE_BITMAP)
565 FIXME("Unhandled brush type %#x.\n", brush_impl->type);
566 return;
569 /* Translate from clip space to world (D2D rendertarget) space, taking the
570 * dpi and rendertarget transform into account. */
571 tmp_x = (2.0f * render_target->dpi_x) / (96.0f * render_target->pixel_size.width);
572 tmp_y = -(2.0f * render_target->dpi_y) / (96.0f * render_target->pixel_size.height);
573 transform._11 = render_target->drawing_state.transform._11 * tmp_x;
574 transform._21 = render_target->drawing_state.transform._21 * tmp_x;
575 transform._31 = render_target->drawing_state.transform._31 * tmp_x - 1.0f;
576 transform.pad0 = 0.0f;
577 transform._12 = render_target->drawing_state.transform._12 * tmp_y;
578 transform._22 = render_target->drawing_state.transform._22 * tmp_y;
579 transform._32 = render_target->drawing_state.transform._32 * tmp_y + 1.0f;
580 transform.pad1 = 0.0f;
582 /* Translate from world space to object space. */
583 tmp_x = rect->left + (rect->right - rect->left) / 2.0f;
584 tmp_y = rect->top + (rect->bottom - rect->top) / 2.0f;
585 transform._31 += tmp_x * transform._11 + tmp_y * transform._21;
586 transform._32 += tmp_x * transform._12 + tmp_y * transform._22;
587 tmp_x = (rect->right - rect->left) / 2.0f;
588 tmp_y = (rect->bottom - rect->top) / 2.0f;
589 transform._11 *= tmp_x;
590 transform._12 *= tmp_x;
591 transform._21 *= tmp_y;
592 transform._22 *= tmp_y;
594 buffer_desc.ByteWidth = sizeof(transform);
595 buffer_desc.Usage = D3D10_USAGE_DEFAULT;
596 buffer_desc.BindFlags = D3D10_BIND_CONSTANT_BUFFER;
597 buffer_desc.CPUAccessFlags = 0;
598 buffer_desc.MiscFlags = 0;
600 buffer_data.pSysMem = &transform;
601 buffer_data.SysMemPitch = 0;
602 buffer_data.SysMemSlicePitch = 0;
604 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device, &buffer_desc, &buffer_data, &vs_cb)))
606 WARN("Failed to create constant buffer, hr %#x.\n", hr);
607 return;
610 if (brush_impl->type == D2D_BRUSH_TYPE_BITMAP)
612 struct d2d_bitmap *bitmap = brush_impl->u.bitmap.bitmap;
613 D2D_MATRIX_3X2_F w, b;
614 float dpi_scale, d;
616 ps = render_target->rect_bitmap_ps;
618 /* Scale for dpi. */
619 w = render_target->drawing_state.transform;
620 dpi_scale = render_target->dpi_x / 96.0f;
621 w._11 *= dpi_scale;
622 w._21 *= dpi_scale;
623 w._31 *= dpi_scale;
624 dpi_scale = render_target->dpi_y / 96.0f;
625 w._12 *= dpi_scale;
626 w._22 *= dpi_scale;
627 w._32 *= dpi_scale;
629 /* Scale for bitmap size and dpi. */
630 b = brush_impl->transform;
631 dpi_scale = bitmap->pixel_size.width * (bitmap->dpi_x / 96.0f);
632 b._11 *= dpi_scale;
633 b._21 *= dpi_scale;
634 dpi_scale = bitmap->pixel_size.height * (bitmap->dpi_y / 96.0f);
635 b._12 *= dpi_scale;
636 b._22 *= dpi_scale;
638 d2d_matrix_multiply(&b, &w);
640 /* Invert the matrix. (Because the matrix is applied to the sampling
641 * coordinates. I.e., to scale the bitmap by 2 we need to divide the
642 * coordinates by 2.) */
643 d = b._11 * b._22 - b._21 * b._12;
644 if (d != 0.0f)
646 transform._11 = b._22 / d;
647 transform._21 = -b._21 / d;
648 transform._31 = (b._21 * b._32 - b._31 * b._22) / d;
649 transform._12 = -b._12 / d;
650 transform._22 = b._11 / d;
651 transform._32 = -(b._11 * b._32 - b._31 * b._12) / d;
653 transform.pad1 = brush_impl->opacity;
655 buffer_desc.ByteWidth = sizeof(transform);
656 buffer_data.pSysMem = &transform;
658 else
660 ps = render_target->rect_solid_ps;
662 color = brush_impl->u.solid.color;
663 color.a *= brush_impl->opacity;
665 buffer_desc.ByteWidth = sizeof(color);
666 buffer_data.pSysMem = &color;
669 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device, &buffer_desc, &buffer_data, &ps_cb)))
671 WARN("Failed to create constant buffer, hr %#x.\n", hr);
672 ID3D10Buffer_Release(vs_cb);
673 return;
676 d2d_draw(render_target, vs_cb, ps, ps_cb, brush_impl);
678 ID3D10Buffer_Release(ps_cb);
679 ID3D10Buffer_Release(vs_cb);
682 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawRoundedRectangle(ID2D1RenderTarget *iface,
683 const D2D1_ROUNDED_RECT *rect, ID2D1Brush *brush, float stroke_width, ID2D1StrokeStyle *stroke_style)
685 FIXME("iface %p, rect %p, brush %p, stroke_width %.8e, stroke_style %p stub!\n",
686 iface, rect, brush, stroke_width, stroke_style);
689 static void STDMETHODCALLTYPE d2d_d3d_render_target_FillRoundedRectangle(ID2D1RenderTarget *iface,
690 const D2D1_ROUNDED_RECT *rect, ID2D1Brush *brush)
692 FIXME("iface %p, rect %p, brush %p stub!\n", iface, rect, brush);
695 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawEllipse(ID2D1RenderTarget *iface,
696 const D2D1_ELLIPSE *ellipse, ID2D1Brush *brush, float stroke_width, ID2D1StrokeStyle *stroke_style)
698 FIXME("iface %p, ellipse %p, brush %p, stroke_width %.8e, stroke_style %p stub!\n",
699 iface, ellipse, brush, stroke_width, stroke_style);
702 static void STDMETHODCALLTYPE d2d_d3d_render_target_FillEllipse(ID2D1RenderTarget *iface,
703 const D2D1_ELLIPSE *ellipse, ID2D1Brush *brush)
705 FIXME("iface %p, ellipse %p, brush %p stub!\n", iface, ellipse, brush);
708 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawGeometry(ID2D1RenderTarget *iface,
709 ID2D1Geometry *geometry, ID2D1Brush *brush, float stroke_width, ID2D1StrokeStyle *stroke_style)
711 FIXME("iface %p, geometry %p, brush %p, stroke_width %.8e, stroke_style %p stub!\n",
712 iface, geometry, brush, stroke_width, stroke_style);
715 static void STDMETHODCALLTYPE d2d_d3d_render_target_FillGeometry(ID2D1RenderTarget *iface,
716 ID2D1Geometry *geometry, ID2D1Brush *brush, ID2D1Brush *opacity_brush)
718 FIXME("iface %p, geometry %p, brush %p, opacity_brush %p stub!\n", iface, geometry, brush, opacity_brush);
721 static void STDMETHODCALLTYPE d2d_d3d_render_target_FillMesh(ID2D1RenderTarget *iface,
722 ID2D1Mesh *mesh, ID2D1Brush *brush)
724 FIXME("iface %p, mesh %p, brush %p stub!\n", iface, mesh, brush);
727 static void STDMETHODCALLTYPE d2d_d3d_render_target_FillOpacityMask(ID2D1RenderTarget *iface,
728 ID2D1Bitmap *mask, ID2D1Brush *brush, D2D1_OPACITY_MASK_CONTENT content,
729 const D2D1_RECT_F *dst_rect, const D2D1_RECT_F *src_rect)
731 FIXME("iface %p, mask %p, brush %p, content %#x, dst_rect %p, src_rect %p stub!\n",
732 iface, mask, brush, content, dst_rect, src_rect);
735 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawBitmap(ID2D1RenderTarget *iface,
736 ID2D1Bitmap *bitmap, const D2D1_RECT_F *dst_rect, float opacity,
737 D2D1_BITMAP_INTERPOLATION_MODE interpolation_mode, const D2D1_RECT_F *src_rect)
739 D2D1_BITMAP_BRUSH_PROPERTIES bitmap_brush_desc;
740 D2D1_BRUSH_PROPERTIES brush_desc;
741 ID2D1BitmapBrush *brush;
742 D2D1_RECT_F s, d;
743 HRESULT hr;
745 TRACE("iface %p, bitmap %p, dst_rect %p, opacity %.8e, interpolation_mode %#x, src_rect %p.\n",
746 iface, bitmap, dst_rect, opacity, interpolation_mode, src_rect);
748 if (src_rect)
750 s = *src_rect;
752 else
754 D2D1_SIZE_F size;
756 size = ID2D1Bitmap_GetSize(bitmap);
757 s.left = 0.0f;
758 s.top = 0.0f;
759 s.right = size.width;
760 s.bottom = size.height;
763 if (dst_rect)
765 d = *dst_rect;
767 else
769 d.left = 0.0f;
770 d.top = 0.0f;
771 d.right = s.right - s.left;
772 d.bottom = s.bottom - s.top;
775 bitmap_brush_desc.extendModeX = D2D1_EXTEND_MODE_CLAMP;
776 bitmap_brush_desc.extendModeY = D2D1_EXTEND_MODE_CLAMP;
777 bitmap_brush_desc.interpolationMode = interpolation_mode;
779 brush_desc.opacity = opacity;
780 brush_desc.transform._11 = (d.right - d.left) / (s.right - s.left);
781 brush_desc.transform._21 = 0.0f;
782 brush_desc.transform._31 = d.left - s.left;
783 brush_desc.transform._12 = 0.0f;
784 brush_desc.transform._22 = (d.bottom - d.top) / (s.bottom - s.top);
785 brush_desc.transform._32 = d.top - s.top;
787 if (FAILED(hr = ID2D1RenderTarget_CreateBitmapBrush(iface, bitmap, &bitmap_brush_desc, &brush_desc, &brush)))
789 ERR("Failed to create bitmap brush, hr %#x.\n", hr);
790 return;
793 ID2D1RenderTarget_FillRectangle(iface, &d, (ID2D1Brush *)brush);
794 ID2D1BitmapBrush_Release(brush);
797 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawText(ID2D1RenderTarget *iface,
798 const WCHAR *string, UINT32 string_len, IDWriteTextFormat *text_format, const D2D1_RECT_F *layout_rect,
799 ID2D1Brush *brush, D2D1_DRAW_TEXT_OPTIONS options, DWRITE_MEASURING_MODE measuring_mode)
801 FIXME("iface %p, string %s, string_len %u, text_format %p, layout_rect %p, "
802 "brush %p, options %#x, measuring_mode %#x stub!\n",
803 iface, debugstr_wn(string, string_len), string_len, text_format, layout_rect,
804 brush, options, measuring_mode);
807 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawTextLayout(ID2D1RenderTarget *iface,
808 D2D1_POINT_2F origin, IDWriteTextLayout *layout, ID2D1Brush *brush, D2D1_DRAW_TEXT_OPTIONS options)
810 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
811 struct d2d_draw_text_layout_ctx ctx;
812 HRESULT hr;
814 TRACE("iface %p, origin {%.8e, %.8e}, layout %p, brush %p, options %#x.\n",
815 iface, origin.x, origin.y, layout, brush, options);
817 ctx.brush = brush;
818 ctx.options = options;
820 if (FAILED(hr = IDWriteTextLayout_Draw(layout,
821 &ctx, &render_target->IDWriteTextRenderer_iface, origin.x, origin.y)))
822 FIXME("Failed to draw text layout, hr %#x.\n", hr);
825 static void STDMETHODCALLTYPE d2d_d3d_render_target_DrawGlyphRun(ID2D1RenderTarget *iface,
826 D2D1_POINT_2F baseline_origin, const DWRITE_GLYPH_RUN *glyph_run, ID2D1Brush *brush,
827 DWRITE_MEASURING_MODE measuring_mode)
829 FIXME("iface %p, baseline_origin {%.8e, %.8e}, glyph_run %p, brush %p, measuring_mode %#x stub!\n",
830 iface, baseline_origin.x, baseline_origin.y, glyph_run, brush, measuring_mode);
833 static void STDMETHODCALLTYPE d2d_d3d_render_target_SetTransform(ID2D1RenderTarget *iface,
834 const D2D1_MATRIX_3X2_F *transform)
836 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
838 TRACE("iface %p, transform %p.\n", iface, transform);
840 render_target->drawing_state.transform = *transform;
843 static void STDMETHODCALLTYPE d2d_d3d_render_target_GetTransform(ID2D1RenderTarget *iface,
844 D2D1_MATRIX_3X2_F *transform)
846 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
848 TRACE("iface %p, transform %p.\n", iface, transform);
850 *transform = render_target->drawing_state.transform;
853 static void STDMETHODCALLTYPE d2d_d3d_render_target_SetAntialiasMode(ID2D1RenderTarget *iface,
854 D2D1_ANTIALIAS_MODE antialias_mode)
856 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
858 TRACE("iface %p, antialias_mode %#x stub!\n", iface, antialias_mode);
860 render_target->drawing_state.antialiasMode = antialias_mode;
863 static D2D1_ANTIALIAS_MODE STDMETHODCALLTYPE d2d_d3d_render_target_GetAntialiasMode(ID2D1RenderTarget *iface)
865 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
867 TRACE("iface %p.\n", iface);
869 return render_target->drawing_state.antialiasMode;
872 static void STDMETHODCALLTYPE d2d_d3d_render_target_SetTextAntialiasMode(ID2D1RenderTarget *iface,
873 D2D1_TEXT_ANTIALIAS_MODE antialias_mode)
875 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
877 TRACE("iface %p, antialias_mode %#x.\n", iface, antialias_mode);
879 render_target->drawing_state.textAntialiasMode = antialias_mode;
882 static D2D1_TEXT_ANTIALIAS_MODE STDMETHODCALLTYPE d2d_d3d_render_target_GetTextAntialiasMode(ID2D1RenderTarget *iface)
884 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
886 TRACE("iface %p.\n", iface);
888 return render_target->drawing_state.textAntialiasMode;
891 static void STDMETHODCALLTYPE d2d_d3d_render_target_SetTextRenderingParams(ID2D1RenderTarget *iface,
892 IDWriteRenderingParams *text_rendering_params)
894 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
896 TRACE("iface %p, text_rendering_params %p.\n", iface, text_rendering_params);
898 if (text_rendering_params)
899 IDWriteRenderingParams_AddRef(text_rendering_params);
900 if (render_target->text_rendering_params)
901 IDWriteRenderingParams_Release(render_target->text_rendering_params);
902 render_target->text_rendering_params = text_rendering_params;
905 static void STDMETHODCALLTYPE d2d_d3d_render_target_GetTextRenderingParams(ID2D1RenderTarget *iface,
906 IDWriteRenderingParams **text_rendering_params)
908 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
910 TRACE("iface %p, text_rendering_params %p.\n", iface, text_rendering_params);
912 if ((*text_rendering_params = render_target->text_rendering_params))
913 IDWriteRenderingParams_AddRef(*text_rendering_params);
916 static void STDMETHODCALLTYPE d2d_d3d_render_target_SetTags(ID2D1RenderTarget *iface, D2D1_TAG tag1, D2D1_TAG tag2)
918 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
920 TRACE("iface %p, tag1 %s, tag2 %s.\n", iface, wine_dbgstr_longlong(tag1), wine_dbgstr_longlong(tag2));
922 render_target->drawing_state.tag1 = tag1;
923 render_target->drawing_state.tag2 = tag2;
926 static void STDMETHODCALLTYPE d2d_d3d_render_target_GetTags(ID2D1RenderTarget *iface, D2D1_TAG *tag1, D2D1_TAG *tag2)
928 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
930 TRACE("iface %p, tag1 %p, tag2 %p.\n", iface, tag1, tag2);
932 *tag1 = render_target->drawing_state.tag1;
933 *tag2 = render_target->drawing_state.tag2;
936 static void STDMETHODCALLTYPE d2d_d3d_render_target_PushLayer(ID2D1RenderTarget *iface,
937 const D2D1_LAYER_PARAMETERS *layer_parameters, ID2D1Layer *layer)
939 FIXME("iface %p, layer_parameters %p, layer %p stub!\n", iface, layer_parameters, layer);
942 static void STDMETHODCALLTYPE d2d_d3d_render_target_PopLayer(ID2D1RenderTarget *iface)
944 FIXME("iface %p stub!\n", iface);
947 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_Flush(ID2D1RenderTarget *iface, D2D1_TAG *tag1, D2D1_TAG *tag2)
949 FIXME("iface %p, tag1 %p, tag2 %p stub!\n", iface, tag1, tag2);
951 return E_NOTIMPL;
954 static void STDMETHODCALLTYPE d2d_d3d_render_target_SaveDrawingState(ID2D1RenderTarget *iface,
955 ID2D1DrawingStateBlock *state_block)
957 struct d2d_state_block *state_block_impl = unsafe_impl_from_ID2D1DrawingStateBlock(state_block);
958 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
960 TRACE("iface %p, state_block %p.\n", iface, state_block);
962 state_block_impl->drawing_state = render_target->drawing_state;
963 if (render_target->text_rendering_params)
964 IDWriteRenderingParams_AddRef(render_target->text_rendering_params);
965 if (state_block_impl->text_rendering_params)
966 IDWriteRenderingParams_Release(state_block_impl->text_rendering_params);
967 state_block_impl->text_rendering_params = render_target->text_rendering_params;
970 static void STDMETHODCALLTYPE d2d_d3d_render_target_RestoreDrawingState(ID2D1RenderTarget *iface,
971 ID2D1DrawingStateBlock *state_block)
973 struct d2d_state_block *state_block_impl = unsafe_impl_from_ID2D1DrawingStateBlock(state_block);
974 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
976 TRACE("iface %p, state_block %p.\n", iface, state_block);
978 render_target->drawing_state = state_block_impl->drawing_state;
979 if (state_block_impl->text_rendering_params)
980 IDWriteRenderingParams_AddRef(state_block_impl->text_rendering_params);
981 if (render_target->text_rendering_params)
982 IDWriteRenderingParams_Release(render_target->text_rendering_params);
983 render_target->text_rendering_params = state_block_impl->text_rendering_params;
986 static void STDMETHODCALLTYPE d2d_d3d_render_target_PushAxisAlignedClip(ID2D1RenderTarget *iface,
987 const D2D1_RECT_F *clip_rect, D2D1_ANTIALIAS_MODE antialias_mode)
989 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
990 D2D1_RECT_F transformed_rect;
991 float x_scale, y_scale;
992 D2D1_POINT_2F point;
994 TRACE("iface %p, clip_rect %p, antialias_mode %#x.\n", iface, clip_rect, antialias_mode);
996 if (antialias_mode != D2D1_ANTIALIAS_MODE_ALIASED)
997 FIXME("Ignoring antialias_mode %#x.\n", antialias_mode);
999 x_scale = render_target->dpi_x / 96.0f;
1000 y_scale = render_target->dpi_y / 96.0f;
1001 d2d_point_transform(&point, &render_target->drawing_state.transform,
1002 clip_rect->left * x_scale, clip_rect->top * y_scale);
1003 d2d_rect_set(&transformed_rect, point.x, point.y, point.x, point.y);
1004 d2d_point_transform(&point, &render_target->drawing_state.transform,
1005 clip_rect->left * x_scale, clip_rect->bottom * y_scale);
1006 d2d_rect_expand(&transformed_rect, &point);
1007 d2d_point_transform(&point, &render_target->drawing_state.transform,
1008 clip_rect->right * x_scale, clip_rect->top * y_scale);
1009 d2d_rect_expand(&transformed_rect, &point);
1010 d2d_point_transform(&point, &render_target->drawing_state.transform,
1011 clip_rect->right * x_scale, clip_rect->bottom * y_scale);
1012 d2d_rect_expand(&transformed_rect, &point);
1014 if (!d2d_clip_stack_push(&render_target->clip_stack, &transformed_rect))
1015 WARN("Failed to push clip rect.\n");
1018 static void STDMETHODCALLTYPE d2d_d3d_render_target_PopAxisAlignedClip(ID2D1RenderTarget *iface)
1020 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1022 TRACE("iface %p.\n", iface);
1024 d2d_clip_stack_pop(&render_target->clip_stack);
1027 static void STDMETHODCALLTYPE d2d_d3d_render_target_Clear(ID2D1RenderTarget *iface, const D2D1_COLOR_F *color)
1029 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1030 D3D10_SUBRESOURCE_DATA buffer_data;
1031 D3D10_BUFFER_DESC buffer_desc;
1032 ID3D10Buffer *vs_cb, *ps_cb;
1033 HRESULT hr;
1035 static const float transform[] =
1037 1.0f, 0.0f, 0.0f, 0.0f,
1038 0.0f, -1.0f, 0.0f, 0.0f,
1041 TRACE("iface %p, color %p.\n", iface, color);
1043 buffer_desc.ByteWidth = sizeof(transform);
1044 buffer_desc.Usage = D3D10_USAGE_DEFAULT;
1045 buffer_desc.BindFlags = D3D10_BIND_CONSTANT_BUFFER;
1046 buffer_desc.CPUAccessFlags = 0;
1047 buffer_desc.MiscFlags = 0;
1049 buffer_data.pSysMem = transform;
1050 buffer_data.SysMemPitch = 0;
1051 buffer_data.SysMemSlicePitch = 0;
1053 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device, &buffer_desc, &buffer_data, &vs_cb)))
1055 WARN("Failed to create constant buffer, hr %#x.\n", hr);
1056 return;
1059 buffer_desc.ByteWidth = sizeof(*color);
1060 buffer_data.pSysMem = color;
1062 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device, &buffer_desc, &buffer_data, &ps_cb)))
1064 WARN("Failed to create constant buffer, hr %#x.\n", hr);
1065 ID3D10Buffer_Release(vs_cb);
1066 return;
1069 d2d_draw(render_target, vs_cb, render_target->rect_solid_ps, ps_cb, NULL);
1071 ID3D10Buffer_Release(ps_cb);
1072 ID3D10Buffer_Release(vs_cb);
1075 static void STDMETHODCALLTYPE d2d_d3d_render_target_BeginDraw(ID2D1RenderTarget *iface)
1077 TRACE("iface %p.\n", iface);
1080 static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_EndDraw(ID2D1RenderTarget *iface,
1081 D2D1_TAG *tag1, D2D1_TAG *tag2)
1083 TRACE("iface %p, tag1 %p, tag2 %p.\n", iface, tag1, tag2);
1085 if (tag1)
1086 *tag1 = 0;
1087 if (tag2)
1088 *tag2 = 0;
1090 return S_OK;
1093 static D2D1_PIXEL_FORMAT * STDMETHODCALLTYPE d2d_d3d_render_target_GetPixelFormat(ID2D1RenderTarget *iface,
1094 D2D1_PIXEL_FORMAT *format)
1096 FIXME("iface %p, format %p stub!\n", iface, format);
1098 format->format = DXGI_FORMAT_UNKNOWN;
1099 format->alphaMode = D2D1_ALPHA_MODE_UNKNOWN;
1100 return format;
1103 static void STDMETHODCALLTYPE d2d_d3d_render_target_SetDpi(ID2D1RenderTarget *iface, float dpi_x, float dpi_y)
1105 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1107 TRACE("iface %p, dpi_x %.8e, dpi_y %.8e.\n", iface, dpi_x, dpi_y);
1109 if (dpi_x == 0.0f && dpi_y == 0.0f)
1111 dpi_x = 96.0f;
1112 dpi_y = 96.0f;
1115 render_target->dpi_x = dpi_x;
1116 render_target->dpi_y = dpi_y;
1119 static void STDMETHODCALLTYPE d2d_d3d_render_target_GetDpi(ID2D1RenderTarget *iface, float *dpi_x, float *dpi_y)
1121 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1123 TRACE("iface %p, dpi_x %p, dpi_y %p.\n", iface, dpi_x, dpi_y);
1125 *dpi_x = render_target->dpi_x;
1126 *dpi_y = render_target->dpi_y;
1129 static D2D1_SIZE_F * STDMETHODCALLTYPE d2d_d3d_render_target_GetSize(ID2D1RenderTarget *iface, D2D1_SIZE_F *size)
1131 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1133 TRACE("iface %p, size %p.\n", iface, size);
1135 size->width = render_target->pixel_size.width / (render_target->dpi_x / 96.0f);
1136 size->height = render_target->pixel_size.height / (render_target->dpi_y / 96.0f);
1137 return size;
1140 static D2D1_SIZE_U * STDMETHODCALLTYPE d2d_d3d_render_target_GetPixelSize(ID2D1RenderTarget *iface,
1141 D2D1_SIZE_U *pixel_size)
1143 struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
1145 TRACE("iface %p, pixel_size %p.\n", iface, pixel_size);
1147 *pixel_size = render_target->pixel_size;
1148 return pixel_size;
1151 static UINT32 STDMETHODCALLTYPE d2d_d3d_render_target_GetMaximumBitmapSize(ID2D1RenderTarget *iface)
1153 FIXME("iface %p stub!\n", iface);
1155 return 0;
1158 static BOOL STDMETHODCALLTYPE d2d_d3d_render_target_IsSupported(ID2D1RenderTarget *iface,
1159 const D2D1_RENDER_TARGET_PROPERTIES *desc)
1161 FIXME("iface %p, desc %p stub!\n", iface, desc);
1163 return FALSE;
1166 static const struct ID2D1RenderTargetVtbl d2d_d3d_render_target_vtbl =
1168 d2d_d3d_render_target_QueryInterface,
1169 d2d_d3d_render_target_AddRef,
1170 d2d_d3d_render_target_Release,
1171 d2d_d3d_render_target_GetFactory,
1172 d2d_d3d_render_target_CreateBitmap,
1173 d2d_d3d_render_target_CreateBitmapFromWicBitmap,
1174 d2d_d3d_render_target_CreateSharedBitmap,
1175 d2d_d3d_render_target_CreateBitmapBrush,
1176 d2d_d3d_render_target_CreateSolidColorBrush,
1177 d2d_d3d_render_target_CreateGradientStopCollection,
1178 d2d_d3d_render_target_CreateLinearGradientBrush,
1179 d2d_d3d_render_target_CreateRadialGradientBrush,
1180 d2d_d3d_render_target_CreateCompatibleRenderTarget,
1181 d2d_d3d_render_target_CreateLayer,
1182 d2d_d3d_render_target_CreateMesh,
1183 d2d_d3d_render_target_DrawLine,
1184 d2d_d3d_render_target_DrawRectangle,
1185 d2d_d3d_render_target_FillRectangle,
1186 d2d_d3d_render_target_DrawRoundedRectangle,
1187 d2d_d3d_render_target_FillRoundedRectangle,
1188 d2d_d3d_render_target_DrawEllipse,
1189 d2d_d3d_render_target_FillEllipse,
1190 d2d_d3d_render_target_DrawGeometry,
1191 d2d_d3d_render_target_FillGeometry,
1192 d2d_d3d_render_target_FillMesh,
1193 d2d_d3d_render_target_FillOpacityMask,
1194 d2d_d3d_render_target_DrawBitmap,
1195 d2d_d3d_render_target_DrawText,
1196 d2d_d3d_render_target_DrawTextLayout,
1197 d2d_d3d_render_target_DrawGlyphRun,
1198 d2d_d3d_render_target_SetTransform,
1199 d2d_d3d_render_target_GetTransform,
1200 d2d_d3d_render_target_SetAntialiasMode,
1201 d2d_d3d_render_target_GetAntialiasMode,
1202 d2d_d3d_render_target_SetTextAntialiasMode,
1203 d2d_d3d_render_target_GetTextAntialiasMode,
1204 d2d_d3d_render_target_SetTextRenderingParams,
1205 d2d_d3d_render_target_GetTextRenderingParams,
1206 d2d_d3d_render_target_SetTags,
1207 d2d_d3d_render_target_GetTags,
1208 d2d_d3d_render_target_PushLayer,
1209 d2d_d3d_render_target_PopLayer,
1210 d2d_d3d_render_target_Flush,
1211 d2d_d3d_render_target_SaveDrawingState,
1212 d2d_d3d_render_target_RestoreDrawingState,
1213 d2d_d3d_render_target_PushAxisAlignedClip,
1214 d2d_d3d_render_target_PopAxisAlignedClip,
1215 d2d_d3d_render_target_Clear,
1216 d2d_d3d_render_target_BeginDraw,
1217 d2d_d3d_render_target_EndDraw,
1218 d2d_d3d_render_target_GetPixelFormat,
1219 d2d_d3d_render_target_SetDpi,
1220 d2d_d3d_render_target_GetDpi,
1221 d2d_d3d_render_target_GetSize,
1222 d2d_d3d_render_target_GetPixelSize,
1223 d2d_d3d_render_target_GetMaximumBitmapSize,
1224 d2d_d3d_render_target_IsSupported,
1227 static inline struct d2d_d3d_render_target *impl_from_IDWriteTextRenderer(IDWriteTextRenderer *iface)
1229 return CONTAINING_RECORD(iface, struct d2d_d3d_render_target, IDWriteTextRenderer_iface);
1232 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_QueryInterface(IDWriteTextRenderer *iface, REFIID iid, void **out)
1234 TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
1236 if (IsEqualGUID(iid, &IID_IDWriteTextRenderer)
1237 || IsEqualGUID(iid, &IID_IDWritePixelSnapping)
1238 || IsEqualGUID(iid, &IID_IUnknown))
1240 IDWriteTextRenderer_AddRef(iface);
1241 *out = iface;
1242 return S_OK;
1245 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
1247 *out = NULL;
1248 return E_NOINTERFACE;
1251 static ULONG STDMETHODCALLTYPE d2d_text_renderer_AddRef(IDWriteTextRenderer *iface)
1253 struct d2d_d3d_render_target *render_target = impl_from_IDWriteTextRenderer(iface);
1255 TRACE("iface %p.\n", iface);
1257 return d2d_d3d_render_target_AddRef(&render_target->ID2D1RenderTarget_iface);
1260 static ULONG STDMETHODCALLTYPE d2d_text_renderer_Release(IDWriteTextRenderer *iface)
1262 struct d2d_d3d_render_target *render_target = impl_from_IDWriteTextRenderer(iface);
1264 TRACE("iface %p.\n", iface);
1266 return d2d_d3d_render_target_Release(&render_target->ID2D1RenderTarget_iface);
1269 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_IsPixelSnappingDisabled(IDWriteTextRenderer *iface,
1270 void *ctx, BOOL *disabled)
1272 FIXME("iface %p, ctx %p, disabled %p stub!\n", iface, ctx, disabled);
1274 return E_NOTIMPL;
1277 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_GetCurrentTransform(IDWriteTextRenderer *iface,
1278 void *ctx, DWRITE_MATRIX *transform)
1280 FIXME("iface %p, ctx %p, transform %p stub!\n", iface, ctx, transform);
1282 return E_NOTIMPL;
1285 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_GetPixelsPerDip(IDWriteTextRenderer *iface, void *ctx, float *ppd)
1287 FIXME("iface %p, ctx %p, ppd %p stub!\n", iface, ctx, ppd);
1289 return E_NOTIMPL;
1292 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_DrawGlyphRun(IDWriteTextRenderer *iface, void *ctx,
1293 float baseline_origin_x, float baseline_origin_y, DWRITE_MEASURING_MODE measuring_mode,
1294 const DWRITE_GLYPH_RUN *glyph_run, const DWRITE_GLYPH_RUN_DESCRIPTION *desc, IUnknown *effect)
1296 FIXME("iface %p, ctx %p, baseline_origin_x %.8e, baseline_origin_y %.8e, "
1297 "measuring_mode %#x, glyph_run %p, desc %p, effect %p stub!\n",
1298 iface, ctx, baseline_origin_x, baseline_origin_y,
1299 measuring_mode, glyph_run, desc, effect);
1301 return E_NOTIMPL;
1304 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_DrawUnderline(IDWriteTextRenderer *iface, void *ctx,
1305 float baseline_origin_x, float baseline_origin_y, const DWRITE_UNDERLINE *underline, IUnknown *effect)
1307 FIXME("iface %p, ctx %p, baseline_origin_x %.8e, baseline_origin_y %.8e, underline %p, effect %p stub!\n",
1308 iface, ctx, baseline_origin_x, baseline_origin_y, underline, effect);
1310 return E_NOTIMPL;
1313 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_DrawStrikethrough(IDWriteTextRenderer *iface, void *ctx,
1314 float baseline_origin_x, float baseline_origin_y, const DWRITE_STRIKETHROUGH *strikethrough, IUnknown *effect)
1316 FIXME("iface %p, ctx %p, baseline_origin_x %.8e, baseline_origin_y %.8e, strikethrough %p, effect %p stub!\n",
1317 iface, ctx, baseline_origin_x, baseline_origin_y, strikethrough, effect);
1319 return E_NOTIMPL;
1322 static HRESULT STDMETHODCALLTYPE d2d_text_renderer_DrawInlineObject(IDWriteTextRenderer *iface, void *ctx,
1323 float origin_x, float origin_y, IDWriteInlineObject *object, BOOL is_sideways, BOOL is_rtl, IUnknown *effect)
1325 FIXME("iface %p, ctx %p, origin_x %.8e, origin_y %.8e, object %p, is_sideways %#x, is_rtl %#x, effect %p stub!\n",
1326 iface, ctx, origin_x, origin_y, object, is_sideways, is_rtl, effect);
1328 return E_NOTIMPL;
1331 static const struct IDWriteTextRendererVtbl d2d_text_renderer_vtbl =
1333 d2d_text_renderer_QueryInterface,
1334 d2d_text_renderer_AddRef,
1335 d2d_text_renderer_Release,
1336 d2d_text_renderer_IsPixelSnappingDisabled,
1337 d2d_text_renderer_GetCurrentTransform,
1338 d2d_text_renderer_GetPixelsPerDip,
1339 d2d_text_renderer_DrawGlyphRun,
1340 d2d_text_renderer_DrawUnderline,
1341 d2d_text_renderer_DrawStrikethrough,
1342 d2d_text_renderer_DrawInlineObject,
1345 HRESULT d2d_d3d_render_target_init(struct d2d_d3d_render_target *render_target, ID2D1Factory *factory,
1346 IDXGISurface *surface, const D2D1_RENDER_TARGET_PROPERTIES *desc)
1348 D3D10_SUBRESOURCE_DATA buffer_data;
1349 D3D10_STATE_BLOCK_MASK state_mask;
1350 DXGI_SURFACE_DESC surface_desc;
1351 D3D10_RASTERIZER_DESC rs_desc;
1352 D3D10_BUFFER_DESC buffer_desc;
1353 D3D10_BLEND_DESC blend_desc;
1354 ID3D10Resource *resource;
1355 HRESULT hr;
1357 static const D3D10_INPUT_ELEMENT_DESC il_desc[] =
1359 {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0},
1361 static const DWORD vs_code[] =
1363 /* float3x2 transform;
1365 * float4 main(float4 position : POSITION) : SV_POSITION
1367 * return float4(mul(position.xyw, transform), position.zw);
1368 * } */
1369 0x43425844, 0x0add3194, 0x205f74ec, 0xab527fe7, 0xbe6ad704, 0x00000001, 0x00000128, 0x00000003,
1370 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020,
1371 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000f0f, 0x49534f50, 0x4e4f4954, 0xababab00,
1372 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000001, 0x00000003,
1373 0x00000000, 0x0000000f, 0x505f5653, 0x5449534f, 0x004e4f49, 0x52444853, 0x0000008c, 0x00010040,
1374 0x00000023, 0x04000059, 0x00208e46, 0x00000000, 0x00000002, 0x0300005f, 0x001010f2, 0x00000000,
1375 0x04000067, 0x001020f2, 0x00000000, 0x00000001, 0x08000010, 0x00102012, 0x00000000, 0x00101346,
1376 0x00000000, 0x00208246, 0x00000000, 0x00000000, 0x08000010, 0x00102022, 0x00000000, 0x00101346,
1377 0x00000000, 0x00208246, 0x00000000, 0x00000001, 0x05000036, 0x001020c2, 0x00000000, 0x00101ea6,
1378 0x00000000, 0x0100003e,
1380 static const DWORD rect_solid_ps_code[] =
1382 /* float4 color;
1384 * float4 main(float4 position : SV_POSITION) : SV_Target
1386 * return color;
1387 * } */
1388 0x43425844, 0x88eefcfd, 0x93d6fd47, 0x173c242f, 0x0106d07a, 0x00000001, 0x000000dc, 0x00000003,
1389 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020,
1390 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x505f5653, 0x5449534f, 0x004e4f49,
1391 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003,
1392 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x00000040, 0x00000040,
1393 0x00000010, 0x04000059, 0x00208e46, 0x00000000, 0x00000001, 0x03000065, 0x001020f2, 0x00000000,
1394 0x06000036, 0x001020f2, 0x00000000, 0x00208e46, 0x00000000, 0x00000000, 0x0100003e,
1396 static const DWORD rect_bitmap_ps_code[] =
1398 #if 0
1399 float3x2 transform;
1400 float opacity;
1402 SamplerState s;
1403 Texture2D t;
1405 float4 main(float4 position : SV_POSITION) : SV_Target
1407 float2 texcoord;
1408 float4 ret;
1410 texcoord.x = position.x * transform._11 + position.y * transform._21 + transform._31;
1411 texcoord.y = position.x * transform._12 + position.y * transform._22 + transform._32;
1412 ret = t.Sample(s, texcoord);
1413 ret.a *= opacity;
1415 return ret;
1417 #endif
1418 0x43425844, 0x9a5f9280, 0xa5351c23, 0x15d6e760, 0xce35bcc3, 0x00000001, 0x000001d0, 0x00000003,
1419 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020,
1420 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000030f, 0x505f5653, 0x5449534f, 0x004e4f49,
1421 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003,
1422 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x00000134, 0x00000040,
1423 0x0000004d, 0x04000059, 0x00208e46, 0x00000000, 0x00000002, 0x0300005a, 0x00106000, 0x00000000,
1424 0x04001858, 0x00107000, 0x00000000, 0x00005555, 0x04002064, 0x00101032, 0x00000000, 0x00000001,
1425 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000001, 0x0800000f, 0x00100012, 0x00000000,
1426 0x00101046, 0x00000000, 0x00208046, 0x00000000, 0x00000000, 0x08000000, 0x00100012, 0x00000000,
1427 0x0010000a, 0x00000000, 0x0020802a, 0x00000000, 0x00000000, 0x0800000f, 0x00100042, 0x00000000,
1428 0x00101046, 0x00000000, 0x00208046, 0x00000000, 0x00000001, 0x08000000, 0x00100022, 0x00000000,
1429 0x0010002a, 0x00000000, 0x0020802a, 0x00000000, 0x00000001, 0x09000045, 0x001000f2, 0x00000000,
1430 0x00100046, 0x00000000, 0x00107e46, 0x00000000, 0x00106000, 0x00000000, 0x08000038, 0x00102082,
1431 0x00000000, 0x0010003a, 0x00000000, 0x0020803a, 0x00000000, 0x00000001, 0x05000036, 0x00102072,
1432 0x00000000, 0x00100246, 0x00000000, 0x0100003e,
1434 static const struct
1436 float x, y;
1438 quad[] =
1440 {-1.0f, 1.0f},
1441 {-1.0f, -1.0f},
1442 { 1.0f, 1.0f},
1443 { 1.0f, -1.0f},
1445 static const D2D1_MATRIX_3X2_F identity =
1447 1.0f, 0.0f,
1448 0.0f, 1.0f,
1449 0.0f, 0.0f,
1452 FIXME("Ignoring render target properties.\n");
1454 render_target->ID2D1RenderTarget_iface.lpVtbl = &d2d_d3d_render_target_vtbl;
1455 render_target->IDWriteTextRenderer_iface.lpVtbl = &d2d_text_renderer_vtbl;
1456 render_target->refcount = 1;
1457 render_target->factory = factory;
1458 ID2D1Factory_AddRef(render_target->factory);
1460 if (FAILED(hr = IDXGISurface_GetDevice(surface, &IID_ID3D10Device, (void **)&render_target->device)))
1462 WARN("Failed to get device interface, hr %#x.\n", hr);
1463 ID2D1Factory_Release(render_target->factory);
1464 return hr;
1467 if (FAILED(hr = IDXGISurface_QueryInterface(surface, &IID_ID3D10Resource, (void **)&resource)))
1469 WARN("Failed to get ID3D10Resource interface, hr %#x.\n", hr);
1470 goto err;
1473 hr = ID3D10Device_CreateRenderTargetView(render_target->device, resource, NULL, &render_target->view);
1474 ID3D10Resource_Release(resource);
1475 if (FAILED(hr))
1477 WARN("Failed to create rendertarget view, hr %#x.\n", hr);
1478 goto err;
1481 if (FAILED(hr = D3D10StateBlockMaskEnableAll(&state_mask)))
1483 WARN("Failed to create stateblock mask, hr %#x.\n", hr);
1484 goto err;
1487 if (FAILED(hr = D3D10CreateStateBlock(render_target->device, &state_mask, &render_target->stateblock)))
1489 WARN("Failed to create stateblock, hr %#x.\n", hr);
1490 goto err;
1493 if (FAILED(hr = ID3D10Device_CreateInputLayout(render_target->device, il_desc,
1494 sizeof(il_desc) / sizeof(*il_desc), vs_code, sizeof(vs_code),
1495 &render_target->il)))
1497 WARN("Failed to create clear input layout, hr %#x.\n", hr);
1498 goto err;
1501 buffer_desc.ByteWidth = sizeof(quad);
1502 buffer_desc.Usage = D3D10_USAGE_DEFAULT;
1503 buffer_desc.BindFlags = D3D10_BIND_VERTEX_BUFFER;
1504 buffer_desc.CPUAccessFlags = 0;
1505 buffer_desc.MiscFlags = 0;
1507 buffer_data.pSysMem = quad;
1508 buffer_data.SysMemPitch = 0;
1509 buffer_data.SysMemSlicePitch = 0;
1511 render_target->vb_stride = sizeof(*quad);
1512 if (FAILED(hr = ID3D10Device_CreateBuffer(render_target->device,
1513 &buffer_desc, &buffer_data, &render_target->vb)))
1515 WARN("Failed to create clear vertex buffer, hr %#x.\n", hr);
1516 goto err;
1519 if (FAILED(hr = ID3D10Device_CreateVertexShader(render_target->device,
1520 vs_code, sizeof(vs_code), &render_target->vs)))
1522 WARN("Failed to create clear vertex shader, hr %#x.\n", hr);
1523 goto err;
1526 rs_desc.FillMode = D3D10_FILL_SOLID;
1527 rs_desc.CullMode = D3D10_CULL_BACK;
1528 rs_desc.FrontCounterClockwise = FALSE;
1529 rs_desc.DepthBias = 0;
1530 rs_desc.DepthBiasClamp = 0.0f;
1531 rs_desc.SlopeScaledDepthBias = 0.0f;
1532 rs_desc.DepthClipEnable = TRUE;
1533 rs_desc.ScissorEnable = TRUE;
1534 rs_desc.MultisampleEnable = FALSE;
1535 rs_desc.AntialiasedLineEnable = FALSE;
1536 if (FAILED(hr = ID3D10Device_CreateRasterizerState(render_target->device, &rs_desc, &render_target->rs)))
1538 WARN("Failed to create clear rasterizer state, hr %#x.\n", hr);
1539 goto err;
1542 memset(&blend_desc, 0, sizeof(blend_desc));
1543 blend_desc.BlendEnable[0] = TRUE;
1544 blend_desc.SrcBlend = D3D10_BLEND_SRC_ALPHA;
1545 blend_desc.DestBlend = D3D10_BLEND_INV_SRC_ALPHA;
1546 blend_desc.BlendOp = D3D10_BLEND_OP_ADD;
1547 blend_desc.SrcBlendAlpha = D3D10_BLEND_ZERO;
1548 blend_desc.DestBlendAlpha = D3D10_BLEND_ONE;
1549 blend_desc.BlendOpAlpha = D3D10_BLEND_OP_ADD;
1550 blend_desc.RenderTargetWriteMask[0] = D3D10_COLOR_WRITE_ENABLE_ALL;
1551 if (FAILED(hr = ID3D10Device_CreateBlendState(render_target->device, &blend_desc, &render_target->bs)))
1553 WARN("Failed to create blend state, hr %#x.\n", hr);
1554 goto err;
1557 if (FAILED(hr = ID3D10Device_CreatePixelShader(render_target->device,
1558 rect_solid_ps_code, sizeof(rect_solid_ps_code), &render_target->rect_solid_ps)))
1560 WARN("Failed to create pixel shader, hr %#x.\n", hr);
1561 goto err;
1564 if (FAILED(hr = ID3D10Device_CreatePixelShader(render_target->device,
1565 rect_bitmap_ps_code, sizeof(rect_bitmap_ps_code), &render_target->rect_bitmap_ps)))
1567 WARN("Failed to create pixel shader, hr %#x.\n", hr);
1568 goto err;
1571 if (FAILED(hr = IDXGISurface_GetDesc(surface, &surface_desc)))
1573 WARN("Failed to get surface desc, hr %#x.\n", hr);
1574 goto err;
1577 render_target->pixel_size.width = surface_desc.Width;
1578 render_target->pixel_size.height = surface_desc.Height;
1579 render_target->drawing_state.transform = identity;
1581 if (!d2d_clip_stack_init(&render_target->clip_stack))
1583 WARN("Failed to initialize clip stack.\n");
1584 hr = E_FAIL;
1585 goto err;
1588 render_target->dpi_x = desc->dpiX;
1589 render_target->dpi_y = desc->dpiY;
1591 if (render_target->dpi_x == 0.0f && render_target->dpi_y == 0.0f)
1593 render_target->dpi_x = 96.0f;
1594 render_target->dpi_y = 96.0f;
1597 return S_OK;
1599 err:
1600 if (render_target->rect_bitmap_ps)
1601 ID3D10PixelShader_Release(render_target->rect_bitmap_ps);
1602 if (render_target->rect_solid_ps)
1603 ID3D10PixelShader_Release(render_target->rect_solid_ps);
1604 if (render_target->bs)
1605 ID3D10BlendState_Release(render_target->bs);
1606 if (render_target->rs)
1607 ID3D10RasterizerState_Release(render_target->rs);
1608 if (render_target->vs)
1609 ID3D10VertexShader_Release(render_target->vs);
1610 if (render_target->vb)
1611 ID3D10Buffer_Release(render_target->vb);
1612 if (render_target->il)
1613 ID3D10InputLayout_Release(render_target->il);
1614 if (render_target->stateblock)
1615 render_target->stateblock->lpVtbl->Release(render_target->stateblock);
1616 if (render_target->view)
1617 ID3D10RenderTargetView_Release(render_target->view);
1618 if (render_target->device)
1619 ID3D10Device_Release(render_target->device);
1620 ID2D1Factory_Release(render_target->factory);
1621 return hr;