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 HRESULT STDMETHODCALLTYPE
d2d_offset_transform_QueryInterface(ID2D1OffsetTransform
*iface
,
34 REFIID iid
, void **out
)
36 TRACE("iface %p, iid %s, out %p.\n", iface
, debugstr_guid(iid
), out
);
38 if (IsEqualGUID(iid
, &IID_ID2D1OffsetTransform
)
39 || IsEqualGUID(iid
, &IID_ID2D1TransformNode
)
40 || IsEqualGUID(iid
, &IID_IUnknown
))
43 ID2D1OffsetTransform_AddRef(iface
);
47 WARN("Unsupported interface %s.\n", debugstr_guid(iid
));
52 static ULONG STDMETHODCALLTYPE
d2d_offset_transform_AddRef(ID2D1OffsetTransform
*iface
)
54 struct d2d_transform
*transform
= impl_from_ID2D1OffsetTransform(iface
);
55 ULONG refcount
= InterlockedIncrement(&transform
->refcount
);
57 TRACE("%p increasing refcount to %lu.\n", iface
, refcount
);
62 static ULONG STDMETHODCALLTYPE
d2d_offset_transform_Release(ID2D1OffsetTransform
*iface
)
64 struct d2d_transform
*transform
= impl_from_ID2D1OffsetTransform(iface
);
65 ULONG refcount
= InterlockedDecrement(&transform
->refcount
);
67 TRACE("%p decreasing refcount to %lu.\n", iface
, refcount
);
75 static UINT32 STDMETHODCALLTYPE
d2d_offset_transform_GetInputCount(ID2D1OffsetTransform
*iface
)
77 TRACE("iface %p.\n", iface
);
82 static void STDMETHODCALLTYPE
d2d_offset_transform_SetOffset(ID2D1OffsetTransform
*iface
,
85 struct d2d_transform
*transform
= impl_from_ID2D1OffsetTransform(iface
);
87 TRACE("iface %p, offset %s.\n", iface
, debug_d2d_point_2l(&offset
));
89 transform
->offset
= offset
;
92 static D2D1_POINT_2L
* STDMETHODCALLTYPE
d2d_offset_transform_GetOffset(ID2D1OffsetTransform
*iface
,
93 D2D1_POINT_2L
*offset
)
95 struct d2d_transform
*transform
= impl_from_ID2D1OffsetTransform(iface
);
97 TRACE("iface %p.\n", iface
);
99 *offset
= transform
->offset
;
103 static const ID2D1OffsetTransformVtbl d2d_offset_transform_vtbl
=
105 d2d_offset_transform_QueryInterface
,
106 d2d_offset_transform_AddRef
,
107 d2d_offset_transform_Release
,
108 d2d_offset_transform_GetInputCount
,
109 d2d_offset_transform_SetOffset
,
110 d2d_offset_transform_GetOffset
,
113 static HRESULT
d2d_offset_transform_create(D2D1_POINT_2L offset
, ID2D1OffsetTransform
**transform
)
115 struct d2d_transform
*object
;
117 if (!(object
= calloc(1, sizeof(*object
))))
118 return E_OUTOFMEMORY
;
120 object
->ID2D1TransformNode_iface
.lpVtbl
= (ID2D1TransformNodeVtbl
*)&d2d_offset_transform_vtbl
;
121 object
->refcount
= 1;
122 object
->offset
= offset
;
124 *transform
= (ID2D1OffsetTransform
*)&object
->ID2D1TransformNode_iface
;
129 static HRESULT STDMETHODCALLTYPE
d2d_blend_transform_QueryInterface(ID2D1BlendTransform
*iface
,
130 REFIID iid
, void **out
)
132 TRACE("iface %p, iid %s, out %p.\n", iface
, debugstr_guid(iid
), out
);
134 if (IsEqualGUID(iid
, &IID_ID2D1BlendTransform
)
135 || IsEqualGUID(iid
, &IID_ID2D1ConcreteTransform
)
136 || IsEqualGUID(iid
, &IID_ID2D1TransformNode
)
137 || IsEqualGUID(iid
, &IID_IUnknown
))
140 ID2D1BlendTransform_AddRef(iface
);
144 WARN("Unsupported interface %s.\n", debugstr_guid(iid
));
146 return E_NOINTERFACE
;
149 static ULONG STDMETHODCALLTYPE
d2d_blend_transform_AddRef(ID2D1BlendTransform
*iface
)
151 struct d2d_transform
*transform
= impl_from_ID2D1BlendTransform(iface
);
152 ULONG refcount
= InterlockedIncrement(&transform
->refcount
);
154 TRACE("%p increasing refcount to %lu.\n", iface
, refcount
);
159 static ULONG STDMETHODCALLTYPE
d2d_blend_transform_Release(ID2D1BlendTransform
*iface
)
161 struct d2d_transform
*transform
= impl_from_ID2D1BlendTransform(iface
);
162 ULONG refcount
= InterlockedDecrement(&transform
->refcount
);
164 TRACE("%p decreasing refcount to %lu.\n", iface
, refcount
);
172 static UINT32 STDMETHODCALLTYPE
d2d_blend_transform_GetInputCount(ID2D1BlendTransform
*iface
)
174 struct d2d_transform
*transform
= impl_from_ID2D1BlendTransform(iface
);
176 TRACE("iface %p.\n", iface
);
178 return transform
->input_count
;
181 static HRESULT STDMETHODCALLTYPE
d2d_blend_transform_SetOutputBuffer(ID2D1BlendTransform
*iface
,
182 D2D1_BUFFER_PRECISION precision
, D2D1_CHANNEL_DEPTH depth
)
184 FIXME("iface %p, precision %u, depth %u stub.\n", iface
, precision
, depth
);
189 static void STDMETHODCALLTYPE
d2d_blend_transform_SetCached(ID2D1BlendTransform
*iface
,
192 FIXME("iface %p, is_cached %d stub.\n", iface
, is_cached
);
195 static void STDMETHODCALLTYPE
d2d_blend_transform_SetDescription(ID2D1BlendTransform
*iface
,
196 const D2D1_BLEND_DESCRIPTION
*description
)
198 struct d2d_transform
*transform
= impl_from_ID2D1BlendTransform(iface
);
200 TRACE("iface %p, description %p.\n", iface
, description
);
202 transform
->blend_desc
= *description
;
205 static void STDMETHODCALLTYPE
d2d_blend_transform_GetDescription(ID2D1BlendTransform
*iface
,
206 D2D1_BLEND_DESCRIPTION
*description
)
208 struct d2d_transform
*transform
= impl_from_ID2D1BlendTransform(iface
);
210 TRACE("iface %p, description %p.\n", iface
, description
);
212 *description
= transform
->blend_desc
;
215 static const ID2D1BlendTransformVtbl d2d_blend_transform_vtbl
=
217 d2d_blend_transform_QueryInterface
,
218 d2d_blend_transform_AddRef
,
219 d2d_blend_transform_Release
,
220 d2d_blend_transform_GetInputCount
,
221 d2d_blend_transform_SetOutputBuffer
,
222 d2d_blend_transform_SetCached
,
223 d2d_blend_transform_SetDescription
,
224 d2d_blend_transform_GetDescription
,
227 static HRESULT
d2d_blend_transform_create(UINT32 input_count
, const D2D1_BLEND_DESCRIPTION
*blend_desc
,
228 ID2D1BlendTransform
**transform
)
230 struct d2d_transform
*object
;
237 if (!(object
= calloc(1, sizeof(*object
))))
238 return E_OUTOFMEMORY
;
240 object
->ID2D1TransformNode_iface
.lpVtbl
= (ID2D1TransformNodeVtbl
*)&d2d_blend_transform_vtbl
;
241 object
->refcount
= 1;
242 object
->input_count
= input_count
;
243 object
->blend_desc
= *blend_desc
;
245 *transform
= (ID2D1BlendTransform
*)&object
->ID2D1TransformNode_iface
;
250 static struct d2d_transform_node
* d2d_transform_graph_get_node(const struct d2d_transform_graph
*graph
,
251 ID2D1TransformNode
*object
)
253 struct d2d_transform_node
*node
;
255 LIST_FOR_EACH_ENTRY(node
, &graph
->nodes
, struct d2d_transform_node
, entry
)
257 if (node
->object
== object
)
264 static HRESULT
d2d_transform_graph_add_node(struct d2d_transform_graph
*graph
,
265 ID2D1TransformNode
*object
)
267 struct d2d_transform_node
*node
;
269 if (!(node
= calloc(1, sizeof(*node
))))
270 return E_OUTOFMEMORY
;
272 node
->object
= object
;
273 ID2D1TransformNode_AddRef(node
->object
);
274 list_add_tail(&graph
->nodes
, &node
->entry
);
279 static void d2d_transform_graph_delete_node(struct d2d_transform_graph
*graph
,
280 struct d2d_transform_node
*node
)
284 list_remove(&node
->entry
);
285 ID2D1TransformNode_Release(node
->object
);
287 for (i
= 0; i
< graph
->input_count
; ++i
)
289 if (graph
->inputs
[i
].node
== node
)
290 memset(&graph
->inputs
[i
].node
, 0, sizeof(graph
->inputs
[i
].node
));
293 if (graph
->output
== node
)
294 graph
->output
= NULL
;
299 static void d2d_transform_graph_clear(struct d2d_transform_graph
*graph
)
301 struct d2d_transform_node
*node
, *node_next
;
303 LIST_FOR_EACH_ENTRY_SAFE(node
, node_next
, &graph
->nodes
, struct d2d_transform_node
, entry
)
305 d2d_transform_graph_delete_node(graph
, node
);
309 static inline struct d2d_transform_graph
*impl_from_ID2D1TransformGraph(ID2D1TransformGraph
*iface
)
311 return CONTAINING_RECORD(iface
, struct d2d_transform_graph
, ID2D1TransformGraph_iface
);
314 static HRESULT STDMETHODCALLTYPE
d2d_transform_graph_QueryInterface(ID2D1TransformGraph
*iface
, REFIID iid
, void **out
)
316 TRACE("iface %p, iid %s, out %p.\n", iface
, debugstr_guid(iid
), out
);
318 if (IsEqualGUID(iid
, &IID_ID2D1TransformGraph
)
319 || IsEqualGUID(iid
, &IID_IUnknown
))
321 ID2D1TransformGraph_AddRef(iface
);
327 return E_NOINTERFACE
;
330 static ULONG STDMETHODCALLTYPE
d2d_transform_graph_AddRef(ID2D1TransformGraph
*iface
)
332 struct d2d_transform_graph
*graph
=impl_from_ID2D1TransformGraph(iface
);
333 ULONG refcount
= InterlockedIncrement(&graph
->refcount
);
335 TRACE("%p increasing refcount to %lu.\n", iface
, refcount
);
340 static ULONG STDMETHODCALLTYPE
d2d_transform_graph_Release(ID2D1TransformGraph
*iface
)
342 struct d2d_transform_graph
*graph
= impl_from_ID2D1TransformGraph(iface
);
343 ULONG refcount
= InterlockedDecrement(&graph
->refcount
);
345 TRACE("%p decreasing refcount to %lu.\n", iface
, refcount
);
349 d2d_transform_graph_clear(graph
);
357 static UINT32 STDMETHODCALLTYPE
d2d_transform_graph_GetInputCount(ID2D1TransformGraph
*iface
)
359 struct d2d_transform_graph
*graph
= impl_from_ID2D1TransformGraph(iface
);
361 TRACE("iface %p.\n", iface
);
363 return graph
->input_count
;
366 static HRESULT STDMETHODCALLTYPE
d2d_transform_graph_SetSingleTransformNode(ID2D1TransformGraph
*iface
,
367 ID2D1TransformNode
*object
)
369 struct d2d_transform_graph
*graph
= impl_from_ID2D1TransformGraph(iface
);
370 struct d2d_transform_node
*node
;
371 unsigned int i
, input_count
;
374 TRACE("iface %p, object %p.\n", iface
, object
);
376 d2d_transform_graph_clear(graph
);
377 if (FAILED(hr
= d2d_transform_graph_add_node(graph
, object
)))
380 node
= d2d_transform_graph_get_node(graph
, object
);
381 graph
->output
= node
;
383 input_count
= ID2D1TransformNode_GetInputCount(object
);
384 if (graph
->input_count
!= input_count
)
387 for (i
= 0; i
< graph
->input_count
; ++i
)
389 graph
->inputs
[i
].node
= node
;
390 graph
->inputs
[i
].index
= i
;
396 static HRESULT STDMETHODCALLTYPE
d2d_transform_graph_AddNode(ID2D1TransformGraph
*iface
,
397 ID2D1TransformNode
*object
)
399 struct d2d_transform_graph
*graph
= impl_from_ID2D1TransformGraph(iface
);
401 TRACE("iface %p, object %p.\n", iface
, object
);
403 if (d2d_transform_graph_get_node(graph
, object
))
406 return d2d_transform_graph_add_node(graph
, object
);
409 static HRESULT STDMETHODCALLTYPE
d2d_transform_graph_RemoveNode(ID2D1TransformGraph
*iface
,
410 ID2D1TransformNode
*object
)
412 struct d2d_transform_graph
*graph
= impl_from_ID2D1TransformGraph(iface
);
413 struct d2d_transform_node
*node
;
415 TRACE("iface %p, object %p.\n", iface
, object
);
417 if (!(node
= d2d_transform_graph_get_node(graph
, object
)))
418 return HRESULT_FROM_WIN32(ERROR_NOT_FOUND
);
420 d2d_transform_graph_delete_node(graph
, node
);
424 static HRESULT STDMETHODCALLTYPE
d2d_transform_graph_SetOutputNode(ID2D1TransformGraph
*iface
,
425 ID2D1TransformNode
*object
)
427 struct d2d_transform_graph
*graph
= impl_from_ID2D1TransformGraph(iface
);
428 struct d2d_transform_node
*node
;
430 TRACE("iface %p, object %p.\n", iface
, object
);
432 if (!(node
= d2d_transform_graph_get_node(graph
, object
)))
433 return HRESULT_FROM_WIN32(ERROR_NOT_FOUND
);
435 graph
->output
= node
;
440 static HRESULT STDMETHODCALLTYPE
d2d_transform_graph_ConnectNode(ID2D1TransformGraph
*iface
,
441 ID2D1TransformNode
*from_node
, ID2D1TransformNode
*to_node
, UINT32 index
)
443 FIXME("iface %p, from_node %p, to_node %p, index %u stub!\n", iface
, from_node
, to_node
, index
);
448 static HRESULT STDMETHODCALLTYPE
d2d_transform_graph_ConnectToEffectInput(ID2D1TransformGraph
*iface
,
449 UINT32 input_index
, ID2D1TransformNode
*object
, UINT32 node_index
)
451 struct d2d_transform_graph
*graph
= impl_from_ID2D1TransformGraph(iface
);
452 struct d2d_transform_node
*node
;
455 TRACE("iface %p, input_index %u, object %p, node_index %u.\n", iface
, input_index
, object
, node_index
);
457 if (!(node
= d2d_transform_graph_get_node(graph
, object
)))
458 return HRESULT_FROM_WIN32(ERROR_NOT_FOUND
);
460 if (input_index
>= graph
->input_count
)
463 count
= ID2D1TransformNode_GetInputCount(object
);
464 if (node_index
>= count
)
467 graph
->inputs
[input_index
].node
= node
;
468 graph
->inputs
[input_index
].index
= node_index
;
473 static void STDMETHODCALLTYPE
d2d_transform_graph_Clear(ID2D1TransformGraph
*iface
)
475 struct d2d_transform_graph
*graph
= impl_from_ID2D1TransformGraph(iface
);
477 TRACE("iface %p.\n", iface
);
479 d2d_transform_graph_clear(graph
);
482 static HRESULT STDMETHODCALLTYPE
d2d_transform_graph_SetPassthroughGraph(ID2D1TransformGraph
*iface
, UINT32 index
)
484 FIXME("iface %p, index %u stub!\n", iface
, index
);
489 static const ID2D1TransformGraphVtbl d2d_transform_graph_vtbl
=
491 d2d_transform_graph_QueryInterface
,
492 d2d_transform_graph_AddRef
,
493 d2d_transform_graph_Release
,
494 d2d_transform_graph_GetInputCount
,
495 d2d_transform_graph_SetSingleTransformNode
,
496 d2d_transform_graph_AddNode
,
497 d2d_transform_graph_RemoveNode
,
498 d2d_transform_graph_SetOutputNode
,
499 d2d_transform_graph_ConnectNode
,
500 d2d_transform_graph_ConnectToEffectInput
,
501 d2d_transform_graph_Clear
,
502 d2d_transform_graph_SetPassthroughGraph
,
505 static HRESULT
d2d_transform_graph_create(UINT32 input_count
, struct d2d_transform_graph
**graph
)
507 struct d2d_transform_graph
*object
;
509 if (!(object
= calloc(1, sizeof(*object
))))
510 return E_OUTOFMEMORY
;
512 object
->ID2D1TransformGraph_iface
.lpVtbl
= &d2d_transform_graph_vtbl
;
513 object
->refcount
= 1;
514 list_init(&object
->nodes
);
516 if (!(object
->inputs
= calloc(input_count
, sizeof(*object
->inputs
))))
519 return E_OUTOFMEMORY
;
521 object
->input_count
= input_count
;
528 static HRESULT STDMETHODCALLTYPE
d2d_effect_impl_QueryInterface(ID2D1EffectImpl
*iface
, REFIID iid
, void **out
)
530 TRACE("iface %p, iid %s, out %p.\n", iface
, debugstr_guid(iid
), out
);
532 if (IsEqualGUID(iid
, &IID_ID2D1EffectImpl
)
533 || IsEqualGUID(iid
, &IID_IUnknown
))
535 ID2D1EffectImpl_AddRef(iface
);
541 return E_NOINTERFACE
;
544 static ULONG STDMETHODCALLTYPE
d2d_effect_impl_AddRef(ID2D1EffectImpl
*iface
)
549 static ULONG STDMETHODCALLTYPE
d2d_effect_impl_Release(ID2D1EffectImpl
*iface
)
554 static HRESULT STDMETHODCALLTYPE
d2d_effect_impl_Initialize(ID2D1EffectImpl
*iface
,
555 ID2D1EffectContext
*context
, ID2D1TransformGraph
*graph
)
560 static HRESULT STDMETHODCALLTYPE
d2d_effect_impl_PrepareForRender(ID2D1EffectImpl
*iface
, D2D1_CHANGE_TYPE type
)
565 static HRESULT STDMETHODCALLTYPE
d2d_effect_impl_SetGraph(ID2D1EffectImpl
*iface
, ID2D1TransformGraph
*graph
)
570 static const ID2D1EffectImplVtbl d2d_effect_impl_vtbl
=
572 d2d_effect_impl_QueryInterface
,
573 d2d_effect_impl_AddRef
,
574 d2d_effect_impl_Release
,
575 d2d_effect_impl_Initialize
,
576 d2d_effect_impl_PrepareForRender
,
577 d2d_effect_impl_SetGraph
,
580 static HRESULT STDMETHODCALLTYPE
builtin_factory_stub(IUnknown
**effect_impl
)
582 static ID2D1EffectImpl builtin_stub
= { &d2d_effect_impl_vtbl
};
584 *effect_impl
= (IUnknown
*)&builtin_stub
;
589 static const WCHAR _2d_affine_transform_description
[] =
590 L
"<?xml version='1.0'?> \
592 <Property name='DisplayName' type='string' value='2D Affine Transform'/> \
593 <Property name='Author' type='string' value='The Wine Project'/> \
594 <Property name='Category' type='string' value='Stub'/> \
595 <Property name='Description' type='string' value='2D Affine Transform'/> \
597 <Input name='Source'/> \
601 static const WCHAR _3d_perspective_transform_description
[] =
602 L
"<?xml version='1.0'?> \
604 <Property name='DisplayName' type='string' value='3D Perspective Transform'/> \
605 <Property name='Author' type='string' value='The Wine Project'/> \
606 <Property name='Category' type='string' value='Stub'/> \
607 <Property name='Description' type='string' value='3D Perspective Transform'/> \
609 <Input name='Source'/> \
613 static const WCHAR composite_description
[] =
614 L
"<?xml version='1.0'?> \
616 <Property name='DisplayName' type='string' value='Composite'/> \
617 <Property name='Author' type='string' value='The Wine Project'/> \
618 <Property name='Category' type='string' value='Stub'/> \
619 <Property name='Description' type='string' value='Composite'/> \
620 <Inputs minimum='1' maximum='0xffffffff' > \
621 <Input name='Source1'/> \
622 <Input name='Source2'/> \
626 static const WCHAR crop_description
[] =
627 L
"<?xml version='1.0'?> \
629 <Property name='DisplayName' type='string' value='Crop'/> \
630 <Property name='Author' type='string' value='The Wine Project'/> \
631 <Property name='Category' type='string' value='Stub'/> \
632 <Property name='Description' type='string' value='Crop'/> \
634 <Input name='Source'/> \
638 static const WCHAR shadow_description
[] =
639 L
"<?xml version='1.0'?> \
641 <Property name='DisplayName' type='string' value='Shadow'/> \
642 <Property name='Author' type='string' value='The Wine Project'/> \
643 <Property name='Category' type='string' value='Stub'/> \
644 <Property name='Description' type='string' value='Shadow'/> \
646 <Input name='Source'/> \
650 static const WCHAR grayscale_description
[] =
651 L
"<?xml version='1.0'?> \
653 <Property name='DisplayName' type='string' value='Grayscale'/> \
654 <Property name='Author' type='string' value='The Wine Project'/> \
655 <Property name='Category' type='string' value='Stub'/> \
656 <Property name='Description' type='string' value='Grayscale'/> \
658 <Input name='Source'/> \
662 void d2d_effects_init_builtins(struct d2d_factory
*factory
)
664 static const struct builtin_description
667 const WCHAR
*description
;
671 { &CLSID_D2D12DAffineTransform
, _2d_affine_transform_description
},
672 { &CLSID_D2D13DPerspectiveTransform
, _3d_perspective_transform_description
},
673 { &CLSID_D2D1Composite
, composite_description
},
674 { &CLSID_D2D1Crop
, crop_description
},
675 { &CLSID_D2D1Shadow
, shadow_description
},
676 { &CLSID_D2D1Grayscale
, grayscale_description
},
681 for (i
= 0; i
< ARRAY_SIZE(builtin_effects
); ++i
)
683 if (FAILED(hr
= d2d_factory_register_builtin_effect(factory
, builtin_effects
[i
].clsid
, builtin_effects
[i
].description
,
684 NULL
, 0, builtin_factory_stub
)))
686 WARN("Failed to register the effect %s, hr %#lx.\n", wine_dbgstr_guid(builtin_effects
[i
].clsid
), hr
);
691 /* Same syntax is used for value and default values. */
692 static HRESULT
d2d_effect_parse_float_array(D2D1_PROPERTY_TYPE type
, const WCHAR
*value
,
695 unsigned int i
, num_components
;
698 /* Type values are sequential. */
701 case D2D1_PROPERTY_TYPE_VECTOR2
:
702 case D2D1_PROPERTY_TYPE_VECTOR3
:
703 case D2D1_PROPERTY_TYPE_VECTOR4
:
704 num_components
= (type
- D2D1_PROPERTY_TYPE_VECTOR2
) + 2;
706 case D2D1_PROPERTY_TYPE_MATRIX_3X2
:
709 case D2D1_PROPERTY_TYPE_MATRIX_4X3
:
710 case D2D1_PROPERTY_TYPE_MATRIX_4X4
:
711 case D2D1_PROPERTY_TYPE_MATRIX_5X4
:
712 num_components
= (type
- D2D1_PROPERTY_TYPE_MATRIX_4X3
) * 4 + 12;
718 if (*(value
++) != '(') return E_INVALIDARG
;
720 for (i
= 0; i
< num_components
; ++i
)
722 vec
[i
] = wcstof(value
, &end_ptr
);
723 if (value
== end_ptr
) return E_INVALIDARG
;
726 /* Trailing characters after last component are ignored. */
727 if (i
== num_components
- 1) continue;
728 if (*(value
++) != ',') return E_INVALIDARG
;
734 static HRESULT
d2d_effect_properties_internal_add(struct d2d_effect_properties
*props
,
735 const WCHAR
*name
, UINT32 index
, BOOL subprop
, D2D1_PROPERTY_TYPE type
, const WCHAR
*value
)
737 static const UINT32 sizes
[] =
739 [D2D1_PROPERTY_TYPE_UNKNOWN
] = 0,
740 [D2D1_PROPERTY_TYPE_STRING
] = 0,
741 [D2D1_PROPERTY_TYPE_BOOL
] = sizeof(BOOL
),
742 [D2D1_PROPERTY_TYPE_UINT32
] = sizeof(UINT32
),
743 [D2D1_PROPERTY_TYPE_INT32
] = sizeof(INT32
),
744 [D2D1_PROPERTY_TYPE_FLOAT
] = sizeof(float),
745 [D2D1_PROPERTY_TYPE_VECTOR2
] = sizeof(D2D_VECTOR_2F
),
746 [D2D1_PROPERTY_TYPE_VECTOR3
] = sizeof(D2D_VECTOR_3F
),
747 [D2D1_PROPERTY_TYPE_VECTOR4
] = sizeof(D2D_VECTOR_4F
),
748 [D2D1_PROPERTY_TYPE_BLOB
] = 0 /* FIXME */,
749 [D2D1_PROPERTY_TYPE_IUNKNOWN
] = sizeof(IUnknown
*),
750 [D2D1_PROPERTY_TYPE_ENUM
] = sizeof(UINT32
),
751 [D2D1_PROPERTY_TYPE_ARRAY
] = sizeof(UINT32
),
752 [D2D1_PROPERTY_TYPE_CLSID
] = sizeof(CLSID
),
753 [D2D1_PROPERTY_TYPE_MATRIX_3X2
] = sizeof(D2D_MATRIX_3X2_F
),
754 [D2D1_PROPERTY_TYPE_MATRIX_4X3
] = sizeof(D2D_MATRIX_4X3_F
),
755 [D2D1_PROPERTY_TYPE_MATRIX_4X4
] = sizeof(D2D_MATRIX_4X4_F
),
756 [D2D1_PROPERTY_TYPE_MATRIX_5X4
] = sizeof(D2D_MATRIX_5X4_F
),
757 [D2D1_PROPERTY_TYPE_COLOR_CONTEXT
] = sizeof(ID2D1ColorContext
*),
759 struct d2d_effect_property
*p
;
762 assert(type
>= D2D1_PROPERTY_TYPE_STRING
&& type
<= D2D1_PROPERTY_TYPE_COLOR_CONTEXT
);
764 if (type
== D2D1_PROPERTY_TYPE_BLOB
)
766 FIXME("Ignoring property %s of type %u.\n", wine_dbgstr_w(name
), type
);
770 if (!d2d_array_reserve((void **)&props
->properties
, &props
->size
, props
->count
+ 1,
771 sizeof(*props
->properties
)))
773 return E_OUTOFMEMORY
;
776 /* TODO: we could save some space for properties that have both getter and setter. */
777 if (!d2d_array_reserve((void **)&props
->data
.ptr
, &props
->data
.size
,
778 props
->data
.count
+ sizes
[type
], sizeof(*props
->data
.ptr
)))
780 return E_OUTOFMEMORY
;
782 props
->data
.count
+= sizes
[type
];
784 p
= &props
->properties
[props
->count
++];
785 memset(p
, 0, sizeof(*p
));
787 if (p
->index
< 0x80000000)
789 props
->custom_count
++;
790 /* FIXME: this should probably be controlled by subproperty */
796 p
->readonly
= index
!= D2D1_PROPERTY_CACHED
&& index
!= D2D1_PROPERTY_PRECISION
;
797 p
->name
= wcsdup(name
);
799 if (p
->type
== D2D1_PROPERTY_TYPE_STRING
&& value
)
801 p
->data
.ptr
= wcsdup(value
);
802 p
->size
= (wcslen(value
) + 1) * sizeof(WCHAR
);
812 p
->data
.offset
= props
->offset
;
813 p
->size
= sizes
[type
];
814 props
->offset
+= p
->size
;
820 case D2D1_PROPERTY_TYPE_UINT32
:
821 case D2D1_PROPERTY_TYPE_INT32
:
822 _uint32
= wcstoul(value
, NULL
, 0);
825 case D2D1_PROPERTY_TYPE_ENUM
:
826 _uint32
= wcstoul(value
, NULL
, 10);
829 case D2D1_PROPERTY_TYPE_BOOL
:
830 if (!wcscmp(value
, L
"true")) _bool
= TRUE
;
831 else if (!wcscmp(value
, L
"false")) _bool
= FALSE
;
832 else return E_INVALIDARG
;
835 case D2D1_PROPERTY_TYPE_CLSID
:
836 CLSIDFromString(value
, &_clsid
);
839 case D2D1_PROPERTY_TYPE_VECTOR2
:
840 case D2D1_PROPERTY_TYPE_VECTOR3
:
841 case D2D1_PROPERTY_TYPE_VECTOR4
:
842 case D2D1_PROPERTY_TYPE_MATRIX_3X2
:
843 case D2D1_PROPERTY_TYPE_MATRIX_4X3
:
844 case D2D1_PROPERTY_TYPE_MATRIX_4X4
:
845 case D2D1_PROPERTY_TYPE_MATRIX_5X4
:
846 if (FAILED(hr
= d2d_effect_parse_float_array(p
->type
, value
, _vec
)))
848 WARN("Failed to parse float array %s for type %u.\n",
849 wine_dbgstr_w(value
), p
->type
);
854 case D2D1_PROPERTY_TYPE_IUNKNOWN
:
855 case D2D1_PROPERTY_TYPE_COLOR_CONTEXT
:
858 FIXME("Initial value for property type %u is not handled.\n", p
->type
);
861 if (src
&& p
->size
) memcpy(props
->data
.ptr
+ p
->data
.offset
, src
, p
->size
);
864 memset(props
->data
.ptr
+ p
->data
.offset
, 0, p
->size
);
870 HRESULT
d2d_effect_properties_add(struct d2d_effect_properties
*props
, const WCHAR
*name
,
871 UINT32 index
, D2D1_PROPERTY_TYPE type
, const WCHAR
*value
)
873 return d2d_effect_properties_internal_add(props
, name
, index
, FALSE
, type
, value
);
876 HRESULT
d2d_effect_subproperties_add(struct d2d_effect_properties
*props
, const WCHAR
*name
,
877 UINT32 index
, D2D1_PROPERTY_TYPE type
, const WCHAR
*value
)
879 return d2d_effect_properties_internal_add(props
, name
, index
, TRUE
, type
, value
);
882 static HRESULT
d2d_effect_duplicate_properties(struct d2d_effect_properties
*dst
,
883 const struct d2d_effect_properties
*src
)
888 memset(dst
, 0, sizeof(*dst
));
889 dst
->offset
= src
->offset
;
890 dst
->size
= src
->count
;
891 dst
->count
= src
->count
;
892 dst
->custom_count
= src
->custom_count
;
893 dst
->data
.size
= src
->data
.count
;
894 dst
->data
.count
= src
->data
.count
;
896 if (!(dst
->data
.ptr
= malloc(dst
->data
.size
)))
897 return E_OUTOFMEMORY
;
898 memcpy(dst
->data
.ptr
, src
->data
.ptr
, dst
->data
.size
);
900 if (!(dst
->properties
= calloc(dst
->size
, sizeof(*dst
->properties
))))
901 return E_OUTOFMEMORY
;
903 for (i
= 0; i
< dst
->count
; ++i
)
905 struct d2d_effect_property
*d
= &dst
->properties
[i
];
906 const struct d2d_effect_property
*s
= &src
->properties
[i
];
909 d
->name
= wcsdup(s
->name
);
910 if (d
->type
== D2D1_PROPERTY_TYPE_STRING
)
911 d
->data
.ptr
= wcsdup((WCHAR
*)s
->data
.ptr
);
913 if (s
->subproperties
)
915 if (!(d
->subproperties
= calloc(1, sizeof(*d
->subproperties
))))
916 return E_OUTOFMEMORY
;
917 if (FAILED(hr
= d2d_effect_duplicate_properties(d
->subproperties
, s
->subproperties
)))
925 static struct d2d_effect_property
* d2d_effect_properties_get_property_by_index(
926 const struct d2d_effect_properties
*properties
, UINT32 index
)
930 for (i
= 0; i
< properties
->count
; ++i
)
932 if (properties
->properties
[i
].index
== index
)
933 return &properties
->properties
[i
];
939 struct d2d_effect_property
* d2d_effect_properties_get_property_by_name(
940 const struct d2d_effect_properties
*properties
, const WCHAR
*name
)
944 for (i
= 0; i
< properties
->count
; ++i
)
946 if (!wcscmp(properties
->properties
[i
].name
, name
))
947 return &properties
->properties
[i
];
953 static UINT32
d2d_effect_properties_get_value_size(const struct d2d_effect_properties
*properties
,
956 struct d2d_effect
*effect
= properties
->effect
;
957 struct d2d_effect_property
*prop
;
960 if (!(prop
= d2d_effect_properties_get_property_by_index(properties
, index
)))
963 if (prop
->get_function
)
965 if (FAILED(prop
->get_function((IUnknown
*)effect
->impl
, NULL
, 0, &size
))) return 0;
972 static HRESULT
d2d_effect_return_string(const WCHAR
*str
, WCHAR
*buffer
, UINT32 buffer_size
)
974 UINT32 size
= str
? wcslen(str
) : 0;
975 if (size
>= buffer_size
) return D2DERR_INSUFFICIENT_BUFFER
;
976 if (str
) memcpy(buffer
, str
, (size
+ 1) * sizeof(*buffer
));
981 static HRESULT
d2d_effect_property_get_value(const struct d2d_effect_properties
*properties
,
982 const struct d2d_effect_property
*prop
, D2D1_PROPERTY_TYPE type
, BYTE
*value
, UINT32 size
)
984 struct d2d_effect
*effect
= properties
->effect
;
987 if (type
!= D2D1_PROPERTY_TYPE_UNKNOWN
&& prop
->type
!= type
) return E_INVALIDARG
;
988 if (prop
->type
!= D2D1_PROPERTY_TYPE_STRING
&& prop
->size
!= size
) return E_INVALIDARG
;
990 if (prop
->get_function
)
991 return prop
->get_function((IUnknown
*)effect
->impl
, value
, size
, &actual_size
);
995 case D2D1_PROPERTY_TYPE_BLOB
:
996 FIXME("Unimplemented for type %u.\n", prop
->type
);
998 case D2D1_PROPERTY_TYPE_STRING
:
999 return d2d_effect_return_string(prop
->data
.ptr
, (WCHAR
*)value
, size
/ sizeof(WCHAR
));
1001 memcpy(value
, properties
->data
.ptr
+ prop
->data
.offset
, size
);
1008 HRESULT
d2d_effect_property_get_uint32_value(const struct d2d_effect_properties
*properties
,
1009 const struct d2d_effect_property
*prop
, UINT32
*value
)
1011 return d2d_effect_property_get_value(properties
, prop
, D2D1_PROPERTY_TYPE_UINT32
,
1012 (BYTE
*)value
, sizeof(*value
));
1015 static HRESULT
d2d_effect_property_set_value(struct d2d_effect_properties
*properties
,
1016 struct d2d_effect_property
*prop
, D2D1_PROPERTY_TYPE type
, const BYTE
*value
, UINT32 size
)
1018 struct d2d_effect
*effect
= properties
->effect
;
1019 if (prop
->readonly
) return E_INVALIDARG
;
1020 if (type
!= D2D1_PROPERTY_TYPE_UNKNOWN
&& prop
->type
!= type
) return E_INVALIDARG
;
1021 if (prop
->get_function
&& !prop
->set_function
) return E_INVALIDARG
;
1022 if (prop
->index
< 0x80000000 && !prop
->set_function
) return E_INVALIDARG
;
1024 if (prop
->set_function
)
1025 return prop
->set_function((IUnknown
*)effect
->impl
, value
, size
);
1027 if (prop
->size
!= size
) return E_INVALIDARG
;
1031 case D2D1_PROPERTY_TYPE_BOOL
:
1032 case D2D1_PROPERTY_TYPE_UINT32
:
1033 case D2D1_PROPERTY_TYPE_ENUM
:
1034 memcpy(properties
->data
.ptr
+ prop
->data
.offset
, value
, size
);
1037 FIXME("Unhandled type %u.\n", prop
->type
);
1043 void d2d_effect_properties_cleanup(struct d2d_effect_properties
*props
)
1045 struct d2d_effect_property
*p
;
1048 for (i
= 0; i
< props
->count
; ++i
)
1050 p
= &props
->properties
[i
];
1052 if (p
->type
== D2D1_PROPERTY_TYPE_STRING
)
1054 if (p
->subproperties
)
1056 d2d_effect_properties_cleanup(p
->subproperties
);
1057 free(p
->subproperties
);
1060 free(props
->properties
);
1061 free(props
->data
.ptr
);
1064 static inline struct d2d_effect_context
*impl_from_ID2D1EffectContext(ID2D1EffectContext
*iface
)
1066 return CONTAINING_RECORD(iface
, struct d2d_effect_context
, ID2D1EffectContext_iface
);
1069 static HRESULT STDMETHODCALLTYPE
d2d_effect_context_QueryInterface(ID2D1EffectContext
*iface
, REFIID iid
, void **out
)
1071 TRACE("iface %p, iid %s, out %p.\n", iface
, debugstr_guid(iid
), out
);
1073 if (IsEqualGUID(iid
, &IID_ID2D1EffectContext
)
1074 || IsEqualGUID(iid
, &IID_IUnknown
))
1076 ID2D1EffectContext_AddRef(iface
);
1081 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid
));
1084 return E_NOINTERFACE
;
1087 static ULONG STDMETHODCALLTYPE
d2d_effect_context_AddRef(ID2D1EffectContext
*iface
)
1089 struct d2d_effect_context
*effect_context
= impl_from_ID2D1EffectContext(iface
);
1090 ULONG refcount
= InterlockedIncrement(&effect_context
->refcount
);
1092 TRACE("%p increasing refcount to %lu.\n", iface
, refcount
);
1097 static ULONG STDMETHODCALLTYPE
d2d_effect_context_Release(ID2D1EffectContext
*iface
)
1099 struct d2d_effect_context
*effect_context
= impl_from_ID2D1EffectContext(iface
);
1100 ULONG refcount
= InterlockedDecrement(&effect_context
->refcount
);
1102 TRACE("%p decreasing refcount to %lu.\n", iface
, refcount
);
1106 ID2D1DeviceContext1_Release(&effect_context
->device_context
->ID2D1DeviceContext1_iface
);
1107 free(effect_context
);
1113 static void STDMETHODCALLTYPE
d2d_effect_context_GetDpi(ID2D1EffectContext
*iface
, float *dpi_x
, float *dpi_y
)
1115 struct d2d_effect_context
*effect_context
= impl_from_ID2D1EffectContext(iface
);
1117 TRACE("iface %p, dpi_x %p, dpi_y %p.\n", iface
, dpi_x
, dpi_y
);
1119 ID2D1DeviceContext1_GetDpi(&effect_context
->device_context
->ID2D1DeviceContext1_iface
, dpi_x
, dpi_y
);
1122 static HRESULT STDMETHODCALLTYPE
d2d_effect_context_CreateEffect(ID2D1EffectContext
*iface
,
1123 REFCLSID clsid
, ID2D1Effect
**effect
)
1125 struct d2d_effect_context
*effect_context
= impl_from_ID2D1EffectContext(iface
);
1127 TRACE("iface %p, clsid %s, effect %p.\n", iface
, debugstr_guid(clsid
), effect
);
1129 return ID2D1DeviceContext1_CreateEffect(&effect_context
->device_context
->ID2D1DeviceContext1_iface
,
1133 static HRESULT STDMETHODCALLTYPE
d2d_effect_context_GetMaximumSupportedFeatureLevel(ID2D1EffectContext
*iface
,
1134 const D3D_FEATURE_LEVEL
*levels
, UINT32 level_count
, D3D_FEATURE_LEVEL
*max_level
)
1136 FIXME("iface %p, levels %p, level_count %u, max_level %p stub!\n", iface
, levels
, level_count
, max_level
);
1141 static HRESULT STDMETHODCALLTYPE
d2d_effect_context_CreateTransformNodeFromEffect(ID2D1EffectContext
*iface
,
1142 ID2D1Effect
*effect
, ID2D1TransformNode
**node
)
1144 FIXME("iface %p, effect %p, node %p stub!\n", iface
, effect
, node
);
1149 static HRESULT STDMETHODCALLTYPE
d2d_effect_context_CreateBlendTransform(ID2D1EffectContext
*iface
,
1150 UINT32 num_inputs
, const D2D1_BLEND_DESCRIPTION
*description
, ID2D1BlendTransform
**transform
)
1152 TRACE("iface %p, num_inputs %u, description %p, transform %p,\n", iface
, num_inputs
, description
, transform
);
1154 return d2d_blend_transform_create(num_inputs
, description
, transform
);
1157 static HRESULT STDMETHODCALLTYPE
d2d_effect_context_CreateBorderTransform(ID2D1EffectContext
*iface
,
1158 D2D1_EXTEND_MODE mode_x
, D2D1_EXTEND_MODE mode_y
, ID2D1BorderTransform
**transform
)
1160 FIXME("iface %p, mode_x %#x, mode_y %#x, transform %p stub!\n", iface
, mode_x
, mode_y
, transform
);
1165 static HRESULT STDMETHODCALLTYPE
d2d_effect_context_CreateOffsetTransform(ID2D1EffectContext
*iface
,
1166 D2D1_POINT_2L offset
, ID2D1OffsetTransform
**transform
)
1168 TRACE("iface %p, offset %s, transform %p.\n", iface
, debug_d2d_point_2l(&offset
), transform
);
1170 return d2d_offset_transform_create(offset
, transform
);
1173 static HRESULT STDMETHODCALLTYPE
d2d_effect_context_CreateBoundsAdjustmentTransform(ID2D1EffectContext
*iface
,
1174 const D2D1_RECT_L
*output_rect
, ID2D1BoundsAdjustmentTransform
**transform
)
1176 FIXME("iface %p, output_rect %s, transform %p stub!\n", iface
, debug_d2d_rect_l(output_rect
), transform
);
1181 static HRESULT STDMETHODCALLTYPE
d2d_effect_context_LoadPixelShader(ID2D1EffectContext
*iface
,
1182 REFGUID shader_id
, const BYTE
*buffer
, UINT32 buffer_size
)
1184 struct d2d_effect_context
*effect_context
= impl_from_ID2D1EffectContext(iface
);
1185 ID3D11PixelShader
*shader
;
1188 TRACE("iface %p, shader_id %s, buffer %p, buffer_size %u.\n",
1189 iface
, debugstr_guid(shader_id
), buffer
, buffer_size
);
1191 if (d2d_device_is_shader_loaded(effect_context
->device_context
->device
, shader_id
))
1194 if (FAILED(hr
= ID3D11Device1_CreatePixelShader(effect_context
->device_context
->d3d_device
,
1195 buffer
, buffer_size
, NULL
, &shader
)))
1197 WARN("Failed to create a pixel shader, hr %#lx.\n", hr
);
1201 hr
= d2d_device_add_shader(effect_context
->device_context
->device
, shader_id
, (IUnknown
*)shader
);
1202 ID3D11PixelShader_Release(shader
);
1207 static HRESULT STDMETHODCALLTYPE
d2d_effect_context_LoadVertexShader(ID2D1EffectContext
*iface
,
1208 REFGUID shader_id
, const BYTE
*buffer
, UINT32 buffer_size
)
1210 struct d2d_effect_context
*effect_context
= impl_from_ID2D1EffectContext(iface
);
1211 ID3D11VertexShader
*shader
;
1214 TRACE("iface %p, shader_id %s, buffer %p, buffer_size %u.\n",
1215 iface
, debugstr_guid(shader_id
), buffer
, buffer_size
);
1217 if (d2d_device_is_shader_loaded(effect_context
->device_context
->device
, shader_id
))
1220 if (FAILED(hr
= ID3D11Device1_CreateVertexShader(effect_context
->device_context
->d3d_device
,
1221 buffer
, buffer_size
, NULL
, &shader
)))
1223 WARN("Failed to create vertex shader, hr %#lx.\n", hr
);
1227 hr
= d2d_device_add_shader(effect_context
->device_context
->device
, shader_id
, (IUnknown
*)shader
);
1228 ID3D11VertexShader_Release(shader
);
1233 static HRESULT STDMETHODCALLTYPE
d2d_effect_context_LoadComputeShader(ID2D1EffectContext
*iface
,
1234 REFGUID shader_id
, const BYTE
*buffer
, UINT32 buffer_size
)
1236 struct d2d_effect_context
*effect_context
= impl_from_ID2D1EffectContext(iface
);
1237 ID3D11ComputeShader
*shader
;
1240 TRACE("iface %p, shader_id %s, buffer %p, buffer_size %u.\n",
1241 iface
, debugstr_guid(shader_id
), buffer
, buffer_size
);
1243 if (d2d_device_is_shader_loaded(effect_context
->device_context
->device
, shader_id
))
1246 if (FAILED(hr
= ID3D11Device1_CreateComputeShader(effect_context
->device_context
->d3d_device
,
1247 buffer
, buffer_size
, NULL
, &shader
)))
1249 WARN("Failed to create a compute shader, hr %#lx.\n", hr
);
1253 hr
= d2d_device_add_shader(effect_context
->device_context
->device
, shader_id
, (IUnknown
*)shader
);
1254 ID3D11ComputeShader_Release(shader
);
1259 static BOOL STDMETHODCALLTYPE
d2d_effect_context_IsShaderLoaded(ID2D1EffectContext
*iface
, REFGUID shader_id
)
1261 struct d2d_effect_context
*effect_context
= impl_from_ID2D1EffectContext(iface
);
1263 TRACE("iface %p, shader_id %s.\n", iface
, debugstr_guid(shader_id
));
1265 return d2d_device_is_shader_loaded(effect_context
->device_context
->device
, shader_id
);
1268 static HRESULT STDMETHODCALLTYPE
d2d_effect_context_CreateResourceTexture(ID2D1EffectContext
*iface
,
1269 const GUID
*id
, const D2D1_RESOURCE_TEXTURE_PROPERTIES
*texture_properties
,
1270 const BYTE
*data
, const UINT32
*strides
, UINT32 data_size
, ID2D1ResourceTexture
**texture
)
1272 FIXME("iface %p, id %s, texture_properties %p, data %p, strides %p, data_size %u, texture %p stub!\n",
1273 iface
, debugstr_guid(id
), texture_properties
, data
, strides
, data_size
, texture
);
1278 static HRESULT STDMETHODCALLTYPE
d2d_effect_context_FindResourceTexture(ID2D1EffectContext
*iface
,
1279 const GUID
*id
, ID2D1ResourceTexture
**texture
)
1281 FIXME("iface %p, id %s, texture %p stub!\n", iface
, debugstr_guid(id
), texture
);
1286 static HRESULT STDMETHODCALLTYPE
d2d_effect_context_CreateVertexBuffer(ID2D1EffectContext
*iface
,
1287 const D2D1_VERTEX_BUFFER_PROPERTIES
*buffer_properties
, const GUID
*id
,
1288 const D2D1_CUSTOM_VERTEX_BUFFER_PROPERTIES
*custom_buffer_properties
, ID2D1VertexBuffer
**buffer
)
1290 FIXME("iface %p, buffer_properties %p, id %s, custom_buffer_properties %p, buffer %p stub!\n",
1291 iface
, buffer_properties
, debugstr_guid(id
), custom_buffer_properties
, buffer
);
1296 static HRESULT STDMETHODCALLTYPE
d2d_effect_context_FindVertexBuffer(ID2D1EffectContext
*iface
,
1297 const GUID
*id
, ID2D1VertexBuffer
**buffer
)
1299 FIXME("iface %p, id %s, buffer %p stub!\n", iface
, debugstr_guid(id
), buffer
);
1304 static HRESULT STDMETHODCALLTYPE
d2d_effect_context_CreateColorContext(ID2D1EffectContext
*iface
,
1305 D2D1_COLOR_SPACE space
, const BYTE
*profile
, UINT32 profile_size
, ID2D1ColorContext
**color_context
)
1307 struct d2d_effect_context
*effect_context
= impl_from_ID2D1EffectContext(iface
);
1309 TRACE("iface %p, space %#x, profile %p, profile_size %u, color_context %p.\n",
1310 iface
, space
, profile
, profile_size
, color_context
);
1312 return ID2D1DeviceContext1_CreateColorContext(&effect_context
->device_context
->ID2D1DeviceContext1_iface
,
1313 space
, profile
, profile_size
, color_context
);
1316 static HRESULT STDMETHODCALLTYPE
d2d_effect_context_CreateColorContextFromFilename(ID2D1EffectContext
*iface
,
1317 const WCHAR
*filename
, ID2D1ColorContext
**color_context
)
1319 struct d2d_effect_context
*effect_context
= impl_from_ID2D1EffectContext(iface
);
1321 TRACE("iface %p, filename %s, color_context %p.\n", iface
, debugstr_w(filename
), color_context
);
1323 return ID2D1DeviceContext1_CreateColorContextFromFilename(&effect_context
->device_context
->ID2D1DeviceContext1_iface
,
1324 filename
, color_context
);
1327 static HRESULT STDMETHODCALLTYPE
d2d_effect_context_CreateColorContextFromWicColorContext(ID2D1EffectContext
*iface
,
1328 IWICColorContext
*wic_color_context
, ID2D1ColorContext
**color_context
)
1330 struct d2d_effect_context
*effect_context
= impl_from_ID2D1EffectContext(iface
);
1332 TRACE("iface %p, wic_color_context %p, color_context %p.\n", iface
, wic_color_context
, color_context
);
1334 return ID2D1DeviceContext1_CreateColorContextFromWicColorContext(&effect_context
->device_context
->ID2D1DeviceContext1_iface
,
1335 wic_color_context
, color_context
);
1338 static HRESULT STDMETHODCALLTYPE
d2d_effect_context_CheckFeatureSupport(ID2D1EffectContext
*iface
,
1339 D2D1_FEATURE feature
, void *data
, UINT32 data_size
)
1341 struct d2d_effect_context
*effect_context
= impl_from_ID2D1EffectContext(iface
);
1342 D3D11_FEATURE d3d11_feature
;
1344 TRACE("iface %p, feature %#x, data %p, data_size %u.\n", iface
, feature
, data
, data_size
);
1346 /* Data structures are compatible. */
1349 case D2D1_FEATURE_DOUBLES
: d3d11_feature
= D3D11_FEATURE_DOUBLES
; break;
1350 case D2D1_FEATURE_D3D10_X_HARDWARE_OPTIONS
: d3d11_feature
= D3D11_FEATURE_D3D10_X_HARDWARE_OPTIONS
; break;
1352 WARN("Unexpected feature index %d.\n", feature
);
1353 return E_INVALIDARG
;
1356 return ID3D11Device1_CheckFeatureSupport(effect_context
->device_context
->d3d_device
,
1357 d3d11_feature
, data
, data_size
);
1360 static BOOL STDMETHODCALLTYPE
d2d_effect_context_IsBufferPrecisionSupported(ID2D1EffectContext
*iface
,
1361 D2D1_BUFFER_PRECISION precision
)
1363 struct d2d_effect_context
*effect_context
= impl_from_ID2D1EffectContext(iface
);
1365 TRACE("iface %p, precision %u.\n", iface
, precision
);
1367 return ID2D1DeviceContext1_IsBufferPrecisionSupported(&effect_context
->device_context
->ID2D1DeviceContext1_iface
,
1371 static const ID2D1EffectContextVtbl d2d_effect_context_vtbl
=
1373 d2d_effect_context_QueryInterface
,
1374 d2d_effect_context_AddRef
,
1375 d2d_effect_context_Release
,
1376 d2d_effect_context_GetDpi
,
1377 d2d_effect_context_CreateEffect
,
1378 d2d_effect_context_GetMaximumSupportedFeatureLevel
,
1379 d2d_effect_context_CreateTransformNodeFromEffect
,
1380 d2d_effect_context_CreateBlendTransform
,
1381 d2d_effect_context_CreateBorderTransform
,
1382 d2d_effect_context_CreateOffsetTransform
,
1383 d2d_effect_context_CreateBoundsAdjustmentTransform
,
1384 d2d_effect_context_LoadPixelShader
,
1385 d2d_effect_context_LoadVertexShader
,
1386 d2d_effect_context_LoadComputeShader
,
1387 d2d_effect_context_IsShaderLoaded
,
1388 d2d_effect_context_CreateResourceTexture
,
1389 d2d_effect_context_FindResourceTexture
,
1390 d2d_effect_context_CreateVertexBuffer
,
1391 d2d_effect_context_FindVertexBuffer
,
1392 d2d_effect_context_CreateColorContext
,
1393 d2d_effect_context_CreateColorContextFromFilename
,
1394 d2d_effect_context_CreateColorContextFromWicColorContext
,
1395 d2d_effect_context_CheckFeatureSupport
,
1396 d2d_effect_context_IsBufferPrecisionSupported
,
1399 void d2d_effect_context_init(struct d2d_effect_context
*effect_context
, struct d2d_device_context
*device_context
)
1401 effect_context
->ID2D1EffectContext_iface
.lpVtbl
= &d2d_effect_context_vtbl
;
1402 effect_context
->refcount
= 1;
1403 effect_context
->device_context
= device_context
;
1404 ID2D1DeviceContext1_AddRef(&device_context
->ID2D1DeviceContext1_iface
);
1407 static inline struct d2d_effect
*impl_from_ID2D1Effect(ID2D1Effect
*iface
)
1409 return CONTAINING_RECORD(iface
, struct d2d_effect
, ID2D1Effect_iface
);
1412 static void d2d_effect_cleanup(struct d2d_effect
*effect
)
1416 for (i
= 0; i
< effect
->input_count
; ++i
)
1418 if (effect
->inputs
[i
])
1419 ID2D1Image_Release(effect
->inputs
[i
]);
1421 free(effect
->inputs
);
1422 ID2D1EffectContext_Release(&effect
->effect_context
->ID2D1EffectContext_iface
);
1424 ID2D1TransformGraph_Release(&effect
->graph
->ID2D1TransformGraph_iface
);
1425 d2d_effect_properties_cleanup(&effect
->properties
);
1427 ID2D1EffectImpl_Release(effect
->impl
);
1430 static HRESULT STDMETHODCALLTYPE
d2d_effect_QueryInterface(ID2D1Effect
*iface
, REFIID iid
, void **out
)
1432 struct d2d_effect
*effect
= impl_from_ID2D1Effect(iface
);
1433 TRACE("iface %p, iid %s, out %p.\n", iface
, debugstr_guid(iid
), out
);
1435 if (IsEqualGUID(iid
, &IID_ID2D1Effect
)
1436 || IsEqualGUID(iid
, &IID_ID2D1Properties
)
1437 || IsEqualGUID(iid
, &IID_IUnknown
))
1439 ID2D1Effect_AddRef(iface
);
1444 if (IsEqualGUID(iid
, &IID_ID2D1Image
)
1445 || IsEqualGUID(iid
, &IID_ID2D1Resource
))
1447 ID2D1Image_AddRef(&effect
->ID2D1Image_iface
);
1448 *out
= &effect
->ID2D1Image_iface
;
1452 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid
));
1455 return E_NOINTERFACE
;
1458 static ULONG STDMETHODCALLTYPE
d2d_effect_AddRef(ID2D1Effect
*iface
)
1460 struct d2d_effect
*effect
= impl_from_ID2D1Effect(iface
);
1461 ULONG refcount
= InterlockedIncrement(&effect
->refcount
);
1463 TRACE("%p increasing refcount to %lu.\n", iface
, refcount
);
1468 static ULONG STDMETHODCALLTYPE
d2d_effect_Release(ID2D1Effect
*iface
)
1470 struct d2d_effect
*effect
= impl_from_ID2D1Effect(iface
);
1471 ULONG refcount
= InterlockedDecrement(&effect
->refcount
);
1473 TRACE("%p decreasing refcount to %lu.\n", iface
, refcount
);
1477 d2d_effect_cleanup(effect
);
1484 static UINT32 STDMETHODCALLTYPE
d2d_effect_GetPropertyCount(ID2D1Effect
*iface
)
1486 struct d2d_effect
*effect
= impl_from_ID2D1Effect(iface
);
1488 TRACE("iface %p.\n", iface
);
1490 return ID2D1Properties_GetPropertyCount(&effect
->properties
.ID2D1Properties_iface
);
1493 static HRESULT STDMETHODCALLTYPE
d2d_effect_GetPropertyName(ID2D1Effect
*iface
, UINT32 index
,
1494 WCHAR
*name
, UINT32 name_count
)
1496 struct d2d_effect
*effect
= impl_from_ID2D1Effect(iface
);
1498 TRACE("iface %p, index %u, name %p, name_count %u.\n", iface
, index
, name
, name_count
);
1500 return ID2D1Properties_GetPropertyName(&effect
->properties
.ID2D1Properties_iface
,
1501 index
, name
, name_count
);
1504 static UINT32 STDMETHODCALLTYPE
d2d_effect_GetPropertyNameLength(ID2D1Effect
*iface
, UINT32 index
)
1506 struct d2d_effect
*effect
= impl_from_ID2D1Effect(iface
);
1508 TRACE("iface %p, index %u.\n", iface
, index
);
1510 return ID2D1Properties_GetPropertyNameLength(&effect
->properties
.ID2D1Properties_iface
, index
);
1513 static D2D1_PROPERTY_TYPE STDMETHODCALLTYPE
d2d_effect_GetType(ID2D1Effect
*iface
, UINT32 index
)
1515 struct d2d_effect
*effect
= impl_from_ID2D1Effect(iface
);
1517 TRACE("iface %p, index %#x.\n", iface
, index
);
1519 return ID2D1Properties_GetType(&effect
->properties
.ID2D1Properties_iface
, index
);
1522 static UINT32 STDMETHODCALLTYPE
d2d_effect_GetPropertyIndex(ID2D1Effect
*iface
, const WCHAR
*name
)
1524 struct d2d_effect
*effect
= impl_from_ID2D1Effect(iface
);
1526 TRACE("iface %p, name %s.\n", iface
, debugstr_w(name
));
1528 return ID2D1Properties_GetPropertyIndex(&effect
->properties
.ID2D1Properties_iface
, name
);
1531 static HRESULT STDMETHODCALLTYPE
d2d_effect_SetValueByName(ID2D1Effect
*iface
, const WCHAR
*name
,
1532 D2D1_PROPERTY_TYPE type
, const BYTE
*value
, UINT32 value_size
)
1534 struct d2d_effect
*effect
= impl_from_ID2D1Effect(iface
);
1536 TRACE("iface %p, name %s, type %u, value %p, value_size %u.\n", iface
, debugstr_w(name
),
1537 type
, value
, value_size
);
1539 return ID2D1Properties_SetValueByName(&effect
->properties
.ID2D1Properties_iface
, name
,
1540 type
, value
, value_size
);
1543 static HRESULT STDMETHODCALLTYPE
d2d_effect_SetValue(ID2D1Effect
*iface
, UINT32 index
, D2D1_PROPERTY_TYPE type
,
1544 const BYTE
*value
, UINT32 value_size
)
1546 struct d2d_effect
*effect
= impl_from_ID2D1Effect(iface
);
1548 TRACE("iface %p, index %#x, type %u, value %p, value_size %u.\n", iface
, index
, type
, value
, value_size
);
1550 return ID2D1Properties_SetValue(&effect
->properties
.ID2D1Properties_iface
, index
, type
,
1554 static HRESULT STDMETHODCALLTYPE
d2d_effect_GetValueByName(ID2D1Effect
*iface
, const WCHAR
*name
,
1555 D2D1_PROPERTY_TYPE type
, BYTE
*value
, UINT32 value_size
)
1557 struct d2d_effect
*effect
= impl_from_ID2D1Effect(iface
);
1559 TRACE("iface %p, name %s, type %#x, value %p, value_size %u.\n", iface
, debugstr_w(name
), type
,
1562 return ID2D1Properties_GetValueByName(&effect
->properties
.ID2D1Properties_iface
, name
, type
,
1566 static HRESULT
d2d_effect_get_value(struct d2d_effect
*effect
, UINT32 index
, D2D1_PROPERTY_TYPE type
,
1567 BYTE
*value
, UINT32 value_size
)
1569 return ID2D1Properties_GetValue(&effect
->properties
.ID2D1Properties_iface
, index
, type
, value
, value_size
);
1572 static HRESULT STDMETHODCALLTYPE
d2d_effect_GetValue(ID2D1Effect
*iface
, UINT32 index
, D2D1_PROPERTY_TYPE type
,
1573 BYTE
*value
, UINT32 value_size
)
1575 struct d2d_effect
*effect
= impl_from_ID2D1Effect(iface
);
1577 TRACE("iface %p, index %#x, type %u, value %p, value_size %u.\n", iface
, index
, type
, value
, value_size
);
1579 return d2d_effect_get_value(effect
, index
, type
, value
, value_size
);
1582 static UINT32 STDMETHODCALLTYPE
d2d_effect_GetValueSize(ID2D1Effect
*iface
, UINT32 index
)
1584 struct d2d_effect
*effect
= impl_from_ID2D1Effect(iface
);
1586 TRACE("iface %p, index %#x.\n", iface
, index
);
1588 return ID2D1Properties_GetValueSize(&effect
->properties
.ID2D1Properties_iface
, index
);
1591 static HRESULT STDMETHODCALLTYPE
d2d_effect_GetSubProperties(ID2D1Effect
*iface
, UINT32 index
,
1592 ID2D1Properties
**props
)
1594 struct d2d_effect
*effect
= impl_from_ID2D1Effect(iface
);
1596 TRACE("iface %p, index %u, props %p.\n", iface
, index
, props
);
1598 return ID2D1Properties_GetSubProperties(&effect
->properties
.ID2D1Properties_iface
, index
, props
);
1601 static void STDMETHODCALLTYPE
d2d_effect_SetInput(ID2D1Effect
*iface
, UINT32 index
, ID2D1Image
*input
, BOOL invalidate
)
1603 struct d2d_effect
*effect
= impl_from_ID2D1Effect(iface
);
1605 TRACE("iface %p, index %u, input %p, invalidate %#x.\n", iface
, index
, input
, invalidate
);
1607 if (index
>= effect
->input_count
)
1610 ID2D1Image_AddRef(input
);
1611 if (effect
->inputs
[index
])
1612 ID2D1Image_Release(effect
->inputs
[index
]);
1613 effect
->inputs
[index
] = input
;
1616 static HRESULT
d2d_effect_set_input_count(struct d2d_effect
*effect
, UINT32 count
)
1618 bool initialized
= effect
->inputs
!= NULL
;
1622 if (count
== effect
->input_count
)
1625 if (count
< effect
->input_count
)
1627 for (i
= count
; i
< effect
->input_count
; ++i
)
1629 if (effect
->inputs
[i
])
1630 ID2D1Image_Release(effect
->inputs
[i
]);
1635 if (!d2d_array_reserve((void **)&effect
->inputs
, &effect
->inputs_size
,
1636 count
, sizeof(*effect
->inputs
)))
1638 ERR("Failed to resize inputs array.\n");
1639 return E_OUTOFMEMORY
;
1642 memset(&effect
->inputs
[effect
->input_count
], 0, sizeof(*effect
->inputs
) * (count
- effect
->input_count
));
1644 effect
->input_count
= count
;
1648 ID2D1TransformGraph_Release(&effect
->graph
->ID2D1TransformGraph_iface
);
1649 effect
->graph
= NULL
;
1651 if (SUCCEEDED(hr
= d2d_transform_graph_create(count
, &effect
->graph
)))
1653 if (FAILED(hr
= ID2D1EffectImpl_SetGraph(effect
->impl
, &effect
->graph
->ID2D1TransformGraph_iface
)))
1654 WARN("Failed to set a new transform graph, hr %#lx.\n", hr
);
1661 static HRESULT STDMETHODCALLTYPE
d2d_effect_SetInputCount(ID2D1Effect
*iface
, UINT32 count
)
1663 struct d2d_effect
*effect
= impl_from_ID2D1Effect(iface
);
1664 unsigned int min_inputs
, max_inputs
;
1666 TRACE("iface %p, count %u.\n", iface
, count
);
1668 d2d_effect_get_value(effect
, D2D1_PROPERTY_MIN_INPUTS
, D2D1_PROPERTY_TYPE_UINT32
,
1669 (BYTE
*)&min_inputs
, sizeof(min_inputs
));
1670 d2d_effect_get_value(effect
, D2D1_PROPERTY_MAX_INPUTS
, D2D1_PROPERTY_TYPE_UINT32
,
1671 (BYTE
*)&max_inputs
, sizeof(max_inputs
));
1673 if (count
< min_inputs
|| count
> max_inputs
)
1674 return E_INVALIDARG
;
1676 return d2d_effect_set_input_count(effect
, count
);
1679 static void STDMETHODCALLTYPE
d2d_effect_GetInput(ID2D1Effect
*iface
, UINT32 index
, ID2D1Image
**input
)
1681 struct d2d_effect
*effect
= impl_from_ID2D1Effect(iface
);
1683 TRACE("iface %p, index %u, input %p.\n", iface
, index
, input
);
1685 if (index
< effect
->input_count
&& effect
->inputs
[index
])
1686 ID2D1Image_AddRef(*input
= effect
->inputs
[index
]);
1691 static UINT32 STDMETHODCALLTYPE
d2d_effect_GetInputCount(ID2D1Effect
*iface
)
1693 struct d2d_effect
*effect
= impl_from_ID2D1Effect(iface
);
1695 TRACE("iface %p.\n", iface
);
1697 return effect
->input_count
;
1700 static void STDMETHODCALLTYPE
d2d_effect_GetOutput(ID2D1Effect
*iface
, ID2D1Image
**output
)
1702 struct d2d_effect
*effect
= impl_from_ID2D1Effect(iface
);
1704 TRACE("iface %p, output %p.\n", iface
, output
);
1706 ID2D1Image_AddRef(*output
= &effect
->ID2D1Image_iface
);
1709 static const ID2D1EffectVtbl d2d_effect_vtbl
=
1711 d2d_effect_QueryInterface
,
1714 d2d_effect_GetPropertyCount
,
1715 d2d_effect_GetPropertyName
,
1716 d2d_effect_GetPropertyNameLength
,
1718 d2d_effect_GetPropertyIndex
,
1719 d2d_effect_SetValueByName
,
1720 d2d_effect_SetValue
,
1721 d2d_effect_GetValueByName
,
1722 d2d_effect_GetValue
,
1723 d2d_effect_GetValueSize
,
1724 d2d_effect_GetSubProperties
,
1725 d2d_effect_SetInput
,
1726 d2d_effect_SetInputCount
,
1727 d2d_effect_GetInput
,
1728 d2d_effect_GetInputCount
,
1729 d2d_effect_GetOutput
,
1732 static inline struct d2d_effect
*impl_from_ID2D1Image(ID2D1Image
*iface
)
1734 return CONTAINING_RECORD(iface
, struct d2d_effect
, ID2D1Image_iface
);
1737 static HRESULT STDMETHODCALLTYPE
d2d_effect_image_QueryInterface(ID2D1Image
*iface
, REFIID iid
, void **out
)
1739 struct d2d_effect
*effect
= impl_from_ID2D1Image(iface
);
1741 TRACE("iface %p, iid %s, out %p.\n", iface
, debugstr_guid(iid
), out
);
1743 return d2d_effect_QueryInterface(&effect
->ID2D1Effect_iface
, iid
, out
);
1746 static ULONG STDMETHODCALLTYPE
d2d_effect_image_AddRef(ID2D1Image
*iface
)
1748 struct d2d_effect
*effect
= impl_from_ID2D1Image(iface
);
1750 TRACE("iface %p.\n", iface
);
1752 return d2d_effect_AddRef(&effect
->ID2D1Effect_iface
);
1755 static ULONG STDMETHODCALLTYPE
d2d_effect_image_Release(ID2D1Image
*iface
)
1757 struct d2d_effect
*effect
= impl_from_ID2D1Image(iface
);
1759 TRACE("iface %p.\n", iface
);
1761 return d2d_effect_Release(&effect
->ID2D1Effect_iface
);
1764 static void STDMETHODCALLTYPE
d2d_effect_image_GetFactory(ID2D1Image
*iface
, ID2D1Factory
**factory
)
1766 struct d2d_effect
*effect
= impl_from_ID2D1Image(iface
);
1768 TRACE("iface %p, factory %p.\n", iface
, factory
);
1770 ID2D1Factory_AddRef(*factory
= effect
->effect_context
->device_context
->factory
);
1773 static const ID2D1ImageVtbl d2d_effect_image_vtbl
=
1775 d2d_effect_image_QueryInterface
,
1776 d2d_effect_image_AddRef
,
1777 d2d_effect_image_Release
,
1778 d2d_effect_image_GetFactory
,
1781 static inline struct d2d_effect_properties
*impl_from_ID2D1Properties(ID2D1Properties
*iface
)
1783 return CONTAINING_RECORD(iface
, struct d2d_effect_properties
, ID2D1Properties_iface
);
1786 static HRESULT STDMETHODCALLTYPE
d2d_effect_properties_QueryInterface(ID2D1Properties
*iface
,
1787 REFIID riid
, void **obj
)
1789 if (IsEqualGUID(riid
, &IID_ID2D1Properties
) ||
1790 IsEqualGUID(riid
, &IID_IUnknown
))
1793 ID2D1Properties_AddRef(iface
);
1798 return E_NOINTERFACE
;
1801 static ULONG STDMETHODCALLTYPE
d2d_effect_properties_AddRef(ID2D1Properties
*iface
)
1803 struct d2d_effect_properties
*properties
= impl_from_ID2D1Properties(iface
);
1804 return ID2D1Effect_AddRef(&properties
->effect
->ID2D1Effect_iface
);
1807 static ULONG STDMETHODCALLTYPE
d2d_effect_properties_Release(ID2D1Properties
*iface
)
1809 struct d2d_effect_properties
*properties
= impl_from_ID2D1Properties(iface
);
1810 return ID2D1Effect_Release(&properties
->effect
->ID2D1Effect_iface
);
1813 static UINT32 STDMETHODCALLTYPE
d2d_effect_properties_GetPropertyCount(ID2D1Properties
*iface
)
1815 struct d2d_effect_properties
*properties
= impl_from_ID2D1Properties(iface
);
1817 TRACE("iface %p.\n", iface
);
1819 return properties
->custom_count
;
1822 static HRESULT STDMETHODCALLTYPE
d2d_effect_properties_GetPropertyName(ID2D1Properties
*iface
,
1823 UINT32 index
, WCHAR
*name
, UINT32 name_count
)
1825 struct d2d_effect_properties
*properties
= impl_from_ID2D1Properties(iface
);
1826 struct d2d_effect_property
*prop
;
1828 TRACE("iface %p, index %u, name %p, name_count %u.\n", iface
, index
, name
, name_count
);
1830 if (!(prop
= d2d_effect_properties_get_property_by_index(properties
, index
)))
1831 return D2DERR_INVALID_PROPERTY
;
1833 return d2d_effect_return_string(prop
->name
, name
, name_count
);
1836 static UINT32 STDMETHODCALLTYPE
d2d_effect_properties_GetPropertyNameLength(ID2D1Properties
*iface
,
1839 struct d2d_effect_properties
*properties
= impl_from_ID2D1Properties(iface
);
1840 struct d2d_effect_property
*prop
;
1842 TRACE("iface %p, index %u.\n", iface
, index
);
1844 if (!(prop
= d2d_effect_properties_get_property_by_index(properties
, index
)))
1845 return D2DERR_INVALID_PROPERTY
;
1847 return wcslen(prop
->name
) + 1;
1850 static D2D1_PROPERTY_TYPE STDMETHODCALLTYPE
d2d_effect_properties_GetType(ID2D1Properties
*iface
,
1853 struct d2d_effect_properties
*properties
= impl_from_ID2D1Properties(iface
);
1854 struct d2d_effect_property
*prop
;
1856 TRACE("iface %p, index %#x.\n", iface
, index
);
1858 if (!(prop
= d2d_effect_properties_get_property_by_index(properties
, index
)))
1859 return D2D1_PROPERTY_TYPE_UNKNOWN
;
1864 static UINT32 STDMETHODCALLTYPE
d2d_effect_properties_GetPropertyIndex(ID2D1Properties
*iface
,
1867 struct d2d_effect_properties
*properties
= impl_from_ID2D1Properties(iface
);
1868 struct d2d_effect_property
*prop
;
1870 TRACE("iface %p, name %s.\n", iface
, debugstr_w(name
));
1872 if (!(prop
= d2d_effect_properties_get_property_by_name(properties
, name
)))
1873 return D2D1_INVALID_PROPERTY_INDEX
;
1878 static HRESULT STDMETHODCALLTYPE
d2d_effect_properties_SetValueByName(ID2D1Properties
*iface
,
1879 const WCHAR
*name
, D2D1_PROPERTY_TYPE type
, const BYTE
*value
, UINT32 value_size
)
1881 struct d2d_effect_properties
*properties
= impl_from_ID2D1Properties(iface
);
1882 struct d2d_effect_property
*prop
;
1884 TRACE("iface %p, name %s, type %u, value %p, value_size %u.\n", iface
, debugstr_w(name
),
1885 type
, value
, value_size
);
1887 if (!(prop
= d2d_effect_properties_get_property_by_name(properties
, name
)))
1888 return D2DERR_INVALID_PROPERTY
;
1890 return d2d_effect_property_set_value(properties
, prop
, type
, value
, value_size
);
1893 static HRESULT STDMETHODCALLTYPE
d2d_effect_properties_SetValue(ID2D1Properties
*iface
,
1894 UINT32 index
, D2D1_PROPERTY_TYPE type
, const BYTE
*value
, UINT32 value_size
)
1896 struct d2d_effect_properties
*properties
= impl_from_ID2D1Properties(iface
);
1897 struct d2d_effect_property
*prop
;
1899 TRACE("iface %p, index %#x, type %u, value %p, value_size %u.\n", iface
, index
, type
, value
, value_size
);
1901 if (!(prop
= d2d_effect_properties_get_property_by_index(properties
, index
)))
1902 return D2DERR_INVALID_PROPERTY
;
1904 return d2d_effect_property_set_value(properties
, prop
, type
, value
, value_size
);
1907 static HRESULT STDMETHODCALLTYPE
d2d_effect_properties_GetValueByName(ID2D1Properties
*iface
,
1908 const WCHAR
*name
, D2D1_PROPERTY_TYPE type
, BYTE
*value
, UINT32 value_size
)
1910 struct d2d_effect_properties
*properties
= impl_from_ID2D1Properties(iface
);
1911 struct d2d_effect_property
*prop
;
1913 TRACE("iface %p, name %s, type %#x, value %p, value_size %u.\n", iface
, debugstr_w(name
), type
,
1916 if (!(prop
= d2d_effect_properties_get_property_by_name(properties
, name
)))
1917 return D2DERR_INVALID_PROPERTY
;
1919 return d2d_effect_property_get_value(properties
, prop
, type
, value
, value_size
);
1922 static HRESULT STDMETHODCALLTYPE
d2d_effect_properties_GetValue(ID2D1Properties
*iface
,
1923 UINT32 index
, D2D1_PROPERTY_TYPE type
, BYTE
*value
, UINT32 value_size
)
1925 struct d2d_effect_properties
*properties
= impl_from_ID2D1Properties(iface
);
1926 struct d2d_effect_property
*prop
;
1928 TRACE("iface %p, index %#x, type %u, value %p, value_size %u.\n", iface
, index
, type
, value
, value_size
);
1930 if (!(prop
= d2d_effect_properties_get_property_by_index(properties
, index
)))
1931 return D2DERR_INVALID_PROPERTY
;
1933 return d2d_effect_property_get_value(properties
, prop
, type
, value
, value_size
);
1936 static UINT32 STDMETHODCALLTYPE
d2d_effect_properties_GetValueSize(ID2D1Properties
*iface
,
1939 struct d2d_effect_properties
*properties
= impl_from_ID2D1Properties(iface
);
1941 TRACE("iface %p, index %#x.\n", iface
, index
);
1943 return d2d_effect_properties_get_value_size(properties
, index
);
1946 static HRESULT STDMETHODCALLTYPE
d2d_effect_properties_GetSubProperties(ID2D1Properties
*iface
,
1947 UINT32 index
, ID2D1Properties
**props
)
1949 struct d2d_effect_properties
*properties
= impl_from_ID2D1Properties(iface
);
1950 struct d2d_effect_property
*prop
;
1952 TRACE("iface %p, index %u, props %p.\n", iface
, index
, props
);
1954 if (!(prop
= d2d_effect_properties_get_property_by_index(properties
, index
)))
1955 return D2DERR_INVALID_PROPERTY
;
1957 if (!prop
->subproperties
) return D2DERR_NO_SUBPROPERTIES
;
1959 *props
= &prop
->subproperties
->ID2D1Properties_iface
;
1960 ID2D1Properties_AddRef(*props
);
1964 static const ID2D1PropertiesVtbl d2d_effect_properties_vtbl
=
1966 d2d_effect_properties_QueryInterface
,
1967 d2d_effect_properties_AddRef
,
1968 d2d_effect_properties_Release
,
1969 d2d_effect_properties_GetPropertyCount
,
1970 d2d_effect_properties_GetPropertyName
,
1971 d2d_effect_properties_GetPropertyNameLength
,
1972 d2d_effect_properties_GetType
,
1973 d2d_effect_properties_GetPropertyIndex
,
1974 d2d_effect_properties_SetValueByName
,
1975 d2d_effect_properties_SetValue
,
1976 d2d_effect_properties_GetValueByName
,
1977 d2d_effect_properties_GetValue
,
1978 d2d_effect_properties_GetValueSize
,
1979 d2d_effect_properties_GetSubProperties
,
1982 static void d2d_effect_init_properties_vtbls(struct d2d_effect
*effect
)
1986 effect
->properties
.ID2D1Properties_iface
.lpVtbl
= &d2d_effect_properties_vtbl
;
1987 effect
->properties
.effect
= effect
;
1989 for (i
= 0; i
< effect
->properties
.count
; ++i
)
1991 struct d2d_effect_property
*prop
= &effect
->properties
.properties
[i
];
1992 if (!prop
->subproperties
) continue;
1993 prop
->subproperties
->ID2D1Properties_iface
.lpVtbl
= &d2d_effect_properties_vtbl
;
1994 prop
->subproperties
->effect
= effect
;
1998 HRESULT
d2d_effect_create(struct d2d_device_context
*context
, const CLSID
*effect_id
,
1999 ID2D1Effect
**effect
)
2001 struct d2d_effect_context
*effect_context
;
2002 const struct d2d_effect_registration
*reg
;
2003 struct d2d_effect
*object
;
2008 if (!(reg
= d2d_factory_get_registered_effect(context
->factory
, effect_id
)))
2010 WARN("Effect id %s not found.\n", wine_dbgstr_guid(effect_id
));
2011 return D2DERR_EFFECT_IS_NOT_REGISTERED
;
2014 if (!(effect_context
= calloc(1, sizeof(*effect_context
))))
2015 return E_OUTOFMEMORY
;
2016 d2d_effect_context_init(effect_context
, context
);
2018 if (!(object
= calloc(1, sizeof(*object
))))
2020 ID2D1EffectContext_Release(&effect_context
->ID2D1EffectContext_iface
);
2021 return E_OUTOFMEMORY
;
2024 object
->ID2D1Effect_iface
.lpVtbl
= &d2d_effect_vtbl
;
2025 object
->ID2D1Image_iface
.lpVtbl
= &d2d_effect_image_vtbl
;
2026 object
->refcount
= 1;
2027 object
->effect_context
= effect_context
;
2029 /* Create properties */
2030 d2d_effect_duplicate_properties(&object
->properties
, ®
->properties
);
2032 StringFromGUID2(effect_id
, clsidW
, ARRAY_SIZE(clsidW
));
2033 d2d_effect_properties_add(&object
->properties
, L
"CLSID", D2D1_PROPERTY_CLSID
, D2D1_PROPERTY_TYPE_CLSID
, clsidW
);
2034 d2d_effect_properties_add(&object
->properties
, L
"Cached", D2D1_PROPERTY_CACHED
, D2D1_PROPERTY_TYPE_BOOL
, L
"false");
2035 d2d_effect_properties_add(&object
->properties
, L
"Precision", D2D1_PROPERTY_PRECISION
, D2D1_PROPERTY_TYPE_ENUM
, L
"0");
2036 d2d_effect_init_properties_vtbls(object
);
2038 /* Sync instance input count with default input count from the description. */
2039 d2d_effect_get_value(object
, D2D1_PROPERTY_INPUTS
, D2D1_PROPERTY_TYPE_ARRAY
, (BYTE
*)&input_count
, sizeof(input_count
));
2040 d2d_effect_set_input_count(object
, input_count
);
2042 if (FAILED(hr
= d2d_transform_graph_create(input_count
, &object
->graph
)))
2044 ID2D1EffectContext_Release(&effect_context
->ID2D1EffectContext_iface
);
2048 if (FAILED(hr
= reg
->factory((IUnknown
**)&object
->impl
)))
2050 WARN("Failed to create implementation object, hr %#lx.\n", hr
);
2051 ID2D1Effect_Release(&object
->ID2D1Effect_iface
);
2055 if (FAILED(hr
= ID2D1EffectImpl_Initialize(object
->impl
, &effect_context
->ID2D1EffectContext_iface
,
2056 &object
->graph
->ID2D1TransformGraph_iface
)))
2058 WARN("Failed to initialize effect, hr %#lx.\n", hr
);
2059 ID2D1Effect_Release(&object
->ID2D1Effect_iface
);
2063 *effect
= &object
->ID2D1Effect_iface
;
2065 TRACE("Created effect %p.\n", *effect
);