[PATCH] wined3d: Restore the Topmost state upon exiting fullscreen, when used from DXGI.

Rémi Bernon rbernon at codeweavers.com
Thu Jul 2 08:14:18 CDT 2020


On 2020-07-02 14:41, Gabriel Ivăncescu wrote:
> DXGI, unlike D3D9 and below, restores the topmost state when exiting
> fullscreen. Unreal Engine 4 games (e.g. Deep Rock Galactic) depend on this
> because they don't unset it manually, so the window remains topmost on Wine.
> 
> Signed-off-by: Gabriel Ivăncescu <gabrielopcode at gmail.com>
> ---
> 
> In fact, we already have tests for this in DXGI, but they've been marked
> todo_wine, which this patch fixes.
> 
>   dlls/dxgi/swapchain.c    | 2 ++
>   dlls/dxgi/tests/dxgi.c   | 2 --
>   dlls/wined3d/swapchain.c | 8 +++++++-
>   include/wine/wined3d.h   | 1 +
>   4 files changed, 10 insertions(+), 3 deletions(-)
> 
> diff --git a/dlls/dxgi/swapchain.c b/dlls/dxgi/swapchain.c
> index f37aee9..2895e0e 100644
> --- a/dlls/dxgi/swapchain.c
> +++ b/dlls/dxgi/swapchain.c
> @@ -416,6 +416,7 @@ static HRESULT STDMETHODCALLTYPE DECLSPEC_HOTPATCH d3d11_swapchain_SetFullscreen
>       wined3d_swapchain_get_desc(swapchain->wined3d_swapchain, &swapchain_desc);
>       swapchain_desc.output = dxgi_output->wined3d_output;
>       swapchain_desc.windowed = !fullscreen;
> +    swapchain_desc.flags |= WINED3D_SWAPCHAIN_TOPMOST_RESTORE;
>       hr = wined3d_swapchain_state_set_fullscreen(state, &swapchain_desc, NULL);
>       wined3d_mutex_unlock();
>       if (FAILED(hr))
> @@ -2243,6 +2244,7 @@ static HRESULT STDMETHODCALLTYPE DECLSPEC_HOTPATCH d3d12_swapchain_SetFullscreen
>           goto fail;
>       wined3d_mutex_lock();
>       wined3d_desc.windowed = !fullscreen;
> +    wined3d_desc.flags |= WINED3D_SWAPCHAIN_TOPMOST_RESTORE;
>       hr = wined3d_swapchain_state_set_fullscreen(swapchain->state, &wined3d_desc, NULL);
>       wined3d_mutex_unlock();
>       if (FAILED(hr))
> diff --git a/dlls/dxgi/tests/dxgi.c b/dlls/dxgi/tests/dxgi.c
> index 8f52e1d..8d243e2 100644
> --- a/dlls/dxgi/tests/dxgi.c
> +++ b/dlls/dxgi/tests/dxgi.c
> @@ -5859,7 +5859,6 @@ static void test_swapchain_window_styles(void)
>           todo_wine_if(!(tests[i].expected_style & WS_VISIBLE))
>           ok(style == tests[i].expected_style, "Test %u: Got style %#x, expected %#x.\n",
>                   i, style, tests[i].expected_style);
> -        todo_wine_if(!(tests[i].expected_exstyle & WS_EX_TOPMOST))
>           ok(exstyle == tests[i].expected_exstyle, "Test %u: Got exstyle %#x, expected %#x.\n",
>                   i, exstyle, tests[i].expected_exstyle);
>   
> @@ -5871,7 +5870,6 @@ static void test_swapchain_window_styles(void)
>           todo_wine_if(!(tests[i].expected_style & WS_VISIBLE))
>           ok(style == tests[i].expected_style, "Test %u: Got style %#x, expected %#x.\n",
>                   i, style, tests[i].expected_style);
> -        todo_wine_if(!(tests[i].expected_exstyle & WS_EX_TOPMOST))
>           ok(exstyle == tests[i].expected_exstyle, "Test %u: Got exstyle %#x, expected %#x.\n",
>                   i, exstyle, tests[i].expected_exstyle);
>   
> diff --git a/dlls/wined3d/swapchain.c b/dlls/wined3d/swapchain.c
> index e9d6272..84aba06 100644
> --- a/dlls/wined3d/swapchain.c
> +++ b/dlls/wined3d/swapchain.c
> @@ -2114,6 +2114,10 @@ void wined3d_swapchain_state_restore_from_fullscreen(struct wined3d_swapchain_st
>       if (!state->style && !state->exstyle)
>           return;
>   
> +    /* DXGI restores WS_EX_TOPMOST, unlike Direct3D 9 and below */
> +    if ((state->desc.flags & WINED3D_SWAPCHAIN_TOPMOST_RESTORE) && !(state->exstyle & WS_EX_TOPMOST))
> +        window_pos_flags &= ~SWP_NOZORDER;
> +
>       style = GetWindowLongW(window, GWL_STYLE);
>       exstyle = GetWindowLongW(window, GWL_EXSTYLE);
>   
> @@ -2145,7 +2149,7 @@ void wined3d_swapchain_state_restore_from_fullscreen(struct wined3d_swapchain_st
>           rect = *window_rect;
>       else
>           window_pos_flags |= (SWP_NOMOVE | SWP_NOSIZE);
> -    SetWindowPos(window, 0, rect.left, rect.top,
> +    SetWindowPos(window, HWND_NOTOPMOST, rect.left, rect.top,
>               rect.right - rect.left, rect.bottom - rect.top, window_pos_flags);
>   
>       wined3d_filter_messages(window, filter);
> @@ -2243,6 +2247,8 @@ HRESULT CDECL wined3d_swapchain_state_set_fullscreen(struct wined3d_swapchain_st
>           RECT *window_rect = NULL;
>           if (state->desc.flags & WINED3D_SWAPCHAIN_RESTORE_WINDOW_RECT)
>               window_rect = &state->original_window_rect;
> +        if (swapchain_desc->flags & WINED3D_SWAPCHAIN_TOPMOST_RESTORE)
> +            state->desc.flags |= WINED3D_SWAPCHAIN_TOPMOST_RESTORE;
>           wined3d_swapchain_state_restore_from_fullscreen(state, state->device_window, window_rect);
>       }
>   
> diff --git a/include/wine/wined3d.h b/include/wine/wined3d.h
> index 346d1d0..cee46d3 100644
> --- a/include/wine/wined3d.h
> +++ b/include/wine/wined3d.h
> @@ -905,6 +905,7 @@ enum wined3d_shader_type
>   #define WINED3D_SWAPCHAIN_GDI_COMPATIBLE                        0x00008000u
>   #define WINED3D_SWAPCHAIN_IMPLICIT                              0x00010000u
>   #define WINED3D_SWAPCHAIN_HOOK                                  0x00020000u
> +#define WINED3D_SWAPCHAIN_TOPMOST_RESTORE                       0x00040000u
>   
>   #define WINED3DDP_MAXTEXCOORD                                   8
>   
> 

Hi,

I investigated this logic a while ago, and I believe it's a little bit 
more convoluted. I think there's, for instance, some interaction with 
the WINED3DCREATE_NOWINDOWCHANGES flag, but the behavior also varies 
between ddraw, d3d <= 9, d3d >= 9ex and dxgi.

AFAICS there's also the same kind of change / restore logic with window 
visibility, and of course window styles -- which wined3d incorrectly 
modifies.

I have some patches with some more tests showing that, but it was based 
on some other changes to remove the window styles updates, that I sent a 
while ago but didn't try sending again since then.

I'm attaching my whole series if you want to have a look, potentially 
the additional tests can be interesting. Feel free to take over it too.
-- 
Rémi Bernon <rbernon at codeweavers.com>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: wined3d-window-updates.patch
Type: text/x-patch
Size: 97970 bytes
Desc: not available
URL: <http://www.winehq.org/pipermail/wine-devel/attachments/20200702/f113f036/attachment-0001.bin>


More information about the wine-devel mailing list