From: Nikolay Sivov <nsivov(a)codeweavers.com>
Signed-off-by: Nikolay Sivov <nsivov(a)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();
}
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/5648