d2d1/effect: Keep builtin effects in the same list as the custom once.

Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com>
This commit is contained in:
Ziqing Hui 2022-07-02 23:02:49 +03:00 committed by Alexandre Julliard
parent ffab990bd6
commit 97abb6d2ba
4 changed files with 78 additions and 49 deletions

View file

@ -643,14 +643,20 @@ struct d2d_effect_registration
struct list entry; struct list entry;
PD2D1_EFFECT_FACTORY factory; PD2D1_EFFECT_FACTORY factory;
UINT32 registration_count; UINT32 registration_count;
BOOL builtin;
CLSID id; CLSID id;
UINT32 input_count; UINT32 input_count;
UINT32 default_input_count;
struct d2d_effect_properties properties; 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, struct d2d_effect_registration * d2d_factory_get_registered_effect(ID2D1Factory *factory,
const GUID *effect_id) DECLSPEC_HIDDEN; 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 struct d2d_transform_graph
{ {

View file

@ -229,6 +229,33 @@ static const struct d2d_effect_info builtin_effects[] =
{&CLSID_D2D1Grayscale, 1, 1, 1}, {&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. */ /* Same syntax is used for value and default values. */
static HRESULT d2d_effect_parse_float_array(D2D1_PROPERTY_TYPE type, const WCHAR *value, static HRESULT d2d_effect_parse_float_array(D2D1_PROPERTY_TYPE type, const WCHAR *value,
float *vec) 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, HRESULT d2d_effect_create(struct d2d_device_context *context, const CLSID *effect_id,
ID2D1Effect **effect) ID2D1Effect **effect)
{ {
const struct d2d_effect_info *builtin = NULL;
struct d2d_effect_context *effect_context; struct d2d_effect_context *effect_context;
const struct d2d_effect_registration *reg; const struct d2d_effect_registration *reg;
unsigned int i, default_input_count;
struct d2d_transform_graph *graph; struct d2d_transform_graph *graph;
PD2D1_EFFECT_FACTORY factory;
struct d2d_effect *object; struct d2d_effect *object;
WCHAR clsidW[39]; WCHAR clsidW[39];
HRESULT hr; HRESULT hr;
if (!(reg = d2d_factory_get_registered_effect(context->factory, effect_id))) 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)); WARN("Effect id %s not found.\n", wine_dbgstr_guid(effect_id));
return D2DERR_EFFECT_IS_NOT_REGISTERED; 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; object->graph = graph;
/* Create properties */ /* 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_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;
}
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"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"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_properties_add(&object->properties, L"Precision", D2D1_PROPERTY_PRECISION, D2D1_PROPERTY_TYPE_ENUM, L"0");
d2d_effect_init_properties_vtbls(object); 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); WARN("Failed to create implementation object, hr %#lx.\n", hr);
ID2D1Effect_Release(&object->ID2D1Effect_iface); ID2D1Effect_Release(&object->ID2D1Effect_iface);

View file

@ -48,6 +48,7 @@ struct d2d_factory
float dpi_y; float dpi_y;
struct list effects; struct list effects;
INIT_ONCE init_builtins;
CRITICAL_SECTION cs; 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); 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, struct d2d_effect_registration * d2d_factory_get_registered_effect(ID2D1Factory *iface,
const GUID *id) 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; struct d2d_effect_registration *reg;
d2d_effects_init_builtins(factory);
LIST_FOR_EACH_ENTRY(reg, &factory->effects, struct d2d_effect_registration, entry) LIST_FOR_EACH_ENTRY(reg, &factory->effects, struct d2d_effect_registration, entry)
{ {
if (IsEqualGUID(id, &reg->id)) return reg; 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", 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); 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 (IsEqualGUID(effect_id, &effect->id))
{ {
if (effect->builtin) return E_INVALIDARG;
++effect->registration_count; ++effect->registration_count;
return S_OK; return S_OK;
} }
@ -948,7 +971,12 @@ static HRESULT STDMETHODCALLTYPE d2d_factory_RegisterEffectFromStream(ID2D1Facto
effect->registration_count = 1; effect->registration_count = 1;
effect->id = *effect_id; effect->id = *effect_id;
effect->factory = effect_factory; 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; 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)); 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 (IsEqualGUID(effect_id, &effect->id))
{ {
if (effect->builtin) break;
if (!--effect->registration_count) if (!--effect->registration_count)
{ {
list_remove(&effect->entry); 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); d2d_factory_reload_sysmetrics(factory);
list_init(&factory->effects); list_init(&factory->effects);
InitializeCriticalSection(&factory->cs); InitializeCriticalSection(&factory->cs);
InitOnceInitialize(&factory->init_builtins);
} }
HRESULT WINAPI D2D1CreateFactory(D2D1_FACTORY_TYPE factory_type, REFIID iid, HRESULT WINAPI D2D1CreateFactory(D2D1_FACTORY_TYPE factory_type, REFIID iid,

View file

@ -10848,6 +10848,11 @@ static void test_effect_register(BOOL d3d11)
return; 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 */ /* Register effect once */
for (i = 0; i < ARRAY_SIZE(xml_tests); ++i) for (i = 0; i < ARRAY_SIZE(xml_tests); ++i)
{ {