[PATCH 3/5] d2d1/effect: Keep builtin effects in the same list as the custom once.
Ziqing Hui
wine at gitlab.winehq.org
Tue Jul 5 01:31:29 CDT 2022
From: Ziqing Hui <zhui at codeweavers.com>
Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
---
dlls/d2d1/d2d1_private.h | 6 ++++
dlls/d2d1/effect.c | 76 ++++++++++++++++------------------------
dlls/d2d1/factory.c | 40 ++++++++++++++++++---
dlls/d2d1/tests/d2d1.c | 5 +++
4 files changed, 78 insertions(+), 49 deletions(-)
diff --git a/dlls/d2d1/d2d1_private.h b/dlls/d2d1/d2d1_private.h
index db6787c2f86..98f99744746 100644
--- a/dlls/d2d1/d2d1_private.h
+++ b/dlls/d2d1/d2d1_private.h
@@ -643,14 +643,20 @@ struct d2d_effect_registration
struct list entry;
PD2D1_EFFECT_FACTORY factory;
UINT32 registration_count;
+ BOOL builtin;
CLSID id;
UINT32 input_count;
+ UINT32 default_input_count;
struct d2d_effect_properties properties;
};
+struct d2d_factory;
+void d2d_effects_init_builtins(struct d2d_factory *factory) DECLSPEC_HIDDEN;
struct d2d_effect_registration * d2d_factory_get_registered_effect(ID2D1Factory *factory,
const GUID *effect_id) DECLSPEC_HIDDEN;
+void d2d_factory_register_effect(struct d2d_factory *factory,
+ struct d2d_effect_registration *effect) DECLSPEC_HIDDEN;
struct d2d_transform_graph
{
diff --git a/dlls/d2d1/effect.c b/dlls/d2d1/effect.c
index 640aab15817..7b086e20b9b 100644
--- a/dlls/d2d1/effect.c
+++ b/dlls/d2d1/effect.c
@@ -229,6 +229,33 @@ static const struct d2d_effect_info builtin_effects[] =
{&CLSID_D2D1Grayscale, 1, 1, 1},
};
+void d2d_effects_init_builtins(struct d2d_factory *factory)
+{
+ struct d2d_effect_registration *effect;
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(builtin_effects); ++i)
+ {
+ const struct d2d_effect_info *info = &builtin_effects[i];
+ WCHAR max_inputs[32];
+
+ if (!(effect = calloc(1, sizeof(*effect))))
+ return;
+
+ swprintf(max_inputs, ARRAY_SIZE(max_inputs), L"%lu", info->max_inputs);
+ d2d_effect_properties_add(&effect->properties, L"MinInputs", D2D1_PROPERTY_MIN_INPUTS,
+ D2D1_PROPERTY_TYPE_UINT32, L"1");
+ d2d_effect_properties_add(&effect->properties, L"MaxInputs", D2D1_PROPERTY_MAX_INPUTS,
+ D2D1_PROPERTY_TYPE_UINT32, max_inputs);
+
+ memcpy(&effect->id, info->clsid, sizeof(*info->clsid));
+ effect->default_input_count = info->default_input_count;
+ effect->factory = builtin_factory_stub;
+ effect->builtin = TRUE;
+ d2d_factory_register_effect(factory, effect);
+ }
+}
+
/* Same syntax is used for value and default values. */
static HRESULT d2d_effect_parse_float_array(D2D1_PROPERTY_TYPE type, const WCHAR *value,
float *vec)
@@ -1539,31 +1566,14 @@ static void d2d_effect_init_properties_vtbls(struct d2d_effect *effect)
HRESULT d2d_effect_create(struct d2d_device_context *context, const CLSID *effect_id,
ID2D1Effect **effect)
{
- const struct d2d_effect_info *builtin = NULL;
struct d2d_effect_context *effect_context;
const struct d2d_effect_registration *reg;
- unsigned int i, default_input_count;
struct d2d_transform_graph *graph;
- PD2D1_EFFECT_FACTORY factory;
struct d2d_effect *object;
WCHAR clsidW[39];
HRESULT hr;
if (!(reg = d2d_factory_get_registered_effect(context->factory, effect_id)))
- {
- for (i = 0; i < ARRAY_SIZE(builtin_effects); ++i)
- {
- const struct d2d_effect_info *info = &builtin_effects[i];
-
- if (IsEqualGUID(effect_id, info->clsid))
- {
- builtin = info;
- break;
- }
- }
- }
-
- if (!reg && !builtin)
{
WARN("Effect id %s not found.\n", wine_dbgstr_guid(effect_id));
return D2DERR_EFFECT_IS_NOT_REGISTERED;
@@ -1594,41 +1604,17 @@ HRESULT d2d_effect_create(struct d2d_device_context *context, const CLSID *effec
object->graph = graph;
/* Create properties */
- StringFromGUID2(effect_id, clsidW, ARRAY_SIZE(clsidW));
- if (builtin)
- {
- WCHAR max_inputs[32];
- swprintf(max_inputs, ARRAY_SIZE(max_inputs), L"%lu", builtin->max_inputs);
- d2d_effect_properties_add(&object->properties, L"MinInputs", D2D1_PROPERTY_MIN_INPUTS,
- D2D1_PROPERTY_TYPE_UINT32, L"1");
- d2d_effect_properties_add(&object->properties, L"MaxInputs", D2D1_PROPERTY_MAX_INPUTS,
- D2D1_PROPERTY_TYPE_UINT32, max_inputs);
-
- default_input_count = builtin->default_input_count;
-
- factory = builtin_factory_stub;
- }
- else
- {
- d2d_effect_duplicate_properties(&object->properties, ®->properties);
- d2d_effect_properties_add(&object->properties, L"MinInputs", D2D1_PROPERTY_MIN_INPUTS,
- D2D1_PROPERTY_TYPE_UINT32, L"1");
- d2d_effect_properties_add(&object->properties, L"MaxInputs", D2D1_PROPERTY_MAX_INPUTS,
- D2D1_PROPERTY_TYPE_UINT32, L"1" /* FIXME */);
-
- default_input_count = 1;
-
- factory = reg->factory;
- }
+ d2d_effect_duplicate_properties(&object->properties, ®->properties);
+ StringFromGUID2(effect_id, clsidW, ARRAY_SIZE(clsidW));
d2d_effect_properties_add(&object->properties, L"CLSID", D2D1_PROPERTY_CLSID, D2D1_PROPERTY_TYPE_CLSID, clsidW);
d2d_effect_properties_add(&object->properties, L"Cached", D2D1_PROPERTY_CACHED, D2D1_PROPERTY_TYPE_BOOL, L"false");
d2d_effect_properties_add(&object->properties, L"Precision", D2D1_PROPERTY_PRECISION, D2D1_PROPERTY_TYPE_ENUM, L"0");
d2d_effect_init_properties_vtbls(object);
- d2d_effect_SetInputCount(&object->ID2D1Effect_iface, default_input_count);
+ d2d_effect_SetInputCount(&object->ID2D1Effect_iface, reg->default_input_count);
- if (FAILED(hr = factory((IUnknown **)&object->impl)))
+ if (FAILED(hr = reg->factory((IUnknown **)&object->impl)))
{
WARN("Failed to create implementation object, hr %#lx.\n", hr);
ID2D1Effect_Release(&object->ID2D1Effect_iface);
diff --git a/dlls/d2d1/factory.c b/dlls/d2d1/factory.c
index 0a8a3bbd5b1..856af97cd43 100644
--- a/dlls/d2d1/factory.c
+++ b/dlls/d2d1/factory.c
@@ -48,6 +48,7 @@ struct d2d_factory
float dpi_y;
struct list effects;
+ INIT_ONCE init_builtins;
CRITICAL_SECTION cs;
};
@@ -67,12 +68,31 @@ static inline struct d2d_factory *impl_from_ID2D1Multithread(ID2D1Multithread *i
return CONTAINING_RECORD(iface, struct d2d_factory, ID2D1Multithread_iface);
}
+static BOOL WINAPI d2d_factory_builtins_initonce(INIT_ONCE *once, void *param, void **context)
+{
+ d2d_effects_init_builtins(param);
+
+ return TRUE;
+}
+
+static void d2d_factory_init_builtin_effects(struct d2d_factory *factory)
+{
+ InitOnceExecuteOnce(&factory->init_builtins, d2d_factory_builtins_initonce, factory, NULL);
+}
+
+void d2d_factory_register_effect(struct d2d_factory *factory, struct d2d_effect_registration *effect)
+{
+ list_add_tail(&factory->effects, &effect->entry);
+}
+
struct d2d_effect_registration * d2d_factory_get_registered_effect(ID2D1Factory *iface,
const GUID *id)
{
- const struct d2d_factory *factory = unsafe_impl_from_ID2D1Factory(iface);
+ struct d2d_factory *factory = unsafe_impl_from_ID2D1Factory(iface);
struct d2d_effect_registration *reg;
+ d2d_effects_init_builtins(factory);
+
LIST_FOR_EACH_ENTRY(reg, &factory->effects, struct d2d_effect_registration, entry)
{
if (IsEqualGUID(id, ®->id)) return reg;
@@ -884,10 +904,13 @@ static HRESULT STDMETHODCALLTYPE d2d_factory_RegisterEffectFromStream(ID2D1Facto
TRACE("iface %p, effect_id %s, property_xml %p, bindings %p, binding_count %u, effect_factory %p.\n",
iface, debugstr_guid(effect_id), property_xml, bindings, binding_count, effect_factory);
- LIST_FOR_EACH_ENTRY(effect, &factory->effects, struct d2d_effect_registration, entry)
+ d2d_factory_init_builtin_effects(factory);
+
+ LIST_FOR_EACH_ENTRY_REV(effect, &factory->effects, struct d2d_effect_registration, entry)
{
if (IsEqualGUID(effect_id, &effect->id))
{
+ if (effect->builtin) return E_INVALIDARG;
++effect->registration_count;
return S_OK;
}
@@ -948,7 +971,12 @@ static HRESULT STDMETHODCALLTYPE d2d_factory_RegisterEffectFromStream(ID2D1Facto
effect->registration_count = 1;
effect->id = *effect_id;
effect->factory = effect_factory;
- list_add_tail(&factory->effects, &effect->entry);
+ d2d_effect_properties_add(&effect->properties, L"MinInputs", D2D1_PROPERTY_MIN_INPUTS,
+ D2D1_PROPERTY_TYPE_UINT32, L"1");
+ d2d_effect_properties_add(&effect->properties, L"MaxInputs", D2D1_PROPERTY_MAX_INPUTS,
+ D2D1_PROPERTY_TYPE_UINT32, L"1" /* FIXME */);
+ effect->default_input_count = 1;
+ d2d_factory_register_effect(factory, effect);
return S_OK;
}
@@ -987,10 +1015,13 @@ static HRESULT STDMETHODCALLTYPE d2d_factory_UnregisterEffect(ID2D1Factory3 *ifa
TRACE("iface %p, effect_id %s.\n", iface, debugstr_guid(effect_id));
- LIST_FOR_EACH_ENTRY(effect, &factory->effects, struct d2d_effect_registration, entry)
+ d2d_factory_init_builtin_effects(factory);
+
+ LIST_FOR_EACH_ENTRY_REV(effect, &factory->effects, struct d2d_effect_registration, entry)
{
if (IsEqualGUID(effect_id, &effect->id))
{
+ if (effect->builtin) break;
if (!--effect->registration_count)
{
list_remove(&effect->entry);
@@ -1156,6 +1187,7 @@ static void d2d_factory_init(struct d2d_factory *factory, D2D1_FACTORY_TYPE fact
d2d_factory_reload_sysmetrics(factory);
list_init(&factory->effects);
InitializeCriticalSection(&factory->cs);
+ InitOnceInitialize(&factory->init_builtins);
}
HRESULT WINAPI D2D1CreateFactory(D2D1_FACTORY_TYPE factory_type, REFIID iid,
diff --git a/dlls/d2d1/tests/d2d1.c b/dlls/d2d1/tests/d2d1.c
index 05ebf10e666..585016890a6 100644
--- a/dlls/d2d1/tests/d2d1.c
+++ b/dlls/d2d1/tests/d2d1.c
@@ -10848,6 +10848,11 @@ static void test_effect_register(BOOL d3d11)
return;
}
+ /* Using builtin effect CLSID. */
+ hr = ID2D1Factory1_RegisterEffectFromString(factory, &CLSID_D2D1Crop, effect_xml_a, NULL,
+ 0, effect_impl_create);
+ ok(hr == E_INVALIDARG, "Got unexpected hr %#lx.\n", hr);
+
/* Register effect once */
for (i = 0; i < ARRAY_SIZE(xml_tests); ++i)
{
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/377
More information about the wine-devel
mailing list