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 const struct d2d_effect_info builtin_effects
[] =
25 {&CLSID_D2D12DAffineTransform
, 1, 1, 1},
26 {&CLSID_D2D13DPerspectiveTransform
, 1, 1, 1},
27 {&CLSID_D2D1Composite
, 2, 1, 0xffffffff},
28 {&CLSID_D2D1Crop
, 1, 1, 1},
31 static inline struct d2d_effect
*impl_from_ID2D1Effect(ID2D1Effect
*iface
)
33 return CONTAINING_RECORD(iface
, struct d2d_effect
, ID2D1Effect_iface
);
36 static void d2d_effect_cleanup(struct d2d_effect
*effect
)
40 for (i
= 0; i
< effect
->input_count
; ++i
)
42 if (effect
->inputs
[i
])
43 ID2D1Image_Release(effect
->inputs
[i
]);
45 heap_free(effect
->inputs
);
46 ID2D1Factory_Release(effect
->factory
);
49 static HRESULT STDMETHODCALLTYPE
d2d_effect_QueryInterface(ID2D1Effect
*iface
, REFIID iid
, void **out
)
51 struct d2d_effect
*effect
= impl_from_ID2D1Effect(iface
);
52 TRACE("iface %p, iid %s, out %p.\n", iface
, debugstr_guid(iid
), out
);
54 if (IsEqualGUID(iid
, &IID_ID2D1Effect
)
55 || IsEqualGUID(iid
, &IID_ID2D1Properties
)
56 || IsEqualGUID(iid
, &IID_IUnknown
))
58 ID2D1Effect_AddRef(iface
);
63 if (IsEqualGUID(iid
, &IID_ID2D1Image
)
64 || IsEqualGUID(iid
, &IID_ID2D1Resource
))
66 ID2D1Image_AddRef(&effect
->ID2D1Image_iface
);
67 *out
= &effect
->ID2D1Image_iface
;
71 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid
));
77 static ULONG STDMETHODCALLTYPE
d2d_effect_AddRef(ID2D1Effect
*iface
)
79 struct d2d_effect
*effect
= impl_from_ID2D1Effect(iface
);
80 ULONG refcount
= InterlockedIncrement(&effect
->refcount
);
82 TRACE("%p increasing refcount to %u.\n", iface
, refcount
);
87 static ULONG STDMETHODCALLTYPE
d2d_effect_Release(ID2D1Effect
*iface
)
89 struct d2d_effect
*effect
= impl_from_ID2D1Effect(iface
);
90 ULONG refcount
= InterlockedDecrement(&effect
->refcount
);
92 TRACE("%p decreasing refcount to %u.\n", iface
, refcount
);
96 d2d_effect_cleanup(effect
);
103 static UINT32 STDMETHODCALLTYPE
d2d_effect_GetPropertyCount(ID2D1Effect
*iface
)
105 FIXME("iface %p stub!\n", iface
);
110 static HRESULT STDMETHODCALLTYPE
d2d_effect_GetPropertyName(ID2D1Effect
*iface
, UINT32 index
,
111 WCHAR
*name
, UINT32 name_count
)
113 FIXME("iface %p, index %u, name %p, name_count %u stub!\n", iface
, index
, name
, name_count
);
118 static UINT32 STDMETHODCALLTYPE
d2d_effect_GetPropertyNameLength(ID2D1Effect
*iface
, UINT32 index
)
120 FIXME("iface %p, index %u stub!\n", iface
, index
);
125 static D2D1_PROPERTY_TYPE STDMETHODCALLTYPE
d2d_effect_GetType(ID2D1Effect
*iface
, UINT32 index
)
127 FIXME("iface %p, index %u stub!\n", iface
, index
);
132 static UINT32 STDMETHODCALLTYPE
d2d_effect_GetPropertyIndex(ID2D1Effect
*iface
, const WCHAR
*name
)
134 FIXME("iface %p, name %s stub!\n", iface
, debugstr_w(name
));
139 static HRESULT STDMETHODCALLTYPE
d2d_effect_SetValueByName(ID2D1Effect
*iface
, const WCHAR
*name
,
140 D2D1_PROPERTY_TYPE type
, const BYTE
*value
, UINT32 value_size
)
142 FIXME("iface %p, name %s, type %#x, value %p, value_size %u stub!\n", iface
, debugstr_w(name
),
143 type
, value
, value_size
);
148 static HRESULT STDMETHODCALLTYPE
d2d_effect_SetValue(ID2D1Effect
*iface
, UINT32 index
, D2D1_PROPERTY_TYPE type
,
149 const BYTE
*value
, UINT32 value_size
)
151 FIXME("iface %p, index %u, type %#x, value %p, value_size %u stub!\n", iface
, index
, type
, value
, value_size
);
156 static HRESULT STDMETHODCALLTYPE
d2d_effect_GetValueByName(ID2D1Effect
*iface
, const WCHAR
*name
,
157 D2D1_PROPERTY_TYPE type
, BYTE
*value
, UINT32 value_size
)
159 FIXME("iface %p, name %s, type %#x, value %p, value_size %u stub!\n", iface
, debugstr_w(name
), type
,
165 static HRESULT STDMETHODCALLTYPE
d2d_effect_GetValue(ID2D1Effect
*iface
, UINT32 index
, D2D1_PROPERTY_TYPE type
,
166 BYTE
*value
, UINT32 value_size
)
168 struct d2d_effect
*effect
= impl_from_ID2D1Effect(iface
);
171 TRACE("iface %p, index %u, type %#x, value %p, value_size %u.\n", iface
, index
, type
, value
, value_size
);
175 case D2D1_PROPERTY_CLSID
:
176 if ((type
!= D2D1_PROPERTY_TYPE_UNKNOWN
&& type
!= D2D1_PROPERTY_TYPE_CLSID
)
177 || value_size
!= sizeof(*effect
->info
->clsid
))
179 src
= effect
->info
->clsid
;
181 case D2D1_PROPERTY_MIN_INPUTS
:
182 if ((type
!= D2D1_PROPERTY_TYPE_UNKNOWN
&& type
!= D2D1_PROPERTY_TYPE_UINT32
)
183 || value_size
!= sizeof(effect
->info
->min_inputs
))
185 src
= &effect
->info
->min_inputs
;
187 case D2D1_PROPERTY_MAX_INPUTS
:
188 if ((type
!= D2D1_PROPERTY_TYPE_UNKNOWN
&& type
!= D2D1_PROPERTY_TYPE_UINT32
)
189 || value_size
!= sizeof(effect
->info
->max_inputs
))
191 src
= &effect
->info
->max_inputs
;
194 if (index
< D2D1_PROPERTY_CLSID
)
195 FIXME("Custom properties are not supported.\n");
196 else if (index
<= D2D1_PROPERTY_MAX_INPUTS
)
197 FIXME("Standard property %#x is not supported.\n", index
);
198 return D2DERR_INVALID_PROPERTY
;
201 memcpy(value
, src
, value_size
);
206 static UINT32 STDMETHODCALLTYPE
d2d_effect_GetValueSize(ID2D1Effect
*iface
, UINT32 index
)
208 FIXME("iface %p, index %u stub!\n", iface
, index
);
213 static HRESULT STDMETHODCALLTYPE
d2d_effect_GetSubProperties(ID2D1Effect
*iface
, UINT32 index
, ID2D1Properties
**props
)
215 FIXME("iface %p, index %u, props %p stub!\n", iface
, index
, props
);
220 static void STDMETHODCALLTYPE
d2d_effect_SetInput(ID2D1Effect
*iface
, UINT32 index
, ID2D1Image
*input
, BOOL invalidate
)
222 struct d2d_effect
*effect
= impl_from_ID2D1Effect(iface
);
224 TRACE("iface %p, index %u, input %p, invalidate %#x.\n", iface
, index
, input
, invalidate
);
226 if (index
>= effect
->input_count
)
229 ID2D1Image_AddRef(input
);
230 if (effect
->inputs
[index
])
231 ID2D1Image_Release(effect
->inputs
[index
]);
232 effect
->inputs
[index
] = input
;
235 static HRESULT STDMETHODCALLTYPE
d2d_effect_SetInputCount(ID2D1Effect
*iface
, UINT32 count
)
237 struct d2d_effect
*effect
= impl_from_ID2D1Effect(iface
);
240 TRACE("iface %p, count %u.\n", iface
, count
);
242 if (count
< effect
->info
->min_inputs
|| count
> effect
->info
->max_inputs
)
244 if (count
== effect
->input_count
)
247 if (count
< effect
->input_count
)
249 for (i
= count
; i
< effect
->input_count
; ++i
)
251 if (effect
->inputs
[i
])
252 ID2D1Image_Release(effect
->inputs
[i
]);
254 effect
->input_count
= count
;
258 if (!d2d_array_reserve((void **)&effect
->inputs
, &effect
->inputs_size
,
259 count
, sizeof(*effect
->inputs
)))
261 ERR("Failed to resize inputs array.\n");
262 return E_OUTOFMEMORY
;
265 memset(&effect
->inputs
[effect
->input_count
], 0, sizeof(*effect
->inputs
) * (count
- effect
->input_count
));
266 effect
->input_count
= count
;
271 static void STDMETHODCALLTYPE
d2d_effect_GetInput(ID2D1Effect
*iface
, UINT32 index
, ID2D1Image
**input
)
273 struct d2d_effect
*effect
= impl_from_ID2D1Effect(iface
);
275 TRACE("iface %p, index %u, input %p.\n", iface
, index
, input
);
277 if (index
< effect
->input_count
&& effect
->inputs
[index
])
278 ID2D1Image_AddRef(*input
= effect
->inputs
[index
]);
283 static UINT32 STDMETHODCALLTYPE
d2d_effect_GetInputCount(ID2D1Effect
*iface
)
285 struct d2d_effect
*effect
= impl_from_ID2D1Effect(iface
);
287 TRACE("iface %p.\n", iface
);
289 return effect
->input_count
;
292 static void STDMETHODCALLTYPE
d2d_effect_GetOutput(ID2D1Effect
*iface
, ID2D1Image
**output
)
294 struct d2d_effect
*effect
= impl_from_ID2D1Effect(iface
);
296 TRACE("iface %p, output %p.\n", iface
, output
);
298 ID2D1Image_AddRef(*output
= &effect
->ID2D1Image_iface
);
301 static const ID2D1EffectVtbl d2d_effect_vtbl
=
303 d2d_effect_QueryInterface
,
306 d2d_effect_GetPropertyCount
,
307 d2d_effect_GetPropertyName
,
308 d2d_effect_GetPropertyNameLength
,
310 d2d_effect_GetPropertyIndex
,
311 d2d_effect_SetValueByName
,
313 d2d_effect_GetValueByName
,
315 d2d_effect_GetValueSize
,
316 d2d_effect_GetSubProperties
,
318 d2d_effect_SetInputCount
,
320 d2d_effect_GetInputCount
,
321 d2d_effect_GetOutput
,
324 static inline struct d2d_effect
*impl_from_ID2D1Image(ID2D1Image
*iface
)
326 return CONTAINING_RECORD(iface
, struct d2d_effect
, ID2D1Image_iface
);
329 static HRESULT STDMETHODCALLTYPE
d2d_effect_image_QueryInterface(ID2D1Image
*iface
, REFIID iid
, void **out
)
331 struct d2d_effect
*effect
= impl_from_ID2D1Image(iface
);
333 TRACE("iface %p, iid %s, out %p.\n", iface
, debugstr_guid(iid
), out
);
335 return d2d_effect_QueryInterface(&effect
->ID2D1Effect_iface
, iid
, out
);
338 static ULONG STDMETHODCALLTYPE
d2d_effect_image_AddRef(ID2D1Image
*iface
)
340 struct d2d_effect
*effect
= impl_from_ID2D1Image(iface
);
342 TRACE("iface %p.\n", iface
);
344 return d2d_effect_AddRef(&effect
->ID2D1Effect_iface
);
347 static ULONG STDMETHODCALLTYPE
d2d_effect_image_Release(ID2D1Image
*iface
)
349 struct d2d_effect
*effect
= impl_from_ID2D1Image(iface
);
351 TRACE("iface %p.\n", iface
);
353 return d2d_effect_Release(&effect
->ID2D1Effect_iface
);
356 static void STDMETHODCALLTYPE
d2d_effect_image_GetFactory(ID2D1Image
*iface
, ID2D1Factory
**factory
)
358 struct d2d_effect
*effect
= impl_from_ID2D1Image(iface
);
360 TRACE("iface %p, factory %p.\n", iface
, factory
);
362 ID2D1Factory_AddRef(*factory
= effect
->factory
);
365 static const ID2D1ImageVtbl d2d_effect_image_vtbl
=
367 d2d_effect_image_QueryInterface
,
368 d2d_effect_image_AddRef
,
369 d2d_effect_image_Release
,
370 d2d_effect_image_GetFactory
,
373 HRESULT
d2d_effect_init(struct d2d_effect
*effect
, ID2D1Factory
*factory
, const CLSID
*effect_id
)
377 effect
->ID2D1Effect_iface
.lpVtbl
= &d2d_effect_vtbl
;
378 effect
->ID2D1Image_iface
.lpVtbl
= &d2d_effect_image_vtbl
;
379 effect
->refcount
= 1;
381 for (i
= 0; i
< ARRAY_SIZE(builtin_effects
); ++i
)
383 if (IsEqualGUID(effect_id
, builtin_effects
[i
].clsid
))
385 effect
->info
= &builtin_effects
[i
];
386 d2d_effect_SetInputCount(&effect
->ID2D1Effect_iface
, effect
->info
->default_input_count
);
387 ID2D1Factory_AddRef(effect
->factory
= factory
);
392 WARN("Unsupported effect clsid %s.\n", debugstr_guid(effect_id
));