[PATCH] wined3d: Ignore clears if count = 0 and rects != NULL (try 2)

Stefan Dösinger stefan at codeweavers.com
Wed Jan 23 08:02:45 CST 2013


try 2:
-> Add tests for old ddraw versions.
-> Add braces around initialization in ddraw7.
-> Consistent casing of hex numbers.
-> Fix the WARN line in wined3d.

Fixes bug 19773.

In cutscenes, Largo Winch clears an area on the top and bottom of the
screen with a clear that clears two rectangles. Outside of the
cutscenes, it still performs the clear call, but sets the rectangle
count to 0. The rectangles contain whatever area is left over from the
cutscene fade-out effect, usually the bottom two lines. Wine currently
ignores the rectangles and clears the entire screen to black.
---
 dlls/d3d8/tests/visual.c  | 27 +++++++++++++++++++
 dlls/d3d9/tests/visual.c  | 27 +++++++++++++++++++
 dlls/ddraw/tests/ddraw1.c | 66 +++++++++++++++++++++++++++++++++++++++++++++
 dlls/ddraw/tests/ddraw2.c | 69 +++++++++++++++++++++++++++++++++++++++++++++++
 dlls/ddraw/tests/ddraw4.c | 44 ++++++++++++++++++++++++++++++
 dlls/ddraw/tests/ddraw7.c | 45 +++++++++++++++++++++++++++++++
 dlls/ddraw/viewport.c     | 12 +++++++++
 dlls/wined3d/device.c     |  6 +++++
 8 files changed, 296 insertions(+)

diff --git a/dlls/d3d8/tests/visual.c b/dlls/d3d8/tests/visual.c
index 6aaf365..764e9c1 100644
--- a/dlls/d3d8/tests/visual.c
+++ b/dlls/d3d8/tests/visual.c
@@ -347,6 +347,33 @@ static void clear_test(IDirect3DDevice8 *device)
     ok(color == 0x00ffffff, "Clear rectangle 4(neg, neg) has color %08x\n", color);
 
     IDirect3DDevice8_Present(device, NULL, NULL, NULL, NULL);
+
+    hr = IDirect3DDevice8_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
+    ok(SUCCEEDED(hr), "IDirect3DDevice8_Clear failed with %#08x\n", hr);
+
+    rect[0].x1 = 0;
+    rect[0].y1 = 0;
+    rect[0].x2 = 640;
+    rect[0].y2 = 480;
+    hr = IDirect3DDevice8_Clear(device, 0, rect, D3DCLEAR_TARGET, 0xffff0000, 0.0, 0);
+    ok(SUCCEEDED(hr), "IDirect3DDevice8_Clear failed with %#08x\n", hr);
+
+    color = getPixelColor(device, 320, 240);
+    ok(color_match(color, D3DCOLOR_ARGB(0x00, 0xff, 0xff, 0xff), 1),
+            "Clear with count = 0, rect != NULL has color %#08x\n", color);
+
+    IDirect3DDevice8_Present(device, NULL, NULL, NULL, NULL);
+
+    hr = IDirect3DDevice8_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
+    ok(SUCCEEDED(hr), "IDirect3DDevice8_Clear failed with %#08x\n", hr);
+    hr = IDirect3DDevice8_Clear(device, 1, NULL, D3DCLEAR_TARGET, 0xff00ff00, 0.0, 0);
+    ok(SUCCEEDED(hr), "IDirect3DDevice8_Clear failed with %#08x\n", hr);
+
+    color = getPixelColor(device, 320, 240);
+    ok(color_match(color, D3DCOLOR_ARGB(0x00, 0x00, 0xff, 0x00), 1),
+            "Clear with count = 1, rect = NULL has color %#08x\n", color);
+
+    IDirect3DDevice8_Present(device, NULL, NULL, NULL, NULL);
 }
 
 struct sVertex {
diff --git a/dlls/d3d9/tests/visual.c b/dlls/d3d9/tests/visual.c
index a9c5c44..4d429c4 100644
--- a/dlls/d3d9/tests/visual.c
+++ b/dlls/d3d9/tests/visual.c
@@ -678,6 +678,33 @@ static void clear_test(IDirect3DDevice9 *device)
     ok(color == 0x00ffffff, "Color write protected clear returned color %08x\n", color);
 
     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
+
+    hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x00ffffff, 0.0, 0);
+    ok(SUCCEEDED(hr), "IDirect3DDevice9_Clear failed with %08x\n", hr);
+
+    rect[0].x1 = 0;
+    rect[0].y1 = 0;
+    rect[0].x2 = 640;
+    rect[0].y2 = 480;
+    hr = IDirect3DDevice9_Clear(device, 0, rect, D3DCLEAR_TARGET, 0x00ff0000, 0.0, 0);
+    ok(SUCCEEDED(hr), "IDirect3DDevice9_Clear failed with %08x\n", hr);
+
+    color = getPixelColor(device, 320, 240);
+    ok(color_match(color, D3DCOLOR_ARGB(0x00, 0xff, 0xff, 0xff), 1),
+            "Clear with count = 0, rect != NULL has color %08x\n", color);
+
+    IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
+
+    hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
+    ok(SUCCEEDED(hr), "IDirect3DDevice9_Clear failed with %08x\n", hr);
+    hr = IDirect3DDevice9_Clear(device, 1, NULL, D3DCLEAR_TARGET, 0xff00ff00, 0.0, 0);
+    ok(SUCCEEDED(hr), "IDirect3DDevice9_Clear failed with %08x\n", hr);
+
+    color = getPixelColor(device, 320, 240);
+    ok(color_match(color, D3DCOLOR_ARGB(0x00, 0x00, 0xff, 0x00), 1),
+            "Clear with count = 1, rect = NULL has color %08x\n", color);
+
+    IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
 }
 
 static void color_fill_test(IDirect3DDevice9 *device)
diff --git a/dlls/ddraw/tests/ddraw1.c b/dlls/ddraw/tests/ddraw1.c
index 2cbcf44..80121f0 100644
--- a/dlls/ddraw/tests/ddraw1.c
+++ b/dlls/ddraw/tests/ddraw1.c
@@ -1,5 +1,6 @@
 /*
  * Copyright 2011-2012 Henri Verbeet for CodeWeavers
+ * Copyright 2012-2013 Stefan Dösinger for CodeWeavers
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -2659,6 +2660,70 @@ static void test_coop_level_multi_window(void)
     DestroyWindow(window1);
 }
 
+static void test_clear_rect_count(void)
+{
+    static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
+    IDirect3DMaterial *white, *red, *green, *blue;
+    IDirect3DViewport *viewport;
+    IDirect3DDevice *device;
+    IDirectDrawSurface *rt;
+    IDirectDraw *ddraw;
+    D3DCOLOR color;
+    HWND window;
+    HRESULT hr;
+
+    window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
+            0, 0, 640, 480, 0, 0, 0, 0);
+    if (!(ddraw = create_ddraw()))
+    {
+        skip("Failed to create ddraw object, skipping test.\n");
+        DestroyWindow(window);
+        return;
+    }
+    if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
+    {
+        skip("Failed to create D3D device, skipping test.\n");
+        IDirectDraw_Release(ddraw);
+        DestroyWindow(window);
+        return;
+    }
+
+    hr = IDirect3DDevice_QueryInterface(device, &IID_IDirectDrawSurface, (void **)&rt);
+    ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
+
+    white = create_diffuse_material(device, 1.0f, 1.0f, 1.0f, 1.0f);
+    red   = create_diffuse_material(device, 1.0f, 0.0f, 0.0f, 1.0f);
+    green = create_diffuse_material(device, 0.0f, 1.0f, 0.0f, 1.0f);
+    blue  = create_diffuse_material(device, 0.0f, 0.0f, 1.0f, 1.0f);
+    viewport = create_viewport(device, 0, 0, 640, 480);
+
+    viewport_set_background(device, viewport, white);
+    hr = IDirect3DViewport_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
+    ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
+    viewport_set_background(device, viewport, red);
+    hr = IDirect3DViewport_Clear(viewport, 0, &clear_rect, D3DCLEAR_TARGET);
+    ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
+    viewport_set_background(device, viewport, green);
+    hr = IDirect3DViewport_Clear(viewport, 0, NULL, D3DCLEAR_TARGET);
+    ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
+    viewport_set_background(device, viewport, blue);
+    hr = IDirect3DViewport_Clear(viewport, 1, NULL, D3DCLEAR_TARGET);
+    ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
+
+    color = get_surface_color(rt, 320, 240);
+    ok(compare_color(color, 0x00ffffff, 1), "Got unexpected color 0x%08x.\n", color);
+
+    IDirectDrawSurface_Release(rt);
+    destroy_viewport(device, viewport);
+    destroy_material(white);
+    destroy_material(red);
+    destroy_material(green);
+    destroy_material(blue);
+    IDirect3DDevice_Release(device);
+    IDirectDraw_Release(ddraw);
+    DestroyWindow(window);
+}
+
 START_TEST(ddraw1)
 {
     test_coop_level_create_device_window();
@@ -2680,4 +2745,5 @@ START_TEST(ddraw1)
     test_initialize();
     test_coop_level_surf_create();
     test_coop_level_multi_window();
+    test_clear_rect_count();
 }
diff --git a/dlls/ddraw/tests/ddraw2.c b/dlls/ddraw/tests/ddraw2.c
index 79b0e9b..a3ecbfd 100644
--- a/dlls/ddraw/tests/ddraw2.c
+++ b/dlls/ddraw/tests/ddraw2.c
@@ -1,5 +1,6 @@
 /*
  * Copyright 2011-2012 Henri Verbeet for CodeWeavers
+ * Copyright 2012-2013 Stefan Dösinger for CodeWeavers
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -2778,6 +2779,73 @@ static void test_coop_level_multi_window(void)
     DestroyWindow(window1);
 }
 
+static void test_clear_rect_count(void)
+{
+    static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
+    IDirect3DMaterial2 *white, *red, *green, *blue;
+    IDirect3DViewport2 *viewport;
+    IDirect3DDevice2 *device;
+    IDirectDrawSurface *rt;
+    IDirectDraw2 *ddraw;
+    D3DCOLOR color;
+    HWND window;
+    HRESULT hr;
+
+    window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
+            0, 0, 640, 480, 0, 0, 0, 0);
+    if (!(ddraw = create_ddraw()))
+    {
+        skip("Failed to create ddraw object, skipping test.\n");
+        DestroyWindow(window);
+        return;
+    }
+    if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
+    {
+        skip("Failed to create D3D device, skipping test.\n");
+        IDirectDraw2_Release(ddraw);
+        DestroyWindow(window);
+        return;
+    }
+
+    hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
+    ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
+
+    white = create_diffuse_material(device, 1.0f, 1.0f, 1.0f, 1.0f);
+    red   = create_diffuse_material(device, 1.0f, 0.0f, 0.0f, 1.0f);
+    green = create_diffuse_material(device, 0.0f, 1.0f, 0.0f, 1.0f);
+    blue  = create_diffuse_material(device, 0.0f, 0.0f, 1.0f, 1.0f);
+
+    viewport = create_viewport(device, 0, 0, 640, 480);
+    hr = IDirect3DDevice2_SetCurrentViewport(device, viewport);
+    ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
+
+    viewport_set_background(device, viewport, white);
+    hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
+    ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
+    viewport_set_background(device, viewport, red);
+    hr = IDirect3DViewport2_Clear(viewport, 0, &clear_rect, D3DCLEAR_TARGET);
+    ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
+    viewport_set_background(device, viewport, green);
+    hr = IDirect3DViewport2_Clear(viewport, 0, NULL, D3DCLEAR_TARGET);
+    ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
+    viewport_set_background(device, viewport, blue);
+    hr = IDirect3DViewport2_Clear(viewport, 0, &clear_rect, D3DCLEAR_TARGET);
+    ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
+
+    color = get_surface_color(rt, 320, 240);
+    ok(compare_color(color, 0x00ffffff, 1), "Got unexpected color 0x%08x.\n", color);
+
+    IDirectDrawSurface_Release(rt);
+    destroy_viewport(device, viewport);
+    destroy_material(white);
+    destroy_material(red);
+    destroy_material(green);
+    destroy_material(blue);
+    IDirect3DDevice2_Release(device);
+    IDirectDraw2_Release(ddraw);
+    DestroyWindow(window);
+}
+
 START_TEST(ddraw2)
 {
     test_coop_level_create_device_window();
@@ -2801,4 +2869,5 @@ START_TEST(ddraw2)
     test_initialize();
     test_coop_level_surf_create();
     test_coop_level_multi_window();
+    test_clear_rect_count();
 }
diff --git a/dlls/ddraw/tests/ddraw4.c b/dlls/ddraw/tests/ddraw4.c
index 76ed55d..e43143f 100644
--- a/dlls/ddraw/tests/ddraw4.c
+++ b/dlls/ddraw/tests/ddraw4.c
@@ -3037,6 +3037,49 @@ static void test_draw_strided(void)
     DestroyWindow(window);
 }
 
+static void test_clear_rect_count(void)
+{
+    IDirectDrawSurface4 *rt;
+    IDirect3DDevice3 *device;
+    D3DCOLOR color;
+    HWND window;
+    HRESULT hr;
+    IDirect3DViewport3 *viewport;
+    static D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
+
+    window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
+            0, 0, 640, 480, 0, 0, 0, 0);
+    if (!(device = create_device(window, DDSCL_NORMAL)))
+    {
+        skip("Failed to create D3D device, skipping test.\n");
+        DestroyWindow(window);
+        return;
+    }
+
+    hr = IDirect3DDevice3_GetRenderTarget(device, &rt);
+    ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
+
+    viewport = create_viewport(device, 0, 0, 640, 480);
+    hr = IDirect3DDevice3_SetCurrentViewport(device, viewport);
+    ok(SUCCEEDED(hr), "Failed to activate the viewport, hr %#x.\n", hr);
+    hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0x00ffffff, 0.0f, 0);
+    ok(SUCCEEDED(hr), "Failed to clear the viewport, hr %#x.\n", hr);
+    hr = IDirect3DViewport3_Clear2(viewport, 0, &clear_rect, D3DCLEAR_TARGET, 0x00ff0000, 0.0f, 0);
+    ok(SUCCEEDED(hr), "Failed to clear the viewport, hr %#x.\n", hr);
+    hr = IDirect3DViewport3_Clear2(viewport, 0, NULL, D3DCLEAR_TARGET, 0x0000ff00, 0.0f, 0);
+    ok(SUCCEEDED(hr), "Failed to clear the viewport, hr %#x.\n", hr);
+    hr = IDirect3DViewport3_Clear2(viewport, 1, NULL, D3DCLEAR_TARGET, 0x000000ff, 0.0f, 0);
+    ok(SUCCEEDED(hr), "Failed to clear the viewport, hr %#x.\n", hr);
+
+    color = get_surface_color(rt, 320, 240);
+    ok(compare_color(color, 0x00ffffff, 1), "Got unexpected color 0x%08x.\n", color);
+
+    IDirect3DViewport3_Release(viewport);
+    IDirectDrawSurface4_Release(rt);
+    IDirect3DDevice3_Release(device);
+    DestroyWindow(window);
+}
+
 START_TEST(ddraw4)
 {
     test_process_vertices();
@@ -3063,4 +3106,5 @@ START_TEST(ddraw4)
     test_vb_discard();
     test_coop_level_multi_window();
     test_draw_strided();
+    test_clear_rect_count();
 }
diff --git a/dlls/ddraw/tests/ddraw7.c b/dlls/ddraw/tests/ddraw7.c
index 6b6f6d6..6651687 100644
--- a/dlls/ddraw/tests/ddraw7.c
+++ b/dlls/ddraw/tests/ddraw7.c
@@ -2839,6 +2839,50 @@ static void test_draw_strided(void)
     DestroyWindow(window);
 }
 
+static void test_clear_rect_count(void)
+{
+    IDirectDrawSurface7 *rt;
+    IDirect3DDevice7 *device;
+    D3DCOLOR color;
+    HWND window;
+    HRESULT hr;
+    D3DRECT rect = {{0}, {0}, {640}, {480}};
+
+    window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW,
+            0, 0, 640, 480, 0, 0, 0, 0);
+    if (!(device = create_device(window, DDSCL_NORMAL)))
+    {
+        skip("Failed to create D3D device, skipping test.\n");
+        DestroyWindow(window);
+        return;
+    }
+
+    hr = IDirect3DDevice7_GetRenderTarget(device, &rt);
+    ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
+
+    hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x00ffffff, 1.0f, 0);
+    ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
+    hr = IDirect3DDevice7_Clear(device, 0, &rect, D3DCLEAR_TARGET, 0x00ff0000, 1.0f, 0);
+    ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
+
+    color = get_surface_color(rt, 320, 240);
+    ok(compare_color(color, 0x00ffffff, 1),
+            "Clear with count = 0, rect != NULL has color %#08x.\n", color);
+
+    hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x00ffffff, 1.0f, 0);
+    ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
+    hr = IDirect3DDevice7_Clear(device, 1, NULL, D3DCLEAR_TARGET, 0x0000ff00, 1.0f, 0);
+    ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
+
+    color = get_surface_color(rt, 320, 240);
+    ok(compare_color(color, 0x0000ff00, 1),
+            "Clear with count = 1, rect = NULL has color %#08x.\n", color);
+
+    IDirectDrawSurface7_Release(rt);
+    IDirect3DDevice7_Release(device);
+    DestroyWindow(window);
+}
+
 START_TEST(ddraw7)
 {
     HMODULE module = GetModuleHandleA("ddraw.dll");
@@ -2872,4 +2916,5 @@ START_TEST(ddraw7)
     test_vb_discard();
     test_coop_level_multi_window();
     test_draw_strided();
+    test_clear_rect_count();
 }
diff --git a/dlls/ddraw/viewport.c b/dlls/ddraw/viewport.c
index f78ead0..9231c19 100644
--- a/dlls/ddraw/viewport.c
+++ b/dlls/ddraw/viewport.c
@@ -670,6 +670,12 @@ static HRESULT WINAPI d3d_viewport_Clear(IDirect3DViewport3 *iface,
 
     TRACE("iface %p, rect_count %u, rects %p, flags %#x.\n", iface, rect_count, rects, flags);
 
+    if (!rects || !rect_count)
+    {
+        WARN("rect_count = %u, rects = %p, ignoring clear\n", rect_count, rects);
+        return D3D_OK;
+    }
+
     if (This->active_device == NULL) {
         ERR(" Trying to clear a viewport not attached to a device !\n");
         return D3DERR_VIEWPORTHASNODEVICE;
@@ -1060,6 +1066,12 @@ static HRESULT WINAPI d3d_viewport_Clear2(IDirect3DViewport3 *iface, DWORD rect_
     TRACE("iface %p, rect_count %u, rects %p, flags %#x, color 0x%08x, depth %.8e, stencil %u.\n",
             iface, rect_count, rects, flags, color, depth, stencil);
 
+    if (!rects || !rect_count)
+    {
+        WARN("rect_count = %u, rects = %p, ignoring clear\n", rect_count, rects);
+        return D3D_OK;
+    }
+
     wined3d_mutex_lock();
 
     if (!viewport->active_device)
diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c
index cedb39e..3ad5f71 100644
--- a/dlls/wined3d/device.c
+++ b/dlls/wined3d/device.c
@@ -4011,6 +4011,12 @@ HRESULT CDECL wined3d_device_clear(struct wined3d_device *device, DWORD rect_cou
     TRACE("device %p, rect_count %u, rects %p, flags %#x, color {%.8e, %.8e, %.8e, %.8e}, depth %.8e, stencil %u.\n",
             device, rect_count, rects, flags, color->r, color->g, color->b, color->a, depth, stencil);
 
+    if (!rect_count && rects)
+    {
+        WARN("Rects is %p, but rect_count is 0, ignoring clear\n", rects);
+        return WINED3D_OK;
+    }
+
     if (flags & (WINED3DCLEAR_ZBUFFER | WINED3DCLEAR_STENCIL))
     {
         struct wined3d_surface *ds = device->fb.depth_stencil;
-- 
1.7.12.4




More information about the wine-patches mailing list