2 * Copyright 2018 Nikolay Sivov 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 "d2d1_private.h"
21 WINE_DEFAULT_DEBUG_CHANNEL(d2d
);
23 static inline struct d2d_transform
*impl_from_ID2D1OffsetTransform(ID2D1OffsetTransform
*iface
)
25 return CONTAINING_RECORD(iface
, struct d2d_transform
, ID2D1TransformNode_iface
);
28 static inline struct d2d_transform
*impl_from_ID2D1BlendTransform(ID2D1BlendTransform
*iface
)
30 return CONTAINING_RECORD(iface
, struct d2d_transform
, ID2D1TransformNode_iface
);
33 static inline struct d2d_transform
*impl_from_ID2D1BorderTransform(ID2D1BorderTransform
*iface
)
35 return CONTAINING_RECORD(iface
, struct d2d_transform
, ID2D1TransformNode_iface
);
38 static inline struct d2d_transform
*impl_from_ID2D1BoundsAdjustmentTransform(
39 ID2D1BoundsAdjustmentTransform
*iface
)
41 return CONTAINING_RECORD(iface
, struct d2d_transform
, ID2D1TransformNode_iface
);
44 static inline struct d2d_vertex_buffer
*impl_from_ID2D1VertexBuffer(ID2D1VertexBuffer
*iface
)
46 return CONTAINING_RECORD(iface
, struct d2d_vertex_buffer
, ID2D1VertexBuffer_iface
);
49 static HRESULT STDMETHODCALLTYPE
d2d_vertex_buffer_QueryInterface(ID2D1VertexBuffer
*iface
,
50 REFIID iid
, void **out
)
52 TRACE("iface %p, iid %s, out %p.\n", iface
, debugstr_guid(iid
), out
);
54 if (IsEqualGUID(iid
, &IID_ID2D1VertexBuffer
)
55 || IsEqualGUID(iid
, &IID_IUnknown
))
58 ID2D1VertexBuffer_AddRef(iface
);
62 WARN("Unsupported interface %s.\n", debugstr_guid(iid
));
67 static ULONG STDMETHODCALLTYPE
d2d_vertex_buffer_AddRef(ID2D1VertexBuffer
*iface
)
69 struct d2d_vertex_buffer
*buffer
= impl_from_ID2D1VertexBuffer(iface
);
70 ULONG refcount
= InterlockedIncrement(&buffer
->refcount
);
72 TRACE("%p increasing refcount to %lu.\n", iface
, refcount
);
77 static ULONG STDMETHODCALLTYPE
d2d_vertex_buffer_Release(ID2D1VertexBuffer
*iface
)
79 struct d2d_vertex_buffer
*buffer
= impl_from_ID2D1VertexBuffer(iface
);
80 ULONG refcount
= InterlockedDecrement(&buffer
->refcount
);
82 TRACE("%p decreasing refcount to %lu.\n", iface
, refcount
);
90 static HRESULT STDMETHODCALLTYPE
d2d_vertex_buffer_Map(ID2D1VertexBuffer
*iface
, BYTE
**data
, UINT32 size
)
92 FIXME("iface %p, data %p, size %u.\n", iface
, data
, size
);
97 static HRESULT STDMETHODCALLTYPE
d2d_vertex_buffer_Unmap(ID2D1VertexBuffer
*iface
)
99 FIXME("iface %p.\n", iface
);
104 static const ID2D1VertexBufferVtbl d2d_vertex_buffer_vtbl
=
106 d2d_vertex_buffer_QueryInterface
,
107 d2d_vertex_buffer_AddRef
,
108 d2d_vertex_buffer_Release
,
109 d2d_vertex_buffer_Map
,
110 d2d_vertex_buffer_Unmap
,
113 static HRESULT
d2d_vertex_buffer_create(ID2D1VertexBuffer
**buffer
)
115 struct d2d_vertex_buffer
*object
;
117 if (!(object
= calloc(1, sizeof(*object
))))
118 return E_OUTOFMEMORY
;
120 object
->ID2D1VertexBuffer_iface
.lpVtbl
= &d2d_vertex_buffer_vtbl
;
121 object
->refcount
= 1;
123 *buffer
= &object
->ID2D1VertexBuffer_iface
;
128 static HRESULT STDMETHODCALLTYPE
d2d_offset_transform_QueryInterface(ID2D1OffsetTransform
*iface
,
129 REFIID iid
, void **out
)
131 TRACE("iface %p, iid %s, out %p.\n", iface
, debugstr_guid(iid
), out
);
133 if (IsEqualGUID(iid
, &IID_ID2D1OffsetTransform
)
134 || IsEqualGUID(iid
, &IID_ID2D1TransformNode
)
135 || IsEqualGUID(iid
, &IID_IUnknown
))
138 ID2D1OffsetTransform_AddRef(iface
);
142 WARN("Unsupported interface %s.\n", debugstr_guid(iid
));
144 return E_NOINTERFACE
;
147 static ULONG STDMETHODCALLTYPE
d2d_offset_transform_AddRef(ID2D1OffsetTransform
*iface
)
149 struct d2d_transform
*transform
= impl_from_ID2D1OffsetTransform(iface
);
150 ULONG refcount
= InterlockedIncrement(&transform
->refcount
);
152 TRACE("%p increasing refcount to %lu.\n", iface
, refcount
);
157 static ULONG STDMETHODCALLTYPE
d2d_offset_transform_Release(ID2D1OffsetTransform
*iface
)
159 struct d2d_transform
*transform
= impl_from_ID2D1OffsetTransform(iface
);
160 ULONG refcount
= InterlockedDecrement(&transform
->refcount
);
162 TRACE("%p decreasing refcount to %lu.\n", iface
, refcount
);
170 static UINT32 STDMETHODCALLTYPE
d2d_offset_transform_GetInputCount(ID2D1OffsetTransform
*iface
)
172 TRACE("iface %p.\n", iface
);
177 static void STDMETHODCALLTYPE
d2d_offset_transform_SetOffset(ID2D1OffsetTransform
*iface
,
178 D2D1_POINT_2L offset
)
180 struct d2d_transform
*transform
= impl_from_ID2D1OffsetTransform(iface
);
182 TRACE("iface %p, offset %s.\n", iface
, debug_d2d_point_2l(&offset
));
184 transform
->offset
= offset
;
187 static D2D1_POINT_2L
* STDMETHODCALLTYPE
d2d_offset_transform_GetOffset(ID2D1OffsetTransform
*iface
,
188 D2D1_POINT_2L
*offset
)
190 struct d2d_transform
*transform
= impl_from_ID2D1OffsetTransform(iface
);
192 TRACE("iface %p.\n", iface
);
194 *offset
= transform
->offset
;
198 static const ID2D1OffsetTransformVtbl d2d_offset_transform_vtbl
=
200 d2d_offset_transform_QueryInterface
,
201 d2d_offset_transform_AddRef
,
202 d2d_offset_transform_Release
,
203 d2d_offset_transform_GetInputCount
,
204 d2d_offset_transform_SetOffset
,
205 d2d_offset_transform_GetOffset
,
208 static HRESULT
d2d_offset_transform_create(D2D1_POINT_2L offset
, ID2D1OffsetTransform
**transform
)
210 struct d2d_transform
*object
;
212 if (!(object
= calloc(1, sizeof(*object
))))
213 return E_OUTOFMEMORY
;
215 object
->ID2D1TransformNode_iface
.lpVtbl
= (ID2D1TransformNodeVtbl
*)&d2d_offset_transform_vtbl
;
216 object
->refcount
= 1;
217 object
->offset
= offset
;
219 *transform
= (ID2D1OffsetTransform
*)&object
->ID2D1TransformNode_iface
;
224 static HRESULT STDMETHODCALLTYPE
d2d_blend_transform_QueryInterface(ID2D1BlendTransform
*iface
,
225 REFIID iid
, void **out
)
227 TRACE("iface %p, iid %s, out %p.\n", iface
, debugstr_guid(iid
), out
);
229 if (IsEqualGUID(iid
, &IID_ID2D1BlendTransform
)
230 || IsEqualGUID(iid
, &IID_ID2D1ConcreteTransform
)
231 || IsEqualGUID(iid
, &IID_ID2D1TransformNode
)
232 || IsEqualGUID(iid
, &IID_IUnknown
))
235 ID2D1BlendTransform_AddRef(iface
);
239 WARN("Unsupported interface %s.\n", debugstr_guid(iid
));
241 return E_NOINTERFACE
;
244 static ULONG STDMETHODCALLTYPE
d2d_blend_transform_AddRef(ID2D1BlendTransform
*iface
)
246 struct d2d_transform
*transform
= impl_from_ID2D1BlendTransform(iface
);
247 ULONG refcount
= InterlockedIncrement(&transform
->refcount
);
249 TRACE("%p increasing refcount to %lu.\n", iface
, refcount
);
254 static ULONG STDMETHODCALLTYPE
d2d_blend_transform_Release(ID2D1BlendTransform
*iface
)
256 struct d2d_transform
*transform
= impl_from_ID2D1BlendTransform(iface
);
257 ULONG refcount
= InterlockedDecrement(&transform
->refcount
);
259 TRACE("%p decreasing refcount to %lu.\n", iface
, refcount
);
267 static UINT32 STDMETHODCALLTYPE
d2d_blend_transform_GetInputCount(ID2D1BlendTransform
*iface
)
269 struct d2d_transform
*transform
= impl_from_ID2D1BlendTransform(iface
);
271 TRACE("iface %p.\n", iface
);
273 return transform
->input_count
;
276 static HRESULT STDMETHODCALLTYPE
d2d_blend_transform_SetOutputBuffer(ID2D1BlendTransform
*iface
,
277 D2D1_BUFFER_PRECISION precision
, D2D1_CHANNEL_DEPTH depth
)
279 FIXME("iface %p, precision %u, depth %u stub.\n", iface
, precision
, depth
);
284 static void STDMETHODCALLTYPE
d2d_blend_transform_SetCached(ID2D1BlendTransform
*iface
,
287 FIXME("iface %p, is_cached %d stub.\n", iface
, is_cached
);
290 static void STDMETHODCALLTYPE
d2d_blend_transform_SetDescription(ID2D1BlendTransform
*iface
,
291 const D2D1_BLEND_DESCRIPTION
*description
)
293 struct d2d_transform
*transform
= impl_from_ID2D1BlendTransform(iface
);
295 TRACE("iface %p, description %p.\n", iface
, description
);
297 transform
->blend_desc
= *description
;
300 static void STDMETHODCALLTYPE
d2d_blend_transform_GetDescription(ID2D1BlendTransform
*iface
,
301 D2D1_BLEND_DESCRIPTION
*description
)
303 struct d2d_transform
*transform
= impl_from_ID2D1BlendTransform(iface
);
305 TRACE("iface %p, description %p.\n", iface
, description
);
307 *description
= transform
->blend_desc
;
310 static const ID2D1BlendTransformVtbl d2d_blend_transform_vtbl
=
312 d2d_blend_transform_QueryInterface
,
313 d2d_blend_transform_AddRef
,
314 d2d_blend_transform_Release
,
315 d2d_blend_transform_GetInputCount
,
316 d2d_blend_transform_SetOutputBuffer
,
317 d2d_blend_transform_SetCached
,
318 d2d_blend_transform_SetDescription
,
319 d2d_blend_transform_GetDescription
,
322 static HRESULT
d2d_blend_transform_create(UINT32 input_count
, const D2D1_BLEND_DESCRIPTION
*blend_desc
,
323 ID2D1BlendTransform
**transform
)
325 struct d2d_transform
*object
;
332 if (!(object
= calloc(1, sizeof(*object
))))
333 return E_OUTOFMEMORY
;
335 object
->ID2D1TransformNode_iface
.lpVtbl
= (ID2D1TransformNodeVtbl
*)&d2d_blend_transform_vtbl
;
336 object
->refcount
= 1;
337 object
->input_count
= input_count
;
338 object
->blend_desc
= *blend_desc
;
340 *transform
= (ID2D1BlendTransform
*)&object
->ID2D1TransformNode_iface
;
345 static HRESULT STDMETHODCALLTYPE
d2d_border_transform_QueryInterface(ID2D1BorderTransform
*iface
,
346 REFIID iid
, void **out
)
348 TRACE("iface %p, iid %s, out %p.\n", iface
, debugstr_guid(iid
), out
);
350 if (IsEqualGUID(iid
, &IID_ID2D1BorderTransform
)
351 || IsEqualGUID(iid
, &IID_ID2D1ConcreteTransform
)
352 || IsEqualGUID(iid
, &IID_ID2D1TransformNode
)
353 || IsEqualGUID(iid
, &IID_IUnknown
))
356 ID2D1BorderTransform_AddRef(iface
);
360 WARN("Unsupported interface %s.\n", debugstr_guid(iid
));
362 return E_NOINTERFACE
;
365 static ULONG STDMETHODCALLTYPE
d2d_border_transform_AddRef(ID2D1BorderTransform
*iface
)
367 struct d2d_transform
*transform
= impl_from_ID2D1BorderTransform(iface
);
368 ULONG refcount
= InterlockedIncrement(&transform
->refcount
);
370 TRACE("%p increasing refcount to %lu.\n", iface
, refcount
);
375 static ULONG STDMETHODCALLTYPE
d2d_border_transform_Release(ID2D1BorderTransform
*iface
)
377 struct d2d_transform
*transform
= impl_from_ID2D1BorderTransform(iface
);
378 ULONG refcount
= InterlockedDecrement(&transform
->refcount
);
380 TRACE("%p decreasing refcount to %lu.\n", iface
, refcount
);
388 static UINT32 STDMETHODCALLTYPE
d2d_border_transform_GetInputCount(ID2D1BorderTransform
*iface
)
390 TRACE("iface %p.\n", iface
);
395 static HRESULT STDMETHODCALLTYPE
d2d_border_transform_SetOutputBuffer(
396 ID2D1BorderTransform
*iface
, D2D1_BUFFER_PRECISION precision
, D2D1_CHANNEL_DEPTH depth
)
398 FIXME("iface %p, precision %u, depth %u stub.\n", iface
, precision
, depth
);
403 static void STDMETHODCALLTYPE
d2d_border_transform_SetCached(
404 ID2D1BorderTransform
*iface
, BOOL is_cached
)
406 FIXME("iface %p, is_cached %d stub.\n", iface
, is_cached
);
409 static void STDMETHODCALLTYPE
d2d_border_transform_SetExtendModeX(
410 ID2D1BorderTransform
*iface
, D2D1_EXTEND_MODE mode
)
412 struct d2d_transform
*transform
= impl_from_ID2D1BorderTransform(iface
);
414 TRACE("iface %p.\n", iface
);
418 case D2D1_EXTEND_MODE_CLAMP
:
419 case D2D1_EXTEND_MODE_WRAP
:
420 case D2D1_EXTEND_MODE_MIRROR
:
421 transform
->border
.mode_x
= mode
;
428 static void STDMETHODCALLTYPE
d2d_border_transform_SetExtendModeY(
429 ID2D1BorderTransform
*iface
, D2D1_EXTEND_MODE mode
)
431 struct d2d_transform
*transform
= impl_from_ID2D1BorderTransform(iface
);
433 TRACE("iface %p.\n", iface
);
437 case D2D1_EXTEND_MODE_CLAMP
:
438 case D2D1_EXTEND_MODE_WRAP
:
439 case D2D1_EXTEND_MODE_MIRROR
:
440 transform
->border
.mode_y
= mode
;
447 static D2D1_EXTEND_MODE STDMETHODCALLTYPE
d2d_border_transform_GetExtendModeX(
448 ID2D1BorderTransform
*iface
)
450 struct d2d_transform
*transform
= impl_from_ID2D1BorderTransform(iface
);
452 TRACE("iface %p.\n", iface
);
454 return transform
->border
.mode_x
;
457 static D2D1_EXTEND_MODE STDMETHODCALLTYPE
d2d_border_transform_GetExtendModeY(
458 ID2D1BorderTransform
*iface
)
460 struct d2d_transform
*transform
= impl_from_ID2D1BorderTransform(iface
);
462 TRACE("iface %p.\n", iface
);
464 return transform
->border
.mode_y
;
467 static const ID2D1BorderTransformVtbl d2d_border_transform_vtbl
=
469 d2d_border_transform_QueryInterface
,
470 d2d_border_transform_AddRef
,
471 d2d_border_transform_Release
,
472 d2d_border_transform_GetInputCount
,
473 d2d_border_transform_SetOutputBuffer
,
474 d2d_border_transform_SetCached
,
475 d2d_border_transform_SetExtendModeX
,
476 d2d_border_transform_SetExtendModeY
,
477 d2d_border_transform_GetExtendModeX
,
478 d2d_border_transform_GetExtendModeY
,
481 static HRESULT
d2d_border_transform_create(D2D1_EXTEND_MODE mode_x
, D2D1_EXTEND_MODE mode_y
,
482 ID2D1BorderTransform
**transform
)
484 struct d2d_transform
*object
;
488 if (!(object
= calloc(1, sizeof(*object
))))
489 return E_OUTOFMEMORY
;
491 object
->ID2D1TransformNode_iface
.lpVtbl
= (ID2D1TransformNodeVtbl
*)&d2d_border_transform_vtbl
;
492 object
->refcount
= 1;
493 object
->border
.mode_x
= mode_x
;
494 object
->border
.mode_y
= mode_y
;
496 *transform
= (ID2D1BorderTransform
*)&object
->ID2D1TransformNode_iface
;
501 static HRESULT STDMETHODCALLTYPE
d2d_bounds_adjustment_transform_QueryInterface(
502 ID2D1BoundsAdjustmentTransform
*iface
, REFIID iid
, void **out
)
504 TRACE("iface %p, iid %s, out %p.\n", iface
, debugstr_guid(iid
), out
);
506 if (IsEqualGUID(iid
, &IID_ID2D1BoundsAdjustmentTransform
)
507 || IsEqualGUID(iid
, &IID_ID2D1TransformNode
)
508 || IsEqualGUID(iid
, &IID_IUnknown
))
511 ID2D1BoundsAdjustmentTransform_AddRef(iface
);
515 WARN("Unsupported interface %s.\n", debugstr_guid(iid
));
517 return E_NOINTERFACE
;
520 static ULONG STDMETHODCALLTYPE
d2d_bounds_adjustment_transform_AddRef(
521 ID2D1BoundsAdjustmentTransform
*iface
)
523 struct d2d_transform
*transform
= impl_from_ID2D1BoundsAdjustmentTransform(iface
);
524 ULONG refcount
= InterlockedIncrement(&transform
->refcount
);
526 TRACE("%p increasing refcount to %lu.\n", iface
, refcount
);
531 static ULONG STDMETHODCALLTYPE
d2d_bounds_adjustment_transform_Release(
532 ID2D1BoundsAdjustmentTransform
*iface
)
534 struct d2d_transform
*transform
= impl_from_ID2D1BoundsAdjustmentTransform(iface
);
535 ULONG refcount
= InterlockedDecrement(&transform
->refcount
);
537 TRACE("%p decreasing refcount to %lu.\n", iface
, refcount
);
545 static UINT32 STDMETHODCALLTYPE
d2d_bounds_adjustment_transform_GetInputCount(
546 ID2D1BoundsAdjustmentTransform
*iface
)
548 TRACE("iface %p.\n", iface
);
553 static void STDMETHODCALLTYPE
d2d_bounds_adjustment_transform_SetOutputBounds(
554 ID2D1BoundsAdjustmentTransform
*iface
, const D2D1_RECT_L
*bounds
)
556 struct d2d_transform
*transform
= impl_from_ID2D1BoundsAdjustmentTransform(iface
);
558 TRACE("iface %p.\n", iface
);
560 transform
->bounds
= *bounds
;
563 static void STDMETHODCALLTYPE
d2d_bounds_adjustment_transform_GetOutputBounds(
564 ID2D1BoundsAdjustmentTransform
*iface
, D2D1_RECT_L
*bounds
)
566 struct d2d_transform
*transform
= impl_from_ID2D1BoundsAdjustmentTransform(iface
);
568 TRACE("iface %p.\n", iface
);
570 *bounds
= transform
->bounds
;
573 static const ID2D1BoundsAdjustmentTransformVtbl d2d_bounds_adjustment_transform_vtbl
=
575 d2d_bounds_adjustment_transform_QueryInterface
,
576 d2d_bounds_adjustment_transform_AddRef
,
577 d2d_bounds_adjustment_transform_Release
,
578 d2d_bounds_adjustment_transform_GetInputCount
,
579 d2d_bounds_adjustment_transform_SetOutputBounds
,
580 d2d_bounds_adjustment_transform_GetOutputBounds
,
583 static HRESULT
d2d_bounds_adjustment_transform_create(const D2D1_RECT_L
*rect
,
584 ID2D1BoundsAdjustmentTransform
**transform
)
586 struct d2d_transform
*object
;
590 if (!(object
= calloc(1, sizeof(*object
))))
591 return E_OUTOFMEMORY
;
593 object
->ID2D1TransformNode_iface
.lpVtbl
= (ID2D1TransformNodeVtbl
*)&d2d_bounds_adjustment_transform_vtbl
;
594 object
->refcount
= 1;
595 object
->bounds
= *rect
;
597 *transform
= (ID2D1BoundsAdjustmentTransform
*)&object
->ID2D1TransformNode_iface
;
602 static struct d2d_transform_node
* d2d_transform_graph_get_node(const struct d2d_transform_graph
*graph
,
603 ID2D1TransformNode
*object
)
605 struct d2d_transform_node
*node
;
607 LIST_FOR_EACH_ENTRY(node
, &graph
->nodes
, struct d2d_transform_node
, entry
)
609 if (node
->object
== object
)
616 static HRESULT
d2d_transform_graph_add_node(struct d2d_transform_graph
*graph
,
617 ID2D1TransformNode
*object
)
619 struct d2d_transform_node
*node
;
621 if (!(node
= calloc(1, sizeof(*node
))))
622 return E_OUTOFMEMORY
;
623 node
->input_count
= ID2D1TransformNode_GetInputCount(object
);
624 if (!(node
->inputs
= calloc(node
->input_count
, sizeof(*node
->inputs
))))
627 return E_OUTOFMEMORY
;
630 node
->object
= object
;
631 ID2D1TransformNode_AddRef(node
->object
);
632 list_add_tail(&graph
->nodes
, &node
->entry
);
637 static void d2d_transform_node_disconnect(struct d2d_transform_node
*node
)
639 struct d2d_transform_node
*output
= node
->output
;
645 for (i
= 0; i
< output
->input_count
; ++i
)
647 if (output
->inputs
[i
] == node
)
649 output
->inputs
[i
] = NULL
;
655 static void d2d_transform_graph_delete_node(struct d2d_transform_graph
*graph
,
656 struct d2d_transform_node
*node
)
660 list_remove(&node
->entry
);
661 ID2D1TransformNode_Release(node
->object
);
663 for (i
= 0; i
< graph
->input_count
; ++i
)
665 if (graph
->inputs
[i
].node
== node
)
666 memset(&graph
->inputs
[i
].node
, 0, sizeof(graph
->inputs
[i
].node
));
669 if (graph
->output
== node
)
670 graph
->output
= NULL
;
672 if (node
->render_info
)
673 ID2D1DrawInfo_Release(&node
->render_info
->ID2D1DrawInfo_iface
);
675 d2d_transform_node_disconnect(node
);
681 static void d2d_transform_graph_clear(struct d2d_transform_graph
*graph
)
683 struct d2d_transform_node
*node
, *node_next
;
685 LIST_FOR_EACH_ENTRY_SAFE(node
, node_next
, &graph
->nodes
, struct d2d_transform_node
, entry
)
687 d2d_transform_graph_delete_node(graph
, node
);
689 graph
->passthrough
= false;
692 static inline struct d2d_transform_graph
*impl_from_ID2D1TransformGraph(ID2D1TransformGraph
*iface
)
694 return CONTAINING_RECORD(iface
, struct d2d_transform_graph
, ID2D1TransformGraph_iface
);
697 static HRESULT STDMETHODCALLTYPE
d2d_transform_graph_QueryInterface(ID2D1TransformGraph
*iface
, REFIID iid
, void **out
)
699 TRACE("iface %p, iid %s, out %p.\n", iface
, debugstr_guid(iid
), out
);
701 if (IsEqualGUID(iid
, &IID_ID2D1TransformGraph
)
702 || IsEqualGUID(iid
, &IID_IUnknown
))
704 ID2D1TransformGraph_AddRef(iface
);
710 return E_NOINTERFACE
;
713 static ULONG STDMETHODCALLTYPE
d2d_transform_graph_AddRef(ID2D1TransformGraph
*iface
)
715 struct d2d_transform_graph
*graph
=impl_from_ID2D1TransformGraph(iface
);
716 ULONG refcount
= InterlockedIncrement(&graph
->refcount
);
718 TRACE("%p increasing refcount to %lu.\n", iface
, refcount
);
723 static ULONG STDMETHODCALLTYPE
d2d_transform_graph_Release(ID2D1TransformGraph
*iface
)
725 struct d2d_transform_graph
*graph
= impl_from_ID2D1TransformGraph(iface
);
726 ULONG refcount
= InterlockedDecrement(&graph
->refcount
);
728 TRACE("%p decreasing refcount to %lu.\n", iface
, refcount
);
732 d2d_transform_graph_clear(graph
);
740 static UINT32 STDMETHODCALLTYPE
d2d_transform_graph_GetInputCount(ID2D1TransformGraph
*iface
)
742 struct d2d_transform_graph
*graph
= impl_from_ID2D1TransformGraph(iface
);
744 TRACE("iface %p.\n", iface
);
746 return graph
->input_count
;
749 static HRESULT STDMETHODCALLTYPE
d2d_transform_graph_SetSingleTransformNode(ID2D1TransformGraph
*iface
,
750 ID2D1TransformNode
*object
)
752 struct d2d_transform_graph
*graph
= impl_from_ID2D1TransformGraph(iface
);
753 struct d2d_transform_node
*node
;
754 unsigned int i
, input_count
;
757 TRACE("iface %p, object %p.\n", iface
, object
);
759 d2d_transform_graph_clear(graph
);
760 if (FAILED(hr
= d2d_transform_graph_add_node(graph
, object
)))
763 node
= d2d_transform_graph_get_node(graph
, object
);
764 graph
->output
= node
;
766 input_count
= ID2D1TransformNode_GetInputCount(object
);
767 if (graph
->input_count
!= input_count
)
770 for (i
= 0; i
< graph
->input_count
; ++i
)
772 graph
->inputs
[i
].node
= node
;
773 graph
->inputs
[i
].index
= i
;
779 static HRESULT STDMETHODCALLTYPE
d2d_transform_graph_AddNode(ID2D1TransformGraph
*iface
,
780 ID2D1TransformNode
*object
)
782 struct d2d_transform_graph
*graph
= impl_from_ID2D1TransformGraph(iface
);
784 TRACE("iface %p, object %p.\n", iface
, object
);
786 if (d2d_transform_graph_get_node(graph
, object
))
789 return d2d_transform_graph_add_node(graph
, object
);
792 static HRESULT STDMETHODCALLTYPE
d2d_transform_graph_RemoveNode(ID2D1TransformGraph
*iface
,
793 ID2D1TransformNode
*object
)
795 struct d2d_transform_graph
*graph
= impl_from_ID2D1TransformGraph(iface
);
796 struct d2d_transform_node
*node
;
798 TRACE("iface %p, object %p.\n", iface
, object
);
800 if (!(node
= d2d_transform_graph_get_node(graph
, object
)))
801 return HRESULT_FROM_WIN32(ERROR_NOT_FOUND
);
803 d2d_transform_graph_delete_node(graph
, node
);
807 static HRESULT STDMETHODCALLTYPE
d2d_transform_graph_SetOutputNode(ID2D1TransformGraph
*iface
,
808 ID2D1TransformNode
*object
)
810 struct d2d_transform_graph
*graph
= impl_from_ID2D1TransformGraph(iface
);
811 struct d2d_transform_node
*node
;
813 TRACE("iface %p, object %p.\n", iface
, object
);
815 if (!(node
= d2d_transform_graph_get_node(graph
, object
)))
816 return HRESULT_FROM_WIN32(ERROR_NOT_FOUND
);
818 graph
->output
= node
;
819 graph
->passthrough
= false;
824 static HRESULT STDMETHODCALLTYPE
d2d_transform_graph_ConnectNode(ID2D1TransformGraph
*iface
,
825 ID2D1TransformNode
*from_node
, ID2D1TransformNode
*to_node
, UINT32 index
)
827 struct d2d_transform_graph
*graph
= impl_from_ID2D1TransformGraph(iface
);
828 struct d2d_transform_node
*from
, *to
;
830 TRACE("iface %p, from_node %p, to_node %p, index %u.\n", iface
, from_node
, to_node
, index
);
832 if (!(from
= d2d_transform_graph_get_node(graph
, from_node
)))
833 return HRESULT_FROM_WIN32(ERROR_NOT_FOUND
);
835 if (!(to
= d2d_transform_graph_get_node(graph
, to_node
)))
836 return HRESULT_FROM_WIN32(ERROR_NOT_FOUND
);
838 if (index
>= to
->input_count
)
841 d2d_transform_node_disconnect(from
);
842 to
->inputs
[index
] = from
;
848 static HRESULT STDMETHODCALLTYPE
d2d_transform_graph_ConnectToEffectInput(ID2D1TransformGraph
*iface
,
849 UINT32 input_index
, ID2D1TransformNode
*object
, UINT32 node_index
)
851 struct d2d_transform_graph
*graph
= impl_from_ID2D1TransformGraph(iface
);
852 struct d2d_transform_node
*node
;
855 TRACE("iface %p, input_index %u, object %p, node_index %u.\n", iface
, input_index
, object
, node_index
);
857 if (!(node
= d2d_transform_graph_get_node(graph
, object
)))
858 return HRESULT_FROM_WIN32(ERROR_NOT_FOUND
);
860 if (input_index
>= graph
->input_count
)
863 count
= ID2D1TransformNode_GetInputCount(object
);
864 if (node_index
>= count
)
867 graph
->inputs
[input_index
].node
= node
;
868 graph
->inputs
[input_index
].index
= node_index
;
869 graph
->passthrough
= false;
874 static void STDMETHODCALLTYPE
d2d_transform_graph_Clear(ID2D1TransformGraph
*iface
)
876 struct d2d_transform_graph
*graph
= impl_from_ID2D1TransformGraph(iface
);
878 TRACE("iface %p.\n", iface
);
880 d2d_transform_graph_clear(graph
);
883 static HRESULT STDMETHODCALLTYPE
d2d_transform_graph_SetPassthroughGraph(ID2D1TransformGraph
*iface
, UINT32 index
)
885 struct d2d_transform_graph
*graph
= impl_from_ID2D1TransformGraph(iface
);
887 TRACE("iface %p, index %u.\n", iface
, index
);
889 if (index
>= graph
->input_count
)
892 d2d_transform_graph_clear(graph
);
894 graph
->passthrough
= true;
895 graph
->passthrough_input
= index
;
900 static const ID2D1TransformGraphVtbl d2d_transform_graph_vtbl
=
902 d2d_transform_graph_QueryInterface
,
903 d2d_transform_graph_AddRef
,
904 d2d_transform_graph_Release
,
905 d2d_transform_graph_GetInputCount
,
906 d2d_transform_graph_SetSingleTransformNode
,
907 d2d_transform_graph_AddNode
,
908 d2d_transform_graph_RemoveNode
,
909 d2d_transform_graph_SetOutputNode
,
910 d2d_transform_graph_ConnectNode
,
911 d2d_transform_graph_ConnectToEffectInput
,
912 d2d_transform_graph_Clear
,
913 d2d_transform_graph_SetPassthroughGraph
,
916 static HRESULT
d2d_transform_graph_create(UINT32 input_count
, struct d2d_transform_graph
**graph
)
918 struct d2d_transform_graph
*object
;
920 if (!(object
= calloc(1, sizeof(*object
))))
921 return E_OUTOFMEMORY
;
923 object
->ID2D1TransformGraph_iface
.lpVtbl
= &d2d_transform_graph_vtbl
;
924 object
->refcount
= 1;
925 list_init(&object
->nodes
);
927 if (!(object
->inputs
= calloc(input_count
, sizeof(*object
->inputs
))))
930 return E_OUTOFMEMORY
;
932 object
->input_count
= input_count
;
939 static HRESULT STDMETHODCALLTYPE
d2d_effect_impl_QueryInterface(ID2D1EffectImpl
*iface
, REFIID iid
, void **out
)
941 TRACE("iface %p, iid %s, out %p.\n", iface
, debugstr_guid(iid
), out
);
943 if (IsEqualGUID(iid
, &IID_ID2D1EffectImpl
)
944 || IsEqualGUID(iid
, &IID_IUnknown
))
946 ID2D1EffectImpl_AddRef(iface
);
952 return E_NOINTERFACE
;
955 static ULONG STDMETHODCALLTYPE
d2d_effect_impl_AddRef(ID2D1EffectImpl
*iface
)
960 static ULONG STDMETHODCALLTYPE
d2d_effect_impl_Release(ID2D1EffectImpl
*iface
)
965 static HRESULT STDMETHODCALLTYPE
d2d_effect_impl_Initialize(ID2D1EffectImpl
*iface
,
966 ID2D1EffectContext
*context
, ID2D1TransformGraph
*graph
)
971 static HRESULT STDMETHODCALLTYPE
d2d_effect_impl_PrepareForRender(ID2D1EffectImpl
*iface
, D2D1_CHANGE_TYPE type
)
976 static HRESULT STDMETHODCALLTYPE
d2d_effect_impl_SetGraph(ID2D1EffectImpl
*iface
, ID2D1TransformGraph
*graph
)
981 static const ID2D1EffectImplVtbl d2d_effect_impl_vtbl
=
983 d2d_effect_impl_QueryInterface
,
984 d2d_effect_impl_AddRef
,
985 d2d_effect_impl_Release
,
986 d2d_effect_impl_Initialize
,
987 d2d_effect_impl_PrepareForRender
,
988 d2d_effect_impl_SetGraph
,
991 static HRESULT STDMETHODCALLTYPE
builtin_factory_stub(IUnknown
**effect_impl
)
993 static ID2D1EffectImpl builtin_stub
= { &d2d_effect_impl_vtbl
};
995 *effect_impl
= (IUnknown
*)&builtin_stub
;
1000 static const WCHAR _2d_affine_transform_description
[] =
1001 L
"<?xml version='1.0'?> \
1003 <Property name='DisplayName' type='string' value='2D Affine Transform'/> \
1004 <Property name='Author' type='string' value='The Wine Project'/> \
1005 <Property name='Category' type='string' value='Stub'/> \
1006 <Property name='Description' type='string' value='2D Affine Transform'/> \
1008 <Input name='Source'/> \
1012 static const WCHAR _3d_perspective_transform_description
[] =
1013 L
"<?xml version='1.0'?> \
1015 <Property name='DisplayName' type='string' value='3D Perspective Transform'/> \
1016 <Property name='Author' type='string' value='The Wine Project'/> \
1017 <Property name='Category' type='string' value='Stub'/> \
1018 <Property name='Description' type='string' value='3D Perspective Transform'/> \
1020 <Input name='Source'/> \
1024 static const WCHAR composite_description
[] =
1025 L
"<?xml version='1.0'?> \
1027 <Property name='DisplayName' type='string' value='Composite'/> \
1028 <Property name='Author' type='string' value='The Wine Project'/> \
1029 <Property name='Category' type='string' value='Stub'/> \
1030 <Property name='Description' type='string' value='Composite'/> \
1031 <Inputs minimum='1' maximum='0xffffffff' > \
1032 <Input name='Source1'/> \
1033 <Input name='Source2'/> \
1037 static const WCHAR crop_description
[] =
1038 L
"<?xml version='1.0'?> \
1040 <Property name='DisplayName' type='string' value='Crop'/> \
1041 <Property name='Author' type='string' value='The Wine Project'/> \
1042 <Property name='Category' type='string' value='Stub'/> \
1043 <Property name='Description' type='string' value='Crop'/> \
1045 <Input name='Source'/> \
1047 <Property name='Rect' type='vector4' /> \
1050 static const WCHAR shadow_description
[] =
1051 L
"<?xml version='1.0'?> \
1053 <Property name='DisplayName' type='string' value='Shadow'/> \
1054 <Property name='Author' type='string' value='The Wine Project'/> \
1055 <Property name='Category' type='string' value='Stub'/> \
1056 <Property name='Description' type='string' value='Shadow'/> \
1058 <Input name='Source'/> \
1062 static const WCHAR grayscale_description
[] =
1063 L
"<?xml version='1.0'?> \
1065 <Property name='DisplayName' type='string' value='Grayscale'/> \
1066 <Property name='Author' type='string' value='The Wine Project'/> \
1067 <Property name='Category' type='string' value='Stub'/> \
1068 <Property name='Description' type='string' value='Grayscale'/> \
1070 <Input name='Source'/> \
1074 void d2d_effects_init_builtins(struct d2d_factory
*factory
)
1076 static const struct builtin_description
1079 const WCHAR
*description
;
1083 { &CLSID_D2D12DAffineTransform
, _2d_affine_transform_description
},
1084 { &CLSID_D2D13DPerspectiveTransform
, _3d_perspective_transform_description
},
1085 { &CLSID_D2D1Composite
, composite_description
},
1086 { &CLSID_D2D1Crop
, crop_description
},
1087 { &CLSID_D2D1Shadow
, shadow_description
},
1088 { &CLSID_D2D1Grayscale
, grayscale_description
},
1093 for (i
= 0; i
< ARRAY_SIZE(builtin_effects
); ++i
)
1095 if (FAILED(hr
= d2d_factory_register_builtin_effect(factory
, builtin_effects
[i
].clsid
, builtin_effects
[i
].description
,
1096 NULL
, 0, builtin_factory_stub
)))
1098 WARN("Failed to register the effect %s, hr %#lx.\n", wine_dbgstr_guid(builtin_effects
[i
].clsid
), hr
);
1103 /* Same syntax is used for value and default values. */
1104 static HRESULT
d2d_effect_parse_float_array(D2D1_PROPERTY_TYPE type
, const WCHAR
*value
,
1107 unsigned int i
, num_components
;
1110 /* Type values are sequential. */
1113 case D2D1_PROPERTY_TYPE_VECTOR2
:
1114 case D2D1_PROPERTY_TYPE_VECTOR3
:
1115 case D2D1_PROPERTY_TYPE_VECTOR4
:
1116 num_components
= (type
- D2D1_PROPERTY_TYPE_VECTOR2
) + 2;
1118 case D2D1_PROPERTY_TYPE_MATRIX_3X2
:
1121 case D2D1_PROPERTY_TYPE_MATRIX_4X3
:
1122 case D2D1_PROPERTY_TYPE_MATRIX_4X4
:
1123 case D2D1_PROPERTY_TYPE_MATRIX_5X4
:
1124 num_components
= (type
- D2D1_PROPERTY_TYPE_MATRIX_4X3
) * 4 + 12;
1127 return E_UNEXPECTED
;
1130 if (*(value
++) != '(') return E_INVALIDARG
;
1132 for (i
= 0; i
< num_components
; ++i
)
1134 vec
[i
] = wcstof(value
, &end_ptr
);
1135 if (value
== end_ptr
) return E_INVALIDARG
;
1138 /* Trailing characters after last component are ignored. */
1139 if (i
== num_components
- 1) continue;
1140 if (*(value
++) != ',') return E_INVALIDARG
;
1146 static HRESULT
d2d_effect_properties_internal_add(struct d2d_effect_properties
*props
,
1147 const WCHAR
*name
, UINT32 index
, BOOL subprop
, D2D1_PROPERTY_TYPE type
, const WCHAR
*value
)
1149 static const UINT32 sizes
[] =
1151 [D2D1_PROPERTY_TYPE_UNKNOWN
] = 0,
1152 [D2D1_PROPERTY_TYPE_STRING
] = 0,
1153 [D2D1_PROPERTY_TYPE_BOOL
] = sizeof(BOOL
),
1154 [D2D1_PROPERTY_TYPE_UINT32
] = sizeof(UINT32
),
1155 [D2D1_PROPERTY_TYPE_INT32
] = sizeof(INT32
),
1156 [D2D1_PROPERTY_TYPE_FLOAT
] = sizeof(float),
1157 [D2D1_PROPERTY_TYPE_VECTOR2
] = sizeof(D2D_VECTOR_2F
),
1158 [D2D1_PROPERTY_TYPE_VECTOR3
] = sizeof(D2D_VECTOR_3F
),
1159 [D2D1_PROPERTY_TYPE_VECTOR4
] = sizeof(D2D_VECTOR_4F
),
1160 [D2D1_PROPERTY_TYPE_BLOB
] = 0 /* FIXME */,
1161 [D2D1_PROPERTY_TYPE_IUNKNOWN
] = sizeof(IUnknown
*),
1162 [D2D1_PROPERTY_TYPE_ENUM
] = sizeof(UINT32
),
1163 [D2D1_PROPERTY_TYPE_ARRAY
] = sizeof(UINT32
),
1164 [D2D1_PROPERTY_TYPE_CLSID
] = sizeof(CLSID
),
1165 [D2D1_PROPERTY_TYPE_MATRIX_3X2
] = sizeof(D2D_MATRIX_3X2_F
),
1166 [D2D1_PROPERTY_TYPE_MATRIX_4X3
] = sizeof(D2D_MATRIX_4X3_F
),
1167 [D2D1_PROPERTY_TYPE_MATRIX_4X4
] = sizeof(D2D_MATRIX_4X4_F
),
1168 [D2D1_PROPERTY_TYPE_MATRIX_5X4
] = sizeof(D2D_MATRIX_5X4_F
),
1169 [D2D1_PROPERTY_TYPE_COLOR_CONTEXT
] = sizeof(ID2D1ColorContext
*),
1171 struct d2d_effect_property
*p
;
1174 assert(type
>= D2D1_PROPERTY_TYPE_STRING
&& type
<= D2D1_PROPERTY_TYPE_COLOR_CONTEXT
);
1176 if (type
== D2D1_PROPERTY_TYPE_BLOB
)
1178 FIXME("Ignoring property %s of type %u.\n", wine_dbgstr_w(name
), type
);
1182 if (!d2d_array_reserve((void **)&props
->properties
, &props
->size
, props
->count
+ 1,
1183 sizeof(*props
->properties
)))
1185 return E_OUTOFMEMORY
;
1188 /* TODO: we could save some space for properties that have both getter and setter. */
1189 if (!d2d_array_reserve((void **)&props
->data
.ptr
, &props
->data
.size
,
1190 props
->data
.count
+ sizes
[type
], sizeof(*props
->data
.ptr
)))
1192 return E_OUTOFMEMORY
;
1194 props
->data
.count
+= sizes
[type
];
1196 p
= &props
->properties
[props
->count
++];
1197 memset(p
, 0, sizeof(*p
));
1199 if (p
->index
< 0x80000000)
1201 props
->custom_count
++;
1202 /* FIXME: this should probably be controlled by subproperty */
1203 p
->readonly
= FALSE
;
1208 p
->readonly
= index
!= D2D1_PROPERTY_CACHED
&& index
!= D2D1_PROPERTY_PRECISION
;
1209 p
->name
= wcsdup(name
);
1211 if (p
->type
== D2D1_PROPERTY_TYPE_STRING
)
1213 p
->data
.ptr
= wcsdup(value
);
1214 p
->size
= value
? (wcslen(value
) + 1) * sizeof(WCHAR
) : sizeof(WCHAR
);
1224 p
->data
.offset
= props
->offset
;
1225 p
->size
= sizes
[type
];
1226 props
->offset
+= p
->size
;
1232 case D2D1_PROPERTY_TYPE_UINT32
:
1233 case D2D1_PROPERTY_TYPE_INT32
:
1234 _uint32
= wcstoul(value
, NULL
, 0);
1237 case D2D1_PROPERTY_TYPE_ENUM
:
1238 _uint32
= wcstoul(value
, NULL
, 10);
1241 case D2D1_PROPERTY_TYPE_BOOL
:
1242 if (!wcscmp(value
, L
"true")) _bool
= TRUE
;
1243 else if (!wcscmp(value
, L
"false")) _bool
= FALSE
;
1244 else return E_INVALIDARG
;
1247 case D2D1_PROPERTY_TYPE_CLSID
:
1248 CLSIDFromString(value
, &_clsid
);
1251 case D2D1_PROPERTY_TYPE_VECTOR2
:
1252 case D2D1_PROPERTY_TYPE_VECTOR3
:
1253 case D2D1_PROPERTY_TYPE_VECTOR4
:
1254 case D2D1_PROPERTY_TYPE_MATRIX_3X2
:
1255 case D2D1_PROPERTY_TYPE_MATRIX_4X3
:
1256 case D2D1_PROPERTY_TYPE_MATRIX_4X4
:
1257 case D2D1_PROPERTY_TYPE_MATRIX_5X4
:
1258 if (FAILED(hr
= d2d_effect_parse_float_array(p
->type
, value
, _vec
)))
1260 WARN("Failed to parse float array %s for type %u.\n",
1261 wine_dbgstr_w(value
), p
->type
);
1266 case D2D1_PROPERTY_TYPE_IUNKNOWN
:
1267 case D2D1_PROPERTY_TYPE_COLOR_CONTEXT
:
1270 FIXME("Initial value for property type %u is not handled.\n", p
->type
);
1273 if (src
&& p
->size
) memcpy(props
->data
.ptr
+ p
->data
.offset
, src
, p
->size
);
1276 memset(props
->data
.ptr
+ p
->data
.offset
, 0, p
->size
);
1282 HRESULT
d2d_effect_properties_add(struct d2d_effect_properties
*props
, const WCHAR
*name
,
1283 UINT32 index
, D2D1_PROPERTY_TYPE type
, const WCHAR
*value
)
1285 return d2d_effect_properties_internal_add(props
, name
, index
, FALSE
, type
, value
);
1288 HRESULT
d2d_effect_subproperties_add(struct d2d_effect_properties
*props
, const WCHAR
*name
,
1289 UINT32 index
, D2D1_PROPERTY_TYPE type
, const WCHAR
*value
)
1291 return d2d_effect_properties_internal_add(props
, name
, index
, TRUE
, type
, value
);
1294 static HRESULT
d2d_effect_duplicate_properties(struct d2d_effect
*effect
,
1295 struct d2d_effect_properties
*dst
, const struct d2d_effect_properties
*src
)
1301 dst
->effect
= effect
;
1303 if (!(dst
->data
.ptr
= malloc(dst
->data
.size
)))
1304 return E_OUTOFMEMORY
;
1305 memcpy(dst
->data
.ptr
, src
->data
.ptr
, dst
->data
.size
);
1307 if (!(dst
->properties
= calloc(dst
->size
, sizeof(*dst
->properties
))))
1308 return E_OUTOFMEMORY
;
1310 for (i
= 0; i
< dst
->count
; ++i
)
1312 struct d2d_effect_property
*d
= &dst
->properties
[i
];
1313 const struct d2d_effect_property
*s
= &src
->properties
[i
];
1316 d
->name
= wcsdup(s
->name
);
1317 if (d
->type
== D2D1_PROPERTY_TYPE_STRING
)
1318 d
->data
.ptr
= wcsdup((WCHAR
*)s
->data
.ptr
);
1320 if (s
->subproperties
)
1322 if (!(d
->subproperties
= calloc(1, sizeof(*d
->subproperties
))))
1323 return E_OUTOFMEMORY
;
1324 if (FAILED(hr
= d2d_effect_duplicate_properties(effect
, d
->subproperties
, s
->subproperties
)))
1332 static struct d2d_effect_property
* d2d_effect_properties_get_property_by_index(
1333 const struct d2d_effect_properties
*properties
, UINT32 index
)
1337 for (i
= 0; i
< properties
->count
; ++i
)
1339 if (properties
->properties
[i
].index
== index
)
1340 return &properties
->properties
[i
];
1346 struct d2d_effect_property
* d2d_effect_properties_get_property_by_name(
1347 const struct d2d_effect_properties
*properties
, const WCHAR
*name
)
1351 for (i
= 0; i
< properties
->count
; ++i
)
1353 if (!wcscmp(properties
->properties
[i
].name
, name
))
1354 return &properties
->properties
[i
];
1360 static UINT32
d2d_effect_properties_get_value_size(const struct d2d_effect_properties
*properties
,
1363 struct d2d_effect
*effect
= properties
->effect
;
1364 struct d2d_effect_property
*prop
;
1367 if (!(prop
= d2d_effect_properties_get_property_by_index(properties
, index
)))
1370 if (prop
->get_function
)
1372 if (FAILED(prop
->get_function((IUnknown
*)effect
->impl
, NULL
, 0, &size
))) return 0;
1379 static HRESULT
d2d_effect_return_string(const WCHAR
*str
, WCHAR
*buffer
, UINT32 buffer_size
)
1381 UINT32 size
= str
? wcslen(str
) : 0;
1382 if (size
>= buffer_size
) return D2DERR_INSUFFICIENT_BUFFER
;
1383 if (str
) memcpy(buffer
, str
, (size
+ 1) * sizeof(*buffer
));
1388 static HRESULT
d2d_effect_property_get_value(const struct d2d_effect_properties
*properties
,
1389 const struct d2d_effect_property
*prop
, D2D1_PROPERTY_TYPE type
, BYTE
*value
, UINT32 size
)
1391 struct d2d_effect
*effect
= properties
->effect
;
1394 memset(value
, 0, size
);
1396 if (type
!= D2D1_PROPERTY_TYPE_UNKNOWN
&& prop
->type
!= type
) return E_INVALIDARG
;
1397 if (prop
->type
!= D2D1_PROPERTY_TYPE_STRING
&& prop
->size
!= size
) return E_INVALIDARG
;
1399 if (prop
->get_function
)
1400 return prop
->get_function((IUnknown
*)effect
->impl
, value
, size
, &actual_size
);
1404 case D2D1_PROPERTY_TYPE_BLOB
:
1405 FIXME("Unimplemented for type %u.\n", prop
->type
);
1407 case D2D1_PROPERTY_TYPE_STRING
:
1408 return d2d_effect_return_string(prop
->data
.ptr
, (WCHAR
*)value
, size
/ sizeof(WCHAR
));
1410 memcpy(value
, properties
->data
.ptr
+ prop
->data
.offset
, size
);
1417 HRESULT
d2d_effect_property_get_uint32_value(const struct d2d_effect_properties
*properties
,
1418 const struct d2d_effect_property
*prop
, UINT32
*value
)
1420 return d2d_effect_property_get_value(properties
, prop
, D2D1_PROPERTY_TYPE_UINT32
,
1421 (BYTE
*)value
, sizeof(*value
));
1424 static HRESULT
d2d_effect_property_set_value(struct d2d_effect_properties
*properties
,
1425 struct d2d_effect_property
*prop
, D2D1_PROPERTY_TYPE type
, const BYTE
*value
, UINT32 size
)
1427 struct d2d_effect
*effect
= properties
->effect
;
1428 if (prop
->readonly
|| !effect
) return E_INVALIDARG
;
1429 if (type
!= D2D1_PROPERTY_TYPE_UNKNOWN
&& prop
->type
!= type
) return E_INVALIDARG
;
1430 if (prop
->get_function
&& !prop
->set_function
) return E_INVALIDARG
;
1431 if (prop
->index
< 0x80000000 && !prop
->set_function
) return E_INVALIDARG
;
1433 if (prop
->set_function
)
1434 return prop
->set_function((IUnknown
*)effect
->impl
, value
, size
);
1436 if (prop
->size
!= size
) return E_INVALIDARG
;
1440 case D2D1_PROPERTY_TYPE_BOOL
:
1441 case D2D1_PROPERTY_TYPE_UINT32
:
1442 case D2D1_PROPERTY_TYPE_ENUM
:
1443 memcpy(properties
->data
.ptr
+ prop
->data
.offset
, value
, size
);
1446 FIXME("Unhandled type %u.\n", prop
->type
);
1452 void d2d_effect_properties_cleanup(struct d2d_effect_properties
*props
)
1454 struct d2d_effect_property
*p
;
1457 for (i
= 0; i
< props
->count
; ++i
)
1459 p
= &props
->properties
[i
];
1461 if (p
->type
== D2D1_PROPERTY_TYPE_STRING
)
1463 if (p
->subproperties
)
1465 d2d_effect_properties_cleanup(p
->subproperties
);
1466 free(p
->subproperties
);
1469 free(props
->properties
);
1470 free(props
->data
.ptr
);
1473 static inline struct d2d_effect_context
*impl_from_ID2D1EffectContext(ID2D1EffectContext
*iface
)
1475 return CONTAINING_RECORD(iface
, struct d2d_effect_context
, ID2D1EffectContext_iface
);
1478 static HRESULT STDMETHODCALLTYPE
d2d_effect_context_QueryInterface(ID2D1EffectContext
*iface
, REFIID iid
, void **out
)
1480 TRACE("iface %p, iid %s, out %p.\n", iface
, debugstr_guid(iid
), out
);
1482 if (IsEqualGUID(iid
, &IID_ID2D1EffectContext
)
1483 || IsEqualGUID(iid
, &IID_IUnknown
))
1485 ID2D1EffectContext_AddRef(iface
);
1490 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid
));
1493 return E_NOINTERFACE
;
1496 static ULONG STDMETHODCALLTYPE
d2d_effect_context_AddRef(ID2D1EffectContext
*iface
)
1498 struct d2d_effect_context
*effect_context
= impl_from_ID2D1EffectContext(iface
);
1499 ULONG refcount
= InterlockedIncrement(&effect_context
->refcount
);
1501 TRACE("%p increasing refcount to %lu.\n", iface
, refcount
);
1506 static ULONG STDMETHODCALLTYPE
d2d_effect_context_Release(ID2D1EffectContext
*iface
)
1508 struct d2d_effect_context
*effect_context
= impl_from_ID2D1EffectContext(iface
);
1509 ULONG refcount
= InterlockedDecrement(&effect_context
->refcount
);
1511 TRACE("%p decreasing refcount to %lu.\n", iface
, refcount
);
1515 ID2D1DeviceContext6_Release(&effect_context
->device_context
->ID2D1DeviceContext6_iface
);
1516 free(effect_context
);
1522 static void STDMETHODCALLTYPE
d2d_effect_context_GetDpi(ID2D1EffectContext
*iface
, float *dpi_x
, float *dpi_y
)
1524 struct d2d_effect_context
*effect_context
= impl_from_ID2D1EffectContext(iface
);
1526 TRACE("iface %p, dpi_x %p, dpi_y %p.\n", iface
, dpi_x
, dpi_y
);
1528 ID2D1DeviceContext6_GetDpi(&effect_context
->device_context
->ID2D1DeviceContext6_iface
, dpi_x
, dpi_y
);
1531 static HRESULT STDMETHODCALLTYPE
d2d_effect_context_CreateEffect(ID2D1EffectContext
*iface
,
1532 REFCLSID clsid
, ID2D1Effect
**effect
)
1534 struct d2d_effect_context
*effect_context
= impl_from_ID2D1EffectContext(iface
);
1536 TRACE("iface %p, clsid %s, effect %p.\n", iface
, debugstr_guid(clsid
), effect
);
1538 return ID2D1DeviceContext6_CreateEffect(&effect_context
->device_context
->ID2D1DeviceContext6_iface
,
1542 static HRESULT STDMETHODCALLTYPE
d2d_effect_context_GetMaximumSupportedFeatureLevel(ID2D1EffectContext
*iface
,
1543 const D3D_FEATURE_LEVEL
*levels
, UINT32 level_count
, D3D_FEATURE_LEVEL
*max_level
)
1545 FIXME("iface %p, levels %p, level_count %u, max_level %p stub!\n", iface
, levels
, level_count
, max_level
);
1550 static HRESULT STDMETHODCALLTYPE
d2d_effect_context_CreateTransformNodeFromEffect(ID2D1EffectContext
*iface
,
1551 ID2D1Effect
*effect
, ID2D1TransformNode
**node
)
1553 FIXME("iface %p, effect %p, node %p stub!\n", iface
, effect
, node
);
1558 static HRESULT STDMETHODCALLTYPE
d2d_effect_context_CreateBlendTransform(ID2D1EffectContext
*iface
,
1559 UINT32 num_inputs
, const D2D1_BLEND_DESCRIPTION
*description
, ID2D1BlendTransform
**transform
)
1561 TRACE("iface %p, num_inputs %u, description %p, transform %p,\n", iface
, num_inputs
, description
, transform
);
1563 return d2d_blend_transform_create(num_inputs
, description
, transform
);
1566 static HRESULT STDMETHODCALLTYPE
d2d_effect_context_CreateBorderTransform(ID2D1EffectContext
*iface
,
1567 D2D1_EXTEND_MODE mode_x
, D2D1_EXTEND_MODE mode_y
, ID2D1BorderTransform
**transform
)
1569 TRACE("iface %p, mode_x %#x, mode_y %#x, transform %p.\n", iface
, mode_x
, mode_y
, transform
);
1571 return d2d_border_transform_create(mode_x
, mode_y
, transform
);
1574 static HRESULT STDMETHODCALLTYPE
d2d_effect_context_CreateOffsetTransform(ID2D1EffectContext
*iface
,
1575 D2D1_POINT_2L offset
, ID2D1OffsetTransform
**transform
)
1577 TRACE("iface %p, offset %s, transform %p.\n", iface
, debug_d2d_point_2l(&offset
), transform
);
1579 return d2d_offset_transform_create(offset
, transform
);
1582 static HRESULT STDMETHODCALLTYPE
d2d_effect_context_CreateBoundsAdjustmentTransform(ID2D1EffectContext
*iface
,
1583 const D2D1_RECT_L
*output_rect
, ID2D1BoundsAdjustmentTransform
**transform
)
1585 TRACE("iface %p, output_rect %s, transform %p.\n", iface
, debug_d2d_rect_l(output_rect
), transform
);
1587 return d2d_bounds_adjustment_transform_create(output_rect
, transform
);
1590 static HRESULT STDMETHODCALLTYPE
d2d_effect_context_LoadPixelShader(ID2D1EffectContext
*iface
,
1591 REFGUID shader_id
, const BYTE
*buffer
, UINT32 buffer_size
)
1593 struct d2d_effect_context
*effect_context
= impl_from_ID2D1EffectContext(iface
);
1594 struct d2d_device
*device
= effect_context
->device_context
->device
;
1595 ID3D11PixelShader
*shader
;
1598 TRACE("iface %p, shader_id %s, buffer %p, buffer_size %u.\n",
1599 iface
, debugstr_guid(shader_id
), buffer
, buffer_size
);
1601 if (d2d_device_get_indexed_object(&device
->shaders
, shader_id
, NULL
))
1604 if (FAILED(hr
= ID3D11Device1_CreatePixelShader(effect_context
->device_context
->d3d_device
,
1605 buffer
, buffer_size
, NULL
, &shader
)))
1607 WARN("Failed to create a pixel shader, hr %#lx.\n", hr
);
1611 hr
= d2d_device_add_indexed_object(&device
->shaders
, shader_id
, (IUnknown
*)shader
);
1612 ID3D11PixelShader_Release(shader
);
1617 static HRESULT STDMETHODCALLTYPE
d2d_effect_context_LoadVertexShader(ID2D1EffectContext
*iface
,
1618 REFGUID shader_id
, const BYTE
*buffer
, UINT32 buffer_size
)
1620 struct d2d_effect_context
*effect_context
= impl_from_ID2D1EffectContext(iface
);
1621 struct d2d_device
*device
= effect_context
->device_context
->device
;
1622 ID3D11VertexShader
*shader
;
1625 TRACE("iface %p, shader_id %s, buffer %p, buffer_size %u.\n",
1626 iface
, debugstr_guid(shader_id
), buffer
, buffer_size
);
1628 if (d2d_device_get_indexed_object(&device
->shaders
, shader_id
, NULL
))
1631 if (FAILED(hr
= ID3D11Device1_CreateVertexShader(effect_context
->device_context
->d3d_device
,
1632 buffer
, buffer_size
, NULL
, &shader
)))
1634 WARN("Failed to create vertex shader, hr %#lx.\n", hr
);
1638 hr
= d2d_device_add_indexed_object(&device
->shaders
, shader_id
, (IUnknown
*)shader
);
1639 ID3D11VertexShader_Release(shader
);
1644 static HRESULT STDMETHODCALLTYPE
d2d_effect_context_LoadComputeShader(ID2D1EffectContext
*iface
,
1645 REFGUID shader_id
, const BYTE
*buffer
, UINT32 buffer_size
)
1647 struct d2d_effect_context
*effect_context
= impl_from_ID2D1EffectContext(iface
);
1648 struct d2d_device
*device
= effect_context
->device_context
->device
;
1649 ID3D11ComputeShader
*shader
;
1652 TRACE("iface %p, shader_id %s, buffer %p, buffer_size %u.\n",
1653 iface
, debugstr_guid(shader_id
), buffer
, buffer_size
);
1655 if (d2d_device_get_indexed_object(&device
->shaders
, shader_id
, NULL
))
1658 if (FAILED(hr
= ID3D11Device1_CreateComputeShader(effect_context
->device_context
->d3d_device
,
1659 buffer
, buffer_size
, NULL
, &shader
)))
1661 WARN("Failed to create a compute shader, hr %#lx.\n", hr
);
1665 hr
= d2d_device_add_indexed_object(&device
->shaders
, shader_id
, (IUnknown
*)shader
);
1666 ID3D11ComputeShader_Release(shader
);
1671 static BOOL STDMETHODCALLTYPE
d2d_effect_context_IsShaderLoaded(ID2D1EffectContext
*iface
, REFGUID shader_id
)
1673 struct d2d_effect_context
*effect_context
= impl_from_ID2D1EffectContext(iface
);
1674 struct d2d_device
*device
= effect_context
->device_context
->device
;
1676 TRACE("iface %p, shader_id %s.\n", iface
, debugstr_guid(shader_id
));
1678 return d2d_device_get_indexed_object(&device
->shaders
, shader_id
, NULL
);
1681 static HRESULT STDMETHODCALLTYPE
d2d_effect_context_CreateResourceTexture(ID2D1EffectContext
*iface
,
1682 const GUID
*id
, const D2D1_RESOURCE_TEXTURE_PROPERTIES
*texture_properties
,
1683 const BYTE
*data
, const UINT32
*strides
, UINT32 data_size
, ID2D1ResourceTexture
**texture
)
1685 FIXME("iface %p, id %s, texture_properties %p, data %p, strides %p, data_size %u, texture %p stub!\n",
1686 iface
, debugstr_guid(id
), texture_properties
, data
, strides
, data_size
, texture
);
1691 static HRESULT STDMETHODCALLTYPE
d2d_effect_context_FindResourceTexture(ID2D1EffectContext
*iface
,
1692 const GUID
*id
, ID2D1ResourceTexture
**texture
)
1694 FIXME("iface %p, id %s, texture %p stub!\n", iface
, debugstr_guid(id
), texture
);
1699 static HRESULT STDMETHODCALLTYPE
d2d_effect_context_CreateVertexBuffer(ID2D1EffectContext
*iface
,
1700 const D2D1_VERTEX_BUFFER_PROPERTIES
*buffer_properties
, const GUID
*id
,
1701 const D2D1_CUSTOM_VERTEX_BUFFER_PROPERTIES
*custom_buffer_properties
,
1702 ID2D1VertexBuffer
**buffer
)
1704 struct d2d_effect_context
*effect_context
= impl_from_ID2D1EffectContext(iface
);
1705 struct d2d_device_context
*context
= effect_context
->device_context
;
1708 FIXME("iface %p, buffer_properties %p, id %s, custom_buffer_properties %p, buffer %p stub!\n",
1709 iface
, buffer_properties
, debugstr_guid(id
), custom_buffer_properties
, buffer
);
1711 if (id
&& d2d_device_get_indexed_object(&context
->vertex_buffers
, id
, (IUnknown
**)buffer
))
1714 if (SUCCEEDED(hr
= d2d_vertex_buffer_create(buffer
)))
1717 hr
= d2d_device_add_indexed_object(&context
->vertex_buffers
, id
, (IUnknown
*)*buffer
);
1726 static HRESULT STDMETHODCALLTYPE
d2d_effect_context_FindVertexBuffer(ID2D1EffectContext
*iface
,
1727 const GUID
*id
, ID2D1VertexBuffer
**buffer
)
1729 struct d2d_effect_context
*effect_context
= impl_from_ID2D1EffectContext(iface
);
1730 struct d2d_device_context
*context
= effect_context
->device_context
;
1732 TRACE("iface %p, id %s, buffer %p.\n", iface
, debugstr_guid(id
), buffer
);
1734 if (!d2d_device_get_indexed_object(&context
->vertex_buffers
, id
, (IUnknown
**)buffer
))
1735 return HRESULT_FROM_WIN32(ERROR_NOT_FOUND
);
1740 static HRESULT STDMETHODCALLTYPE
d2d_effect_context_CreateColorContext(ID2D1EffectContext
*iface
,
1741 D2D1_COLOR_SPACE space
, const BYTE
*profile
, UINT32 profile_size
, ID2D1ColorContext
**color_context
)
1743 struct d2d_effect_context
*effect_context
= impl_from_ID2D1EffectContext(iface
);
1745 TRACE("iface %p, space %#x, profile %p, profile_size %u, color_context %p.\n",
1746 iface
, space
, profile
, profile_size
, color_context
);
1748 return ID2D1DeviceContext6_CreateColorContext(&effect_context
->device_context
->ID2D1DeviceContext6_iface
,
1749 space
, profile
, profile_size
, color_context
);
1752 static HRESULT STDMETHODCALLTYPE
d2d_effect_context_CreateColorContextFromFilename(ID2D1EffectContext
*iface
,
1753 const WCHAR
*filename
, ID2D1ColorContext
**color_context
)
1755 struct d2d_effect_context
*effect_context
= impl_from_ID2D1EffectContext(iface
);
1757 TRACE("iface %p, filename %s, color_context %p.\n", iface
, debugstr_w(filename
), color_context
);
1759 return ID2D1DeviceContext6_CreateColorContextFromFilename(&effect_context
->device_context
->ID2D1DeviceContext6_iface
,
1760 filename
, color_context
);
1763 static HRESULT STDMETHODCALLTYPE
d2d_effect_context_CreateColorContextFromWicColorContext(ID2D1EffectContext
*iface
,
1764 IWICColorContext
*wic_color_context
, ID2D1ColorContext
**color_context
)
1766 struct d2d_effect_context
*effect_context
= impl_from_ID2D1EffectContext(iface
);
1768 TRACE("iface %p, wic_color_context %p, color_context %p.\n", iface
, wic_color_context
, color_context
);
1770 return ID2D1DeviceContext6_CreateColorContextFromWicColorContext(&effect_context
->device_context
->ID2D1DeviceContext6_iface
,
1771 wic_color_context
, color_context
);
1774 static HRESULT STDMETHODCALLTYPE
d2d_effect_context_CheckFeatureSupport(ID2D1EffectContext
*iface
,
1775 D2D1_FEATURE feature
, void *data
, UINT32 data_size
)
1777 struct d2d_effect_context
*effect_context
= impl_from_ID2D1EffectContext(iface
);
1778 D3D11_FEATURE d3d11_feature
;
1780 TRACE("iface %p, feature %#x, data %p, data_size %u.\n", iface
, feature
, data
, data_size
);
1782 /* Data structures are compatible. */
1785 case D2D1_FEATURE_DOUBLES
: d3d11_feature
= D3D11_FEATURE_DOUBLES
; break;
1786 case D2D1_FEATURE_D3D10_X_HARDWARE_OPTIONS
: d3d11_feature
= D3D11_FEATURE_D3D10_X_HARDWARE_OPTIONS
; break;
1788 WARN("Unexpected feature index %d.\n", feature
);
1789 return E_INVALIDARG
;
1792 return ID3D11Device1_CheckFeatureSupport(effect_context
->device_context
->d3d_device
,
1793 d3d11_feature
, data
, data_size
);
1796 static BOOL STDMETHODCALLTYPE
d2d_effect_context_IsBufferPrecisionSupported(ID2D1EffectContext
*iface
,
1797 D2D1_BUFFER_PRECISION precision
)
1799 struct d2d_effect_context
*effect_context
= impl_from_ID2D1EffectContext(iface
);
1801 TRACE("iface %p, precision %u.\n", iface
, precision
);
1803 return ID2D1DeviceContext6_IsBufferPrecisionSupported(&effect_context
->device_context
->ID2D1DeviceContext6_iface
,
1807 static const ID2D1EffectContextVtbl d2d_effect_context_vtbl
=
1809 d2d_effect_context_QueryInterface
,
1810 d2d_effect_context_AddRef
,
1811 d2d_effect_context_Release
,
1812 d2d_effect_context_GetDpi
,
1813 d2d_effect_context_CreateEffect
,
1814 d2d_effect_context_GetMaximumSupportedFeatureLevel
,
1815 d2d_effect_context_CreateTransformNodeFromEffect
,
1816 d2d_effect_context_CreateBlendTransform
,
1817 d2d_effect_context_CreateBorderTransform
,
1818 d2d_effect_context_CreateOffsetTransform
,
1819 d2d_effect_context_CreateBoundsAdjustmentTransform
,
1820 d2d_effect_context_LoadPixelShader
,
1821 d2d_effect_context_LoadVertexShader
,
1822 d2d_effect_context_LoadComputeShader
,
1823 d2d_effect_context_IsShaderLoaded
,
1824 d2d_effect_context_CreateResourceTexture
,
1825 d2d_effect_context_FindResourceTexture
,
1826 d2d_effect_context_CreateVertexBuffer
,
1827 d2d_effect_context_FindVertexBuffer
,
1828 d2d_effect_context_CreateColorContext
,
1829 d2d_effect_context_CreateColorContextFromFilename
,
1830 d2d_effect_context_CreateColorContextFromWicColorContext
,
1831 d2d_effect_context_CheckFeatureSupport
,
1832 d2d_effect_context_IsBufferPrecisionSupported
,
1835 void d2d_effect_context_init(struct d2d_effect_context
*effect_context
, struct d2d_device_context
*device_context
)
1837 effect_context
->ID2D1EffectContext_iface
.lpVtbl
= &d2d_effect_context_vtbl
;
1838 effect_context
->refcount
= 1;
1839 effect_context
->device_context
= device_context
;
1840 ID2D1DeviceContext6_AddRef(&device_context
->ID2D1DeviceContext6_iface
);
1843 static inline struct d2d_effect
*impl_from_ID2D1Effect(ID2D1Effect
*iface
)
1845 return CONTAINING_RECORD(iface
, struct d2d_effect
, ID2D1Effect_iface
);
1848 static void d2d_effect_cleanup(struct d2d_effect
*effect
)
1852 for (i
= 0; i
< effect
->input_count
; ++i
)
1854 if (effect
->inputs
[i
])
1855 ID2D1Image_Release(effect
->inputs
[i
]);
1857 free(effect
->inputs
);
1858 ID2D1EffectContext_Release(&effect
->effect_context
->ID2D1EffectContext_iface
);
1860 ID2D1TransformGraph_Release(&effect
->graph
->ID2D1TransformGraph_iface
);
1861 //d2d_effect_properties_cleanup(&effect->properties);
1863 ID2D1EffectImpl_Release(effect
->impl
);
1866 static HRESULT STDMETHODCALLTYPE
d2d_effect_QueryInterface(ID2D1Effect
*iface
, REFIID iid
, void **out
)
1868 struct d2d_effect
*effect
= impl_from_ID2D1Effect(iface
);
1869 TRACE("iface %p, iid %s, out %p.\n", iface
, debugstr_guid(iid
), out
);
1871 if (IsEqualGUID(iid
, &IID_ID2D1Effect
)
1872 || IsEqualGUID(iid
, &IID_ID2D1Properties
)
1873 || IsEqualGUID(iid
, &IID_IUnknown
))
1875 ID2D1Effect_AddRef(iface
);
1880 if (IsEqualGUID(iid
, &IID_ID2D1Image
)
1881 || IsEqualGUID(iid
, &IID_ID2D1Resource
))
1883 ID2D1Image_AddRef(&effect
->ID2D1Image_iface
);
1884 *out
= &effect
->ID2D1Image_iface
;
1888 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid
));
1891 return E_NOINTERFACE
;
1894 static ULONG STDMETHODCALLTYPE
d2d_effect_AddRef(ID2D1Effect
*iface
)
1896 struct d2d_effect
*effect
= impl_from_ID2D1Effect(iface
);
1897 ULONG refcount
= InterlockedIncrement(&effect
->refcount
);
1899 TRACE("%p increasing refcount to %lu.\n", iface
, refcount
);
1904 static ULONG STDMETHODCALLTYPE
d2d_effect_Release(ID2D1Effect
*iface
)
1906 struct d2d_effect
*effect
= impl_from_ID2D1Effect(iface
);
1907 ULONG refcount
= InterlockedDecrement(&effect
->refcount
);
1909 TRACE("%p decreasing refcount to %lu.\n", iface
, refcount
);
1913 d2d_effect_cleanup(effect
);
1920 static UINT32 STDMETHODCALLTYPE
d2d_effect_GetPropertyCount(ID2D1Effect
*iface
)
1922 struct d2d_effect
*effect
= impl_from_ID2D1Effect(iface
);
1924 TRACE("iface %p.\n", iface
);
1926 return ID2D1Properties_GetPropertyCount(&effect
->properties
.ID2D1Properties_iface
);
1929 static HRESULT STDMETHODCALLTYPE
d2d_effect_GetPropertyName(ID2D1Effect
*iface
, UINT32 index
,
1930 WCHAR
*name
, UINT32 name_count
)
1932 struct d2d_effect
*effect
= impl_from_ID2D1Effect(iface
);
1934 TRACE("iface %p, index %u, name %p, name_count %u.\n", iface
, index
, name
, name_count
);
1936 return ID2D1Properties_GetPropertyName(&effect
->properties
.ID2D1Properties_iface
,
1937 index
, name
, name_count
);
1940 static UINT32 STDMETHODCALLTYPE
d2d_effect_GetPropertyNameLength(ID2D1Effect
*iface
, UINT32 index
)
1942 struct d2d_effect
*effect
= impl_from_ID2D1Effect(iface
);
1944 TRACE("iface %p, index %u.\n", iface
, index
);
1946 return ID2D1Properties_GetPropertyNameLength(&effect
->properties
.ID2D1Properties_iface
, index
);
1949 static D2D1_PROPERTY_TYPE STDMETHODCALLTYPE
d2d_effect_GetType(ID2D1Effect
*iface
, UINT32 index
)
1951 struct d2d_effect
*effect
= impl_from_ID2D1Effect(iface
);
1953 TRACE("iface %p, index %#x.\n", iface
, index
);
1955 return ID2D1Properties_GetType(&effect
->properties
.ID2D1Properties_iface
, index
);
1958 static UINT32 STDMETHODCALLTYPE
d2d_effect_GetPropertyIndex(ID2D1Effect
*iface
, const WCHAR
*name
)
1960 struct d2d_effect
*effect
= impl_from_ID2D1Effect(iface
);
1962 TRACE("iface %p, name %s.\n", iface
, debugstr_w(name
));
1964 return ID2D1Properties_GetPropertyIndex(&effect
->properties
.ID2D1Properties_iface
, name
);
1967 static HRESULT STDMETHODCALLTYPE
d2d_effect_SetValueByName(ID2D1Effect
*iface
, const WCHAR
*name
,
1968 D2D1_PROPERTY_TYPE type
, const BYTE
*value
, UINT32 value_size
)
1970 struct d2d_effect
*effect
= impl_from_ID2D1Effect(iface
);
1972 TRACE("iface %p, name %s, type %u, value %p, value_size %u.\n", iface
, debugstr_w(name
),
1973 type
, value
, value_size
);
1975 return ID2D1Properties_SetValueByName(&effect
->properties
.ID2D1Properties_iface
, name
,
1976 type
, value
, value_size
);
1979 static HRESULT STDMETHODCALLTYPE
d2d_effect_SetValue(ID2D1Effect
*iface
, UINT32 index
, D2D1_PROPERTY_TYPE type
,
1980 const BYTE
*value
, UINT32 value_size
)
1982 struct d2d_effect
*effect
= impl_from_ID2D1Effect(iface
);
1984 TRACE("iface %p, index %#x, type %u, value %p, value_size %u.\n", iface
, index
, type
, value
, value_size
);
1986 return ID2D1Properties_SetValue(&effect
->properties
.ID2D1Properties_iface
, index
, type
,
1990 static HRESULT STDMETHODCALLTYPE
d2d_effect_GetValueByName(ID2D1Effect
*iface
, const WCHAR
*name
,
1991 D2D1_PROPERTY_TYPE type
, BYTE
*value
, UINT32 value_size
)
1993 struct d2d_effect
*effect
= impl_from_ID2D1Effect(iface
);
1995 TRACE("iface %p, name %s, type %#x, value %p, value_size %u.\n", iface
, debugstr_w(name
), type
,
1998 return ID2D1Properties_GetValueByName(&effect
->properties
.ID2D1Properties_iface
, name
, type
,
2002 static HRESULT
d2d_effect_get_value(struct d2d_effect
*effect
, UINT32 index
, D2D1_PROPERTY_TYPE type
,
2003 BYTE
*value
, UINT32 value_size
)
2005 return ID2D1Properties_GetValue(&effect
->properties
.ID2D1Properties_iface
, index
, type
, value
, value_size
);
2008 static HRESULT STDMETHODCALLTYPE
d2d_effect_GetValue(ID2D1Effect
*iface
, UINT32 index
, D2D1_PROPERTY_TYPE type
,
2009 BYTE
*value
, UINT32 value_size
)
2011 struct d2d_effect
*effect
= impl_from_ID2D1Effect(iface
);
2013 TRACE("iface %p, index %#x, type %u, value %p, value_size %u.\n", iface
, index
, type
, value
, value_size
);
2015 return d2d_effect_get_value(effect
, index
, type
, value
, value_size
);
2018 static UINT32 STDMETHODCALLTYPE
d2d_effect_GetValueSize(ID2D1Effect
*iface
, UINT32 index
)
2020 struct d2d_effect
*effect
= impl_from_ID2D1Effect(iface
);
2022 TRACE("iface %p, index %#x.\n", iface
, index
);
2024 return ID2D1Properties_GetValueSize(&effect
->properties
.ID2D1Properties_iface
, index
);
2027 static HRESULT STDMETHODCALLTYPE
d2d_effect_GetSubProperties(ID2D1Effect
*iface
, UINT32 index
,
2028 ID2D1Properties
**props
)
2030 struct d2d_effect
*effect
= impl_from_ID2D1Effect(iface
);
2032 TRACE("iface %p, index %u, props %p.\n", iface
, index
, props
);
2034 return ID2D1Properties_GetSubProperties(&effect
->properties
.ID2D1Properties_iface
, index
, props
);
2037 static void STDMETHODCALLTYPE
d2d_effect_SetInput(ID2D1Effect
*iface
, UINT32 index
, ID2D1Image
*input
, BOOL invalidate
)
2039 struct d2d_effect
*effect
= impl_from_ID2D1Effect(iface
);
2041 TRACE("iface %p, index %u, input %p, invalidate %#x.\n", iface
, index
, input
, invalidate
);
2043 if (index
>= effect
->input_count
)
2046 ID2D1Image_AddRef(input
);
2047 if (effect
->inputs
[index
])
2048 ID2D1Image_Release(effect
->inputs
[index
]);
2049 effect
->inputs
[index
] = input
;
2052 static HRESULT
d2d_effect_set_input_count(struct d2d_effect
*effect
, UINT32 count
)
2054 bool initialized
= effect
->inputs
!= NULL
;
2058 if (count
== effect
->input_count
)
2061 if (count
< effect
->input_count
)
2063 for (i
= count
; i
< effect
->input_count
; ++i
)
2065 if (effect
->inputs
[i
])
2066 ID2D1Image_Release(effect
->inputs
[i
]);
2071 if (!d2d_array_reserve((void **)&effect
->inputs
, &effect
->inputs_size
,
2072 count
, sizeof(*effect
->inputs
)))
2074 ERR("Failed to resize inputs array.\n");
2075 return E_OUTOFMEMORY
;
2078 memset(&effect
->inputs
[effect
->input_count
], 0, sizeof(*effect
->inputs
) * (count
- effect
->input_count
));
2080 effect
->input_count
= count
;
2084 ID2D1TransformGraph_Release(&effect
->graph
->ID2D1TransformGraph_iface
);
2085 effect
->graph
= NULL
;
2087 if (SUCCEEDED(hr
= d2d_transform_graph_create(count
, &effect
->graph
)))
2089 if (FAILED(hr
= ID2D1EffectImpl_SetGraph(effect
->impl
, &effect
->graph
->ID2D1TransformGraph_iface
)))
2090 WARN("Failed to set a new transform graph, hr %#lx.\n", hr
);
2097 static HRESULT STDMETHODCALLTYPE
d2d_effect_SetInputCount(ID2D1Effect
*iface
, UINT32 count
)
2099 struct d2d_effect
*effect
= impl_from_ID2D1Effect(iface
);
2100 unsigned int min_inputs
, max_inputs
;
2102 TRACE("iface %p, count %u.\n", iface
, count
);
2104 d2d_effect_get_value(effect
, D2D1_PROPERTY_MIN_INPUTS
, D2D1_PROPERTY_TYPE_UINT32
,
2105 (BYTE
*)&min_inputs
, sizeof(min_inputs
));
2106 d2d_effect_get_value(effect
, D2D1_PROPERTY_MAX_INPUTS
, D2D1_PROPERTY_TYPE_UINT32
,
2107 (BYTE
*)&max_inputs
, sizeof(max_inputs
));
2109 if (count
< min_inputs
|| count
> max_inputs
)
2110 return E_INVALIDARG
;
2112 return d2d_effect_set_input_count(effect
, count
);
2115 static void STDMETHODCALLTYPE
d2d_effect_GetInput(ID2D1Effect
*iface
, UINT32 index
, ID2D1Image
**input
)
2117 struct d2d_effect
*effect
= impl_from_ID2D1Effect(iface
);
2119 TRACE("iface %p, index %u, input %p.\n", iface
, index
, input
);
2121 if (index
< effect
->input_count
&& effect
->inputs
[index
])
2122 ID2D1Image_AddRef(*input
= effect
->inputs
[index
]);
2127 static UINT32 STDMETHODCALLTYPE
d2d_effect_GetInputCount(ID2D1Effect
*iface
)
2129 struct d2d_effect
*effect
= impl_from_ID2D1Effect(iface
);
2131 TRACE("iface %p.\n", iface
);
2133 return effect
->input_count
;
2136 static void STDMETHODCALLTYPE
d2d_effect_GetOutput(ID2D1Effect
*iface
, ID2D1Image
**output
)
2138 struct d2d_effect
*effect
= impl_from_ID2D1Effect(iface
);
2140 TRACE("iface %p, output %p.\n", iface
, output
);
2142 ID2D1Image_AddRef(*output
= &effect
->ID2D1Image_iface
);
2145 static const ID2D1EffectVtbl d2d_effect_vtbl
=
2147 d2d_effect_QueryInterface
,
2150 d2d_effect_GetPropertyCount
,
2151 d2d_effect_GetPropertyName
,
2152 d2d_effect_GetPropertyNameLength
,
2154 d2d_effect_GetPropertyIndex
,
2155 d2d_effect_SetValueByName
,
2156 d2d_effect_SetValue
,
2157 d2d_effect_GetValueByName
,
2158 d2d_effect_GetValue
,
2159 d2d_effect_GetValueSize
,
2160 d2d_effect_GetSubProperties
,
2161 d2d_effect_SetInput
,
2162 d2d_effect_SetInputCount
,
2163 d2d_effect_GetInput
,
2164 d2d_effect_GetInputCount
,
2165 d2d_effect_GetOutput
,
2168 static inline struct d2d_effect
*impl_from_ID2D1Image(ID2D1Image
*iface
)
2170 return CONTAINING_RECORD(iface
, struct d2d_effect
, ID2D1Image_iface
);
2173 static HRESULT STDMETHODCALLTYPE
d2d_effect_image_QueryInterface(ID2D1Image
*iface
, REFIID iid
, void **out
)
2175 struct d2d_effect
*effect
= impl_from_ID2D1Image(iface
);
2177 TRACE("iface %p, iid %s, out %p.\n", iface
, debugstr_guid(iid
), out
);
2179 return d2d_effect_QueryInterface(&effect
->ID2D1Effect_iface
, iid
, out
);
2182 static ULONG STDMETHODCALLTYPE
d2d_effect_image_AddRef(ID2D1Image
*iface
)
2184 struct d2d_effect
*effect
= impl_from_ID2D1Image(iface
);
2186 TRACE("iface %p.\n", iface
);
2188 return d2d_effect_AddRef(&effect
->ID2D1Effect_iface
);
2191 static ULONG STDMETHODCALLTYPE
d2d_effect_image_Release(ID2D1Image
*iface
)
2193 struct d2d_effect
*effect
= impl_from_ID2D1Image(iface
);
2195 TRACE("iface %p.\n", iface
);
2197 return d2d_effect_Release(&effect
->ID2D1Effect_iface
);
2200 static void STDMETHODCALLTYPE
d2d_effect_image_GetFactory(ID2D1Image
*iface
, ID2D1Factory
**factory
)
2202 struct d2d_effect
*effect
= impl_from_ID2D1Image(iface
);
2204 TRACE("iface %p, factory %p.\n", iface
, factory
);
2206 ID2D1Factory_AddRef(*factory
= effect
->effect_context
->device_context
->factory
);
2209 static const ID2D1ImageVtbl d2d_effect_image_vtbl
=
2211 d2d_effect_image_QueryInterface
,
2212 d2d_effect_image_AddRef
,
2213 d2d_effect_image_Release
,
2214 d2d_effect_image_GetFactory
,
2217 static inline struct d2d_effect_properties
*impl_from_ID2D1Properties(ID2D1Properties
*iface
)
2219 return CONTAINING_RECORD(iface
, struct d2d_effect_properties
, ID2D1Properties_iface
);
2222 static HRESULT STDMETHODCALLTYPE
d2d_effect_properties_QueryInterface(ID2D1Properties
*iface
,
2223 REFIID riid
, void **obj
)
2225 if (IsEqualGUID(riid
, &IID_ID2D1Properties
) ||
2226 IsEqualGUID(riid
, &IID_IUnknown
))
2229 ID2D1Properties_AddRef(iface
);
2234 return E_NOINTERFACE
;
2237 static ULONG STDMETHODCALLTYPE
d2d_effect_properties_AddRef(ID2D1Properties
*iface
)
2239 struct d2d_effect_properties
*properties
= impl_from_ID2D1Properties(iface
);
2241 if (properties
->effect
)
2242 return ID2D1Effect_AddRef(&properties
->effect
->ID2D1Effect_iface
);
2244 return InterlockedIncrement(&properties
->refcount
);
2247 static ULONG STDMETHODCALLTYPE
d2d_effect_properties_Release(ID2D1Properties
*iface
)
2249 struct d2d_effect_properties
*properties
= impl_from_ID2D1Properties(iface
);
2252 if (properties
->effect
)
2253 return ID2D1Effect_Release(&properties
->effect
->ID2D1Effect_iface
);
2255 refcount
= InterlockedDecrement(&properties
->refcount
);
2259 d2d_effect_properties_cleanup(properties
);
2266 static UINT32 STDMETHODCALLTYPE
d2d_effect_properties_GetPropertyCount(ID2D1Properties
*iface
)
2268 struct d2d_effect_properties
*properties
= impl_from_ID2D1Properties(iface
);
2270 TRACE("iface %p.\n", iface
);
2272 return properties
->custom_count
;
2275 static HRESULT STDMETHODCALLTYPE
d2d_effect_properties_GetPropertyName(ID2D1Properties
*iface
,
2276 UINT32 index
, WCHAR
*name
, UINT32 name_count
)
2278 struct d2d_effect_properties
*properties
= impl_from_ID2D1Properties(iface
);
2279 struct d2d_effect_property
*prop
;
2281 TRACE("iface %p, index %u, name %p, name_count %u.\n", iface
, index
, name
, name_count
);
2283 if (!(prop
= d2d_effect_properties_get_property_by_index(properties
, index
)))
2284 return D2DERR_INVALID_PROPERTY
;
2286 return d2d_effect_return_string(prop
->name
, name
, name_count
);
2289 static UINT32 STDMETHODCALLTYPE
d2d_effect_properties_GetPropertyNameLength(ID2D1Properties
*iface
,
2292 struct d2d_effect_properties
*properties
= impl_from_ID2D1Properties(iface
);
2293 struct d2d_effect_property
*prop
;
2295 TRACE("iface %p, index %u.\n", iface
, index
);
2297 if (!(prop
= d2d_effect_properties_get_property_by_index(properties
, index
)))
2298 return D2DERR_INVALID_PROPERTY
;
2300 return wcslen(prop
->name
);
2303 static D2D1_PROPERTY_TYPE STDMETHODCALLTYPE
d2d_effect_properties_GetType(ID2D1Properties
*iface
,
2306 struct d2d_effect_properties
*properties
= impl_from_ID2D1Properties(iface
);
2307 struct d2d_effect_property
*prop
;
2309 TRACE("iface %p, index %#x.\n", iface
, index
);
2311 if (!(prop
= d2d_effect_properties_get_property_by_index(properties
, index
)))
2312 return D2D1_PROPERTY_TYPE_UNKNOWN
;
2317 static UINT32 STDMETHODCALLTYPE
d2d_effect_properties_GetPropertyIndex(ID2D1Properties
*iface
,
2320 struct d2d_effect_properties
*properties
= impl_from_ID2D1Properties(iface
);
2321 struct d2d_effect_property
*prop
;
2323 TRACE("iface %p, name %s.\n", iface
, debugstr_w(name
));
2325 if (!(prop
= d2d_effect_properties_get_property_by_name(properties
, name
)))
2326 return D2D1_INVALID_PROPERTY_INDEX
;
2331 static HRESULT STDMETHODCALLTYPE
d2d_effect_properties_SetValueByName(ID2D1Properties
*iface
,
2332 const WCHAR
*name
, D2D1_PROPERTY_TYPE type
, const BYTE
*value
, UINT32 value_size
)
2334 struct d2d_effect_properties
*properties
= impl_from_ID2D1Properties(iface
);
2335 struct d2d_effect_property
*prop
;
2337 TRACE("iface %p, name %s, type %u, value %p, value_size %u.\n", iface
, debugstr_w(name
),
2338 type
, value
, value_size
);
2340 if (!(prop
= d2d_effect_properties_get_property_by_name(properties
, name
)))
2341 return D2DERR_INVALID_PROPERTY
;
2343 return d2d_effect_property_set_value(properties
, prop
, type
, value
, value_size
);
2346 static HRESULT STDMETHODCALLTYPE
d2d_effect_properties_SetValue(ID2D1Properties
*iface
,
2347 UINT32 index
, D2D1_PROPERTY_TYPE type
, const BYTE
*value
, UINT32 value_size
)
2349 struct d2d_effect_properties
*properties
= impl_from_ID2D1Properties(iface
);
2350 struct d2d_effect_property
*prop
;
2352 TRACE("iface %p, index %#x, type %u, value %p, value_size %u.\n", iface
, index
, type
, value
, value_size
);
2354 if (!(prop
= d2d_effect_properties_get_property_by_index(properties
, index
)))
2355 return D2DERR_INVALID_PROPERTY
;
2357 return d2d_effect_property_set_value(properties
, prop
, type
, value
, value_size
);
2360 static HRESULT STDMETHODCALLTYPE
d2d_effect_properties_GetValueByName(ID2D1Properties
*iface
,
2361 const WCHAR
*name
, D2D1_PROPERTY_TYPE type
, BYTE
*value
, UINT32 value_size
)
2363 struct d2d_effect_properties
*properties
= impl_from_ID2D1Properties(iface
);
2364 struct d2d_effect_property
*prop
;
2366 TRACE("iface %p, name %s, type %#x, value %p, value_size %u.\n", iface
, debugstr_w(name
), type
,
2369 if (!(prop
= d2d_effect_properties_get_property_by_name(properties
, name
)))
2370 return D2DERR_INVALID_PROPERTY
;
2372 return d2d_effect_property_get_value(properties
, prop
, type
, value
, value_size
);
2375 static HRESULT STDMETHODCALLTYPE
d2d_effect_properties_GetValue(ID2D1Properties
*iface
,
2376 UINT32 index
, D2D1_PROPERTY_TYPE type
, BYTE
*value
, UINT32 value_size
)
2378 struct d2d_effect_properties
*properties
= impl_from_ID2D1Properties(iface
);
2379 struct d2d_effect_property
*prop
;
2381 TRACE("iface %p, index %#x, type %u, value %p, value_size %u.\n", iface
, index
, type
, value
, value_size
);
2383 if (!(prop
= d2d_effect_properties_get_property_by_index(properties
, index
)))
2384 return D2DERR_INVALID_PROPERTY
;
2386 return d2d_effect_property_get_value(properties
, prop
, type
, value
, value_size
);
2389 static UINT32 STDMETHODCALLTYPE
d2d_effect_properties_GetValueSize(ID2D1Properties
*iface
,
2392 struct d2d_effect_properties
*properties
= impl_from_ID2D1Properties(iface
);
2394 TRACE("iface %p, index %#x.\n", iface
, index
);
2396 return d2d_effect_properties_get_value_size(properties
, index
);
2399 static HRESULT STDMETHODCALLTYPE
d2d_effect_properties_GetSubProperties(ID2D1Properties
*iface
,
2400 UINT32 index
, ID2D1Properties
**props
)
2402 struct d2d_effect_properties
*properties
= impl_from_ID2D1Properties(iface
);
2403 struct d2d_effect_property
*prop
;
2405 TRACE("iface %p, index %u, props %p.\n", iface
, index
, props
);
2407 if (!(prop
= d2d_effect_properties_get_property_by_index(properties
, index
)))
2408 return D2DERR_INVALID_PROPERTY
;
2410 if (!prop
->subproperties
) return D2DERR_NO_SUBPROPERTIES
;
2412 *props
= &prop
->subproperties
->ID2D1Properties_iface
;
2413 ID2D1Properties_AddRef(*props
);
2417 static const ID2D1PropertiesVtbl d2d_effect_properties_vtbl
=
2419 d2d_effect_properties_QueryInterface
,
2420 d2d_effect_properties_AddRef
,
2421 d2d_effect_properties_Release
,
2422 d2d_effect_properties_GetPropertyCount
,
2423 d2d_effect_properties_GetPropertyName
,
2424 d2d_effect_properties_GetPropertyNameLength
,
2425 d2d_effect_properties_GetType
,
2426 d2d_effect_properties_GetPropertyIndex
,
2427 d2d_effect_properties_SetValueByName
,
2428 d2d_effect_properties_SetValue
,
2429 d2d_effect_properties_GetValueByName
,
2430 d2d_effect_properties_GetValue
,
2431 d2d_effect_properties_GetValueSize
,
2432 d2d_effect_properties_GetSubProperties
,
2435 void d2d_effect_init_properties(struct d2d_effect
*effect
,
2436 struct d2d_effect_properties
*properties
)
2438 properties
->ID2D1Properties_iface
.lpVtbl
= &d2d_effect_properties_vtbl
;
2439 properties
->effect
= effect
;
2440 properties
->refcount
= 1;
2443 static struct d2d_render_info
*impl_from_ID2D1DrawInfo(ID2D1DrawInfo
*iface
)
2445 return CONTAINING_RECORD(iface
, struct d2d_render_info
, ID2D1DrawInfo_iface
);
2448 static HRESULT STDMETHODCALLTYPE
d2d_draw_info_QueryInterface(ID2D1DrawInfo
*iface
, REFIID iid
,
2451 TRACE("iface %p, iid %s, obj %p.\n", iface
, debugstr_guid(iid
), obj
);
2453 if (IsEqualGUID(iid
, &IID_ID2D1DrawInfo
)
2454 || IsEqualGUID(iid
, &IID_ID2D1RenderInfo
)
2455 || IsEqualGUID(iid
, &IID_IUnknown
))
2458 ID2D1DrawInfo_AddRef(iface
);
2462 WARN("Unsupported interface %s.\n", debugstr_guid(iid
));
2466 return E_NOINTERFACE
;
2469 static ULONG STDMETHODCALLTYPE
d2d_draw_info_AddRef(ID2D1DrawInfo
*iface
)
2471 struct d2d_render_info
*render_info
= impl_from_ID2D1DrawInfo(iface
);
2472 ULONG refcount
= InterlockedIncrement(&render_info
->refcount
);
2474 TRACE("iface %p refcount %lu.\n", iface
, refcount
);
2479 static ULONG STDMETHODCALLTYPE
d2d_draw_info_Release(ID2D1DrawInfo
*iface
)
2481 struct d2d_render_info
*render_info
= impl_from_ID2D1DrawInfo(iface
);
2482 ULONG refcount
= InterlockedDecrement(&render_info
->refcount
);
2484 TRACE("iface %p refcount %lu.\n", iface
, refcount
);
2492 static HRESULT STDMETHODCALLTYPE
d2d_draw_info_SetInputDescription(ID2D1DrawInfo
*iface
,
2493 UINT32 index
, D2D1_INPUT_DESCRIPTION description
)
2495 FIXME("iface %p, index %u stub.\n", iface
, index
);
2500 static HRESULT STDMETHODCALLTYPE
d2d_draw_info_SetOutputBuffer(ID2D1DrawInfo
*iface
,
2501 D2D1_BUFFER_PRECISION precision
, D2D1_CHANNEL_DEPTH depth
)
2503 FIXME("iface %p, precision %u, depth %u stub.\n", iface
, precision
, depth
);
2508 static void STDMETHODCALLTYPE
d2d_draw_info_SetCached(ID2D1DrawInfo
*iface
, BOOL is_cached
)
2510 FIXME("iface %p, is_cached %d stub.\n", iface
, is_cached
);
2513 static void STDMETHODCALLTYPE
d2d_draw_info_SetInstructionCountHint(ID2D1DrawInfo
*iface
,
2516 FIXME("iface %p, count %u stub.\n", iface
, count
);
2519 static HRESULT STDMETHODCALLTYPE
d2d_draw_info_SetPixelShaderConstantBuffer(ID2D1DrawInfo
*iface
,
2520 const BYTE
*buffer
, UINT32 size
)
2522 FIXME("iface %p, buffer %p, size %u stub.\n", iface
, buffer
, size
);
2527 static HRESULT STDMETHODCALLTYPE
d2d_draw_info_SetResourceTexture(ID2D1DrawInfo
*iface
,
2528 UINT32 index
, ID2D1ResourceTexture
*texture
)
2530 FIXME("iface %p, index %u, texture %p stub.\n", iface
, index
, texture
);
2535 static HRESULT STDMETHODCALLTYPE
d2d_draw_info_SetVertexShaderConstantBuffer(ID2D1DrawInfo
*iface
,
2536 const BYTE
*buffer
, UINT32 size
)
2538 FIXME("iface %p, buffer %p, size %u stub.\n", iface
, buffer
, size
);
2543 static HRESULT STDMETHODCALLTYPE
d2d_draw_info_SetPixelShader(ID2D1DrawInfo
*iface
,
2544 REFGUID id
, D2D1_PIXEL_OPTIONS options
)
2546 struct d2d_render_info
*render_info
= impl_from_ID2D1DrawInfo(iface
);
2548 TRACE("iface %p, id %s, options %u.\n", iface
, debugstr_guid(id
), options
);
2550 render_info
->mask
|= D2D_RENDER_INFO_PIXEL_SHADER
;
2551 render_info
->pixel_shader
= *id
;
2555 static HRESULT STDMETHODCALLTYPE
d2d_draw_info_SetVertexProcessing(ID2D1DrawInfo
*iface
,
2556 ID2D1VertexBuffer
*buffer
, D2D1_VERTEX_OPTIONS options
,
2557 const D2D1_BLEND_DESCRIPTION
*description
, const D2D1_VERTEX_RANGE
*range
,
2560 FIXME("iface %p, buffer %p, options %#x, description %p, range %p, shader %s stub.\n",
2561 iface
, buffer
, options
, description
, range
, debugstr_guid(shader
));
2566 static const ID2D1DrawInfoVtbl d2d_draw_info_vtbl
=
2568 d2d_draw_info_QueryInterface
,
2569 d2d_draw_info_AddRef
,
2570 d2d_draw_info_Release
,
2571 d2d_draw_info_SetInputDescription
,
2572 d2d_draw_info_SetOutputBuffer
,
2573 d2d_draw_info_SetCached
,
2574 d2d_draw_info_SetInstructionCountHint
,
2575 d2d_draw_info_SetPixelShaderConstantBuffer
,
2576 d2d_draw_info_SetResourceTexture
,
2577 d2d_draw_info_SetVertexShaderConstantBuffer
,
2578 d2d_draw_info_SetPixelShader
,
2579 d2d_draw_info_SetVertexProcessing
,
2582 static HRESULT
d2d_effect_render_info_create(struct d2d_render_info
**obj
)
2584 struct d2d_render_info
*object
;
2586 if (!(object
= calloc(1, sizeof(*object
))))
2587 return E_OUTOFMEMORY
;
2589 object
->ID2D1DrawInfo_iface
.lpVtbl
= &d2d_draw_info_vtbl
;
2590 object
->refcount
= 1;
2597 static bool d2d_transform_node_needs_render_info(const struct d2d_transform_node
*node
)
2599 static const GUID
*iids
[] =
2601 &IID_ID2D1SourceTransform
,
2602 &IID_ID2D1ComputeTransform
,
2603 &IID_ID2D1DrawTransform
,
2608 for (i
= 0; i
< ARRAY_SIZE(iids
); ++i
)
2610 if (SUCCEEDED(ID2D1TransformNode_QueryInterface(node
->object
, iids
[i
], (void **)&obj
)))
2612 IUnknown_Release(obj
);
2620 static HRESULT
d2d_effect_transform_graph_initialize_nodes(struct d2d_transform_graph
*graph
)
2622 ID2D1DrawTransform
*draw_transform
;
2623 struct d2d_transform_node
*node
;
2626 LIST_FOR_EACH_ENTRY(node
, &graph
->nodes
, struct d2d_transform_node
, entry
)
2628 if (d2d_transform_node_needs_render_info(node
))
2630 if (FAILED(hr
= d2d_effect_render_info_create(&node
->render_info
)))
2634 if (SUCCEEDED(ID2D1TransformNode_QueryInterface(node
->object
, &IID_ID2D1DrawTransform
,
2635 (void **)&draw_transform
)))
2637 hr
= ID2D1DrawTransform_SetDrawInfo(draw_transform
, &node
->render_info
->ID2D1DrawInfo_iface
);
2638 ID2D1DrawTransform_Release(draw_transform
);
2641 WARN("Failed to set draw info, hr %#lx.\n", hr
);
2647 FIXME("Unsupported node %p.\n", node
);
2655 HRESULT
d2d_effect_create(struct d2d_device_context
*context
, const CLSID
*effect_id
,
2656 ID2D1Effect
**effect
)
2658 struct d2d_effect_context
*effect_context
;
2659 const struct d2d_effect_registration
*reg
;
2660 struct d2d_effect
*object
;
2665 if (!(reg
= d2d_factory_get_registered_effect(context
->factory
, effect_id
)))
2667 WARN("Effect id %s not found.\n", wine_dbgstr_guid(effect_id
));
2668 return D2DERR_EFFECT_IS_NOT_REGISTERED
;
2671 if (!(effect_context
= calloc(1, sizeof(*effect_context
))))
2672 return E_OUTOFMEMORY
;
2673 d2d_effect_context_init(effect_context
, context
);
2675 if (!(object
= calloc(1, sizeof(*object
))))
2677 ID2D1EffectContext_Release(&effect_context
->ID2D1EffectContext_iface
);
2678 return E_OUTOFMEMORY
;
2681 object
->ID2D1Effect_iface
.lpVtbl
= &d2d_effect_vtbl
;
2682 object
->ID2D1Image_iface
.lpVtbl
= &d2d_effect_image_vtbl
;
2683 object
->refcount
= 1;
2684 object
->effect_context
= effect_context
;
2686 /* Create properties */
2687 d2d_effect_duplicate_properties(object
, &object
->properties
, reg
->properties
);
2689 StringFromGUID2(effect_id
, clsidW
, ARRAY_SIZE(clsidW
));
2690 d2d_effect_properties_add(&object
->properties
, L
"CLSID", D2D1_PROPERTY_CLSID
, D2D1_PROPERTY_TYPE_CLSID
, clsidW
);
2691 d2d_effect_properties_add(&object
->properties
, L
"Cached", D2D1_PROPERTY_CACHED
, D2D1_PROPERTY_TYPE_BOOL
, L
"false");
2692 d2d_effect_properties_add(&object
->properties
, L
"Precision", D2D1_PROPERTY_PRECISION
, D2D1_PROPERTY_TYPE_ENUM
, L
"0");
2694 /* Sync instance input count with default input count from the description. */
2695 d2d_effect_get_value(object
, D2D1_PROPERTY_INPUTS
, D2D1_PROPERTY_TYPE_ARRAY
, (BYTE
*)&input_count
, sizeof(input_count
));
2696 d2d_effect_set_input_count(object
, input_count
);
2698 if (FAILED(hr
= d2d_transform_graph_create(input_count
, &object
->graph
)))
2700 ID2D1EffectContext_Release(&effect_context
->ID2D1EffectContext_iface
);
2704 if (FAILED(hr
= reg
->factory((IUnknown
**)&object
->impl
)))
2706 WARN("Failed to create implementation object, hr %#lx.\n", hr
);
2707 ID2D1Effect_Release(&object
->ID2D1Effect_iface
);
2711 if (FAILED(hr
= ID2D1EffectImpl_Initialize(object
->impl
, &effect_context
->ID2D1EffectContext_iface
,
2712 &object
->graph
->ID2D1TransformGraph_iface
)))
2714 WARN("Failed to initialize effect, hr %#lx.\n", hr
);
2715 ID2D1Effect_Release(&object
->ID2D1Effect_iface
);
2719 if (FAILED(hr
= d2d_effect_transform_graph_initialize_nodes(object
->graph
)))
2721 WARN("Failed to initialize graph nodes, hr %#lx.\n", hr
);
2722 ID2D1Effect_Release(&object
->ID2D1Effect_iface
);
2726 *effect
= &object
->ID2D1Effect_iface
;
2728 TRACE("Created effect %p.\n", *effect
);