Commit ce3d3f75 authored by Nikolay Sivov's avatar Nikolay Sivov Committed by Alexandre Julliard

d2d1: Implement GetEffectProperties().

parent ceefcca7
......@@ -651,6 +651,7 @@ struct d2d_effect_property
struct d2d_effect_properties
{
ID2D1Properties ID2D1Properties_iface;
LONG refcount;
struct d2d_effect *effect;
struct d2d_effect_property *properties;
......@@ -674,7 +675,7 @@ struct d2d_effect_registration
BOOL builtin;
CLSID id;
struct d2d_effect_properties properties;
struct d2d_effect_properties *properties;
};
struct d2d_factory
......@@ -785,6 +786,7 @@ struct d2d_effect
HRESULT d2d_effect_create(struct d2d_device_context *context, const CLSID *effect_id,
ID2D1Effect **effect);
void d2d_effect_init_properties(struct d2d_effect *effect, struct d2d_effect_properties *properties);
HRESULT d2d_effect_properties_add(struct d2d_effect_properties *props, const WCHAR *name,
UINT32 index, D2D1_PROPERTY_TYPE type, const WCHAR *value);
HRESULT d2d_effect_subproperties_add(struct d2d_effect_properties *props, const WCHAR *name,
......
......@@ -1150,19 +1150,14 @@ HRESULT d2d_effect_subproperties_add(struct d2d_effect_properties *props, const
return d2d_effect_properties_internal_add(props, name, index, TRUE, type, value);
}
static HRESULT d2d_effect_duplicate_properties(struct d2d_effect_properties *dst,
const struct d2d_effect_properties *src)
static HRESULT d2d_effect_duplicate_properties(struct d2d_effect *effect,
struct d2d_effect_properties *dst, const struct d2d_effect_properties *src)
{
HRESULT hr;
size_t i;
memset(dst, 0, sizeof(*dst));
dst->offset = src->offset;
dst->size = src->count;
dst->count = src->count;
dst->custom_count = src->custom_count;
dst->data.size = src->data.count;
dst->data.count = src->data.count;
*dst = *src;
dst->effect = effect;
if (!(dst->data.ptr = malloc(dst->data.size)))
return E_OUTOFMEMORY;
......@@ -1185,7 +1180,7 @@ static HRESULT d2d_effect_duplicate_properties(struct d2d_effect_properties *dst
{
if (!(d->subproperties = calloc(1, sizeof(*d->subproperties))))
return E_OUTOFMEMORY;
if (FAILED(hr = d2d_effect_duplicate_properties(d->subproperties, s->subproperties)))
if (FAILED(hr = d2d_effect_duplicate_properties(effect, d->subproperties, s->subproperties)))
return hr;
}
}
......@@ -1289,7 +1284,7 @@ static HRESULT d2d_effect_property_set_value(struct d2d_effect_properties *prope
struct d2d_effect_property *prop, D2D1_PROPERTY_TYPE type, const BYTE *value, UINT32 size)
{
struct d2d_effect *effect = properties->effect;
if (prop->readonly) return E_INVALIDARG;
if (prop->readonly || !effect) return E_INVALIDARG;
if (type != D2D1_PROPERTY_TYPE_UNKNOWN && prop->type != type) return E_INVALIDARG;
if (prop->get_function && !prop->set_function) return E_INVALIDARG;
if (prop->index < 0x80000000 && !prop->set_function) return E_INVALIDARG;
......@@ -1695,7 +1690,7 @@ static void d2d_effect_cleanup(struct d2d_effect *effect)
ID2D1EffectContext_Release(&effect->effect_context->ID2D1EffectContext_iface);
if (effect->graph)
ID2D1TransformGraph_Release(&effect->graph->ID2D1TransformGraph_iface);
d2d_effect_properties_cleanup(&effect->properties);
//d2d_effect_properties_cleanup(&effect->properties);
if (effect->impl)
ID2D1EffectImpl_Release(effect->impl);
}
......@@ -2074,13 +2069,30 @@ static HRESULT STDMETHODCALLTYPE d2d_effect_properties_QueryInterface(ID2D1Prope
static ULONG STDMETHODCALLTYPE d2d_effect_properties_AddRef(ID2D1Properties *iface)
{
struct d2d_effect_properties *properties = impl_from_ID2D1Properties(iface);
return ID2D1Effect_AddRef(&properties->effect->ID2D1Effect_iface);
if (properties->effect)
return ID2D1Effect_AddRef(&properties->effect->ID2D1Effect_iface);
return InterlockedIncrement(&properties->refcount);
}
static ULONG STDMETHODCALLTYPE d2d_effect_properties_Release(ID2D1Properties *iface)
{
struct d2d_effect_properties *properties = impl_from_ID2D1Properties(iface);
return ID2D1Effect_Release(&properties->effect->ID2D1Effect_iface);
ULONG refcount;
if (properties->effect)
return ID2D1Effect_Release(&properties->effect->ID2D1Effect_iface);
refcount = InterlockedDecrement(&properties->refcount);
if (!refcount)
{
d2d_effect_properties_cleanup(properties);
free(properties);
}
return refcount;
}
static UINT32 STDMETHODCALLTYPE d2d_effect_properties_GetPropertyCount(ID2D1Properties *iface)
......@@ -2252,20 +2264,12 @@ static const ID2D1PropertiesVtbl d2d_effect_properties_vtbl =
d2d_effect_properties_GetSubProperties,
};
static void d2d_effect_init_properties_vtbls(struct d2d_effect *effect)
void d2d_effect_init_properties(struct d2d_effect *effect,
struct d2d_effect_properties *properties)
{
unsigned int i;
effect->properties.ID2D1Properties_iface.lpVtbl = &d2d_effect_properties_vtbl;
effect->properties.effect = effect;
for (i = 0; i < effect->properties.count; ++i)
{
struct d2d_effect_property *prop = &effect->properties.properties[i];
if (!prop->subproperties) continue;
prop->subproperties->ID2D1Properties_iface.lpVtbl = &d2d_effect_properties_vtbl;
prop->subproperties->effect = effect;
}
properties->ID2D1Properties_iface.lpVtbl = &d2d_effect_properties_vtbl;
properties->effect = effect;
properties->refcount = 1;
}
static struct d2d_render_info *impl_from_ID2D1DrawInfo(ID2D1DrawInfo *iface)
......@@ -2512,13 +2516,12 @@ HRESULT d2d_effect_create(struct d2d_device_context *context, const CLSID *effec
object->effect_context = effect_context;
/* Create properties */
d2d_effect_duplicate_properties(&object->properties, &reg->properties);
d2d_effect_duplicate_properties(object, &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);
/* Sync instance input count with default input count from the description. */
d2d_effect_get_value(object, D2D1_PROPERTY_INPUTS, D2D1_PROPERTY_TYPE_ARRAY, (BYTE *)&input_count, sizeof(input_count));
......
......@@ -32,7 +32,7 @@ struct d2d_settings d2d_settings =
static void d2d_effect_registration_cleanup(struct d2d_effect_registration *reg)
{
d2d_effect_properties_cleanup(&reg->properties);
ID2D1Properties_Release(&reg->properties->ID2D1Properties_iface);
free(reg);
}
......@@ -724,10 +724,10 @@ static struct d2d_effect_property * parse_effect_get_property(const struct d2d_e
{
unsigned int i;
for (i = 0; i < effect->properties.count; ++i)
for (i = 0; i < effect->properties->count; ++i)
{
if (!wcscmp(name, effect->properties.properties[i].name))
return &effect->properties.properties[i];
if (!wcscmp(name, effect->properties->properties[i].name))
return &effect->properties->properties[i];
}
return NULL;
......@@ -776,8 +776,8 @@ static HRESULT parse_effect_property(IXmlReader *reader, struct d2d_effect_regis
if (SUCCEEDED(hr))
{
index = parse_effect_get_property_index(&effect->properties, name);
hr = d2d_effect_properties_add(&effect->properties, name, index, type, value);
index = parse_effect_get_property_index(effect->properties, name);
hr = d2d_effect_properties_add(effect->properties, name, index, type, value);
}
free(value);
......@@ -797,14 +797,15 @@ static HRESULT parse_effect_inputs(IXmlReader *reader, struct d2d_effect_registr
WCHAR buffW[16];
HRESULT hr;
if (FAILED(hr = d2d_effect_properties_add(&effect->properties, L"Inputs",
if (FAILED(hr = d2d_effect_properties_add(effect->properties, L"Inputs",
D2D1_PROPERTY_INPUTS, D2D1_PROPERTY_TYPE_ARRAY, NULL)))
return hr;
if (!(inputs = d2d_effect_properties_get_property_by_name(&effect->properties, L"Inputs")))
if (!(inputs = d2d_effect_properties_get_property_by_name(effect->properties, L"Inputs")))
return E_FAIL;
if (!(inputs->subproperties = calloc(1, sizeof(*inputs->subproperties))))
return E_OUTOFMEMORY;
d2d_effect_init_properties(NULL, inputs->subproperties);
subproperties = inputs->subproperties;
d2d_effect_subproperties_add(subproperties, L"IsReadOnly", D2D1_SUBPROPERTY_ISREADONLY,
......@@ -814,21 +815,21 @@ static HRESULT parse_effect_inputs(IXmlReader *reader, struct d2d_effect_registr
if (SUCCEEDED(parse_effect_get_attribute(reader, L"minimum", &value)))
{
hr = d2d_effect_properties_add(&effect->properties, L"MinInputs", D2D1_PROPERTY_MIN_INPUTS,
hr = d2d_effect_properties_add(effect->properties, L"MinInputs", D2D1_PROPERTY_MIN_INPUTS,
D2D1_PROPERTY_TYPE_UINT32, value);
free(value);
if (FAILED(hr)) return hr;
}
if (SUCCEEDED(parse_effect_get_attribute(reader, L"maximum", &value)))
{
hr = d2d_effect_properties_add(&effect->properties, L"MaxInputs", D2D1_PROPERTY_MAX_INPUTS,
hr = d2d_effect_properties_add(effect->properties, L"MaxInputs", D2D1_PROPERTY_MAX_INPUTS,
D2D1_PROPERTY_TYPE_UINT32, value);
free(value);
if (FAILED(hr)) return hr;
}
min_inputs = d2d_effect_properties_get_property_by_name(&effect->properties, L"MinInputs");
max_inputs = d2d_effect_properties_get_property_by_name(&effect->properties, L"MaxInputs");
min_inputs = d2d_effect_properties_get_property_by_name(effect->properties, L"MinInputs");
max_inputs = d2d_effect_properties_get_property_by_name(effect->properties, L"MaxInputs");
if (!IXmlReader_IsEmptyElement(reader))
{
......@@ -846,16 +847,16 @@ static HRESULT parse_effect_inputs(IXmlReader *reader, struct d2d_effect_registr
free(name);
}
*(UINT32 *)(effect->properties.data.ptr + inputs->data.offset) = input_count;
*(UINT32 *)(effect->properties->data.ptr + inputs->data.offset) = input_count;
if (FAILED(hr = IXmlReader_GetNodeType(reader, &node_type))) return hr;
if (node_type != XmlNodeType_EndElement) return HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
}
if (min_inputs)
d2d_effect_property_get_uint32_value(&effect->properties, min_inputs, &min_inputs_value);
d2d_effect_property_get_uint32_value(effect->properties, min_inputs, &min_inputs_value);
if (max_inputs)
d2d_effect_property_get_uint32_value(&effect->properties, max_inputs, &max_inputs_value);
d2d_effect_property_get_uint32_value(effect->properties, max_inputs, &max_inputs_value);
/* Validate the range */
if (min_inputs && max_inputs)
......@@ -885,16 +886,16 @@ static HRESULT parse_effect_inputs(IXmlReader *reader, struct d2d_effect_registr
{
swprintf(buffW, ARRAY_SIZE(buffW), L"%lu", min_inputs ? min_inputs_value : max_inputs_value);
if (min_inputs)
hr = d2d_effect_properties_add(&effect->properties, L"MaxInputs", D2D1_PROPERTY_MAX_INPUTS, D2D1_PROPERTY_TYPE_UINT32, buffW);
hr = d2d_effect_properties_add(effect->properties, L"MaxInputs", D2D1_PROPERTY_MAX_INPUTS, D2D1_PROPERTY_TYPE_UINT32, buffW);
else
hr = d2d_effect_properties_add(&effect->properties, L"MinInputs", D2D1_PROPERTY_MIN_INPUTS, D2D1_PROPERTY_TYPE_UINT32, buffW);
hr = d2d_effect_properties_add(effect->properties, L"MinInputs", D2D1_PROPERTY_MIN_INPUTS, D2D1_PROPERTY_TYPE_UINT32, buffW);
}
else if (!min_inputs)
{
swprintf(buffW, ARRAY_SIZE(buffW), L"%lu", input_count);
hr = d2d_effect_properties_add(&effect->properties, L"MinInputs", D2D1_PROPERTY_MIN_INPUTS, D2D1_PROPERTY_TYPE_UINT32, buffW);
hr = d2d_effect_properties_add(effect->properties, L"MinInputs", D2D1_PROPERTY_MIN_INPUTS, D2D1_PROPERTY_TYPE_UINT32, buffW);
if (SUCCEEDED(hr))
hr = d2d_effect_properties_add(&effect->properties, L"MaxInputs", D2D1_PROPERTY_MAX_INPUTS, D2D1_PROPERTY_TYPE_UINT32, buffW);
hr = d2d_effect_properties_add(effect->properties, L"MaxInputs", D2D1_PROPERTY_MAX_INPUTS, D2D1_PROPERTY_TYPE_UINT32, buffW);
}
return hr;
......@@ -973,6 +974,13 @@ static HRESULT d2d_factory_register_effect_from_stream(struct d2d_factory *facto
IXmlReader_Release(reader);
return E_OUTOFMEMORY;
}
if (!(effect->properties = calloc(1, sizeof(*effect->properties))))
{
IXmlReader_Release(reader);
free(effect);
return E_OUTOFMEMORY;
}
d2d_effect_init_properties(NULL, effect->properties);
effect->builtin = builtin;
hr = parse_effect_xml(reader, effect);
......@@ -1015,6 +1023,7 @@ static HRESULT d2d_factory_register_effect_from_stream(struct d2d_factory *facto
effect->registration_count = 1;
effect->id = *effect_id;
effect->factory = effect_factory;
d2d_factory_register_effect(factory, effect);
return S_OK;
......@@ -1146,9 +1155,23 @@ static HRESULT STDMETHODCALLTYPE d2d_factory_GetRegisteredEffects(ID2D1Factory3
static HRESULT STDMETHODCALLTYPE d2d_factory_GetEffectProperties(ID2D1Factory3 *iface,
REFCLSID effect_id, ID2D1Properties **props)
{
FIXME("iface %p, effect_id %s, props %p stub!\n", iface, debugstr_guid(effect_id), props);
struct d2d_factory *factory = impl_from_ID2D1Factory3(iface);
const struct d2d_effect_registration *reg;
return E_NOTIMPL;
TRACE("iface %p, effect_id %s, props %p.\n", iface, debugstr_guid(effect_id), props);
d2d_factory_init_builtin_effects(factory);
if (!(reg = d2d_factory_get_registered_effect((ID2D1Factory *)iface, effect_id)))
{
WARN("Effect id %s not found.\n", wine_dbgstr_guid(effect_id));
return HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
}
*props = &reg->properties->ID2D1Properties_iface;
ID2D1Properties_AddRef(*props);
return S_OK;
}
static HRESULT STDMETHODCALLTYPE d2d_factory_ID2D1Factory2_CreateDevice(ID2D1Factory3 *iface, IDXGIDevice *dxgi_device,
......
......@@ -482,6 +482,14 @@ static void set_rect(D2D1_RECT_F *rect, float left, float top, float right, floa
rect->bottom = bottom;
}
static void set_vec4(D2D_VECTOR_4F *vec, float x, float y, float z, float w)
{
vec->x = x;
vec->y = y;
vec->z = z;
vec->w = w;
}
static void set_rounded_rect(D2D1_ROUNDED_RECT *rect, float left, float top, float right, float bottom,
float radius_x, float radius_y)
{
......@@ -14696,6 +14704,88 @@ static void test_effect_custom_pixel_shader(BOOL d3d11)
release_test_context(&ctx);
}
static void test_get_effect_properties(BOOL d3d11)
{
ID2D1Properties *properties, *properties2;
struct d2d1_test_context ctx;
D2D_VECTOR_4F rect, rect2;
D2D1_PROPERTY_TYPE type;
ID2D1Factory1 *factory;
UINT32 count, index;
WCHAR buffW[64];
ULONG refcount;
HRESULT hr;
if (!init_test_context(&ctx, d3d11))
return;
factory = ctx.factory1;
if (!factory)
{
release_test_context(&ctx);
return;
}
hr = ID2D1Factory1_GetEffectProperties(factory, &GUID_NULL, &properties);
ok(hr == HRESULT_FROM_WIN32(ERROR_NOT_FOUND), "Unexpected hr %#lx.\n", hr);
hr = ID2D1Factory1_GetEffectProperties(factory, &CLSID_D2D1Crop, &properties);
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
refcount = get_refcount(properties);
ok(refcount == 2, "Unexpected refcount %lu.\n", refcount);
hr = ID2D1Factory1_GetEffectProperties(factory, &CLSID_D2D1Crop, &properties2);
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
ok(properties == properties2, "Unexpected instance.\n");
refcount = get_refcount(properties);
ok(refcount == 3, "Unexpected refcount %lu.\n", refcount);
ID2D1Properties_Release(properties2);
count = ID2D1Properties_GetPropertyCount(properties);
todo_wine
ok(count == 2, "Unexpected property count %u.\n", count);
hr = ID2D1Properties_GetPropertyName(properties, 0, buffW, ARRAY_SIZE(buffW));
todo_wine
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
if (SUCCEEDED(hr))
ok(!wcscmp(buffW, L"Rect"), "Unexpected name %s.\n", debugstr_w(buffW));
count = ID2D1Properties_GetPropertyNameLength(properties, 0);
todo_wine
ok(count == 4, "Unexpected name length %u.\n", count);
type = ID2D1Properties_GetType(properties, 0);
todo_wine
ok(type == D2D1_PROPERTY_TYPE_VECTOR4, "Unexpected property type %u.\n", type);
index = ID2D1Properties_GetPropertyIndex(properties, L"prop");
ok(index == ~0u, "Unexpected index %u.\n", index);
set_vec4(&rect, 0.0f, 2.0f, 10.0f, 20.0f);
hr = ID2D1Properties_SetValue(properties, D2D1_CROP_PROP_RECT, D2D1_PROPERTY_TYPE_VECTOR4,
(const BYTE *)&rect, sizeof(rect));
todo_wine
ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
hr = ID2D1Properties_SetValue(properties, 1000, D2D1_PROPERTY_TYPE_VECTOR4,
(const BYTE *)&rect, sizeof(rect));
ok(hr == D2DERR_INVALID_PROPERTY, "Unexpected hr %#lx.\n", hr);
set_vec4(&rect2, 1.0f, 2.0f, 3.0f, 4.0f);
set_vec4(&rect, 0.0f, .0f, 0.0f, 0.0f);
hr = ID2D1Properties_GetValue(properties, D2D1_CROP_PROP_RECT, D2D1_PROPERTY_TYPE_VECTOR4,
(BYTE *)&rect2, sizeof(rect2));
todo_wine
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
if (SUCCEEDED(hr))
ok(!memcmp(&rect, &rect2, sizeof(rect)), "Unexpected value.\n");
ID2D1Properties_Release(properties);
release_test_context(&ctx);
}
START_TEST(d2d1)
{
HMODULE d2d1_dll = GetModuleHandleA("d2d1.dll");
......@@ -14787,6 +14877,7 @@ START_TEST(d2d1)
queue_test(test_bitmap_map);
queue_test(test_bitmap_create);
queue_test(test_effect_custom_pixel_shader);
queue_test(test_get_effect_properties);
run_queued_tests();
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment