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);