[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, &reg->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, &reg->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, &reg->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