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_graph
*impl_from_ID2D1TransformGraph(ID2D1TransformGraph
*iface
)
25 return CONTAINING_RECORD(iface
, struct d2d_transform_graph
, ID2D1TransformGraph_iface
);
28 static HRESULT STDMETHODCALLTYPE
d2d_transform_graph_QueryInterface(ID2D1TransformGraph
*iface
, REFIID iid
, void **out
)
30 TRACE("iface %p, iid %s, out %p.\n", iface
, debugstr_guid(iid
), out
);
32 if (IsEqualGUID(iid
, &IID_ID2D1TransformGraph
)
33 || IsEqualGUID(iid
, &IID_IUnknown
))
35 ID2D1TransformGraph_AddRef(iface
);
44 static ULONG STDMETHODCALLTYPE
d2d_transform_graph_AddRef(ID2D1TransformGraph
*iface
)
46 struct d2d_transform_graph
*graph
=impl_from_ID2D1TransformGraph(iface
);
47 ULONG refcount
= InterlockedIncrement(&graph
->refcount
);
49 TRACE("%p increasing refcount to %lu.\n", iface
, refcount
);
54 static ULONG STDMETHODCALLTYPE
d2d_transform_graph_Release(ID2D1TransformGraph
*iface
)
56 struct d2d_transform_graph
*graph
= impl_from_ID2D1TransformGraph(iface
);
57 ULONG refcount
= InterlockedDecrement(&graph
->refcount
);
59 TRACE("%p decreasing refcount to %lu.\n", iface
, refcount
);
67 static UINT32 STDMETHODCALLTYPE
d2d_transform_graph_GetInputCount(ID2D1TransformGraph
*iface
)
69 FIXME("iface %p stub!\n", iface
);
74 static HRESULT STDMETHODCALLTYPE
d2d_transform_graph_SetSingleTransformNode(ID2D1TransformGraph
*iface
,
75 ID2D1TransformNode
*node
)
77 FIXME("iface %p, node %p stub!\n", iface
, node
);
82 static HRESULT STDMETHODCALLTYPE
d2d_transform_graph_AddNode(ID2D1TransformGraph
*iface
, ID2D1TransformNode
*node
)
84 FIXME("iface %p, node %p stub!\n", iface
, node
);
89 static HRESULT STDMETHODCALLTYPE
d2d_transform_graph_RemoveNode(ID2D1TransformGraph
*iface
, ID2D1TransformNode
*node
)
91 FIXME("iface %p, node %p stub!\n", iface
, node
);
96 static HRESULT STDMETHODCALLTYPE
d2d_transform_graph_SetOutputNode(ID2D1TransformGraph
*iface
, ID2D1TransformNode
*node
)
98 FIXME("iface %p, node %p stub!\n", iface
, node
);
103 static HRESULT STDMETHODCALLTYPE
d2d_transform_graph_ConnectNode(ID2D1TransformGraph
*iface
,
104 ID2D1TransformNode
*from_node
, ID2D1TransformNode
*to_node
, UINT32 index
)
106 FIXME("iface %p, from_node %p, to_node %p, index %u stub!\n", iface
, from_node
, to_node
, index
);
111 static HRESULT STDMETHODCALLTYPE
d2d_transform_graph_ConnectToEffectInput(ID2D1TransformGraph
*iface
,
112 UINT32 input_index
, ID2D1TransformNode
*node
, UINT32 node_index
)
114 FIXME("iface %p, input_index %u, node %p, node_index %u stub!\n", iface
, input_index
, node
, node_index
);
119 static void STDMETHODCALLTYPE
d2d_transform_graph_Clear(ID2D1TransformGraph
*iface
)
121 FIXME("iface %p stub!\n", iface
);
124 static HRESULT STDMETHODCALLTYPE
d2d_transform_graph_SetPassthroughGraph(ID2D1TransformGraph
*iface
, UINT32 index
)
126 FIXME("iface %p, index %u stub!\n", iface
, index
);
131 static const ID2D1TransformGraphVtbl d2d_transform_graph_vtbl
=
133 d2d_transform_graph_QueryInterface
,
134 d2d_transform_graph_AddRef
,
135 d2d_transform_graph_Release
,
136 d2d_transform_graph_GetInputCount
,
137 d2d_transform_graph_SetSingleTransformNode
,
138 d2d_transform_graph_AddNode
,
139 d2d_transform_graph_RemoveNode
,
140 d2d_transform_graph_SetOutputNode
,
141 d2d_transform_graph_ConnectNode
,
142 d2d_transform_graph_ConnectToEffectInput
,
143 d2d_transform_graph_Clear
,
144 d2d_transform_graph_SetPassthroughGraph
,
147 static void d2d_transform_graph_init(struct d2d_transform_graph
*graph
)
149 graph
->ID2D1TransformGraph_iface
.lpVtbl
= &d2d_transform_graph_vtbl
;
153 static HRESULT STDMETHODCALLTYPE
d2d_effect_impl_QueryInterface(ID2D1EffectImpl
*iface
, REFIID iid
, void **out
)
155 TRACE("iface %p, iid %s, out %p.\n", iface
, debugstr_guid(iid
), out
);
157 if (IsEqualGUID(iid
, &IID_ID2D1EffectImpl
)
158 || IsEqualGUID(iid
, &IID_IUnknown
))
160 ID2D1EffectImpl_AddRef(iface
);
166 return E_NOINTERFACE
;
169 static ULONG STDMETHODCALLTYPE
d2d_effect_impl_AddRef(ID2D1EffectImpl
*iface
)
174 static ULONG STDMETHODCALLTYPE
d2d_effect_impl_Release(ID2D1EffectImpl
*iface
)
179 static HRESULT STDMETHODCALLTYPE
d2d_effect_impl_Initialize(ID2D1EffectImpl
*iface
,
180 ID2D1EffectContext
*context
, ID2D1TransformGraph
*graph
)
185 static HRESULT STDMETHODCALLTYPE
d2d_effect_impl_PrepareForRender(ID2D1EffectImpl
*iface
, D2D1_CHANGE_TYPE type
)
190 static HRESULT STDMETHODCALLTYPE
d2d_effect_impl_SetGraph(ID2D1EffectImpl
*iface
, ID2D1TransformGraph
*graph
)
195 static const ID2D1EffectImplVtbl d2d_effect_impl_vtbl
=
197 d2d_effect_impl_QueryInterface
,
198 d2d_effect_impl_AddRef
,
199 d2d_effect_impl_Release
,
200 d2d_effect_impl_Initialize
,
201 d2d_effect_impl_PrepareForRender
,
202 d2d_effect_impl_SetGraph
,
205 static HRESULT STDMETHODCALLTYPE
builtin_factory_stub(IUnknown
**effect_impl
)
207 static ID2D1EffectImpl builtin_stub
= { &d2d_effect_impl_vtbl
};
209 *effect_impl
= (IUnknown
*)&builtin_stub
;
214 static const WCHAR _2d_affine_transform_description
[] =
215 L
"<?xml version='1.0'?> \
217 <Property name='DisplayName' type='string' value='2D Affine Transform'/> \
218 <Property name='Author' type='string' value='The Wine Project'/> \
219 <Property name='Category' type='string' value='Stub'/> \
220 <Property name='Description' type='string' value='2D Affine Transform'/> \
222 <Input name='Source'/> \
226 static const WCHAR _3d_perspective_transform_description
[] =
227 L
"<?xml version='1.0'?> \
229 <Property name='DisplayName' type='string' value='3D Perspective Transform'/> \
230 <Property name='Author' type='string' value='The Wine Project'/> \
231 <Property name='Category' type='string' value='Stub'/> \
232 <Property name='Description' type='string' value='3D Perspective Transform'/> \
234 <Input name='Source'/> \
238 static const WCHAR composite_description
[] =
239 L
"<?xml version='1.0'?> \
241 <Property name='DisplayName' type='string' value='Composite'/> \
242 <Property name='Author' type='string' value='The Wine Project'/> \
243 <Property name='Category' type='string' value='Stub'/> \
244 <Property name='Description' type='string' value='Composite'/> \
245 <Inputs minimum='1' maximum='0xffffffff' > \
246 <Input name='Source1'/> \
247 <Input name='Source2'/> \
251 static const WCHAR crop_description
[] =
252 L
"<?xml version='1.0'?> \
254 <Property name='DisplayName' type='string' value='Crop'/> \
255 <Property name='Author' type='string' value='The Wine Project'/> \
256 <Property name='Category' type='string' value='Stub'/> \
257 <Property name='Description' type='string' value='Crop'/> \
259 <Input name='Source'/> \
263 static const WCHAR shadow_description
[] =
264 L
"<?xml version='1.0'?> \
266 <Property name='DisplayName' type='string' value='Shadow'/> \
267 <Property name='Author' type='string' value='The Wine Project'/> \
268 <Property name='Category' type='string' value='Stub'/> \
269 <Property name='Description' type='string' value='Shadow'/> \
271 <Input name='Source'/> \
275 static const WCHAR grayscale_description
[] =
276 L
"<?xml version='1.0'?> \
278 <Property name='DisplayName' type='string' value='Grayscale'/> \
279 <Property name='Author' type='string' value='The Wine Project'/> \
280 <Property name='Category' type='string' value='Stub'/> \
281 <Property name='Description' type='string' value='Grayscale'/> \
283 <Input name='Source'/> \
287 void d2d_effects_init_builtins(struct d2d_factory
*factory
)
289 static const struct builtin_description
292 const WCHAR
*description
;
296 { &CLSID_D2D12DAffineTransform
, _2d_affine_transform_description
},
297 { &CLSID_D2D13DPerspectiveTransform
, _3d_perspective_transform_description
},
298 { &CLSID_D2D1Composite
, composite_description
},
299 { &CLSID_D2D1Crop
, crop_description
},
300 { &CLSID_D2D1Shadow
, shadow_description
},
301 { &CLSID_D2D1Grayscale
, grayscale_description
},
306 for (i
= 0; i
< ARRAY_SIZE(builtin_effects
); ++i
)
308 if (FAILED(hr
= d2d_factory_register_builtin_effect(factory
, builtin_effects
[i
].clsid
, builtin_effects
[i
].description
,
309 NULL
, 0, builtin_factory_stub
)))
311 WARN("Failed to register the effect %s, hr %#lx.\n", wine_dbgstr_guid(builtin_effects
[i
].clsid
), hr
);
316 /* Same syntax is used for value and default values. */
317 static HRESULT
d2d_effect_parse_float_array(D2D1_PROPERTY_TYPE type
, const WCHAR
*value
,
320 unsigned int i
, num_components
;
323 /* Type values are sequential. */
326 case D2D1_PROPERTY_TYPE_VECTOR2
:
327 case D2D1_PROPERTY_TYPE_VECTOR3
:
328 case D2D1_PROPERTY_TYPE_VECTOR4
:
329 num_components
= (type
- D2D1_PROPERTY_TYPE_VECTOR2
) + 2;
331 case D2D1_PROPERTY_TYPE_MATRIX_3X2
:
334 case D2D1_PROPERTY_TYPE_MATRIX_4X3
:
335 case D2D1_PROPERTY_TYPE_MATRIX_4X4
:
336 case D2D1_PROPERTY_TYPE_MATRIX_5X4
:
337 num_components
= (type
- D2D1_PROPERTY_TYPE_MATRIX_4X3
) * 4 + 12;
343 if (*(value
++) != '(') return E_INVALIDARG
;
345 for (i
= 0; i
< num_components
; ++i
)
347 vec
[i
] = wcstof(value
, &end_ptr
);
348 if (value
== end_ptr
) return E_INVALIDARG
;
351 /* Trailing characters after last component are ignored. */
352 if (i
== num_components
- 1) continue;
353 if (*(value
++) != ',') return E_INVALIDARG
;
359 static HRESULT
d2d_effect_properties_internal_add(struct d2d_effect_properties
*props
,
360 const WCHAR
*name
, UINT32 index
, BOOL subprop
, D2D1_PROPERTY_TYPE type
, const WCHAR
*value
)
362 static const UINT32 sizes
[] =
364 0, /* D2D1_PROPERTY_TYPE_UNKNOWN */
365 0, /* D2D1_PROPERTY_TYPE_STRING */
366 sizeof(BOOL
), /* D2D1_PROPERTY_TYPE_BOOL */
367 sizeof(UINT32
), /* D2D1_PROPERTY_TYPE_UINT32 */
368 sizeof(INT32
), /* D2D1_PROPERTY_TYPE_INT32 */
369 sizeof(float), /* D2D1_PROPERTY_TYPE_FLOAT */
370 2 * sizeof(float), /* D2D1_PROPERTY_TYPE_VECTOR2 */
371 3 * sizeof(float), /* D2D1_PROPERTY_TYPE_VECTOR3 */
372 4 * sizeof(float), /* D2D1_PROPERTY_TYPE_VECTOR4 */
373 0, /* FIXME: D2D1_PROPERTY_TYPE_BLOB */
374 sizeof(void *), /* D2D1_PROPERTY_TYPE_IUNKNOWN */
375 sizeof(UINT32
), /* D2D1_PROPERTY_TYPE_ENUM */
376 sizeof(UINT32
), /* D2D1_PROPERTY_TYPE_ARRAY */
377 sizeof(CLSID
), /* D2D1_PROPERTY_TYPE_CLSID */
378 6 * sizeof(float), /* D2D1_PROPERTY_TYPE_MATRIX_3X2 */
379 12 * sizeof(float), /* D2D1_PROPERTY_TYPE_MATRIX_4X3 */
380 16 * sizeof(float), /* D2D1_PROPERTY_TYPE_MATRIX_4X4 */
381 20 * sizeof(float), /* D2D1_PROPERTY_TYPE_MATRIX_5X4 */
382 sizeof(void *), /* D2D1_PROPERTY_TYPE_COLOR_CONTEXT */
384 struct d2d_effect_property
*p
;
387 assert(type
>= D2D1_PROPERTY_TYPE_STRING
&& type
<= D2D1_PROPERTY_TYPE_COLOR_CONTEXT
);
389 if (type
== D2D1_PROPERTY_TYPE_BLOB
)
391 FIXME("Ignoring property %s of type %u.\n", wine_dbgstr_w(name
), type
);
395 if (!d2d_array_reserve((void **)&props
->properties
, &props
->size
, props
->count
+ 1,
396 sizeof(*props
->properties
)))
398 return E_OUTOFMEMORY
;
401 /* TODO: we could save some space for properties that have both getter and setter. */
402 if (!d2d_array_reserve((void **)&props
->data
.ptr
, &props
->data
.size
,
403 props
->data
.count
+ sizes
[type
], sizeof(*props
->data
.ptr
)))
405 return E_OUTOFMEMORY
;
407 props
->data
.count
+= sizes
[type
];
409 p
= &props
->properties
[props
->count
++];
410 memset(p
, 0, sizeof(*p
));
412 if (p
->index
< 0x80000000)
414 props
->custom_count
++;
415 /* FIXME: this should probably be controlled by subproperty */
421 p
->readonly
= index
!= D2D1_PROPERTY_CACHED
&& index
!= D2D1_PROPERTY_PRECISION
;
422 p
->name
= wcsdup(name
);
424 if (p
->type
== D2D1_PROPERTY_TYPE_STRING
&& value
)
426 p
->data
.ptr
= wcsdup(value
);
427 p
->size
= (wcslen(value
) + 1) * sizeof(WCHAR
);
437 p
->data
.offset
= props
->offset
;
438 p
->size
= sizes
[type
];
439 props
->offset
+= p
->size
;
445 case D2D1_PROPERTY_TYPE_UINT32
:
446 case D2D1_PROPERTY_TYPE_INT32
:
447 _uint32
= wcstoul(value
, NULL
, 0);
450 case D2D1_PROPERTY_TYPE_ENUM
:
451 _uint32
= wcstoul(value
, NULL
, 10);
454 case D2D1_PROPERTY_TYPE_BOOL
:
455 if (!wcscmp(value
, L
"true")) _bool
= TRUE
;
456 else if (!wcscmp(value
, L
"false")) _bool
= FALSE
;
457 else return E_INVALIDARG
;
460 case D2D1_PROPERTY_TYPE_CLSID
:
461 CLSIDFromString(value
, &_clsid
);
464 case D2D1_PROPERTY_TYPE_VECTOR2
:
465 case D2D1_PROPERTY_TYPE_VECTOR3
:
466 case D2D1_PROPERTY_TYPE_VECTOR4
:
467 case D2D1_PROPERTY_TYPE_MATRIX_3X2
:
468 case D2D1_PROPERTY_TYPE_MATRIX_4X3
:
469 case D2D1_PROPERTY_TYPE_MATRIX_4X4
:
470 case D2D1_PROPERTY_TYPE_MATRIX_5X4
:
471 if (FAILED(hr
= d2d_effect_parse_float_array(p
->type
, value
, _vec
)))
473 WARN("Failed to parse float array %s for type %u.\n",
474 wine_dbgstr_w(value
), p
->type
);
479 case D2D1_PROPERTY_TYPE_IUNKNOWN
:
480 case D2D1_PROPERTY_TYPE_COLOR_CONTEXT
:
483 FIXME("Initial value for property type %u is not handled.\n", p
->type
);
486 if (src
&& p
->size
) memcpy(props
->data
.ptr
+ p
->data
.offset
, src
, p
->size
);
489 memset(props
->data
.ptr
+ p
->data
.offset
, 0, p
->size
);
495 HRESULT
d2d_effect_properties_add(struct d2d_effect_properties
*props
, const WCHAR
*name
,
496 UINT32 index
, D2D1_PROPERTY_TYPE type
, const WCHAR
*value
)
498 return d2d_effect_properties_internal_add(props
, name
, index
, FALSE
, type
, value
);
501 HRESULT
d2d_effect_subproperties_add(struct d2d_effect_properties
*props
, const WCHAR
*name
,
502 UINT32 index
, D2D1_PROPERTY_TYPE type
, const WCHAR
*value
)
504 return d2d_effect_properties_internal_add(props
, name
, index
, TRUE
, type
, value
);
507 static HRESULT
d2d_effect_duplicate_properties(struct d2d_effect_properties
*dst
,
508 const struct d2d_effect_properties
*src
)
513 memset(dst
, 0, sizeof(*dst
));
514 dst
->offset
= src
->offset
;
515 dst
->size
= src
->count
;
516 dst
->count
= src
->count
;
517 dst
->custom_count
= src
->custom_count
;
518 dst
->data
.size
= src
->data
.count
;
519 dst
->data
.count
= src
->data
.count
;
521 if (!(dst
->data
.ptr
= malloc(dst
->data
.size
)))
522 return E_OUTOFMEMORY
;
523 memcpy(dst
->data
.ptr
, src
->data
.ptr
, dst
->data
.size
);
525 if (!(dst
->properties
= calloc(dst
->size
, sizeof(*dst
->properties
))))
526 return E_OUTOFMEMORY
;
528 for (i
= 0; i
< dst
->count
; ++i
)
530 struct d2d_effect_property
*d
= &dst
->properties
[i
];
531 const struct d2d_effect_property
*s
= &src
->properties
[i
];
534 d
->name
= wcsdup(s
->name
);
535 if (d
->type
== D2D1_PROPERTY_TYPE_STRING
)
536 d
->data
.ptr
= wcsdup((WCHAR
*)s
->data
.ptr
);
538 if (s
->subproperties
)
540 if (!(d
->subproperties
= calloc(1, sizeof(*d
->subproperties
))))
541 return E_OUTOFMEMORY
;
542 if (FAILED(hr
= d2d_effect_duplicate_properties(d
->subproperties
, s
->subproperties
)))
550 static struct d2d_effect_property
* d2d_effect_properties_get_property_by_index(
551 const struct d2d_effect_properties
*properties
, UINT32 index
)
555 for (i
= 0; i
< properties
->count
; ++i
)
557 if (properties
->properties
[i
].index
== index
)
558 return &properties
->properties
[i
];
564 struct d2d_effect_property
* d2d_effect_properties_get_property_by_name(
565 const struct d2d_effect_properties
*properties
, const WCHAR
*name
)
569 for (i
= 0; i
< properties
->count
; ++i
)
571 if (!wcscmp(properties
->properties
[i
].name
, name
))
572 return &properties
->properties
[i
];
578 static UINT32
d2d_effect_properties_get_value_size(const struct d2d_effect_properties
*properties
,
581 struct d2d_effect
*effect
= properties
->effect
;
582 struct d2d_effect_property
*prop
;
585 if (!(prop
= d2d_effect_properties_get_property_by_index(properties
, index
)))
588 if (prop
->get_function
)
590 if (FAILED(prop
->get_function((IUnknown
*)effect
->impl
, NULL
, 0, &size
))) return 0;
597 static HRESULT
d2d_effect_return_string(const WCHAR
*str
, WCHAR
*buffer
, UINT32 buffer_size
)
599 UINT32 size
= str
? wcslen(str
) : 0;
600 if (size
>= buffer_size
) return D2DERR_INSUFFICIENT_BUFFER
;
601 if (str
) memcpy(buffer
, str
, (size
+ 1) * sizeof(*buffer
));
606 static HRESULT
d2d_effect_property_get_value(const struct d2d_effect_properties
*properties
,
607 const struct d2d_effect_property
*prop
, D2D1_PROPERTY_TYPE type
, BYTE
*value
, UINT32 size
)
609 struct d2d_effect
*effect
= properties
->effect
;
612 if (type
!= D2D1_PROPERTY_TYPE_UNKNOWN
&& prop
->type
!= type
) return E_INVALIDARG
;
613 if (prop
->type
!= D2D1_PROPERTY_TYPE_STRING
&& prop
->size
!= size
) return E_INVALIDARG
;
615 if (prop
->get_function
)
616 return prop
->get_function((IUnknown
*)effect
->impl
, value
, size
, &actual_size
);
620 case D2D1_PROPERTY_TYPE_BLOB
:
621 FIXME("Unimplemented for type %u.\n", prop
->type
);
623 case D2D1_PROPERTY_TYPE_STRING
:
624 return d2d_effect_return_string(prop
->data
.ptr
, (WCHAR
*)value
, size
/ sizeof(WCHAR
));
626 memcpy(value
, properties
->data
.ptr
+ prop
->data
.offset
, size
);
633 HRESULT
d2d_effect_property_get_uint32_value(const struct d2d_effect_properties
*properties
,
634 const struct d2d_effect_property
*prop
, UINT32
*value
)
636 return d2d_effect_property_get_value(properties
, prop
, D2D1_PROPERTY_TYPE_UINT32
,
637 (BYTE
*)value
, sizeof(*value
));
640 static HRESULT
d2d_effect_property_set_value(struct d2d_effect_properties
*properties
,
641 struct d2d_effect_property
*prop
, D2D1_PROPERTY_TYPE type
, const BYTE
*value
, UINT32 size
)
643 struct d2d_effect
*effect
= properties
->effect
;
644 if (prop
->readonly
) return E_INVALIDARG
;
645 if (type
!= D2D1_PROPERTY_TYPE_UNKNOWN
&& prop
->type
!= type
) return E_INVALIDARG
;
646 if (prop
->get_function
&& !prop
->set_function
) return E_INVALIDARG
;
647 if (prop
->index
< 0x80000000 && !prop
->set_function
) return E_INVALIDARG
;
649 if (prop
->set_function
)
650 return prop
->set_function((IUnknown
*)effect
->impl
, value
, size
);
652 if (prop
->size
!= size
) return E_INVALIDARG
;
656 case D2D1_PROPERTY_TYPE_BOOL
:
657 case D2D1_PROPERTY_TYPE_UINT32
:
658 case D2D1_PROPERTY_TYPE_ENUM
:
659 memcpy(properties
->data
.ptr
+ prop
->data
.offset
, value
, size
);
662 FIXME("Unhandled type %u.\n", prop
->type
);
668 void d2d_effect_properties_cleanup(struct d2d_effect_properties
*props
)
670 struct d2d_effect_property
*p
;
673 for (i
= 0; i
< props
->count
; ++i
)
675 p
= &props
->properties
[i
];
677 if (p
->type
== D2D1_PROPERTY_TYPE_STRING
)
679 if (p
->subproperties
)
681 d2d_effect_properties_cleanup(p
->subproperties
);
682 free(p
->subproperties
);
685 free(props
->properties
);
686 free(props
->data
.ptr
);
689 static inline struct d2d_effect_context
*impl_from_ID2D1EffectContext(ID2D1EffectContext
*iface
)
691 return CONTAINING_RECORD(iface
, struct d2d_effect_context
, ID2D1EffectContext_iface
);
694 static HRESULT STDMETHODCALLTYPE
d2d_effect_context_QueryInterface(ID2D1EffectContext
*iface
, REFIID iid
, void **out
)
696 TRACE("iface %p, iid %s, out %p.\n", iface
, debugstr_guid(iid
), out
);
698 if (IsEqualGUID(iid
, &IID_ID2D1EffectContext
)
699 || IsEqualGUID(iid
, &IID_IUnknown
))
701 ID2D1EffectContext_AddRef(iface
);
706 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid
));
709 return E_NOINTERFACE
;
712 static ULONG STDMETHODCALLTYPE
d2d_effect_context_AddRef(ID2D1EffectContext
*iface
)
714 struct d2d_effect_context
*effect_context
= impl_from_ID2D1EffectContext(iface
);
715 ULONG refcount
= InterlockedIncrement(&effect_context
->refcount
);
717 TRACE("%p increasing refcount to %lu.\n", iface
, refcount
);
722 static ULONG STDMETHODCALLTYPE
d2d_effect_context_Release(ID2D1EffectContext
*iface
)
724 struct d2d_effect_context
*effect_context
= impl_from_ID2D1EffectContext(iface
);
725 ULONG refcount
= InterlockedDecrement(&effect_context
->refcount
);
727 TRACE("%p decreasing refcount to %lu.\n", iface
, refcount
);
731 ID2D1DeviceContext1_Release(&effect_context
->device_context
->ID2D1DeviceContext1_iface
);
732 free(effect_context
);
738 static void STDMETHODCALLTYPE
d2d_effect_context_GetDpi(ID2D1EffectContext
*iface
, float *dpi_x
, float *dpi_y
)
740 struct d2d_effect_context
*effect_context
= impl_from_ID2D1EffectContext(iface
);
742 TRACE("iface %p, dpi_x %p, dpi_y %p.\n", iface
, dpi_x
, dpi_y
);
744 ID2D1DeviceContext1_GetDpi(&effect_context
->device_context
->ID2D1DeviceContext1_iface
, dpi_x
, dpi_y
);
747 static HRESULT STDMETHODCALLTYPE
d2d_effect_context_CreateEffect(ID2D1EffectContext
*iface
,
748 REFCLSID clsid
, ID2D1Effect
**effect
)
750 struct d2d_effect_context
*effect_context
= impl_from_ID2D1EffectContext(iface
);
752 TRACE("iface %p, clsid %s, effect %p.\n", iface
, debugstr_guid(clsid
), effect
);
754 return ID2D1DeviceContext1_CreateEffect(&effect_context
->device_context
->ID2D1DeviceContext1_iface
,
758 static HRESULT STDMETHODCALLTYPE
d2d_effect_context_GetMaximumSupportedFeatureLevel(ID2D1EffectContext
*iface
,
759 const D3D_FEATURE_LEVEL
*levels
, UINT32 level_count
, D3D_FEATURE_LEVEL
*max_level
)
761 FIXME("iface %p, levels %p, level_count %u, max_level %p stub!\n", iface
, levels
, level_count
, max_level
);
766 static HRESULT STDMETHODCALLTYPE
d2d_effect_context_CreateTransformNodeFromEffect(ID2D1EffectContext
*iface
,
767 ID2D1Effect
*effect
, ID2D1TransformNode
**node
)
769 FIXME("iface %p, effect %p, node %p stub!\n", iface
, effect
, node
);
774 static HRESULT STDMETHODCALLTYPE
d2d_effect_context_CreateBlendTransform(ID2D1EffectContext
*iface
,
775 UINT32 num_inputs
, const D2D1_BLEND_DESCRIPTION
*description
, ID2D1BlendTransform
**transform
)
777 FIXME("iface %p, num_inputs %u, description %p, transform %p stub!\n", iface
, num_inputs
, description
, transform
);
782 static HRESULT STDMETHODCALLTYPE
d2d_effect_context_CreateBorderTransform(ID2D1EffectContext
*iface
,
783 D2D1_EXTEND_MODE mode_x
, D2D1_EXTEND_MODE mode_y
, ID2D1BorderTransform
**transform
)
785 FIXME("iface %p, mode_x %#x, mode_y %#x, transform %p stub!\n", iface
, mode_x
, mode_y
, transform
);
790 static HRESULT STDMETHODCALLTYPE
d2d_effect_context_CreateOffsetTransform(ID2D1EffectContext
*iface
,
791 D2D1_POINT_2L offset
, ID2D1OffsetTransform
**transform
)
793 FIXME("iface %p, offset %s, transform %p stub!\n", iface
, debug_d2d_point_2l(&offset
), transform
);
798 static HRESULT STDMETHODCALLTYPE
d2d_effect_context_CreateBoundsAdjustmentTransform(ID2D1EffectContext
*iface
,
799 const D2D1_RECT_L
*output_rect
, ID2D1BoundsAdjustmentTransform
**transform
)
801 FIXME("iface %p, output_rect %s, transform %p stub!\n", iface
, debug_d2d_rect_l(output_rect
), transform
);
806 static HRESULT STDMETHODCALLTYPE
d2d_effect_context_LoadPixelShader(ID2D1EffectContext
*iface
,
807 REFGUID shader_id
, const BYTE
*buffer
, UINT32 buffer_size
)
809 struct d2d_effect_context
*effect_context
= impl_from_ID2D1EffectContext(iface
);
810 ID3D11PixelShader
*shader
;
813 TRACE("iface %p, shader_id %s, buffer %p, buffer_size %u.\n",
814 iface
, debugstr_guid(shader_id
), buffer
, buffer_size
);
816 if (ID2D1EffectContext_IsShaderLoaded(iface
, shader_id
))
819 if (FAILED(hr
= ID3D11Device1_CreatePixelShader(effect_context
->device_context
->d3d_device
,
820 buffer
, buffer_size
, NULL
, &shader
)))
822 WARN("Failed to create a pixel shader, hr %#lx.\n", hr
);
826 hr
= d2d_device_add_shader(effect_context
->device_context
->device
, shader_id
, (IUnknown
*)shader
);
827 ID3D11PixelShader_Release(shader
);
832 static HRESULT STDMETHODCALLTYPE
d2d_effect_context_LoadVertexShader(ID2D1EffectContext
*iface
,
833 REFGUID shader_id
, const BYTE
*buffer
, UINT32 buffer_size
)
835 struct d2d_effect_context
*effect_context
= impl_from_ID2D1EffectContext(iface
);
836 ID3D11VertexShader
*shader
;
839 TRACE("iface %p, shader_id %s, buffer %p, buffer_size %u.\n",
840 iface
, debugstr_guid(shader_id
), buffer
, buffer_size
);
842 if (ID2D1EffectContext_IsShaderLoaded(iface
, shader_id
))
845 if (FAILED(hr
= ID3D11Device1_CreateVertexShader(effect_context
->device_context
->d3d_device
,
846 buffer
, buffer_size
, NULL
, &shader
)))
848 WARN("Failed to create vertex shader, hr %#lx.\n", hr
);
852 hr
= d2d_device_add_shader(effect_context
->device_context
->device
, shader_id
, (IUnknown
*)shader
);
853 ID3D11VertexShader_Release(shader
);
858 static HRESULT STDMETHODCALLTYPE
d2d_effect_context_LoadComputeShader(ID2D1EffectContext
*iface
,
859 REFGUID shader_id
, const BYTE
*buffer
, UINT32 buffer_size
)
861 struct d2d_effect_context
*effect_context
= impl_from_ID2D1EffectContext(iface
);
862 ID3D11ComputeShader
*shader
;
865 TRACE("iface %p, shader_id %s, buffer %p, buffer_size %u.\n",
866 iface
, debugstr_guid(shader_id
), buffer
, buffer_size
);
868 if (ID2D1EffectContext_IsShaderLoaded(iface
, shader_id
))
871 if (FAILED(hr
= ID3D11Device1_CreateComputeShader(effect_context
->device_context
->d3d_device
,
872 buffer
, buffer_size
, NULL
, &shader
)))
874 WARN("Failed to create a compute shader, hr %#lx.\n", hr
);
878 hr
= d2d_device_add_shader(effect_context
->device_context
->device
, shader_id
, (IUnknown
*)shader
);
879 ID3D11ComputeShader_Release(shader
);
884 static BOOL STDMETHODCALLTYPE
d2d_effect_context_IsShaderLoaded(ID2D1EffectContext
*iface
, REFGUID shader_id
)
886 struct d2d_effect_context
*effect_context
= impl_from_ID2D1EffectContext(iface
);
888 TRACE("iface %p, shader_id %s.\n", iface
, debugstr_guid(shader_id
));
890 return d2d_device_is_shader_loaded(effect_context
->device_context
->device
, shader_id
);
893 static HRESULT STDMETHODCALLTYPE
d2d_effect_context_CreateResourceTexture(ID2D1EffectContext
*iface
,
894 const GUID
*id
, const D2D1_RESOURCE_TEXTURE_PROPERTIES
*texture_properties
,
895 const BYTE
*data
, const UINT32
*strides
, UINT32 data_size
, ID2D1ResourceTexture
**texture
)
897 FIXME("iface %p, id %s, texture_properties %p, data %p, strides %p, data_size %u, texture %p stub!\n",
898 iface
, debugstr_guid(id
), texture_properties
, data
, strides
, data_size
, texture
);
903 static HRESULT STDMETHODCALLTYPE
d2d_effect_context_FindResourceTexture(ID2D1EffectContext
*iface
,
904 const GUID
*id
, ID2D1ResourceTexture
**texture
)
906 FIXME("iface %p, id %s, texture %p stub!\n", iface
, debugstr_guid(id
), texture
);
911 static HRESULT STDMETHODCALLTYPE
d2d_effect_context_CreateVertexBuffer(ID2D1EffectContext
*iface
,
912 const D2D1_VERTEX_BUFFER_PROPERTIES
*buffer_properties
, const GUID
*id
,
913 const D2D1_CUSTOM_VERTEX_BUFFER_PROPERTIES
*custom_buffer_properties
, ID2D1VertexBuffer
**buffer
)
915 FIXME("iface %p, buffer_properties %p, id %s, custom_buffer_properties %p, buffer %p stub!\n",
916 iface
, buffer_properties
, debugstr_guid(id
), custom_buffer_properties
, buffer
);
921 static HRESULT STDMETHODCALLTYPE
d2d_effect_context_FindVertexBuffer(ID2D1EffectContext
*iface
,
922 const GUID
*id
, ID2D1VertexBuffer
**buffer
)
924 FIXME("iface %p, id %s, buffer %p stub!\n", iface
, debugstr_guid(id
), buffer
);
929 static HRESULT STDMETHODCALLTYPE
d2d_effect_context_CreateColorContext(ID2D1EffectContext
*iface
,
930 D2D1_COLOR_SPACE space
, const BYTE
*profile
, UINT32 profile_size
, ID2D1ColorContext
**color_context
)
932 struct d2d_effect_context
*effect_context
= impl_from_ID2D1EffectContext(iface
);
934 TRACE("iface %p, space %#x, profile %p, profile_size %u, color_context %p.\n",
935 iface
, space
, profile
, profile_size
, color_context
);
937 return ID2D1DeviceContext1_CreateColorContext(&effect_context
->device_context
->ID2D1DeviceContext1_iface
,
938 space
, profile
, profile_size
, color_context
);
941 static HRESULT STDMETHODCALLTYPE
d2d_effect_context_CreateColorContextFromFilename(ID2D1EffectContext
*iface
,
942 const WCHAR
*filename
, ID2D1ColorContext
**color_context
)
944 struct d2d_effect_context
*effect_context
= impl_from_ID2D1EffectContext(iface
);
946 TRACE("iface %p, filename %s, color_context %p.\n", iface
, debugstr_w(filename
), color_context
);
948 return ID2D1DeviceContext1_CreateColorContextFromFilename(&effect_context
->device_context
->ID2D1DeviceContext1_iface
,
949 filename
, color_context
);
952 static HRESULT STDMETHODCALLTYPE
d2d_effect_context_CreateColorContextFromWicColorContext(ID2D1EffectContext
*iface
,
953 IWICColorContext
*wic_color_context
, ID2D1ColorContext
**color_context
)
955 struct d2d_effect_context
*effect_context
= impl_from_ID2D1EffectContext(iface
);
957 TRACE("iface %p, wic_color_context %p, color_context %p.\n", iface
, wic_color_context
, color_context
);
959 return ID2D1DeviceContext1_CreateColorContextFromWicColorContext(&effect_context
->device_context
->ID2D1DeviceContext1_iface
,
960 wic_color_context
, color_context
);
963 static HRESULT STDMETHODCALLTYPE
d2d_effect_context_CheckFeatureSupport(ID2D1EffectContext
*iface
,
964 D2D1_FEATURE feature
, void *data
, UINT32 data_size
)
966 struct d2d_effect_context
*effect_context
= impl_from_ID2D1EffectContext(iface
);
967 D3D11_FEATURE d3d11_feature
;
969 TRACE("iface %p, feature %#x, data %p, data_size %u.\n", iface
, feature
, data
, data_size
);
971 /* Data structures are compatible. */
974 case D2D1_FEATURE_DOUBLES
: d3d11_feature
= D3D11_FEATURE_DOUBLES
; break;
975 case D2D1_FEATURE_D3D10_X_HARDWARE_OPTIONS
: d3d11_feature
= D3D11_FEATURE_D3D10_X_HARDWARE_OPTIONS
; break;
977 WARN("Unexpected feature index %d.\n", feature
);
981 return ID3D11Device1_CheckFeatureSupport(effect_context
->device_context
->d3d_device
,
982 d3d11_feature
, data
, data_size
);
985 static BOOL STDMETHODCALLTYPE
d2d_effect_context_IsBufferPrecisionSupported(ID2D1EffectContext
*iface
,
986 D2D1_BUFFER_PRECISION precision
)
988 struct d2d_effect_context
*effect_context
= impl_from_ID2D1EffectContext(iface
);
990 TRACE("iface %p, precision %u.\n", iface
, precision
);
992 return ID2D1DeviceContext1_IsBufferPrecisionSupported(&effect_context
->device_context
->ID2D1DeviceContext1_iface
,
996 static const ID2D1EffectContextVtbl d2d_effect_context_vtbl
=
998 d2d_effect_context_QueryInterface
,
999 d2d_effect_context_AddRef
,
1000 d2d_effect_context_Release
,
1001 d2d_effect_context_GetDpi
,
1002 d2d_effect_context_CreateEffect
,
1003 d2d_effect_context_GetMaximumSupportedFeatureLevel
,
1004 d2d_effect_context_CreateTransformNodeFromEffect
,
1005 d2d_effect_context_CreateBlendTransform
,
1006 d2d_effect_context_CreateBorderTransform
,
1007 d2d_effect_context_CreateOffsetTransform
,
1008 d2d_effect_context_CreateBoundsAdjustmentTransform
,
1009 d2d_effect_context_LoadPixelShader
,
1010 d2d_effect_context_LoadVertexShader
,
1011 d2d_effect_context_LoadComputeShader
,
1012 d2d_effect_context_IsShaderLoaded
,
1013 d2d_effect_context_CreateResourceTexture
,
1014 d2d_effect_context_FindResourceTexture
,
1015 d2d_effect_context_CreateVertexBuffer
,
1016 d2d_effect_context_FindVertexBuffer
,
1017 d2d_effect_context_CreateColorContext
,
1018 d2d_effect_context_CreateColorContextFromFilename
,
1019 d2d_effect_context_CreateColorContextFromWicColorContext
,
1020 d2d_effect_context_CheckFeatureSupport
,
1021 d2d_effect_context_IsBufferPrecisionSupported
,
1024 void d2d_effect_context_init(struct d2d_effect_context
*effect_context
, struct d2d_device_context
*device_context
)
1026 effect_context
->ID2D1EffectContext_iface
.lpVtbl
= &d2d_effect_context_vtbl
;
1027 effect_context
->refcount
= 1;
1028 effect_context
->device_context
= device_context
;
1029 ID2D1DeviceContext1_AddRef(&device_context
->ID2D1DeviceContext1_iface
);
1032 static inline struct d2d_effect
*impl_from_ID2D1Effect(ID2D1Effect
*iface
)
1034 return CONTAINING_RECORD(iface
, struct d2d_effect
, ID2D1Effect_iface
);
1037 static void d2d_effect_cleanup(struct d2d_effect
*effect
)
1041 for (i
= 0; i
< effect
->input_count
; ++i
)
1043 if (effect
->inputs
[i
])
1044 ID2D1Image_Release(effect
->inputs
[i
]);
1046 free(effect
->inputs
);
1047 ID2D1EffectContext_Release(&effect
->effect_context
->ID2D1EffectContext_iface
);
1049 ID2D1TransformGraph_Release(&effect
->graph
->ID2D1TransformGraph_iface
);
1050 d2d_effect_properties_cleanup(&effect
->properties
);
1052 ID2D1EffectImpl_Release(effect
->impl
);
1055 static HRESULT STDMETHODCALLTYPE
d2d_effect_QueryInterface(ID2D1Effect
*iface
, REFIID iid
, void **out
)
1057 struct d2d_effect
*effect
= impl_from_ID2D1Effect(iface
);
1058 TRACE("iface %p, iid %s, out %p.\n", iface
, debugstr_guid(iid
), out
);
1060 if (IsEqualGUID(iid
, &IID_ID2D1Effect
)
1061 || IsEqualGUID(iid
, &IID_ID2D1Properties
)
1062 || IsEqualGUID(iid
, &IID_IUnknown
))
1064 ID2D1Effect_AddRef(iface
);
1069 if (IsEqualGUID(iid
, &IID_ID2D1Image
)
1070 || IsEqualGUID(iid
, &IID_ID2D1Resource
))
1072 ID2D1Image_AddRef(&effect
->ID2D1Image_iface
);
1073 *out
= &effect
->ID2D1Image_iface
;
1077 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid
));
1080 return E_NOINTERFACE
;
1083 static ULONG STDMETHODCALLTYPE
d2d_effect_AddRef(ID2D1Effect
*iface
)
1085 struct d2d_effect
*effect
= impl_from_ID2D1Effect(iface
);
1086 ULONG refcount
= InterlockedIncrement(&effect
->refcount
);
1088 TRACE("%p increasing refcount to %lu.\n", iface
, refcount
);
1093 static ULONG STDMETHODCALLTYPE
d2d_effect_Release(ID2D1Effect
*iface
)
1095 struct d2d_effect
*effect
= impl_from_ID2D1Effect(iface
);
1096 ULONG refcount
= InterlockedDecrement(&effect
->refcount
);
1098 TRACE("%p decreasing refcount to %lu.\n", iface
, refcount
);
1102 d2d_effect_cleanup(effect
);
1109 static UINT32 STDMETHODCALLTYPE
d2d_effect_GetPropertyCount(ID2D1Effect
*iface
)
1111 struct d2d_effect
*effect
= impl_from_ID2D1Effect(iface
);
1113 TRACE("iface %p.\n", iface
);
1115 return ID2D1Properties_GetPropertyCount(&effect
->properties
.ID2D1Properties_iface
);
1118 static HRESULT STDMETHODCALLTYPE
d2d_effect_GetPropertyName(ID2D1Effect
*iface
, UINT32 index
,
1119 WCHAR
*name
, UINT32 name_count
)
1121 struct d2d_effect
*effect
= impl_from_ID2D1Effect(iface
);
1123 TRACE("iface %p, index %u, name %p, name_count %u.\n", iface
, index
, name
, name_count
);
1125 return ID2D1Properties_GetPropertyName(&effect
->properties
.ID2D1Properties_iface
,
1126 index
, name
, name_count
);
1129 static UINT32 STDMETHODCALLTYPE
d2d_effect_GetPropertyNameLength(ID2D1Effect
*iface
, UINT32 index
)
1131 struct d2d_effect
*effect
= impl_from_ID2D1Effect(iface
);
1133 TRACE("iface %p, index %u.\n", iface
, index
);
1135 return ID2D1Properties_GetPropertyNameLength(&effect
->properties
.ID2D1Properties_iface
, index
);
1138 static D2D1_PROPERTY_TYPE STDMETHODCALLTYPE
d2d_effect_GetType(ID2D1Effect
*iface
, UINT32 index
)
1140 struct d2d_effect
*effect
= impl_from_ID2D1Effect(iface
);
1142 TRACE("iface %p, index %#x.\n", iface
, index
);
1144 return ID2D1Properties_GetType(&effect
->properties
.ID2D1Properties_iface
, index
);
1147 static UINT32 STDMETHODCALLTYPE
d2d_effect_GetPropertyIndex(ID2D1Effect
*iface
, const WCHAR
*name
)
1149 struct d2d_effect
*effect
= impl_from_ID2D1Effect(iface
);
1151 TRACE("iface %p, name %s.\n", iface
, debugstr_w(name
));
1153 return ID2D1Properties_GetPropertyIndex(&effect
->properties
.ID2D1Properties_iface
, name
);
1156 static HRESULT STDMETHODCALLTYPE
d2d_effect_SetValueByName(ID2D1Effect
*iface
, const WCHAR
*name
,
1157 D2D1_PROPERTY_TYPE type
, const BYTE
*value
, UINT32 value_size
)
1159 struct d2d_effect
*effect
= impl_from_ID2D1Effect(iface
);
1161 TRACE("iface %p, name %s, type %u, value %p, value_size %u.\n", iface
, debugstr_w(name
),
1162 type
, value
, value_size
);
1164 return ID2D1Properties_SetValueByName(&effect
->properties
.ID2D1Properties_iface
, name
,
1165 type
, value
, value_size
);
1168 static HRESULT STDMETHODCALLTYPE
d2d_effect_SetValue(ID2D1Effect
*iface
, UINT32 index
, D2D1_PROPERTY_TYPE type
,
1169 const BYTE
*value
, UINT32 value_size
)
1171 struct d2d_effect
*effect
= impl_from_ID2D1Effect(iface
);
1173 TRACE("iface %p, index %#x, type %u, value %p, value_size %u.\n", iface
, index
, type
, value
, value_size
);
1175 return ID2D1Properties_SetValue(&effect
->properties
.ID2D1Properties_iface
, index
, type
,
1179 static HRESULT STDMETHODCALLTYPE
d2d_effect_GetValueByName(ID2D1Effect
*iface
, const WCHAR
*name
,
1180 D2D1_PROPERTY_TYPE type
, BYTE
*value
, UINT32 value_size
)
1182 struct d2d_effect
*effect
= impl_from_ID2D1Effect(iface
);
1184 TRACE("iface %p, name %s, type %#x, value %p, value_size %u.\n", iface
, debugstr_w(name
), type
,
1187 return ID2D1Properties_GetValueByName(&effect
->properties
.ID2D1Properties_iface
, name
, type
,
1191 static HRESULT
d2d_effect_get_value(struct d2d_effect
*effect
, UINT32 index
, D2D1_PROPERTY_TYPE type
,
1192 BYTE
*value
, UINT32 value_size
)
1194 return ID2D1Properties_GetValue(&effect
->properties
.ID2D1Properties_iface
, index
, type
, value
, value_size
);
1197 static HRESULT STDMETHODCALLTYPE
d2d_effect_GetValue(ID2D1Effect
*iface
, UINT32 index
, D2D1_PROPERTY_TYPE type
,
1198 BYTE
*value
, UINT32 value_size
)
1200 struct d2d_effect
*effect
= impl_from_ID2D1Effect(iface
);
1202 TRACE("iface %p, index %#x, type %u, value %p, value_size %u.\n", iface
, index
, type
, value
, value_size
);
1204 return d2d_effect_get_value(effect
, index
, type
, value
, value_size
);
1207 static UINT32 STDMETHODCALLTYPE
d2d_effect_GetValueSize(ID2D1Effect
*iface
, UINT32 index
)
1209 struct d2d_effect
*effect
= impl_from_ID2D1Effect(iface
);
1211 TRACE("iface %p, index %#x.\n", iface
, index
);
1213 return ID2D1Properties_GetValueSize(&effect
->properties
.ID2D1Properties_iface
, index
);
1216 static HRESULT STDMETHODCALLTYPE
d2d_effect_GetSubProperties(ID2D1Effect
*iface
, UINT32 index
,
1217 ID2D1Properties
**props
)
1219 struct d2d_effect
*effect
= impl_from_ID2D1Effect(iface
);
1221 TRACE("iface %p, index %u, props %p.\n", iface
, index
, props
);
1223 return ID2D1Properties_GetSubProperties(&effect
->properties
.ID2D1Properties_iface
, index
, props
);
1226 static void STDMETHODCALLTYPE
d2d_effect_SetInput(ID2D1Effect
*iface
, UINT32 index
, ID2D1Image
*input
, BOOL invalidate
)
1228 struct d2d_effect
*effect
= impl_from_ID2D1Effect(iface
);
1230 TRACE("iface %p, index %u, input %p, invalidate %#x.\n", iface
, index
, input
, invalidate
);
1232 if (index
>= effect
->input_count
)
1235 ID2D1Image_AddRef(input
);
1236 if (effect
->inputs
[index
])
1237 ID2D1Image_Release(effect
->inputs
[index
]);
1238 effect
->inputs
[index
] = input
;
1241 static HRESULT
d2d_effect_set_input_count(struct d2d_effect
*effect
, UINT32 count
)
1243 bool initialized
= effect
->inputs
!= NULL
;
1247 if (count
== effect
->input_count
)
1250 if (count
< effect
->input_count
)
1252 for (i
= count
; i
< effect
->input_count
; ++i
)
1254 if (effect
->inputs
[i
])
1255 ID2D1Image_Release(effect
->inputs
[i
]);
1260 if (!d2d_array_reserve((void **)&effect
->inputs
, &effect
->inputs_size
,
1261 count
, sizeof(*effect
->inputs
)))
1263 ERR("Failed to resize inputs array.\n");
1264 return E_OUTOFMEMORY
;
1267 memset(&effect
->inputs
[effect
->input_count
], 0, sizeof(*effect
->inputs
) * (count
- effect
->input_count
));
1269 effect
->input_count
= count
;
1273 ID2D1TransformGraph_Release(&effect
->graph
->ID2D1TransformGraph_iface
);
1274 effect
->graph
= NULL
;
1276 if (!(effect
->graph
= calloc(1, sizeof(*effect
->graph
))))
1277 return E_OUTOFMEMORY
;
1278 d2d_transform_graph_init(effect
->graph
);
1280 if (FAILED(hr
= ID2D1EffectImpl_SetGraph(effect
->impl
, &effect
->graph
->ID2D1TransformGraph_iface
)))
1281 WARN("Failed to set a new transform graph, hr %#lx.\n", hr
);
1287 static HRESULT STDMETHODCALLTYPE
d2d_effect_SetInputCount(ID2D1Effect
*iface
, UINT32 count
)
1289 struct d2d_effect
*effect
= impl_from_ID2D1Effect(iface
);
1290 unsigned int min_inputs
, max_inputs
;
1292 TRACE("iface %p, count %u.\n", iface
, count
);
1294 d2d_effect_get_value(effect
, D2D1_PROPERTY_MIN_INPUTS
, D2D1_PROPERTY_TYPE_UINT32
,
1295 (BYTE
*)&min_inputs
, sizeof(min_inputs
));
1296 d2d_effect_get_value(effect
, D2D1_PROPERTY_MAX_INPUTS
, D2D1_PROPERTY_TYPE_UINT32
,
1297 (BYTE
*)&max_inputs
, sizeof(max_inputs
));
1299 if (count
< min_inputs
|| count
> max_inputs
)
1300 return E_INVALIDARG
;
1302 return d2d_effect_set_input_count(effect
, count
);
1305 static void STDMETHODCALLTYPE
d2d_effect_GetInput(ID2D1Effect
*iface
, UINT32 index
, ID2D1Image
**input
)
1307 struct d2d_effect
*effect
= impl_from_ID2D1Effect(iface
);
1309 TRACE("iface %p, index %u, input %p.\n", iface
, index
, input
);
1311 if (index
< effect
->input_count
&& effect
->inputs
[index
])
1312 ID2D1Image_AddRef(*input
= effect
->inputs
[index
]);
1317 static UINT32 STDMETHODCALLTYPE
d2d_effect_GetInputCount(ID2D1Effect
*iface
)
1319 struct d2d_effect
*effect
= impl_from_ID2D1Effect(iface
);
1321 TRACE("iface %p.\n", iface
);
1323 return effect
->input_count
;
1326 static void STDMETHODCALLTYPE
d2d_effect_GetOutput(ID2D1Effect
*iface
, ID2D1Image
**output
)
1328 struct d2d_effect
*effect
= impl_from_ID2D1Effect(iface
);
1330 TRACE("iface %p, output %p.\n", iface
, output
);
1332 ID2D1Image_AddRef(*output
= &effect
->ID2D1Image_iface
);
1335 static const ID2D1EffectVtbl d2d_effect_vtbl
=
1337 d2d_effect_QueryInterface
,
1340 d2d_effect_GetPropertyCount
,
1341 d2d_effect_GetPropertyName
,
1342 d2d_effect_GetPropertyNameLength
,
1344 d2d_effect_GetPropertyIndex
,
1345 d2d_effect_SetValueByName
,
1346 d2d_effect_SetValue
,
1347 d2d_effect_GetValueByName
,
1348 d2d_effect_GetValue
,
1349 d2d_effect_GetValueSize
,
1350 d2d_effect_GetSubProperties
,
1351 d2d_effect_SetInput
,
1352 d2d_effect_SetInputCount
,
1353 d2d_effect_GetInput
,
1354 d2d_effect_GetInputCount
,
1355 d2d_effect_GetOutput
,
1358 static inline struct d2d_effect
*impl_from_ID2D1Image(ID2D1Image
*iface
)
1360 return CONTAINING_RECORD(iface
, struct d2d_effect
, ID2D1Image_iface
);
1363 static HRESULT STDMETHODCALLTYPE
d2d_effect_image_QueryInterface(ID2D1Image
*iface
, REFIID iid
, void **out
)
1365 struct d2d_effect
*effect
= impl_from_ID2D1Image(iface
);
1367 TRACE("iface %p, iid %s, out %p.\n", iface
, debugstr_guid(iid
), out
);
1369 return d2d_effect_QueryInterface(&effect
->ID2D1Effect_iface
, iid
, out
);
1372 static ULONG STDMETHODCALLTYPE
d2d_effect_image_AddRef(ID2D1Image
*iface
)
1374 struct d2d_effect
*effect
= impl_from_ID2D1Image(iface
);
1376 TRACE("iface %p.\n", iface
);
1378 return d2d_effect_AddRef(&effect
->ID2D1Effect_iface
);
1381 static ULONG STDMETHODCALLTYPE
d2d_effect_image_Release(ID2D1Image
*iface
)
1383 struct d2d_effect
*effect
= impl_from_ID2D1Image(iface
);
1385 TRACE("iface %p.\n", iface
);
1387 return d2d_effect_Release(&effect
->ID2D1Effect_iface
);
1390 static void STDMETHODCALLTYPE
d2d_effect_image_GetFactory(ID2D1Image
*iface
, ID2D1Factory
**factory
)
1392 struct d2d_effect
*effect
= impl_from_ID2D1Image(iface
);
1394 TRACE("iface %p, factory %p.\n", iface
, factory
);
1396 ID2D1Factory_AddRef(*factory
= effect
->effect_context
->device_context
->factory
);
1399 static const ID2D1ImageVtbl d2d_effect_image_vtbl
=
1401 d2d_effect_image_QueryInterface
,
1402 d2d_effect_image_AddRef
,
1403 d2d_effect_image_Release
,
1404 d2d_effect_image_GetFactory
,
1407 static inline struct d2d_effect_properties
*impl_from_ID2D1Properties(ID2D1Properties
*iface
)
1409 return CONTAINING_RECORD(iface
, struct d2d_effect_properties
, ID2D1Properties_iface
);
1412 static HRESULT STDMETHODCALLTYPE
d2d_effect_properties_QueryInterface(ID2D1Properties
*iface
,
1413 REFIID riid
, void **obj
)
1415 if (IsEqualGUID(riid
, &IID_ID2D1Properties
) ||
1416 IsEqualGUID(riid
, &IID_IUnknown
))
1419 ID2D1Properties_AddRef(iface
);
1424 return E_NOINTERFACE
;
1427 static ULONG STDMETHODCALLTYPE
d2d_effect_properties_AddRef(ID2D1Properties
*iface
)
1429 struct d2d_effect_properties
*properties
= impl_from_ID2D1Properties(iface
);
1430 return ID2D1Effect_AddRef(&properties
->effect
->ID2D1Effect_iface
);
1433 static ULONG STDMETHODCALLTYPE
d2d_effect_properties_Release(ID2D1Properties
*iface
)
1435 struct d2d_effect_properties
*properties
= impl_from_ID2D1Properties(iface
);
1436 return ID2D1Effect_Release(&properties
->effect
->ID2D1Effect_iface
);
1439 static UINT32 STDMETHODCALLTYPE
d2d_effect_properties_GetPropertyCount(ID2D1Properties
*iface
)
1441 struct d2d_effect_properties
*properties
= impl_from_ID2D1Properties(iface
);
1443 TRACE("iface %p.\n", iface
);
1445 return properties
->custom_count
;
1448 static HRESULT STDMETHODCALLTYPE
d2d_effect_properties_GetPropertyName(ID2D1Properties
*iface
,
1449 UINT32 index
, WCHAR
*name
, UINT32 name_count
)
1451 struct d2d_effect_properties
*properties
= impl_from_ID2D1Properties(iface
);
1452 struct d2d_effect_property
*prop
;
1454 TRACE("iface %p, index %u, name %p, name_count %u.\n", iface
, index
, name
, name_count
);
1456 if (!(prop
= d2d_effect_properties_get_property_by_index(properties
, index
)))
1457 return D2DERR_INVALID_PROPERTY
;
1459 return d2d_effect_return_string(prop
->name
, name
, name_count
);
1462 static UINT32 STDMETHODCALLTYPE
d2d_effect_properties_GetPropertyNameLength(ID2D1Properties
*iface
,
1465 struct d2d_effect_properties
*properties
= impl_from_ID2D1Properties(iface
);
1466 struct d2d_effect_property
*prop
;
1468 TRACE("iface %p, index %u.\n", iface
, index
);
1470 if (!(prop
= d2d_effect_properties_get_property_by_index(properties
, index
)))
1471 return D2DERR_INVALID_PROPERTY
;
1473 return wcslen(prop
->name
) + 1;
1476 static D2D1_PROPERTY_TYPE STDMETHODCALLTYPE
d2d_effect_properties_GetType(ID2D1Properties
*iface
,
1479 struct d2d_effect_properties
*properties
= impl_from_ID2D1Properties(iface
);
1480 struct d2d_effect_property
*prop
;
1482 TRACE("iface %p, index %#x.\n", iface
, index
);
1484 if (!(prop
= d2d_effect_properties_get_property_by_index(properties
, index
)))
1485 return D2D1_PROPERTY_TYPE_UNKNOWN
;
1490 static UINT32 STDMETHODCALLTYPE
d2d_effect_properties_GetPropertyIndex(ID2D1Properties
*iface
,
1493 struct d2d_effect_properties
*properties
= impl_from_ID2D1Properties(iface
);
1494 struct d2d_effect_property
*prop
;
1496 TRACE("iface %p, name %s.\n", iface
, debugstr_w(name
));
1498 if (!(prop
= d2d_effect_properties_get_property_by_name(properties
, name
)))
1499 return D2D1_INVALID_PROPERTY_INDEX
;
1504 static HRESULT STDMETHODCALLTYPE
d2d_effect_properties_SetValueByName(ID2D1Properties
*iface
,
1505 const WCHAR
*name
, D2D1_PROPERTY_TYPE type
, const BYTE
*value
, UINT32 value_size
)
1507 struct d2d_effect_properties
*properties
= impl_from_ID2D1Properties(iface
);
1508 struct d2d_effect_property
*prop
;
1510 TRACE("iface %p, name %s, type %u, value %p, value_size %u.\n", iface
, debugstr_w(name
),
1511 type
, value
, value_size
);
1513 if (!(prop
= d2d_effect_properties_get_property_by_name(properties
, name
)))
1514 return D2DERR_INVALID_PROPERTY
;
1516 return d2d_effect_property_set_value(properties
, prop
, type
, value
, value_size
);
1519 static HRESULT STDMETHODCALLTYPE
d2d_effect_properties_SetValue(ID2D1Properties
*iface
,
1520 UINT32 index
, D2D1_PROPERTY_TYPE type
, const BYTE
*value
, UINT32 value_size
)
1522 struct d2d_effect_properties
*properties
= impl_from_ID2D1Properties(iface
);
1523 struct d2d_effect_property
*prop
;
1525 TRACE("iface %p, index %#x, type %u, value %p, value_size %u.\n", iface
, index
, type
, value
, value_size
);
1527 if (!(prop
= d2d_effect_properties_get_property_by_index(properties
, index
)))
1528 return D2DERR_INVALID_PROPERTY
;
1530 return d2d_effect_property_set_value(properties
, prop
, type
, value
, value_size
);
1533 static HRESULT STDMETHODCALLTYPE
d2d_effect_properties_GetValueByName(ID2D1Properties
*iface
,
1534 const WCHAR
*name
, D2D1_PROPERTY_TYPE type
, BYTE
*value
, UINT32 value_size
)
1536 struct d2d_effect_properties
*properties
= impl_from_ID2D1Properties(iface
);
1537 struct d2d_effect_property
*prop
;
1539 TRACE("iface %p, name %s, type %#x, value %p, value_size %u.\n", iface
, debugstr_w(name
), type
,
1542 if (!(prop
= d2d_effect_properties_get_property_by_name(properties
, name
)))
1543 return D2DERR_INVALID_PROPERTY
;
1545 return d2d_effect_property_get_value(properties
, prop
, type
, value
, value_size
);
1548 static HRESULT STDMETHODCALLTYPE
d2d_effect_properties_GetValue(ID2D1Properties
*iface
,
1549 UINT32 index
, D2D1_PROPERTY_TYPE type
, BYTE
*value
, UINT32 value_size
)
1551 struct d2d_effect_properties
*properties
= impl_from_ID2D1Properties(iface
);
1552 struct d2d_effect_property
*prop
;
1554 TRACE("iface %p, index %#x, type %u, value %p, value_size %u.\n", iface
, index
, type
, value
, value_size
);
1556 if (!(prop
= d2d_effect_properties_get_property_by_index(properties
, index
)))
1557 return D2DERR_INVALID_PROPERTY
;
1559 return d2d_effect_property_get_value(properties
, prop
, type
, value
, value_size
);
1562 static UINT32 STDMETHODCALLTYPE
d2d_effect_properties_GetValueSize(ID2D1Properties
*iface
,
1565 struct d2d_effect_properties
*properties
= impl_from_ID2D1Properties(iface
);
1567 TRACE("iface %p, index %#x.\n", iface
, index
);
1569 return d2d_effect_properties_get_value_size(properties
, index
);
1572 static HRESULT STDMETHODCALLTYPE
d2d_effect_properties_GetSubProperties(ID2D1Properties
*iface
,
1573 UINT32 index
, ID2D1Properties
**props
)
1575 struct d2d_effect_properties
*properties
= impl_from_ID2D1Properties(iface
);
1576 struct d2d_effect_property
*prop
;
1578 TRACE("iface %p, index %u, props %p.\n", iface
, index
, props
);
1580 if (!(prop
= d2d_effect_properties_get_property_by_index(properties
, index
)))
1581 return D2DERR_INVALID_PROPERTY
;
1583 if (!prop
->subproperties
) return D2DERR_NO_SUBPROPERTIES
;
1585 *props
= &prop
->subproperties
->ID2D1Properties_iface
;
1586 ID2D1Properties_AddRef(*props
);
1590 static const ID2D1PropertiesVtbl d2d_effect_properties_vtbl
=
1592 d2d_effect_properties_QueryInterface
,
1593 d2d_effect_properties_AddRef
,
1594 d2d_effect_properties_Release
,
1595 d2d_effect_properties_GetPropertyCount
,
1596 d2d_effect_properties_GetPropertyName
,
1597 d2d_effect_properties_GetPropertyNameLength
,
1598 d2d_effect_properties_GetType
,
1599 d2d_effect_properties_GetPropertyIndex
,
1600 d2d_effect_properties_SetValueByName
,
1601 d2d_effect_properties_SetValue
,
1602 d2d_effect_properties_GetValueByName
,
1603 d2d_effect_properties_GetValue
,
1604 d2d_effect_properties_GetValueSize
,
1605 d2d_effect_properties_GetSubProperties
,
1608 static void d2d_effect_init_properties_vtbls(struct d2d_effect
*effect
)
1612 effect
->properties
.ID2D1Properties_iface
.lpVtbl
= &d2d_effect_properties_vtbl
;
1613 effect
->properties
.effect
= effect
;
1615 for (i
= 0; i
< effect
->properties
.count
; ++i
)
1617 struct d2d_effect_property
*prop
= &effect
->properties
.properties
[i
];
1618 if (!prop
->subproperties
) continue;
1619 prop
->subproperties
->ID2D1Properties_iface
.lpVtbl
= &d2d_effect_properties_vtbl
;
1620 prop
->subproperties
->effect
= effect
;
1624 HRESULT
d2d_effect_create(struct d2d_device_context
*context
, const CLSID
*effect_id
,
1625 ID2D1Effect
**effect
)
1627 struct d2d_effect_context
*effect_context
;
1628 const struct d2d_effect_registration
*reg
;
1629 struct d2d_transform_graph
*graph
;
1630 struct d2d_effect
*object
;
1635 if (!(reg
= d2d_factory_get_registered_effect(context
->factory
, effect_id
)))
1637 WARN("Effect id %s not found.\n", wine_dbgstr_guid(effect_id
));
1638 return D2DERR_EFFECT_IS_NOT_REGISTERED
;
1641 if (!(effect_context
= calloc(1, sizeof(*effect_context
))))
1642 return E_OUTOFMEMORY
;
1643 d2d_effect_context_init(effect_context
, context
);
1645 if (!(graph
= calloc(1, sizeof(*graph
))))
1647 ID2D1EffectContext_Release(&effect_context
->ID2D1EffectContext_iface
);
1648 return E_OUTOFMEMORY
;
1650 d2d_transform_graph_init(graph
);
1652 if (!(object
= calloc(1, sizeof(*object
))))
1654 ID2D1TransformGraph_Release(&graph
->ID2D1TransformGraph_iface
);
1655 ID2D1EffectContext_Release(&effect_context
->ID2D1EffectContext_iface
);
1656 return E_OUTOFMEMORY
;
1659 object
->ID2D1Effect_iface
.lpVtbl
= &d2d_effect_vtbl
;
1660 object
->ID2D1Image_iface
.lpVtbl
= &d2d_effect_image_vtbl
;
1661 object
->refcount
= 1;
1662 object
->effect_context
= effect_context
;
1663 object
->graph
= graph
;
1665 /* Create properties */
1666 d2d_effect_duplicate_properties(&object
->properties
, ®
->properties
);
1668 StringFromGUID2(effect_id
, clsidW
, ARRAY_SIZE(clsidW
));
1669 d2d_effect_properties_add(&object
->properties
, L
"CLSID", D2D1_PROPERTY_CLSID
, D2D1_PROPERTY_TYPE_CLSID
, clsidW
);
1670 d2d_effect_properties_add(&object
->properties
, L
"Cached", D2D1_PROPERTY_CACHED
, D2D1_PROPERTY_TYPE_BOOL
, L
"false");
1671 d2d_effect_properties_add(&object
->properties
, L
"Precision", D2D1_PROPERTY_PRECISION
, D2D1_PROPERTY_TYPE_ENUM
, L
"0");
1672 d2d_effect_init_properties_vtbls(object
);
1674 /* Sync instance input count with default input count from the description. */
1675 d2d_effect_get_value(object
, D2D1_PROPERTY_INPUTS
, D2D1_PROPERTY_TYPE_ARRAY
, (BYTE
*)&input_count
, sizeof(input_count
));
1676 d2d_effect_set_input_count(object
, input_count
);
1678 if (FAILED(hr
= reg
->factory((IUnknown
**)&object
->impl
)))
1680 WARN("Failed to create implementation object, hr %#lx.\n", hr
);
1681 ID2D1Effect_Release(&object
->ID2D1Effect_iface
);
1685 if (FAILED(hr
= ID2D1EffectImpl_Initialize(object
->impl
, &effect_context
->ID2D1EffectContext_iface
,
1686 &graph
->ID2D1TransformGraph_iface
)))
1688 WARN("Failed to initialize effect, hr %#lx.\n", hr
);
1689 ID2D1Effect_Release(&object
->ID2D1Effect_iface
);
1693 *effect
= &object
->ID2D1Effect_iface
;
1695 TRACE("Created effect %p.\n", *effect
);