From c21efa0cad0e968dcc9c439169e09ba7b3fed27c Mon Sep 17 00:00:00 2001 From: Jules Blok Date: Wed, 9 Nov 2016 01:07:56 +0100 Subject: [PATCH 1/9] D3D: Move exclusive mode switching to UI thread. This prevents deadlocks when switching to exclusive mode. And it also allows the CPU thread to block until we've completed the switch. --- Source/Core/DolphinWX/Frame.cpp | 29 +++--------- Source/Core/DolphinWX/FrameTools.cpp | 6 --- Source/Core/DolphinWX/Globals.h | 1 - Source/Core/VideoBackends/D3D/Render.cpp | 58 ++++++++---------------- Source/Core/VideoBackends/D3D/Render.h | 1 + Source/Core/VideoCommon/RenderBase.h | 1 + 6 files changed, 28 insertions(+), 68 deletions(-) diff --git a/Source/Core/DolphinWX/Frame.cpp b/Source/Core/DolphinWX/Frame.cpp index 129cd16108..2611ec491e 100644 --- a/Source/Core/DolphinWX/Frame.cpp +++ b/Source/Core/DolphinWX/Frame.cpp @@ -1131,28 +1131,12 @@ void CFrame::OnMouse(wxMouseEvent& event) void CFrame::DoFullscreen(bool enable_fullscreen) { - if (g_Config.bExclusiveMode && Core::GetState() == Core::CORE_PAUSE) - { - // A responsive renderer is required for exclusive fullscreen, but the - // renderer can only respond in the running state. Therefore we ignore - // fullscreen switches if we are in exclusive fullscreen, but the - // renderer is not running. - // TODO: Allow the renderer to switch fullscreen modes while paused. - return; - } - ToggleDisplayMode(enable_fullscreen); - if (enable_fullscreen) - { - m_RenderFrame->ShowFullScreen(true, wxFULLSCREEN_ALL); - } - else if (!g_Config.bExclusiveMode) - { - // Exiting exclusive fullscreen should be done from a Renderer callback. - // Therefore we don't exit fullscreen from here if we are in exclusive mode. - m_RenderFrame->ShowFullScreen(false, wxFULLSCREEN_ALL); - } + if (!enable_fullscreen && g_renderer) + g_renderer->SetFullscreen(false); + + m_RenderFrame->ShowFullScreen(enable_fullscreen, wxFULLSCREEN_ALL); if (SConfig::GetInstance().bRenderToMain) { @@ -1200,9 +1184,10 @@ void CFrame::DoFullscreen(bool enable_fullscreen) else { m_RenderFrame->Raise(); - } - g_Config.bFullscreen = enable_fullscreen; + if (enable_fullscreen && g_renderer) + g_renderer->SetFullscreen(true); + } } const CGameListCtrl* CFrame::GetGameListCtrl() const diff --git a/Source/Core/DolphinWX/FrameTools.cpp b/Source/Core/DolphinWX/FrameTools.cpp index 58f8c34afb..63416f6464 100644 --- a/Source/Core/DolphinWX/FrameTools.cpp +++ b/Source/Core/DolphinWX/FrameTools.cpp @@ -787,12 +787,6 @@ void CFrame::DoStop() // waiting on inputs bool should_pause = !NetPlayDialog::GetNetPlayClient(); - // If exclusive fullscreen is not enabled then we can pause the emulation - // before we've exited fullscreen. If not then we need to exit fullscreen first. - should_pause = - should_pause && (!RendererIsFullscreen() || !g_Config.ExclusiveFullscreenEnabled() || - SConfig::GetInstance().bRenderToMain); - if (should_pause) { Core::SetState(Core::CORE_PAUSE); diff --git a/Source/Core/DolphinWX/Globals.h b/Source/Core/DolphinWX/Globals.h index cd36f68c1a..3ab8c809cd 100644 --- a/Source/Core/DolphinWX/Globals.h +++ b/Source/Core/DolphinWX/Globals.h @@ -292,7 +292,6 @@ enum IDM_WINDOW_SIZE_REQUEST, IDM_STOPPED, IDM_HOST_MESSAGE, - IDM_FULLSCREEN_REQUEST, // Used for Host_ConnectWiimote() IDM_FORCE_CONNECT_WIIMOTE1, diff --git a/Source/Core/VideoBackends/D3D/Render.cpp b/Source/Core/VideoBackends/D3D/Render.cpp index bf0b487276..70dbb77bb3 100644 --- a/Source/Core/VideoBackends/D3D/Render.cpp +++ b/Source/Core/VideoBackends/D3D/Render.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -43,6 +44,9 @@ namespace DX11 static u32 s_last_multisamples = 1; static bool s_last_stereo_mode = false; static bool s_last_xfb_mode = false; +static bool s_last_exclusive_mode = false; + +static std::mutex s_critical_fullscreen; static Television s_television; @@ -851,8 +855,6 @@ void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, SetWindowSize(fbStride, fbHeight); const bool windowResized = CheckForResize(); - const bool fullscreen = g_ActiveConfig.bFullscreen && !g_ActiveConfig.bBorderlessFullscreen && - !SConfig::GetInstance().bRenderToMain; bool xfbchanged = s_last_xfb_mode != g_ActiveConfig.bUseRealXFB; @@ -869,33 +871,19 @@ void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, // Flip/present backbuffer to frontbuffer here D3D::Present(); - // Check exclusive fullscreen state - bool exclusive_mode, fullscreen_changed = false; - if (SUCCEEDED(D3D::GetFullscreenState(&exclusive_mode))) + // Check if we need to regain exclusive mode { - if (fullscreen && !exclusive_mode) - { - if (g_Config.bExclusiveMode) - OSD::AddMessage("Lost exclusive fullscreen."); + std::lock_guard lk(s_critical_fullscreen); - // 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(); - - g_Config.bExclusiveMode = false; - } - else if (!fullscreen && exclusive_mode) - { - // Exclusive fullscreen is disabled, but we're still in exclusive mode. - fullscreen_changed = true; - } + bool exclusive_mode = false; + D3D::GetFullscreenState(&exclusive_mode); + if (s_last_exclusive_mode && !exclusive_mode && Host_RendererHasFocus()) + D3D::SetFullscreenState(true); } // Resize the back buffers NOW to avoid flickering if (CalculateTargetSize(s_backbuffer_width, s_backbuffer_height) || xfbchanged || windowResized || - fullscreen_changed || s_last_efb_scale != g_ActiveConfig.iEFBScale || + s_last_efb_scale != g_ActiveConfig.iEFBScale || s_last_multisamples != g_ActiveConfig.iMultisamples || s_last_stereo_mode != (g_ActiveConfig.iStereoMode > 0)) { @@ -903,23 +891,8 @@ void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, s_last_multisamples = g_ActiveConfig.iMultisamples; PixelShaderCache::InvalidateMSAAShaders(); - if (windowResized || fullscreen_changed) + if (windowResized) { - // Apply fullscreen state - if (fullscreen_changed) - { - g_Config.bExclusiveMode = fullscreen; - - if (fullscreen) - OSD::AddMessage("Entered exclusive fullscreen."); - - D3D::SetFullscreenState(fullscreen); - - // If fullscreen is disabled we can safely notify the UI to exit fullscreen. - if (!g_ActiveConfig.bFullscreen) - Host_RequestFullscreen(false); - } - // TODO: Aren't we still holding a reference to the back buffer right now? D3D::Reset(); SAFE_RELEASE(s_screenshot_texture); @@ -1291,4 +1264,11 @@ void Renderer::BlitScreen(TargetRectangle src, TargetRectangle dst, D3DTexture2D } } +void Renderer::SetFullscreen(bool enable_fullscreen) +{ + std::lock_guard lk(s_critical_fullscreen); + s_last_exclusive_mode = enable_fullscreen; + D3D::SetFullscreenState(enable_fullscreen); +} + } // namespace DX11 diff --git a/Source/Core/VideoBackends/D3D/Render.h b/Source/Core/VideoBackends/D3D/Render.h index 66f546be6c..43e9519be9 100644 --- a/Source/Core/VideoBackends/D3D/Render.h +++ b/Source/Core/VideoBackends/D3D/Render.h @@ -25,6 +25,7 @@ public: void SetSamplerState(int stage, int texindex, bool custom_tex) override; void SetInterlacingMode() override; void SetViewport() override; + void SetFullscreen(bool enable_fullscreen) override; // TODO: Fix confusing names (see ResetAPIState and RestoreAPIState) void ApplyState(bool bUseDstAlpha) override; diff --git a/Source/Core/VideoCommon/RenderBase.h b/Source/Core/VideoCommon/RenderBase.h index 94f48d0b9b..4e1f6fe23b 100644 --- a/Source/Core/VideoCommon/RenderBase.h +++ b/Source/Core/VideoCommon/RenderBase.h @@ -72,6 +72,7 @@ public: virtual void SetSamplerState(int stage, int texindex, bool custom_tex) {} virtual void SetInterlacingMode() {} virtual void SetViewport() {} + virtual void SetFullscreen(bool enable_fullscreen) {} virtual void ApplyState(bool bUseDstAlpha) {} virtual void RestoreState() {} virtual void ResetAPIState() {} From 0a194f8a3e1378acffe82c6c9d4ea3f5aa7a4ddd Mon Sep 17 00:00:00 2001 From: Jules Blok Date: Wed, 9 Nov 2016 01:09:40 +0100 Subject: [PATCH 2/9] VideoConfig: Remove fullscreen flags. These weren't actually settings, they were used as a bad way to communicate with the GPU thread. --- Source/Core/Core/Analytics.cpp | 2 -- Source/Core/VideoBackends/D3D/D3DBase.cpp | 2 +- Source/Core/VideoBackends/D3D12/Render.cpp | 2 -- Source/Core/VideoCommon/VideoConfig.cpp | 4 ---- Source/Core/VideoCommon/VideoConfig.h | 2 -- 5 files changed, 1 insertion(+), 11 deletions(-) diff --git a/Source/Core/Core/Analytics.cpp b/Source/Core/Core/Analytics.cpp index 65d298af0d..4d2dcd8e41 100644 --- a/Source/Core/Core/Analytics.cpp +++ b/Source/Core/Core/Analytics.cpp @@ -211,8 +211,6 @@ void DolphinAnalytics::MakePerGameBuilder() builder.AddData("cfg-gfx-realxfb", g_Config.RealXFBEnabled()); builder.AddData("cfg-gfx-virtualxfb", g_Config.VirtualXFBEnabled()); builder.AddData("cfg-gfx-vsync", g_Config.bVSync); - builder.AddData("cfg-gfx-fullscreen", g_Config.bFullscreen); - builder.AddData("cfg-gfx-exclusive-mode", g_Config.bExclusiveMode); builder.AddData("cfg-gfx-aspect-ratio", g_Config.iAspectRatio); builder.AddData("cfg-gfx-efb-access", g_Config.bEFBAccessEnable); builder.AddData("cfg-gfx-efb-scale", g_Config.iEFBScale); diff --git a/Source/Core/VideoBackends/D3D/D3DBase.cpp b/Source/Core/VideoBackends/D3D/D3DBase.cpp index 55f3e524bd..21580c856d 100644 --- a/Source/Core/VideoBackends/D3D/D3DBase.cpp +++ b/Source/Core/VideoBackends/D3D/D3DBase.cpp @@ -315,7 +315,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_Config.bFullscreen; + swap_chain_desc.Windowed = TRUE; DXGI_OUTPUT_DESC out_desc = {}; output->GetDesc(&out_desc); diff --git a/Source/Core/VideoBackends/D3D12/Render.cpp b/Source/Core/VideoBackends/D3D12/Render.cpp index 8b3c36651b..f37357aef4 100644 --- a/Source/Core/VideoBackends/D3D12/Render.cpp +++ b/Source/Core/VideoBackends/D3D12/Render.cpp @@ -803,8 +803,6 @@ void Renderer::SwapImpl(u32 xfb_addr, u32 fb_width, u32 fb_stride, u32 fb_height SetWindowSize(fb_stride, fb_height); const bool window_resized = CheckForResize(); - const bool fullscreen = g_ActiveConfig.bFullscreen && !g_ActiveConfig.bBorderlessFullscreen && - !SConfig::GetInstance().bRenderToMain; bool xfb_changed = s_last_xfb_mode != g_ActiveConfig.bUseRealXFB; diff --git a/Source/Core/VideoCommon/VideoConfig.cpp b/Source/Core/VideoCommon/VideoConfig.cpp index 0e79b4b180..115dbf8162 100644 --- a/Source/Core/VideoCommon/VideoConfig.cpp +++ b/Source/Core/VideoCommon/VideoConfig.cpp @@ -31,10 +31,6 @@ VideoConfig::VideoConfig() { bRunning = false; - // Exclusive fullscreen flags - bFullscreen = false; - bExclusiveMode = false; - // Needed for the first frame, I think fAspectRatioHackW = 1; fAspectRatioHackH = 1; diff --git a/Source/Core/VideoCommon/VideoConfig.h b/Source/Core/VideoCommon/VideoConfig.h index b866ce6343..225c12d590 100644 --- a/Source/Core/VideoCommon/VideoConfig.h +++ b/Source/Core/VideoCommon/VideoConfig.h @@ -63,8 +63,6 @@ struct VideoConfig final // General bool bVSync; - bool bFullscreen; - bool bExclusiveMode; bool bRunning; bool bWidescreenHack; int iAspectRatio; From 0028ee96b34d566f459f690a44e0c5ffcc7621a0 Mon Sep 17 00:00:00 2001 From: Jules Blok Date: Wed, 9 Nov 2016 01:10:32 +0100 Subject: [PATCH 3/9] Host: Remove the Host_RequestFullscreen() method. No longer needed, since the exclusive mode switch is now handled synchronously on the CPU thread. --- Source/Core/Core/Host.h | 1 - Source/Core/DolphinQt2/Host.cpp | 3 --- Source/Core/DolphinWX/Frame.cpp | 15 --------------- Source/Core/DolphinWX/Main.cpp | 7 ------- Source/Core/DolphinWX/MainNoGUI.cpp | 4 ---- 5 files changed, 30 deletions(-) diff --git a/Source/Core/Core/Host.h b/Source/Core/Core/Host.h index 2f517c4c8e..349d65f7a6 100644 --- a/Source/Core/Core/Host.h +++ b/Source/Core/Core/Host.h @@ -31,7 +31,6 @@ void Host_Message(int Id); void Host_NotifyMapLoaded(); void Host_RefreshDSPDebuggerWindow(); void Host_RequestRenderWindowSize(int width, int height); -void Host_RequestFullscreen(bool enable_fullscreen); void Host_SetStartupDebuggingParameters(); void Host_SetWiiMoteConnectionState(int _State); void Host_UpdateDisasmDialog(); diff --git a/Source/Core/DolphinQt2/Host.cpp b/Source/Core/DolphinQt2/Host.cpp index 906853bc3c..0797f4f39e 100644 --- a/Source/Core/DolphinQt2/Host.cpp +++ b/Source/Core/DolphinQt2/Host.cpp @@ -100,9 +100,6 @@ void Host_YieldToUI() void Host_UpdateMainFrame() { } -void Host_RequestFullscreen(bool enable) -{ -} void Host_RequestRenderWindowSize(int w, int h) { } diff --git a/Source/Core/DolphinWX/Frame.cpp b/Source/Core/DolphinWX/Frame.cpp index 2611ec491e..5d7fd6b316 100644 --- a/Source/Core/DolphinWX/Frame.cpp +++ b/Source/Core/DolphinWX/Frame.cpp @@ -701,21 +701,6 @@ void CFrame::OnHostMessage(wxCommandEvent& event) } break; - case IDM_FULLSCREEN_REQUEST: - { - bool enable_fullscreen = event.GetInt() == 0 ? false : true; - ToggleDisplayMode(enable_fullscreen); - if (m_RenderFrame != nullptr) - m_RenderFrame->ShowFullScreen(enable_fullscreen); - - // If the stop dialog initiated this fullscreen switch then we need - // to pause the emulator after we've completed the switch. - // TODO: Allow the renderer to switch fullscreen modes while paused. - if (m_confirmStop) - Core::SetState(Core::CORE_PAUSE); - } - break; - case WM_USER_CREATE: if (SConfig::GetInstance().bHideCursor) m_RenderParent->SetCursor(wxCURSOR_BLANK); diff --git a/Source/Core/DolphinWX/Main.cpp b/Source/Core/DolphinWX/Main.cpp index 444b270d39..f87de73a0c 100644 --- a/Source/Core/DolphinWX/Main.cpp +++ b/Source/Core/DolphinWX/Main.cpp @@ -452,13 +452,6 @@ void Host_RequestRenderWindowSize(int width, int height) main_frame->GetEventHandler()->AddPendingEvent(event); } -void Host_RequestFullscreen(bool enable_fullscreen) -{ - wxCommandEvent event(wxEVT_HOST_COMMAND, IDM_FULLSCREEN_REQUEST); - event.SetInt(enable_fullscreen ? 1 : 0); - main_frame->GetEventHandler()->AddPendingEvent(event); -} - void Host_SetStartupDebuggingParameters() { SConfig& StartUp = SConfig::GetInstance(); diff --git a/Source/Core/DolphinWX/MainNoGUI.cpp b/Source/Core/DolphinWX/MainNoGUI.cpp index 6c8a53b88d..b0c6e9a321 100644 --- a/Source/Core/DolphinWX/MainNoGUI.cpp +++ b/Source/Core/DolphinWX/MainNoGUI.cpp @@ -113,10 +113,6 @@ void Host_RequestRenderWindowSize(int width, int height) { } -void Host_RequestFullscreen(bool enable_fullscreen) -{ -} - void Host_SetStartupDebuggingParameters() { SConfig& StartUp = SConfig::GetInstance(); From 9909babe2c482c2fc7d65a4594188067df0a8ece Mon Sep 17 00:00:00 2001 From: Jules Blok Date: Wed, 9 Nov 2016 01:41:38 +0100 Subject: [PATCH 4/9] D3DBase: Create the swapchain in fullscreen mode if enabled. --- Source/Core/VideoBackends/D3D/D3DBase.cpp | 18 +++++++----------- Source/Core/VideoBackends/D3D/D3DBase.h | 2 +- Source/Core/VideoBackends/D3D/Render.cpp | 4 ++-- Source/Core/VideoBackends/D3D12/D3DBase.cpp | 5 ++--- Source/Core/VideoBackends/D3D12/D3DBase.h | 2 +- 5 files changed, 13 insertions(+), 18 deletions(-) diff --git a/Source/Core/VideoBackends/D3D/D3DBase.cpp b/Source/Core/VideoBackends/D3D/D3DBase.cpp index 21580c856d..3edd936efa 100644 --- a/Source/Core/VideoBackends/D3D/D3DBase.cpp +++ b/Source/Core/VideoBackends/D3D/D3DBase.cpp @@ -8,6 +8,7 @@ #include "Common/Logging/Log.h" #include "Common/MsgHandler.h" #include "Common/StringUtil.h" +#include "Core/ConfigManager.h" #include "VideoBackends/D3D/D3DBase.h" #include "VideoBackends/D3D/D3DState.h" #include "VideoBackends/D3D/D3DTexture.h" @@ -315,7 +316,8 @@ 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 = TRUE; + swap_chain_desc.Windowed = + !SConfig::GetInstance().bFullscreen || g_ActiveConfig.bBorderlessFullscreen; DXGI_OUTPUT_DESC out_desc = {}; output->GetDesc(&out_desc); @@ -610,17 +612,11 @@ HRESULT SetFullscreenState(bool enable_fullscreen) return swapchain->SetFullscreenState(enable_fullscreen, nullptr); } -HRESULT GetFullscreenState(bool* fullscreen_state) +bool GetFullscreenState() { - if (fullscreen_state == nullptr) - { - return E_POINTER; - } - - BOOL state; - HRESULT hr = swapchain->GetFullscreenState(&state, nullptr); - *fullscreen_state = !!state; - return hr; + BOOL state = FALSE; + swapchain->GetFullscreenState(&state, nullptr); + return !!state; } } // namespace D3D diff --git a/Source/Core/VideoBackends/D3D/D3DBase.h b/Source/Core/VideoBackends/D3D/D3DBase.h index 24c6848434..668671fee6 100644 --- a/Source/Core/VideoBackends/D3D/D3DBase.h +++ b/Source/Core/VideoBackends/D3D/D3DBase.h @@ -75,7 +75,7 @@ bool BGRATexturesSupported(); unsigned int GetMaxTextureSize(); HRESULT SetFullscreenState(bool enable_fullscreen); -HRESULT GetFullscreenState(bool* fullscreen_state); +bool GetFullscreenState(); // This function will assign a name to the given resource. // The DirectX debug layer will make it easier to identify resources that way, diff --git a/Source/Core/VideoBackends/D3D/Render.cpp b/Source/Core/VideoBackends/D3D/Render.cpp index 70dbb77bb3..26bd8956bc 100644 --- a/Source/Core/VideoBackends/D3D/Render.cpp +++ b/Source/Core/VideoBackends/D3D/Render.cpp @@ -254,6 +254,7 @@ Renderer::Renderer(void*& window_handle) s_last_efb_scale = g_ActiveConfig.iEFBScale; s_last_stereo_mode = g_ActiveConfig.iStereoMode > 0; s_last_xfb_mode = g_ActiveConfig.bUseRealXFB; + s_last_exclusive_mode = D3D::GetFullscreenState(); CalculateTargetSize(s_backbuffer_width, s_backbuffer_height); PixelShaderManager::SetEfbScaleChanged(); @@ -875,8 +876,7 @@ void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, { std::lock_guard lk(s_critical_fullscreen); - bool exclusive_mode = false; - D3D::GetFullscreenState(&exclusive_mode); + const bool exclusive_mode = D3D::GetFullscreenState(); if (s_last_exclusive_mode && !exclusive_mode && Host_RendererHasFocus()) D3D::SetFullscreenState(true); } diff --git a/Source/Core/VideoBackends/D3D12/D3DBase.cpp b/Source/Core/VideoBackends/D3D12/D3DBase.cpp index 5405ec1f2e..9f1da4042e 100644 --- a/Source/Core/VideoBackends/D3D12/D3DBase.cpp +++ b/Source/Core/VideoBackends/D3D12/D3DBase.cpp @@ -871,12 +871,11 @@ HRESULT SetFullscreenState(bool enable_fullscreen) return S_OK; } -HRESULT GetFullscreenState(bool* fullscreen_state) +bool GetFullscreenState() { // Fullscreen exclusive intentionally not supported in DX12 backend. No performance // difference between it and windowed full-screen due to usage of a FLIP swap chain. - *fullscreen_state = false; - return S_OK; + return false; } } // namespace D3D diff --git a/Source/Core/VideoBackends/D3D12/D3DBase.h b/Source/Core/VideoBackends/D3D12/D3DBase.h index a23bad1feb..89cd02738d 100644 --- a/Source/Core/VideoBackends/D3D12/D3DBase.h +++ b/Source/Core/VideoBackends/D3D12/D3DBase.h @@ -124,7 +124,7 @@ const std::string VertexShaderVersionString(); unsigned int GetMaxTextureSize(); HRESULT SetFullscreenState(bool enable_fullscreen); -HRESULT GetFullscreenState(bool* fullscreen_state); +bool GetFullscreenState(); // This function will assign a name to the given resource. // The DirectX debug layer will make it easier to identify resources that way, From d7cf5e28b656aaccc847e1f4c1da361037638e27 Mon Sep 17 00:00:00 2001 From: Jules Blok Date: Wed, 9 Nov 2016 01:41:38 +0100 Subject: [PATCH 5/9] Frame: Use PauseAndLock when switching fullscreen modes. This allows us to regain exclusive mode directly from OnActive(). --- Source/Core/DolphinWX/Frame.cpp | 38 +++++++++++++++++++----- Source/Core/VideoBackends/D3D/Render.cpp | 21 ++++--------- Source/Core/VideoBackends/D3D/Render.h | 1 + Source/Core/VideoCommon/RenderBase.h | 1 + 4 files changed, 38 insertions(+), 23 deletions(-) diff --git a/Source/Core/DolphinWX/Frame.cpp b/Source/Core/DolphinWX/Frame.cpp index 5d7fd6b316..2c18202716 100644 --- a/Source/Core/DolphinWX/Frame.cpp +++ b/Source/Core/DolphinWX/Frame.cpp @@ -525,6 +525,16 @@ void CFrame::OnActive(wxActivateEvent& event) { if (SConfig::GetInstance().bRenderToMain) m_RenderParent->SetFocus(); + else if (RendererIsFullscreen() && g_ActiveConfig.ExclusiveFullscreenEnabled()) + { + // Regain exclusive mode if it was lost due to a focus change. + if (g_renderer && !g_renderer->IsFullscreen()) + { + bool was_unpaused = Core::PauseAndLock(true); + g_renderer->SetFullscreen(true); + Core::PauseAndLock(false, was_unpaused); + } + } if (SConfig::GetInstance().m_PauseOnFocusLost && Core::GetState() == Core::CORE_PAUSE) DoPause(); @@ -1118,13 +1128,10 @@ void CFrame::DoFullscreen(bool enable_fullscreen) { ToggleDisplayMode(enable_fullscreen); - if (!enable_fullscreen && g_renderer) - g_renderer->SetFullscreen(false); - - m_RenderFrame->ShowFullScreen(enable_fullscreen, wxFULLSCREEN_ALL); - if (SConfig::GetInstance().bRenderToMain) { + m_RenderFrame->ShowFullScreen(enable_fullscreen, wxFULLSCREEN_ALL); + if (enable_fullscreen) { // Save the current mode before going to fullscreen @@ -1166,12 +1173,29 @@ void CFrame::DoFullscreen(bool enable_fullscreen) } } } - else + else if (g_ActiveConfig.ExclusiveFullscreenEnabled()) { + if (g_renderer && !enable_fullscreen) + { + bool was_unpaused = Core::PauseAndLock(true); + g_renderer->SetFullscreen(false); + Core::PauseAndLock(false, was_unpaused); + } + + m_RenderFrame->ShowFullScreen(enable_fullscreen, wxFULLSCREEN_ALL); m_RenderFrame->Raise(); - if (enable_fullscreen && g_renderer) + if (g_renderer && enable_fullscreen) + { + bool was_unpaused = Core::PauseAndLock(true); g_renderer->SetFullscreen(true); + Core::PauseAndLock(false, was_unpaused); + } + } + else + { + m_RenderFrame->ShowFullScreen(enable_fullscreen, wxFULLSCREEN_ALL); + m_RenderFrame->Raise(); } } diff --git a/Source/Core/VideoBackends/D3D/Render.cpp b/Source/Core/VideoBackends/D3D/Render.cpp index 26bd8956bc..0653f48afa 100644 --- a/Source/Core/VideoBackends/D3D/Render.cpp +++ b/Source/Core/VideoBackends/D3D/Render.cpp @@ -5,7 +5,6 @@ #include #include #include -#include #include #include #include @@ -44,9 +43,6 @@ namespace DX11 static u32 s_last_multisamples = 1; static bool s_last_stereo_mode = false; static bool s_last_xfb_mode = false; -static bool s_last_exclusive_mode = false; - -static std::mutex s_critical_fullscreen; static Television s_television; @@ -254,7 +250,6 @@ Renderer::Renderer(void*& window_handle) s_last_efb_scale = g_ActiveConfig.iEFBScale; s_last_stereo_mode = g_ActiveConfig.iStereoMode > 0; s_last_xfb_mode = g_ActiveConfig.bUseRealXFB; - s_last_exclusive_mode = D3D::GetFullscreenState(); CalculateTargetSize(s_backbuffer_width, s_backbuffer_height); PixelShaderManager::SetEfbScaleChanged(); @@ -872,15 +867,6 @@ void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, // Flip/present backbuffer to frontbuffer here D3D::Present(); - // Check if we need to regain exclusive mode - { - std::lock_guard lk(s_critical_fullscreen); - - const bool exclusive_mode = D3D::GetFullscreenState(); - if (s_last_exclusive_mode && !exclusive_mode && Host_RendererHasFocus()) - D3D::SetFullscreenState(true); - } - // Resize the back buffers NOW to avoid flickering if (CalculateTargetSize(s_backbuffer_width, s_backbuffer_height) || xfbchanged || windowResized || s_last_efb_scale != g_ActiveConfig.iEFBScale || @@ -1266,9 +1252,12 @@ void Renderer::BlitScreen(TargetRectangle src, TargetRectangle dst, D3DTexture2D void Renderer::SetFullscreen(bool enable_fullscreen) { - std::lock_guard lk(s_critical_fullscreen); - s_last_exclusive_mode = enable_fullscreen; D3D::SetFullscreenState(enable_fullscreen); } +bool Renderer::IsFullscreen() +{ + return D3D::GetFullscreenState(); +} + } // namespace DX11 diff --git a/Source/Core/VideoBackends/D3D/Render.h b/Source/Core/VideoBackends/D3D/Render.h index 43e9519be9..bb16316aef 100644 --- a/Source/Core/VideoBackends/D3D/Render.h +++ b/Source/Core/VideoBackends/D3D/Render.h @@ -26,6 +26,7 @@ public: void SetInterlacingMode() override; void SetViewport() override; void SetFullscreen(bool enable_fullscreen) override; + bool IsFullscreen() override; // TODO: Fix confusing names (see ResetAPIState and RestoreAPIState) void ApplyState(bool bUseDstAlpha) override; diff --git a/Source/Core/VideoCommon/RenderBase.h b/Source/Core/VideoCommon/RenderBase.h index 4e1f6fe23b..15324f0ab5 100644 --- a/Source/Core/VideoCommon/RenderBase.h +++ b/Source/Core/VideoCommon/RenderBase.h @@ -73,6 +73,7 @@ public: virtual void SetInterlacingMode() {} virtual void SetViewport() {} virtual void SetFullscreen(bool enable_fullscreen) {} + virtual bool IsFullscreen() { return false; } virtual void ApplyState(bool bUseDstAlpha) {} virtual void RestoreState() {} virtual void ResetAPIState() {} From d8201a7e8bb26291f378f1197df0893955220031 Mon Sep 17 00:00:00 2001 From: Jules Blok Date: Fri, 11 Nov 2016 01:02:23 +0100 Subject: [PATCH 6/9] Frame: Remove exclusive mode OSD messages. --- Source/Core/DolphinWX/Frame.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/Source/Core/DolphinWX/Frame.cpp b/Source/Core/DolphinWX/Frame.cpp index 2c18202716..cf0929d639 100644 --- a/Source/Core/DolphinWX/Frame.cpp +++ b/Source/Core/DolphinWX/Frame.cpp @@ -202,11 +202,6 @@ bool CRenderFrame::ShowFullScreen(bool show, long style) { // OpenGL requires the pop-up style to activate exclusive mode. SetWindowStyle((GetWindowStyle() & ~wxDEFAULT_FRAME_STYLE) | wxPOPUP_WINDOW); - - // Some backends don't support exclusive fullscreen, so we - // can't tell exactly when exclusive mode is activated. - if (!g_Config.backend_info.bSupportsExclusiveFullscreen) - OSD::AddMessage("Entered exclusive fullscreen."); } #endif From aab6b70868b5d785886b9d54f7d49848463e002e Mon Sep 17 00:00:00 2001 From: Jules Blok Date: Fri, 11 Nov 2016 20:48:19 +0100 Subject: [PATCH 7/9] MainAndroid: Remove obsolete Host_RequestFullscreen() function --- Source/Android/jni/MainAndroid.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Source/Android/jni/MainAndroid.cpp b/Source/Android/jni/MainAndroid.cpp index 4cd975fae8..24fabfb72a 100644 --- a/Source/Android/jni/MainAndroid.cpp +++ b/Source/Android/jni/MainAndroid.cpp @@ -113,10 +113,6 @@ void Host_RequestRenderWindowSize(int width, int height) { } -void Host_RequestFullscreen(bool enable_fullscreen) -{ -} - void Host_SetStartupDebuggingParameters() { } From aa0e4472c0ff0091ff6e699894b5ef674e6c7647 Mon Sep 17 00:00:00 2001 From: Jules Blok Date: Fri, 11 Nov 2016 21:24:08 +0100 Subject: [PATCH 8/9] Frame: Move exclusive mode switching to helper function. --- Source/Core/DolphinWX/Frame.cpp | 36 ++++++++++++++------------------- Source/Core/DolphinWX/Frame.h | 1 + 2 files changed, 16 insertions(+), 21 deletions(-) diff --git a/Source/Core/DolphinWX/Frame.cpp b/Source/Core/DolphinWX/Frame.cpp index cf0929d639..a2a32c6ac8 100644 --- a/Source/Core/DolphinWX/Frame.cpp +++ b/Source/Core/DolphinWX/Frame.cpp @@ -521,15 +521,7 @@ void CFrame::OnActive(wxActivateEvent& event) if (SConfig::GetInstance().bRenderToMain) m_RenderParent->SetFocus(); else if (RendererIsFullscreen() && g_ActiveConfig.ExclusiveFullscreenEnabled()) - { - // Regain exclusive mode if it was lost due to a focus change. - if (g_renderer && !g_renderer->IsFullscreen()) - { - bool was_unpaused = Core::PauseAndLock(true); - g_renderer->SetFullscreen(true); - Core::PauseAndLock(false, was_unpaused); - } - } + DoExclusiveFullscreen(true); // Regain exclusive mode if (SConfig::GetInstance().m_PauseOnFocusLost && Core::GetState() == Core::CORE_PAUSE) DoPause(); @@ -1170,22 +1162,14 @@ void CFrame::DoFullscreen(bool enable_fullscreen) } else if (g_ActiveConfig.ExclusiveFullscreenEnabled()) { - if (g_renderer && !enable_fullscreen) - { - bool was_unpaused = Core::PauseAndLock(true); - g_renderer->SetFullscreen(false); - Core::PauseAndLock(false, was_unpaused); - } + if (!enable_fullscreen) + DoExclusiveFullscreen(false); m_RenderFrame->ShowFullScreen(enable_fullscreen, wxFULLSCREEN_ALL); m_RenderFrame->Raise(); - if (g_renderer && enable_fullscreen) - { - bool was_unpaused = Core::PauseAndLock(true); - g_renderer->SetFullscreen(true); - Core::PauseAndLock(false, was_unpaused); - } + if (enable_fullscreen) + DoExclusiveFullscreen(true); } else { @@ -1194,6 +1178,16 @@ void CFrame::DoFullscreen(bool enable_fullscreen) } } +void CFrame::DoExclusiveFullscreen(bool enable_fullscreen) +{ + if (g_renderer && g_renderer->IsFullscreen() != enable_fullscreen) + { + bool was_unpaused = Core::PauseAndLock(true); + g_renderer->SetFullscreen(enable_fullscreen); + Core::PauseAndLock(false, was_unpaused); + } +} + const CGameListCtrl* CFrame::GetGameListCtrl() const { return m_GameListCtrl; diff --git a/Source/Core/DolphinWX/Frame.h b/Source/Core/DolphinWX/Frame.h index c621043aff..dfe0a637e6 100644 --- a/Source/Core/DolphinWX/Frame.h +++ b/Source/Core/DolphinWX/Frame.h @@ -106,6 +106,7 @@ public: bool RendererHasFocus(); bool RendererIsFullscreen(); void DoFullscreen(bool bF); + void DoExclusiveFullscreen(bool bF); void ToggleDisplayMode(bool bFullscreen); static void ConnectWiimote(int wm_idx, bool connect); void UpdateTitle(const std::string& str); From 7e35a47b511176aa2c285568d582c6ea281a4ce1 Mon Sep 17 00:00:00 2001 From: Jules Blok Date: Sun, 13 Nov 2016 22:16:29 +0100 Subject: [PATCH 9/9] Cosmetics. --- Source/Core/DolphinWX/Frame.cpp | 12 ++++++------ Source/Core/DolphinWX/Frame.h | 4 ++-- Source/Core/VideoBackends/D3D/Render.cpp | 2 +- Source/Core/VideoBackends/D3D/Render.h | 2 +- Source/Core/VideoCommon/RenderBase.h | 2 +- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/Source/Core/DolphinWX/Frame.cpp b/Source/Core/DolphinWX/Frame.cpp index a2a32c6ac8..290b1a8e10 100644 --- a/Source/Core/DolphinWX/Frame.cpp +++ b/Source/Core/DolphinWX/Frame.cpp @@ -1180,12 +1180,12 @@ void CFrame::DoFullscreen(bool enable_fullscreen) void CFrame::DoExclusiveFullscreen(bool enable_fullscreen) { - if (g_renderer && g_renderer->IsFullscreen() != enable_fullscreen) - { - bool was_unpaused = Core::PauseAndLock(true); - g_renderer->SetFullscreen(enable_fullscreen); - Core::PauseAndLock(false, was_unpaused); - } + if (!g_renderer || g_renderer->IsFullscreen() == enable_fullscreen) + return; + + bool was_unpaused = Core::PauseAndLock(true); + g_renderer->SetFullscreen(enable_fullscreen); + Core::PauseAndLock(false, was_unpaused); } const CGameListCtrl* CFrame::GetGameListCtrl() const diff --git a/Source/Core/DolphinWX/Frame.h b/Source/Core/DolphinWX/Frame.h index dfe0a637e6..dc31fed7cd 100644 --- a/Source/Core/DolphinWX/Frame.h +++ b/Source/Core/DolphinWX/Frame.h @@ -105,8 +105,8 @@ public: void OnRenderParentMove(wxMoveEvent& event); bool RendererHasFocus(); bool RendererIsFullscreen(); - void DoFullscreen(bool bF); - void DoExclusiveFullscreen(bool bF); + void DoFullscreen(bool enable_fullscreen); + void DoExclusiveFullscreen(bool enable_fullscreen); void ToggleDisplayMode(bool bFullscreen); static void ConnectWiimote(int wm_idx, bool connect); void UpdateTitle(const std::string& str); diff --git a/Source/Core/VideoBackends/D3D/Render.cpp b/Source/Core/VideoBackends/D3D/Render.cpp index 0653f48afa..7845c84662 100644 --- a/Source/Core/VideoBackends/D3D/Render.cpp +++ b/Source/Core/VideoBackends/D3D/Render.cpp @@ -1255,7 +1255,7 @@ void Renderer::SetFullscreen(bool enable_fullscreen) D3D::SetFullscreenState(enable_fullscreen); } -bool Renderer::IsFullscreen() +bool Renderer::IsFullscreen() const { return D3D::GetFullscreenState(); } diff --git a/Source/Core/VideoBackends/D3D/Render.h b/Source/Core/VideoBackends/D3D/Render.h index bb16316aef..0507b76c80 100644 --- a/Source/Core/VideoBackends/D3D/Render.h +++ b/Source/Core/VideoBackends/D3D/Render.h @@ -26,7 +26,7 @@ public: void SetInterlacingMode() override; void SetViewport() override; void SetFullscreen(bool enable_fullscreen) override; - bool IsFullscreen() override; + bool IsFullscreen() const override; // TODO: Fix confusing names (see ResetAPIState and RestoreAPIState) void ApplyState(bool bUseDstAlpha) override; diff --git a/Source/Core/VideoCommon/RenderBase.h b/Source/Core/VideoCommon/RenderBase.h index 15324f0ab5..3d37b716f9 100644 --- a/Source/Core/VideoCommon/RenderBase.h +++ b/Source/Core/VideoCommon/RenderBase.h @@ -73,7 +73,7 @@ public: virtual void SetInterlacingMode() {} virtual void SetViewport() {} virtual void SetFullscreen(bool enable_fullscreen) {} - virtual bool IsFullscreen() { return false; } + virtual bool IsFullscreen() const { return false; } virtual void ApplyState(bool bUseDstAlpha) {} virtual void RestoreState() {} virtual void ResetAPIState() {}