On Thu, 2008-02-14 at 09:18 +0100, Stefan Dösinger wrote: > Am Donnerstag, 14. Februar 2008 04:22:16 schrieb Peter Dons Tychsen: > > Why does the SwapChain-destroy function play around with the resolution > > at all. Is that really necessary? I think it should not do it if the > > caller is ddraw at least. > I thought I'm filtering this out in the case of ddraw, but maybe that got > lost. The reason why the swapchain restores the resolution is the different > way ddraw/d3d8 and d3d8/d3d9 set up the screen. > > In ddraw the app calls IDirectDraw7::SetDisplayMode. This sets the mode. Then > it creates a DDSCAPS_PRIMARYSURFACE surface, which creates the swapchain. > > In d3d8/d3d9 the swapchain controls the video mode > > I think the problem is that RestoreDisplayMode is called before the primary > surface is destroyed. The question is why this happens. I can think of the > following reasons: > > -> Refcounting problem, or the app just doesn't release the surfaces. Then > ddraw.dll destroys the objects on DLL_PROCESS_DETACH > > -> The app calls it that way. This needs a test, but I think it is not > allowed > to call SetDisplayMode / RestoreDisplayMode while a primary surface is around
OK, i have now eaten enough wine-gums to comprehend this.... I think there is a general problem in swapchain->release. The swapchain should only change the resolution back to the original *if* the current resolution is still the same as the swapchain enforced. If someone else has intervened, it should let it be. This fixes the problem at hand, but would also fix other silly problems. Some could for example have called Release() while the "window" is not even visible (tabbed to desktop for example). Please review my patch and let med know if it is submittable. If you hate it, i will eat more wine-gums. :-) /pedro
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);