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"
24 WINE_DEFAULT_DEBUG_CHANNEL(d2d
);
26 static inline struct d2d_gradient
*impl_from_ID2D1GradientStopCollection(ID2D1GradientStopCollection
*iface
)
28 return CONTAINING_RECORD(iface
, struct d2d_gradient
, ID2D1GradientStopCollection_iface
);
31 static HRESULT STDMETHODCALLTYPE
d2d_gradient_QueryInterface(ID2D1GradientStopCollection
*iface
,
32 REFIID iid
, void **out
)
34 TRACE("iface %p, iid %s, out %p.\n", iface
, debugstr_guid(iid
), out
);
36 if (IsEqualGUID(iid
, &IID_ID2D1GradientStopCollection
)
37 || IsEqualGUID(iid
, &IID_ID2D1Resource
)
38 || IsEqualGUID(iid
, &IID_IUnknown
))
40 ID2D1GradientStopCollection_AddRef(iface
);
45 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid
));
51 static ULONG STDMETHODCALLTYPE
d2d_gradient_AddRef(ID2D1GradientStopCollection
*iface
)
53 struct d2d_gradient
*gradient
= impl_from_ID2D1GradientStopCollection(iface
);
54 ULONG refcount
= InterlockedIncrement(&gradient
->refcount
);
56 TRACE("%p increasing refcount to %u.\n", iface
, refcount
);
61 static ULONG STDMETHODCALLTYPE
d2d_gradient_Release(ID2D1GradientStopCollection
*iface
)
63 struct d2d_gradient
*gradient
= impl_from_ID2D1GradientStopCollection(iface
);
64 ULONG refcount
= InterlockedDecrement(&gradient
->refcount
);
66 TRACE("%p decreasing refcount to %u.\n", iface
, refcount
);
70 HeapFree(GetProcessHeap(), 0, gradient
->stops
);
71 ID3D10ShaderResourceView_Release(gradient
->view
);
72 ID2D1Factory_Release(gradient
->factory
);
73 HeapFree(GetProcessHeap(), 0, gradient
);
79 static void STDMETHODCALLTYPE
d2d_gradient_GetFactory(ID2D1GradientStopCollection
*iface
, ID2D1Factory
**factory
)
81 struct d2d_gradient
*gradient
= impl_from_ID2D1GradientStopCollection(iface
);
83 TRACE("iface %p, factory %p.\n", iface
, factory
);
85 ID2D1Factory_AddRef(*factory
= gradient
->factory
);
88 static UINT32 STDMETHODCALLTYPE
d2d_gradient_GetGradientStopCount(ID2D1GradientStopCollection
*iface
)
90 struct d2d_gradient
*gradient
= impl_from_ID2D1GradientStopCollection(iface
);
92 TRACE("iface %p.\n", iface
);
94 return gradient
->stop_count
;
97 static void STDMETHODCALLTYPE
d2d_gradient_GetGradientStops(ID2D1GradientStopCollection
*iface
,
98 D2D1_GRADIENT_STOP
*stops
, UINT32 stop_count
)
100 struct d2d_gradient
*gradient
= impl_from_ID2D1GradientStopCollection(iface
);
102 TRACE("iface %p, stops %p, stop_count %u.\n", iface
, stops
, stop_count
);
104 memcpy(stops
, gradient
->stops
, min(gradient
->stop_count
, stop_count
) * sizeof(*stops
));
107 static D2D1_GAMMA STDMETHODCALLTYPE
d2d_gradient_GetColorInterpolationGamma(ID2D1GradientStopCollection
*iface
)
109 FIXME("iface %p stub!\n", iface
);
111 return D2D1_GAMMA_1_0
;
114 static D2D1_EXTEND_MODE STDMETHODCALLTYPE
d2d_gradient_GetExtendMode(ID2D1GradientStopCollection
*iface
)
116 FIXME("iface %p stub!\n", iface
);
118 return D2D1_EXTEND_MODE_CLAMP
;
121 static const struct ID2D1GradientStopCollectionVtbl d2d_gradient_vtbl
=
123 d2d_gradient_QueryInterface
,
125 d2d_gradient_Release
,
126 d2d_gradient_GetFactory
,
127 d2d_gradient_GetGradientStopCount
,
128 d2d_gradient_GetGradientStops
,
129 d2d_gradient_GetColorInterpolationGamma
,
130 d2d_gradient_GetExtendMode
,
133 HRESULT
d2d_gradient_create(ID2D1Factory
*factory
, ID3D10Device
*device
, const D2D1_GRADIENT_STOP
*stops
,
134 UINT32 stop_count
, D2D1_GAMMA gamma
, D2D1_EXTEND_MODE extend_mode
, struct d2d_gradient
**gradient
)
136 D3D10_SHADER_RESOURCE_VIEW_DESC srv_desc
;
137 D3D10_SUBRESOURCE_DATA buffer_data
;
138 ID3D10ShaderResourceView
*view
;
139 D3D10_BUFFER_DESC buffer_desc
;
140 struct d2d_vec4
*data
;
141 ID3D10Buffer
*buffer
;
145 if (!(data
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, 2 * stop_count
* sizeof(*data
))))
147 ERR("Failed to allocate data.\n");
148 return E_OUTOFMEMORY
;
151 for (i
= 0; i
< stop_count
; ++i
)
153 data
[i
* 2].x
= stops
[i
].position
;
154 data
[i
* 2 + 1].x
= stops
[i
].color
.r
;
155 data
[i
* 2 + 1].y
= stops
[i
].color
.g
;
156 data
[i
* 2 + 1].z
= stops
[i
].color
.b
;
157 data
[i
* 2 + 1].w
= stops
[i
].color
.a
;
160 buffer_desc
.ByteWidth
= 2 * stop_count
* sizeof(*data
);
161 buffer_desc
.Usage
= D3D10_USAGE_DEFAULT
;
162 buffer_desc
.BindFlags
= D3D10_BIND_SHADER_RESOURCE
;
163 buffer_desc
.CPUAccessFlags
= 0;
164 buffer_desc
.MiscFlags
= 0;
166 buffer_data
.pSysMem
= data
;
167 buffer_data
.SysMemPitch
= 0;
168 buffer_data
.SysMemSlicePitch
= 0;
170 hr
= ID3D10Device_CreateBuffer(device
, &buffer_desc
, &buffer_data
, &buffer
);
171 HeapFree(GetProcessHeap(), 0, data
);
174 ERR("Failed to create buffer, hr %#x.\n", hr
);
178 srv_desc
.Format
= DXGI_FORMAT_R32G32B32A32_FLOAT
;
179 srv_desc
.ViewDimension
= D3D10_SRV_DIMENSION_BUFFER
;
180 srv_desc
.Buffer
.ElementOffset
= 0;
181 srv_desc
.Buffer
.ElementWidth
= 2 * stop_count
;
183 hr
= ID3D10Device_CreateShaderResourceView(device
, (ID3D10Resource
*)buffer
, &srv_desc
, &view
);
184 ID3D10Buffer_Release(buffer
);
187 ERR("Failed to create view, hr %#x.\n", hr
);
191 if (!(*gradient
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(**gradient
))))
193 ID3D10ShaderResourceView_Release(view
);
194 return E_OUTOFMEMORY
;
197 if (gamma
!= D2D1_GAMMA_2_2
)
198 FIXME("Ignoring gamma %#x.\n", gamma
);
199 if (extend_mode
!= D2D1_EXTEND_MODE_CLAMP
)
200 FIXME("Ignoring extend mode %#x.\n", extend_mode
);
202 (*gradient
)->ID2D1GradientStopCollection_iface
.lpVtbl
= &d2d_gradient_vtbl
;
203 (*gradient
)->refcount
= 1;
204 ID2D1Factory_AddRef((*gradient
)->factory
= factory
);
205 (*gradient
)->view
= view
;
207 (*gradient
)->stop_count
= stop_count
;
208 if (!((*gradient
)->stops
= HeapAlloc(GetProcessHeap(), 0, stop_count
* sizeof(*stops
))))
210 ID3D10ShaderResourceView_Release(view
);
211 HeapFree(GetProcessHeap(), 0, *gradient
);
212 return E_OUTOFMEMORY
;
214 memcpy((*gradient
)->stops
, stops
, stop_count
* sizeof(*stops
));
216 TRACE("Created gradient %p.\n", *gradient
);
220 static void d2d_brush_destroy(struct d2d_brush
*brush
)
222 ID2D1Factory_Release(brush
->factory
);
223 HeapFree(GetProcessHeap(), 0, brush
);
226 static void d2d_brush_init(struct d2d_brush
*brush
, ID2D1Factory
*factory
,
227 enum d2d_brush_type type
, const D2D1_BRUSH_PROPERTIES
*desc
, const struct ID2D1BrushVtbl
*vtbl
)
229 static const D2D1_MATRIX_3X2_F identity
=
236 brush
->ID2D1Brush_iface
.lpVtbl
= vtbl
;
238 ID2D1Factory_AddRef(brush
->factory
= factory
);
239 brush
->opacity
= desc
? desc
->opacity
: 1.0f
;
240 brush
->transform
= desc
? desc
->transform
: identity
;
244 static inline struct d2d_brush
*impl_from_ID2D1SolidColorBrush(ID2D1SolidColorBrush
*iface
)
246 return CONTAINING_RECORD(iface
, struct d2d_brush
, ID2D1Brush_iface
);
249 static HRESULT STDMETHODCALLTYPE
d2d_solid_color_brush_QueryInterface(ID2D1SolidColorBrush
*iface
,
250 REFIID iid
, void **out
)
252 TRACE("iface %p, iid %s, out %p.\n", iface
, debugstr_guid(iid
), out
);
254 if (IsEqualGUID(iid
, &IID_ID2D1SolidColorBrush
)
255 || IsEqualGUID(iid
, &IID_ID2D1Brush
)
256 || IsEqualGUID(iid
, &IID_ID2D1Resource
)
257 || IsEqualGUID(iid
, &IID_IUnknown
))
259 ID2D1SolidColorBrush_AddRef(iface
);
264 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid
));
267 return E_NOINTERFACE
;
270 static ULONG STDMETHODCALLTYPE
d2d_solid_color_brush_AddRef(ID2D1SolidColorBrush
*iface
)
272 struct d2d_brush
*brush
= impl_from_ID2D1SolidColorBrush(iface
);
273 ULONG refcount
= InterlockedIncrement(&brush
->refcount
);
275 TRACE("%p increasing refcount to %u.\n", iface
, refcount
);
280 static ULONG STDMETHODCALLTYPE
d2d_solid_color_brush_Release(ID2D1SolidColorBrush
*iface
)
282 struct d2d_brush
*brush
= impl_from_ID2D1SolidColorBrush(iface
);
283 ULONG refcount
= InterlockedDecrement(&brush
->refcount
);
285 TRACE("%p decreasing refcount to %u.\n", iface
, refcount
);
288 d2d_brush_destroy(brush
);
293 static void STDMETHODCALLTYPE
d2d_solid_color_brush_GetFactory(ID2D1SolidColorBrush
*iface
, ID2D1Factory
**factory
)
295 struct d2d_brush
*brush
= impl_from_ID2D1SolidColorBrush(iface
);
297 TRACE("iface %p, factory %p.\n", iface
, factory
);
299 ID2D1Factory_AddRef(*factory
= brush
->factory
);
302 static void STDMETHODCALLTYPE
d2d_solid_color_brush_SetOpacity(ID2D1SolidColorBrush
*iface
, float opacity
)
304 struct d2d_brush
*brush
= impl_from_ID2D1SolidColorBrush(iface
);
306 TRACE("iface %p, opacity %.8e.\n", iface
, opacity
);
308 brush
->opacity
= opacity
;
311 static void STDMETHODCALLTYPE
d2d_solid_color_brush_SetTransform(ID2D1SolidColorBrush
*iface
,
312 const D2D1_MATRIX_3X2_F
*transform
)
314 struct d2d_brush
*brush
= impl_from_ID2D1SolidColorBrush(iface
);
316 TRACE("iface %p, transform %p.\n", iface
, transform
);
318 brush
->transform
= *transform
;
321 static float STDMETHODCALLTYPE
d2d_solid_color_brush_GetOpacity(ID2D1SolidColorBrush
*iface
)
323 struct d2d_brush
*brush
= impl_from_ID2D1SolidColorBrush(iface
);
325 TRACE("iface %p.\n", iface
);
327 return brush
->opacity
;
330 static void STDMETHODCALLTYPE
d2d_solid_color_brush_GetTransform(ID2D1SolidColorBrush
*iface
,
331 D2D1_MATRIX_3X2_F
*transform
)
333 struct d2d_brush
*brush
= impl_from_ID2D1SolidColorBrush(iface
);
335 TRACE("iface %p, transform %p.\n", iface
, transform
);
337 *transform
= brush
->transform
;
340 static void STDMETHODCALLTYPE
d2d_solid_color_brush_SetColor(ID2D1SolidColorBrush
*iface
, const D2D1_COLOR_F
*color
)
342 struct d2d_brush
*brush
= impl_from_ID2D1SolidColorBrush(iface
);
344 TRACE("iface %p, color %p.\n", iface
, color
);
346 brush
->u
.solid
.color
= *color
;
349 static D2D1_COLOR_F
* STDMETHODCALLTYPE
d2d_solid_color_brush_GetColor(ID2D1SolidColorBrush
*iface
, D2D1_COLOR_F
*color
)
351 struct d2d_brush
*brush
= impl_from_ID2D1SolidColorBrush(iface
);
353 TRACE("iface %p, color %p.\n", iface
, color
);
355 *color
= brush
->u
.solid
.color
;
359 static const struct ID2D1SolidColorBrushVtbl d2d_solid_color_brush_vtbl
=
361 d2d_solid_color_brush_QueryInterface
,
362 d2d_solid_color_brush_AddRef
,
363 d2d_solid_color_brush_Release
,
364 d2d_solid_color_brush_GetFactory
,
365 d2d_solid_color_brush_SetOpacity
,
366 d2d_solid_color_brush_SetTransform
,
367 d2d_solid_color_brush_GetOpacity
,
368 d2d_solid_color_brush_GetTransform
,
369 d2d_solid_color_brush_SetColor
,
370 d2d_solid_color_brush_GetColor
,
373 HRESULT
d2d_solid_color_brush_create(ID2D1Factory
*factory
, const D2D1_COLOR_F
*color
,
374 const D2D1_BRUSH_PROPERTIES
*desc
, struct d2d_brush
**brush
)
376 if (!(*brush
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(**brush
))))
377 return E_OUTOFMEMORY
;
379 d2d_brush_init(*brush
, factory
, D2D_BRUSH_TYPE_SOLID
, desc
,
380 (ID2D1BrushVtbl
*)&d2d_solid_color_brush_vtbl
);
381 (*brush
)->u
.solid
.color
= *color
;
383 TRACE("Created brush %p.\n", *brush
);
387 static inline struct d2d_brush
*impl_from_ID2D1LinearGradientBrush(ID2D1LinearGradientBrush
*iface
)
389 return CONTAINING_RECORD(iface
, struct d2d_brush
, ID2D1Brush_iface
);
392 static HRESULT STDMETHODCALLTYPE
d2d_linear_gradient_brush_QueryInterface(ID2D1LinearGradientBrush
*iface
,
393 REFIID iid
, void **out
)
395 TRACE("iface %p, iid %s, out %p.\n", iface
, debugstr_guid(iid
), out
);
397 if (IsEqualGUID(iid
, &IID_ID2D1LinearGradientBrush
)
398 || IsEqualGUID(iid
, &IID_ID2D1Brush
)
399 || IsEqualGUID(iid
, &IID_ID2D1Resource
)
400 || IsEqualGUID(iid
, &IID_IUnknown
))
402 ID2D1LinearGradientBrush_AddRef(iface
);
407 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid
));
410 return E_NOINTERFACE
;
413 static ULONG STDMETHODCALLTYPE
d2d_linear_gradient_brush_AddRef(ID2D1LinearGradientBrush
*iface
)
415 struct d2d_brush
*brush
= impl_from_ID2D1LinearGradientBrush(iface
);
416 ULONG refcount
= InterlockedIncrement(&brush
->refcount
);
418 TRACE("%p increasing refcount to %u.\n", iface
, refcount
);
423 static ULONG STDMETHODCALLTYPE
d2d_linear_gradient_brush_Release(ID2D1LinearGradientBrush
*iface
)
425 struct d2d_brush
*brush
= impl_from_ID2D1LinearGradientBrush(iface
);
426 ULONG refcount
= InterlockedDecrement(&brush
->refcount
);
428 TRACE("%p decreasing refcount to %u.\n", iface
, refcount
);
432 ID2D1GradientStopCollection_Release(brush
->u
.linear
.gradient
);
433 d2d_brush_destroy(brush
);
439 static void STDMETHODCALLTYPE
d2d_linear_gradient_brush_GetFactory(ID2D1LinearGradientBrush
*iface
,
440 ID2D1Factory
**factory
)
442 struct d2d_brush
*brush
= impl_from_ID2D1LinearGradientBrush(iface
);
444 TRACE("iface %p, factory %p.\n", iface
, factory
);
446 ID2D1Factory_AddRef(*factory
= brush
->factory
);
449 static void STDMETHODCALLTYPE
d2d_linear_gradient_brush_SetOpacity(ID2D1LinearGradientBrush
*iface
, float opacity
)
451 struct d2d_brush
*brush
= impl_from_ID2D1LinearGradientBrush(iface
);
453 TRACE("iface %p, opacity %.8e.\n", iface
, opacity
);
455 brush
->opacity
= opacity
;
458 static void STDMETHODCALLTYPE
d2d_linear_gradient_brush_SetTransform(ID2D1LinearGradientBrush
*iface
,
459 const D2D1_MATRIX_3X2_F
*transform
)
461 struct d2d_brush
*brush
= impl_from_ID2D1LinearGradientBrush(iface
);
463 TRACE("iface %p, transform %p.\n", iface
, transform
);
465 brush
->transform
= *transform
;
468 static float STDMETHODCALLTYPE
d2d_linear_gradient_brush_GetOpacity(ID2D1LinearGradientBrush
*iface
)
470 struct d2d_brush
*brush
= impl_from_ID2D1LinearGradientBrush(iface
);
472 TRACE("iface %p.\n", iface
);
474 return brush
->opacity
;
477 static void STDMETHODCALLTYPE
d2d_linear_gradient_brush_GetTransform(ID2D1LinearGradientBrush
*iface
,
478 D2D1_MATRIX_3X2_F
*transform
)
480 struct d2d_brush
*brush
= impl_from_ID2D1LinearGradientBrush(iface
);
482 TRACE("iface %p, transform %p.\n", iface
, transform
);
484 *transform
= brush
->transform
;
487 static void STDMETHODCALLTYPE
d2d_linear_gradient_brush_SetStartPoint(ID2D1LinearGradientBrush
*iface
,
488 D2D1_POINT_2F start_point
)
490 struct d2d_brush
*brush
= impl_from_ID2D1LinearGradientBrush(iface
);
492 TRACE("iface %p, start_point {%.8e, %.8e}.\n", iface
, start_point
.x
, start_point
.y
);
494 brush
->u
.linear
.desc
.startPoint
= start_point
;
497 static void STDMETHODCALLTYPE
d2d_linear_gradient_brush_SetEndPoint(ID2D1LinearGradientBrush
*iface
,
498 D2D1_POINT_2F end_point
)
500 struct d2d_brush
*brush
= impl_from_ID2D1LinearGradientBrush(iface
);
502 TRACE("iface %p, end_point {%.8e, %.8e}.\n", iface
, end_point
.x
, end_point
.y
);
504 brush
->u
.linear
.desc
.endPoint
= end_point
;
507 static D2D1_POINT_2F
* STDMETHODCALLTYPE
d2d_linear_gradient_brush_GetStartPoint(ID2D1LinearGradientBrush
*iface
,
508 D2D1_POINT_2F
*point
)
510 struct d2d_brush
*brush
= impl_from_ID2D1LinearGradientBrush(iface
);
512 TRACE("iface %p, point %p.\n", iface
, point
);
514 *point
= brush
->u
.linear
.desc
.startPoint
;
518 static D2D1_POINT_2F
* STDMETHODCALLTYPE
d2d_linear_gradient_brush_GetEndPoint(ID2D1LinearGradientBrush
*iface
,
519 D2D1_POINT_2F
*point
)
521 struct d2d_brush
*brush
= impl_from_ID2D1LinearGradientBrush(iface
);
523 TRACE("iface %p, point %p.\n", iface
, point
);
525 *point
= brush
->u
.linear
.desc
.endPoint
;
529 static void STDMETHODCALLTYPE
d2d_linear_gradient_brush_GetGradientStopCollection(ID2D1LinearGradientBrush
*iface
,
530 ID2D1GradientStopCollection
**gradient
)
532 struct d2d_brush
*brush
= impl_from_ID2D1LinearGradientBrush(iface
);
534 TRACE("iface %p, gradient %p.\n", iface
, gradient
);
536 ID2D1GradientStopCollection_AddRef(*gradient
= brush
->u
.linear
.gradient
);
539 static const struct ID2D1LinearGradientBrushVtbl d2d_linear_gradient_brush_vtbl
=
541 d2d_linear_gradient_brush_QueryInterface
,
542 d2d_linear_gradient_brush_AddRef
,
543 d2d_linear_gradient_brush_Release
,
544 d2d_linear_gradient_brush_GetFactory
,
545 d2d_linear_gradient_brush_SetOpacity
,
546 d2d_linear_gradient_brush_SetTransform
,
547 d2d_linear_gradient_brush_GetOpacity
,
548 d2d_linear_gradient_brush_GetTransform
,
549 d2d_linear_gradient_brush_SetStartPoint
,
550 d2d_linear_gradient_brush_SetEndPoint
,
551 d2d_linear_gradient_brush_GetStartPoint
,
552 d2d_linear_gradient_brush_GetEndPoint
,
553 d2d_linear_gradient_brush_GetGradientStopCollection
,
556 HRESULT
d2d_linear_gradient_brush_create(ID2D1Factory
*factory
, const D2D1_LINEAR_GRADIENT_BRUSH_PROPERTIES
*gradient_brush_desc
,
557 const D2D1_BRUSH_PROPERTIES
*brush_desc
, ID2D1GradientStopCollection
*gradient
, struct d2d_brush
**brush
)
559 if (!(*brush
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(**brush
))))
560 return E_OUTOFMEMORY
;
562 d2d_brush_init(*brush
, factory
, D2D_BRUSH_TYPE_LINEAR
, brush_desc
,
563 (ID2D1BrushVtbl
*)&d2d_linear_gradient_brush_vtbl
);
564 (*brush
)->u
.linear
.desc
= *gradient_brush_desc
;
565 ID2D1GradientStopCollection_AddRef((*brush
)->u
.linear
.gradient
= gradient
);
567 TRACE("Created brush %p.\n", *brush
);
571 static inline struct d2d_brush
*impl_from_ID2D1BitmapBrush(ID2D1BitmapBrush
*iface
)
573 return CONTAINING_RECORD(iface
, struct d2d_brush
, ID2D1Brush_iface
);
576 static HRESULT STDMETHODCALLTYPE
d2d_bitmap_brush_QueryInterface(ID2D1BitmapBrush
*iface
,
577 REFIID iid
, void **out
)
579 TRACE("iface %p, iid %s, out %p.\n", iface
, debugstr_guid(iid
), out
);
581 if (IsEqualGUID(iid
, &IID_ID2D1BitmapBrush
)
582 || IsEqualGUID(iid
, &IID_ID2D1Brush
)
583 || IsEqualGUID(iid
, &IID_ID2D1Resource
)
584 || IsEqualGUID(iid
, &IID_IUnknown
))
586 ID2D1BitmapBrush_AddRef(iface
);
591 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid
));
594 return E_NOINTERFACE
;
597 static ULONG STDMETHODCALLTYPE
d2d_bitmap_brush_AddRef(ID2D1BitmapBrush
*iface
)
599 struct d2d_brush
*brush
= impl_from_ID2D1BitmapBrush(iface
);
600 ULONG refcount
= InterlockedIncrement(&brush
->refcount
);
602 TRACE("%p increasing refcount to %u.\n", iface
, refcount
);
607 static ULONG STDMETHODCALLTYPE
d2d_bitmap_brush_Release(ID2D1BitmapBrush
*iface
)
609 struct d2d_brush
*brush
= impl_from_ID2D1BitmapBrush(iface
);
610 ULONG refcount
= InterlockedDecrement(&brush
->refcount
);
612 TRACE("%p decreasing refcount to %u.\n", iface
, refcount
);
616 if (brush
->u
.bitmap
.sampler_state
)
617 ID3D10SamplerState_Release(brush
->u
.bitmap
.sampler_state
);
618 if (brush
->u
.bitmap
.bitmap
)
619 ID2D1Bitmap_Release(&brush
->u
.bitmap
.bitmap
->ID2D1Bitmap_iface
);
620 d2d_brush_destroy(brush
);
626 static void STDMETHODCALLTYPE
d2d_bitmap_brush_GetFactory(ID2D1BitmapBrush
*iface
,
627 ID2D1Factory
**factory
)
629 struct d2d_brush
*brush
= impl_from_ID2D1BitmapBrush(iface
);
631 TRACE("iface %p, factory %p.\n", iface
, factory
);
633 ID2D1Factory_AddRef(*factory
= brush
->factory
);
636 static void STDMETHODCALLTYPE
d2d_bitmap_brush_SetOpacity(ID2D1BitmapBrush
*iface
, float opacity
)
638 struct d2d_brush
*brush
= impl_from_ID2D1BitmapBrush(iface
);
640 TRACE("iface %p, opacity %.8e.\n", iface
, opacity
);
642 brush
->opacity
= opacity
;
645 static void STDMETHODCALLTYPE
d2d_bitmap_brush_SetTransform(ID2D1BitmapBrush
*iface
,
646 const D2D1_MATRIX_3X2_F
*transform
)
648 struct d2d_brush
*brush
= impl_from_ID2D1BitmapBrush(iface
);
650 TRACE("iface %p, transform %p.\n", iface
, transform
);
652 brush
->transform
= *transform
;
655 static float STDMETHODCALLTYPE
d2d_bitmap_brush_GetOpacity(ID2D1BitmapBrush
*iface
)
657 struct d2d_brush
*brush
= impl_from_ID2D1BitmapBrush(iface
);
659 TRACE("iface %p.\n", iface
);
661 return brush
->opacity
;
664 static void STDMETHODCALLTYPE
d2d_bitmap_brush_GetTransform(ID2D1BitmapBrush
*iface
,
665 D2D1_MATRIX_3X2_F
*transform
)
667 struct d2d_brush
*brush
= impl_from_ID2D1BitmapBrush(iface
);
669 TRACE("iface %p, transform %p.\n", iface
, transform
);
671 *transform
= brush
->transform
;
674 static void STDMETHODCALLTYPE
d2d_bitmap_brush_SetExtendModeX(ID2D1BitmapBrush
*iface
, D2D1_EXTEND_MODE mode
)
676 struct d2d_brush
*brush
= impl_from_ID2D1BitmapBrush(iface
);
678 TRACE("iface %p, mode %#x.\n", iface
, mode
);
680 brush
->u
.bitmap
.extend_mode_x
= mode
;
681 if (brush
->u
.bitmap
.sampler_state
)
683 ID3D10SamplerState_Release(brush
->u
.bitmap
.sampler_state
);
684 brush
->u
.bitmap
.sampler_state
= NULL
;
688 static void STDMETHODCALLTYPE
d2d_bitmap_brush_SetExtendModeY(ID2D1BitmapBrush
*iface
, D2D1_EXTEND_MODE mode
)
690 struct d2d_brush
*brush
= impl_from_ID2D1BitmapBrush(iface
);
692 TRACE("iface %p, mode %#x.\n", iface
, mode
);
694 brush
->u
.bitmap
.extend_mode_y
= mode
;
695 if (brush
->u
.bitmap
.sampler_state
)
697 ID3D10SamplerState_Release(brush
->u
.bitmap
.sampler_state
);
698 brush
->u
.bitmap
.sampler_state
= NULL
;
702 static void STDMETHODCALLTYPE
d2d_bitmap_brush_SetInterpolationMode(ID2D1BitmapBrush
*iface
,
703 D2D1_BITMAP_INTERPOLATION_MODE mode
)
705 struct d2d_brush
*brush
= impl_from_ID2D1BitmapBrush(iface
);
707 TRACE("iface %p, mode %#x.\n", iface
, mode
);
709 brush
->u
.bitmap
.interpolation_mode
= mode
;
710 if (brush
->u
.bitmap
.sampler_state
)
712 ID3D10SamplerState_Release(brush
->u
.bitmap
.sampler_state
);
713 brush
->u
.bitmap
.sampler_state
= NULL
;
717 static void STDMETHODCALLTYPE
d2d_bitmap_brush_SetBitmap(ID2D1BitmapBrush
*iface
, ID2D1Bitmap
*bitmap
)
719 struct d2d_brush
*brush
= impl_from_ID2D1BitmapBrush(iface
);
721 TRACE("iface %p, bitmap %p.\n", iface
, bitmap
);
724 ID2D1Bitmap_AddRef(bitmap
);
725 if (brush
->u
.bitmap
.bitmap
)
726 ID2D1Bitmap_Release(&brush
->u
.bitmap
.bitmap
->ID2D1Bitmap_iface
);
727 brush
->u
.bitmap
.bitmap
= unsafe_impl_from_ID2D1Bitmap(bitmap
);
730 static D2D1_EXTEND_MODE STDMETHODCALLTYPE
d2d_bitmap_brush_GetExtendModeX(ID2D1BitmapBrush
*iface
)
732 struct d2d_brush
*brush
= impl_from_ID2D1BitmapBrush(iface
);
734 TRACE("iface %p.\n", iface
);
736 return brush
->u
.bitmap
.extend_mode_x
;
739 static D2D1_EXTEND_MODE STDMETHODCALLTYPE
d2d_bitmap_brush_GetExtendModeY(ID2D1BitmapBrush
*iface
)
741 struct d2d_brush
*brush
= impl_from_ID2D1BitmapBrush(iface
);
743 TRACE("iface %p.\n", iface
);
745 return brush
->u
.bitmap
.extend_mode_y
;
748 static D2D1_BITMAP_INTERPOLATION_MODE STDMETHODCALLTYPE
d2d_bitmap_brush_GetInterpolationMode(ID2D1BitmapBrush
*iface
)
750 struct d2d_brush
*brush
= impl_from_ID2D1BitmapBrush(iface
);
752 TRACE("iface %p.\n", iface
);
754 return brush
->u
.bitmap
.interpolation_mode
;
757 static void STDMETHODCALLTYPE
d2d_bitmap_brush_GetBitmap(ID2D1BitmapBrush
*iface
, ID2D1Bitmap
**bitmap
)
759 struct d2d_brush
*brush
= impl_from_ID2D1BitmapBrush(iface
);
761 TRACE("iface %p, bitmap %p.\n", iface
, bitmap
);
763 if ((*bitmap
= &brush
->u
.bitmap
.bitmap
->ID2D1Bitmap_iface
))
764 ID2D1Bitmap_AddRef(*bitmap
);
767 static const struct ID2D1BitmapBrushVtbl d2d_bitmap_brush_vtbl
=
769 d2d_bitmap_brush_QueryInterface
,
770 d2d_bitmap_brush_AddRef
,
771 d2d_bitmap_brush_Release
,
772 d2d_bitmap_brush_GetFactory
,
773 d2d_bitmap_brush_SetOpacity
,
774 d2d_bitmap_brush_SetTransform
,
775 d2d_bitmap_brush_GetOpacity
,
776 d2d_bitmap_brush_GetTransform
,
777 d2d_bitmap_brush_SetExtendModeX
,
778 d2d_bitmap_brush_SetExtendModeY
,
779 d2d_bitmap_brush_SetInterpolationMode
,
780 d2d_bitmap_brush_SetBitmap
,
781 d2d_bitmap_brush_GetExtendModeX
,
782 d2d_bitmap_brush_GetExtendModeY
,
783 d2d_bitmap_brush_GetInterpolationMode
,
784 d2d_bitmap_brush_GetBitmap
,
787 HRESULT
d2d_bitmap_brush_create(ID2D1Factory
*factory
, ID2D1Bitmap
*bitmap
, const D2D1_BITMAP_BRUSH_PROPERTIES
*bitmap_brush_desc
,
788 const D2D1_BRUSH_PROPERTIES
*brush_desc
, struct d2d_brush
**brush
)
790 if (!(*brush
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(**brush
))))
791 return E_OUTOFMEMORY
;
793 d2d_brush_init(*brush
, factory
, D2D_BRUSH_TYPE_BITMAP
,
794 brush_desc
, (ID2D1BrushVtbl
*)&d2d_bitmap_brush_vtbl
);
795 if (((*brush
)->u
.bitmap
.bitmap
= unsafe_impl_from_ID2D1Bitmap(bitmap
)))
796 ID2D1Bitmap_AddRef(&(*brush
)->u
.bitmap
.bitmap
->ID2D1Bitmap_iface
);
797 if (bitmap_brush_desc
)
799 (*brush
)->u
.bitmap
.extend_mode_x
= bitmap_brush_desc
->extendModeX
;
800 (*brush
)->u
.bitmap
.extend_mode_y
= bitmap_brush_desc
->extendModeY
;
801 (*brush
)->u
.bitmap
.interpolation_mode
= bitmap_brush_desc
->interpolationMode
;
805 (*brush
)->u
.bitmap
.extend_mode_x
= D2D1_EXTEND_MODE_CLAMP
;
806 (*brush
)->u
.bitmap
.extend_mode_y
= D2D1_EXTEND_MODE_CLAMP
;
807 (*brush
)->u
.bitmap
.interpolation_mode
= D2D1_BITMAP_INTERPOLATION_MODE_LINEAR
;
810 TRACE("Created brush %p.\n", *brush
);
814 struct d2d_brush
*unsafe_impl_from_ID2D1Brush(ID2D1Brush
*iface
)
818 assert(iface
->lpVtbl
== (const ID2D1BrushVtbl
*)&d2d_solid_color_brush_vtbl
819 || iface
->lpVtbl
== (const ID2D1BrushVtbl
*)&d2d_linear_gradient_brush_vtbl
820 || iface
->lpVtbl
== (const ID2D1BrushVtbl
*)&d2d_bitmap_brush_vtbl
);
821 return CONTAINING_RECORD(iface
, struct d2d_brush
, ID2D1Brush_iface
);
824 static D3D10_TEXTURE_ADDRESS_MODE
texture_address_mode_from_extend_mode(D2D1_EXTEND_MODE mode
)
828 case D2D1_EXTEND_MODE_CLAMP
:
829 return D3D10_TEXTURE_ADDRESS_CLAMP
;
830 case D2D1_EXTEND_MODE_WRAP
:
831 return D3D10_TEXTURE_ADDRESS_WRAP
;
832 case D2D1_EXTEND_MODE_MIRROR
:
833 return D3D10_TEXTURE_ADDRESS_MIRROR
;
835 FIXME("Unhandled extend mode %#x.\n", mode
);
836 return D3D10_TEXTURE_ADDRESS_CLAMP
;
840 static BOOL
d2d_brush_fill_cb(const struct d2d_brush
*brush
,
841 const struct d2d_d3d_render_target
*render_target
, struct d2d_brush_cb
*cb
)
843 struct d2d_bitmap
*bitmap
;
844 D2D1_COLOR_F
*colour
;
850 cb
->type
= D2D_BRUSH_TYPE_COUNT
;
854 cb
->type
= brush
->type
;
855 cb
->opacity
= brush
->opacity
;
859 case D2D_BRUSH_TYPE_SOLID
:
860 colour
= &cb
->u
.solid
.colour
;
862 *colour
= brush
->u
.solid
.color
;
863 colour
->r
*= colour
->a
;
864 colour
->g
*= colour
->a
;
865 colour
->b
*= colour
->a
;
869 case D2D_BRUSH_TYPE_BITMAP
:
870 bitmap
= brush
->u
.bitmap
.bitmap
;
872 /* Scale for bitmap size and dpi. */
873 b
= brush
->transform
;
874 dpi_scale
= bitmap
->pixel_size
.width
* (96.0f
/ bitmap
->dpi_x
);
877 dpi_scale
= bitmap
->pixel_size
.height
* (96.0f
/ bitmap
->dpi_y
);
881 /* Invert the matrix. (Because the matrix is applied to the
882 * sampling coordinates. I.e., to scale the bitmap by 2 we need to
883 * divide the coordinates by 2.) */
884 d
= b
._11
* b
._22
- b
._21
* b
._12
;
887 cb
->u
.bitmap
._11
= b
._22
/ d
;
888 cb
->u
.bitmap
._21
= -b
._21
/ d
;
889 cb
->u
.bitmap
._31
= (b
._21
* b
._32
- b
._31
* b
._22
) / d
;
890 cb
->u
.bitmap
._12
= -b
._12
/ d
;
891 cb
->u
.bitmap
._22
= b
._11
/ d
;
892 cb
->u
.bitmap
._32
= -(b
._11
* b
._32
- b
._31
* b
._12
) / d
;
895 cb
->u
.bitmap
.ignore_alpha
= bitmap
->format
.alphaMode
== D2D1_ALPHA_MODE_IGNORE
;
900 FIXME("Unhandled brush type %#x.\n", brush
->type
);
905 HRESULT
d2d_brush_get_ps_cb(struct d2d_brush
*brush
, struct d2d_brush
*opacity_brush
,
906 BOOL outline
, struct d2d_d3d_render_target
*render_target
, ID3D10Buffer
**ps_cb
)
908 D3D10_SUBRESOURCE_DATA buffer_data
;
909 struct d2d_ps_cb cb_data
= {0};
910 D3D10_BUFFER_DESC buffer_desc
;
913 cb_data
.outline
= outline
;
914 if (!d2d_brush_fill_cb(brush
, render_target
, &cb_data
.colour_brush
))
916 if (!d2d_brush_fill_cb(opacity_brush
, render_target
, &cb_data
.opacity_brush
))
919 buffer_desc
.ByteWidth
= sizeof(cb_data
);
920 buffer_desc
.Usage
= D3D10_USAGE_DEFAULT
;
921 buffer_desc
.BindFlags
= D3D10_BIND_CONSTANT_BUFFER
;
922 buffer_desc
.CPUAccessFlags
= 0;
923 buffer_desc
.MiscFlags
= 0;
925 buffer_data
.pSysMem
= &cb_data
;
926 buffer_data
.SysMemPitch
= 0;
927 buffer_data
.SysMemSlicePitch
= 0;
929 if (FAILED(hr
= ID3D10Device_CreateBuffer(render_target
->device
, &buffer_desc
, &buffer_data
, ps_cb
)))
930 ERR("Failed to create constant buffer, hr %#x.\n", hr
);
935 static void d2d_brush_bind_bitmap(struct d2d_brush
*brush
, ID3D10Device
*device
, unsigned int brush_idx
)
939 ID3D10Device_PSSetShaderResources(device
, brush_idx
, 1, &brush
->u
.bitmap
.bitmap
->view
);
940 if (!brush
->u
.bitmap
.sampler_state
)
942 D3D10_SAMPLER_DESC sampler_desc
;
944 if (brush
->u
.bitmap
.interpolation_mode
== D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR
)
945 sampler_desc
.Filter
= D3D10_FILTER_MIN_MAG_MIP_POINT
;
947 sampler_desc
.Filter
= D3D10_FILTER_MIN_MAG_MIP_LINEAR
;
948 sampler_desc
.AddressU
= texture_address_mode_from_extend_mode(brush
->u
.bitmap
.extend_mode_x
);
949 sampler_desc
.AddressV
= texture_address_mode_from_extend_mode(brush
->u
.bitmap
.extend_mode_y
);
950 sampler_desc
.AddressW
= D3D10_TEXTURE_ADDRESS_CLAMP
;
951 sampler_desc
.MipLODBias
= 0.0f
;
952 sampler_desc
.MaxAnisotropy
= 0;
953 sampler_desc
.ComparisonFunc
= D3D10_COMPARISON_NEVER
;
954 sampler_desc
.BorderColor
[0] = 0.0f
;
955 sampler_desc
.BorderColor
[1] = 0.0f
;
956 sampler_desc
.BorderColor
[2] = 0.0f
;
957 sampler_desc
.BorderColor
[3] = 0.0f
;
958 sampler_desc
.MinLOD
= 0.0f
;
959 sampler_desc
.MaxLOD
= 0.0f
;
961 if (FAILED(hr
= ID3D10Device_CreateSamplerState(device
,
962 &sampler_desc
, &brush
->u
.bitmap
.sampler_state
)))
963 ERR("Failed to create sampler state, hr %#x.\n", hr
);
965 ID3D10Device_PSSetSamplers(device
, brush_idx
, 1, &brush
->u
.bitmap
.sampler_state
);
968 void d2d_brush_bind_resources(struct d2d_brush
*brush
, ID3D10Device
*device
, unsigned int brush_idx
)
970 if (brush
->type
== D2D_BRUSH_TYPE_BITMAP
)
971 d2d_brush_bind_bitmap(brush
, device
, brush_idx
);
972 else if (brush
->type
!= D2D_BRUSH_TYPE_SOLID
)
973 FIXME("Unhandled brush type %#x.\n", brush
->type
);