[PATCH 0/3] MR5469: d2d1/effect: Zero value buffer on size or type mismatch.
Found this after seeing test crashes caused by writing to adjacent stack memory, corrupting it. Happened with "size + 1" tests. Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com> -- https://gitlab.winehq.org/wine/wine/-/merge_requests/5469
From: Nikolay Sivov <nsivov(a)codeweavers.com> Found this after seeing test crashes caused by writing to adjacent stack memory, corrupting it. Happened with "size + 1" tests. Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com> --- dlls/d2d1/effect.c | 2 + dlls/d2d1/tests/d2d1.c | 86 +++++++++++++++++++++++++++++++----------- 2 files changed, 67 insertions(+), 21 deletions(-) diff --git a/dlls/d2d1/effect.c b/dlls/d2d1/effect.c index 42d2c589edc..6738bc43a1d 100644 --- a/dlls/d2d1/effect.c +++ b/dlls/d2d1/effect.c @@ -1252,6 +1252,8 @@ static HRESULT d2d_effect_property_get_value(const struct d2d_effect_properties struct d2d_effect *effect = properties->effect; UINT32 actual_size; + memset(value, 0, size); + if (type != D2D1_PROPERTY_TYPE_UNKNOWN && prop->type != type) return E_INVALIDARG; if (prop->type != D2D1_PROPERTY_TYPE_STRING && prop->size != size) return E_INVALIDARG; diff --git a/dlls/d2d1/tests/d2d1.c b/dlls/d2d1/tests/d2d1.c index ad7d5163f1f..15a9eeb00ab 100644 --- a/dlls/d2d1/tests/d2d1.c +++ b/dlls/d2d1/tests/d2d1.c @@ -20,6 +20,7 @@ #include <limits.h> #include <math.h> #include <float.h> +#include <stdint.h> #include "d3dcompiler.h" #include "d2d1_3.h" #include "d2d1effectauthor.h" @@ -11707,6 +11708,19 @@ static void test_effect_context(BOOL d3d11) release_test_context(&ctx); } +#define check_zero_buffer(a, b) check_zero_buffer_(a, b, __LINE__) +static void check_zero_buffer_(const void *buffer, size_t size, unsigned int line) +{ + const uint32_t *ptr = buffer; + const uint8_t *ptr2 = buffer; + size_t i; + + for (i = 0; i < size / sizeof(*ptr); ++i) + ok_(__FILE__, line)(!ptr[i], "Expected zero value %#x.\n", ptr[i]); + for (i = 0; i < size % sizeof(*ptr); ++i) + ok_(__FILE__, line)(!ptr2[size - i - 1], "Expected zero value %#x.\n", ptr2[i]); +} + static void test_effect_properties(BOOL d3d11) { UINT32 i, min_inputs, max_inputs, integer, index, size; @@ -11720,6 +11734,7 @@ static void test_effect_properties(BOOL d3d11) ID2D1Effect *effect; UINT32 count, data; WCHAR buffer[128]; + BYTE value[128]; float mat[20]; INT32 val; CLSID clsid; @@ -12077,55 +12092,84 @@ static void test_effect_properties(BOOL d3d11) index = ID2D1Effect_GetPropertyIndex(effect, L"Integer"); ok(index == 1, "Got unexpected index %u.\n", index); - effect_context = (ID2D1EffectContext *)0xdeadbeef; - hr = ID2D1Effect_GetValueByName(effect, - L"Context", D2D1_PROPERTY_TYPE_IUNKNOWN, (BYTE *)&effect_context, sizeof(effect_context) - 1); + /* On type mismatch output buffer is zeroed. */ + memset(value, 0xcc, sizeof(value)); + hr = ID2D1Effect_GetValueByName(effect, L"Context", D2D1_PROPERTY_TYPE_UINT32, value, sizeof(void *)); ok(hr == E_INVALIDARG, "Got unexpected hr %#lx.\n", hr); - hr = ID2D1Effect_GetValueByName(effect, - L"Context", D2D1_PROPERTY_TYPE_IUNKNOWN, (BYTE *)&effect_context, sizeof(effect_context) + 1); + check_zero_buffer(value, sizeof(void *)); + + /* On size mismatch output buffer is zeroed. */ + memset(value, 0xcc, sizeof(value)); + hr = ID2D1Effect_GetValueByName(effect, L"Context", D2D1_PROPERTY_TYPE_IUNKNOWN, value, sizeof(void *) - 1); + ok(hr == E_INVALIDARG, "Got unexpected hr %#lx.\n", hr); + check_zero_buffer(value, sizeof(void *) - 1); + + memset(value, 0xcc, sizeof(value)); + hr = ID2D1Effect_GetValueByName(effect, L"Context", D2D1_PROPERTY_TYPE_IUNKNOWN, value, sizeof(void *) + 1); ok(hr == E_INVALIDARG, "Got unexpected hr %#lx.\n", hr); + check_zero_buffer(value, sizeof(void *) + 1); + + 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); - ok(effect_context != NULL && effect_context != (ID2D1EffectContext *)0xdeadbeef, - "Got unexpected effect context %p.\n", effect_context); + ok(!!effect_context, "Got unexpected effect context %p.\n", effect_context); - effect_context = (ID2D1EffectContext *)0xdeadbeef; - hr = ID2D1Effect_GetValue(effect, 0, D2D1_PROPERTY_TYPE_IUNKNOWN, (BYTE *)&effect_context, sizeof(effect_context) - 1); + memset(value, 0xcc, sizeof(value)); + hr = ID2D1Effect_GetValue(effect, 0, D2D1_PROPERTY_TYPE_IUNKNOWN, value, sizeof(void *) - 1); ok(hr == E_INVALIDARG, "Got unexpected hr %#lx.\n", hr); - hr = ID2D1Effect_GetValue(effect, 0, D2D1_PROPERTY_TYPE_IUNKNOWN, (BYTE *)&effect_context, sizeof(effect_context) + 1); + check_zero_buffer(value, sizeof(void *) - 1); + + memset(value, 0xcc, sizeof(value)); + hr = ID2D1Effect_GetValue(effect, 0, D2D1_PROPERTY_TYPE_IUNKNOWN, value, sizeof(void *) + 1); ok(hr == E_INVALIDARG, "Got unexpected hr %#lx.\n", hr); + check_zero_buffer(value, sizeof(void *) + 1); + + effect_context = NULL; hr = ID2D1Effect_GetValue(effect, 0, D2D1_PROPERTY_TYPE_IUNKNOWN, (BYTE *)&effect_context, sizeof(effect_context)); ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); - ok(effect_context != NULL && effect_context != (ID2D1EffectContext *)0xdeadbeef, - "Got unexpected effect context %p.\n", effect_context); + ok(!!effect_context, "Got unexpected effect context %p.\n", effect_context); hr = ID2D1Effect_SetValue(effect, 0, D2D1_PROPERTY_TYPE_IUNKNOWN, (BYTE *)&effect_context, sizeof(effect_context)); ok(hr == E_INVALIDARG, "Got unexpected hr %#lx.\n", hr); - integer = 0xdeadbeef; - hr = ID2D1Effect_GetValueByName(effect, L"Integer", D2D1_PROPERTY_TYPE_UINT32, (BYTE *)&integer, sizeof(integer) - 1); + memset(value, 0xcc, sizeof(value)); + hr = ID2D1Effect_GetValueByName(effect, L"Integer", D2D1_PROPERTY_TYPE_UINT32, value, 3); ok(hr == E_INVALIDARG, "Got unexpected hr %#lx.\n", hr); - hr = ID2D1Effect_GetValueByName(effect, L"Integer", D2D1_PROPERTY_TYPE_UINT32, (BYTE *)&integer, sizeof(integer) + 1); + check_zero_buffer(value, 3); + + memset(value, 0xcc, sizeof(value)); + hr = ID2D1Effect_GetValueByName(effect, L"Integer", D2D1_PROPERTY_TYPE_UINT32, value, 5); ok(hr == E_INVALIDARG, "Got unexpected hr %#lx.\n", hr); + check_zero_buffer(value, 5); + + integer = 0; hr = ID2D1Effect_GetValueByName(effect, L"Integer", D2D1_PROPERTY_TYPE_UINT32, (BYTE *)&integer, sizeof(integer)); ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); ok(integer == 10, "Got unexpected integer %u.", integer); - integer = 0xdeadbeef; - hr = ID2D1Effect_GetValue(effect, 1, D2D1_PROPERTY_TYPE_UINT32, (BYTE *)&integer, sizeof(integer) - 1); + memset(value, 0xcc, sizeof(value)); + hr = ID2D1Effect_GetValue(effect, 1, D2D1_PROPERTY_TYPE_UINT32, value, 3); ok(hr == E_INVALIDARG, "Got unexpected hr %#lx.\n", hr); - hr = ID2D1Effect_GetValue(effect, 1, D2D1_PROPERTY_TYPE_UINT32, (BYTE *)&integer, sizeof(integer) + 1); + check_zero_buffer(value, 3); + + memset(value, 0xcc, sizeof(value)); + hr = ID2D1Effect_GetValue(effect, 1, D2D1_PROPERTY_TYPE_UINT32, value, 5); ok(hr == E_INVALIDARG, "Got unexpected hr %#lx.\n", hr); + check_zero_buffer(value, 5); + + integer = 0; hr = ID2D1Effect_GetValue(effect, 1, D2D1_PROPERTY_TYPE_UINT32, (BYTE *)&integer, sizeof(integer)); ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); ok(integer == 10, "Got unexpected integer %u.", integer); - integer = 20; - hr = ID2D1Effect_SetValue(effect, 1, D2D1_PROPERTY_TYPE_UINT32, (BYTE *)&integer, sizeof(integer) - 1); + memset(value, 0, sizeof(value)); + hr = ID2D1Effect_SetValue(effect, 1, D2D1_PROPERTY_TYPE_UINT32, value, 3); ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); - hr = ID2D1Effect_SetValue(effect, 1, D2D1_PROPERTY_TYPE_UINT32, (BYTE *)&integer, sizeof(integer) + 1); + hr = ID2D1Effect_SetValue(effect, 1, D2D1_PROPERTY_TYPE_UINT32, value, 5); ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + + integer = 20; hr = ID2D1Effect_SetValue(effect, 1, D2D1_PROPERTY_TYPE_UINT32, (BYTE *)&integer, sizeof(integer)); ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); integer = 0xdeadbeef; -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/5469
From: Nikolay Sivov <nsivov(a)codeweavers.com> Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com> --- dlls/d2d1/tests/d2d1.c | 57 ++++++++++++++++++++++++------------------ 1 file changed, 33 insertions(+), 24 deletions(-) diff --git a/dlls/d2d1/tests/d2d1.c b/dlls/d2d1/tests/d2d1.c index 15a9eeb00ab..7eaeddda341 100644 --- a/dlls/d2d1/tests/d2d1.c +++ b/dlls/d2d1/tests/d2d1.c @@ -11726,20 +11726,26 @@ static void test_effect_properties(BOOL d3d11) UINT32 i, min_inputs, max_inputs, integer, index, size; ID2D1EffectContext *effect_context; D2D1_BUFFER_PRECISION precision; - float vec2[2], vec3[3], vec4[4]; ID2D1Properties *subproperties; D2D1_PROPERTY_TYPE prop_type; struct d2d1_test_context ctx; + D2D_MATRIX_3X2_F mat3x2; + D2D_MATRIX_4X3_F mat4x3; + D2D_MATRIX_4X4_F mat4x4; + D2D_MATRIX_5X4_F mat5x4; ID2D1Factory1 *factory; ID2D1Effect *effect; UINT32 count, data; + D2D_VECTOR_2F vec2; + D2D_VECTOR_3F vec3; + D2D_VECTOR_4F vec4; WCHAR buffer[128]; BYTE value[128]; - float mat[20]; - INT32 val; CLSID clsid; BOOL cached; HRESULT hr; + float *ptr; + INT32 val; static const WCHAR *effect_author = L"The Wine Project"; static const WCHAR *effect_category = L"Test"; @@ -11890,9 +11896,10 @@ static void test_effect_properties(BOOL d3d11) ok(!wcscmp(buffer, L"Vec2Prop"), "Unexpected name %s.\n", wine_dbgstr_w(buffer)); prop_type = ID2D1Effect_GetType(effect, index); ok(prop_type == D2D1_PROPERTY_TYPE_VECTOR2, "Unexpected type %u.\n", prop_type); - hr = ID2D1Effect_GetValue(effect, index, D2D1_PROPERTY_TYPE_VECTOR2, (BYTE *)vec2, sizeof(vec2)); + hr = ID2D1Effect_GetValue(effect, index, D2D1_PROPERTY_TYPE_VECTOR2, (BYTE *)&vec2, sizeof(vec2)); ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); - ok(vec2[0] == 3.0f && vec2[1] == 4.0f, "Unexpected vector (%.8e,%.8e).\n", vec2[0], vec2[1]); + ok(vec2.x == 3.0f, "Unexpected value %.8e.\n", vec2.x); + ok(vec2.y == 4.0f, "Unexpected value %.8e.\n", vec2.y); /* Vector3 property. */ index = ID2D1Effect_GetPropertyIndex(effect, L"Vec3Prop"); @@ -11901,10 +11908,11 @@ static void test_effect_properties(BOOL d3d11) ok(!wcscmp(buffer, L"Vec3Prop"), "Unexpected name %s.\n", wine_dbgstr_w(buffer)); prop_type = ID2D1Effect_GetType(effect, index); ok(prop_type == D2D1_PROPERTY_TYPE_VECTOR3, "Unexpected type %u.\n", prop_type); - hr = ID2D1Effect_GetValue(effect, index, D2D1_PROPERTY_TYPE_VECTOR3, (BYTE *)vec3, sizeof(vec3)); + hr = ID2D1Effect_GetValue(effect, index, D2D1_PROPERTY_TYPE_VECTOR3, (BYTE *)&vec3, sizeof(vec3)); ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); - ok(vec3[0] == 5.0f && vec3[1] == 6.0f && vec3[2] == 7.0f, "Unexpected vector (%.8e,%.8e,%.8e).\n", - vec3[0], vec3[1], vec3[2]); + ok(vec3.x == 5.0f, "Unexpected value %.8e.\n", vec3.x); + ok(vec3.y == 6.0f, "Unexpected value %.8e.\n", vec3.y); + ok(vec3.z == 7.0f, "Unexpected value %.8e.\n", vec3.z); /* Vector4 property. */ index = ID2D1Effect_GetPropertyIndex(effect, L"Vec4Prop"); @@ -11913,10 +11921,12 @@ static void test_effect_properties(BOOL d3d11) ok(!wcscmp(buffer, L"Vec4Prop"), "Unexpected name %s.\n", wine_dbgstr_w(buffer)); prop_type = ID2D1Effect_GetType(effect, index); ok(prop_type == D2D1_PROPERTY_TYPE_VECTOR4, "Unexpected type %u.\n", prop_type); - hr = ID2D1Effect_GetValue(effect, index, D2D1_PROPERTY_TYPE_VECTOR4, (BYTE *)vec4, sizeof(vec4)); + hr = ID2D1Effect_GetValue(effect, index, D2D1_PROPERTY_TYPE_VECTOR4, (BYTE *)&vec4, sizeof(vec4)); ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); - ok(vec4[0] == 8.0f && vec4[1] == 9.0f && vec4[2] == 10.0f && vec4[3] == 11.0f, - "Unexpected vector (%.8e,%.8e,%.8e,%.8e).\n", vec4[0], vec4[1], vec4[2], vec4[3]); + ok(vec4.x == 8.0f, "Unexpected value %.8e.\n", vec4.x); + ok(vec4.y == 9.0f, "Unexpected value %.8e.\n", vec4.y); + ok(vec4.z == 10.0f, "Unexpected value %.8e.\n", vec4.z); + ok(vec4.w == 11.0f, "Unexpected value %.8e.\n", vec4.w); /* Matrix3x2 property. */ index = ID2D1Effect_GetPropertyIndex(effect, L"Mat3x2Prop"); @@ -11925,11 +11935,10 @@ static void test_effect_properties(BOOL d3d11) ok(!wcscmp(buffer, L"Mat3x2Prop"), "Unexpected name %s.\n", wine_dbgstr_w(buffer)); prop_type = ID2D1Effect_GetType(effect, index); ok(prop_type == D2D1_PROPERTY_TYPE_MATRIX_3X2, "Unexpected type %u.\n", prop_type); - hr = ID2D1Effect_GetValue(effect, index, D2D1_PROPERTY_TYPE_MATRIX_3X2, (BYTE *)mat, 6 * sizeof(float)); + hr = ID2D1Effect_GetValue(effect, index, D2D1_PROPERTY_TYPE_MATRIX_3X2, (BYTE *)&mat3x2, sizeof(mat3x2)); ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); - ok(mat[0] == 1.0f && mat[1] == 2.0f && mat[2] == 3.0f && mat[3] == 4.0f && mat[4] == 5.0f && mat[5] == 6.0f, - "Unexpected matrix (%.8e,%.8e,%.8e,%.8e,%.8e,%.8e).\n", - mat[0], mat[1], mat[2], mat[3], mat[4], mat[5]); + for (i = 0, ptr = (float *)&mat3x2; i < sizeof(mat3x2) / sizeof(*ptr); ++i, ++ptr) + ok(*ptr == 1.0f + i, "Unexpected value %.8e.\n", *ptr); /* Matrix4x3 property. */ index = ID2D1Effect_GetPropertyIndex(effect, L"Mat4x3Prop"); @@ -11938,10 +11947,10 @@ static void test_effect_properties(BOOL d3d11) ok(!wcscmp(buffer, L"Mat4x3Prop"), "Unexpected name %s.\n", wine_dbgstr_w(buffer)); prop_type = ID2D1Effect_GetType(effect, index); ok(prop_type == D2D1_PROPERTY_TYPE_MATRIX_4X3, "Unexpected type %u.\n", prop_type); - hr = ID2D1Effect_GetValue(effect, index, D2D1_PROPERTY_TYPE_MATRIX_4X3, (BYTE *)mat, 12 * sizeof(float)); + hr = ID2D1Effect_GetValue(effect, index, D2D1_PROPERTY_TYPE_MATRIX_4X3, (BYTE *)&mat4x3, sizeof(mat4x3)); ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); - for (i = 0; i < 12; ++i) - ok(mat[i] == 1.0f + i, "Unexpected matrix element %u.\n", i); + for (i = 0, ptr = (float *)&mat4x3; i < sizeof(mat4x3) / sizeof(*ptr); ++i, ++ptr) + ok(*ptr == 1.0f + i, "Unexpected value %.8e.\n", *ptr); /* Matrix4x4 property. */ index = ID2D1Effect_GetPropertyIndex(effect, L"Mat4x4Prop"); @@ -11950,10 +11959,10 @@ static void test_effect_properties(BOOL d3d11) ok(!wcscmp(buffer, L"Mat4x4Prop"), "Unexpected name %s.\n", wine_dbgstr_w(buffer)); prop_type = ID2D1Effect_GetType(effect, index); ok(prop_type == D2D1_PROPERTY_TYPE_MATRIX_4X4, "Unexpected type %u.\n", prop_type); - hr = ID2D1Effect_GetValue(effect, index, D2D1_PROPERTY_TYPE_MATRIX_4X4, (BYTE *)mat, 16 * sizeof(float)); + hr = ID2D1Effect_GetValue(effect, index, D2D1_PROPERTY_TYPE_MATRIX_4X4, (BYTE *)&mat4x4, sizeof(mat4x4)); ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); - for (i = 0; i < 16; ++i) - ok(mat[i] == 1.0f + i, "Unexpected matrix element %u.\n", i); + for (i = 0, ptr = (float *)&mat4x4; i < sizeof(mat4x4) / sizeof(*ptr); ++i, ++ptr) + ok(*ptr == 1.0f + i, "Unexpected value %.8e.\n", *ptr); /* Matrix5x4 property. */ index = ID2D1Effect_GetPropertyIndex(effect, L"Mat5x4Prop"); @@ -11962,10 +11971,10 @@ static void test_effect_properties(BOOL d3d11) ok(!wcscmp(buffer, L"Mat5x4Prop"), "Unexpected name %s.\n", wine_dbgstr_w(buffer)); prop_type = ID2D1Effect_GetType(effect, index); ok(prop_type == D2D1_PROPERTY_TYPE_MATRIX_5X4, "Unexpected type %u.\n", prop_type); - hr = ID2D1Effect_GetValue(effect, index, D2D1_PROPERTY_TYPE_MATRIX_5X4, (BYTE *)mat, 20 * sizeof(float)); + hr = ID2D1Effect_GetValue(effect, index, D2D1_PROPERTY_TYPE_MATRIX_5X4, (BYTE *)&mat5x4, sizeof(mat5x4)); ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); - for (i = 0; i < 20; ++i) - ok(mat[i] == 1.0f + i, "Unexpected matrix element %u.\n", i); + for (i = 0, ptr = (float *)&mat5x4; i < sizeof(mat5x4) / sizeof(*ptr); ++i, ++ptr) + ok(*ptr == 1.0f + i, "Unexpected value %.8e.\n", *ptr); ID2D1Effect_Release(effect); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/5469
From: Nikolay Sivov <nsivov(a)codeweavers.com> Signed-off-by: Nikolay Sivov <nsivov(a)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); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/5469
Hi, It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated. The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=144845 Your paranoid android. === build (build log) === error: patch failed: dlls/d2d1/tests/d2d1.c:11726 Task: Patch failed to apply === debian11 (build log) === error: patch failed: dlls/d2d1/tests/d2d1.c:11726 Task: Patch failed to apply === debian11b (build log) === error: patch failed: dlls/d2d1/tests/d2d1.c:11726 Task: Patch failed to apply
participants (3)
-
Marvin -
Nikolay Sivov -
Nikolay Sivov (@nsivov)