Fixes Country Siblings' crash on startup.
`d2d_device_context_draw` doesn't accept `D2D_TARGET_UNKNOWN` because `render_target->target.bitmap->rtv` isn't reliably set when calling `ID3D11DeviceContext1_OMSetRenderTargets`. Therefore, we check for that condition and return early.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=58185
-- v3: d2d1: Fix a crash in DrawGlyphRun method family if no target is set. d2d1: Fix a crash in FillGeometry method family if no target is set. d2d1: Fix a crash in DrawGeometry method family if no target is set. d2d1: Fix a crash in DrawBitmap method family if no target is set. d2d1: Fix a crash in Clear method if no target is set.
From: Akihiro Sagawa sagawa.aki@gmail.com
--- dlls/d2d1/device.c | 27 +++++++++++++++++++++++++++ dlls/d2d1/tests/d2d1.c | 31 +++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+)
diff --git a/dlls/d2d1/device.c b/dlls/d2d1/device.c index d9494d4f90b..f6ff44cd32c 100644 --- a/dlls/d2d1/device.c +++ b/dlls/d2d1/device.c @@ -1216,6 +1216,15 @@ static void STDMETHODCALLTYPE d2d_device_context_DrawBitmap(ID2D1DeviceContext6 TRACE("iface %p, bitmap %p, dst_rect %s, opacity %.8e, interpolation_mode %#x, src_rect %s.\n", iface, bitmap, debug_d2d_rect_f(dst_rect), opacity, interpolation_mode, debug_d2d_rect_f(src_rect));
+ if (FAILED(context->error.code)) + return; + + if (context->target.type == D2D_TARGET_UNKNOWN) + { + d2d_device_context_set_error(context, D2DERR_WRONG_STATE); + return; + } + if (interpolation_mode != D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR && interpolation_mode != D2D1_BITMAP_INTERPOLATION_MODE_LINEAR) { @@ -2559,6 +2568,15 @@ static void STDMETHODCALLTYPE d2d_device_context_DrawImage(ID2D1DeviceContext6 * iface, image, debug_d2d_point_2f(target_offset), debug_d2d_rect_f(image_rect), interpolation_mode, composite_mode);
+ if (FAILED(context->error.code)) + return; + + if (context->target.type == D2D_TARGET_UNKNOWN) + { + d2d_device_context_set_error(context, D2DERR_WRONG_STATE); + return; + } + if (context->target.type == D2D_TARGET_COMMAND_LIST) { d2d_command_list_draw_image(context->target.command_list, image, target_offset, image_rect, @@ -2598,6 +2616,15 @@ static void STDMETHODCALLTYPE d2d_device_context_ID2D1DeviceContext_DrawBitmap(I iface, bitmap, debug_d2d_rect_f(dst_rect), opacity, interpolation_mode, debug_d2d_rect_f(src_rect), perspective_transform);
+ if (FAILED(context->error.code)) + return; + + if (context->target.type == D2D_TARGET_UNKNOWN) + { + d2d_device_context_set_error(context, D2DERR_WRONG_STATE); + return; + } + if (context->target.type == D2D_TARGET_COMMAND_LIST) { d2d_command_list_draw_bitmap(context->target.command_list, bitmap, dst_rect, opacity, interpolation_mode, diff --git a/dlls/d2d1/tests/d2d1.c b/dlls/d2d1/tests/d2d1.c index 70bb53d3bad..8674a403023 100644 --- a/dlls/d2d1/tests/d2d1.c +++ b/dlls/d2d1/tests/d2d1.c @@ -15717,10 +15717,13 @@ static void test_get_dxgi_device(BOOL d3d11)
static void test_no_target(BOOL d3d11) { + D2D1_BITMAP_PROPERTIES1 bitmap_desc; ID2D1DeviceContext *context; D2D1_MATRIX_3X2_F matrix; IDXGIDevice *dxgi_device; + ID2D1Bitmap1 *bitmap; ID2D1Device *device; + D2D1_SIZE_U size; D2D1_TAG t1, t2; HRESULT hr;
@@ -15756,6 +15759,34 @@ static void test_no_target(BOOL d3d11) ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#lx.\n", hr); ok(t1 == 0x10 && t2 == 0x20, "Unexpected tags %s:%s.\n", wine_dbgstr_longlong(t1), wine_dbgstr_longlong(t2));
+ /* DrawBitmap method */ + set_size_u(&size, 4, 4); + bitmap_desc.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM; + bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_IGNORE; + bitmap_desc.dpiX = 96.0f; + bitmap_desc.dpiY = 96.0f; + bitmap_desc.bitmapOptions = D2D1_BITMAP_OPTIONS_NONE; + bitmap_desc.colorContext = NULL; + hr = ID2D1DeviceContext_CreateBitmap(context, size, NULL, 0, &bitmap_desc, &bitmap); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + + ID2D1DeviceContext_BeginDraw(context); + + ID2D1DeviceContext_SetTags(context, 0x20, 0x10); + ID2D1DeviceContext_SetPrimitiveBlend(context, D2D1_PRIMITIVE_BLEND_SOURCE_OVER); + + ID2D1DeviceContext_SetTags(context, 0x20, 0x20); + ID2D1DeviceContext_DrawBitmap(context, (ID2D1Bitmap *)bitmap, NULL, 1.0f, D2D1_BITMAP_INTERPOLATION_MODE_LINEAR, NULL, NULL); + + ID2D1DeviceContext_SetTags(context, 0x20, 0x30); + ID2D1DeviceContext_DrawBitmap(context, (ID2D1Bitmap *)bitmap, NULL, 1.0f, D2D1_BITMAP_INTERPOLATION_MODE_LINEAR, NULL, NULL); + + hr = ID2D1DeviceContext_EndDraw(context, &t1, &t2); + ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#lx.\n", hr); + ok(t1 == 0x20 && t2 == 0x20, "Unexpected tags %s:%s.\n", wine_dbgstr_longlong(t1), wine_dbgstr_longlong(t2)); + + ID2D1Bitmap1_Release(bitmap); + ID2D1DeviceContext_Release(context); ID2D1Device_Release(device); IDXGIDevice_Release(dxgi_device);
From: Akihiro Sagawa sagawa.aki@gmail.com
--- dlls/d2d1/device.c | 21 +++++++++++++++++++++ dlls/d2d1/tests/d2d1.c | 24 ++++++++++++++++++++++++ 2 files changed, 45 insertions(+)
diff --git a/dlls/d2d1/device.c b/dlls/d2d1/device.c index f6ff44cd32c..e06bbb32cb1 100644 --- a/dlls/d2d1/device.c +++ b/dlls/d2d1/device.c @@ -586,6 +586,9 @@ static void STDMETHODCALLTYPE d2d_device_context_DrawLine(ID2D1DeviceContext6 *i TRACE("iface %p, p0 %s, p1 %s, brush %p, stroke_width %.8e, stroke_style %p.\n", iface, debug_d2d_point_2f(&p0), debug_d2d_point_2f(&p1), brush, stroke_width, stroke_style);
+ if (FAILED(context->error.code)) + return; + if (context->target.type == D2D_TARGET_COMMAND_LIST) { d2d_command_list_draw_line(context->target.command_list, context, p0, p1, brush, stroke_width, stroke_style); @@ -626,6 +629,9 @@ static void STDMETHODCALLTYPE d2d_device_context_DrawRectangle(ID2D1DeviceContex TRACE("iface %p, rect %s, brush %p, stroke_width %.8e, stroke_style %p.\n", iface, debug_d2d_rect_f(rect), brush, stroke_width, stroke_style);
+ if (FAILED(context->error.code)) + return; + if (context->target.type == D2D_TARGET_COMMAND_LIST) { d2d_command_list_draw_rectangle(context->target.command_list, context, rect, brush, stroke_width, stroke_style); @@ -677,6 +683,9 @@ static void STDMETHODCALLTYPE d2d_device_context_DrawRoundedRectangle(ID2D1Devic TRACE("iface %p, rect %p, brush %p, stroke_width %.8e, stroke_style %p.\n", iface, rect, brush, stroke_width, stroke_style);
+ if (FAILED(render_target->error.code)) + return; + if (FAILED(hr = ID2D1Factory_CreateRoundedRectangleGeometry(render_target->factory, rect, &geometry))) { ERR("Failed to create geometry, hr %#lx.\n", hr); @@ -716,6 +725,9 @@ static void STDMETHODCALLTYPE d2d_device_context_DrawEllipse(ID2D1DeviceContext6 TRACE("iface %p, ellipse %p, brush %p, stroke_width %.8e, stroke_style %p.\n", iface, ellipse, brush, stroke_width, stroke_style);
+ if (FAILED(render_target->error.code)) + return; + if (FAILED(hr = ID2D1Factory_CreateEllipseGeometry(render_target->factory, ellipse, &geometry))) { ERR("Failed to create geometry, hr %#lx.\n", hr); @@ -961,6 +973,15 @@ static void STDMETHODCALLTYPE d2d_device_context_DrawGeometry(ID2D1DeviceContext TRACE("iface %p, geometry %p, brush %p, stroke_width %.8e, stroke_style %p.\n", iface, geometry, brush, stroke_width, stroke_style);
+ if (FAILED(context->error.code)) + return; + + if (context->target.type == D2D_TARGET_UNKNOWN) + { + d2d_device_context_set_error(context, D2DERR_WRONG_STATE); + return; + } + if (context->target.type == D2D_TARGET_COMMAND_LIST) { d2d_command_list_draw_geometry(context->target.command_list, context, geometry, brush, diff --git a/dlls/d2d1/tests/d2d1.c b/dlls/d2d1/tests/d2d1.c index 8674a403023..544549a4892 100644 --- a/dlls/d2d1/tests/d2d1.c +++ b/dlls/d2d1/tests/d2d1.c @@ -15718,12 +15718,15 @@ static void test_get_dxgi_device(BOOL d3d11) static void test_no_target(BOOL d3d11) { D2D1_BITMAP_PROPERTIES1 bitmap_desc; + ID2D1SolidColorBrush *brush; ID2D1DeviceContext *context; D2D1_MATRIX_3X2_F matrix; IDXGIDevice *dxgi_device; ID2D1Bitmap1 *bitmap; ID2D1Device *device; + D2D1_COLOR_F color; D2D1_SIZE_U size; + D2D1_RECT_F rect; D2D1_TAG t1, t2; HRESULT hr;
@@ -15787,6 +15790,27 @@ static void test_no_target(BOOL d3d11)
ID2D1Bitmap1_Release(bitmap);
+ /* DrawRectangle method */ + set_color(&color, 0.0f, 0.0f, 0.0f, 0.0f); + hr = ID2D1DeviceContext_CreateSolidColorBrush(context, &color, NULL, &brush); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + + set_rect(&rect, 0.0f, 0.0f, 1.0f, 1.0f); + + ID2D1DeviceContext_BeginDraw(context); + + ID2D1DeviceContext_SetTags(context, 0x30, 0x10); + ID2D1DeviceContext_DrawRectangle(context, &rect, (ID2D1Brush *)brush, 1.0f, NULL); + + ID2D1DeviceContext_SetTags(context, 0x30, 0x20); + ID2D1DeviceContext_DrawRectangle(context, &rect, (ID2D1Brush *)brush, 1.0f, NULL); + + hr = ID2D1DeviceContext_EndDraw(context, &t1, &t2); + ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#lx.\n", hr); + ok(t1 == 0x30 && t2 == 0x10, "Unexpected tags %s:%s.\n", wine_dbgstr_longlong(t1), wine_dbgstr_longlong(t2)); + + ID2D1SolidColorBrush_Release(brush); + ID2D1DeviceContext_Release(context); ID2D1Device_Release(device); IDXGIDevice_Release(dxgi_device);
From: Akihiro Sagawa sagawa.aki@gmail.com
--- dlls/d2d1/device.c | 15 +++++++++++++++ dlls/d2d1/tests/d2d1.c | 13 +++++++++++++ 2 files changed, 28 insertions(+)
diff --git a/dlls/d2d1/device.c b/dlls/d2d1/device.c index e06bbb32cb1..4246b84979f 100644 --- a/dlls/d2d1/device.c +++ b/dlls/d2d1/device.c @@ -657,6 +657,9 @@ static void STDMETHODCALLTYPE d2d_device_context_FillRectangle(ID2D1DeviceContex
TRACE("iface %p, rect %s, brush %p.\n", iface, debug_d2d_rect_f(rect), brush);
+ if (FAILED(context->error.code)) + return; + if (context->target.type == D2D_TARGET_COMMAND_LIST) { d2d_command_list_fill_rectangle(context->target.command_list, context, rect, brush); @@ -705,6 +708,9 @@ static void STDMETHODCALLTYPE d2d_device_context_FillRoundedRectangle(ID2D1Devic
TRACE("iface %p, rect %p, brush %p.\n", iface, rect, brush);
+ if (FAILED(render_target->error.code)) + return; + if (FAILED(hr = ID2D1Factory_CreateRoundedRectangleGeometry(render_target->factory, rect, &geometry))) { ERR("Failed to create geometry, hr %#lx.\n", hr); @@ -747,6 +753,9 @@ static void STDMETHODCALLTYPE d2d_device_context_FillEllipse(ID2D1DeviceContext6
TRACE("iface %p, ellipse %p, brush %p.\n", iface, ellipse, brush);
+ if (FAILED(render_target->error.code)) + return; + if (FAILED(hr = ID2D1Factory_CreateEllipseGeometry(render_target->factory, ellipse, &geometry))) { ERR("Failed to create geometry, hr %#lx.\n", hr); @@ -1109,6 +1118,12 @@ static void STDMETHODCALLTYPE d2d_device_context_FillGeometry(ID2D1DeviceContext if (FAILED(context->error.code)) return;
+ if (context->target.type == D2D_TARGET_UNKNOWN) + { + d2d_device_context_set_error(context, D2DERR_WRONG_STATE); + return; + } + if (opacity_brush && brush_impl->type != D2D_BRUSH_TYPE_BITMAP) { d2d_device_context_set_error(context, D2DERR_INCOMPATIBLE_BRUSH_TYPES); diff --git a/dlls/d2d1/tests/d2d1.c b/dlls/d2d1/tests/d2d1.c index 544549a4892..74a361e5598 100644 --- a/dlls/d2d1/tests/d2d1.c +++ b/dlls/d2d1/tests/d2d1.c @@ -15809,6 +15809,19 @@ static void test_no_target(BOOL d3d11) ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#lx.\n", hr); ok(t1 == 0x30 && t2 == 0x10, "Unexpected tags %s:%s.\n", wine_dbgstr_longlong(t1), wine_dbgstr_longlong(t2));
+ /* FillRectangle method */ + ID2D1DeviceContext_BeginDraw(context); + + ID2D1DeviceContext_SetTags(context, 0x40, 0x10); + ID2D1DeviceContext_FillRectangle(context, &rect, (ID2D1Brush *)brush); + + ID2D1DeviceContext_SetTags(context, 0x40, 0x20); + ID2D1DeviceContext_FillRectangle(context, &rect, (ID2D1Brush *)brush); + + hr = ID2D1DeviceContext_EndDraw(context, &t1, &t2); + ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#lx.\n", hr); + ok(t1 == 0x40 && t2 == 0x10, "Unexpected tags %s:%s.\n", wine_dbgstr_longlong(t1), wine_dbgstr_longlong(t2)); + ID2D1SolidColorBrush_Release(brush);
ID2D1DeviceContext_Release(context);
From: Akihiro Sagawa sagawa.aki@gmail.com
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=58185 --- dlls/d2d1/device.c | 9 ++++++++ dlls/d2d1/tests/d2d1.c | 47 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+)
diff --git a/dlls/d2d1/device.c b/dlls/d2d1/device.c index 4780acb3bec..d9494d4f90b 100644 --- a/dlls/d2d1/device.c +++ b/dlls/d2d1/device.c @@ -1858,6 +1858,15 @@ static void STDMETHODCALLTYPE d2d_device_context_Clear(ID2D1DeviceContext6 *ifac
TRACE("iface %p, colour %p.\n", iface, colour);
+ if (FAILED(context->error.code)) + return; + + if (context->target.type == D2D_TARGET_UNKNOWN) + { + d2d_device_context_set_error(context, D2DERR_WRONG_STATE); + return; + } + if (context->target.type == D2D_TARGET_COMMAND_LIST) { d2d_command_list_clear(context->target.command_list, colour); diff --git a/dlls/d2d1/tests/d2d1.c b/dlls/d2d1/tests/d2d1.c index 997ebc81ceb..70bb53d3bad 100644 --- a/dlls/d2d1/tests/d2d1.c +++ b/dlls/d2d1/tests/d2d1.c @@ -15715,6 +15715,52 @@ static void test_get_dxgi_device(BOOL d3d11) release_test_context(&ctx); }
+static void test_no_target(BOOL d3d11) +{ + ID2D1DeviceContext *context; + D2D1_MATRIX_3X2_F matrix; + IDXGIDevice *dxgi_device; + ID2D1Device *device; + D2D1_TAG t1, t2; + HRESULT hr; + + if (!pD2D1CreateDevice) + { + win_skip("D2D1CreateDevice() is unavailable.\n"); + return; + } + + dxgi_device = create_device(d3d11); + ok(!!dxgi_device, "Failed to create device.\n"); + + hr = pD2D1CreateDevice(dxgi_device, NULL, &device); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + + hr = ID2D1Device_CreateDeviceContext(device, D2D1_DEVICE_CONTEXT_OPTIONS_NONE, &context); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + + /* Clear method */ + ID2D1DeviceContext_BeginDraw(context); + + set_matrix_identity(&matrix); + ID2D1DeviceContext_SetTags(context, 0x10, 0x10); + ID2D1DeviceContext_SetTransform(context, &matrix); + + ID2D1DeviceContext_SetTags(context, 0x10, 0x20); + ID2D1DeviceContext_Clear(context, 0); + + ID2D1DeviceContext_SetTags(context, 0x10, 0x30); + ID2D1DeviceContext_Clear(context, 0); + + hr = ID2D1DeviceContext_EndDraw(context, &t1, &t2); + ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#lx.\n", hr); + ok(t1 == 0x10 && t2 == 0x20, "Unexpected tags %s:%s.\n", wine_dbgstr_longlong(t1), wine_dbgstr_longlong(t2)); + + ID2D1DeviceContext_Release(context); + ID2D1Device_Release(device); + IDXGIDevice_Release(dxgi_device); +} + START_TEST(d2d1) { HMODULE d2d1_dll = GetModuleHandleA("d2d1.dll"); @@ -15812,6 +15858,7 @@ START_TEST(d2d1) queue_test(test_wic_target_format); queue_test(test_effect_blob_property); queue_test(test_get_dxgi_device); + queue_test(test_no_target);
run_queued_tests(); }
From: Akihiro Sagawa sagawa.aki@gmail.com
--- dlls/d2d1/device.c | 6 ++++++ dlls/d2d1/tests/d2d1.c | 24 ++++++++++++++++++++++++ 2 files changed, 30 insertions(+)
diff --git a/dlls/d2d1/device.c b/dlls/d2d1/device.c index 4246b84979f..59e93bfac38 100644 --- a/dlls/d2d1/device.c +++ b/dlls/d2d1/device.c @@ -1549,6 +1549,12 @@ static void d2d_device_context_draw_glyph_run(struct d2d_device_context *context if (FAILED(context->error.code)) return;
+ if (context->target.type == D2D_TARGET_UNKNOWN) + { + d2d_device_context_set_error(context, D2DERR_WRONG_STATE); + return; + } + if (context->target.type == D2D_TARGET_COMMAND_LIST) { d2d_command_list_draw_glyph_run(context->target.command_list, context, baseline_origin, glyph_run, diff --git a/dlls/d2d1/tests/d2d1.c b/dlls/d2d1/tests/d2d1.c index 74a361e5598..ae19ceaf0c8 100644 --- a/dlls/d2d1/tests/d2d1.c +++ b/dlls/d2d1/tests/d2d1.c @@ -15718,6 +15718,8 @@ static void test_get_dxgi_device(BOOL d3d11) static void test_no_target(BOOL d3d11) { D2D1_BITMAP_PROPERTIES1 bitmap_desc; + IDWriteFactory *dwrite_factory; + IDWriteTextFormat *text_format; ID2D1SolidColorBrush *brush; ID2D1DeviceContext *context; D2D1_MATRIX_3X2_F matrix; @@ -15822,6 +15824,28 @@ static void test_no_target(BOOL d3d11) ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#lx.\n", hr); ok(t1 == 0x40 && t2 == 0x10, "Unexpected tags %s:%s.\n", wine_dbgstr_longlong(t1), wine_dbgstr_longlong(t2));
+ /* DrawText method */ + hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, &IID_IDWriteFactory, (IUnknown **)&dwrite_factory); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + hr = IDWriteFactory_CreateTextFormat(dwrite_factory, L"Tahoma", NULL, DWRITE_FONT_WEIGHT_NORMAL, + DWRITE_FONT_STYLE_NORMAL, DWRITE_FONT_STRETCH_NORMAL, 10.0f, L"", &text_format); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + + ID2D1DeviceContext_BeginDraw(context); + + ID2D1DeviceContext_SetTags(context, 0x50, 0x10); + ID2D1DeviceContext_DrawText(context, L"Wine", 4, text_format, &rect, (ID2D1Brush *)brush, D2D1_DRAW_TEXT_OPTIONS_NONE, DWRITE_MEASURING_MODE_NATURAL); + + ID2D1DeviceContext_SetTags(context, 0x50, 0x20); + ID2D1DeviceContext_DrawText(context, L"Wine", 4, text_format, &rect, (ID2D1Brush *)brush, D2D1_DRAW_TEXT_OPTIONS_NONE, DWRITE_MEASURING_MODE_NATURAL); + + hr = ID2D1DeviceContext_EndDraw(context, &t1, &t2); + ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#lx.\n", hr); + ok(t1 == 0x50 && t2 == 0x10, "Unexpected tags %s:%s.\n", wine_dbgstr_longlong(t1), wine_dbgstr_longlong(t2)); + + IDWriteTextFormat_Release(text_format); + IDWriteFactory_Release(dwrite_factory); + ID2D1SolidColorBrush_Release(brush);
ID2D1DeviceContext_Release(context);