From 97abb6d2bad51d8c5d63ec1531519d5d642427a3 Mon Sep 17 00:00:00 2001 From: Ziqing Hui Date: Sat, 2 Jul 2022 23:02:49 +0300 Subject: [PATCH] d2d1/effect: Keep builtin effects in the same list as the custom once. Signed-off-by: Nikolay Sivov --- 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 */ + d2d_effect_duplicate_properties(&object->properties, ®->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_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) {