From 3b9c070ee0e3cb23c72116b97283529fbcd9b7ee Mon Sep 17 00:00:00 2001 From: Jules Blok Date: Sun, 4 Jan 2015 16:33:58 +0100 Subject: [PATCH 1/3] D3D: Only try to apply exclusive mode when the renderer is in focus. --- Source/Core/VideoBackends/D3D/D3DBase.cpp | 2 +- Source/Core/VideoBackends/D3D/Render.cpp | 36 ++++++++++------------- 2 files changed, 17 insertions(+), 21 deletions(-) diff --git a/Source/Core/VideoBackends/D3D/D3DBase.cpp b/Source/Core/VideoBackends/D3D/D3DBase.cpp index f7426da03a..982c5d2e6c 100644 --- a/Source/Core/VideoBackends/D3D/D3DBase.cpp +++ b/Source/Core/VideoBackends/D3D/D3DBase.cpp @@ -265,7 +265,7 @@ HRESULT Create(HWND wnd) swap_chain_desc.OutputWindow = wnd; swap_chain_desc.SampleDesc.Count = 1; swap_chain_desc.SampleDesc.Quality = 0; - swap_chain_desc.Windowed = !g_ActiveConfig.bFullscreen; + swap_chain_desc.Windowed = !g_Config.bFullscreen; DXGI_OUTPUT_DESC out_desc; memset(&out_desc, 0, sizeof(out_desc)); diff --git a/Source/Core/VideoBackends/D3D/Render.cpp b/Source/Core/VideoBackends/D3D/Render.cpp index 5644eae9fb..f24e86a5d2 100644 --- a/Source/Core/VideoBackends/D3D/Render.cpp +++ b/Source/Core/VideoBackends/D3D/Render.cpp @@ -41,13 +41,11 @@ namespace DX11 { static u32 s_last_multisample_mode = 0; +static bool s_last_stereo_mode = false; +static bool s_last_xfb_mode = false; static Television s_television; -static bool s_last_fullscreen_mode = false; -static bool s_last_stereo_mode = 0; -static bool s_last_xfb_mode = false; - ID3D11Buffer* access_efb_cbuf = nullptr; ID3D11BlendState* clearblendstates[4] = {nullptr}; ID3D11DepthStencilState* cleardepthstates[3] = {nullptr}; @@ -230,7 +228,6 @@ Renderer::Renderer(void *&window_handle) s_last_multisample_mode = g_ActiveConfig.iMultisampleMode; s_last_efb_scale = g_ActiveConfig.iEFBScale; - s_last_fullscreen_mode = g_ActiveConfig.bFullscreen; s_last_stereo_mode = g_ActiveConfig.iStereoMode > 0; s_last_xfb_mode = g_ActiveConfig.bUseRealXFB; CalculateTargetSize(s_backbuffer_width, s_backbuffer_height); @@ -866,20 +863,6 @@ void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, co const bool fullscreen = g_ActiveConfig.bFullscreen && !SConfig::GetInstance().m_LocalCoreStartupParameter.bRenderToMain; - bool fullscreen_changed = s_last_fullscreen_mode != fullscreen; - - bool fullscreen_state; - if (SUCCEEDED(D3D::GetFullscreenState(&fullscreen_state))) - { - if (fullscreen_state != fullscreen && Host_RendererHasFocus()) - { - // The current fullscreen state does not match the configuration, - // this may happen when the renderer frame loses focus. When the - // render frame is in focus again we can re-apply the configuration. - fullscreen_changed = true; - } - } - bool xfbchanged = s_last_xfb_mode != g_ActiveConfig.bUseRealXFB; if (FramebufferManagerBase::LastXfbWidth() != fbStride || FramebufferManagerBase::LastXfbHeight() != fbHeight) @@ -894,6 +877,20 @@ void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, co // Flip/present backbuffer to frontbuffer here D3D::Present(); + // Check exclusive fullscreen state + bool fullscreen_state, fullscreen_changed = false; + if (SUCCEEDED(D3D::GetFullscreenState(&fullscreen_state))) + { + if (fullscreen_state != fullscreen) + { + // The current fullscreen state does not match the configuration, + // either we switched fullscreen settings or the render frame + // lost focus. When the render frame is in focus we can apply + // exclusive mode. + fullscreen_changed = Host_RendererHasFocus(); + } + } + // Resize the back buffers NOW to avoid flickering if (xfbchanged || windowResized || @@ -911,7 +908,6 @@ void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, co // Apply fullscreen state if (fullscreen_changed) { - s_last_fullscreen_mode = fullscreen; D3D::SetFullscreenState(fullscreen); // Notify the host that it is safe to exit fullscreen From b7e056c74d6c157d04cbb79bbb7660a169662c53 Mon Sep 17 00:00:00 2001 From: Jules Blok Date: Sun, 4 Jan 2015 17:09:56 +0100 Subject: [PATCH 2/3] Host: Add Host_RendererIsFullscreen(). --- Source/Core/Core/Host.h | 1 + Source/Core/DolphinQt/Host.cpp | 5 +++++ Source/Core/DolphinWX/Frame.h | 2 +- Source/Core/DolphinWX/Main.cpp | 5 +++++ Source/Core/DolphinWX/MainAndroid.cpp | 5 +++++ Source/Core/DolphinWX/MainNoGUI.cpp | 9 ++++++++- Source/Core/DolphinWX/X11Utils.cpp | 7 ++++++- Source/Core/DolphinWX/X11Utils.h | 2 +- Source/UnitTests/TestUtils/StubHost.cpp | 1 + 9 files changed, 33 insertions(+), 4 deletions(-) diff --git a/Source/Core/Core/Host.h b/Source/Core/Core/Host.h index 3bb2ec76b1..2ca0195fa4 100644 --- a/Source/Core/Core/Host.h +++ b/Source/Core/Core/Host.h @@ -25,6 +25,7 @@ bool Host_UIHasFocus(); bool Host_RendererHasFocus(); +bool Host_RendererIsFullscreen(); void Host_ConnectWiimote(int wm_idx, bool connect); void Host_Message(int Id); void Host_NotifyMapLoaded(); diff --git a/Source/Core/DolphinQt/Host.cpp b/Source/Core/DolphinQt/Host.cpp index 1969dad4fd..6868f40f8e 100644 --- a/Source/Core/DolphinQt/Host.cpp +++ b/Source/Core/DolphinQt/Host.cpp @@ -48,6 +48,11 @@ bool Host_UIHasFocus() return g_main_window->isActiveWindow(); } +bool Host_RendererIsFullscreen() +{ + return false; // TODO +} + void Host_RequestFullscreen(bool enable) { // TODO diff --git a/Source/Core/DolphinWX/Frame.h b/Source/Core/DolphinWX/Frame.h index 94c54cbfef..0c9c7bc280 100644 --- a/Source/Core/DolphinWX/Frame.h +++ b/Source/Core/DolphinWX/Frame.h @@ -119,6 +119,7 @@ public: void OnRenderParentMove(wxMoveEvent& event); bool RendererHasFocus(); bool UIHasFocus(); + bool RendererIsFullscreen(); void DoFullscreen(bool bF); void ToggleDisplayMode (bool bFullscreen); void UpdateWiiMenuChoice(wxMenuItem *WiiMenuItem=nullptr); @@ -329,7 +330,6 @@ private: void OnGameListCtrl_ItemActivated(wxListEvent& event); void OnRenderParentResize(wxSizeEvent& event); - bool RendererIsFullscreen(); void StartGame(const std::string& filename); void OnChangeColumnsVisible(wxCommandEvent& event); diff --git a/Source/Core/DolphinWX/Main.cpp b/Source/Core/DolphinWX/Main.cpp index 2d3a322dfa..dcb200059a 100644 --- a/Source/Core/DolphinWX/Main.cpp +++ b/Source/Core/DolphinWX/Main.cpp @@ -572,6 +572,11 @@ bool Host_RendererHasFocus() return main_frame->RendererHasFocus(); } +bool Host_RendererIsFullscreen() +{ + return main_frame->RendererIsFullscreen(); +} + void Host_ConnectWiimote(int wm_idx, bool connect) { CFrame::ConnectWiimote(wm_idx, connect); diff --git a/Source/Core/DolphinWX/MainAndroid.cpp b/Source/Core/DolphinWX/MainAndroid.cpp index 533dd90c30..0d9d4428ce 100644 --- a/Source/Core/DolphinWX/MainAndroid.cpp +++ b/Source/Core/DolphinWX/MainAndroid.cpp @@ -94,6 +94,11 @@ bool Host_RendererHasFocus() return true; } +bool Host_RendererIsFullscreen() +{ + return false; +} + void Host_ConnectWiimote(int wm_idx, bool connect) {} void Host_SetWiiMoteConnectionState(int _State) {} diff --git a/Source/Core/DolphinWX/MainNoGUI.cpp b/Source/Core/DolphinWX/MainNoGUI.cpp index be3d9a7df3..8d6d0282a6 100644 --- a/Source/Core/DolphinWX/MainNoGUI.cpp +++ b/Source/Core/DolphinWX/MainNoGUI.cpp @@ -26,6 +26,7 @@ #include "VideoCommon/VideoBackendBase.h" static bool rendererHasFocus = true; +static bool rendererIsFullscreen = false; static bool running = true; class Platform @@ -89,6 +90,11 @@ bool Host_RendererHasFocus() return rendererHasFocus; } +bool Host_RendererIsFullscreen() +{ + return rendererIsFullscreen; +} + void Host_ConnectWiimote(int wm_idx, bool connect) {} void Host_SetWiiMoteConnectionState(int _State) {} @@ -158,7 +164,7 @@ class PlatformX11 : public Platform if (fullscreen) { - X11Utils::ToggleFullscreen(dpy, win); + rendererIsFullscreen = X11Utils::ToggleFullscreen(dpy, win); #if defined(HAVE_XRANDR) && HAVE_XRANDR XRRConfig->ToggleDisplayMode(True); #endif @@ -246,6 +252,7 @@ class PlatformX11 : public Platform (unsigned int *)&SConfig::GetInstance().m_LocalCoreStartupParameter.iRenderWindowWidth, (unsigned int *)&SConfig::GetInstance().m_LocalCoreStartupParameter.iRenderWindowHeight, &borderDummy, &depthDummy); + rendererIsFullscreen = false; } usleep(100000); } diff --git a/Source/Core/DolphinWX/X11Utils.cpp b/Source/Core/DolphinWX/X11Utils.cpp index 6a666692a2..03973b1aba 100644 --- a/Source/Core/DolphinWX/X11Utils.cpp +++ b/Source/Core/DolphinWX/X11Utils.cpp @@ -24,7 +24,7 @@ extern char **environ; namespace X11Utils { -void ToggleFullscreen(Display *dpy, Window win) +bool ToggleFullscreen(Display *dpy, Window win) { // Init X event structure for _NET_WM_STATE_FULLSCREEN client message XEvent event; @@ -38,7 +38,12 @@ void ToggleFullscreen(Display *dpy, Window win) // Send the event if (!XSendEvent(dpy, DefaultRootWindow(dpy), False, SubstructureRedirectMask | SubstructureNotifyMask, &event)) + { ERROR_LOG(VIDEO, "Failed to switch fullscreen/windowed mode."); + return false; + } + + return true; } void InhibitScreensaver(Display *dpy, Window win, bool suspend) diff --git a/Source/Core/DolphinWX/X11Utils.h b/Source/Core/DolphinWX/X11Utils.h index b68a1babe6..0a62e3027b 100644 --- a/Source/Core/DolphinWX/X11Utils.h +++ b/Source/Core/DolphinWX/X11Utils.h @@ -34,7 +34,7 @@ namespace X11Utils { -void ToggleFullscreen(Display *dpy, Window win); +bool ToggleFullscreen(Display *dpy, Window win); #if defined(HAVE_WX) && HAVE_WX Window XWindowFromHandle(void *Handle); Display *XDisplayFromHandle(void *Handle); diff --git a/Source/UnitTests/TestUtils/StubHost.cpp b/Source/UnitTests/TestUtils/StubHost.cpp index 2e8839ea67..a4d75cdca7 100644 --- a/Source/UnitTests/TestUtils/StubHost.cpp +++ b/Source/UnitTests/TestUtils/StubHost.cpp @@ -22,6 +22,7 @@ void Host_RequestFullscreen(bool) {} void Host_SetStartupDebuggingParameters() {} bool Host_UIHasFocus() { return false; } bool Host_RendererHasFocus() { return false; } +bool Host_RendererIsFullscreen() { return false; } void Host_ConnectWiimote(int, bool) {} void Host_SetWiiMoteConnectionState(int) {} void Host_ShowVideoConfig(void*, const std::string&, const std::string&) {} From 399b6248d1042eedc545630b8b2752c148377b88 Mon Sep 17 00:00:00 2001 From: Jules Blok Date: Mon, 5 Jan 2015 00:01:22 +0100 Subject: [PATCH 3/3] D3D: Further improve exclusive fullscreen state checking. --- Source/Core/VideoBackends/D3D/Render.cpp | 37 ++++++++++++++---------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/Source/Core/VideoBackends/D3D/Render.cpp b/Source/Core/VideoBackends/D3D/Render.cpp index f24e86a5d2..fd8e406ff2 100644 --- a/Source/Core/VideoBackends/D3D/Render.cpp +++ b/Source/Core/VideoBackends/D3D/Render.cpp @@ -878,17 +878,32 @@ void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, co D3D::Present(); // Check exclusive fullscreen state - bool fullscreen_state, fullscreen_changed = false; - if (SUCCEEDED(D3D::GetFullscreenState(&fullscreen_state))) + bool exclusive_mode, fullscreen_changed = false; + if (SUCCEEDED(D3D::GetFullscreenState(&exclusive_mode))) { - if (fullscreen_state != fullscreen) + if (fullscreen && !exclusive_mode) { - // The current fullscreen state does not match the configuration, - // either we switched fullscreen settings or the render frame - // lost focus. When the render frame is in focus we can apply - // exclusive mode. + // Exclusive fullscreen is enabled in the configuration, but we're + // not in exclusive mode. Either exclusive fullscreen was turned on + // or the render frame lost focus. When the render frame is in focus + // we can apply exclusive mode. fullscreen_changed = Host_RendererHasFocus(); } + else if (!fullscreen) + { + if (exclusive_mode) + { + // Exclusive fullscreen is disabled, but we're still in exclusive mode. + fullscreen_changed = true; + } + else if (!g_ActiveConfig.bBorderlessFullscreen && Host_RendererIsFullscreen()) + { + // Exclusive fullscreen is disabled and we are no longer in exclusive + // mode. Thus we can now safely notify the UI to exit fullscreen. But + // we should only do so if borderless fullscreen mode is disabled. + Host_RequestFullscreen(false); + } + } } // Resize the back buffers NOW to avoid flickering @@ -907,16 +922,8 @@ void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, co { // Apply fullscreen state if (fullscreen_changed) - { D3D::SetFullscreenState(fullscreen); - // Notify the host that it is safe to exit fullscreen - if (!fullscreen) - { - Host_RequestFullscreen(false); - } - } - // TODO: Aren't we still holding a reference to the back buffer right now? D3D::Reset(); SAFE_RELEASE(s_screenshot_texture);