[4/12] WineD3D: More Clear fixes

Stefan Dösinger stefan at codeweavers.com
Mon Feb 26 06:42:25 CST 2007


Test for rectangles with x1 > x2 and y1 > y2. Empire earth passes such rects
-------------- next part --------------
From 1a4bdf58a38b4576b76ef1a66572fc439e054b78 Mon Sep 17 00:00:00 2001
From: Stefan Doesinger <stefan at codeweavers.com>
Date: Sat, 24 Feb 2007 22:58:03 +0100
Subject: [PATCH] WineD3D: More Clear fixes

This patch adds a test for the behavior of clear when the x2 or y2 coordinate of the rectangle is left /
above the x1 resp y1 coord(It turned out that the rectangle is ignored silently). Handling the rectangle is
changed a bit: The check for a rectangle is moved out of the for loop, and instead of the (broken) pointer
arithmetic array indices are used.
---
 dlls/d3d8/tests/visual.c  |   49 +++++++++++++++++++++++++++++++++++++++++++++
 dlls/d3d9/tests/visual.c  |   49 +++++++++++++++++++++++++++++++++++++++++++++
 dlls/ddraw/tests/visual.c |   47 +++++++++++++++++++++++++++++++++++++++++++
 dlls/wined3d/device.c     |   49 ++++++++++++++++++++++++++------------------
 4 files changed, 174 insertions(+), 20 deletions(-)

diff --git a/dlls/d3d8/tests/visual.c b/dlls/d3d8/tests/visual.c
index 0f09012..9915fa9 100644
--- a/dlls/d3d8/tests/visual.c
+++ b/dlls/d3d8/tests/visual.c
@@ -259,6 +259,54 @@ static void lighting_test(IDirect3DDevice8 *device)
     ok(hr == D3D_OK, "IDirect3DDevice8_SetRenderState returned %s\n", DXGetErrorString8(hr));
 }
 
+static void clear_test(IDirect3DDevice8 *device)
+{
+    /* Tests the correctness of clearing parameters */
+    HRESULT hr;
+    D3DRECT rect[2];
+    D3DRECT rect_negneg;
+    DWORD color;
+
+    hr = IDirect3DDevice8_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
+    ok(hr == D3D_OK, "IDirect3DDevice8_Clear failed with %s\n", DXGetErrorString8(hr));
+
+    /* Positive x, negative y */
+    rect[0].x1 = 0;
+    rect[0].y1 = 480;
+    rect[0].x2 = 320;
+    rect[0].y2 = 240;
+
+    /* Positive x, positive y */
+    rect[1].x1 = 0;
+    rect[1].y1 = 0;
+    rect[1].x2 = 320;
+    rect[1].y2 = 240;
+    /* Clear 2 rectangles with one call. Shows that a positive value is returned, but the negative rectangle
+     * is ignored, the positive is still cleared afterwards
+     */
+    hr = IDirect3DDevice8_Clear(device, 2, rect, D3DCLEAR_TARGET, 0xffff0000, 0.0, 0);
+    ok(hr == D3D_OK, "IDirect3DDevice8_Clear failed with %s\n", DXGetErrorString8(hr));
+
+    /* negative x, negative y */
+    rect_negneg.x1 = 640;
+    rect_negneg.x1 = 240;
+    rect_negneg.x2 = 320;
+    rect_negneg.y2 = 0;
+    hr = IDirect3DDevice8_Clear(device, 1, &rect_negneg, D3DCLEAR_TARGET, 0xff00ff00, 0.0, 0);
+    ok(hr == D3D_OK, "IDirect3DDevice8_Clear failed with %s\n", DXGetErrorString8(hr));
+
+    IDirect3DDevice8_Present(device, NULL, NULL, NULL, NULL);
+
+    color = getPixelColor(device, 160, 360); /* lower left quad */
+    ok(color == 0x00ffffff, "Clear rectangle 3(pos, neg) has color %08x\n", color);
+    color = getPixelColor(device, 160, 120); /* upper left quad */
+    ok(color == 0x00ff0000, "Clear rectangle 1(pos, pos) has color %08x\n", color);
+    color = getPixelColor(device, 480, 360); /* lower right quad  */
+    ok(color == 0x00ffffff, "Clear rectangle 4(NULL) has color %08x\n", color);
+    color = getPixelColor(device, 480, 120); /* upper right quad */
+    ok(color == 0x00ffffff, "Clear rectangle 4(neg, neg) has color %08x\n", color);
+}
+
 START_TEST(visual)
 {
     IDirect3DDevice8 *device_ptr;
@@ -308,6 +356,7 @@ START_TEST(visual)
 
     /* Now run the real test */
     lighting_test(device_ptr);
+    clear_test(device_ptr);
 
 cleanup:
     if(device_ptr) IDirect3DDevice8_Release(device_ptr);
diff --git a/dlls/d3d9/tests/visual.c b/dlls/d3d9/tests/visual.c
index f5c15a0..b586c22 100644
--- a/dlls/d3d9/tests/visual.c
+++ b/dlls/d3d9/tests/visual.c
@@ -266,6 +266,54 @@ static void lighting_test(IDirect3DDevice9 *device)
     IDirect3DDevice9_SetVertexDeclaration(device, NULL);
 }
 
+static void clear_test(IDirect3DDevice9 *device)
+{
+    /* Tests the correctness of clearing parameters */
+    HRESULT hr;
+    D3DRECT rect[2];
+    D3DRECT rect_negneg;
+    DWORD color;
+
+    hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
+    ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %s\n", DXGetErrorString9(hr));
+
+    /* Positive x, negative y */
+    rect[0].x1 = 0;
+    rect[0].y1 = 480;
+    rect[0].x2 = 320;
+    rect[0].y2 = 240;
+
+    /* Positive x, positive y */
+    rect[1].x1 = 0;
+    rect[1].y1 = 0;
+    rect[1].x2 = 320;
+    rect[1].y2 = 240;
+    /* Clear 2 rectangles with one call. Shows that a positive value is returned, but the negative rectangle
+     * is ignored, the positive is still cleared afterwards
+     */
+    hr = IDirect3DDevice9_Clear(device, 2, rect, D3DCLEAR_TARGET, 0xffff0000, 0.0, 0);
+    ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %s\n", DXGetErrorString9(hr));
+
+    /* negative x, negative y */
+    rect_negneg.x1 = 640;
+    rect_negneg.x1 = 240;
+    rect_negneg.x2 = 320;
+    rect_negneg.y2 = 0;
+    hr = IDirect3DDevice9_Clear(device, 1, &rect_negneg, D3DCLEAR_TARGET, 0xff00ff00, 0.0, 0);
+    ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %s\n", DXGetErrorString9(hr));
+
+    IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
+
+    color = getPixelColor(device, 160, 360); /* lower left quad */
+    ok(color == 0x00ffffff, "Clear rectangle 3(pos, neg) has color %08x\n", color);
+    color = getPixelColor(device, 160, 120); /* upper left quad */
+    ok(color == 0x00ff0000, "Clear rectangle 1(pos, pos) has color %08x\n", color);
+    color = getPixelColor(device, 480, 360); /* lower right quad  */
+    ok(color == 0x00ffffff, "Clear rectangle 4(NULL) has color %08x\n", color);
+    color = getPixelColor(device, 480, 120); /* upper right quad */
+    ok(color == 0x00ffffff, "Clear rectangle 4(neg, neg) has color %08x\n", color);
+}
+
 START_TEST(visual)
 {
     IDirect3DDevice9 *device_ptr;
@@ -315,6 +363,7 @@ START_TEST(visual)
 
     /* Now execute the real tests */
     lighting_test(device_ptr);
+    clear_test(device_ptr);
 
 cleanup:
     if(device_ptr) IDirect3DDevice9_Release(device_ptr);
diff --git a/dlls/ddraw/tests/visual.c b/dlls/ddraw/tests/visual.c
index c2c2ed3..3f23b61 100644
--- a/dlls/ddraw/tests/visual.c
+++ b/dlls/ddraw/tests/visual.c
@@ -301,6 +301,52 @@ static void lighting_test(IDirect3DDevice7 *device)
     ok(hr == D3D_OK, "IDirect3DDevice7_SetRenderState returned %08x\n", hr);
 }
 
+static void clear_test(IDirect3DDevice7 *device)
+{
+    /* Tests the correctness of clearing parameters */
+    HRESULT hr;
+    D3DRECT rect[2];
+    D3DRECT rect_negneg;
+    DWORD color;
+
+    hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
+    ok(hr == D3D_OK, "IDirect3DDevice7_Clear failed with %08x\n", hr);
+
+    /* Positive x, negative y */
+    rect[0].x1 = 0;
+    rect[0].y1 = 480;
+    rect[0].x2 = 320;
+    rect[0].y2 = 240;
+
+    /* Positive x, positive y */
+    rect[1].x1 = 0;
+    rect[1].y1 = 0;
+    rect[1].x2 = 320;
+    rect[1].y2 = 240;
+    /* Clear 2 rectangles with one call. Shows that a positive value is returned, but the negative rectangle
+     * is ignored, the positive is still cleared afterwards
+     */
+    hr = IDirect3DDevice7_Clear(device, 2, rect, D3DCLEAR_TARGET, 0xffff0000, 0.0, 0);
+    ok(hr == D3D_OK, "IDirect3DDevice7_Clear failed with %08x\n", hr);
+
+    /* negative x, negative y */
+    rect_negneg.x1 = 640;
+    rect_negneg.x1 = 240;
+    rect_negneg.x2 = 320;
+    rect_negneg.y2 = 0;
+    hr = IDirect3DDevice7_Clear(device, 1, &rect_negneg, D3DCLEAR_TARGET, 0xff00ff00, 0.0, 0);
+    ok(hr == D3D_OK, "IDirect3DDevice7_Clear failed with %08x\n", hr);
+
+    color = getPixelColor(device, 160, 360); /* lower left quad */
+    ok(color == 0x00ffffff, "Clear rectangle 3(pos, neg) has color %08x\n", color);
+    color = getPixelColor(device, 160, 120); /* upper left quad */
+    ok(color == 0x00ff0000, "Clear rectangle 1(pos, pos) has color %08x\n", color);
+    color = getPixelColor(device, 480, 360); /* lower right quad  */
+    ok(color == 0x00ffffff, "Clear rectangle 4(NULL) has color %08x\n", color);
+    color = getPixelColor(device, 480, 120); /* upper right quad */
+    ok(color == 0x00ffffff, "Clear rectangle 4(neg, neg) has color %08x\n", color);
+}
+
 START_TEST(visual)
 {
     HRESULT hr;
@@ -342,6 +388,7 @@ START_TEST(visual)
 
     /* Now run the tests */
     lighting_test(Direct3DDevice);
+    clear_test(Direct3DDevice);
 
 cleanup:
     releaseObjects();
diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c
index 119a929..dbd2071 100644
--- a/dlls/wined3d/device.c
+++ b/dlls/wined3d/device.c
@@ -4242,26 +4242,34 @@ static HRESULT WINAPI IWineD3DDeviceImpl_Clear(IWineD3DDevice *iface, DWORD Coun
         glMask = glMask | GL_COLOR_BUFFER_BIT;
     }
 
-    /* Now process each rect in turn */
-    for (i = 0; i < Count || i == 0; i++) {
-
-        if (curRect) {
+    if (!curRect) {
+        glClear(glMask);
+        checkGLcall("glClear");
+    } else {
+        /* Now process each rect in turn */
+        for (i = 0; i < Count; i++) {
             /* Note gl uses lower left, width/height */
             TRACE("(%p) %p Rect=(%d,%d)->(%d,%d) glRect=(%d,%d), len=%d, hei=%d\n", This, curRect,
-                  curRect->x1, curRect->y1, curRect->x2, curRect->y2,
-                  curRect->x1, (((IWineD3DSurfaceImpl *)This->render_targets[0])->currentDesc.Height - curRect->y2),
-                  curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
-            glScissor(curRect->x1, (((IWineD3DSurfaceImpl *)This->render_targets[0])->currentDesc.Height - curRect->y2),
-                      curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
-            checkGLcall("glScissor");
-        }
+                  curRect[i].x1, curRect[i].y1, curRect[i].x2, curRect[i].y2,
+                  curRect[i].x1, (((IWineD3DSurfaceImpl *)This->render_targets[0])->currentDesc.Height - curRect[i].y2),
+                  curRect[i].x2 - curRect[i].x1, curRect[i].y2 - curRect[i].y1);
 
-        /* Clear the selected rectangle (or full screen) */
-        glClear(glMask);
-        checkGLcall("glClear");
+            /* Tests show that rectangles where x1 > x2 or y1 > y2 are ignored silently.
+             * The rectangle is not cleared, no error is returned, but further rectanlges are
+             * still cleared if they are valid
+             */
+            if(curRect[i].x1 > curRect[i].x2 || curRect[i].y1 > curRect[i].y2) {
+                TRACE("Rectangle with negative dimensions, ignoring\n");
+                continue;
+            }
 
-        /* Step to the next rectangle */
-        if (curRect) curRect = curRect + sizeof(WINED3DRECT);
+            glScissor(curRect[i].x1, ((IWineD3DSurfaceImpl *)This->render_targets[0])->currentDesc.Height - curRect[i].y2,
+                        curRect[i].x2 - curRect[i].x1, curRect[i].y2 - curRect[i].y1);
+            checkGLcall("glScissor");
+
+            glClear(glMask);
+            checkGLcall("glClear");
+        }
     }
 
     /* Restore the old values (why..?) */
@@ -4269,10 +4277,11 @@ static HRESULT WINAPI IWineD3DDeviceImpl_Clear(IWineD3DDevice *iface, DWORD Coun
         glStencilMask(This->stateBlock->renderState[WINED3DRS_STENCILWRITEMASK]);
     }
     if (Flags & WINED3DCLEAR_TARGET) {
-        glColorMask(This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & WINED3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
-                    This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & WINED3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
-                    This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & WINED3DCOLORWRITEENABLE_BLUE  ? GL_TRUE : GL_FALSE,
-                    This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & WINED3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
+        DWORD mask = This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE];
+        glColorMask(mask & WINED3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
+                    mask & WINED3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
+                    mask & WINED3DCOLORWRITEENABLE_BLUE  ? GL_TRUE : GL_FALSE,
+                    mask & WINED3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
     }
 
     LEAVE_GL();
-- 
1.4.4.3



More information about the wine-patches mailing list