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
20 #include "wine/port.h"
22 #include "d2d1_private.h"
25 WINE_DEFAULT_DEBUG_CHANNEL(d2d
);
27 #define INITIAL_CLIP_STACK_SIZE 4
29 struct d2d_draw_text_layout_ctx
32 D2D1_DRAW_TEXT_OPTIONS options
;
35 static void d2d_point_transform(D2D1_POINT_2F
*dst
, const D2D1_MATRIX_3X2_F
*matrix
, float x
, float y
)
37 dst
->x
= x
* matrix
->_11
+ y
* matrix
->_21
+ matrix
->_31
;
38 dst
->y
= x
* matrix
->_12
+ y
* matrix
->_22
+ matrix
->_32
;
41 static void d2d_rect_expand(D2D1_RECT_F
*dst
, const D2D1_POINT_2F
*point
)
43 if (point
->x
< dst
->left
)
45 if (point
->y
< dst
->top
)
47 if (point
->x
> dst
->right
)
48 dst
->right
= point
->x
;
49 if (point
->y
> dst
->bottom
)
50 dst
->bottom
= point
->y
;
53 static void d2d_rect_intersect(D2D1_RECT_F
*dst
, const D2D1_RECT_F
*src
)
55 if (src
->left
> dst
->left
)
56 dst
->left
= src
->left
;
57 if (src
->top
> dst
->top
)
59 if (src
->right
< dst
->right
)
60 dst
->right
= src
->right
;
61 if (src
->bottom
< dst
->bottom
)
62 dst
->bottom
= src
->bottom
;
65 static void d2d_rect_set(D2D1_RECT_F
*dst
, float left
, float top
, float right
, float bottom
)
73 static BOOL
d2d_clip_stack_init(struct d2d_clip_stack
*stack
)
75 if (!(stack
->stack
= HeapAlloc(GetProcessHeap(), 0, INITIAL_CLIP_STACK_SIZE
* sizeof(*stack
->stack
))))
78 stack
->size
= INITIAL_CLIP_STACK_SIZE
;
84 static void d2d_clip_stack_cleanup(struct d2d_clip_stack
*stack
)
86 HeapFree(GetProcessHeap(), 0, stack
->stack
);
89 static BOOL
d2d_clip_stack_push(struct d2d_clip_stack
*stack
, const D2D1_RECT_F
*rect
)
93 if (stack
->count
== stack
->size
)
95 D2D1_RECT_F
*new_stack
;
96 unsigned int new_size
;
98 if (stack
->size
> UINT_MAX
/ 2)
101 new_size
= stack
->size
* 2;
102 if (!(new_stack
= HeapReAlloc(GetProcessHeap(), 0, stack
->stack
, new_size
* sizeof(*stack
->stack
))))
105 stack
->stack
= new_stack
;
106 stack
->size
= new_size
;
111 d2d_rect_intersect(&r
, &stack
->stack
[stack
->count
- 1]);
112 stack
->stack
[stack
->count
++] = r
;
117 static void d2d_clip_stack_pop(struct d2d_clip_stack
*stack
)
124 static void d2d_draw(struct d2d_d3d_render_target
*render_target
, ID3D10Buffer
*vs_cb
,
125 ID3D10PixelShader
*ps
, ID3D10Buffer
*ps_cb
, struct d2d_brush
*brush
)
127 ID3D10Device
*device
= render_target
->device
;
131 static const float blend_factor
[] = {1.0f
, 1.0f
, 1.0f
, 1.0f
};
135 vp
.Width
= render_target
->pixel_size
.width
;
136 vp
.Height
= render_target
->pixel_size
.height
;
140 if (FAILED(hr
= render_target
->stateblock
->lpVtbl
->Capture(render_target
->stateblock
)))
142 WARN("Failed to capture stateblock, hr %#x.\n", hr
);
146 ID3D10Device_ClearState(device
);
148 ID3D10Device_IASetInputLayout(device
, render_target
->il
);
149 ID3D10Device_IASetPrimitiveTopology(device
, D3D10_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP
);
151 ID3D10Device_IASetVertexBuffers(device
, 0, 1, &render_target
->vb
,
152 &render_target
->vb_stride
, &offset
);
153 ID3D10Device_VSSetConstantBuffers(device
, 0, 1, &vs_cb
);
154 ID3D10Device_VSSetShader(device
, render_target
->vs
);
155 ID3D10Device_PSSetConstantBuffers(device
, 0, 1, &ps_cb
);
156 ID3D10Device_PSSetShader(device
, ps
);
157 ID3D10Device_RSSetViewports(device
, 1, &vp
);
158 if (render_target
->clip_stack
.count
)
160 const D2D1_RECT_F
*clip_rect
;
161 D3D10_RECT scissor_rect
;
163 clip_rect
= &render_target
->clip_stack
.stack
[render_target
->clip_stack
.count
- 1];
164 scissor_rect
.left
= clip_rect
->left
+ 0.5f
;
165 scissor_rect
.top
= clip_rect
->top
+ 0.5f
;
166 scissor_rect
.right
= clip_rect
->right
+ 0.5f
;
167 scissor_rect
.bottom
= clip_rect
->bottom
+ 0.5f
;
168 ID3D10Device_RSSetScissorRects(device
, 1, &scissor_rect
);
169 ID3D10Device_RSSetState(device
, render_target
->rs
);
171 ID3D10Device_OMSetRenderTargets(device
, 1, &render_target
->view
, NULL
);
174 ID3D10Device_OMSetBlendState(device
, render_target
->bs
, blend_factor
, D3D10_DEFAULT_SAMPLE_MASK
);
175 d2d_brush_bind_resources(brush
, device
);
178 ID3D10Device_Draw(device
, 4, 0);
180 if (FAILED(hr
= render_target
->stateblock
->lpVtbl
->Apply(render_target
->stateblock
)))
181 WARN("Failed to apply stateblock, hr %#x.\n", hr
);
184 static inline struct d2d_d3d_render_target
*impl_from_ID2D1RenderTarget(ID2D1RenderTarget
*iface
)
186 return CONTAINING_RECORD(iface
, struct d2d_d3d_render_target
, ID2D1RenderTarget_iface
);
189 static HRESULT STDMETHODCALLTYPE
d2d_d3d_render_target_QueryInterface(ID2D1RenderTarget
*iface
, REFIID iid
, void **out
)
191 TRACE("iface %p, iid %s, out %p.\n", iface
, debugstr_guid(iid
), out
);
193 if (IsEqualGUID(iid
, &IID_ID2D1RenderTarget
)
194 || IsEqualGUID(iid
, &IID_ID2D1Resource
)
195 || IsEqualGUID(iid
, &IID_IUnknown
))
197 ID2D1RenderTarget_AddRef(iface
);
202 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid
));
205 return E_NOINTERFACE
;
208 static ULONG STDMETHODCALLTYPE
d2d_d3d_render_target_AddRef(ID2D1RenderTarget
*iface
)
210 struct d2d_d3d_render_target
*render_target
= impl_from_ID2D1RenderTarget(iface
);
211 ULONG refcount
= InterlockedIncrement(&render_target
->refcount
);
213 TRACE("%p increasing refcount to %u.\n", iface
, refcount
);
218 static ULONG STDMETHODCALLTYPE
d2d_d3d_render_target_Release(ID2D1RenderTarget
*iface
)
220 struct d2d_d3d_render_target
*render_target
= impl_from_ID2D1RenderTarget(iface
);
221 ULONG refcount
= InterlockedDecrement(&render_target
->refcount
);
223 TRACE("%p decreasing refcount to %u.\n", iface
, refcount
);
227 d2d_clip_stack_cleanup(&render_target
->clip_stack
);
228 ID3D10PixelShader_Release(render_target
->rect_bitmap_ps
);
229 ID3D10PixelShader_Release(render_target
->rect_solid_ps
);
230 ID3D10BlendState_Release(render_target
->bs
);
231 ID3D10RasterizerState_Release(render_target
->rs
);
232 ID3D10VertexShader_Release(render_target
->vs
);
233 ID3D10Buffer_Release(render_target
->vb
);
234 ID3D10InputLayout_Release(render_target
->il
);
235 render_target
->stateblock
->lpVtbl
->Release(render_target
->stateblock
);
236 ID3D10RenderTargetView_Release(render_target
->view
);
237 ID3D10Device_Release(render_target
->device
);
238 HeapFree(GetProcessHeap(), 0, render_target
);
244 static void STDMETHODCALLTYPE
d2d_d3d_render_target_GetFactory(ID2D1RenderTarget
*iface
, ID2D1Factory
**factory
)
246 FIXME("iface %p, factory %p stub!\n", iface
, factory
);
251 static HRESULT STDMETHODCALLTYPE
d2d_d3d_render_target_CreateBitmap(ID2D1RenderTarget
*iface
,
252 D2D1_SIZE_U size
, const void *src_data
, UINT32 pitch
, const D2D1_BITMAP_PROPERTIES
*desc
, ID2D1Bitmap
**bitmap
)
254 struct d2d_d3d_render_target
*render_target
= impl_from_ID2D1RenderTarget(iface
);
255 struct d2d_bitmap
*object
;
258 TRACE("iface %p, size {%u, %u}, src_data %p, pitch %u, desc %p, bitmap %p.\n",
259 iface
, size
.width
, size
.height
, src_data
, pitch
, desc
, bitmap
);
261 if (!(object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*object
))))
262 return E_OUTOFMEMORY
;
264 if (FAILED(hr
= d2d_bitmap_init(object
, render_target
, size
, src_data
, pitch
, desc
)))
266 WARN("Failed to initialize bitmap, hr %#x.\n", hr
);
267 HeapFree(GetProcessHeap(), 0, object
);
271 TRACE("Created bitmap %p.\n", object
);
272 *bitmap
= &object
->ID2D1Bitmap_iface
;
277 static HRESULT STDMETHODCALLTYPE
d2d_d3d_render_target_CreateBitmapFromWicBitmap(ID2D1RenderTarget
*iface
,
278 IWICBitmapSource
*bitmap_source
, const D2D1_BITMAP_PROPERTIES
*desc
, ID2D1Bitmap
**bitmap
)
280 D2D1_BITMAP_PROPERTIES bitmap_desc
;
281 unsigned int bpp
, data_size
;
288 TRACE("iface %p, bitmap_source %p, desc %p, bitmap %p.\n",
289 iface
, bitmap_source
, desc
, bitmap
);
291 if (FAILED(hr
= IWICBitmapSource_GetSize(bitmap_source
, &size
.width
, &size
.height
)))
293 WARN("Failed to get bitmap size, hr %#x.\n", hr
);
299 bitmap_desc
.pixelFormat
.format
= DXGI_FORMAT_UNKNOWN
;
300 bitmap_desc
.pixelFormat
.alphaMode
= D2D1_ALPHA_MODE_UNKNOWN
;
301 bitmap_desc
.dpiX
= 0.0f
;
302 bitmap_desc
.dpiY
= 0.0f
;
309 if (bitmap_desc
.pixelFormat
.format
== DXGI_FORMAT_UNKNOWN
)
311 WICPixelFormatGUID wic_format
;
313 if (FAILED(hr
= IWICBitmapSource_GetPixelFormat(bitmap_source
, &wic_format
)))
315 WARN("Failed to get bitmap format, hr %#x.\n", hr
);
319 if (IsEqualGUID(&wic_format
, &GUID_WICPixelFormat32bppPBGRA
)
320 || IsEqualGUID(&wic_format
, &GUID_WICPixelFormat32bppBGR
))
322 bitmap_desc
.pixelFormat
.format
= DXGI_FORMAT_B8G8R8A8_UNORM
;
326 WARN("Unsupported WIC bitmap format %s.\n", debugstr_guid(&wic_format
));
327 return D2DERR_UNSUPPORTED_PIXEL_FORMAT
;
331 switch (bitmap_desc
.pixelFormat
.format
)
333 case DXGI_FORMAT_B8G8R8A8_UNORM
:
338 FIXME("Unhandled format %#x.\n", bitmap_desc
.pixelFormat
.format
);
339 return D2DERR_UNSUPPORTED_PIXEL_FORMAT
;
342 pitch
= ((bpp
* size
.width
) + 15) & ~15;
343 data_size
= pitch
* size
.height
;
344 if (!(data
= HeapAlloc(GetProcessHeap(), 0, data_size
)))
345 return E_OUTOFMEMORY
;
349 rect
.Width
= size
.width
;
350 rect
.Height
= size
.height
;
351 if (FAILED(hr
= IWICBitmapSource_CopyPixels(bitmap_source
, &rect
, pitch
, data_size
, data
)))
353 WARN("Failed to copy bitmap pixels, hr %#x.\n", hr
);
354 HeapFree(GetProcessHeap(), 0, data
);
358 hr
= d2d_d3d_render_target_CreateBitmap(iface
, size
, data
, pitch
, &bitmap_desc
, bitmap
);
360 HeapFree(GetProcessHeap(), 0, data
);
365 static HRESULT STDMETHODCALLTYPE
d2d_d3d_render_target_CreateSharedBitmap(ID2D1RenderTarget
*iface
,
366 REFIID iid
, void *data
, const D2D1_BITMAP_PROPERTIES
*desc
, ID2D1Bitmap
**bitmap
)
368 FIXME("iface %p, iid %s, data %p, desc %p, bitmap %p stub!\n",
369 iface
, debugstr_guid(iid
), data
, desc
, bitmap
);
374 static HRESULT STDMETHODCALLTYPE
d2d_d3d_render_target_CreateBitmapBrush(ID2D1RenderTarget
*iface
,
375 ID2D1Bitmap
*bitmap
, const D2D1_BITMAP_BRUSH_PROPERTIES
*bitmap_brush_desc
,
376 const D2D1_BRUSH_PROPERTIES
*brush_desc
, ID2D1BitmapBrush
**brush
)
378 struct d2d_d3d_render_target
*render_target
= impl_from_ID2D1RenderTarget(iface
);
379 struct d2d_brush
*object
;
382 TRACE("iface %p, bitmap %p, bitmap_brush_desc %p, brush_desc %p, brush %p.\n",
383 iface
, bitmap
, bitmap_brush_desc
, brush_desc
, brush
);
385 if (!(object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*object
))))
386 return E_OUTOFMEMORY
;
388 if (FAILED(hr
= d2d_bitmap_brush_init(object
, render_target
, bitmap
, bitmap_brush_desc
, brush_desc
)))
390 WARN("Failed to initialize brush, hr %#x.\n", hr
);
391 HeapFree(GetProcessHeap(), 0, object
);
395 TRACE("Created brush %p.\n", object
);
396 *brush
= (ID2D1BitmapBrush
*)&object
->ID2D1Brush_iface
;
401 static HRESULT STDMETHODCALLTYPE
d2d_d3d_render_target_CreateSolidColorBrush(ID2D1RenderTarget
*iface
,
402 const D2D1_COLOR_F
*color
, const D2D1_BRUSH_PROPERTIES
*desc
, ID2D1SolidColorBrush
**brush
)
404 struct d2d_brush
*object
;
406 TRACE("iface %p, color %p, desc %p, brush %p.\n", iface
, color
, desc
, brush
);
408 if (!(object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*object
))))
409 return E_OUTOFMEMORY
;
411 d2d_solid_color_brush_init(object
, iface
, color
, desc
);
413 TRACE("Created brush %p.\n", object
);
414 *brush
= (ID2D1SolidColorBrush
*)&object
->ID2D1Brush_iface
;
419 static HRESULT STDMETHODCALLTYPE
d2d_d3d_render_target_CreateGradientStopCollection(ID2D1RenderTarget
*iface
,
420 const D2D1_GRADIENT_STOP
*stops
, UINT32 stop_count
, D2D1_GAMMA gamma
, D2D1_EXTEND_MODE extend_mode
,
421 ID2D1GradientStopCollection
**gradient
)
423 struct d2d_gradient
*object
;
426 TRACE("iface %p, stops %p, stop_count %u, gamma %#x, extend_mode %#x, gradient %p.\n",
427 iface
, stops
, stop_count
, gamma
, extend_mode
, gradient
);
429 if (!(object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*object
))))
430 return E_OUTOFMEMORY
;
432 if (FAILED(hr
= d2d_gradient_init(object
, iface
, stops
, stop_count
, gamma
, extend_mode
)))
434 WARN("Failed to initialize gradient, hr %#x.\n", hr
);
435 HeapFree(GetProcessHeap(), 0, object
);
439 TRACE("Created gradient %p.\n", object
);
440 *gradient
= &object
->ID2D1GradientStopCollection_iface
;
445 static HRESULT STDMETHODCALLTYPE
d2d_d3d_render_target_CreateLinearGradientBrush(ID2D1RenderTarget
*iface
,
446 const D2D1_LINEAR_GRADIENT_BRUSH_PROPERTIES
*gradient_brush_desc
, const D2D1_BRUSH_PROPERTIES
*brush_desc
,
447 ID2D1GradientStopCollection
*gradient
, ID2D1LinearGradientBrush
**brush
)
449 struct d2d_brush
*object
;
451 TRACE("iface %p, gradient_brush_desc %p, brush_desc %p, gradient %p, brush %p.\n",
452 iface
, gradient_brush_desc
, brush_desc
, gradient
, brush
);
454 if (!(object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*object
))))
455 return E_OUTOFMEMORY
;
457 d2d_linear_gradient_brush_init(object
, iface
, gradient_brush_desc
, brush_desc
, gradient
);
459 TRACE("Created brush %p.\n", object
);
460 *brush
= (ID2D1LinearGradientBrush
*)&object
->ID2D1Brush_iface
;
465 static HRESULT STDMETHODCALLTYPE
d2d_d3d_render_target_CreateRadialGradientBrush(ID2D1RenderTarget
*iface
,
466 const D2D1_RADIAL_GRADIENT_BRUSH_PROPERTIES
*gradient_brush_desc
, const D2D1_BRUSH_PROPERTIES
*brush_desc
,
467 ID2D1GradientStopCollection
*gradient
, ID2D1RadialGradientBrush
**brush
)
469 FIXME("iface %p, gradient_brush_desc %p, brush_desc %p, gradient %p, brush %p stub!\n",
470 iface
, gradient_brush_desc
, brush_desc
, gradient
, brush
);
475 static HRESULT STDMETHODCALLTYPE
d2d_d3d_render_target_CreateCompatibleRenderTarget(ID2D1RenderTarget
*iface
,
476 const D2D1_SIZE_F
*size
, const D2D1_SIZE_U
*pixel_size
, const D2D1_PIXEL_FORMAT
*format
,
477 D2D1_COMPATIBLE_RENDER_TARGET_OPTIONS options
, ID2D1BitmapRenderTarget
**render_target
)
479 FIXME("iface %p, size %p, pixel_size %p, format %p, options %#x, render_target %p stub!\n",
480 iface
, size
, pixel_size
, format
, options
, render_target
);
485 static HRESULT STDMETHODCALLTYPE
d2d_d3d_render_target_CreateLayer(ID2D1RenderTarget
*iface
,
486 const D2D1_SIZE_F
*size
, ID2D1Layer
**layer
)
488 FIXME("iface %p, size %p, layer %p stub!\n", iface
, size
, layer
);
493 static HRESULT STDMETHODCALLTYPE
d2d_d3d_render_target_CreateMesh(ID2D1RenderTarget
*iface
, ID2D1Mesh
**mesh
)
495 struct d2d_mesh
*object
;
497 TRACE("iface %p, mesh %p.\n", iface
, mesh
);
499 if (!(object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*object
))))
500 return E_OUTOFMEMORY
;
502 d2d_mesh_init(object
);
504 TRACE("Created mesh %p.\n", object
);
505 *mesh
= &object
->ID2D1Mesh_iface
;
510 static void STDMETHODCALLTYPE
d2d_d3d_render_target_DrawLine(ID2D1RenderTarget
*iface
,
511 D2D1_POINT_2F p0
, D2D1_POINT_2F p1
, ID2D1Brush
*brush
, float stroke_width
, ID2D1StrokeStyle
*stroke_style
)
513 FIXME("iface %p, p0 {%.8e, %.8e}, p1 {%.8e, %.8e}, brush %p, stroke_width %.8e, stroke_style %p stub!\n",
514 iface
, p0
.x
, p0
.y
, p1
.x
, p1
.y
, brush
, stroke_width
, stroke_style
);
517 static void STDMETHODCALLTYPE
d2d_d3d_render_target_DrawRectangle(ID2D1RenderTarget
*iface
,
518 const D2D1_RECT_F
*rect
, ID2D1Brush
*brush
, float stroke_width
, ID2D1StrokeStyle
*stroke_style
)
520 FIXME("iface %p, rect %p, brush %p, stroke_width %.8e, stroke_style %p stub!\n",
521 iface
, rect
, brush
, stroke_width
, stroke_style
);
524 static void STDMETHODCALLTYPE
d2d_d3d_render_target_FillRectangle(ID2D1RenderTarget
*iface
,
525 const D2D1_RECT_F
*rect
, ID2D1Brush
*brush
)
527 struct d2d_d3d_render_target
*render_target
= impl_from_ID2D1RenderTarget(iface
);
528 struct d2d_brush
*brush_impl
= unsafe_impl_from_ID2D1Brush(brush
);
529 D3D10_SUBRESOURCE_DATA buffer_data
;
530 D3D10_BUFFER_DESC buffer_desc
;
531 ID3D10Buffer
*vs_cb
, *ps_cb
;
532 ID3D10PixelShader
*ps
;
538 float _11
, _21
, _31
, pad0
;
539 float _12
, _22
, _32
, pad1
;
540 } transform
, transform_inverse
;
542 TRACE("iface %p, rect %p, brush %p.\n", iface
, rect
, brush
);
544 if (brush_impl
->type
!= D2D_BRUSH_TYPE_SOLID
545 && brush_impl
->type
!= D2D_BRUSH_TYPE_BITMAP
)
547 FIXME("Unhandled brush type %#x.\n", brush_impl
->type
);
551 /* Translate from clip space to world (D2D rendertarget) space, taking the
552 * dpi and rendertarget transform into account. */
553 tmp_x
= (2.0f
* render_target
->dpi_x
) / (96.0f
* render_target
->pixel_size
.width
);
554 tmp_y
= -(2.0f
* render_target
->dpi_y
) / (96.0f
* render_target
->pixel_size
.height
);
555 transform
._11
= render_target
->transform
._11
* tmp_x
;
556 transform
._21
= render_target
->transform
._21
* tmp_x
;
557 transform
._31
= render_target
->transform
._31
* tmp_x
- 1.0f
;
558 transform
.pad0
= 0.0f
;
559 transform
._12
= render_target
->transform
._12
* tmp_y
;
560 transform
._22
= render_target
->transform
._22
* tmp_y
;
561 transform
._32
= render_target
->transform
._32
* tmp_y
+ 1.0f
;
562 transform
.pad1
= 0.0f
;
564 /* Translate from world space to object space. */
565 tmp_x
= rect
->left
+ (rect
->right
- rect
->left
) / 2.0f
;
566 tmp_y
= rect
->top
+ (rect
->bottom
- rect
->top
) / 2.0f
;
567 transform
._31
+= tmp_x
* transform
._11
+ tmp_y
* transform
._21
;
568 transform
._32
+= tmp_x
* transform
._12
+ tmp_y
* transform
._22
;
569 tmp_x
= (rect
->right
- rect
->left
) / 2.0f
;
570 tmp_y
= (rect
->bottom
- rect
->top
) / 2.0f
;
571 transform
._11
*= tmp_x
;
572 transform
._12
*= tmp_x
;
573 transform
._21
*= tmp_y
;
574 transform
._22
*= tmp_y
;
576 buffer_desc
.ByteWidth
= sizeof(transform
);
577 buffer_desc
.Usage
= D3D10_USAGE_DEFAULT
;
578 buffer_desc
.BindFlags
= D3D10_BIND_CONSTANT_BUFFER
;
579 buffer_desc
.CPUAccessFlags
= 0;
580 buffer_desc
.MiscFlags
= 0;
582 buffer_data
.pSysMem
= &transform
;
583 buffer_data
.SysMemPitch
= 0;
584 buffer_data
.SysMemSlicePitch
= 0;
586 if (FAILED(hr
= ID3D10Device_CreateBuffer(render_target
->device
, &buffer_desc
, &buffer_data
, &vs_cb
)))
588 WARN("Failed to create constant buffer, hr %#x.\n", hr
);
592 if (brush_impl
->type
== D2D_BRUSH_TYPE_BITMAP
)
594 struct d2d_bitmap
*bitmap
= brush_impl
->u
.bitmap
.bitmap
;
595 float rt_scale
, rt_bitmap_scale
, d
;
597 ps
= render_target
->rect_bitmap_ps
;
599 /* Scale for bitmap size and dpi. */
600 rt_scale
= render_target
->dpi_x
/ 96.0f
;
601 rt_bitmap_scale
= bitmap
->pixel_size
.width
* (bitmap
->dpi_x
/ 96.0f
) * rt_scale
;
602 transform
._11
= brush_impl
->transform
._11
* rt_bitmap_scale
;
603 transform
._21
= brush_impl
->transform
._21
* rt_bitmap_scale
;
604 transform
._31
= brush_impl
->transform
._31
* rt_scale
;
605 rt_scale
= render_target
->dpi_y
/ 96.0f
;
606 rt_bitmap_scale
= bitmap
->pixel_size
.height
* (bitmap
->dpi_y
/ 96.0f
) * rt_scale
;
607 transform
._12
= brush_impl
->transform
._12
* rt_bitmap_scale
;
608 transform
._22
= brush_impl
->transform
._22
* rt_bitmap_scale
;
609 transform
._32
= brush_impl
->transform
._32
* rt_scale
;
611 /* Invert the matrix. (Because the matrix is applied to the sampling
612 * coordinates. I.e., to scale the bitmap by 2 we need to divide the
613 * coordinates by 2.) */
614 d
= transform
._11
* transform
._22
- transform
._21
* transform
._22
;
617 transform_inverse
._11
= transform
._22
/ d
;
618 transform_inverse
._21
= -transform
._21
/ d
;
619 transform_inverse
._31
= (transform
._21
* transform
._32
- transform
._31
* transform
._22
) / d
;
620 transform_inverse
._12
= -transform
._12
/ d
;
621 transform_inverse
._22
= transform
._11
/ d
;
622 transform_inverse
._32
= -(transform
._11
* transform
._32
- transform
._31
* transform
._12
) / d
;
625 buffer_desc
.ByteWidth
= sizeof(transform_inverse
);
626 buffer_data
.pSysMem
= &transform_inverse
;
630 ps
= render_target
->rect_solid_ps
;
632 color
= brush_impl
->u
.solid
.color
;
633 color
.r
*= brush_impl
->opacity
;
634 color
.g
*= brush_impl
->opacity
;
635 color
.b
*= brush_impl
->opacity
;
636 color
.a
*= brush_impl
->opacity
;
638 buffer_desc
.ByteWidth
= sizeof(color
);
639 buffer_data
.pSysMem
= &color
;
642 if (FAILED(hr
= ID3D10Device_CreateBuffer(render_target
->device
, &buffer_desc
, &buffer_data
, &ps_cb
)))
644 WARN("Failed to create constant buffer, hr %#x.\n", hr
);
645 ID3D10Buffer_Release(vs_cb
);
649 d2d_draw(render_target
, vs_cb
, ps
, ps_cb
, brush_impl
);
651 ID3D10Buffer_Release(ps_cb
);
652 ID3D10Buffer_Release(vs_cb
);
655 static void STDMETHODCALLTYPE
d2d_d3d_render_target_DrawRoundedRectangle(ID2D1RenderTarget
*iface
,
656 const D2D1_ROUNDED_RECT
*rect
, ID2D1Brush
*brush
, float stroke_width
, ID2D1StrokeStyle
*stroke_style
)
658 FIXME("iface %p, rect %p, brush %p, stroke_width %.8e, stroke_style %p stub!\n",
659 iface
, rect
, brush
, stroke_width
, stroke_style
);
662 static void STDMETHODCALLTYPE
d2d_d3d_render_target_FillRoundedRectangle(ID2D1RenderTarget
*iface
,
663 const D2D1_ROUNDED_RECT
*rect
, ID2D1Brush
*brush
)
665 FIXME("iface %p, rect %p, brush %p stub!\n", iface
, rect
, brush
);
668 static void STDMETHODCALLTYPE
d2d_d3d_render_target_DrawEllipse(ID2D1RenderTarget
*iface
,
669 const D2D1_ELLIPSE
*ellipse
, ID2D1Brush
*brush
, float stroke_width
, ID2D1StrokeStyle
*stroke_style
)
671 FIXME("iface %p, ellipse %p, brush %p, stroke_width %.8e, stroke_style %p stub!\n",
672 iface
, ellipse
, brush
, stroke_width
, stroke_style
);
675 static void STDMETHODCALLTYPE
d2d_d3d_render_target_FillEllipse(ID2D1RenderTarget
*iface
,
676 const D2D1_ELLIPSE
*ellipse
, ID2D1Brush
*brush
)
678 FIXME("iface %p, ellipse %p, brush %p stub!\n", iface
, ellipse
, brush
);
681 static void STDMETHODCALLTYPE
d2d_d3d_render_target_DrawGeometry(ID2D1RenderTarget
*iface
,
682 ID2D1Geometry
*geometry
, ID2D1Brush
*brush
, float stroke_width
, ID2D1StrokeStyle
*stroke_style
)
684 FIXME("iface %p, geometry %p, brush %p, stroke_width %.8e, stroke_style %p stub!\n",
685 iface
, geometry
, brush
, stroke_width
, stroke_style
);
688 static void STDMETHODCALLTYPE
d2d_d3d_render_target_FillGeometry(ID2D1RenderTarget
*iface
,
689 ID2D1Geometry
*geometry
, ID2D1Brush
*brush
, ID2D1Brush
*opacity_brush
)
691 FIXME("iface %p, geometry %p, brush %p, opacity_brush %p stub!\n", iface
, geometry
, brush
, opacity_brush
);
694 static void STDMETHODCALLTYPE
d2d_d3d_render_target_FillMesh(ID2D1RenderTarget
*iface
,
695 ID2D1Mesh
*mesh
, ID2D1Brush
*brush
)
697 FIXME("iface %p, mesh %p, brush %p stub!\n", iface
, mesh
, brush
);
700 static void STDMETHODCALLTYPE
d2d_d3d_render_target_FillOpacityMask(ID2D1RenderTarget
*iface
,
701 ID2D1Bitmap
*mask
, ID2D1Brush
*brush
, D2D1_OPACITY_MASK_CONTENT content
,
702 const D2D1_RECT_F
*dst_rect
, const D2D1_RECT_F
*src_rect
)
704 FIXME("iface %p, mask %p, brush %p, content %#x, dst_rect %p, src_rect %p stub!\n",
705 iface
, mask
, brush
, content
, dst_rect
, src_rect
);
708 static void STDMETHODCALLTYPE
d2d_d3d_render_target_DrawBitmap(ID2D1RenderTarget
*iface
,
709 ID2D1Bitmap
*bitmap
, const D2D1_RECT_F
*dst_rect
, float opacity
,
710 D2D1_BITMAP_INTERPOLATION_MODE interpolation_mode
, const D2D1_RECT_F
*src_rect
)
712 D2D1_BITMAP_BRUSH_PROPERTIES bitmap_brush_desc
;
713 D2D1_BRUSH_PROPERTIES brush_desc
;
714 ID2D1BitmapBrush
*brush
;
718 TRACE("iface %p, bitmap %p, dst_rect %p, opacity %.8e, interpolation_mode %#x, src_rect %p.\n",
719 iface
, bitmap
, dst_rect
, opacity
, interpolation_mode
, src_rect
);
729 size
= ID2D1Bitmap_GetSize(bitmap
);
732 s
.right
= size
.width
;
733 s
.bottom
= size
.height
;
744 d
.right
= s
.right
- s
.left
;
745 d
.bottom
= s
.bottom
- s
.top
;
748 bitmap_brush_desc
.extendModeX
= D2D1_EXTEND_MODE_CLAMP
;
749 bitmap_brush_desc
.extendModeY
= D2D1_EXTEND_MODE_CLAMP
;
750 bitmap_brush_desc
.interpolationMode
= interpolation_mode
;
752 brush_desc
.opacity
= opacity
;
753 brush_desc
.transform
._11
= (d
.right
- d
.left
) / (s
.right
- s
.left
);
754 brush_desc
.transform
._21
= 0.0f
;
755 brush_desc
.transform
._31
= d
.left
;
756 brush_desc
.transform
._12
= 0.0f
;
757 brush_desc
.transform
._22
= (d
.bottom
- d
.top
) / (s
.bottom
- s
.top
);
758 brush_desc
.transform
._32
= d
.top
;
760 if (FAILED(hr
= ID2D1RenderTarget_CreateBitmapBrush(iface
, bitmap
, &bitmap_brush_desc
, &brush_desc
, &brush
)))
762 ERR("Failed to create bitmap brush, hr %#x.\n", hr
);
766 ID2D1RenderTarget_FillRectangle(iface
, &d
, (ID2D1Brush
*)brush
);
767 ID2D1BitmapBrush_Release(brush
);
770 static void STDMETHODCALLTYPE
d2d_d3d_render_target_DrawText(ID2D1RenderTarget
*iface
,
771 const WCHAR
*string
, UINT32 string_len
, IDWriteTextFormat
*text_format
, const D2D1_RECT_F
*layout_rect
,
772 ID2D1Brush
*brush
, D2D1_DRAW_TEXT_OPTIONS options
, DWRITE_MEASURING_MODE measuring_mode
)
774 FIXME("iface %p, string %s, string_len %u, text_format %p, layout_rect %p, "
775 "brush %p, options %#x, measuring_mode %#x stub!\n",
776 iface
, debugstr_wn(string
, string_len
), string_len
, text_format
, layout_rect
,
777 brush
, options
, measuring_mode
);
780 static void STDMETHODCALLTYPE
d2d_d3d_render_target_DrawTextLayout(ID2D1RenderTarget
*iface
,
781 D2D1_POINT_2F origin
, IDWriteTextLayout
*layout
, ID2D1Brush
*brush
, D2D1_DRAW_TEXT_OPTIONS options
)
783 struct d2d_d3d_render_target
*render_target
= impl_from_ID2D1RenderTarget(iface
);
784 struct d2d_draw_text_layout_ctx ctx
;
787 TRACE("iface %p, origin {%.8e, %.8e}, layout %p, brush %p, options %#x.\n",
788 iface
, origin
.x
, origin
.y
, layout
, brush
, options
);
791 ctx
.options
= options
;
793 if (FAILED(hr
= IDWriteTextLayout_Draw(layout
,
794 &ctx
, &render_target
->IDWriteTextRenderer_iface
, origin
.x
, origin
.y
)))
795 FIXME("Failed to draw text layout, hr %#x.\n", hr
);
798 static void STDMETHODCALLTYPE
d2d_d3d_render_target_DrawGlyphRun(ID2D1RenderTarget
*iface
,
799 D2D1_POINT_2F baseline_origin
, const DWRITE_GLYPH_RUN
*glyph_run
, ID2D1Brush
*brush
,
800 DWRITE_MEASURING_MODE measuring_mode
)
802 FIXME("iface %p, baseline_origin {%.8e, %.8e}, glyph_run %p, brush %p, measuring_mode %#x stub!\n",
803 iface
, baseline_origin
.x
, baseline_origin
.y
, glyph_run
, brush
, measuring_mode
);
806 static void STDMETHODCALLTYPE
d2d_d3d_render_target_SetTransform(ID2D1RenderTarget
*iface
,
807 const D2D1_MATRIX_3X2_F
*transform
)
809 struct d2d_d3d_render_target
*render_target
= impl_from_ID2D1RenderTarget(iface
);
811 TRACE("iface %p, transform %p.\n", iface
, transform
);
813 render_target
->transform
= *transform
;
816 static void STDMETHODCALLTYPE
d2d_d3d_render_target_GetTransform(ID2D1RenderTarget
*iface
,
817 D2D1_MATRIX_3X2_F
*transform
)
819 struct d2d_d3d_render_target
*render_target
= impl_from_ID2D1RenderTarget(iface
);
821 TRACE("iface %p, transform %p.\n", iface
, transform
);
823 *transform
= render_target
->transform
;
826 static void STDMETHODCALLTYPE
d2d_d3d_render_target_SetAntialiasMode(ID2D1RenderTarget
*iface
,
827 D2D1_ANTIALIAS_MODE antialias_mode
)
829 FIXME("iface %p, antialias_mode %#x stub!\n", iface
, antialias_mode
);
832 static D2D1_ANTIALIAS_MODE STDMETHODCALLTYPE
d2d_d3d_render_target_GetAntialiasMode(ID2D1RenderTarget
*iface
)
834 FIXME("iface %p stub!\n", iface
);
836 return D2D1_ANTIALIAS_MODE_PER_PRIMITIVE
;
839 static void STDMETHODCALLTYPE
d2d_d3d_render_target_SetTextAntialiasMode(ID2D1RenderTarget
*iface
,
840 D2D1_TEXT_ANTIALIAS_MODE antialias_mode
)
842 FIXME("iface %p, antialias_mode %#x stub!\n", iface
, antialias_mode
);
845 static D2D1_TEXT_ANTIALIAS_MODE STDMETHODCALLTYPE
d2d_d3d_render_target_GetTextAntialiasMode(ID2D1RenderTarget
*iface
)
847 FIXME("iface %p stub!\n", iface
);
849 return D2D1_TEXT_ANTIALIAS_MODE_DEFAULT
;
852 static void STDMETHODCALLTYPE
d2d_d3d_render_target_SetTextRenderingParams(ID2D1RenderTarget
*iface
,
853 IDWriteRenderingParams
*text_rendering_params
)
855 FIXME("iface %p, text_rendering_params %p stub!\n", iface
, text_rendering_params
);
858 static void STDMETHODCALLTYPE
d2d_d3d_render_target_GetTextRenderingParams(ID2D1RenderTarget
*iface
,
859 IDWriteRenderingParams
**text_rendering_params
)
861 FIXME("iface %p, text_rendering_params %p stub!\n", iface
, text_rendering_params
);
863 *text_rendering_params
= NULL
;
866 static void STDMETHODCALLTYPE
d2d_d3d_render_target_SetTags(ID2D1RenderTarget
*iface
, D2D1_TAG tag1
, D2D1_TAG tag2
)
868 FIXME("iface %p, tag1 %s, tag2 %s stub!\n", iface
, wine_dbgstr_longlong(tag1
), wine_dbgstr_longlong(tag2
));
871 static void STDMETHODCALLTYPE
d2d_d3d_render_target_GetTags(ID2D1RenderTarget
*iface
, D2D1_TAG
*tag1
, D2D1_TAG
*tag2
)
873 FIXME("iface %p, tag1 %p, tag2 %p stub!\n", iface
, tag1
, tag2
);
879 static void STDMETHODCALLTYPE
d2d_d3d_render_target_PushLayer(ID2D1RenderTarget
*iface
,
880 const D2D1_LAYER_PARAMETERS
*layer_parameters
, ID2D1Layer
*layer
)
882 FIXME("iface %p, layer_parameters %p, layer %p stub!\n", iface
, layer_parameters
, layer
);
885 static void STDMETHODCALLTYPE
d2d_d3d_render_target_PopLayer(ID2D1RenderTarget
*iface
)
887 FIXME("iface %p stub!\n", iface
);
890 static HRESULT STDMETHODCALLTYPE
d2d_d3d_render_target_Flush(ID2D1RenderTarget
*iface
, D2D1_TAG
*tag1
, D2D1_TAG
*tag2
)
892 FIXME("iface %p, tag1 %p, tag2 %p stub!\n", iface
, tag1
, tag2
);
897 static void STDMETHODCALLTYPE
d2d_d3d_render_target_SaveDrawingState(ID2D1RenderTarget
*iface
,
898 ID2D1DrawingStateBlock
*state_block
)
900 FIXME("iface %p, state_block %p stub!\n", iface
, state_block
);
903 static void STDMETHODCALLTYPE
d2d_d3d_render_target_RestoreDrawingState(ID2D1RenderTarget
*iface
,
904 ID2D1DrawingStateBlock
*state_block
)
906 FIXME("iface %p, state_block %p stub!\n", iface
, state_block
);
909 static void STDMETHODCALLTYPE
d2d_d3d_render_target_PushAxisAlignedClip(ID2D1RenderTarget
*iface
,
910 const D2D1_RECT_F
*clip_rect
, D2D1_ANTIALIAS_MODE antialias_mode
)
912 struct d2d_d3d_render_target
*render_target
= impl_from_ID2D1RenderTarget(iface
);
913 D2D1_RECT_F transformed_rect
;
914 float x_scale
, y_scale
;
917 TRACE("iface %p, clip_rect %p, antialias_mode %#x.\n", iface
, clip_rect
, antialias_mode
);
919 if (antialias_mode
!= D2D1_ANTIALIAS_MODE_ALIASED
)
920 FIXME("Ignoring antialias_mode %#x.\n", antialias_mode
);
922 x_scale
= render_target
->dpi_x
/ 96.0f
;
923 y_scale
= render_target
->dpi_y
/ 96.0f
;
924 d2d_point_transform(&point
, &render_target
->transform
, clip_rect
->left
* x_scale
, clip_rect
->top
* y_scale
);
925 d2d_rect_set(&transformed_rect
, point
.x
, point
.y
, point
.x
, point
.y
);
926 d2d_point_transform(&point
, &render_target
->transform
, clip_rect
->left
* x_scale
, clip_rect
->bottom
* y_scale
);
927 d2d_rect_expand(&transformed_rect
, &point
);
928 d2d_point_transform(&point
, &render_target
->transform
, clip_rect
->right
* x_scale
, clip_rect
->top
* y_scale
);
929 d2d_rect_expand(&transformed_rect
, &point
);
930 d2d_point_transform(&point
, &render_target
->transform
, clip_rect
->right
* x_scale
, clip_rect
->bottom
* y_scale
);
931 d2d_rect_expand(&transformed_rect
, &point
);
933 if (!d2d_clip_stack_push(&render_target
->clip_stack
, &transformed_rect
))
934 WARN("Failed to push clip rect.\n");
937 static void STDMETHODCALLTYPE
d2d_d3d_render_target_PopAxisAlignedClip(ID2D1RenderTarget
*iface
)
939 struct d2d_d3d_render_target
*render_target
= impl_from_ID2D1RenderTarget(iface
);
941 TRACE("iface %p.\n", iface
);
943 d2d_clip_stack_pop(&render_target
->clip_stack
);
946 static void STDMETHODCALLTYPE
d2d_d3d_render_target_Clear(ID2D1RenderTarget
*iface
, const D2D1_COLOR_F
*color
)
948 struct d2d_d3d_render_target
*render_target
= impl_from_ID2D1RenderTarget(iface
);
949 D3D10_SUBRESOURCE_DATA buffer_data
;
950 D3D10_BUFFER_DESC buffer_desc
;
951 ID3D10Buffer
*vs_cb
, *ps_cb
;
954 static const float transform
[] =
956 1.0f
, 0.0f
, 0.0f
, 0.0f
,
957 0.0f
, -1.0f
, 0.0f
, 0.0f
,
960 TRACE("iface %p, color %p.\n", iface
, color
);
962 buffer_desc
.ByteWidth
= sizeof(transform
);
963 buffer_desc
.Usage
= D3D10_USAGE_DEFAULT
;
964 buffer_desc
.BindFlags
= D3D10_BIND_CONSTANT_BUFFER
;
965 buffer_desc
.CPUAccessFlags
= 0;
966 buffer_desc
.MiscFlags
= 0;
968 buffer_data
.pSysMem
= transform
;
969 buffer_data
.SysMemPitch
= 0;
970 buffer_data
.SysMemSlicePitch
= 0;
972 if (FAILED(hr
= ID3D10Device_CreateBuffer(render_target
->device
, &buffer_desc
, &buffer_data
, &vs_cb
)))
974 WARN("Failed to create constant buffer, hr %#x.\n", hr
);
978 buffer_desc
.ByteWidth
= sizeof(*color
);
979 buffer_data
.pSysMem
= color
;
981 if (FAILED(hr
= ID3D10Device_CreateBuffer(render_target
->device
, &buffer_desc
, &buffer_data
, &ps_cb
)))
983 WARN("Failed to create constant buffer, hr %#x.\n", hr
);
984 ID3D10Buffer_Release(vs_cb
);
988 d2d_draw(render_target
, vs_cb
, render_target
->rect_solid_ps
, ps_cb
, NULL
);
990 ID3D10Buffer_Release(ps_cb
);
991 ID3D10Buffer_Release(vs_cb
);
994 static void STDMETHODCALLTYPE
d2d_d3d_render_target_BeginDraw(ID2D1RenderTarget
*iface
)
996 TRACE("iface %p.\n", iface
);
999 static HRESULT STDMETHODCALLTYPE
d2d_d3d_render_target_EndDraw(ID2D1RenderTarget
*iface
,
1000 D2D1_TAG
*tag1
, D2D1_TAG
*tag2
)
1002 TRACE("iface %p, tag1 %p, tag2 %p.\n", iface
, tag1
, tag2
);
1012 static D2D1_PIXEL_FORMAT
* STDMETHODCALLTYPE
d2d_d3d_render_target_GetPixelFormat(ID2D1RenderTarget
*iface
,
1013 D2D1_PIXEL_FORMAT
*format
)
1015 FIXME("iface %p, format %p stub!\n", iface
, format
);
1017 format
->format
= DXGI_FORMAT_UNKNOWN
;
1018 format
->alphaMode
= D2D1_ALPHA_MODE_UNKNOWN
;
1022 static void STDMETHODCALLTYPE
d2d_d3d_render_target_SetDpi(ID2D1RenderTarget
*iface
, float dpi_x
, float dpi_y
)
1024 struct d2d_d3d_render_target
*render_target
= impl_from_ID2D1RenderTarget(iface
);
1026 TRACE("iface %p, dpi_x %.8e, dpi_y %.8e.\n", iface
, dpi_x
, dpi_y
);
1028 if (dpi_x
== 0.0f
&& dpi_y
== 0.0f
)
1034 render_target
->dpi_x
= dpi_x
;
1035 render_target
->dpi_y
= dpi_y
;
1038 static void STDMETHODCALLTYPE
d2d_d3d_render_target_GetDpi(ID2D1RenderTarget
*iface
, float *dpi_x
, float *dpi_y
)
1040 struct d2d_d3d_render_target
*render_target
= impl_from_ID2D1RenderTarget(iface
);
1042 TRACE("iface %p, dpi_x %p, dpi_y %p.\n", iface
, dpi_x
, dpi_y
);
1044 *dpi_x
= render_target
->dpi_x
;
1045 *dpi_y
= render_target
->dpi_y
;
1048 static D2D1_SIZE_F
* STDMETHODCALLTYPE
d2d_d3d_render_target_GetSize(ID2D1RenderTarget
*iface
, D2D1_SIZE_F
*size
)
1050 struct d2d_d3d_render_target
*render_target
= impl_from_ID2D1RenderTarget(iface
);
1052 TRACE("iface %p, size %p.\n", iface
, size
);
1054 size
->width
= render_target
->pixel_size
.width
/ (render_target
->dpi_x
/ 96.0f
);
1055 size
->height
= render_target
->pixel_size
.height
/ (render_target
->dpi_y
/ 96.0f
);
1059 static D2D1_SIZE_U
* STDMETHODCALLTYPE
d2d_d3d_render_target_GetPixelSize(ID2D1RenderTarget
*iface
,
1060 D2D1_SIZE_U
*pixel_size
)
1062 struct d2d_d3d_render_target
*render_target
= impl_from_ID2D1RenderTarget(iface
);
1064 TRACE("iface %p, pixel_size %p.\n", iface
, pixel_size
);
1066 *pixel_size
= render_target
->pixel_size
;
1070 static UINT32 STDMETHODCALLTYPE
d2d_d3d_render_target_GetMaximumBitmapSize(ID2D1RenderTarget
*iface
)
1072 FIXME("iface %p stub!\n", iface
);
1077 static BOOL STDMETHODCALLTYPE
d2d_d3d_render_target_IsSupported(ID2D1RenderTarget
*iface
,
1078 const D2D1_RENDER_TARGET_PROPERTIES
*desc
)
1080 FIXME("iface %p, desc %p stub!\n", iface
, desc
);
1085 static const struct ID2D1RenderTargetVtbl d2d_d3d_render_target_vtbl
=
1087 d2d_d3d_render_target_QueryInterface
,
1088 d2d_d3d_render_target_AddRef
,
1089 d2d_d3d_render_target_Release
,
1090 d2d_d3d_render_target_GetFactory
,
1091 d2d_d3d_render_target_CreateBitmap
,
1092 d2d_d3d_render_target_CreateBitmapFromWicBitmap
,
1093 d2d_d3d_render_target_CreateSharedBitmap
,
1094 d2d_d3d_render_target_CreateBitmapBrush
,
1095 d2d_d3d_render_target_CreateSolidColorBrush
,
1096 d2d_d3d_render_target_CreateGradientStopCollection
,
1097 d2d_d3d_render_target_CreateLinearGradientBrush
,
1098 d2d_d3d_render_target_CreateRadialGradientBrush
,
1099 d2d_d3d_render_target_CreateCompatibleRenderTarget
,
1100 d2d_d3d_render_target_CreateLayer
,
1101 d2d_d3d_render_target_CreateMesh
,
1102 d2d_d3d_render_target_DrawLine
,
1103 d2d_d3d_render_target_DrawRectangle
,
1104 d2d_d3d_render_target_FillRectangle
,
1105 d2d_d3d_render_target_DrawRoundedRectangle
,
1106 d2d_d3d_render_target_FillRoundedRectangle
,
1107 d2d_d3d_render_target_DrawEllipse
,
1108 d2d_d3d_render_target_FillEllipse
,
1109 d2d_d3d_render_target_DrawGeometry
,
1110 d2d_d3d_render_target_FillGeometry
,
1111 d2d_d3d_render_target_FillMesh
,
1112 d2d_d3d_render_target_FillOpacityMask
,
1113 d2d_d3d_render_target_DrawBitmap
,
1114 d2d_d3d_render_target_DrawText
,
1115 d2d_d3d_render_target_DrawTextLayout
,
1116 d2d_d3d_render_target_DrawGlyphRun
,
1117 d2d_d3d_render_target_SetTransform
,
1118 d2d_d3d_render_target_GetTransform
,
1119 d2d_d3d_render_target_SetAntialiasMode
,
1120 d2d_d3d_render_target_GetAntialiasMode
,
1121 d2d_d3d_render_target_SetTextAntialiasMode
,
1122 d2d_d3d_render_target_GetTextAntialiasMode
,
1123 d2d_d3d_render_target_SetTextRenderingParams
,
1124 d2d_d3d_render_target_GetTextRenderingParams
,
1125 d2d_d3d_render_target_SetTags
,
1126 d2d_d3d_render_target_GetTags
,
1127 d2d_d3d_render_target_PushLayer
,
1128 d2d_d3d_render_target_PopLayer
,
1129 d2d_d3d_render_target_Flush
,
1130 d2d_d3d_render_target_SaveDrawingState
,
1131 d2d_d3d_render_target_RestoreDrawingState
,
1132 d2d_d3d_render_target_PushAxisAlignedClip
,
1133 d2d_d3d_render_target_PopAxisAlignedClip
,
1134 d2d_d3d_render_target_Clear
,
1135 d2d_d3d_render_target_BeginDraw
,
1136 d2d_d3d_render_target_EndDraw
,
1137 d2d_d3d_render_target_GetPixelFormat
,
1138 d2d_d3d_render_target_SetDpi
,
1139 d2d_d3d_render_target_GetDpi
,
1140 d2d_d3d_render_target_GetSize
,
1141 d2d_d3d_render_target_GetPixelSize
,
1142 d2d_d3d_render_target_GetMaximumBitmapSize
,
1143 d2d_d3d_render_target_IsSupported
,
1146 static inline struct d2d_d3d_render_target
*impl_from_IDWriteTextRenderer(IDWriteTextRenderer
*iface
)
1148 return CONTAINING_RECORD(iface
, struct d2d_d3d_render_target
, IDWriteTextRenderer_iface
);
1151 static HRESULT STDMETHODCALLTYPE
d2d_text_renderer_QueryInterface(IDWriteTextRenderer
*iface
, REFIID iid
, void **out
)
1153 TRACE("iface %p, iid %s, out %p.\n", iface
, debugstr_guid(iid
), out
);
1155 if (IsEqualGUID(iid
, &IID_IDWriteTextRenderer
)
1156 || IsEqualGUID(iid
, &IID_IDWritePixelSnapping
)
1157 || IsEqualGUID(iid
, &IID_IUnknown
))
1159 IDWriteTextRenderer_AddRef(iface
);
1164 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid
));
1167 return E_NOINTERFACE
;
1170 static ULONG STDMETHODCALLTYPE
d2d_text_renderer_AddRef(IDWriteTextRenderer
*iface
)
1172 struct d2d_d3d_render_target
*render_target
= impl_from_IDWriteTextRenderer(iface
);
1174 TRACE("iface %p.\n", iface
);
1176 return d2d_d3d_render_target_AddRef(&render_target
->ID2D1RenderTarget_iface
);
1179 static ULONG STDMETHODCALLTYPE
d2d_text_renderer_Release(IDWriteTextRenderer
*iface
)
1181 struct d2d_d3d_render_target
*render_target
= impl_from_IDWriteTextRenderer(iface
);
1183 TRACE("iface %p.\n", iface
);
1185 return d2d_d3d_render_target_Release(&render_target
->ID2D1RenderTarget_iface
);
1188 static HRESULT STDMETHODCALLTYPE
d2d_text_renderer_IsPixelSnappingDisabled(IDWriteTextRenderer
*iface
,
1189 void *ctx
, BOOL
*disabled
)
1191 FIXME("iface %p, ctx %p, disabled %p stub!\n", iface
, ctx
, disabled
);
1196 static HRESULT STDMETHODCALLTYPE
d2d_text_renderer_GetCurrentTransform(IDWriteTextRenderer
*iface
,
1197 void *ctx
, DWRITE_MATRIX
*transform
)
1199 FIXME("iface %p, ctx %p, transform %p stub!\n", iface
, ctx
, transform
);
1204 static HRESULT STDMETHODCALLTYPE
d2d_text_renderer_GetPixelsPerDip(IDWriteTextRenderer
*iface
, void *ctx
, float *ppd
)
1206 FIXME("iface %p, ctx %p, ppd %p stub!\n", iface
, ctx
, ppd
);
1211 static HRESULT STDMETHODCALLTYPE
d2d_text_renderer_DrawGlyphRun(IDWriteTextRenderer
*iface
, void *ctx
,
1212 float baseline_origin_x
, float baseline_origin_y
, DWRITE_MEASURING_MODE measuring_mode
,
1213 const DWRITE_GLYPH_RUN
*glyph_run
, const DWRITE_GLYPH_RUN_DESCRIPTION
*desc
, IUnknown
*effect
)
1215 FIXME("iface %p, ctx %p, baseline_origin_x %.8e, baseline_origin_y %.8e, "
1216 "measuring_mode %#x, glyph_run %p, desc %p, effect %p stub!\n",
1217 iface
, ctx
, baseline_origin_x
, baseline_origin_y
,
1218 measuring_mode
, glyph_run
, desc
, effect
);
1223 static HRESULT STDMETHODCALLTYPE
d2d_text_renderer_DrawUnderline(IDWriteTextRenderer
*iface
, void *ctx
,
1224 float baseline_origin_x
, float baseline_origin_y
, const DWRITE_UNDERLINE
*underline
, IUnknown
*effect
)
1226 FIXME("iface %p, ctx %p, baseline_origin_x %.8e, baseline_origin_y %.8e, underline %p, effect %p stub!\n",
1227 iface
, ctx
, baseline_origin_x
, baseline_origin_y
, underline
, effect
);
1232 static HRESULT STDMETHODCALLTYPE
d2d_text_renderer_DrawStrikethrough(IDWriteTextRenderer
*iface
, void *ctx
,
1233 float baseline_origin_x
, float baseline_origin_y
, const DWRITE_STRIKETHROUGH
*strikethrough
, IUnknown
*effect
)
1235 FIXME("iface %p, ctx %p, baseline_origin_x %.8e, baseline_origin_y %.8e, strikethrough %p, effect %p stub!\n",
1236 iface
, ctx
, baseline_origin_x
, baseline_origin_y
, strikethrough
, effect
);
1241 static HRESULT STDMETHODCALLTYPE
d2d_text_renderer_DrawInlineObject(IDWriteTextRenderer
*iface
, void *ctx
,
1242 float origin_x
, float origin_y
, IDWriteInlineObject
*object
, BOOL is_sideways
, BOOL is_rtl
, IUnknown
*effect
)
1244 FIXME("iface %p, ctx %p, origin_x %.8e, origin_y %.8e, object %p, is_sideways %#x, is_rtl %#x, effect %p stub!\n",
1245 iface
, ctx
, origin_x
, origin_y
, object
, is_sideways
, is_rtl
, effect
);
1250 static const struct IDWriteTextRendererVtbl d2d_text_renderer_vtbl
=
1252 d2d_text_renderer_QueryInterface
,
1253 d2d_text_renderer_AddRef
,
1254 d2d_text_renderer_Release
,
1255 d2d_text_renderer_IsPixelSnappingDisabled
,
1256 d2d_text_renderer_GetCurrentTransform
,
1257 d2d_text_renderer_GetPixelsPerDip
,
1258 d2d_text_renderer_DrawGlyphRun
,
1259 d2d_text_renderer_DrawUnderline
,
1260 d2d_text_renderer_DrawStrikethrough
,
1261 d2d_text_renderer_DrawInlineObject
,
1264 HRESULT
d2d_d3d_render_target_init(struct d2d_d3d_render_target
*render_target
, ID2D1Factory
*factory
,
1265 IDXGISurface
*surface
, const D2D1_RENDER_TARGET_PROPERTIES
*desc
)
1267 D3D10_SUBRESOURCE_DATA buffer_data
;
1268 D3D10_STATE_BLOCK_MASK state_mask
;
1269 DXGI_SURFACE_DESC surface_desc
;
1270 D3D10_RASTERIZER_DESC rs_desc
;
1271 D3D10_BUFFER_DESC buffer_desc
;
1272 D3D10_BLEND_DESC blend_desc
;
1273 ID3D10Resource
*resource
;
1276 static const D3D10_INPUT_ELEMENT_DESC il_desc
[] =
1278 {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT
, 0, 0, D3D10_INPUT_PER_VERTEX_DATA
, 0},
1280 static const DWORD vs_code
[] =
1282 /* float3x2 transform;
1284 * float4 main(float4 position : POSITION) : SV_POSITION
1286 * return float4(mul(position.xyw, transform), position.zw);
1288 0x43425844, 0x0add3194, 0x205f74ec, 0xab527fe7, 0xbe6ad704, 0x00000001, 0x00000128, 0x00000003,
1289 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020,
1290 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000f0f, 0x49534f50, 0x4e4f4954, 0xababab00,
1291 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000001, 0x00000003,
1292 0x00000000, 0x0000000f, 0x505f5653, 0x5449534f, 0x004e4f49, 0x52444853, 0x0000008c, 0x00010040,
1293 0x00000023, 0x04000059, 0x00208e46, 0x00000000, 0x00000002, 0x0300005f, 0x001010f2, 0x00000000,
1294 0x04000067, 0x001020f2, 0x00000000, 0x00000001, 0x08000010, 0x00102012, 0x00000000, 0x00101346,
1295 0x00000000, 0x00208246, 0x00000000, 0x00000000, 0x08000010, 0x00102022, 0x00000000, 0x00101346,
1296 0x00000000, 0x00208246, 0x00000000, 0x00000001, 0x05000036, 0x001020c2, 0x00000000, 0x00101ea6,
1297 0x00000000, 0x0100003e,
1299 static const DWORD rect_solid_ps_code
[] =
1303 * float4 main(float4 position : SV_POSITION) : SV_Target
1307 0x43425844, 0x88eefcfd, 0x93d6fd47, 0x173c242f, 0x0106d07a, 0x00000001, 0x000000dc, 0x00000003,
1308 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020,
1309 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x505f5653, 0x5449534f, 0x004e4f49,
1310 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003,
1311 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x00000040, 0x00000040,
1312 0x00000010, 0x04000059, 0x00208e46, 0x00000000, 0x00000001, 0x03000065, 0x001020f2, 0x00000000,
1313 0x06000036, 0x001020f2, 0x00000000, 0x00208e46, 0x00000000, 0x00000000, 0x0100003e,
1315 static const DWORD rect_bitmap_ps_code
[] =
1322 float4
main(float4 position
: SV_POSITION
) : SV_Target
1324 return t
.Sample(s
, mul(float3(position
.xy
, 1.0), transform
));
1327 0x43425844, 0x20fce5be, 0x138fa37f, 0x9554f03f, 0x3dbe9c02, 0x00000001, 0x00000184, 0x00000003,
1328 0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020,
1329 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000030f, 0x505f5653, 0x5449534f, 0x004e4f49,
1330 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003,
1331 0x00000000, 0x0000000f, 0x545f5653, 0x65677261, 0xabab0074, 0x52444853, 0x000000e8, 0x00000040,
1332 0x0000003a, 0x04000059, 0x00208e46, 0x00000000, 0x00000002, 0x0300005a, 0x00106000, 0x00000000,
1333 0x04001858, 0x00107000, 0x00000000, 0x00005555, 0x04002064, 0x00101032, 0x00000000, 0x00000001,
1334 0x03000065, 0x001020f2, 0x00000000, 0x02000068, 0x00000002, 0x05000036, 0x00100032, 0x00000000,
1335 0x00101046, 0x00000000, 0x05000036, 0x00100042, 0x00000000, 0x00004001, 0x3f800000, 0x08000010,
1336 0x00100012, 0x00000001, 0x00100246, 0x00000000, 0x00208246, 0x00000000, 0x00000000, 0x08000010,
1337 0x00100022, 0x00000001, 0x00100246, 0x00000000, 0x00208246, 0x00000000, 0x00000001, 0x09000045,
1338 0x001020f2, 0x00000000, 0x00100046, 0x00000001, 0x00107e46, 0x00000000, 0x00106000, 0x00000000,
1352 static const D2D1_MATRIX_3X2_F identity
=
1359 FIXME("Ignoring render target properties.\n");
1361 render_target
->ID2D1RenderTarget_iface
.lpVtbl
= &d2d_d3d_render_target_vtbl
;
1362 render_target
->IDWriteTextRenderer_iface
.lpVtbl
= &d2d_text_renderer_vtbl
;
1363 render_target
->refcount
= 1;
1365 if (FAILED(hr
= IDXGISurface_GetDevice(surface
, &IID_ID3D10Device
, (void **)&render_target
->device
)))
1367 WARN("Failed to get device interface, hr %#x.\n", hr
);
1371 if (FAILED(hr
= IDXGISurface_QueryInterface(surface
, &IID_ID3D10Resource
, (void **)&resource
)))
1373 WARN("Failed to get ID3D10Resource interface, hr %#x.\n", hr
);
1377 hr
= ID3D10Device_CreateRenderTargetView(render_target
->device
, resource
, NULL
, &render_target
->view
);
1378 ID3D10Resource_Release(resource
);
1381 WARN("Failed to create rendertarget view, hr %#x.\n", hr
);
1385 if (FAILED(hr
= D3D10StateBlockMaskEnableAll(&state_mask
)))
1387 WARN("Failed to create stateblock mask, hr %#x.\n", hr
);
1391 if (FAILED(hr
= D3D10CreateStateBlock(render_target
->device
, &state_mask
, &render_target
->stateblock
)))
1393 WARN("Failed to create stateblock, hr %#x.\n", hr
);
1397 if (FAILED(hr
= ID3D10Device_CreateInputLayout(render_target
->device
, il_desc
,
1398 sizeof(il_desc
) / sizeof(*il_desc
), vs_code
, sizeof(vs_code
),
1399 &render_target
->il
)))
1401 WARN("Failed to create clear input layout, hr %#x.\n", hr
);
1405 buffer_desc
.ByteWidth
= sizeof(quad
);
1406 buffer_desc
.Usage
= D3D10_USAGE_DEFAULT
;
1407 buffer_desc
.BindFlags
= D3D10_BIND_VERTEX_BUFFER
;
1408 buffer_desc
.CPUAccessFlags
= 0;
1409 buffer_desc
.MiscFlags
= 0;
1411 buffer_data
.pSysMem
= quad
;
1412 buffer_data
.SysMemPitch
= 0;
1413 buffer_data
.SysMemSlicePitch
= 0;
1415 render_target
->vb_stride
= sizeof(*quad
);
1416 if (FAILED(hr
= ID3D10Device_CreateBuffer(render_target
->device
,
1417 &buffer_desc
, &buffer_data
, &render_target
->vb
)))
1419 WARN("Failed to create clear vertex buffer, hr %#x.\n", hr
);
1423 if (FAILED(hr
= ID3D10Device_CreateVertexShader(render_target
->device
,
1424 vs_code
, sizeof(vs_code
), &render_target
->vs
)))
1426 WARN("Failed to create clear vertex shader, hr %#x.\n", hr
);
1430 rs_desc
.FillMode
= D3D10_FILL_SOLID
;
1431 rs_desc
.CullMode
= D3D10_CULL_BACK
;
1432 rs_desc
.FrontCounterClockwise
= FALSE
;
1433 rs_desc
.DepthBias
= 0;
1434 rs_desc
.DepthBiasClamp
= 0.0f
;
1435 rs_desc
.SlopeScaledDepthBias
= 0.0f
;
1436 rs_desc
.DepthClipEnable
= TRUE
;
1437 rs_desc
.ScissorEnable
= TRUE
;
1438 rs_desc
.MultisampleEnable
= FALSE
;
1439 rs_desc
.AntialiasedLineEnable
= FALSE
;
1440 if (FAILED(hr
= ID3D10Device_CreateRasterizerState(render_target
->device
, &rs_desc
, &render_target
->rs
)))
1442 WARN("Failed to create clear rasterizer state, hr %#x.\n", hr
);
1446 memset(&blend_desc
, 0, sizeof(blend_desc
));
1447 blend_desc
.BlendEnable
[0] = TRUE
;
1448 blend_desc
.SrcBlend
= D3D10_BLEND_SRC_ALPHA
;
1449 blend_desc
.DestBlend
= D3D10_BLEND_INV_SRC_ALPHA
;
1450 blend_desc
.BlendOp
= D3D10_BLEND_OP_ADD
;
1451 blend_desc
.SrcBlendAlpha
= D3D10_BLEND_ZERO
;
1452 blend_desc
.DestBlendAlpha
= D3D10_BLEND_ONE
;
1453 blend_desc
.BlendOpAlpha
= D3D10_BLEND_OP_ADD
;
1454 blend_desc
.RenderTargetWriteMask
[0] = D3D10_COLOR_WRITE_ENABLE_ALL
;
1455 if (FAILED(hr
= ID3D10Device_CreateBlendState(render_target
->device
, &blend_desc
, &render_target
->bs
)))
1457 WARN("Failed to create blend state, hr %#x.\n", hr
);
1461 if (FAILED(hr
= ID3D10Device_CreatePixelShader(render_target
->device
,
1462 rect_solid_ps_code
, sizeof(rect_solid_ps_code
), &render_target
->rect_solid_ps
)))
1464 WARN("Failed to create pixel shader, hr %#x.\n", hr
);
1468 if (FAILED(hr
= ID3D10Device_CreatePixelShader(render_target
->device
,
1469 rect_bitmap_ps_code
, sizeof(rect_bitmap_ps_code
), &render_target
->rect_bitmap_ps
)))
1471 WARN("Failed to create pixel shader, hr %#x.\n", hr
);
1475 if (FAILED(hr
= IDXGISurface_GetDesc(surface
, &surface_desc
)))
1477 WARN("Failed to get surface desc, hr %#x.\n", hr
);
1481 render_target
->pixel_size
.width
= surface_desc
.Width
;
1482 render_target
->pixel_size
.height
= surface_desc
.Height
;
1483 render_target
->transform
= identity
;
1485 if (!d2d_clip_stack_init(&render_target
->clip_stack
))
1487 WARN("Failed to initialize clip stack.\n");
1492 render_target
->dpi_x
= desc
->dpiX
;
1493 render_target
->dpi_y
= desc
->dpiY
;
1495 if (render_target
->dpi_x
== 0.0f
&& render_target
->dpi_y
== 0.0f
)
1497 render_target
->dpi_x
= 96.0f
;
1498 render_target
->dpi_y
= 96.0f
;
1504 if (render_target
->rect_bitmap_ps
)
1505 ID3D10PixelShader_Release(render_target
->rect_bitmap_ps
);
1506 if (render_target
->rect_solid_ps
)
1507 ID3D10PixelShader_Release(render_target
->rect_solid_ps
);
1508 if (render_target
->bs
)
1509 ID3D10BlendState_Release(render_target
->bs
);
1510 if (render_target
->rs
)
1511 ID3D10RasterizerState_Release(render_target
->rs
);
1512 if (render_target
->vs
)
1513 ID3D10VertexShader_Release(render_target
->vs
);
1514 if (render_target
->vb
)
1515 ID3D10Buffer_Release(render_target
->vb
);
1516 if (render_target
->il
)
1517 ID3D10InputLayout_Release(render_target
->il
);
1518 if (render_target
->stateblock
)
1519 render_target
->stateblock
->lpVtbl
->Release(render_target
->stateblock
);
1520 if (render_target
->view
)
1521 ID3D10RenderTargetView_Release(render_target
->view
);
1522 if (render_target
->device
)
1523 ID3D10Device_Release(render_target
->device
);