Module: wine Branch: master Commit: 0a9f2494df5a90acb0b1d483a2d915a1c4dbc413 URL: https://gitlab.winehq.org/wine/wine/-/commit/0a9f2494df5a90acb0b1d483a2d915a...
Author: Nikolay Sivov nsivov@codeweavers.com Date: Mon Apr 8 10:18:39 2024 +0200
d2d1/effect: Make it possible to set render info for draw-transform nodes.
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com
---
dlls/d2d1/d2d1_private.h | 15 ++++ dlls/d2d1/effect.c | 222 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 237 insertions(+)
diff --git a/dlls/d2d1/d2d1_private.h b/dlls/d2d1/d2d1_private.h index 6b6d51d4b3c..f5f484e0778 100644 --- a/dlls/d2d1/d2d1_private.h +++ b/dlls/d2d1/d2d1_private.h @@ -728,10 +728,25 @@ struct d2d_transform UINT32 input_count; };
+enum d2d_render_info_mask +{ + D2D_RENDER_INFO_PIXEL_SHADER = 0x1, +}; + +struct d2d_render_info +{ + ID2D1DrawInfo ID2D1DrawInfo_iface; + LONG refcount; + + unsigned int mask; + GUID pixel_shader; +}; + struct d2d_transform_node { struct list entry; ID2D1TransformNode *object; + struct d2d_render_info *render_info; };
struct d2d_transform_node_connection diff --git a/dlls/d2d1/effect.c b/dlls/d2d1/effect.c index 6738bc43a1d..a6738823e6f 100644 --- a/dlls/d2d1/effect.c +++ b/dlls/d2d1/effect.c @@ -561,6 +561,9 @@ static void d2d_transform_graph_delete_node(struct d2d_transform_graph *graph, if (graph->output == node) graph->output = NULL;
+ if (node->render_info) + ID2D1DrawInfo_Release(&node->render_info->ID2D1DrawInfo_iface); + free(node); }
@@ -2265,6 +2268,218 @@ static void d2d_effect_init_properties_vtbls(struct d2d_effect *effect) } }
+static struct d2d_render_info *impl_from_ID2D1DrawInfo(ID2D1DrawInfo *iface) +{ + return CONTAINING_RECORD(iface, struct d2d_render_info, ID2D1DrawInfo_iface); +} + +static HRESULT STDMETHODCALLTYPE d2d_draw_info_QueryInterface(ID2D1DrawInfo *iface, REFIID iid, + void **obj) +{ + TRACE("iface %p, iid %s, obj %p.\n", iface, debugstr_guid(iid), obj); + + if (IsEqualGUID(iid, &IID_ID2D1DrawInfo) + || IsEqualGUID(iid, &IID_ID2D1RenderInfo) + || IsEqualGUID(iid, &IID_IUnknown)) + { + *obj = iface; + ID2D1DrawInfo_AddRef(iface); + return S_OK; + } + + WARN("Unsupported interface %s.\n", debugstr_guid(iid)); + + *obj = NULL; + + return E_NOINTERFACE; +} + +static ULONG STDMETHODCALLTYPE d2d_draw_info_AddRef(ID2D1DrawInfo *iface) +{ + struct d2d_render_info *render_info = impl_from_ID2D1DrawInfo(iface); + ULONG refcount = InterlockedIncrement(&render_info->refcount); + + TRACE("iface %p refcount %lu.\n", iface, refcount); + + return refcount; +} + +static ULONG STDMETHODCALLTYPE d2d_draw_info_Release(ID2D1DrawInfo *iface) +{ + struct d2d_render_info *render_info = impl_from_ID2D1DrawInfo(iface); + ULONG refcount = InterlockedDecrement(&render_info->refcount); + + TRACE("iface %p refcount %lu.\n", iface, refcount); + + if (!refcount) + free(render_info); + + return refcount; +} + +static HRESULT STDMETHODCALLTYPE d2d_draw_info_SetInputDescription(ID2D1DrawInfo *iface, + UINT32 index, D2D1_INPUT_DESCRIPTION description) +{ + FIXME("iface %p, index %u stub.\n", iface, index); + + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE d2d_draw_info_SetOutputBuffer(ID2D1DrawInfo *iface, + D2D1_BUFFER_PRECISION precision, D2D1_CHANNEL_DEPTH depth) +{ + FIXME("iface %p, precision %u, depth %u stub.\n", iface, precision, depth); + + return E_NOTIMPL; +} + +static void STDMETHODCALLTYPE d2d_draw_info_SetCached(ID2D1DrawInfo *iface, BOOL is_cached) +{ + FIXME("iface %p, is_cached %d stub.\n", iface, is_cached); +} + +static void STDMETHODCALLTYPE d2d_draw_info_SetInstructionCountHint(ID2D1DrawInfo *iface, + UINT32 count) +{ + FIXME("iface %p, count %u stub.\n", iface, count); +} + +static HRESULT STDMETHODCALLTYPE d2d_draw_info_SetPixelShaderConstantBuffer(ID2D1DrawInfo *iface, + const BYTE *buffer, UINT32 size) +{ + FIXME("iface %p, buffer %p, size %u stub.\n", iface, buffer, size); + + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE d2d_draw_info_SetResourceTexture(ID2D1DrawInfo *iface, + UINT32 index, ID2D1ResourceTexture *texture) +{ + FIXME("iface %p, index %u, texture %p stub.\n", iface, index, texture); + + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE d2d_draw_info_SetVertexShaderConstantBuffer(ID2D1DrawInfo *iface, + const BYTE *buffer, UINT32 size) +{ + FIXME("iface %p, buffer %p, size %u stub.\n", iface, buffer, size); + + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE d2d_draw_info_SetPixelShader(ID2D1DrawInfo *iface, + REFGUID id, D2D1_PIXEL_OPTIONS options) +{ + struct d2d_render_info *render_info = impl_from_ID2D1DrawInfo(iface); + + TRACE("iface %p, id %s, options %u.\n", iface, debugstr_guid(id), options); + + render_info->mask |= D2D_RENDER_INFO_PIXEL_SHADER; + render_info->pixel_shader = *id; + return S_OK; +} + +static HRESULT STDMETHODCALLTYPE d2d_draw_info_SetVertexProcessing(ID2D1DrawInfo *iface, + ID2D1VertexBuffer *buffer, D2D1_VERTEX_OPTIONS options, + const D2D1_BLEND_DESCRIPTION *description, const D2D1_VERTEX_RANGE *range, + const GUID *shader) +{ + FIXME("iface %p, buffer %p, options %#x, description %p, range %p, shader %s stub.\n", + iface, buffer, options, description, range, debugstr_guid(shader)); + + return E_NOTIMPL; +} + +static const ID2D1DrawInfoVtbl d2d_draw_info_vtbl = +{ + d2d_draw_info_QueryInterface, + d2d_draw_info_AddRef, + d2d_draw_info_Release, + d2d_draw_info_SetInputDescription, + d2d_draw_info_SetOutputBuffer, + d2d_draw_info_SetCached, + d2d_draw_info_SetInstructionCountHint, + d2d_draw_info_SetPixelShaderConstantBuffer, + d2d_draw_info_SetResourceTexture, + d2d_draw_info_SetVertexShaderConstantBuffer, + d2d_draw_info_SetPixelShader, + d2d_draw_info_SetVertexProcessing, +}; + +static HRESULT d2d_effect_render_info_create(struct d2d_render_info **obj) +{ + struct d2d_render_info *object; + + if (!(object = calloc(1, sizeof(*object)))) + return E_OUTOFMEMORY; + + object->ID2D1DrawInfo_iface.lpVtbl = &d2d_draw_info_vtbl; + object->refcount = 1; + + *obj = object; + + return S_OK; +} + +static bool d2d_transform_node_needs_render_info(const struct d2d_transform_node *node) +{ + static const GUID *iids[] = + { + &IID_ID2D1SourceTransform, + &IID_ID2D1ComputeTransform, + &IID_ID2D1DrawTransform, + }; + unsigned int i; + IUnknown *obj; + + for (i = 0; i < ARRAY_SIZE(iids); ++i) + { + if (SUCCEEDED(ID2D1TransformNode_QueryInterface(node->object, iids[i], (void **)&obj))) + { + IUnknown_Release(obj); + return true; + } + } + + return false; +} + +static HRESULT d2d_effect_transform_graph_initialize_nodes(struct d2d_transform_graph *graph) +{ + ID2D1DrawTransform *draw_transform; + struct d2d_transform_node *node; + HRESULT hr; + + LIST_FOR_EACH_ENTRY(node, &graph->nodes, struct d2d_transform_node, entry) + { + if (d2d_transform_node_needs_render_info(node)) + { + if (FAILED(hr = d2d_effect_render_info_create(&node->render_info))) + return hr; + } + + if (SUCCEEDED(ID2D1TransformNode_QueryInterface(node->object, &IID_ID2D1DrawTransform, + (void **)&draw_transform))) + { + hr = ID2D1DrawTransform_SetDrawInfo(draw_transform, &node->render_info->ID2D1DrawInfo_iface); + ID2D1DrawTransform_Release(draw_transform); + if (FAILED(hr)) + { + WARN("Failed to set draw info, hr %#lx.\n", hr); + return hr; + } + } + else + { + FIXME("Unsupported node %p.\n", node); + return E_NOTIMPL; + } + } + + return S_OK; +} + HRESULT d2d_effect_create(struct d2d_device_context *context, const CLSID *effect_id, ID2D1Effect **effect) { @@ -2330,6 +2545,13 @@ HRESULT d2d_effect_create(struct d2d_device_context *context, const CLSID *effec return hr; }
+ if (FAILED(hr = d2d_effect_transform_graph_initialize_nodes(object->graph))) + { + WARN("Failed to initialize graph nodes, hr %#lx.\n", hr); + ID2D1Effect_Release(&object->ID2D1Effect_iface); + return hr; + } + *effect = &object->ID2D1Effect_iface;
TRACE("Created effect %p.\n", *effect);