widl: Properly align name table entries.
[wine.git] / dlls / d2d1 / effect.c
blobcf715332fdea6c1a0c60205716617cd4ff66fd8a
1 /*
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))
42 *out = iface;
43 ID2D1OffsetTransform_AddRef(iface);
44 return S_OK;
47 WARN("Unsupported interface %s.\n", debugstr_guid(iid));
48 *out = NULL;
49 return E_NOINTERFACE;
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);
59 return 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);
69 if (!refcount)
70 free(transform);
72 return refcount;
75 static UINT32 STDMETHODCALLTYPE d2d_offset_transform_GetInputCount(ID2D1OffsetTransform *iface)
77 TRACE("iface %p.\n", iface);
79 return 1;
82 static void STDMETHODCALLTYPE d2d_offset_transform_SetOffset(ID2D1OffsetTransform *iface,
83 D2D1_POINT_2L offset)
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;
100 return 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;
126 return S_OK;
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))
139 *out = iface;
140 ID2D1BlendTransform_AddRef(iface);
141 return S_OK;
144 WARN("Unsupported interface %s.\n", debugstr_guid(iid));
145 *out = NULL;
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);
156 return 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);
166 if (!refcount)
167 free(transform);
169 return 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);
186 return E_NOTIMPL;
189 static void STDMETHODCALLTYPE d2d_blend_transform_SetCached(ID2D1BlendTransform *iface,
190 BOOL is_cached)
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;
232 *transform = NULL;
234 if (!input_count)
235 return E_INVALIDARG;
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;
247 return S_OK;
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)
258 return node;
261 return NULL;
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);
276 return S_OK;
279 static void d2d_transform_graph_delete_node(struct d2d_transform_graph *graph,
280 struct d2d_transform_node *node)
282 unsigned int i;
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;
296 free(node);
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);
322 *out = iface;
323 return S_OK;
326 *out = NULL;
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);
337 return 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);
347 if (!refcount)
349 d2d_transform_graph_clear(graph);
350 free(graph->inputs);
351 free(graph);
354 return refcount;
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;
372 HRESULT hr;
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)))
378 return hr;
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)
385 return E_INVALIDARG;
387 for (i = 0; i < graph->input_count; ++i)
389 graph->inputs[i].node = node;
390 graph->inputs[i].index = i;
393 return S_OK;
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))
404 return E_INVALIDARG;
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);
421 return S_OK;
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;
437 return S_OK;
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);
445 return E_NOTIMPL;
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;
453 unsigned int count;
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)
461 return E_INVALIDARG;
463 count = ID2D1TransformNode_GetInputCount(object);
464 if (node_index >= count)
465 return E_INVALIDARG;
467 graph->inputs[input_index].node = node;
468 graph->inputs[input_index].index = node_index;
470 return S_OK;
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);
486 return E_NOTIMPL;
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))))
518 free(object);
519 return E_OUTOFMEMORY;
521 object->input_count = input_count;
523 *graph = object;
525 return S_OK;
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);
536 *out = iface;
537 return S_OK;
540 *out = NULL;
541 return E_NOINTERFACE;
544 static ULONG STDMETHODCALLTYPE d2d_effect_impl_AddRef(ID2D1EffectImpl *iface)
546 return 2;
549 static ULONG STDMETHODCALLTYPE d2d_effect_impl_Release(ID2D1EffectImpl *iface)
551 return 1;
554 static HRESULT STDMETHODCALLTYPE d2d_effect_impl_Initialize(ID2D1EffectImpl *iface,
555 ID2D1EffectContext *context, ID2D1TransformGraph *graph)
557 return S_OK;
560 static HRESULT STDMETHODCALLTYPE d2d_effect_impl_PrepareForRender(ID2D1EffectImpl *iface, D2D1_CHANGE_TYPE type)
562 return S_OK;
565 static HRESULT STDMETHODCALLTYPE d2d_effect_impl_SetGraph(ID2D1EffectImpl *iface, ID2D1TransformGraph *graph)
567 return S_OK;
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;
586 return S_OK;
589 static const WCHAR _2d_affine_transform_description[] =
590 L"<?xml version='1.0'?> \
591 <Effect> \
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'/> \
596 <Inputs> \
597 <Input name='Source'/> \
598 </Inputs> \
599 </Effect>";
601 static const WCHAR _3d_perspective_transform_description[] =
602 L"<?xml version='1.0'?> \
603 <Effect> \
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'/> \
608 <Inputs> \
609 <Input name='Source'/> \
610 </Inputs> \
611 </Effect>";
613 static const WCHAR composite_description[] =
614 L"<?xml version='1.0'?> \
615 <Effect> \
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'/> \
623 </Inputs> \
624 </Effect>";
626 static const WCHAR crop_description[] =
627 L"<?xml version='1.0'?> \
628 <Effect> \
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'/> \
633 <Inputs > \
634 <Input name='Source'/> \
635 </Inputs> \
636 </Effect>";
638 static const WCHAR shadow_description[] =
639 L"<?xml version='1.0'?> \
640 <Effect> \
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'/> \
645 <Inputs > \
646 <Input name='Source'/> \
647 </Inputs> \
648 </Effect>";
650 static const WCHAR grayscale_description[] =
651 L"<?xml version='1.0'?> \
652 <Effect> \
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'/> \
657 <Inputs > \
658 <Input name='Source'/> \
659 </Inputs> \
660 </Effect>";
662 void d2d_effects_init_builtins(struct d2d_factory *factory)
664 static const struct builtin_description
666 const CLSID *clsid;
667 const WCHAR *description;
669 builtin_effects[] =
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 },
678 unsigned int i;
679 HRESULT hr;
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,
693 float *vec)
695 unsigned int i, num_components;
696 WCHAR *end_ptr;
698 /* Type values are sequential. */
699 switch (type)
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;
705 break;
706 case D2D1_PROPERTY_TYPE_MATRIX_3X2:
707 num_components = 6;
708 break;
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;
713 break;
714 default:
715 return E_UNEXPECTED;
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;
724 value = end_ptr;
726 /* Trailing characters after last component are ignored. */
727 if (i == num_components - 1) continue;
728 if (*(value++) != ',') return E_INVALIDARG;
731 return S_OK;
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;
760 HRESULT hr;
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);
767 return S_OK;
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));
786 p->index = index;
787 if (p->index < 0x80000000)
789 props->custom_count++;
790 /* FIXME: this should probably be controlled by subproperty */
791 p->readonly = FALSE;
793 else if (subprop)
794 p->readonly = TRUE;
795 else
796 p->readonly = index != D2D1_PROPERTY_CACHED && index != D2D1_PROPERTY_PRECISION;
797 p->name = wcsdup(name);
798 p->type = type;
799 if (p->type == D2D1_PROPERTY_TYPE_STRING && value)
801 p->data.ptr = wcsdup(value);
802 p->size = (wcslen(value) + 1) * sizeof(WCHAR);
804 else
806 void *src = NULL;
807 UINT32 _uint32;
808 float _vec[20];
809 CLSID _clsid;
810 BOOL _bool;
812 p->data.offset = props->offset;
813 p->size = sizes[type];
814 props->offset += p->size;
816 if (value)
818 switch (p->type)
820 case D2D1_PROPERTY_TYPE_UINT32:
821 case D2D1_PROPERTY_TYPE_INT32:
822 _uint32 = wcstoul(value, NULL, 0);
823 src = &_uint32;
824 break;
825 case D2D1_PROPERTY_TYPE_ENUM:
826 _uint32 = wcstoul(value, NULL, 10);
827 src = &_uint32;
828 break;
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;
833 src = &_bool;
834 break;
835 case D2D1_PROPERTY_TYPE_CLSID:
836 CLSIDFromString(value, &_clsid);
837 src = &_clsid;
838 break;
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);
850 return hr;
852 src = _vec;
853 break;
854 case D2D1_PROPERTY_TYPE_IUNKNOWN:
855 case D2D1_PROPERTY_TYPE_COLOR_CONTEXT:
856 break;
857 default:
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);
863 else if (p->size)
864 memset(props->data.ptr + p->data.offset, 0, p->size);
867 return S_OK;
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)
885 HRESULT hr;
886 size_t i;
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];
908 *d = *s;
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)))
918 return hr;
922 return S_OK;
925 static struct d2d_effect_property * d2d_effect_properties_get_property_by_index(
926 const struct d2d_effect_properties *properties, UINT32 index)
928 unsigned int i;
930 for (i = 0; i < properties->count; ++i)
932 if (properties->properties[i].index == index)
933 return &properties->properties[i];
936 return NULL;
939 struct d2d_effect_property * d2d_effect_properties_get_property_by_name(
940 const struct d2d_effect_properties *properties, const WCHAR *name)
942 unsigned int i;
944 for (i = 0; i < properties->count; ++i)
946 if (!wcscmp(properties->properties[i].name, name))
947 return &properties->properties[i];
950 return NULL;
953 static UINT32 d2d_effect_properties_get_value_size(const struct d2d_effect_properties *properties,
954 UINT32 index)
956 struct d2d_effect *effect = properties->effect;
957 struct d2d_effect_property *prop;
958 UINT32 size;
960 if (!(prop = d2d_effect_properties_get_property_by_index(properties, index)))
961 return 0;
963 if (prop->get_function)
965 if (FAILED(prop->get_function((IUnknown *)effect->impl, NULL, 0, &size))) return 0;
966 return size;
969 return prop->size;
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));
977 else *buffer = 0;
978 return S_OK;
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;
985 UINT32 actual_size;
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);
993 switch (prop->type)
995 case D2D1_PROPERTY_TYPE_BLOB:
996 FIXME("Unimplemented for type %u.\n", prop->type);
997 return E_NOTIMPL;
998 case D2D1_PROPERTY_TYPE_STRING:
999 return d2d_effect_return_string(prop->data.ptr, (WCHAR *)value, size / sizeof(WCHAR));
1000 default:
1001 memcpy(value, properties->data.ptr + prop->data.offset, size);
1002 break;
1005 return S_OK;
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;
1029 switch (prop->type)
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);
1035 break;
1036 default:
1037 FIXME("Unhandled type %u.\n", prop->type);
1040 return S_OK;
1043 void d2d_effect_properties_cleanup(struct d2d_effect_properties *props)
1045 struct d2d_effect_property *p;
1046 size_t i;
1048 for (i = 0; i < props->count; ++i)
1050 p = &props->properties[i];
1051 free(p->name);
1052 if (p->type == D2D1_PROPERTY_TYPE_STRING)
1053 free(p->data.ptr);
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);
1077 *out = iface;
1078 return S_OK;
1081 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
1083 *out = NULL;
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);
1094 return 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);
1104 if (!refcount)
1106 ID2D1DeviceContext1_Release(&effect_context->device_context->ID2D1DeviceContext1_iface);
1107 free(effect_context);
1110 return refcount;
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,
1130 clsid, effect);
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);
1138 return E_NOTIMPL;
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);
1146 return E_NOTIMPL;
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);
1162 return E_NOTIMPL;
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);
1178 return E_NOTIMPL;
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;
1186 HRESULT hr;
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))
1192 return S_OK;
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);
1198 return hr;
1201 hr = d2d_device_add_shader(effect_context->device_context->device, shader_id, (IUnknown *)shader);
1202 ID3D11PixelShader_Release(shader);
1204 return hr;
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;
1212 HRESULT hr;
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))
1218 return S_OK;
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);
1224 return hr;
1227 hr = d2d_device_add_shader(effect_context->device_context->device, shader_id, (IUnknown *)shader);
1228 ID3D11VertexShader_Release(shader);
1230 return hr;
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;
1238 HRESULT hr;
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))
1244 return S_OK;
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);
1250 return hr;
1253 hr = d2d_device_add_shader(effect_context->device_context->device, shader_id, (IUnknown *)shader);
1254 ID3D11ComputeShader_Release(shader);
1256 return hr;
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);
1275 return E_NOTIMPL;
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);
1283 return E_NOTIMPL;
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);
1293 return E_NOTIMPL;
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);
1301 return E_NOTIMPL;
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. */
1347 switch (feature)
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;
1351 default:
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,
1368 precision);
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)
1414 unsigned int i;
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);
1423 if (effect->graph)
1424 ID2D1TransformGraph_Release(&effect->graph->ID2D1TransformGraph_iface);
1425 d2d_effect_properties_cleanup(&effect->properties);
1426 if (effect->impl)
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);
1440 *out = iface;
1441 return S_OK;
1444 if (IsEqualGUID(iid, &IID_ID2D1Image)
1445 || IsEqualGUID(iid, &IID_ID2D1Resource))
1447 ID2D1Image_AddRef(&effect->ID2D1Image_iface);
1448 *out = &effect->ID2D1Image_iface;
1449 return S_OK;
1452 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
1454 *out = NULL;
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);
1465 return 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);
1475 if (!refcount)
1477 d2d_effect_cleanup(effect);
1478 free(effect);
1481 return refcount;
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,
1551 value, value_size);
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,
1560 value, value_size);
1562 return ID2D1Properties_GetValueByName(&effect->properties.ID2D1Properties_iface, name, type,
1563 value, value_size);
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)
1608 return;
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;
1619 HRESULT hr = S_OK;
1620 unsigned int i;
1622 if (count == effect->input_count)
1623 return S_OK;
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]);
1633 else
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;
1646 if (initialized)
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);
1658 return 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]);
1687 else
1688 *input = NULL;
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,
1712 d2d_effect_AddRef,
1713 d2d_effect_Release,
1714 d2d_effect_GetPropertyCount,
1715 d2d_effect_GetPropertyName,
1716 d2d_effect_GetPropertyNameLength,
1717 d2d_effect_GetType,
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))
1792 *obj = iface;
1793 ID2D1Properties_AddRef(iface);
1794 return S_OK;
1797 *obj = NULL;
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,
1837 UINT32 index)
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,
1851 UINT32 index)
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;
1861 return prop->type;
1864 static UINT32 STDMETHODCALLTYPE d2d_effect_properties_GetPropertyIndex(ID2D1Properties *iface,
1865 const WCHAR *name)
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;
1875 return prop->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,
1914 value, value_size);
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,
1937 UINT32 index)
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);
1961 return S_OK;
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)
1984 unsigned int i;
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;
2004 UINT32 input_count;
2005 WCHAR clsidW[39];
2006 HRESULT hr;
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, &reg->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);
2045 return hr;
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);
2052 return hr;
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);
2060 return hr;
2063 *effect = &object->ID2D1Effect_iface;
2065 TRACE("Created effect %p.\n", *effect);
2067 return S_OK;