Signed-off-by: Ziqing Hui zhui@codeweavers.com ---
This patch is resend to see the its result on test bot.
dlls/d2d1/tests/d2d1.c | 301 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 301 insertions(+)
diff --git a/dlls/d2d1/tests/d2d1.c b/dlls/d2d1/tests/d2d1.c index 663fc150df8..0a8245d6805 100644 --- a/dlls/d2d1/tests/d2d1.c +++ b/dlls/d2d1/tests/d2d1.c @@ -21,6 +21,7 @@ #include <math.h> #include <float.h> #include "d2d1_3.h" +#include "d2d1effectauthor.h" #include "d3d11.h" #include "wincrypt.h" #include "wine/test.h" @@ -29,6 +30,62 @@ #include "wincodec.h" #include "wine/heap.h"
+DEFINE_GUID(CLSID_TestEffect, 0xb9ee12e9,0x32d9,0xe659,0xac,0x61,0x2d,0x7c,0xea,0x69,0x28,0x78); + +static const WCHAR *effect_xml_a = +L"<?xml version='1.0'?> \ + <Effect> \ + <Property name='DisplayName' type='string' value='TestEffect'/> \ + <Property name='Author' type='string' value='The Wine Project'/> \ + <Property name='Category' type='string' value='Test'/> \ + <Property name='Description' type='string' value='Test effect.'/> \ + <Inputs> \ + <Input name='Source'/> \ + </Inputs> \ + <Property name='Integer' type='uint32'> \ + <Property name='DisplayName' type='string' value='Integer'/> \ + <Property name='Min' type='uint32' value='0'/> \ + <Property name='Max' type='uint32' value='100'/> \ + <Property name='Default' type='uint32' value='10'/> \ + </Property> \ + </Effect> \ +"; + +static const WCHAR *effect_xml_b = +L"<?xml version='1.0'?> \ + <Effect> \ + <Property name='DisplayName' type='string' value='TestEffect'/> \ + <Property name='Author' type='string' value='The Wine Project'/> \ + <Property name='Category' type='string' value='Test'/> \ + <Property name='Description' type='string' value='Test effect.'/> \ + <Inputs> \ + <Input name='Source'/> \ + </Inputs> \ + <Property name='Context' type='iunknown'> \ + <Property name='DisplayName' type='string' value='Context'/> \ + </Property> \ + </Effect> \ +"; + +static const WCHAR *effect_xml_c = +L"<?xml version='1.0'?> \ + <Effect> \ + <Property name='DisplayName' type='string' value='TestEffect'/> \ + <Property name='Author' type='string' value='The Wine Project'/> \ + <Property name='Category' type='string' value='Test'/> \ + <Property name='Description' type='string' value='Test effect.'/> \ + <Inputs> \ + <Input name='Source'/> \ + </Inputs> \ + <Property name='Context' type='iunknown'> \ + <Property name='DisplayName' type='string' value='Context'/> \ + </Property> \ + <Property name='Integer' type='uint32'> \ + <Property name='DisplayName' type='string' value='Integer'/> \ + </Property> \ + </Effect> \ +"; + static HRESULT (WINAPI *pD2D1CreateDevice)(IDXGIDevice *dxgi_device, const D2D1_CREATION_PROPERTIES *properties, ID2D1Device **device); static void (WINAPI *pD2D1SinCos)(float angle, float *s, float *c); @@ -118,6 +175,14 @@ struct expected_geometry_figure const struct geometry_segment *segments; };
+struct effect_impl +{ + ID2D1EffectImpl ID2D1EffectImpl_iface; + LONG refcount; + UINT integer; + ID2D1EffectContext *effect_context; +}; + static void queue_d3d1x_test(void (*test)(BOOL d3d11), BOOL d3d11) { if (mt_test_count >= mt_tests_size) @@ -10296,6 +10361,241 @@ static void test_effect(BOOL d3d11) release_test_context(&ctx); }
+static inline struct effect_impl *impl_from_ID2D1EffectImpl(ID2D1EffectImpl *iface) +{ + return CONTAINING_RECORD(iface, struct effect_impl, ID2D1EffectImpl_iface); +} + +static HRESULT STDMETHODCALLTYPE effect_impl_QueryInterface(ID2D1EffectImpl *iface, REFIID iid, void **out) +{ + if (IsEqualGUID(iid, &IID_ID2D1EffectImpl) + || IsEqualGUID(iid, &IID_IUnknown)) + { + ID2D1EffectImpl_AddRef(iface); + *out = iface; + return S_OK; + } + + *out = NULL; + return E_NOINTERFACE; +} + +static ULONG STDMETHODCALLTYPE effect_impl_AddRef(ID2D1EffectImpl *iface) +{ + struct effect_impl *effect_impl = impl_from_ID2D1EffectImpl(iface); + ULONG refcount = InterlockedIncrement(&effect_impl->refcount); + return refcount; +} + +static ULONG STDMETHODCALLTYPE effect_impl_Release(ID2D1EffectImpl *iface) +{ + struct effect_impl *effect_impl = impl_from_ID2D1EffectImpl(iface); + ULONG refcount = InterlockedDecrement(&effect_impl->refcount); + + if (!refcount) + { + if (effect_impl->effect_context) + ID2D1EffectContext_Release(effect_impl->effect_context); + heap_free(effect_impl); + } + + return refcount; +} + +static HRESULT STDMETHODCALLTYPE effect_impl_Initialize(ID2D1EffectImpl *iface, + ID2D1EffectContext *context,ID2D1TransformGraph *graph) +{ + struct effect_impl *effect_impl = impl_from_ID2D1EffectImpl(iface); + ID2D1EffectContext_AddRef(effect_impl->effect_context = context); + return S_OK; +} + +static HRESULT STDMETHODCALLTYPE effect_impl_PrepareForRender(ID2D1EffectImpl *iface, D2D1_CHANGE_TYPE type) +{ + return S_OK; +} + +static HRESULT STDMETHODCALLTYPE effect_impl_SetGraph(ID2D1EffectImpl *iface, ID2D1TransformGraph *graph) +{ + return E_NOTIMPL; +} + +static const ID2D1EffectImplVtbl effect_impl_vtbl = +{ + effect_impl_QueryInterface, + effect_impl_AddRef, + effect_impl_Release, + effect_impl_Initialize, + effect_impl_PrepareForRender, + effect_impl_SetGraph, +}; + +static HRESULT STDMETHODCALLTYPE effect_impl_create(IUnknown **effect_impl) +{ + struct effect_impl *object; + + if (!(object = heap_alloc(sizeof(*object)))) + return E_OUTOFMEMORY; + + object->ID2D1EffectImpl_iface.lpVtbl = &effect_impl_vtbl; + object->refcount = 1; + object->integer = 0; + object->effect_context = NULL; + + *effect_impl = (IUnknown *)&object->ID2D1EffectImpl_iface; + return S_OK; +} + +static HRESULT STDMETHODCALLTYPE effect_impl_set_integer(IUnknown *iface, const BYTE *data, UINT32 data_size) +{ + struct effect_impl *effect_impl = impl_from_ID2D1EffectImpl((ID2D1EffectImpl *)iface); + + if (!data || data_size != sizeof(effect_impl->integer)) + return E_INVALIDARG; + + effect_impl->integer = *((UINT *)data); + + return S_OK; +} + +static HRESULT STDMETHODCALLTYPE effect_impl_get_integer(const IUnknown *iface, + BYTE *data, UINT32 data_size, UINT32 *actual_size) +{ + struct effect_impl *effect_impl = impl_from_ID2D1EffectImpl((ID2D1EffectImpl *)iface); + + if (!data || data_size != sizeof(effect_impl->integer)) + return E_INVALIDARG; + + *((UINT *)data) = effect_impl->integer; + if (actual_size) + *actual_size = sizeof(effect_impl->integer); + + return S_OK; +} + +static HRESULT STDMETHODCALLTYPE effect_impl_get_context(const IUnknown *iface, + BYTE *data, UINT32 data_size, UINT32 *actual_size) +{ + struct effect_impl *effect_impl = impl_from_ID2D1EffectImpl((ID2D1EffectImpl *)iface); + + if (!data || data_size != sizeof(effect_impl->effect_context)) + return E_INVALIDARG; + + *((ID2D1EffectContext **)data) = effect_impl->effect_context; + if (actual_size) + *actual_size = sizeof(effect_impl->effect_context); + + return S_OK; +} + +static void test_effect_register(BOOL d3d11) +{ + struct d2d1_test_context ctx; + ID2D1Factory1 *factory; + unsigned int i; + HRESULT hr; + + const D2D1_PROPERTY_BINDING binding[] = + { + {L"Integer", effect_impl_set_integer, effect_impl_get_integer}, + {L"Context", NULL, effect_impl_get_context}, + {L"Integer", NULL, effect_impl_get_integer}, + {L"Integer", effect_impl_set_integer, NULL}, + {L"Integer", NULL, NULL}, + {L"DeadBeef", effect_impl_set_integer, effect_impl_get_integer}, + }; + + const struct binding_test + { + const D2D1_PROPERTY_BINDING *binding; + UINT32 binding_count; + const WCHAR *effect_xml; + HRESULT hr; + } + binding_tests[] = + { + {NULL, 0, effect_xml_a, S_OK}, + {NULL, 0, effect_xml_b, S_OK}, + {binding, 1, effect_xml_a, S_OK}, + {binding, 1, effect_xml_b, D2DERR_INVALID_PROPERTY}, + {binding + 1, 1, effect_xml_b, S_OK}, + {binding + 2, 1, effect_xml_a, S_OK}, + {binding + 3, 1, effect_xml_a, S_OK}, + {binding + 4, 1, effect_xml_a, S_OK}, + {binding + 5, 1, effect_xml_a, D2DERR_INVALID_PROPERTY}, + {binding, 2, effect_xml_a, D2DERR_INVALID_PROPERTY}, + {binding, 2, effect_xml_b, D2DERR_INVALID_PROPERTY}, + {binding, 2, effect_xml_c, S_OK}, + }; + + if (!init_test_context(&ctx, d3d11)) + return; + + if (!(factory = create_factory(&IID_ID2D1Factory1, NULL))) + { + win_skip("ID2D1Factory1 is not supported.\n"); + release_test_context(&ctx); + return; + } + + /* Register effect once */ + hr = ID2D1Factory1_RegisterEffectFromString(factory, &CLSID_TestEffect, + effect_xml_a, NULL, 0, effect_impl_create); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + hr = ID2D1Factory1_UnregisterEffect(factory, &CLSID_TestEffect); + todo_wine ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + hr = ID2D1Factory1_UnregisterEffect(factory, &CLSID_TestEffect); + todo_wine ok(hr == D2DERR_EFFECT_IS_NOT_REGISTERED, "Got unexpected hr %#lx.\n", hr); + + /* Register effect multiple times */ + hr = ID2D1Factory1_RegisterEffectFromString(factory, &CLSID_TestEffect, + effect_xml_a, NULL, 0, effect_impl_create); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + hr = ID2D1Factory1_RegisterEffectFromString(factory, &CLSID_TestEffect, + effect_xml_a, NULL, 0, effect_impl_create); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + hr = ID2D1Factory1_UnregisterEffect(factory, &CLSID_TestEffect); + todo_wine ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + hr = ID2D1Factory1_UnregisterEffect(factory, &CLSID_TestEffect); + todo_wine ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + hr = ID2D1Factory1_UnregisterEffect(factory, &CLSID_TestEffect); + todo_wine ok(hr == D2DERR_EFFECT_IS_NOT_REGISTERED, "Got unexpected hr %#lx.\n", hr); + + /* Register effect multiple times with different xml */ + hr = ID2D1Factory1_RegisterEffectFromString(factory, &CLSID_TestEffect, + effect_xml_a, NULL, 0, effect_impl_create); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + hr = ID2D1Factory1_RegisterEffectFromString(factory, &CLSID_TestEffect, + effect_xml_b, NULL, 0, effect_impl_create); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + hr = ID2D1Factory1_UnregisterEffect(factory, &CLSID_TestEffect); + todo_wine ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + hr = ID2D1Factory1_UnregisterEffect(factory, &CLSID_TestEffect); + todo_wine ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + + /* Register effect with property binding */ + for (i = 0; i < ARRAY_SIZE(binding_tests); ++i) + { + const struct binding_test *test = &binding_tests[i]; + winetest_push_context("Test %u", i); + + hr = ID2D1Factory1_RegisterEffectFromString(factory, &CLSID_TestEffect, + test->effect_xml, test->binding, test->binding_count, effect_impl_create); + todo_wine_if(test->hr != S_OK) + ok(hr == test->hr, "Got unexpected hr %#lx, expected %#lx.\n", hr, test->hr); + ID2D1Factory1_UnregisterEffect(factory, &CLSID_TestEffect); + + winetest_pop_context(); + } + + /* Unregister builtin effect */ + hr = ID2D1Factory1_UnregisterEffect(factory, &CLSID_D2D1Composite); + todo_wine ok(hr == D2DERR_EFFECT_IS_NOT_REGISTERED, "Got unexpected hr %#lx.\n", hr); + + ID2D1Factory1_Release(factory); + release_test_context(&ctx); +} + static void test_effect_2d_affine(BOOL d3d11) { D2D1_MATRIX_3X2_F rotate, scale, skew; @@ -11088,6 +11388,7 @@ START_TEST(d2d1) queue_d3d10_test(test_colour_space); queue_test(test_geometry_group); queue_test(test_mt_factory); + queue_test(test_effect_register); queue_test(test_effect); queue_test(test_effect_2d_affine); queue_test(test_effect_crop);
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=115229
Your paranoid android.
=== debian11 (32 bit Hindi:India report) ===
d2d1: Unhandled exception: page fault on write access to 0x00000000 in 32-bit code (0x6ac0f55f).