[PATCH 1/4] ddraw: Restore resolution on EXCLUSIVE->NORMAL switch

Stefan Dösinger stefan at codeweavers.com
Tue May 21 06:18:18 CDT 2013


This fixes a 3DMark2000 regression caused by 7c90c1a0. The change
introduced by 7c90c1a0 was correct for IDirectDraw, but newer interfaces
restore the screen resolution.

The new code does not deliver the resolution change messages to the
correct window, see the todo_wine markers in the next patch. Getting
this right isn't simply a matter of passing the correct window to
wined3d_device_restore_fullscreen_window because the delivery of the
correct messages in the new window == old window case is mostly a lucky
side effect of the window style hacks. Those hacks fail if we pass a
different window, because the style of the new window is different from
what wined3d expects, so it doesn't send any messages.
---
 dlls/ddraw/ddraw.c         | 247 +++++++++++++++++++++++++--------------------
 dlls/ddraw/ddraw_private.h |   1 +
 2 files changed, 136 insertions(+), 112 deletions(-)

diff --git a/dlls/ddraw/ddraw.c b/dlls/ddraw/ddraw.c
index b2b637e..a64ca26 100644
--- a/dlls/ddraw/ddraw.c
+++ b/dlls/ddraw/ddraw.c
@@ -4,6 +4,7 @@
  * Copyright 2000-2001 TransGaming Technologies Inc.
  * Copyright 2006 Stefan Dösinger
  * Copyright 2008 Denver Gingerich
+ * Copyright 2007-2008, 2011, 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
@@ -653,6 +654,75 @@ static HRESULT ddraw_create_swapchain(struct ddraw *ddraw, HWND window, BOOL win
 }
 
 /*****************************************************************************
+ * IDirectDraw7::RestoreDisplayMode
+ *
+ * Restores the display mode to what it was at creation time. Basically.
+ *
+ * Returns
+ *  DD_OK on success
+ *  DDERR_NOEXCLUSIVE mode if the device isn't in fullscreen mode
+ *
+ *****************************************************************************/
+static HRESULT WINAPI ddraw7_RestoreDisplayMode(IDirectDraw7 *iface)
+{
+    struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
+    HRESULT hr;
+
+    TRACE("iface %p.\n", iface);
+
+    wined3d_mutex_lock();
+
+    if (!ddraw->restore_mode)
+    {
+        wined3d_mutex_unlock();
+        return DD_OK;
+    }
+
+    if (exclusive_ddraw && exclusive_ddraw != ddraw)
+    {
+        wined3d_mutex_unlock();
+        return DDERR_NOEXCLUSIVEMODE;
+    }
+
+    if (SUCCEEDED(hr = wined3d_set_adapter_display_mode(ddraw->wined3d, WINED3DADAPTER_DEFAULT, &original_mode)))
+    {
+        ddraw->restore_mode = FALSE;
+        restore_mode = FALSE;
+    }
+
+    wined3d_mutex_unlock();
+
+    return hr;
+}
+
+static HRESULT WINAPI ddraw4_RestoreDisplayMode(IDirectDraw4 *iface)
+{
+    struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
+
+    TRACE("iface %p.\n", iface);
+
+    return ddraw7_RestoreDisplayMode(&ddraw->IDirectDraw7_iface);
+}
+
+static HRESULT WINAPI ddraw2_RestoreDisplayMode(IDirectDraw2 *iface)
+{
+    struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
+
+    TRACE("iface %p.\n", iface);
+
+    return ddraw7_RestoreDisplayMode(&ddraw->IDirectDraw7_iface);
+}
+
+static HRESULT WINAPI ddraw1_RestoreDisplayMode(IDirectDraw *iface)
+{
+    struct ddraw *ddraw = impl_from_IDirectDraw(iface);
+
+    TRACE("iface %p.\n", iface);
+
+    return ddraw7_RestoreDisplayMode(&ddraw->IDirectDraw7_iface);
+}
+
+/*****************************************************************************
  * IDirectDraw7::SetCooperativeLevel
  *
  * Sets the cooperative level for the DirectDraw object, and the window
@@ -696,15 +766,16 @@ static HRESULT ddraw_create_swapchain(struct ddraw *ddraw, HWND window, BOOL win
  *   (Probably others too, have to investigate)
  *
  *****************************************************************************/
-static HRESULT WINAPI ddraw7_SetCooperativeLevel(IDirectDraw7 *iface, HWND window, DWORD cooplevel)
+static HRESULT WINAPI ddraw_set_cooperative_level(struct ddraw *ddraw, HWND window,
+        DWORD cooplevel, BOOL restore_mode)
 {
-    struct ddraw *This = impl_from_IDirectDraw7(iface);
     struct wined3d_surface *rt = NULL, *ds = NULL;
     struct wined3d_stateblock *stateblock;
     BOOL restore_state = FALSE;
     HRESULT hr;
 
-    TRACE("iface %p, window %p, flags %#x.\n", iface, window, cooplevel);
+    TRACE("ddraw %p, window %p, flags %#x, restore_mode %s.\n", ddraw, window, cooplevel,
+            restore_mode ? "true" : "false");
     DDRAW_dump_cooperativelevel(cooplevel);
 
     wined3d_mutex_lock();
@@ -745,7 +816,7 @@ static HRESULT WINAPI ddraw7_SetCooperativeLevel(IDirectDraw7 *iface, HWND windo
             return DDERR_INVALIDPARAMS;
         }
 
-        hr = ddraw_set_focus_window(This, window);
+        hr = ddraw_set_focus_window(ddraw, window);
         wined3d_mutex_unlock();
         return hr;
     }
@@ -763,7 +834,7 @@ static HRESULT WINAPI ddraw7_SetCooperativeLevel(IDirectDraw7 *iface, HWND windo
         {
             HWND device_window;
 
-            if (!This->focuswindow && !(cooplevel & DDSCL_SETFOCUSWINDOW))
+            if (!ddraw->focuswindow && !(cooplevel & DDSCL_SETFOCUSWINDOW))
             {
                 WARN("No focus window set.\n");
                 wined3d_mutex_unlock();
@@ -785,8 +856,8 @@ static HRESULT WINAPI ddraw7_SetCooperativeLevel(IDirectDraw7 *iface, HWND windo
 
             /* Native apparently leaks the created device window if setting the
              * focus window below fails. */
-            This->cooperative_level |= DDSCL_CREATEDEVICEWINDOW;
-            This->devicewindow = device_window;
+            ddraw->cooperative_level |= DDSCL_CREATEDEVICEWINDOW;
+            ddraw->devicewindow = device_window;
 
             if (cooplevel & DDSCL_SETFOCUSWINDOW)
             {
@@ -796,7 +867,7 @@ static HRESULT WINAPI ddraw7_SetCooperativeLevel(IDirectDraw7 *iface, HWND windo
                     return DDERR_NOHWND;
                 }
 
-                if (FAILED(hr = ddraw_set_focus_window(This, window)))
+                if (FAILED(hr = ddraw_set_focus_window(ddraw, window)))
                 {
                     wined3d_mutex_unlock();
                     return hr;
@@ -808,35 +879,42 @@ static HRESULT WINAPI ddraw7_SetCooperativeLevel(IDirectDraw7 *iface, HWND windo
     }
     else
     {
-        if (This->cooperative_level & DDSCL_CREATEDEVICEWINDOW)
-            DestroyWindow(This->devicewindow);
-        This->devicewindow = NULL;
-        This->focuswindow = NULL;
+        if (ddraw->cooperative_level & DDSCL_CREATEDEVICEWINDOW)
+            DestroyWindow(ddraw->devicewindow);
+        ddraw->devicewindow = NULL;
+        ddraw->focuswindow = NULL;
+
+        if ((ddraw->cooperative_level & DDSCL_EXCLUSIVE) && restore_mode)
+        {
+            hr = ddraw7_RestoreDisplayMode(&ddraw->IDirectDraw7_iface);
+            if (FAILED(hr))
+                ERR("RestoreDisplayMode failed\n");
+        }
     }
 
-    if ((This->cooperative_level & DDSCL_EXCLUSIVE)
-            && (window != This->dest_window || !(cooplevel & DDSCL_EXCLUSIVE)))
-        wined3d_device_release_focus_window(This->wined3d_device);
+    if ((ddraw->cooperative_level & DDSCL_EXCLUSIVE)
+            && (window != ddraw->dest_window || !(cooplevel & DDSCL_EXCLUSIVE)))
+        wined3d_device_release_focus_window(ddraw->wined3d_device);
 
-    if ((cooplevel & DDSCL_FULLSCREEN) != (This->cooperative_level & DDSCL_FULLSCREEN) || window != This->dest_window)
+    if ((cooplevel & DDSCL_FULLSCREEN) != (ddraw->cooperative_level & DDSCL_FULLSCREEN) || window != ddraw->dest_window)
     {
-        if (This->cooperative_level & DDSCL_FULLSCREEN)
-            wined3d_device_restore_fullscreen_window(This->wined3d_device, This->dest_window);
+        if (ddraw->cooperative_level & DDSCL_FULLSCREEN)
+            wined3d_device_restore_fullscreen_window(ddraw->wined3d_device, ddraw->dest_window);
 
         if (cooplevel & DDSCL_FULLSCREEN)
         {
             struct wined3d_display_mode display_mode;
 
-            wined3d_get_adapter_display_mode(This->wined3d, WINED3DADAPTER_DEFAULT, &display_mode, NULL);
-            wined3d_device_setup_fullscreen_window(This->wined3d_device, window,
+            wined3d_get_adapter_display_mode(ddraw->wined3d, WINED3DADAPTER_DEFAULT, &display_mode, NULL);
+            wined3d_device_setup_fullscreen_window(ddraw->wined3d_device, window,
                     display_mode.width, display_mode.height);
         }
     }
 
     if ((cooplevel & DDSCL_EXCLUSIVE)
-            && (window != This->dest_window || !(This->cooperative_level & DDSCL_EXCLUSIVE)))
+            && (window != ddraw->dest_window || !(ddraw->cooperative_level & DDSCL_EXCLUSIVE)))
     {
-        hr = wined3d_device_acquire_focus_window(This->wined3d_device, window);
+        hr = wined3d_device_acquire_focus_window(ddraw->wined3d_device, window);
         if (FAILED(hr))
         {
             ERR("Failed to acquire focus window, hr %#x.\n", hr);
@@ -845,16 +923,16 @@ static HRESULT WINAPI ddraw7_SetCooperativeLevel(IDirectDraw7 *iface, HWND windo
         }
     }
 
-    if (cooplevel & DDSCL_MULTITHREADED && !(This->cooperative_level & DDSCL_MULTITHREADED))
-        wined3d_device_set_multithreaded(This->wined3d_device);
+    if (cooplevel & DDSCL_MULTITHREADED && !(ddraw->cooperative_level & DDSCL_MULTITHREADED))
+        wined3d_device_set_multithreaded(ddraw->wined3d_device);
 
-    if (This->wined3d_swapchain)
+    if (ddraw->wined3d_swapchain)
     {
         if (DefaultSurfaceType != DDRAW_SURFACE_TYPE_GDI)
         {
             restore_state = TRUE;
 
-            if (FAILED(hr = wined3d_stateblock_create(This->wined3d_device, WINED3D_SBT_ALL, &stateblock)))
+            if (FAILED(hr = wined3d_stateblock_create(ddraw->wined3d_device, WINED3D_SBT_ALL, &stateblock)))
             {
                 ERR("Failed to create stateblock, hr %#x.\n", hr);
                 wined3d_mutex_unlock();
@@ -862,33 +940,33 @@ static HRESULT WINAPI ddraw7_SetCooperativeLevel(IDirectDraw7 *iface, HWND windo
             }
 
             wined3d_stateblock_capture(stateblock);
-            rt = wined3d_device_get_render_target(This->wined3d_device, 0);
-            if (rt == This->wined3d_frontbuffer)
+            rt = wined3d_device_get_render_target(ddraw->wined3d_device, 0);
+            if (rt == ddraw->wined3d_frontbuffer)
                 rt = NULL;
             else if (rt)
                 wined3d_surface_incref(rt);
 
-            if ((ds = wined3d_device_get_depth_stencil(This->wined3d_device)))
+            if ((ds = wined3d_device_get_depth_stencil(ddraw->wined3d_device)))
                 wined3d_surface_incref(ds);
         }
 
-        ddraw_destroy_swapchain(This);
+        ddraw_destroy_swapchain(ddraw);
     }
 
-    if (FAILED(hr = ddraw_create_swapchain(This, window, !(cooplevel & DDSCL_FULLSCREEN))))
+    if (FAILED(hr = ddraw_create_swapchain(ddraw, window, !(cooplevel & DDSCL_FULLSCREEN))))
         ERR("Failed to create swapchain, hr %#x.\n", hr);
 
     if (restore_state)
     {
         if (ds)
         {
-            wined3d_device_set_depth_stencil(This->wined3d_device, ds);
+            wined3d_device_set_depth_stencil(ddraw->wined3d_device, ds);
             wined3d_surface_decref(ds);
         }
 
         if (rt)
         {
-            wined3d_device_set_render_target(This->wined3d_device, 0, rt, FALSE);
+            wined3d_device_set_render_target(ddraw->wined3d_device, 0, rt, FALSE);
             wined3d_surface_decref(rt);
         }
 
@@ -898,33 +976,43 @@ static HRESULT WINAPI ddraw7_SetCooperativeLevel(IDirectDraw7 *iface, HWND windo
 
     /* Unhandled flags */
     if(cooplevel & DDSCL_ALLOWREBOOT)
-        WARN("(%p) Unhandled flag DDSCL_ALLOWREBOOT, harmless\n", This);
+        WARN("(%p) Unhandled flag DDSCL_ALLOWREBOOT, harmless\n", ddraw);
     if(cooplevel & DDSCL_ALLOWMODEX)
-        WARN("(%p) Unhandled flag DDSCL_ALLOWMODEX, harmless\n", This);
+        WARN("(%p) Unhandled flag DDSCL_ALLOWMODEX, harmless\n", ddraw);
     if(cooplevel & DDSCL_FPUSETUP)
-        WARN("(%p) Unhandled flag DDSCL_FPUSETUP, harmless\n", This);
+        WARN("(%p) Unhandled flag DDSCL_FPUSETUP, harmless\n", ddraw);
 
     if (cooplevel & DDSCL_EXCLUSIVE)
-        exclusive_ddraw = This;
-    else if (exclusive_ddraw == This)
+        exclusive_ddraw = ddraw;
+    else if (exclusive_ddraw == ddraw)
         exclusive_ddraw = NULL;
 
     /* Store the cooperative_level */
-    This->cooperative_level = cooplevel;
-    This->dest_window = window;
+    ddraw->cooperative_level = cooplevel;
+    ddraw->dest_window = window;
+
     TRACE("SetCooperativeLevel retuning DD_OK\n");
     wined3d_mutex_unlock();
 
     return DD_OK;
 }
 
+static HRESULT WINAPI ddraw7_SetCooperativeLevel(IDirectDraw7 *iface, HWND window, DWORD flags)
+{
+    struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
+
+    TRACE("iface %p, window %p, flags %#x.\n", iface, window, flags);
+
+    return ddraw_set_cooperative_level(ddraw, window, flags, !ddraw->setcooplevel_ddraw1);
+}
+
 static HRESULT WINAPI ddraw4_SetCooperativeLevel(IDirectDraw4 *iface, HWND window, DWORD flags)
 {
     struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
 
     TRACE("iface %p, window %p, flags %#x.\n", iface, window, flags);
 
-    return ddraw7_SetCooperativeLevel(&ddraw->IDirectDraw7_iface, window, flags);
+    return ddraw_set_cooperative_level(ddraw, window, flags, !ddraw->setcooplevel_ddraw1);
 }
 
 static HRESULT WINAPI ddraw2_SetCooperativeLevel(IDirectDraw2 *iface, HWND window, DWORD flags)
@@ -933,16 +1021,20 @@ static HRESULT WINAPI ddraw2_SetCooperativeLevel(IDirectDraw2 *iface, HWND windo
 
     TRACE("iface %p, window %p, flags %#x.\n", iface, window, flags);
 
-    return ddraw7_SetCooperativeLevel(&ddraw->IDirectDraw7_iface, window, flags);
+    return ddraw_set_cooperative_level(ddraw, window, flags, !ddraw->setcooplevel_ddraw1);
 }
 
 static HRESULT WINAPI ddraw1_SetCooperativeLevel(IDirectDraw *iface, HWND window, DWORD flags)
 {
     struct ddraw *ddraw = impl_from_IDirectDraw(iface);
+    HRESULT hr;
 
     TRACE("iface %p, window %p, flags %#x.\n", iface, window, flags);
 
-    return ddraw7_SetCooperativeLevel(&ddraw->IDirectDraw7_iface, window, flags);
+    hr = ddraw_set_cooperative_level(ddraw, window, flags, FALSE);
+    if (SUCCEEDED(hr))
+        ddraw->setcooplevel_ddraw1 = TRUE;
+    return hr;
 }
 
 /*****************************************************************************
@@ -1070,75 +1162,6 @@ static HRESULT WINAPI ddraw1_SetDisplayMode(IDirectDraw *iface, DWORD width, DWO
 }
 
 /*****************************************************************************
- * IDirectDraw7::RestoreDisplayMode
- *
- * Restores the display mode to what it was at creation time. Basically.
- *
- * Returns
- *  DD_OK on success
- *  DDERR_NOEXCLUSIVE mode if the device isn't in fullscreen mode
- *
- *****************************************************************************/
-static HRESULT WINAPI ddraw7_RestoreDisplayMode(IDirectDraw7 *iface)
-{
-    struct ddraw *ddraw = impl_from_IDirectDraw7(iface);
-    HRESULT hr;
-
-    TRACE("iface %p.\n", iface);
-
-    wined3d_mutex_lock();
-
-    if (!ddraw->restore_mode)
-    {
-        wined3d_mutex_unlock();
-        return DD_OK;
-    }
-
-    if (exclusive_ddraw && exclusive_ddraw != ddraw)
-    {
-        wined3d_mutex_unlock();
-        return DDERR_NOEXCLUSIVEMODE;
-    }
-
-    if (SUCCEEDED(hr = wined3d_set_adapter_display_mode(ddraw->wined3d, WINED3DADAPTER_DEFAULT, &original_mode)))
-    {
-        ddraw->restore_mode = FALSE;
-        restore_mode = FALSE;
-    }
-
-    wined3d_mutex_unlock();
-
-    return hr;
-}
-
-static HRESULT WINAPI ddraw4_RestoreDisplayMode(IDirectDraw4 *iface)
-{
-    struct ddraw *ddraw = impl_from_IDirectDraw4(iface);
-
-    TRACE("iface %p.\n", iface);
-
-    return ddraw7_RestoreDisplayMode(&ddraw->IDirectDraw7_iface);
-}
-
-static HRESULT WINAPI ddraw2_RestoreDisplayMode(IDirectDraw2 *iface)
-{
-    struct ddraw *ddraw = impl_from_IDirectDraw2(iface);
-
-    TRACE("iface %p.\n", iface);
-
-    return ddraw7_RestoreDisplayMode(&ddraw->IDirectDraw7_iface);
-}
-
-static HRESULT WINAPI ddraw1_RestoreDisplayMode(IDirectDraw *iface)
-{
-    struct ddraw *ddraw = impl_from_IDirectDraw(iface);
-
-    TRACE("iface %p.\n", iface);
-
-    return ddraw7_RestoreDisplayMode(&ddraw->IDirectDraw7_iface);
-}
-
-/*****************************************************************************
  * IDirectDraw7::GetCaps
  *
  * Returns the drives capabilities
diff --git a/dlls/ddraw/ddraw_private.h b/dlls/ddraw/ddraw_private.h
index 25985bd..1a20bfe 100644
--- a/dlls/ddraw/ddraw_private.h
+++ b/dlls/ddraw/ddraw_private.h
@@ -86,6 +86,7 @@ struct ddraw
 
     /* DirectDraw things, which are not handled by WineD3D */
     DWORD                   cooperative_level;
+    BOOL                    setcooplevel_ddraw1;
 
     /* D3D things */
     HWND                    d3d_window;
-- 
1.8.1.5




More information about the wine-patches mailing list