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(); }
From: Nikolay Sivov nsivov@codeweavers.com
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/d2d1/d2d1_private.h | 23 ++++++++++++----------- dlls/d2d1/device.c | 40 +++++++++++++++++++++++----------------- dlls/d2d1/effect.c | 18 +++++++++++------- 3 files changed, 46 insertions(+), 35 deletions(-)
diff --git a/dlls/d2d1/d2d1_private.h b/dlls/d2d1/d2d1_private.h index c0ac5ba9a44..fc9e60c3b7d 100644 --- a/dlls/d2d1/d2d1_private.h +++ b/dlls/d2d1/d2d1_private.h @@ -594,10 +594,15 @@ HRESULT d2d_geometry_group_init(struct d2d_geometry *geometry, ID2D1Factory *fac D2D1_FILL_MODE fill_mode, ID2D1Geometry **src_geometries, unsigned int geometry_count); struct d2d_geometry *unsafe_impl_from_ID2D1Geometry(ID2D1Geometry *iface);
-struct d2d_shader +struct d2d_indexed_objects { - GUID id; - IUnknown *shader; + struct + { + GUID id; + IUnknown *object; + } *elements; + size_t size; + size_t count; };
struct d2d_device @@ -607,17 +612,13 @@ struct d2d_device ID2D1Factory1 *factory; IDXGIDevice *dxgi_device;
- struct - { - struct d2d_shader *objects; - size_t size; - size_t count; - } shaders; + struct d2d_indexed_objects shaders; };
struct d2d_device *unsafe_impl_from_ID2D1Device(ID2D1Device1 *iface); -HRESULT d2d_device_add_shader(struct d2d_device *device, REFGUID shader_id, IUnknown *shader); -BOOL d2d_device_is_shader_loaded(struct d2d_device *device, REFGUID shader_id); +HRESULT d2d_device_add_indexed_object(struct d2d_indexed_objects *objects, const GUID *id, + IUnknown *object); +BOOL d2d_device_is_object_indexed(struct d2d_indexed_objects *objects, const GUID *id);
struct d2d_effect_context { diff --git a/dlls/d2d1/device.c b/dlls/d2d1/device.c index 8b1099b180b..7741233f115 100644 --- a/dlls/d2d1/device.c +++ b/dlls/d2d1/device.c @@ -4282,11 +4282,20 @@ static ULONG WINAPI d2d_device_AddRef(ID2D1Device6 *iface) return refcount; }
+static void d2d_device_indexed_objects_clear(struct d2d_indexed_objects *objects) +{ + size_t i; + + for (i = 0; i < objects->count; ++i) + IUnknown_Release(objects->elements[i].object); + free(objects->elements); + objects->elements = NULL; +} + static ULONG WINAPI d2d_device_Release(ID2D1Device6 *iface) { struct d2d_device *device = impl_from_ID2D1Device(iface); ULONG refcount = InterlockedDecrement(&device->refcount); - size_t i;
TRACE("%p decreasing refcount to %lu.\n", iface, refcount);
@@ -4294,9 +4303,7 @@ static ULONG WINAPI d2d_device_Release(ID2D1Device6 *iface) { IDXGIDevice_Release(device->dxgi_device); ID2D1Factory1_Release(device->factory); - for (i = 0; i < device->shaders.count; ++i) - IUnknown_Release(device->shaders.objects[i].shader); - free(device->shaders.objects); + d2d_device_indexed_objects_clear(&device->shaders); free(device); }
@@ -4521,32 +4528,31 @@ void d2d_device_init(struct d2d_device *device, struct d2d_factory *factory, IDX IDXGIDevice_AddRef(device->dxgi_device); }
-HRESULT d2d_device_add_shader(struct d2d_device *device, REFGUID shader_id, IUnknown *shader) +HRESULT d2d_device_add_indexed_object(struct d2d_indexed_objects *objects, + const GUID *id, IUnknown *object) { - struct d2d_shader *entry; - - if (!d2d_array_reserve((void **)&device->shaders.objects, &device->shaders.size, - device->shaders.count + 1, sizeof(*device->shaders.objects))) + if (!d2d_array_reserve((void **)&objects->elements, &objects->size, objects->count + 1, + sizeof(*objects->elements))) { - WARN("Failed to resize shaders array.\n"); + WARN("Failed to resize elements array.\n"); return E_OUTOFMEMORY; }
- entry = &device->shaders.objects[device->shaders.count++]; - entry->id = *shader_id; - entry->shader = shader; - IUnknown_AddRef(entry->shader); + objects->elements[objects->count].id = *id; + objects->elements[objects->count].object = object; + IUnknown_AddRef(object); + objects->count++;
return S_OK; }
-BOOL d2d_device_is_shader_loaded(struct d2d_device *device, REFGUID shader_id) +BOOL d2d_device_is_object_indexed(struct d2d_indexed_objects *objects, const GUID *id) { size_t i;
- for (i = 0; i < device->shaders.count; ++i) + for (i = 0; i < objects->count; ++i) { - if (IsEqualGUID(shader_id, &device->shaders.objects[i].id)) + if (IsEqualGUID(id, &objects->elements[i].id)) return TRUE; }
diff --git a/dlls/d2d1/effect.c b/dlls/d2d1/effect.c index e7f9f78284f..0ad5fabbca7 100644 --- a/dlls/d2d1/effect.c +++ b/dlls/d2d1/effect.c @@ -1451,13 +1451,14 @@ static HRESULT STDMETHODCALLTYPE d2d_effect_context_LoadPixelShader(ID2D1EffectC REFGUID shader_id, const BYTE *buffer, UINT32 buffer_size) { struct d2d_effect_context *effect_context = impl_from_ID2D1EffectContext(iface); + struct d2d_device *device = effect_context->device_context->device; ID3D11PixelShader *shader; HRESULT hr;
TRACE("iface %p, shader_id %s, buffer %p, buffer_size %u.\n", iface, debugstr_guid(shader_id), buffer, buffer_size);
- if (d2d_device_is_shader_loaded(effect_context->device_context->device, shader_id)) + if (d2d_device_is_object_indexed(&device->shaders, shader_id)) return S_OK;
if (FAILED(hr = ID3D11Device1_CreatePixelShader(effect_context->device_context->d3d_device, @@ -1467,7 +1468,7 @@ static HRESULT STDMETHODCALLTYPE d2d_effect_context_LoadPixelShader(ID2D1EffectC return hr; }
- hr = d2d_device_add_shader(effect_context->device_context->device, shader_id, (IUnknown *)shader); + hr = d2d_device_add_indexed_object(&device->shaders, shader_id, (IUnknown *)shader); ID3D11PixelShader_Release(shader);
return hr; @@ -1477,13 +1478,14 @@ static HRESULT STDMETHODCALLTYPE d2d_effect_context_LoadVertexShader(ID2D1Effect REFGUID shader_id, const BYTE *buffer, UINT32 buffer_size) { struct d2d_effect_context *effect_context = impl_from_ID2D1EffectContext(iface); + struct d2d_device *device = effect_context->device_context->device; ID3D11VertexShader *shader; HRESULT hr;
TRACE("iface %p, shader_id %s, buffer %p, buffer_size %u.\n", iface, debugstr_guid(shader_id), buffer, buffer_size);
- if (d2d_device_is_shader_loaded(effect_context->device_context->device, shader_id)) + if (d2d_device_is_object_indexed(&device->shaders, shader_id)) return S_OK;
if (FAILED(hr = ID3D11Device1_CreateVertexShader(effect_context->device_context->d3d_device, @@ -1493,7 +1495,7 @@ static HRESULT STDMETHODCALLTYPE d2d_effect_context_LoadVertexShader(ID2D1Effect return hr; }
- hr = d2d_device_add_shader(effect_context->device_context->device, shader_id, (IUnknown *)shader); + hr = d2d_device_add_indexed_object(&device->shaders, shader_id, (IUnknown *)shader); ID3D11VertexShader_Release(shader);
return hr; @@ -1503,13 +1505,14 @@ static HRESULT STDMETHODCALLTYPE d2d_effect_context_LoadComputeShader(ID2D1Effec REFGUID shader_id, const BYTE *buffer, UINT32 buffer_size) { struct d2d_effect_context *effect_context = impl_from_ID2D1EffectContext(iface); + struct d2d_device *device = effect_context->device_context->device; ID3D11ComputeShader *shader; HRESULT hr;
TRACE("iface %p, shader_id %s, buffer %p, buffer_size %u.\n", iface, debugstr_guid(shader_id), buffer, buffer_size);
- if (d2d_device_is_shader_loaded(effect_context->device_context->device, shader_id)) + if (d2d_device_is_object_indexed(&device->shaders, shader_id)) return S_OK;
if (FAILED(hr = ID3D11Device1_CreateComputeShader(effect_context->device_context->d3d_device, @@ -1519,7 +1522,7 @@ static HRESULT STDMETHODCALLTYPE d2d_effect_context_LoadComputeShader(ID2D1Effec return hr; }
- hr = d2d_device_add_shader(effect_context->device_context->device, shader_id, (IUnknown *)shader); + hr = d2d_device_add_indexed_object(&device->shaders, shader_id, (IUnknown *)shader); ID3D11ComputeShader_Release(shader);
return hr; @@ -1528,10 +1531,11 @@ static HRESULT STDMETHODCALLTYPE d2d_effect_context_LoadComputeShader(ID2D1Effec static BOOL STDMETHODCALLTYPE d2d_effect_context_IsShaderLoaded(ID2D1EffectContext *iface, REFGUID shader_id) { struct d2d_effect_context *effect_context = impl_from_ID2D1EffectContext(iface); + struct d2d_device *device = effect_context->device_context->device;
TRACE("iface %p, shader_id %s.\n", iface, debugstr_guid(shader_id));
- return d2d_device_is_shader_loaded(effect_context->device_context->device, shader_id); + return d2d_device_is_object_indexed(&device->shaders, shader_id); }
static HRESULT STDMETHODCALLTYPE d2d_effect_context_CreateResourceTexture(ID2D1EffectContext *iface,
From: Nikolay Sivov nsivov@codeweavers.com
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/d2d1/d2d1_private.h | 34 +++++++---- dlls/d2d1/device.c | 28 ++++++--- dlls/d2d1/effect.c | 123 ++++++++++++++++++++++++++++++++++++--- dlls/d2d1/tests/d2d1.c | 16 ++++- 4 files changed, 169 insertions(+), 32 deletions(-)
diff --git a/dlls/d2d1/d2d1_private.h b/dlls/d2d1/d2d1_private.h index fc9e60c3b7d..bd6ca55ea96 100644 --- a/dlls/d2d1/d2d1_private.h +++ b/dlls/d2d1/d2d1_private.h @@ -159,6 +159,17 @@ enum d2d_device_context_target_type D2D_TARGET_COMMAND_LIST, };
+struct d2d_indexed_objects +{ + struct + { + GUID id; + IUnknown *object; + } *elements; + size_t size; + size_t count; +}; + struct d2d_device_context { ID2D1DeviceContext6 ID2D1DeviceContext6_iface; @@ -208,6 +219,8 @@ struct d2d_device_context D2D1_RENDER_TARGET_PROPERTIES desc; D2D1_SIZE_U pixel_size; struct d2d_clip_stack clip_stack; + + struct d2d_indexed_objects vertex_buffers; };
HRESULT d2d_d3d_create_render_target(struct d2d_device *device, IDXGISurface *surface, IUnknown *outer_unknown, @@ -594,17 +607,6 @@ HRESULT d2d_geometry_group_init(struct d2d_geometry *geometry, ID2D1Factory *fac D2D1_FILL_MODE fill_mode, ID2D1Geometry **src_geometries, unsigned int geometry_count); struct d2d_geometry *unsafe_impl_from_ID2D1Geometry(ID2D1Geometry *iface);
-struct d2d_indexed_objects -{ - struct - { - GUID id; - IUnknown *object; - } *elements; - size_t size; - size_t count; -}; - struct d2d_device { ID2D1Device6 ID2D1Device6_iface; @@ -618,7 +620,9 @@ struct d2d_device struct d2d_device *unsafe_impl_from_ID2D1Device(ID2D1Device1 *iface); HRESULT d2d_device_add_indexed_object(struct d2d_indexed_objects *objects, const GUID *id, IUnknown *object); -BOOL d2d_device_is_object_indexed(struct d2d_indexed_objects *objects, const GUID *id); +BOOL d2d_device_get_indexed_object(struct d2d_indexed_objects *objects, const GUID *id, + IUnknown **object); +void d2d_device_indexed_objects_clear(struct d2d_indexed_objects *objects);
struct d2d_effect_context { @@ -799,6 +803,12 @@ HRESULT d2d_factory_register_builtin_effect(struct d2d_factory *factory, REFCLSI const WCHAR *property_xml, const D2D1_PROPERTY_BINDING *bindings, UINT32 binding_count, PD2D1_EFFECT_FACTORY effect_factory);
+struct d2d_vertex_buffer +{ + ID2D1VertexBuffer ID2D1VertexBuffer_iface; + LONG refcount; +}; + enum d2d_command_list_state { D2D_COMMAND_LIST_STATE_INITIAL = 0, diff --git a/dlls/d2d1/device.c b/dlls/d2d1/device.c index 7741233f115..75da15c99a5 100644 --- a/dlls/d2d1/device.c +++ b/dlls/d2d1/device.c @@ -304,6 +304,7 @@ static ULONG STDMETHODCALLTYPE d2d_device_context_inner_Release(IUnknown *iface) ID3D11Device1_Release(context->d3d_device); ID2D1Factory_Release(context->factory); ID2D1Device6_Release(&context->device->ID2D1Device6_iface); + d2d_device_indexed_objects_clear(&context->vertex_buffers); free(context); }
@@ -4282,7 +4283,7 @@ static ULONG WINAPI d2d_device_AddRef(ID2D1Device6 *iface) return refcount; }
-static void d2d_device_indexed_objects_clear(struct d2d_indexed_objects *objects) +void d2d_device_indexed_objects_clear(struct d2d_indexed_objects *objects) { size_t i;
@@ -4546,15 +4547,24 @@ HRESULT d2d_device_add_indexed_object(struct d2d_indexed_objects *objects, return S_OK; }
-BOOL d2d_device_is_object_indexed(struct d2d_indexed_objects *objects, const GUID *id) +BOOL d2d_device_get_indexed_object(struct d2d_indexed_objects *objects, const GUID *id, + IUnknown **object) { - size_t i; + size_t i;
- for (i = 0; i < objects->count; ++i) - { - if (IsEqualGUID(id, &objects->elements[i].id)) - return TRUE; - } + for (i = 0; i < objects->count; ++i) + { + if (IsEqualGUID(id, &objects->elements[i].id)) + { + if (object) + { + *object = objects->elements[i].object; + IUnknown_AddRef(*object); + } + return TRUE; + } + }
- return FALSE; + if (object) *object = NULL; + return FALSE; } diff --git a/dlls/d2d1/effect.c b/dlls/d2d1/effect.c index 0ad5fabbca7..25a75a31ecb 100644 --- a/dlls/d2d1/effect.c +++ b/dlls/d2d1/effect.c @@ -41,6 +41,90 @@ static inline struct d2d_transform *impl_from_ID2D1BoundsAdjustmentTransform( return CONTAINING_RECORD(iface, struct d2d_transform, ID2D1TransformNode_iface); }
+static inline struct d2d_vertex_buffer *impl_from_ID2D1VertexBuffer(ID2D1VertexBuffer *iface) +{ + return CONTAINING_RECORD(iface, struct d2d_vertex_buffer, ID2D1VertexBuffer_iface); +} + +static HRESULT STDMETHODCALLTYPE d2d_vertex_buffer_QueryInterface(ID2D1VertexBuffer *iface, + REFIID iid, void **out) +{ + TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out); + + if (IsEqualGUID(iid, &IID_ID2D1VertexBuffer) + || IsEqualGUID(iid, &IID_IUnknown)) + { + *out = iface; + ID2D1VertexBuffer_AddRef(iface); + return S_OK; + } + + WARN("Unsupported interface %s.\n", debugstr_guid(iid)); + *out = NULL; + return E_NOINTERFACE; +} + +static ULONG STDMETHODCALLTYPE d2d_vertex_buffer_AddRef(ID2D1VertexBuffer *iface) +{ + struct d2d_vertex_buffer *buffer = impl_from_ID2D1VertexBuffer(iface); + ULONG refcount = InterlockedIncrement(&buffer->refcount); + + TRACE("%p increasing refcount to %lu.\n", iface, refcount); + + return refcount; +} + +static ULONG STDMETHODCALLTYPE d2d_vertex_buffer_Release(ID2D1VertexBuffer *iface) +{ + struct d2d_vertex_buffer *buffer = impl_from_ID2D1VertexBuffer(iface); + ULONG refcount = InterlockedDecrement(&buffer->refcount); + + TRACE("%p decreasing refcount to %lu.\n", iface, refcount); + + if (!refcount) + free(buffer); + + return refcount; +} + +static HRESULT STDMETHODCALLTYPE d2d_vertex_buffer_Map(ID2D1VertexBuffer *iface, BYTE **data, UINT32 size) +{ + FIXME("iface %p, data %p, size %u.\n", iface, data, size); + + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE d2d_vertex_buffer_Unmap(ID2D1VertexBuffer *iface) +{ + FIXME("iface %p.\n", iface); + + return E_NOTIMPL; +} + +static const ID2D1VertexBufferVtbl d2d_vertex_buffer_vtbl = +{ + d2d_vertex_buffer_QueryInterface, + d2d_vertex_buffer_AddRef, + d2d_vertex_buffer_Release, + d2d_vertex_buffer_Map, + d2d_vertex_buffer_Unmap, +}; + +static HRESULT d2d_vertex_buffer_create(ID2D1VertexBuffer **buffer) +{ + struct d2d_vertex_buffer *object; + + if (!(object = calloc(1, sizeof(*object)))) + return E_OUTOFMEMORY; + + object->ID2D1VertexBuffer_iface.lpVtbl = &d2d_vertex_buffer_vtbl; + object->refcount = 1; + + *buffer = &object->ID2D1VertexBuffer_iface; + + return S_OK; +} + static HRESULT STDMETHODCALLTYPE d2d_offset_transform_QueryInterface(ID2D1OffsetTransform *iface, REFIID iid, void **out) { @@ -1458,7 +1542,7 @@ static HRESULT STDMETHODCALLTYPE d2d_effect_context_LoadPixelShader(ID2D1EffectC TRACE("iface %p, shader_id %s, buffer %p, buffer_size %u.\n", iface, debugstr_guid(shader_id), buffer, buffer_size);
- if (d2d_device_is_object_indexed(&device->shaders, shader_id)) + if (d2d_device_get_indexed_object(&device->shaders, shader_id, NULL)) return S_OK;
if (FAILED(hr = ID3D11Device1_CreatePixelShader(effect_context->device_context->d3d_device, @@ -1485,7 +1569,7 @@ static HRESULT STDMETHODCALLTYPE d2d_effect_context_LoadVertexShader(ID2D1Effect TRACE("iface %p, shader_id %s, buffer %p, buffer_size %u.\n", iface, debugstr_guid(shader_id), buffer, buffer_size);
- if (d2d_device_is_object_indexed(&device->shaders, shader_id)) + if (d2d_device_get_indexed_object(&device->shaders, shader_id, NULL)) return S_OK;
if (FAILED(hr = ID3D11Device1_CreateVertexShader(effect_context->device_context->d3d_device, @@ -1512,7 +1596,7 @@ static HRESULT STDMETHODCALLTYPE d2d_effect_context_LoadComputeShader(ID2D1Effec TRACE("iface %p, shader_id %s, buffer %p, buffer_size %u.\n", iface, debugstr_guid(shader_id), buffer, buffer_size);
- if (d2d_device_is_object_indexed(&device->shaders, shader_id)) + if (d2d_device_get_indexed_object(&device->shaders, shader_id, NULL)) return S_OK;
if (FAILED(hr = ID3D11Device1_CreateComputeShader(effect_context->device_context->d3d_device, @@ -1535,7 +1619,7 @@ static BOOL STDMETHODCALLTYPE d2d_effect_context_IsShaderLoaded(ID2D1EffectConte
TRACE("iface %p, shader_id %s.\n", iface, debugstr_guid(shader_id));
- return d2d_device_is_object_indexed(&device->shaders, shader_id); + return d2d_device_get_indexed_object(&device->shaders, shader_id, NULL); }
static HRESULT STDMETHODCALLTYPE d2d_effect_context_CreateResourceTexture(ID2D1EffectContext *iface, @@ -1558,20 +1642,43 @@ static HRESULT STDMETHODCALLTYPE d2d_effect_context_FindResourceTexture(ID2D1Eff
static HRESULT STDMETHODCALLTYPE d2d_effect_context_CreateVertexBuffer(ID2D1EffectContext *iface, const D2D1_VERTEX_BUFFER_PROPERTIES *buffer_properties, const GUID *id, - const D2D1_CUSTOM_VERTEX_BUFFER_PROPERTIES *custom_buffer_properties, ID2D1VertexBuffer **buffer) + const D2D1_CUSTOM_VERTEX_BUFFER_PROPERTIES *custom_buffer_properties, + ID2D1VertexBuffer **buffer) { + struct d2d_effect_context *effect_context = impl_from_ID2D1EffectContext(iface); + struct d2d_device_context *context = effect_context->device_context; + HRESULT hr; + FIXME("iface %p, buffer_properties %p, id %s, custom_buffer_properties %p, buffer %p stub!\n", iface, buffer_properties, debugstr_guid(id), custom_buffer_properties, buffer);
- return E_NOTIMPL; + if (id && d2d_device_get_indexed_object(&context->vertex_buffers, id, (IUnknown **)buffer)) + return S_OK; + + if (SUCCEEDED(hr = d2d_vertex_buffer_create(buffer))) + { + if (id) + hr = d2d_device_add_indexed_object(&context->vertex_buffers, id, (IUnknown *)*buffer); + } + + if (FAILED(hr)) + *buffer = NULL; + + return hr; }
static HRESULT STDMETHODCALLTYPE d2d_effect_context_FindVertexBuffer(ID2D1EffectContext *iface, const GUID *id, ID2D1VertexBuffer **buffer) { - FIXME("iface %p, id %s, buffer %p stub!\n", iface, debugstr_guid(id), buffer); + struct d2d_effect_context *effect_context = impl_from_ID2D1EffectContext(iface); + struct d2d_device_context *context = effect_context->device_context;
- return E_NOTIMPL; + TRACE("iface %p, id %s, buffer %p.\n", iface, debugstr_guid(id), buffer); + + if (!d2d_device_get_indexed_object(&context->vertex_buffers, id, (IUnknown **)buffer)) + return HRESULT_FROM_WIN32(ERROR_NOT_FOUND); + + return S_OK; }
static HRESULT STDMETHODCALLTYPE d2d_effect_context_CreateColorContext(ID2D1EffectContext *iface, diff --git a/dlls/d2d1/tests/d2d1.c b/dlls/d2d1/tests/d2d1.c index 553d9e1469b..2ec11c342ad 100644 --- a/dlls/d2d1/tests/d2d1.c +++ b/dlls/d2d1/tests/d2d1.c @@ -14965,37 +14965,48 @@ static void test_effect_vertex_buffer(BOOL d3d11) 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. */ + ptr = NULL; hr = ID2D1VertexBuffer_Map(buffer, &ptr, buffer_desc.byteWidth); + todo_wine ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + todo_wine ok(!!ptr, "Unexpected pointer.\n"); hr = ID2D1VertexBuffer_Unmap(buffer); + todo_wine ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
hr = ID2D1VertexBuffer_Map(buffer, &ptr, buffer_desc.byteWidth + 1); + todo_wine ok(hr == E_INVALIDARG, "Got unexpected hr %#lx.\n", hr); hr = ID2D1VertexBuffer_Map(buffer, &ptr, buffer_desc.byteWidth - 1); + todo_wine ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + todo_wine ok(!!ptr, "Unexpected pointer.\n"); hr = ID2D1VertexBuffer_Unmap(buffer); + todo_wine ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
/* Map already mapped. */ hr = ID2D1VertexBuffer_Map(buffer, &ptr, buffer_desc.byteWidth); + todo_wine ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + todo_wine ok(!!ptr, "Unexpected pointer.\n"); + ptr2 = NULL; hr = ID2D1VertexBuffer_Map(buffer, &ptr2, buffer_desc.byteWidth); + todo_wine ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); ok(ptr == ptr2, "Unexpected pointer.\n"); hr = ID2D1VertexBuffer_Unmap(buffer); + todo_wine ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
ID2D1VertexBuffer_Release(buffer); @@ -15084,7 +15095,6 @@ static void test_effect_vertex_buffer(BOOL d3d11)
ID2D1Device_Release(device);
-end: ID2D1Effect_Release(effect); hr = ID2D1Factory1_UnregisterEffect(factory, &CLSID_TestEffect); ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);