[PATCH] Fixed bug in wined3d swapchain, which caused the release of the swap-chain to mess around with the display-modes set by ddraw. Also added test-case for this scenario. Reworked test code minimally, to re-use existing test code.

Peter Dons Tychsen (none) donpedro at dhcppc4.
Sat Feb 16 07:53:47 CST 2008


Tested on winxp and Fedora 8.
---
 dlls/ddraw/tests/ddrawmodes.c |   44 +++++++++++++++++++++++++++++++++++++---
 dlls/wined3d/swapchain.c      |    8 ++++++-
 2 files changed, 47 insertions(+), 5 deletions(-)

diff --git a/dlls/ddraw/tests/ddrawmodes.c b/dlls/ddraw/tests/ddrawmodes.c
index 529c81a..71f62b0 100644
--- a/dlls/ddraw/tests/ddrawmodes.c
+++ b/dlls/ddraw/tests/ddrawmodes.c
@@ -179,14 +179,18 @@ static void setdisplaymode(int i)
                 ok(GetClipCursor(&r), "GetClipCursor() failed\n");
                 ok(EqualRect(&r, &virt), "Invalid clip rect: (%d %d) x (%d %d)\n",
                    r.left, r.top, r.right, r.bottom);
-
-                rc = IDirectDraw_RestoreDisplayMode(lpDD);
-                ok(DD_OK==rc,"RestoreDisplayMode returned: %x\n",rc);
             }
         }
     }
 }
 
+static void restoredisplaymode(void)
+{
+  HRESULT rc;
+  rc = IDirectDraw_RestoreDisplayMode(lpDD);
+  ok(DD_OK==rc,"RestoreDisplayMode returned: %x\n",rc);
+}
+
 static void createsurface(void)
 {
     DDSURFACEDESC ddsd;
@@ -249,14 +253,46 @@ static void testsurface(void)
 static void testdisplaymodes(void)
 {
     int i;
-
+    HRESULT rc;
+ 
     for (i = 0; i < modes_cnt; ++i)
     {
         setdisplaymode(i);
+        restoredisplaymode();
         createsurface();
         testsurface();
         destroysurface();
     }
+  
+    /* Try changing the resolution with an active 3D primary surface. 
+       Then destroy the surface. The resolution should not be touched.
+       We can only do this test if we have more than 1 display mode available */ 
+    if(modes_cnt > 1)
+    {
+        DDSURFACEDESC surfacedesc;
+        DDSURFACEDESC ddsd, ddsd2;
+        int cmp;
+        IDirectDrawSurface *surface = (IDirectDrawSurface *) 0xdeadbeef;
+        setdisplaymode(1);
+        memset(&ddsd, 0, sizeof(ddsd));
+        rc = IDirectDraw_GetDisplayMode(lpDD, &ddsd);
+        ok(rc==DD_OK, "IDirectDraw_GetDisplayMode returned: %x\n",rc);
+        setdisplaymode(0);
+        memset(&surfacedesc, 0, sizeof(surfacedesc));
+        surfacedesc.dwSize = sizeof(surfacedesc);
+        surfacedesc.dwFlags = DDSD_CAPS;
+        surfacedesc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_3DDEVICE;
+        rc = IDirectDraw_CreateSurface(lpDD, &surfacedesc, &surface, NULL);
+        ok(rc==DD_OK, "IDirectDraw_CreateSurface returned: %x\n",rc);
+        setdisplaymode(1); 
+        if(surface) IDirectDrawSurface_Release(surface);
+        memset(&ddsd2, 0, sizeof(ddsd2));
+        rc = IDirectDraw_GetDisplayMode(lpDD, &ddsd2);
+        ok(rc==DD_OK, "IDirectDraw_GetDisplayMode returned: %x\n",rc);
+        cmp = memcmp(&ddsd,&ddsd2,sizeof(DDSURFACEDESC));
+        ok(!cmp, "Display mode changed during surface creation/release\n");
+        restoredisplaymode();    
+    }
 }
 
 static void testcooperativelevels_normal(void)
diff --git a/dlls/wined3d/swapchain.c b/dlls/wined3d/swapchain.c
index 187c0c4..e000818 100644
--- a/dlls/wined3d/swapchain.c
+++ b/dlls/wined3d/swapchain.c
@@ -114,12 +114,18 @@ static void WINAPI IWineD3DSwapChainImpl_Destroy(IWineD3DSwapChain *iface, D3DCB
      * this will be the original desktop resolution. In case of d3d7 this will be a NOP because ddraw sets the resolution
      * before starting up Direct3D, thus orig_width and orig_height will be equal to the modes in the presentation params
      */
-    if(This->presentParms.Windowed == FALSE) {
+    if(This->presentParms.Windowed == FALSE){
+
+      /* Check if someone else changed the mode behind our backs.
+         It could for example be ddraw calling SetDisplayMode() */
+      IWineD3DSwapChain_GetDisplayMode(iface, &mode);
+      if((mode.Width == This->presentParms.BackBufferWidth) && (mode.Height == This->presentParms.BackBufferHeight)){
         mode.Width = This->orig_width;
         mode.Height = This->orig_height;
         mode.RefreshRate = 0;
         mode.Format = This->orig_fmt;
         IWineD3DDevice_SetDisplayMode((IWineD3DDevice *) This->wineD3DDevice, 0, &mode);
+      }
     }
     HeapFree(GetProcessHeap(), 0, This->context);
 
-- 
1.5.3.8


--=-cSR/C4Fvkyxl4b1I0xzl--




More information about the wine-patches mailing list