[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