From: Nikolay Sivov nsivov@codeweavers.com
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/d2d1/tests/d2d1.c | 341 +++++++++++++++++++++++++++++++++++++---- 1 file changed, 313 insertions(+), 28 deletions(-)
diff --git a/dlls/d2d1/tests/d2d1.c b/dlls/d2d1/tests/d2d1.c index 9ae815dcc64..553d9e1469b 100644 --- a/dlls/d2d1/tests/d2d1.c +++ b/dlls/d2d1/tests/d2d1.c @@ -32,8 +32,10 @@ #include "wincodec.h"
DEFINE_GUID(CLSID_TestEffect, 0xb9ee12e9,0x32d9,0xe659,0xac,0x61,0x2d,0x7c,0xea,0x69,0x28,0x78); +DEFINE_GUID(CLSID_AuxEffect, 0xb9ee12e9,0x32d9,0xe659,0xac,0x61,0x2d,0x7c,0xea,0x69,0x28,0x79); DEFINE_GUID(GUID_TestVertexShader, 0x5bcdcfae,0x1e92,0x4dc1,0x94,0xfa,0x3b,0x01,0xca,0x54,0x59,0x20); DEFINE_GUID(GUID_TestPixelShader, 0x53015748,0xfc13,0x4168,0xbd,0x13,0x0f,0xcf,0x15,0x29,0x7f,0x01); +DEFINE_GUID(GUID_CustomVertexBuffer, 0x53015748,0xfc13,0x4168,0xbd,0x13,0x0f,0xcf,0x15,0x29,0x7f,0x02);
static ULONG get_refcount(void *iface) { @@ -389,6 +391,10 @@ struct effect_impl ID2D1EffectContext *effect_context; ID2D1TransformGraph *transform_graph; ID2D1DrawInfo *draw_info; + + const GUID *vertex_buffer; + const GUID *vertex_shader; + const GUID *pixel_shader; };
static void queue_d3d1x_test(void (*test)(BOOL d3d11), BOOL d3d11) @@ -14515,35 +14521,16 @@ static void test_dc_target_is_supported(BOOL d3d11) static HRESULT STDMETHODCALLTYPE ps_effect_impl_Initialize(ID2D1EffectImpl *iface, ID2D1EffectContext *context, ID2D1TransformGraph *graph) { - static const char ps_code[] = - "float4 main() : sv_target\n" - "{\n" - " return float4(0.1, 0.2, 0.3, 0.4);\n" - "}"; - struct effect_impl *effect_impl = impl_from_ID2D1EffectImpl(iface); - ID3D10Blob *blob; - HRESULT hr;
effect_impl->effect_context = context; ID2D1EffectContext_AddRef(effect_impl->effect_context);
- hr = D3DCompile(ps_code, strlen(ps_code), "test_ps", NULL, NULL, "main", - "ps_4_0", 0, 0, &blob, NULL); - ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - - if (SUCCEEDED(hr = ID2D1EffectContext_LoadPixelShader(context, &GUID_TestPixelShader, - ID3D10Blob_GetBufferPointer(blob), ID3D10Blob_GetBufferSize(blob)))) - { - hr = ID2D1TransformGraph_SetSingleTransformNode(graph, + return ID2D1TransformGraph_SetSingleTransformNode(graph, (ID2D1TransformNode *)&effect_impl->ID2D1DrawTransform_iface); - } - - ID3D10Blob_Release(blob); - return hr; }
-static const ID2D1EffectImplVtbl ps_effect_impl_vtbl = +static const ID2D1EffectImplVtbl custom_effect_impl_vtbl = { effect_impl_QueryInterface, effect_impl_AddRef, @@ -14611,6 +14598,9 @@ static HRESULT STDMETHODCALLTYPE effect_impl_draw_transform_MapInvalidRect( static HRESULT STDMETHODCALLTYPE effect_impl_draw_transform_SetDrawInfo(ID2D1DrawTransform *iface, ID2D1DrawInfo *info) { + struct effect_impl *effect_impl = impl_from_ID2D1DrawTransform(iface); + ID2D1VertexBuffer *buffer = NULL; + HRESULT hr = S_OK; ULONG refcount;
check_interface(info, &IID_IUnknown, TRUE); @@ -14620,10 +14610,28 @@ static HRESULT STDMETHODCALLTYPE effect_impl_draw_transform_SetDrawInfo(ID2D1Dra refcount = get_refcount(info); ok(refcount == 1, "Unexpected refcount %lu.\n", refcount);
- return ID2D1DrawInfo_SetPixelShader(info, &GUID_TestPixelShader, 0); + if (effect_impl->pixel_shader) + hr = ID2D1DrawInfo_SetPixelShader(info, effect_impl->pixel_shader, 0); + + if (SUCCEEDED(hr) && (effect_impl->vertex_buffer || effect_impl->vertex_shader)) + { + if (effect_impl->vertex_buffer) + { + hr = ID2D1EffectContext_FindVertexBuffer(effect_impl->effect_context, + effect_impl->vertex_buffer, &buffer); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + } + + hr = ID2D1DrawInfo_SetVertexProcessing(info, buffer, 0, NULL, NULL, effect_impl->vertex_shader); + } + + if (buffer) + ID2D1VertexBuffer_Release(buffer); + + return hr; }
-static const ID2D1DrawTransformVtbl ps_effect_draw_transform_vtbl = +static const ID2D1DrawTransformVtbl custom_shader_effect_draw_transform_vtbl = { effect_impl_draw_transform_QueryInterface, effect_impl_draw_transform_AddRef, @@ -14635,21 +14643,78 @@ static const ID2D1DrawTransformVtbl ps_effect_draw_transform_vtbl = effect_impl_draw_transform_SetDrawInfo, };
-static HRESULT STDMETHODCALLTYPE ps_effect_impl_create(IUnknown **effect_impl) +static HRESULT create_custom_shader_effect(IUnknown **effect_impl, const GUID *pixel_shader, + const GUID *vertex_shader, const GUID *vertex_buffer) { struct effect_impl *object;
if (!(object = calloc(1, sizeof(*object)))) return E_OUTOFMEMORY;
- object->ID2D1EffectImpl_iface.lpVtbl = &ps_effect_impl_vtbl; - object->ID2D1DrawTransform_iface.lpVtbl = &ps_effect_draw_transform_vtbl; + object->ID2D1EffectImpl_iface.lpVtbl = &custom_effect_impl_vtbl; + object->ID2D1DrawTransform_iface.lpVtbl = &custom_shader_effect_draw_transform_vtbl; object->refcount = 1; + object->pixel_shader = pixel_shader; + object->vertex_shader = vertex_shader; + object->vertex_buffer = vertex_buffer;
*effect_impl = (IUnknown *)&object->ID2D1EffectImpl_iface; return S_OK; }
+static HRESULT STDMETHODCALLTYPE custom_effect_impl_create(IUnknown **effect_impl) +{ + return create_custom_shader_effect(effect_impl, &GUID_TestPixelShader, NULL, NULL); +} + +static void preload_shader(const char *target, const char *code, const GUID *id, + struct d2d1_test_context *ctx) +{ + D2D1_PROPERTY_BINDING bindings[1] = { 0 }; + ID2D1EffectContext *effect_context; + ID2D1DeviceContext *context; + ID2D1Factory1 *factory; + ID2D1Effect *effect; + ID3D10Blob *blob; + HRESULT hr; + + context = ctx->context; + factory = ctx->factory1; + + bindings[0].propertyName = L"Context"; + bindings[0].getFunction = effect_impl_get_context; + hr = ID2D1Factory1_RegisterEffectFromString(factory, &CLSID_AuxEffect, effect_xml_b, + bindings, 1, effect_impl_create); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + + hr = ID2D1DeviceContext_CreateEffect(context, &CLSID_AuxEffect, &effect); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + + hr = ID2D1Effect_GetValueByName(effect, L"Context", + D2D1_PROPERTY_TYPE_IUNKNOWN, (BYTE *)&effect_context, sizeof(effect_context)); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + + hr = D3DCompile(code, strlen(code), NULL, NULL, NULL, "main", + target, 0, 0, &blob, NULL); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + if (!strcmp(target, "ps_4_0")) + { + hr = ID2D1EffectContext_LoadPixelShader(effect_context, id, + ID3D10Blob_GetBufferPointer(blob), ID3D10Blob_GetBufferSize(blob)); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + } + else + ok(0, "Unexpected target %s.\n", target); + + ID3D10Blob_Release(blob); + + ID2D1Effect_Release(effect); + + hr = ID2D1Factory1_UnregisterEffect(factory, &CLSID_AuxEffect); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); +} + static void test_effect_custom_pixel_shader(BOOL d3d11) { static const WCHAR *description = @@ -14662,9 +14727,19 @@ static void test_effect_custom_pixel_shader(BOOL d3d11) <Inputs> \ <Input name='Source'/> \ </Inputs> \ + <Property name='Context' type='iunknown'> \ + <Property name='DisplayName' type='string' value='Context'/> \ + </Property> \ </Effect> \ ";
+ static const char ps_code[] = + "float4 main() : sv_target\n" + "{\n" + " return float4(0.1, 0.2, 0.3, 0.4);\n" + "}"; + + D2D1_PROPERTY_BINDING bindings[1] = { 0 }; D2D1_BITMAP_PROPERTIES1 bitmap_desc; DWORD colour, expected_colour; struct d2d1_test_context ctx; @@ -14690,8 +14765,12 @@ static void test_effect_custom_pixel_shader(BOOL d3d11) return; }
- hr = ID2D1Factory1_RegisterEffectFromString(factory, &CLSID_TestEffect, description, NULL, - 0, ps_effect_impl_create); + preload_shader("ps_4_0", ps_code, &GUID_TestPixelShader, &ctx); + + bindings[0].propertyName = L"Context"; + bindings[0].getFunction = effect_impl_get_context; + hr = ID2D1Factory1_RegisterEffectFromString(factory, &CLSID_TestEffect, description, bindings, + ARRAY_SIZE(bindings), custom_effect_impl_create); ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
hr = ID2D1DeviceContext_CreateEffect(context, &CLSID_TestEffect, &effect); @@ -14808,6 +14887,210 @@ static void test_get_effect_properties(BOOL d3d11) release_test_context(&ctx); }
+static void create_effect(ID2D1DeviceContext *device_context, const GUID *id, + ID2D1EffectContext **effect_context, ID2D1Effect **effect) +{ + HRESULT hr; + + hr = ID2D1DeviceContext_CreateEffect(device_context, id, effect); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + + if (effect_context) + { + *effect_context = NULL; + hr = ID2D1Effect_GetValueByName(*effect, L"Context", D2D1_PROPERTY_TYPE_IUNKNOWN, + (BYTE *)effect_context, sizeof*(effect_context)); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + } +} + +static void test_effect_vertex_buffer(BOOL d3d11) +{ + static const char custom_vs_code[] = + "struct vs_out" + "{" + " float4 clipSpaceOutput : SV_POSITION;" + " float4 sceneSpaceOutput : SCENE_POSITION;" + " float4 texelSpaceInput0 : TEXCOORD0;" + "};" + "vs_out main(float2 position : CUSTOM_POSITION)" + "{" + " vs_out output = (vs_out)0;" + " return output;" + "}"; + + static const D2D1_INPUT_ELEMENT_DESC custom_layout[] = + { + {"CUSTOM_POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0}, + }; + + D2D1_CUSTOM_VERTEX_BUFFER_PROPERTIES custom_buffer_desc; + D2D1_VERTEX_BUFFER_PROPERTIES buffer_desc; + ID2D1VertexBuffer *buffer, *buffer2; + ID2D1EffectContext *effect_context; + ID2D1DeviceContext *device_context; + ID2D1Effect *effect, *effect2; + D2D1_PROPERTY_BINDING binding; + struct d2d1_test_context ctx; + D2D_VECTOR_4F data[3 * 6]; + ID2D1Factory1 *factory; + ID2D1Device *device; + BYTE *ptr, *ptr2; + ID3D10Blob *vs; + HRESULT hr; + + if (!init_test_context(&ctx, d3d11)) + return; + + factory = ctx.factory1; + if (!factory) + { + win_skip("ID2D1Factory1 is not supported.\n"); + release_test_context(&ctx); + return; + } + + binding.propertyName = L"Context"; + binding.setFunction = NULL; + binding.getFunction = effect_impl_get_context; + hr = ID2D1Factory1_RegisterEffectFromString(factory, &CLSID_TestEffect, + effect_xml_b, &binding, 1, effect_impl_create); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + + create_effect(ctx.context, &CLSID_TestEffect, &effect_context, &effect); + + buffer_desc.inputCount = 1; + buffer_desc.usage = D2D1_VERTEX_USAGE_STATIC; + buffer_desc.data = (const BYTE *)data; + buffer_desc.byteWidth = sizeof(data); + + hr = ID2D1EffectContext_CreateVertexBuffer(effect_context, &buffer_desc, NULL, NULL, &buffer); + todo_wine + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + if (FAILED(hr)) goto end; + hr = ID2D1EffectContext_CreateVertexBuffer(effect_context, &buffer_desc, NULL, NULL, &buffer2); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + ok(buffer != buffer2, "Unexpected buffer instance.\n"); + ID2D1VertexBuffer_Release(buffer2); + + /* Mapping static buffer. */ + hr = ID2D1VertexBuffer_Map(buffer, &ptr, buffer_desc.byteWidth); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + ok(!!ptr, "Unexpected pointer.\n"); + hr = ID2D1VertexBuffer_Unmap(buffer); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + + hr = ID2D1VertexBuffer_Map(buffer, &ptr, buffer_desc.byteWidth + 1); + ok(hr == E_INVALIDARG, "Got unexpected hr %#lx.\n", hr); + hr = ID2D1VertexBuffer_Map(buffer, &ptr, buffer_desc.byteWidth - 1); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + ok(!!ptr, "Unexpected pointer.\n"); + hr = ID2D1VertexBuffer_Unmap(buffer); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + + /* Map already mapped. */ + hr = ID2D1VertexBuffer_Map(buffer, &ptr, buffer_desc.byteWidth); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + ok(!!ptr, "Unexpected pointer.\n"); + hr = ID2D1VertexBuffer_Map(buffer, &ptr2, buffer_desc.byteWidth); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + ok(ptr == ptr2, "Unexpected pointer.\n"); + hr = ID2D1VertexBuffer_Unmap(buffer); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + + ID2D1VertexBuffer_Release(buffer); + + /* With an id. */ + buffer = (void *)0xdeadbeef; + hr = ID2D1EffectContext_FindVertexBuffer(effect_context, &GUID_NULL, &buffer); + ok(hr == HRESULT_FROM_WIN32(ERROR_NOT_FOUND), "Got unexpected hr %#lx.\n", hr); + ok(!buffer, "Unexpected pointer %p.\n", buffer); + + hr = ID2D1EffectContext_CreateVertexBuffer(effect_context, &buffer_desc, &GUID_NULL, NULL, &buffer); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + hr = ID2D1EffectContext_FindVertexBuffer(effect_context, &GUID_NULL, &buffer2); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + ok(buffer == buffer2, "Unexpected buffer instance.\n"); + ID2D1VertexBuffer_Release(buffer2); + + /* Try to create with the same id.*/ + hr = ID2D1EffectContext_CreateVertexBuffer(effect_context, &buffer_desc, &GUID_NULL, NULL, &buffer2); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + ok(buffer == buffer2, "Unexpected buffer instance.\n"); + ID2D1VertexBuffer_Release(buffer2); + + buffer_desc.usage = D2D1_VERTEX_USAGE_DYNAMIC; + hr = ID2D1EffectContext_CreateVertexBuffer(effect_context, &buffer_desc, &GUID_NULL, NULL, &buffer2); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + ok(buffer == buffer2, "Unexpected buffer instance.\n"); + ID2D1VertexBuffer_Release(buffer2); + + ID2D1VertexBuffer_Release(buffer); + + /* Custom input layout. */ + hr = D3DCompile(custom_vs_code, sizeof(custom_vs_code) - 1, "test_vs", NULL, NULL, + "main", "vs_4_0", 0, 0, &vs, NULL); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + custom_buffer_desc.elementCount = ARRAYSIZE(custom_layout); + custom_buffer_desc.inputElements = custom_layout; + custom_buffer_desc.stride = sizeof(D2D_VECTOR_2F); + custom_buffer_desc.shaderBufferWithInputSignature = ID3D10Blob_GetBufferPointer(vs); + custom_buffer_desc.shaderBufferSize = ID3D10Blob_GetBufferSize(vs); + + hr = ID2D1EffectContext_CreateVertexBuffer(effect_context, &buffer_desc, + &GUID_CustomVertexBuffer, &custom_buffer_desc, &buffer); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + + hr = ID2D1EffectContext_FindVertexBuffer(effect_context, &GUID_CustomVertexBuffer, &buffer2); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + ID2D1VertexBuffer_Release(buffer2); + + ID2D1VertexBuffer_Release(buffer); + + ID3D10Blob_Release(vs); + + /* Buffer is not accessible using different device. */ + hr = ID2D1Factory1_CreateDevice(factory, ctx.device, &device); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + + hr = ID2D1Device_CreateDeviceContext(device, D2D1_DEVICE_CONTEXT_OPTIONS_NONE, &device_context); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + + create_effect(device_context, &CLSID_TestEffect, &effect_context, &effect2); + + hr = ID2D1EffectContext_FindVertexBuffer(effect_context, &GUID_CustomVertexBuffer, &buffer); + ok(hr == HRESULT_FROM_WIN32(ERROR_NOT_FOUND), "Got unexpected hr %#lx.\n", hr); + + ID2D1Effect_Release(effect2); + + ID2D1DeviceContext_Release(device_context); + ID2D1Device_Release(device); + + /* Using same device and different device context. */ + ID2D1DeviceContext_GetDevice(ctx.context, &device); + + hr = ID2D1Device_CreateDeviceContext(device, D2D1_DEVICE_CONTEXT_OPTIONS_NONE, &device_context); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + + create_effect(device_context, &CLSID_TestEffect, &effect_context, &effect2); + + hr = ID2D1EffectContext_FindVertexBuffer(effect_context, &GUID_CustomVertexBuffer, &buffer); + ok(hr == HRESULT_FROM_WIN32(ERROR_NOT_FOUND), "Got unexpected hr %#lx.\n", hr); + + ID2D1Effect_Release(effect2); + + ID2D1DeviceContext_Release(device_context); + + ID2D1Device_Release(device); + +end: + ID2D1Effect_Release(effect); + hr = ID2D1Factory1_UnregisterEffect(factory, &CLSID_TestEffect); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + release_test_context(&ctx); +} + START_TEST(d2d1) { HMODULE d2d1_dll = GetModuleHandleA("d2d1.dll"); @@ -14900,6 +15183,8 @@ START_TEST(d2d1) queue_test(test_bitmap_create); queue_test(test_effect_custom_pixel_shader); queue_test(test_get_effect_properties); + queue_test(test_effect_custom_pixel_shader); + queue_test(test_effect_vertex_buffer);
run_queued_tests(); }