From 1b70bebb5a67bce1482db0ff9e155e72e9c62056 Mon Sep 17 00:00:00 2001 From: Jules Blok Date: Sun, 15 Jun 2014 12:02:55 +0200 Subject: [PATCH 01/22] Don't create a Panel for a seperate render window. Instead of setting RenderParent to null and raising complexity RenderFrame can be its own parent. --- Source/Core/DolphinWX/Frame.h | 2 +- Source/Core/DolphinWX/FrameTools.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/Core/DolphinWX/Frame.h b/Source/Core/DolphinWX/Frame.h index 900753174e..d4024c8c22 100644 --- a/Source/Core/DolphinWX/Frame.h +++ b/Source/Core/DolphinWX/Frame.h @@ -177,7 +177,7 @@ private: CGameListCtrl* m_GameListCtrl; wxPanel* m_Panel; CRenderFrame* m_RenderFrame; - wxPanel* m_RenderParent; + wxWindow* m_RenderParent; CLogWindow* m_LogWindow; LogConfigWindow* m_LogConfigWindow; FifoPlayerDlg* m_FifoPlayerDlg; diff --git a/Source/Core/DolphinWX/FrameTools.cpp b/Source/Core/DolphinWX/FrameTools.cpp index b33cd4bab1..1885ddb55e 100644 --- a/Source/Core/DolphinWX/FrameTools.cpp +++ b/Source/Core/DolphinWX/FrameTools.cpp @@ -976,7 +976,7 @@ void CFrame::StartGame(const std::string& filename) m_RenderFrame->Bind(wxEVT_CLOSE_WINDOW, &CFrame::OnRenderParentClose, this); m_RenderFrame->Bind(wxEVT_ACTIVATE, &CFrame::OnActive, this); m_RenderFrame->Bind(wxEVT_MOVE, &CFrame::OnRenderParentMove, this); - m_RenderParent = new CPanel(m_RenderFrame, wxID_ANY); + m_RenderParent = m_RenderFrame; m_RenderFrame->Show(); } From 66fec6d0bd8c90a96bbd28773199fba392ea9b2e Mon Sep 17 00:00:00 2001 From: Jules Blok Date: Sun, 15 Jun 2014 12:12:19 +0200 Subject: [PATCH 02/22] Remove CPanel. Let the RenderFrame handle those messages. --- Source/Core/DolphinWX/Frame.cpp | 70 +++++++++------------------------ Source/Core/DolphinWX/Frame.h | 18 --------- 2 files changed, 18 insertions(+), 70 deletions(-) diff --git a/Source/Core/DolphinWX/Frame.cpp b/Source/Core/DolphinWX/Frame.cpp index b57f18ad69..94698837dc 100644 --- a/Source/Core/DolphinWX/Frame.cpp +++ b/Source/Core/DolphinWX/Frame.cpp @@ -78,57 +78,6 @@ extern "C" { #include "DolphinWX/resources/Dolphin.c" // NOLINT: Dolphin icon }; -#ifdef _WIN32 -// I could not use FindItemByHWND() instead of this, it crashed on that occasion I used it */ -HWND MSWGetParent_(HWND Parent) -{ - return GetParent(Parent); -} -#endif - -// --------------- -// The CPanel class to receive MSWWindowProc messages from the video backend. - -BEGIN_EVENT_TABLE(CPanel, wxPanel) -END_EVENT_TABLE() - -CPanel::CPanel( - wxWindow *parent, - wxWindowID id - ) - : wxPanel(parent, id, wxDefaultPosition, wxDefaultSize, 0) // disables wxTAB_TRAVERSAL because it was breaking hotkeys -{ -} - -#ifdef _WIN32 - WXLRESULT CPanel::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam) - { - switch (nMsg) - { - case WM_USER: - switch (wParam) - { - case WM_USER_STOP: - main_frame->DoStop(); - break; - - case WM_USER_SETCURSOR: - if (SConfig::GetInstance().m_LocalCoreStartupParameter.bHideCursor && - main_frame->RendererHasFocus() && Core::GetState() == Core::CORE_RUN) - SetCursor(wxCURSOR_BLANK); - else - SetCursor(wxNullCursor); - break; - } - break; - - default: - // By default let wxWidgets do what it normally does with this event - return wxPanel::MSWWindowProc(nMsg, wParam, lParam); - } - return 0; - } -#endif CRenderFrame::CRenderFrame(wxFrame* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style) @@ -213,6 +162,23 @@ WXLRESULT CRenderFrame::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lPa } break; + case WM_USER: + switch (wParam) + { + case WM_USER_STOP: + main_frame->DoStop(); + break; + + case WM_USER_SETCURSOR: + if (SConfig::GetInstance().m_LocalCoreStartupParameter.bHideCursor && + main_frame->RendererHasFocus() && Core::GetState() == Core::CORE_RUN) + SetCursor(wxCURSOR_BLANK); + else + SetCursor(wxNullCursor); + break; + } + break; + case WM_CLOSE: // Let Core finish initializing before accepting any WM_CLOSE messages if (!Core::IsRunning()) break; @@ -384,7 +350,7 @@ CFrame::CFrame(wxFrame* parent, // --------------- // Main panel // This panel is the parent for rendering and it holds the gamelistctrl - m_Panel = new CPanel(this, IDM_MPANEL); + m_Panel = new wxPanel(this, IDM_MPANEL, wxDefaultPosition, wxDefaultSize, 0); m_GameListCtrl = new CGameListCtrl(m_Panel, LIST_CTRL, wxDefaultPosition, wxDefaultSize, diff --git a/Source/Core/DolphinWX/Frame.h b/Source/Core/DolphinWX/Frame.h index d4024c8c22..3ae9216c11 100644 --- a/Source/Core/DolphinWX/Frame.h +++ b/Source/Core/DolphinWX/Frame.h @@ -50,24 +50,6 @@ class wxListEvent; class wxMenuItem; class wxWindow; -// The CPanel class to receive MSWWindowProc messages from the video backend. -class CPanel : public wxPanel -{ - public: - CPanel( - wxWindow* parent, - wxWindowID id = wxID_ANY - ); - - private: - DECLARE_EVENT_TABLE(); - - #ifdef _WIN32 - // Receive WndProc messages - WXLRESULT MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam); - #endif -}; - class CRenderFrame : public wxFrame { public: From 8d76dca30dd1969bc01a0df8b7b23319d95920d3 Mon Sep 17 00:00:00 2001 From: Jules Blok Date: Sun, 15 Jun 2014 13:13:37 +0200 Subject: [PATCH 03/22] Frame: Make RendererHasFocus() compatible with the new window structure. --- Source/Core/DolphinWX/Frame.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Source/Core/DolphinWX/Frame.cpp b/Source/Core/DolphinWX/Frame.cpp index 94698837dc..763909e26b 100644 --- a/Source/Core/DolphinWX/Frame.cpp +++ b/Source/Core/DolphinWX/Frame.cpp @@ -722,7 +722,11 @@ bool CFrame::RendererHasFocus() if (m_RenderParent == nullptr) return false; #ifdef _WIN32 - if (m_RenderParent->GetParent()->GetHWND() == GetForegroundWindow()) + HWND window = GetForegroundWindow(); + if (window == nullptr) + return false; + + if (m_RenderFrame->GetHWND() == window) return true; #else wxWindow *window = wxWindow::FindFocus(); From c323b386ae8bff134c058985261fc56acbaabef7 Mon Sep 17 00:00:00 2001 From: Jules Blok Date: Tue, 17 Jun 2014 11:15:56 +0200 Subject: [PATCH 04/22] Prevent DXGI from making changes to the window. Prevents DXGI from responding to Alt+Enter and messing up our fullscreen handling. --- Source/Core/VideoBackends/D3D/D3DBase.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Source/Core/VideoBackends/D3D/D3DBase.cpp b/Source/Core/VideoBackends/D3D/D3DBase.cpp index e5e1ae2a83..eac3e7ac59 100644 --- a/Source/Core/VideoBackends/D3D/D3DBase.cpp +++ b/Source/Core/VideoBackends/D3D/D3DBase.cpp @@ -308,6 +308,10 @@ HRESULT Create(HWND wnd) SAFE_RELEASE(swapchain); return E_FAIL; } + + hr = factory->MakeWindowAssociation(wnd, DXGI_MWA_NO_WINDOW_CHANGES); + if (FAILED(hr)) MessageBox(wnd, _T("Failed to associate the window"), _T("Dolphin Direct3D 11 backend"), MB_OK | MB_ICONERROR); + SetDebugObjectName((ID3D11DeviceChild*)context, "device context"); SAFE_RELEASE(factory); SAFE_RELEASE(output); From d72375fdfa0182037afcf0a2e64ea01c16a1b6f3 Mon Sep 17 00:00:00 2001 From: Jules Blok Date: Wed, 18 Jun 2014 15:02:42 +0200 Subject: [PATCH 05/22] D3D: Request desktop resolution before overriding the buffer size. This fixes issues where the wrong refresh rate is selected for some monitors. --- Source/Core/VideoBackends/D3D/D3DBase.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/Source/Core/VideoBackends/D3D/D3DBase.cpp b/Source/Core/VideoBackends/D3D/D3DBase.cpp index eac3e7ac59..d2d2cb3996 100644 --- a/Source/Core/VideoBackends/D3D/D3DBase.cpp +++ b/Source/Core/VideoBackends/D3D/D3DBase.cpp @@ -266,16 +266,21 @@ HRESULT Create(HWND wnd) swap_chain_desc.SampleDesc.Quality = 0; swap_chain_desc.Windowed = TRUE; + DXGI_OUTPUT_DESC out_desc; + memset(&out_desc, 0, sizeof(out_desc)); + output->GetDesc(&out_desc); + DXGI_MODE_DESC mode_desc; memset(&mode_desc, 0, sizeof(mode_desc)); - mode_desc.Width = xres; - mode_desc.Height = yres; + mode_desc.Width = out_desc.DesktopCoordinates.right - out_desc.DesktopCoordinates.left; + mode_desc.Height = out_desc.DesktopCoordinates.bottom - out_desc.DesktopCoordinates.top; mode_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; mode_desc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED; hr = output->FindClosestMatchingMode(&mode_desc, &swap_chain_desc.BufferDesc, nullptr); if (FAILED(hr)) MessageBox(wnd, _T("Failed to find a supported video mode"), _T("Dolphin Direct3D 11 backend"), MB_OK | MB_ICONERROR); - // forcing buffer resolution to xres and yres.. TODO: The new video mode might not actually be supported! + // forcing buffer resolution to xres and yres.. + // this is not a problem as long as we're in windowed mode swap_chain_desc.BufferDesc.Width = xres; swap_chain_desc.BufferDesc.Height = yres; From 77bc87938412d8037439607a0c5047abece62452 Mon Sep 17 00:00:00 2001 From: Jules Blok Date: Wed, 18 Jun 2014 15:04:23 +0200 Subject: [PATCH 06/22] D3D: Add exclusive fullscreen support. --- Source/Core/DolphinWX/Frame.cpp | 2 ++ Source/Core/VideoBackends/D3D/D3DBase.cpp | 3 +++ Source/Core/VideoBackends/D3D/Render.cpp | 8 +++++++- Source/Core/VideoCommon/VideoConfig.cpp | 1 + Source/Core/VideoCommon/VideoConfig.h | 2 +- 5 files changed, 14 insertions(+), 2 deletions(-) diff --git a/Source/Core/DolphinWX/Frame.cpp b/Source/Core/DolphinWX/Frame.cpp index 763909e26b..4c258d5453 100644 --- a/Source/Core/DolphinWX/Frame.cpp +++ b/Source/Core/DolphinWX/Frame.cpp @@ -1206,6 +1206,8 @@ void CFrame::DoFullscreen(bool bF) { m_RenderFrame->Raise(); } + + g_Config.bFullscreen = bF; } const CGameListCtrl *CFrame::GetGameListCtrl() const diff --git a/Source/Core/VideoBackends/D3D/D3DBase.cpp b/Source/Core/VideoBackends/D3D/D3DBase.cpp index d2d2cb3996..a0ec02bf30 100644 --- a/Source/Core/VideoBackends/D3D/D3DBase.cpp +++ b/Source/Core/VideoBackends/D3D/D3DBase.cpp @@ -431,6 +431,9 @@ void Reset() // release all back buffer references SAFE_RELEASE(backbuf); + // apply fullscreen state + D3D::swapchain->SetFullscreenState(g_ActiveConfig.bFullscreen, nullptr); + // resize swapchain buffers RECT client; GetClientRect(hWnd, &client); diff --git a/Source/Core/VideoBackends/D3D/Render.cpp b/Source/Core/VideoBackends/D3D/Render.cpp index 2699b56a46..8741900261 100644 --- a/Source/Core/VideoBackends/D3D/Render.cpp +++ b/Source/Core/VideoBackends/D3D/Render.cpp @@ -42,6 +42,8 @@ static u32 s_LastAA = 0; static Television s_television; +static bool s_LastFS = false; + ID3D11Buffer* access_efb_cbuf = nullptr; ID3D11BlendState* clearblendstates[4] = {nullptr}; ID3D11DepthStencilState* cleardepthstates[3] = {nullptr}; @@ -936,6 +938,8 @@ void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbHeight,const EFBRectangl SetWindowSize(fbWidth, fbHeight); const bool windowResized = CheckForResize(); + const bool fullscreen = g_ActiveConfig.bFullscreen; + const bool fsChanged = s_LastFS != fullscreen; bool xfbchanged = false; @@ -954,13 +958,15 @@ void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbHeight,const EFBRectangl // resize the back buffers NOW to avoid flickering if (xfbchanged || windowResized || + fsChanged || s_LastEFBScale != g_ActiveConfig.iEFBScale || s_LastAA != g_ActiveConfig.iMultisampleMode) { s_LastAA = g_ActiveConfig.iMultisampleMode; + s_LastFS = g_ActiveConfig.bFullscreen; PixelShaderCache::InvalidateMSAAShaders(); - if (windowResized) + if (windowResized || fsChanged) { // TODO: Aren't we still holding a reference to the back buffer right now? D3D::Reset(); diff --git a/Source/Core/VideoCommon/VideoConfig.cpp b/Source/Core/VideoCommon/VideoConfig.cpp index 77e4eb819c..1dc75e4ba2 100644 --- a/Source/Core/VideoCommon/VideoConfig.cpp +++ b/Source/Core/VideoCommon/VideoConfig.cpp @@ -28,6 +28,7 @@ void UpdateActiveConfig() VideoConfig::VideoConfig() { bRunning = false; + bFullscreen = false; // Needed for the first frame, I think fAspectRatioHackW = 1; diff --git a/Source/Core/VideoCommon/VideoConfig.h b/Source/Core/VideoCommon/VideoConfig.h index 595ded24ec..8a7490497f 100644 --- a/Source/Core/VideoCommon/VideoConfig.h +++ b/Source/Core/VideoCommon/VideoConfig.h @@ -57,7 +57,7 @@ struct VideoConfig final // General bool bVSync; - + bool bFullscreen; bool bRunning; bool bWidescreenHack; int iAspectRatio; From 961076a3d51b4336f1ef94b230c79b21108e1ee4 Mon Sep 17 00:00:00 2001 From: Jules Blok Date: Fri, 20 Jun 2014 03:45:42 +0200 Subject: [PATCH 07/22] D3D: Return to windowed mode before destroying the swapchain. --- Source/Core/VideoBackends/D3D/D3DBase.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Source/Core/VideoBackends/D3D/D3DBase.cpp b/Source/Core/VideoBackends/D3D/D3DBase.cpp index a0ec02bf30..573fc8a153 100644 --- a/Source/Core/VideoBackends/D3D/D3DBase.cpp +++ b/Source/Core/VideoBackends/D3D/D3DBase.cpp @@ -351,6 +351,9 @@ HRESULT Create(HWND wnd) void Close() { + // we can't release the swapchain while in fullscreen. + swapchain->SetFullscreenState(false, nullptr); + // release all bound resources context->ClearState(); SAFE_RELEASE(backbuf); From 643c9ff17396354aca27cb206d4563d983dcbee3 Mon Sep 17 00:00:00 2001 From: Jules Blok Date: Tue, 8 Jul 2014 17:44:26 +0200 Subject: [PATCH 08/22] D3D: Initialize the renderer in exclusive fullscreen mode if it is enabled. --- Source/Core/VideoBackends/D3D/D3DBase.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Core/VideoBackends/D3D/D3DBase.cpp b/Source/Core/VideoBackends/D3D/D3DBase.cpp index 573fc8a153..bdb16db465 100644 --- a/Source/Core/VideoBackends/D3D/D3DBase.cpp +++ b/Source/Core/VideoBackends/D3D/D3DBase.cpp @@ -264,7 +264,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 = TRUE; + swap_chain_desc.Windowed = !g_ActiveConfig.bFullscreen; DXGI_OUTPUT_DESC out_desc; memset(&out_desc, 0, sizeof(out_desc)); From 5f04e9c52603da6c29706b706a85e5af95360ba1 Mon Sep 17 00:00:00 2001 From: Jules Blok Date: Fri, 11 Jul 2014 17:08:10 +0200 Subject: [PATCH 09/22] D3D: Make the swapchain available outside of the namespace. This commit reverts a part of pull request #579. --- Source/Core/VideoBackends/D3D/D3DBase.cpp | 2 +- Source/Core/VideoBackends/D3D/D3DBase.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Source/Core/VideoBackends/D3D/D3DBase.cpp b/Source/Core/VideoBackends/D3D/D3DBase.cpp index bdb16db465..945ba19359 100644 --- a/Source/Core/VideoBackends/D3D/D3DBase.cpp +++ b/Source/Core/VideoBackends/D3D/D3DBase.cpp @@ -31,7 +31,7 @@ namespace D3D ID3D11Device* device = nullptr; ID3D11DeviceContext* context = nullptr; -static IDXGISwapChain* swapchain = nullptr; +IDXGISwapChain* swapchain = nullptr; D3D_FEATURE_LEVEL featlevel; D3DTexture2D* backbuf = nullptr; HWND hWnd; diff --git a/Source/Core/VideoBackends/D3D/D3DBase.h b/Source/Core/VideoBackends/D3D/D3DBase.h index dfea8d219a..0188c464e3 100644 --- a/Source/Core/VideoBackends/D3D/D3DBase.h +++ b/Source/Core/VideoBackends/D3D/D3DBase.h @@ -40,6 +40,7 @@ void Close(); extern ID3D11Device* device; extern ID3D11DeviceContext* context; +extern IDXGISwapChain* swapchain; extern HWND hWnd; extern bool bFrameInProgress; From 5837b35add2f9a480d7297b5a6674388625bce20 Mon Sep 17 00:00:00 2001 From: Jules Blok Date: Thu, 10 Jul 2014 22:43:15 +0200 Subject: [PATCH 10/22] Renderer: Restore exclusive mode after focus has been regained. --- Source/Core/VideoBackends/D3D/Render.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/Source/Core/VideoBackends/D3D/Render.cpp b/Source/Core/VideoBackends/D3D/Render.cpp index 8741900261..40b431871b 100644 --- a/Source/Core/VideoBackends/D3D/Render.cpp +++ b/Source/Core/VideoBackends/D3D/Render.cpp @@ -939,7 +939,15 @@ void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbHeight,const EFBRectangl const bool windowResized = CheckForResize(); const bool fullscreen = g_ActiveConfig.bFullscreen; - const bool fsChanged = s_LastFS != fullscreen; + + bool fsChanged = s_LastFS != fullscreen; + + BOOL fsState; + if (SUCCEEDED(D3D::swapchain->GetFullscreenState(&fsState, nullptr)) && !!fsState != fullscreen) + { + // We should be in fullscreen, but we're not. Restore it when we regain focus. + fsChanged = Host_RendererHasFocus(); + } bool xfbchanged = false; From d00e76b3efc83b4e55f5eb35910d82d4cdec824b Mon Sep 17 00:00:00 2001 From: Jules Blok Date: Wed, 16 Jul 2014 22:13:13 +0200 Subject: [PATCH 11/22] Cosmetic changes based on feedback on PR #506. --- Source/Core/VideoBackends/D3D/D3DBase.cpp | 3 +++ Source/Core/VideoBackends/D3D/Render.cpp | 21 ++++++++++++--------- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/Source/Core/VideoBackends/D3D/D3DBase.cpp b/Source/Core/VideoBackends/D3D/D3DBase.cpp index 945ba19359..718ed9eec8 100644 --- a/Source/Core/VideoBackends/D3D/D3DBase.cpp +++ b/Source/Core/VideoBackends/D3D/D3DBase.cpp @@ -314,6 +314,9 @@ HRESULT Create(HWND wnd) return E_FAIL; } + // prevent DXGI from responding to Alt+Enter, unfortunately DXGI_MWA_NO_ALT_ENTER + // does not work so we disable all monitoring of window messages. However this + // may make it more difficult for DXGI to handle display mode changes. hr = factory->MakeWindowAssociation(wnd, DXGI_MWA_NO_WINDOW_CHANGES); if (FAILED(hr)) MessageBox(wnd, _T("Failed to associate the window"), _T("Dolphin Direct3D 11 backend"), MB_OK | MB_ICONERROR); diff --git a/Source/Core/VideoBackends/D3D/Render.cpp b/Source/Core/VideoBackends/D3D/Render.cpp index 40b431871b..8311310fb1 100644 --- a/Source/Core/VideoBackends/D3D/Render.cpp +++ b/Source/Core/VideoBackends/D3D/Render.cpp @@ -42,7 +42,7 @@ static u32 s_LastAA = 0; static Television s_television; -static bool s_LastFS = false; +static bool s_last_fullscreen_mode = false; ID3D11Buffer* access_efb_cbuf = nullptr; ID3D11BlendState* clearblendstates[4] = {nullptr}; @@ -940,13 +940,16 @@ void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbHeight,const EFBRectangl const bool windowResized = CheckForResize(); const bool fullscreen = g_ActiveConfig.bFullscreen; - bool fsChanged = s_LastFS != fullscreen; + bool fullscreen_changed = s_last_fullscreen_mode != fullscreen; - BOOL fsState; - if (SUCCEEDED(D3D::swapchain->GetFullscreenState(&fsState, nullptr)) && !!fsState != fullscreen) + BOOL fullscreen_state; + if (SUCCEEDED(D3D::swapchain->GetFullscreenState(&fullscreen_state, nullptr))) { - // We should be in fullscreen, but we're not. Restore it when we regain focus. - fsChanged = Host_RendererHasFocus(); + if (!!fullscreen_state != fullscreen) + { + // We should be in fullscreen, but we're not. Restore it when we regain focus. + fullscreen_changed = Host_RendererHasFocus(); + } } bool xfbchanged = false; @@ -966,15 +969,15 @@ void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbHeight,const EFBRectangl // resize the back buffers NOW to avoid flickering if (xfbchanged || windowResized || - fsChanged || + fullscreen_changed || s_LastEFBScale != g_ActiveConfig.iEFBScale || s_LastAA != g_ActiveConfig.iMultisampleMode) { s_LastAA = g_ActiveConfig.iMultisampleMode; - s_LastFS = g_ActiveConfig.bFullscreen; + s_last_fullscreen_mode = fullscreen; PixelShaderCache::InvalidateMSAAShaders(); - if (windowResized || fsChanged) + if (windowResized || fullscreen_changed) { // TODO: Aren't we still holding a reference to the back buffer right now? D3D::Reset(); From 9064bf147d3a805e82f386aca9becc7f32b51ef8 Mon Sep 17 00:00:00 2001 From: Jules Blok Date: Fri, 11 Jul 2014 15:26:38 +0200 Subject: [PATCH 12/22] D3D: Don't set the windowed mode size when we initialize in fullscreen. --- Source/Core/VideoBackends/D3D/D3DBase.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/Source/Core/VideoBackends/D3D/D3DBase.cpp b/Source/Core/VideoBackends/D3D/D3DBase.cpp index 718ed9eec8..1d03e9b33b 100644 --- a/Source/Core/VideoBackends/D3D/D3DBase.cpp +++ b/Source/Core/VideoBackends/D3D/D3DBase.cpp @@ -279,10 +279,13 @@ HRESULT Create(HWND wnd) hr = output->FindClosestMatchingMode(&mode_desc, &swap_chain_desc.BufferDesc, nullptr); if (FAILED(hr)) MessageBox(wnd, _T("Failed to find a supported video mode"), _T("Dolphin Direct3D 11 backend"), MB_OK | MB_ICONERROR); - // forcing buffer resolution to xres and yres.. - // this is not a problem as long as we're in windowed mode - swap_chain_desc.BufferDesc.Width = xres; - swap_chain_desc.BufferDesc.Height = yres; + if (swap_chain_desc.Windowed) + { + // forcing buffer resolution to xres and yres.. + // this is not a problem as long as we're in windowed mode + swap_chain_desc.BufferDesc.Width = xres; + swap_chain_desc.BufferDesc.Height = yres; + } #if defined(_DEBUG) || defined(DEBUGFAST) // Creating debug devices can sometimes fail if the user doesn't have the correct From 340087199248917139169b157a1b141b348ad972 Mon Sep 17 00:00:00 2001 From: Jules Blok Date: Fri, 11 Jul 2014 15:53:55 +0200 Subject: [PATCH 13/22] Renderer: Don't attempt to switch to exclusive fullscreen if "render to main" is enabled. --- Source/Core/VideoBackends/D3D/Render.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Core/VideoBackends/D3D/Render.cpp b/Source/Core/VideoBackends/D3D/Render.cpp index 8311310fb1..183a4e16c3 100644 --- a/Source/Core/VideoBackends/D3D/Render.cpp +++ b/Source/Core/VideoBackends/D3D/Render.cpp @@ -938,7 +938,7 @@ void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbHeight,const EFBRectangl SetWindowSize(fbWidth, fbHeight); const bool windowResized = CheckForResize(); - const bool fullscreen = g_ActiveConfig.bFullscreen; + const bool fullscreen = g_ActiveConfig.bFullscreen && !SConfig::GetInstance().m_LocalCoreStartupParameter.bRenderToMain; bool fullscreen_changed = s_last_fullscreen_mode != fullscreen; From cd94ff19663ad1d0bb65395d8b822b56d3603863 Mon Sep 17 00:00:00 2001 From: Jules Blok Date: Sat, 19 Jul 2014 20:18:03 +0200 Subject: [PATCH 14/22] VideoConfig: Add "Borderless Fullscreen" option. This option will disable exclusive fullscreen for users who prefer the old behaviour. --- Source/Core/DolphinWX/VideoConfigDiag.cpp | 6 ++++++ Source/Core/DolphinWX/VideoConfigDiag.h | 5 +++++ Source/Core/VideoBackends/D3D/Render.cpp | 3 ++- Source/Core/VideoBackends/D3D/main.cpp | 1 + Source/Core/VideoBackends/OGL/main.cpp | 1 + Source/Core/VideoCommon/VideoConfig.cpp | 4 ++++ Source/Core/VideoCommon/VideoConfig.h | 2 ++ 7 files changed, 21 insertions(+), 1 deletion(-) diff --git a/Source/Core/DolphinWX/VideoConfigDiag.cpp b/Source/Core/DolphinWX/VideoConfigDiag.cpp index 00fab2bb6a..07c1f1e588 100644 --- a/Source/Core/DolphinWX/VideoConfigDiag.cpp +++ b/Source/Core/DolphinWX/VideoConfigDiag.cpp @@ -114,6 +114,7 @@ static wxString pixel_lighting_desc = wxTRANSLATE("Calculate lighting of 3D grap static wxString fast_depth_calc_desc = wxTRANSLATE("Use a less accurate algorithm to calculate depth values.\nCauses issues in a few games but might give a decent speedup.\n\nIf unsure, leave this checked."); static wxString force_filtering_desc = wxTRANSLATE("Force texture filtering even if the emulated game explicitly disabled it.\nImproves texture quality slightly but causes glitches in some games.\n\nIf unsure, leave this unchecked."); static wxString _3d_vision_desc = wxTRANSLATE("Enable 3D effects via stereoscopy using Nvidia 3D Vision technology if it's supported by your GPU.\nPossibly causes issues.\nRequires fullscreen to work.\n\nIf unsure, leave this unchecked."); +static wxString borderless_fullscreen_desc = wxTRANSLATE("Don't use exclusive mode when in fullscreen.\nAllows for faster transitions between fullscreen and windowed mode.\nIncreases input latency, makes movement less smooth and slightly decreases performance.\nExclusive mode is required to support 3D Vision.\n\nIf unsure, leave this unchecked."); static wxString internal_res_desc = wxTRANSLATE("Specifies the resolution used to render at. A high resolution will improve visual quality a lot but is also quite heavy on performance and might cause glitches in certain games.\n\"Multiple of 640x528\" is a bit slower than \"Window Size\" but yields less issues. Generally speaking, the lower the internal resolution is, the better your performance will be.\n\nIf unsure, select 640x528."); static wxString efb_access_desc = wxTRANSLATE("Ignore any requests of the CPU to read from or write to the EFB.\nImproves performance in some games, but might disable some gameplay-related features or graphical effects.\n\nIf unsure, leave this unchecked."); static wxString efb_emulate_format_changes_desc = wxTRANSLATE("Ignore any changes to the EFB format.\nImproves performance in many games without any negative effect. Causes graphical defects in a small number of other games though.\n\nIf unsure, leave this checked."); @@ -584,6 +585,11 @@ VideoConfigDiag::VideoConfigDiag(wxWindow* parent, const std::string &title, con szr_misc->Add(cb_prog_scan); } + // Borderless Fullscreen + borderless_fullscreen = CreateCheckBox(page_advanced, _("Borderless Fullscreen"), wxGetTranslation(borderless_fullscreen_desc), vconfig.bForceBorderlessFullscreen); + borderless_fullscreen->Show(vconfig.backend_info.bSupportsExclusiveFullscreen); + szr_misc->Add(borderless_fullscreen); + wxStaticBoxSizer* const group_misc = new wxStaticBoxSizer(wxVERTICAL, page_advanced, _("Misc")); szr_advanced->Add(group_misc, 0, wxEXPAND | wxALL, 5); group_misc->Add(szr_misc, 1, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, 5); diff --git a/Source/Core/DolphinWX/VideoConfigDiag.h b/Source/Core/DolphinWX/VideoConfigDiag.h index c17506351b..2906729757 100644 --- a/Source/Core/DolphinWX/VideoConfigDiag.h +++ b/Source/Core/DolphinWX/VideoConfigDiag.h @@ -159,6 +159,10 @@ protected: _3d_vision->Enable(vconfig.backend_info.bSupports3DVision); _3d_vision->Show(vconfig.backend_info.bSupports3DVision); + // Borderless Fullscreen + borderless_fullscreen->Enable(vconfig.backend_info.bSupportsExclusiveFullscreen); + borderless_fullscreen->Show(vconfig.backend_info.bSupportsExclusiveFullscreen); + // EFB copy efbcopy_texture->Enable(vconfig.bEFBCopyEnable); efbcopy_ram->Enable(vconfig.bEFBCopyEnable); @@ -189,6 +193,7 @@ protected: SettingChoice* choice_aamode; SettingCheckBox* _3d_vision; + SettingCheckBox* borderless_fullscreen; SettingRadioButton* efbcopy_texture; SettingRadioButton* efbcopy_ram; diff --git a/Source/Core/VideoBackends/D3D/Render.cpp b/Source/Core/VideoBackends/D3D/Render.cpp index 183a4e16c3..a7b2c56212 100644 --- a/Source/Core/VideoBackends/D3D/Render.cpp +++ b/Source/Core/VideoBackends/D3D/Render.cpp @@ -938,7 +938,8 @@ void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbHeight,const EFBRectangl SetWindowSize(fbWidth, fbHeight); const bool windowResized = CheckForResize(); - const bool fullscreen = g_ActiveConfig.bFullscreen && !SConfig::GetInstance().m_LocalCoreStartupParameter.bRenderToMain; + const bool fullscreen = g_ActiveConfig.bFullscreen && !g_ActiveConfig.bForceBorderlessFullscreen && + !SConfig::GetInstance().m_LocalCoreStartupParameter.bRenderToMain; bool fullscreen_changed = s_last_fullscreen_mode != fullscreen; diff --git a/Source/Core/VideoBackends/D3D/main.cpp b/Source/Core/VideoBackends/D3D/main.cpp index be2173cdcf..504951e684 100644 --- a/Source/Core/VideoBackends/D3D/main.cpp +++ b/Source/Core/VideoBackends/D3D/main.cpp @@ -85,6 +85,7 @@ void InitBackendInfo() g_Config.backend_info.bUseRGBATextures = true; // the GX formats barely match any D3D11 formats g_Config.backend_info.bUseMinimalMipCount = true; g_Config.backend_info.bSupports3DVision = false; + g_Config.backend_info.bSupportsExclusiveFullscreen = true; g_Config.backend_info.bSupportsDualSourceBlend = true; g_Config.backend_info.bSupportsPrimitiveRestart = true; g_Config.backend_info.bSupportsOversizedViewports = false; diff --git a/Source/Core/VideoBackends/OGL/main.cpp b/Source/Core/VideoBackends/OGL/main.cpp index fb4079a9c8..0c7e90e097 100644 --- a/Source/Core/VideoBackends/OGL/main.cpp +++ b/Source/Core/VideoBackends/OGL/main.cpp @@ -144,6 +144,7 @@ static void InitBackendInfo() g_Config.backend_info.bUseRGBATextures = true; g_Config.backend_info.bUseMinimalMipCount = false; g_Config.backend_info.bSupports3DVision = false; + g_Config.backend_info.bSupportsExclusiveFullscreen = false; //g_Config.backend_info.bSupportsDualSourceBlend = true; // is gpu dependent and must be set in renderer //g_Config.backend_info.bSupportsEarlyZ = true; // is gpu dependent and must be set in renderer g_Config.backend_info.bSupportsOversizedViewports = true; diff --git a/Source/Core/VideoCommon/VideoConfig.cpp b/Source/Core/VideoCommon/VideoConfig.cpp index 1dc75e4ba2..d995ae2d4b 100644 --- a/Source/Core/VideoCommon/VideoConfig.cpp +++ b/Source/Core/VideoCommon/VideoConfig.cpp @@ -39,6 +39,7 @@ VideoConfig::VideoConfig() backend_info.bUseRGBATextures = false; backend_info.bUseMinimalMipCount = false; backend_info.bSupports3DVision = false; + backend_info.bSupportsExclusiveFullscreen = false; } void VideoConfig::Load(const std::string& ini_file) @@ -83,6 +84,7 @@ void VideoConfig::Load(const std::string& ini_file) settings->Get("DisableFog", &bDisableFog, 0); settings->Get("OMPDecoder", &bOMPDecoder, false); settings->Get("EnableShaderDebugging", &bEnableShaderDebugging, false); + settings->Get("ForceBorderlessFullscreen", &bForceBorderlessFullscreen, false); IniFile::Section* enhancements = iniFile.GetOrCreateSection("Enhancements"); enhancements->Get("ForceFiltering", &bForceFiltering, 0); @@ -211,6 +213,7 @@ void VideoConfig::VerifyValidity() if (iAdapter < 0 || iAdapter > ((int)backend_info.Adapters.size() - 1)) iAdapter = 0; if (iMultisampleMode < 0 || iMultisampleMode >= (int)backend_info.AAModes.size()) iMultisampleMode = 0; if (!backend_info.bSupports3DVision) b3DVision = false; + if (!backend_info.bSupportsExclusiveFullscreen) bForceBorderlessFullscreen = false; } void VideoConfig::Save(const std::string& ini_file) @@ -255,6 +258,7 @@ void VideoConfig::Save(const std::string& ini_file) settings->Set("DisableFog", bDisableFog); settings->Set("OMPDecoder", bOMPDecoder); settings->Set("EnableShaderDebugging", bEnableShaderDebugging); + settings->Set("ForceBorderlessFullscreen", bForceBorderlessFullscreen); IniFile::Section* enhancements = iniFile.GetOrCreateSection("Enhancements"); enhancements->Set("ForceFiltering", bForceFiltering); diff --git a/Source/Core/VideoCommon/VideoConfig.h b/Source/Core/VideoCommon/VideoConfig.h index 8a7490497f..d2c5f1eaae 100644 --- a/Source/Core/VideoCommon/VideoConfig.h +++ b/Source/Core/VideoCommon/VideoConfig.h @@ -101,6 +101,7 @@ struct VideoConfig final int iAnaglyphStereoSeparation; int iAnaglyphFocalAngle; bool b3DVision; + bool bForceBorderlessFullscreen; // Hacks bool bEFBAccessEnable; @@ -140,6 +141,7 @@ struct VideoConfig final bool bUseRGBATextures; // used for D3D in TextureCache bool bUseMinimalMipCount; bool bSupports3DVision; + bool bSupportsExclusiveFullscreen; bool bSupportsDualSourceBlend; bool bSupportsPrimitiveRestart; bool bSupportsOversizedViewports; From 36ea1890c8d1b6084a5bc2e80093878af400810a Mon Sep 17 00:00:00 2001 From: Jules Blok Date: Wed, 16 Jul 2014 15:53:33 +0200 Subject: [PATCH 15/22] Let the Renderer decide when to exit fullscreen. This ensures the transition from/to exclusive mode happens while the RenderFrame is fullscreen. This prevents fullscreen loops and relieves us of having to restore the window size after we exit fullscreen. --- Source/Core/Core/Host.h | 1 + Source/Core/DolphinWX/Frame.cpp | 18 +++++++++++++++++- Source/Core/DolphinWX/Globals.h | 1 + Source/Core/DolphinWX/Main.cpp | 7 +++++++ Source/Core/DolphinWX/MainAndroid.cpp | 3 +++ Source/Core/DolphinWX/MainNoGUI.cpp | 3 +++ Source/Core/VideoBackends/D3D/D3DBase.cpp | 3 --- Source/Core/VideoBackends/D3D/Render.cpp | 9 ++++++++- 8 files changed, 40 insertions(+), 5 deletions(-) diff --git a/Source/Core/Core/Host.h b/Source/Core/Core/Host.h index 32061242f2..fe9ff11a6d 100644 --- a/Source/Core/Core/Host.h +++ b/Source/Core/Core/Host.h @@ -31,6 +31,7 @@ void Host_Message(int Id); void Host_NotifyMapLoaded(); void Host_RefreshDSPDebuggerWindow(); void Host_RequestRenderWindowSize(int width, int height); +void Host_RequestFullscreen(bool fullscreen); void Host_SetStartupDebuggingParameters(); void Host_SetWiiMoteConnectionState(int _State); void Host_ShowJitResults(unsigned int address); diff --git a/Source/Core/DolphinWX/Frame.cpp b/Source/Core/DolphinWX/Frame.cpp index 4c258d5453..25a09d13e1 100644 --- a/Source/Core/DolphinWX/Frame.cpp +++ b/Source/Core/DolphinWX/Frame.cpp @@ -640,6 +640,11 @@ void CFrame::OnHostMessage(wxCommandEvent& event) } break; + case IDM_FULLSCREENREQUEST: + if (m_RenderFrame != nullptr) + m_RenderFrame->ShowFullScreen(event.GetInt() == 0 ? false : true); + break; + case WM_USER_CREATE: if (SConfig::GetInstance().m_LocalCoreStartupParameter.bHideCursor) m_RenderParent->SetCursor(wxCURSOR_BLANK); @@ -1185,7 +1190,18 @@ void CFrame::DoFullscreen(bool bF) [window toggleFullScreen:nil]; } #else - m_RenderFrame->ShowFullScreen(bF, wxFULLSCREEN_ALL); + if (bF) + { + m_RenderFrame->ShowFullScreen(true, wxFULLSCREEN_ALL); + } + else if (!g_ActiveConfig.backend_info.bSupportsExclusiveFullscreen || + SConfig::GetInstance().m_LocalCoreStartupParameter.bRenderToMain || + g_ActiveConfig.bForceBorderlessFullscreen) + { + // Exiting exclusive fullscreen should be done from a Renderer callback. + // Therefore we don't exit fullscreen from here if we support exclusive mode. + m_RenderFrame->ShowFullScreen(false, wxFULLSCREEN_ALL); + } #endif if (SConfig::GetInstance().m_LocalCoreStartupParameter.bRenderToMain) diff --git a/Source/Core/DolphinWX/Globals.h b/Source/Core/DolphinWX/Globals.h index 401f4265ad..2a8fc02854 100644 --- a/Source/Core/DolphinWX/Globals.h +++ b/Source/Core/DolphinWX/Globals.h @@ -256,6 +256,7 @@ enum IDM_WINDOWSIZEREQUEST, IDM_STOPPED, IDM_HOST_MESSAGE, + IDM_FULLSCREENREQUEST, IDM_MPANEL, ID_STATUSBAR, diff --git a/Source/Core/DolphinWX/Main.cpp b/Source/Core/DolphinWX/Main.cpp index ad6d049635..712aca5895 100644 --- a/Source/Core/DolphinWX/Main.cpp +++ b/Source/Core/DolphinWX/Main.cpp @@ -627,6 +627,13 @@ void Host_RequestRenderWindowSize(int width, int height) main_frame->GetEventHandler()->AddPendingEvent(event); } +void Host_RequestFullscreen(bool fullscreen) +{ + wxCommandEvent event(wxEVT_HOST_COMMAND, IDM_FULLSCREENREQUEST); + event.SetInt(fullscreen ? 1 : 0); + main_frame->GetEventHandler()->AddPendingEvent(event); +} + void Host_SetStartupDebuggingParameters() { SCoreStartupParameter& StartUp = SConfig::GetInstance().m_LocalCoreStartupParameter; diff --git a/Source/Core/DolphinWX/MainAndroid.cpp b/Source/Core/DolphinWX/MainAndroid.cpp index d24be7f954..cdbc2a0785 100644 --- a/Source/Core/DolphinWX/MainAndroid.cpp +++ b/Source/Core/DolphinWX/MainAndroid.cpp @@ -94,6 +94,9 @@ void Host_GetRenderWindowSize(int& x, int& y, int& width, int& height) } void Host_RequestRenderWindowSize(int width, int height) {} + +void Host_RequestFullscreen(bool fullscreen) {} + void Host_SetStartupDebuggingParameters() { } diff --git a/Source/Core/DolphinWX/MainNoGUI.cpp b/Source/Core/DolphinWX/MainNoGUI.cpp index 351d818c2c..ee532f702a 100644 --- a/Source/Core/DolphinWX/MainNoGUI.cpp +++ b/Source/Core/DolphinWX/MainNoGUI.cpp @@ -88,6 +88,9 @@ void Host_GetRenderWindowSize(int& x, int& y, int& width, int& height) } void Host_RequestRenderWindowSize(int width, int height) {} + +void Host_RequestFullscreen(bool fullscreen) {} + void Host_SetStartupDebuggingParameters() { SCoreStartupParameter& StartUp = SConfig::GetInstance().m_LocalCoreStartupParameter; diff --git a/Source/Core/VideoBackends/D3D/D3DBase.cpp b/Source/Core/VideoBackends/D3D/D3DBase.cpp index 1d03e9b33b..21226e442c 100644 --- a/Source/Core/VideoBackends/D3D/D3DBase.cpp +++ b/Source/Core/VideoBackends/D3D/D3DBase.cpp @@ -440,9 +440,6 @@ void Reset() // release all back buffer references SAFE_RELEASE(backbuf); - // apply fullscreen state - D3D::swapchain->SetFullscreenState(g_ActiveConfig.bFullscreen, nullptr); - // resize swapchain buffers RECT client; GetClientRect(hWnd, &client); diff --git a/Source/Core/VideoBackends/D3D/Render.cpp b/Source/Core/VideoBackends/D3D/Render.cpp index a7b2c56212..ae23516d5c 100644 --- a/Source/Core/VideoBackends/D3D/Render.cpp +++ b/Source/Core/VideoBackends/D3D/Render.cpp @@ -975,11 +975,18 @@ void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbHeight,const EFBRectangl s_LastAA != g_ActiveConfig.iMultisampleMode) { s_LastAA = g_ActiveConfig.iMultisampleMode; - s_last_fullscreen_mode = fullscreen; PixelShaderCache::InvalidateMSAAShaders(); if (windowResized || fullscreen_changed) { + // apply fullscreen state + if (fullscreen_changed) + { + s_last_fullscreen_mode = fullscreen; + D3D::swapchain->SetFullscreenState(fullscreen, nullptr); + Host_RequestFullscreen(fullscreen); + } + // TODO: Aren't we still holding a reference to the back buffer right now? D3D::Reset(); SAFE_RELEASE(s_screenshot_texture); From 009b4dd3764a983ba5e9476383ea07430cdff8cb Mon Sep 17 00:00:00 2001 From: Jules Blok Date: Mon, 21 Jul 2014 17:55:21 +0200 Subject: [PATCH 16/22] Exit exclusive fullscreen when the stop confirmation is shown. Also have the renderer remember its own fullscreen state. This is done to prevent a case where we exit exclusive fullscreen through the configuration and a focus shift at the same time. In this case the renderer would fail to detect that the fullscreen state was changed. --- Source/Core/DolphinWX/Frame.cpp | 9 ++++---- Source/Core/DolphinWX/Frame.h | 1 + Source/Core/DolphinWX/FrameTools.cpp | 26 +++++++++++++++++------- Source/Core/VideoBackends/D3D/Render.cpp | 4 ++-- Source/Core/VideoCommon/VideoConfig.h | 1 + 5 files changed, 28 insertions(+), 13 deletions(-) diff --git a/Source/Core/DolphinWX/Frame.cpp b/Source/Core/DolphinWX/Frame.cpp index 25a09d13e1..d849324a9f 100644 --- a/Source/Core/DolphinWX/Frame.cpp +++ b/Source/Core/DolphinWX/Frame.cpp @@ -316,7 +316,7 @@ CFrame::CFrame(wxFrame* parent, , m_LogWindow(nullptr), m_LogConfigWindow(nullptr) , m_FifoPlayerDlg(nullptr), UseDebugger(_UseDebugger) , m_bBatchMode(_BatchMode), m_bEdit(false), m_bTabSplit(false), m_bNoDocking(false) - , m_bGameLoading(false), m_bClosing(false) + , m_bGameLoading(false), m_bClosing(false), m_confirmStop(false) { for (int i = 0; i <= IDM_CODEWINDOW - IDM_LOGWINDOW; i++) bFloatWindow[i] = false; @@ -643,6 +643,8 @@ void CFrame::OnHostMessage(wxCommandEvent& event) case IDM_FULLSCREENREQUEST: if (m_RenderFrame != nullptr) m_RenderFrame->ShowFullScreen(event.GetInt() == 0 ? false : true); + if (m_confirmStop) + Core::SetState(Core::CORE_PAUSE); break; case WM_USER_CREATE: @@ -1194,9 +1196,8 @@ void CFrame::DoFullscreen(bool bF) { m_RenderFrame->ShowFullScreen(true, wxFULLSCREEN_ALL); } - else if (!g_ActiveConfig.backend_info.bSupportsExclusiveFullscreen || - SConfig::GetInstance().m_LocalCoreStartupParameter.bRenderToMain || - g_ActiveConfig.bForceBorderlessFullscreen) + else if (!g_Config.ExclusiveFullscreenEnabled() || + SConfig::GetInstance().m_LocalCoreStartupParameter.bRenderToMain) { // Exiting exclusive fullscreen should be done from a Renderer callback. // Therefore we don't exit fullscreen from here if we support exclusive mode. diff --git a/Source/Core/DolphinWX/Frame.h b/Source/Core/DolphinWX/Frame.h index 3ae9216c11..cbf9209d65 100644 --- a/Source/Core/DolphinWX/Frame.h +++ b/Source/Core/DolphinWX/Frame.h @@ -170,6 +170,7 @@ private: bool m_bNoDocking; bool m_bGameLoading; bool m_bClosing; + bool m_confirmStop; std::vector drives; diff --git a/Source/Core/DolphinWX/FrameTools.cpp b/Source/Core/DolphinWX/FrameTools.cpp index 1885ddb55e..937809e050 100644 --- a/Source/Core/DolphinWX/FrameTools.cpp +++ b/Source/Core/DolphinWX/FrameTools.cpp @@ -95,6 +95,7 @@ Core::GetWindowHandle(). #include "InputCommon/ControllerInterface/ControllerInterface.h" #include "VideoCommon/VideoBackendBase.h" +#include "VideoCommon/VideoConfig.h" #ifdef _WIN32 #ifndef SM_XVIRTUALSCREEN @@ -119,8 +120,6 @@ extern "C" { class InputPlugin; class wxFrame; -static bool confirmStop = false; - // Create menu items // --------------------- void CFrame::CreateMenu() @@ -1082,11 +1081,11 @@ void CFrame::DoStop() { if (!Core::IsRunningAndStarted()) return; - if (confirmStop) + if (m_confirmStop) return; // don't let this function run again until it finishes, or is aborted. - confirmStop = true; + m_confirmStop = true; m_bGameLoading = false; if (Core::GetState() != Core::CORE_UNINITIALIZED || @@ -1100,8 +1099,21 @@ void CFrame::DoStop() // Ask for confirmation in case the user accidentally clicked Stop / Escape if (SConfig::GetInstance().m_LocalCoreStartupParameter.bConfirmStop) { + // Pause the state during confirmation and restore it afterwards Core::EState state = Core::GetState(); - Core::SetState(Core::CORE_PAUSE); + + // 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. + if (!RendererIsFullscreen() || !g_Config.ExclusiveFullscreenEnabled() || + SConfig::GetInstance().m_LocalCoreStartupParameter.bRenderToMain) + { + Core::SetState(Core::CORE_PAUSE); + } + else + { + DoFullscreen(false); + } + wxMessageDialog m_StopDlg( this, _("Do you want to stop the current emulation?"), @@ -1113,7 +1125,7 @@ void CFrame::DoStop() if (Ret != wxID_YES) { Core::SetState(state); - confirmStop = false; + m_confirmStop = false; return; } } @@ -1135,7 +1147,7 @@ void CFrame::OnStopped() { wxEndBusyCursor(); - confirmStop = false; + m_confirmStop = false; #if defined(HAVE_X11) && HAVE_X11 if (SConfig::GetInstance().m_LocalCoreStartupParameter.bDisableScreenSaver) diff --git a/Source/Core/VideoBackends/D3D/Render.cpp b/Source/Core/VideoBackends/D3D/Render.cpp index ae23516d5c..40b316787f 100644 --- a/Source/Core/VideoBackends/D3D/Render.cpp +++ b/Source/Core/VideoBackends/D3D/Render.cpp @@ -946,10 +946,10 @@ void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbHeight,const EFBRectangl BOOL fullscreen_state; if (SUCCEEDED(D3D::swapchain->GetFullscreenState(&fullscreen_state, nullptr))) { - if (!!fullscreen_state != fullscreen) + if (!!fullscreen_state != fullscreen && Host_RendererHasFocus()) { // We should be in fullscreen, but we're not. Restore it when we regain focus. - fullscreen_changed = Host_RendererHasFocus(); + fullscreen_changed = true; } } diff --git a/Source/Core/VideoCommon/VideoConfig.h b/Source/Core/VideoCommon/VideoConfig.h index d2c5f1eaae..34d4f314c5 100644 --- a/Source/Core/VideoCommon/VideoConfig.h +++ b/Source/Core/VideoCommon/VideoConfig.h @@ -154,6 +154,7 @@ struct VideoConfig final bool VirtualXFBEnabled() const { return bUseXFB && !bUseRealXFB; } bool EFBCopiesToTextureEnabled() const { return bEFBCopyEnable && bCopyEFBToTexture; } bool EFBCopiesToRamEnabled() const { return bEFBCopyEnable && !bCopyEFBToTexture; } + bool ExclusiveFullscreenEnabled() const { return backend_info.bSupportsExclusiveFullscreen && !bForceBorderlessFullscreen; } }; extern VideoConfig g_Config; From 0c81494c895d7cc6741062e77b5efd11b8009eec Mon Sep 17 00:00:00 2001 From: Jules Blok Date: Mon, 21 Jul 2014 19:56:52 +0200 Subject: [PATCH 17/22] Frame: Make the fullscreen transitions more reliable. --- Source/Core/DolphinWX/Frame.cpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/Source/Core/DolphinWX/Frame.cpp b/Source/Core/DolphinWX/Frame.cpp index d849324a9f..dc0eeeb8e6 100644 --- a/Source/Core/DolphinWX/Frame.cpp +++ b/Source/Core/DolphinWX/Frame.cpp @@ -450,7 +450,7 @@ bool CFrame::RendererIsFullscreen() if (Core::GetState() == Core::CORE_RUN || Core::GetState() == Core::CORE_PAUSE) { - fullscreen = m_RenderFrame->IsFullScreen(); + fullscreen = m_RenderFrame->IsFullScreen() && g_Config.bFullscreen; } #if defined(__APPLE__) @@ -641,10 +641,14 @@ void CFrame::OnHostMessage(wxCommandEvent& event) break; case IDM_FULLSCREENREQUEST: - if (m_RenderFrame != nullptr) - m_RenderFrame->ShowFullScreen(event.GetInt() == 0 ? false : true); - if (m_confirmStop) - Core::SetState(Core::CORE_PAUSE); + { + bool fullscreen = event.GetInt() == 0 ? false : true; + ToggleDisplayMode(fullscreen); + if (m_RenderFrame != nullptr) + m_RenderFrame->ShowFullScreen(fullscreen); + if (m_confirmStop) + Core::SetState(Core::CORE_PAUSE); + } break; case WM_USER_CREATE: From 4b3d57957333288a16451f23db28af60d34b121f Mon Sep 17 00:00:00 2001 From: Jules Blok Date: Mon, 21 Jul 2014 20:10:54 +0200 Subject: [PATCH 18/22] Renderer: Only notify the host when exiting fullscreen --- Source/Core/VideoBackends/D3D/Render.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Source/Core/VideoBackends/D3D/Render.cpp b/Source/Core/VideoBackends/D3D/Render.cpp index 40b316787f..1f883c18fe 100644 --- a/Source/Core/VideoBackends/D3D/Render.cpp +++ b/Source/Core/VideoBackends/D3D/Render.cpp @@ -984,7 +984,12 @@ void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbHeight,const EFBRectangl { s_last_fullscreen_mode = fullscreen; D3D::swapchain->SetFullscreenState(fullscreen, nullptr); - Host_RequestFullscreen(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? From bd9953d97ef45e165d0fb555efa29957c3bb8e82 Mon Sep 17 00:00:00 2001 From: Jules Blok Date: Sat, 26 Jul 2014 12:45:10 +0200 Subject: [PATCH 19/22] Remove the 3D Vision hack. The hack was needed because the Nvidia 3D Vision heuristics are documented to only support surfaces that are the same size as the backbuffer. This would be the case if you enabled the hack and selected the "Auto (Window Size)" internal resolution. However, on recent drivers the same effect is achieved by selecting the "Auto (Multiple)" internal resolution. Therefore the hack is no longer required. --- Source/Core/DolphinWX/VideoConfigDiag.cpp | 9 +-------- Source/Core/DolphinWX/VideoConfigDiag.h | 5 ----- Source/Core/VideoBackends/D3D/main.cpp | 1 - Source/Core/VideoBackends/OGL/main.cpp | 1 - .../VideoCommon/FramebufferManagerBase.cpp | 20 ++----------------- Source/Core/VideoCommon/VideoConfig.cpp | 5 ----- Source/Core/VideoCommon/VideoConfig.h | 1 - 7 files changed, 3 insertions(+), 39 deletions(-) diff --git a/Source/Core/DolphinWX/VideoConfigDiag.cpp b/Source/Core/DolphinWX/VideoConfigDiag.cpp index 07c1f1e588..d128b8854e 100644 --- a/Source/Core/DolphinWX/VideoConfigDiag.cpp +++ b/Source/Core/DolphinWX/VideoConfigDiag.cpp @@ -113,7 +113,6 @@ static wxString scaled_efb_copy_desc = wxTRANSLATE("Greatly increases quality of static wxString pixel_lighting_desc = wxTRANSLATE("Calculate lighting of 3D graphics per-pixel rather than per vertex.\nDecreases emulation speed by some percent (depending on your GPU).\nThis usually is a safe enhancement, but might cause issues sometimes.\n\nIf unsure, leave this unchecked."); static wxString fast_depth_calc_desc = wxTRANSLATE("Use a less accurate algorithm to calculate depth values.\nCauses issues in a few games but might give a decent speedup.\n\nIf unsure, leave this checked."); static wxString force_filtering_desc = wxTRANSLATE("Force texture filtering even if the emulated game explicitly disabled it.\nImproves texture quality slightly but causes glitches in some games.\n\nIf unsure, leave this unchecked."); -static wxString _3d_vision_desc = wxTRANSLATE("Enable 3D effects via stereoscopy using Nvidia 3D Vision technology if it's supported by your GPU.\nPossibly causes issues.\nRequires fullscreen to work.\n\nIf unsure, leave this unchecked."); static wxString borderless_fullscreen_desc = wxTRANSLATE("Don't use exclusive mode when in fullscreen.\nAllows for faster transitions between fullscreen and windowed mode.\nIncreases input latency, makes movement less smooth and slightly decreases performance.\nExclusive mode is required to support 3D Vision.\n\nIf unsure, leave this unchecked."); static wxString internal_res_desc = wxTRANSLATE("Specifies the resolution used to render at. A high resolution will improve visual quality a lot but is also quite heavy on performance and might cause glitches in certain games.\n\"Multiple of 640x528\" is a bit slower than \"Window Size\" but yields less issues. Generally speaking, the lower the internal resolution is, the better your performance will be.\n\nIf unsure, select 640x528."); static wxString efb_access_desc = wxTRANSLATE("Ignore any requests of the CPU to read from or write to the EFB.\nImproves performance in some games, but might disable some gameplay-related features or graphical effects.\n\nIf unsure, leave this unchecked."); @@ -418,7 +417,7 @@ VideoConfigDiag::VideoConfigDiag(wxWindow* parent, const std::string &title, con szr_enh->Add(choice_ppshader); } - // Scaled copy, PL, Bilinear filter, 3D Vision + // Scaled copy, PL, Bilinear filter szr_enh->Add(CreateCheckBox(page_enh, _("Scaled EFB Copy"), wxGetTranslation(scaled_efb_copy_desc), vconfig.bCopyEFBScaled)); szr_enh->Add(CreateCheckBox(page_enh, _("Per-Pixel Lighting"), wxGetTranslation(pixel_lighting_desc), vconfig.bEnablePixelLighting)); szr_enh->Add(CreateCheckBox(page_enh, _("Force Texture Filtering"), wxGetTranslation(force_filtering_desc), vconfig.bForceFiltering)); @@ -426,12 +425,6 @@ VideoConfigDiag::VideoConfigDiag(wxWindow* parent, const std::string &title, con szr_enh->Add(CreateCheckBox(page_enh, _("Widescreen Hack"), wxGetTranslation(ws_hack_desc), vconfig.bWidescreenHack)); szr_enh->Add(CreateCheckBox(page_enh, _("Disable Fog"), wxGetTranslation(disable_fog_desc), vconfig.bDisableFog)); - // 3D Vision - _3d_vision = CreateCheckBox(page_enh, _("3D Vision"), wxGetTranslation(_3d_vision_desc), vconfig.b3DVision); - _3d_vision->Show(vconfig.backend_info.bSupports3DVision); - szr_enh->Add(_3d_vision); - // TODO: Add anaglyph 3d here - wxStaticBoxSizer* const group_enh = new wxStaticBoxSizer(wxVERTICAL, page_enh, _("Enhancements")); group_enh->Add(szr_enh, 1, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, 5); szr_enh_main->Add(group_enh, 0, wxEXPAND | wxALL, 5); diff --git a/Source/Core/DolphinWX/VideoConfigDiag.h b/Source/Core/DolphinWX/VideoConfigDiag.h index 2906729757..ab574cd2fe 100644 --- a/Source/Core/DolphinWX/VideoConfigDiag.h +++ b/Source/Core/DolphinWX/VideoConfigDiag.h @@ -155,10 +155,6 @@ protected: choice_aamode->Enable(vconfig.backend_info.AAModes.size() > 1); text_aamode->Enable(vconfig.backend_info.AAModes.size() > 1); - // 3D vision - _3d_vision->Enable(vconfig.backend_info.bSupports3DVision); - _3d_vision->Show(vconfig.backend_info.bSupports3DVision); - // Borderless Fullscreen borderless_fullscreen->Enable(vconfig.backend_info.bSupportsExclusiveFullscreen); borderless_fullscreen->Show(vconfig.backend_info.bSupportsExclusiveFullscreen); @@ -192,7 +188,6 @@ protected: wxStaticText* text_aamode; SettingChoice* choice_aamode; - SettingCheckBox* _3d_vision; SettingCheckBox* borderless_fullscreen; SettingRadioButton* efbcopy_texture; diff --git a/Source/Core/VideoBackends/D3D/main.cpp b/Source/Core/VideoBackends/D3D/main.cpp index 504951e684..1e78abfcb7 100644 --- a/Source/Core/VideoBackends/D3D/main.cpp +++ b/Source/Core/VideoBackends/D3D/main.cpp @@ -84,7 +84,6 @@ void InitBackendInfo() g_Config.backend_info.APIType = API_D3D; g_Config.backend_info.bUseRGBATextures = true; // the GX formats barely match any D3D11 formats g_Config.backend_info.bUseMinimalMipCount = true; - g_Config.backend_info.bSupports3DVision = false; g_Config.backend_info.bSupportsExclusiveFullscreen = true; g_Config.backend_info.bSupportsDualSourceBlend = true; g_Config.backend_info.bSupportsPrimitiveRestart = true; diff --git a/Source/Core/VideoBackends/OGL/main.cpp b/Source/Core/VideoBackends/OGL/main.cpp index 0c7e90e097..8ee6471019 100644 --- a/Source/Core/VideoBackends/OGL/main.cpp +++ b/Source/Core/VideoBackends/OGL/main.cpp @@ -143,7 +143,6 @@ static void InitBackendInfo() g_Config.backend_info.APIType = API_OPENGL; g_Config.backend_info.bUseRGBATextures = true; g_Config.backend_info.bUseMinimalMipCount = false; - g_Config.backend_info.bSupports3DVision = false; g_Config.backend_info.bSupportsExclusiveFullscreen = false; //g_Config.backend_info.bSupportsDualSourceBlend = true; // is gpu dependent and must be set in renderer //g_Config.backend_info.bSupportsEarlyZ = true; // is gpu dependent and must be set in renderer diff --git a/Source/Core/VideoCommon/FramebufferManagerBase.cpp b/Source/Core/VideoCommon/FramebufferManagerBase.cpp index 6e26dea190..d3dd0b92fd 100644 --- a/Source/Core/VideoCommon/FramebufferManagerBase.cpp +++ b/Source/Core/VideoCommon/FramebufferManagerBase.cpp @@ -236,15 +236,7 @@ int FramebufferManagerBase::ScaleToVirtualXfbWidth(int x, unsigned int backbuffe if (g_ActiveConfig.RealXFBEnabled()) return x; - if (g_ActiveConfig.b3DVision) - { - // This works, yet the version in the else doesn't. No idea why. - return x * (int)backbuffer_width / (int)FramebufferManagerBase::LastXfbWidth(); - } - else - { - return x * (int)Renderer::GetTargetRectangle().GetWidth() / (int)FramebufferManagerBase::LastXfbWidth(); - } + return x * (int)Renderer::GetTargetRectangle().GetWidth() / (int)FramebufferManagerBase::LastXfbWidth(); } int FramebufferManagerBase::ScaleToVirtualXfbHeight(int y, unsigned int backbuffer_height) @@ -252,13 +244,5 @@ int FramebufferManagerBase::ScaleToVirtualXfbHeight(int y, unsigned int backbuff if (g_ActiveConfig.RealXFBEnabled()) return y; - if (g_ActiveConfig.b3DVision) - { - // This works, yet the version in the else doesn't. No idea why. - return y * (int)backbuffer_height / (int)FramebufferManagerBase::LastXfbHeight(); - } - else - { - return y * (int)Renderer::GetTargetRectangle().GetHeight() / (int)FramebufferManagerBase::LastXfbHeight(); - } + return y * (int)Renderer::GetTargetRectangle().GetHeight() / (int)FramebufferManagerBase::LastXfbHeight(); } diff --git a/Source/Core/VideoCommon/VideoConfig.cpp b/Source/Core/VideoCommon/VideoConfig.cpp index d995ae2d4b..4ef7423a92 100644 --- a/Source/Core/VideoCommon/VideoConfig.cpp +++ b/Source/Core/VideoCommon/VideoConfig.cpp @@ -38,7 +38,6 @@ VideoConfig::VideoConfig() backend_info.APIType = API_NONE; backend_info.bUseRGBATextures = false; backend_info.bUseMinimalMipCount = false; - backend_info.bSupports3DVision = false; backend_info.bSupportsExclusiveFullscreen = false; } @@ -90,7 +89,6 @@ void VideoConfig::Load(const std::string& ini_file) enhancements->Get("ForceFiltering", &bForceFiltering, 0); enhancements->Get("MaxAnisotropy", &iMaxAnisotropy, 0); // NOTE - this is x in (1 << x) enhancements->Get("PostProcessingShader", &sPostProcessingShader, ""); - enhancements->Get("Enable3dVision", &b3DVision, false); IniFile::Section* hacks = iniFile.GetOrCreateSection("Hacks"); hacks->Get("EFBAccessEnable", &bEFBAccessEnable, true); @@ -186,7 +184,6 @@ void VideoConfig::GameIniLoad() CHECK_SETTING("Video_Enhancements", "ForceFiltering", bForceFiltering); CHECK_SETTING("Video_Enhancements", "MaxAnisotropy", iMaxAnisotropy); // NOTE - this is x in (1 << x) CHECK_SETTING("Video_Enhancements", "PostProcessingShader", sPostProcessingShader); - CHECK_SETTING("Video_Enhancements", "Enable3dVision", b3DVision); CHECK_SETTING("Video_Hacks", "EFBAccessEnable", bEFBAccessEnable); CHECK_SETTING("Video_Hacks", "EFBCopyEnable", bEFBCopyEnable); @@ -212,7 +209,6 @@ void VideoConfig::VerifyValidity() // TODO: Check iMaxAnisotropy value if (iAdapter < 0 || iAdapter > ((int)backend_info.Adapters.size() - 1)) iAdapter = 0; if (iMultisampleMode < 0 || iMultisampleMode >= (int)backend_info.AAModes.size()) iMultisampleMode = 0; - if (!backend_info.bSupports3DVision) b3DVision = false; if (!backend_info.bSupportsExclusiveFullscreen) bForceBorderlessFullscreen = false; } @@ -264,7 +260,6 @@ void VideoConfig::Save(const std::string& ini_file) enhancements->Set("ForceFiltering", bForceFiltering); enhancements->Set("MaxAnisotropy", iMaxAnisotropy); enhancements->Set("PostProcessingShader", sPostProcessingShader); - enhancements->Set("Enable3dVision", b3DVision); IniFile::Section* hacks = iniFile.GetOrCreateSection("Hacks"); hacks->Set("EFBAccessEnable", bEFBAccessEnable); diff --git a/Source/Core/VideoCommon/VideoConfig.h b/Source/Core/VideoCommon/VideoConfig.h index 34d4f314c5..88a2913d2e 100644 --- a/Source/Core/VideoCommon/VideoConfig.h +++ b/Source/Core/VideoCommon/VideoConfig.h @@ -140,7 +140,6 @@ struct VideoConfig final bool bUseRGBATextures; // used for D3D in TextureCache bool bUseMinimalMipCount; - bool bSupports3DVision; bool bSupportsExclusiveFullscreen; bool bSupportsDualSourceBlend; bool bSupportsPrimitiveRestart; From eea7086b23f45e4566550e99e3bd1fec7ecd4e2c Mon Sep 17 00:00:00 2001 From: Jules Blok Date: Fri, 25 Jul 2014 15:33:50 +0200 Subject: [PATCH 20/22] CFrame: Prevent fullscreen switches if the renderer is halted. --- Source/Core/DolphinWX/Frame.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/Source/Core/DolphinWX/Frame.cpp b/Source/Core/DolphinWX/Frame.cpp index dc0eeeb8e6..1d7fb03819 100644 --- a/Source/Core/DolphinWX/Frame.cpp +++ b/Source/Core/DolphinWX/Frame.cpp @@ -1185,6 +1185,17 @@ void CFrame::OnMouse(wxMouseEvent& event) void CFrame::DoFullscreen(bool bF) { + if (g_Config.ExclusiveFullscreenEnabled() && + !SConfig::GetInstance().m_LocalCoreStartupParameter.bRenderToMain && + Core::GetState() != Core::CORE_RUN) + { + // 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 support + // exclusive fullscreen, but the renderer is not running. + return; + } + ToggleDisplayMode(bF); #if defined(__APPLE__) From 6724ce627516b89cc126ee7f4a876fc8472d46ca Mon Sep 17 00:00:00 2001 From: Jules Blok Date: Sat, 26 Jul 2014 12:43:49 +0200 Subject: [PATCH 21/22] Cosmetic changes based on feedback on PR #506. --- Source/Core/Core/Host.h | 2 +- Source/Core/DolphinWX/Frame.cpp | 35 +++++++++++++---------- Source/Core/DolphinWX/FrameTools.cpp | 2 +- Source/Core/DolphinWX/Main.cpp | 4 +-- Source/Core/DolphinWX/MainAndroid.cpp | 2 +- Source/Core/DolphinWX/MainNoGUI.cpp | 2 +- Source/Core/DolphinWX/VideoConfigDiag.cpp | 4 +-- Source/Core/VideoBackends/D3D/Render.cpp | 12 ++++---- Source/Core/VideoCommon/VideoConfig.cpp | 6 ++-- Source/Core/VideoCommon/VideoConfig.h | 5 ++-- 10 files changed, 40 insertions(+), 34 deletions(-) diff --git a/Source/Core/Core/Host.h b/Source/Core/Core/Host.h index fe9ff11a6d..2d2587138e 100644 --- a/Source/Core/Core/Host.h +++ b/Source/Core/Core/Host.h @@ -31,7 +31,7 @@ void Host_Message(int Id); void Host_NotifyMapLoaded(); void Host_RefreshDSPDebuggerWindow(); void Host_RequestRenderWindowSize(int width, int height); -void Host_RequestFullscreen(bool fullscreen); +void Host_RequestFullscreen(bool enable_fullscreen); void Host_SetStartupDebuggingParameters(); void Host_SetWiiMoteConnectionState(int _State); void Host_ShowJitResults(unsigned int address); diff --git a/Source/Core/DolphinWX/Frame.cpp b/Source/Core/DolphinWX/Frame.cpp index 1d7fb03819..43d5185ee3 100644 --- a/Source/Core/DolphinWX/Frame.cpp +++ b/Source/Core/DolphinWX/Frame.cpp @@ -642,10 +642,14 @@ void CFrame::OnHostMessage(wxCommandEvent& event) case IDM_FULLSCREENREQUEST: { - bool fullscreen = event.GetInt() == 0 ? false : true; - ToggleDisplayMode(fullscreen); + bool enable_fullscreen = event.GetInt() == 0 ? false : true; + ToggleDisplayMode(enable_fullscreen); if (m_RenderFrame != nullptr) - m_RenderFrame->ShowFullScreen(fullscreen); + 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); } @@ -1183,35 +1187,36 @@ void CFrame::OnMouse(wxMouseEvent& event) event.Skip(); } -void CFrame::DoFullscreen(bool bF) +void CFrame::DoFullscreen(bool enable_fullscreen) { - if (g_Config.ExclusiveFullscreenEnabled() && + if (!g_Config.bBorderlessFullscreen && !SConfig::GetInstance().m_LocalCoreStartupParameter.bRenderToMain && Core::GetState() != Core::CORE_RUN) { - // 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 support - // exclusive fullscreen, but the renderer is not running. + // 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 support exclusive fullscreen, but the + // renderer is not running. + // TODO: Allow the renderer to switch fullscreen modes while paused. return; } - ToggleDisplayMode(bF); + ToggleDisplayMode(enable_fullscreen); #if defined(__APPLE__) NSView *view = (NSView *) m_RenderFrame->GetHandle(); NSWindow *window = [view window]; - if (bF != RendererIsFullscreen()) + if (enable_fullscreen != RendererIsFullscreen()) { [window toggleFullScreen:nil]; } #else - if (bF) + if (enable_fullscreen) { m_RenderFrame->ShowFullScreen(true, wxFULLSCREEN_ALL); } - else if (!g_Config.ExclusiveFullscreenEnabled() || + else if (g_Config.bBorderlessFullscreen || SConfig::GetInstance().m_LocalCoreStartupParameter.bRenderToMain) { // Exiting exclusive fullscreen should be done from a Renderer callback. @@ -1222,7 +1227,7 @@ void CFrame::DoFullscreen(bool bF) if (SConfig::GetInstance().m_LocalCoreStartupParameter.bRenderToMain) { - if (bF) + if (enable_fullscreen) { // Save the current mode before going to fullscreen AuiCurrent = m_Mgr->SavePerspective(); @@ -1239,7 +1244,7 @@ void CFrame::DoFullscreen(bool bF) m_RenderFrame->Raise(); } - g_Config.bFullscreen = bF; + g_Config.bFullscreen = enable_fullscreen; } const CGameListCtrl *CFrame::GetGameListCtrl() const diff --git a/Source/Core/DolphinWX/FrameTools.cpp b/Source/Core/DolphinWX/FrameTools.cpp index 937809e050..7da062645f 100644 --- a/Source/Core/DolphinWX/FrameTools.cpp +++ b/Source/Core/DolphinWX/FrameTools.cpp @@ -1104,7 +1104,7 @@ void CFrame::DoStop() // 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. - if (!RendererIsFullscreen() || !g_Config.ExclusiveFullscreenEnabled() || + if (!RendererIsFullscreen() || g_Config.bBorderlessFullscreen || SConfig::GetInstance().m_LocalCoreStartupParameter.bRenderToMain) { Core::SetState(Core::CORE_PAUSE); diff --git a/Source/Core/DolphinWX/Main.cpp b/Source/Core/DolphinWX/Main.cpp index 712aca5895..18a693fb82 100644 --- a/Source/Core/DolphinWX/Main.cpp +++ b/Source/Core/DolphinWX/Main.cpp @@ -627,10 +627,10 @@ void Host_RequestRenderWindowSize(int width, int height) main_frame->GetEventHandler()->AddPendingEvent(event); } -void Host_RequestFullscreen(bool fullscreen) +void Host_RequestFullscreen(bool enable_fullscreen) { wxCommandEvent event(wxEVT_HOST_COMMAND, IDM_FULLSCREENREQUEST); - event.SetInt(fullscreen ? 1 : 0); + event.SetInt(enable_fullscreen ? 1 : 0); main_frame->GetEventHandler()->AddPendingEvent(event); } diff --git a/Source/Core/DolphinWX/MainAndroid.cpp b/Source/Core/DolphinWX/MainAndroid.cpp index cdbc2a0785..cb1d14c023 100644 --- a/Source/Core/DolphinWX/MainAndroid.cpp +++ b/Source/Core/DolphinWX/MainAndroid.cpp @@ -95,7 +95,7 @@ void Host_GetRenderWindowSize(int& x, int& y, int& width, int& height) void Host_RequestRenderWindowSize(int width, int height) {} -void Host_RequestFullscreen(bool fullscreen) {} +void Host_RequestFullscreen(bool enable_fullscreen) {} void Host_SetStartupDebuggingParameters() { diff --git a/Source/Core/DolphinWX/MainNoGUI.cpp b/Source/Core/DolphinWX/MainNoGUI.cpp index ee532f702a..df9276bb59 100644 --- a/Source/Core/DolphinWX/MainNoGUI.cpp +++ b/Source/Core/DolphinWX/MainNoGUI.cpp @@ -89,7 +89,7 @@ void Host_GetRenderWindowSize(int& x, int& y, int& width, int& height) void Host_RequestRenderWindowSize(int width, int height) {} -void Host_RequestFullscreen(bool fullscreen) {} +void Host_RequestFullscreen(bool enable_fullscreen) {} void Host_SetStartupDebuggingParameters() { diff --git a/Source/Core/DolphinWX/VideoConfigDiag.cpp b/Source/Core/DolphinWX/VideoConfigDiag.cpp index d128b8854e..37d7fb8bbd 100644 --- a/Source/Core/DolphinWX/VideoConfigDiag.cpp +++ b/Source/Core/DolphinWX/VideoConfigDiag.cpp @@ -113,7 +113,7 @@ static wxString scaled_efb_copy_desc = wxTRANSLATE("Greatly increases quality of static wxString pixel_lighting_desc = wxTRANSLATE("Calculate lighting of 3D graphics per-pixel rather than per vertex.\nDecreases emulation speed by some percent (depending on your GPU).\nThis usually is a safe enhancement, but might cause issues sometimes.\n\nIf unsure, leave this unchecked."); static wxString fast_depth_calc_desc = wxTRANSLATE("Use a less accurate algorithm to calculate depth values.\nCauses issues in a few games but might give a decent speedup.\n\nIf unsure, leave this checked."); static wxString force_filtering_desc = wxTRANSLATE("Force texture filtering even if the emulated game explicitly disabled it.\nImproves texture quality slightly but causes glitches in some games.\n\nIf unsure, leave this unchecked."); -static wxString borderless_fullscreen_desc = wxTRANSLATE("Don't use exclusive mode when in fullscreen.\nAllows for faster transitions between fullscreen and windowed mode.\nIncreases input latency, makes movement less smooth and slightly decreases performance.\nExclusive mode is required to support 3D Vision.\n\nIf unsure, leave this unchecked."); +static wxString borderless_fullscreen_desc = wxTRANSLATE("Implement fullscreen mode with a borderless window spanning the whole screen instead of using exclusive mode.\nAllows for faster transitions between fullscreen and windowed mode, but increases input latency, makes movement less smooth and slightly decreases performance.\nExclusive mode is required to support Nvidia 3D Vision.\n\nIf unsure, leave this unchecked."); static wxString internal_res_desc = wxTRANSLATE("Specifies the resolution used to render at. A high resolution will improve visual quality a lot but is also quite heavy on performance and might cause glitches in certain games.\n\"Multiple of 640x528\" is a bit slower than \"Window Size\" but yields less issues. Generally speaking, the lower the internal resolution is, the better your performance will be.\n\nIf unsure, select 640x528."); static wxString efb_access_desc = wxTRANSLATE("Ignore any requests of the CPU to read from or write to the EFB.\nImproves performance in some games, but might disable some gameplay-related features or graphical effects.\n\nIf unsure, leave this unchecked."); static wxString efb_emulate_format_changes_desc = wxTRANSLATE("Ignore any changes to the EFB format.\nImproves performance in many games without any negative effect. Causes graphical defects in a small number of other games though.\n\nIf unsure, leave this checked."); @@ -579,7 +579,7 @@ VideoConfigDiag::VideoConfigDiag(wxWindow* parent, const std::string &title, con } // Borderless Fullscreen - borderless_fullscreen = CreateCheckBox(page_advanced, _("Borderless Fullscreen"), wxGetTranslation(borderless_fullscreen_desc), vconfig.bForceBorderlessFullscreen); + borderless_fullscreen = CreateCheckBox(page_advanced, _("Borderless Fullscreen"), wxGetTranslation(borderless_fullscreen_desc), vconfig.bBorderlessFullscreen); borderless_fullscreen->Show(vconfig.backend_info.bSupportsExclusiveFullscreen); szr_misc->Add(borderless_fullscreen); diff --git a/Source/Core/VideoBackends/D3D/Render.cpp b/Source/Core/VideoBackends/D3D/Render.cpp index 1f883c18fe..551d40b95c 100644 --- a/Source/Core/VideoBackends/D3D/Render.cpp +++ b/Source/Core/VideoBackends/D3D/Render.cpp @@ -938,7 +938,7 @@ void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbHeight,const EFBRectangl SetWindowSize(fbWidth, fbHeight); const bool windowResized = CheckForResize(); - const bool fullscreen = g_ActiveConfig.bFullscreen && !g_ActiveConfig.bForceBorderlessFullscreen && + const bool fullscreen = g_ActiveConfig.ExclusiveFullscreenEnabled() && !SConfig::GetInstance().m_LocalCoreStartupParameter.bRenderToMain; bool fullscreen_changed = s_last_fullscreen_mode != fullscreen; @@ -948,7 +948,9 @@ void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbHeight,const EFBRectangl { if (!!fullscreen_state != fullscreen && Host_RendererHasFocus()) { - // We should be in fullscreen, but we're not. Restore it when we regain focus. + // 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; } } @@ -967,7 +969,7 @@ void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbHeight,const EFBRectangl // Flip/present backbuffer to frontbuffer here D3D::Present(); - // resize the back buffers NOW to avoid flickering + // Resize the back buffers NOW to avoid flickering if (xfbchanged || windowResized || fullscreen_changed || @@ -979,13 +981,13 @@ void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbHeight,const EFBRectangl if (windowResized || fullscreen_changed) { - // apply fullscreen state + // Apply fullscreen state if (fullscreen_changed) { s_last_fullscreen_mode = fullscreen; D3D::swapchain->SetFullscreenState(fullscreen, nullptr); - // notify the host that it is safe to exit fullscreen + // Notify the host that it is safe to exit fullscreen if (!fullscreen) { Host_RequestFullscreen(false); diff --git a/Source/Core/VideoCommon/VideoConfig.cpp b/Source/Core/VideoCommon/VideoConfig.cpp index 4ef7423a92..cf7685ada6 100644 --- a/Source/Core/VideoCommon/VideoConfig.cpp +++ b/Source/Core/VideoCommon/VideoConfig.cpp @@ -83,7 +83,7 @@ void VideoConfig::Load(const std::string& ini_file) settings->Get("DisableFog", &bDisableFog, 0); settings->Get("OMPDecoder", &bOMPDecoder, false); settings->Get("EnableShaderDebugging", &bEnableShaderDebugging, false); - settings->Get("ForceBorderlessFullscreen", &bForceBorderlessFullscreen, false); + settings->Get("BorderlessFullscreen", &bBorderlessFullscreen, false); IniFile::Section* enhancements = iniFile.GetOrCreateSection("Enhancements"); enhancements->Get("ForceFiltering", &bForceFiltering, 0); @@ -209,7 +209,7 @@ void VideoConfig::VerifyValidity() // TODO: Check iMaxAnisotropy value if (iAdapter < 0 || iAdapter > ((int)backend_info.Adapters.size() - 1)) iAdapter = 0; if (iMultisampleMode < 0 || iMultisampleMode >= (int)backend_info.AAModes.size()) iMultisampleMode = 0; - if (!backend_info.bSupportsExclusiveFullscreen) bForceBorderlessFullscreen = false; + if (!backend_info.bSupportsExclusiveFullscreen) bBorderlessFullscreen = true; } void VideoConfig::Save(const std::string& ini_file) @@ -254,7 +254,7 @@ void VideoConfig::Save(const std::string& ini_file) settings->Set("DisableFog", bDisableFog); settings->Set("OMPDecoder", bOMPDecoder); settings->Set("EnableShaderDebugging", bEnableShaderDebugging); - settings->Set("ForceBorderlessFullscreen", bForceBorderlessFullscreen); + settings->Set("BorderlessFullscreen", bBorderlessFullscreen); IniFile::Section* enhancements = iniFile.GetOrCreateSection("Enhancements"); enhancements->Set("ForceFiltering", bForceFiltering); diff --git a/Source/Core/VideoCommon/VideoConfig.h b/Source/Core/VideoCommon/VideoConfig.h index 88a2913d2e..2ff29bf87b 100644 --- a/Source/Core/VideoCommon/VideoConfig.h +++ b/Source/Core/VideoCommon/VideoConfig.h @@ -100,8 +100,7 @@ struct VideoConfig final bool bAnaglyphStereo; int iAnaglyphStereoSeparation; int iAnaglyphFocalAngle; - bool b3DVision; - bool bForceBorderlessFullscreen; + bool bBorderlessFullscreen; // Hacks bool bEFBAccessEnable; @@ -153,7 +152,7 @@ struct VideoConfig final bool VirtualXFBEnabled() const { return bUseXFB && !bUseRealXFB; } bool EFBCopiesToTextureEnabled() const { return bEFBCopyEnable && bCopyEFBToTexture; } bool EFBCopiesToRamEnabled() const { return bEFBCopyEnable && !bCopyEFBToTexture; } - bool ExclusiveFullscreenEnabled() const { return backend_info.bSupportsExclusiveFullscreen && !bForceBorderlessFullscreen; } + bool ExclusiveFullscreenEnabled() const { return bFullscreen && !bBorderlessFullscreen; } }; extern VideoConfig g_Config; From 06b13f12d3c7ef9946dfba6d8aa91e9f6b1ed7d6 Mon Sep 17 00:00:00 2001 From: Jules Blok Date: Sat, 26 Jul 2014 13:00:49 +0200 Subject: [PATCH 22/22] D3D: Make the global swapchain static again. --- Source/Core/VideoBackends/D3D/D3DBase.cpp | 20 +++++++++++++++++++- Source/Core/VideoBackends/D3D/D3DBase.h | 4 +++- Source/Core/VideoBackends/D3D/Render.cpp | 8 ++++---- 3 files changed, 26 insertions(+), 6 deletions(-) diff --git a/Source/Core/VideoBackends/D3D/D3DBase.cpp b/Source/Core/VideoBackends/D3D/D3DBase.cpp index 21226e442c..33de5d8065 100644 --- a/Source/Core/VideoBackends/D3D/D3DBase.cpp +++ b/Source/Core/VideoBackends/D3D/D3DBase.cpp @@ -31,7 +31,7 @@ namespace D3D ID3D11Device* device = nullptr; ID3D11DeviceContext* context = nullptr; -IDXGISwapChain* swapchain = nullptr; +static IDXGISwapChain* swapchain = nullptr; D3D_FEATURE_LEVEL featlevel; D3DTexture2D* backbuf = nullptr; HWND hWnd; @@ -492,6 +492,24 @@ void Present() swapchain->Present((UINT)g_ActiveConfig.IsVSync(), 0); } +HRESULT SetFullscreenState(bool enable_fullscreen) +{ + return swapchain->SetFullscreenState(enable_fullscreen, nullptr); +} + +HRESULT GetFullscreenState(bool* fullscreen_state) +{ + if (fullscreen_state == nullptr) + { + return E_POINTER; + } + + BOOL state; + HRESULT hr = swapchain->GetFullscreenState(&state, nullptr); + *fullscreen_state = !!state; + return hr; +} + } // namespace D3D } // namespace DX11 diff --git a/Source/Core/VideoBackends/D3D/D3DBase.h b/Source/Core/VideoBackends/D3D/D3DBase.h index 0188c464e3..2f9f15b623 100644 --- a/Source/Core/VideoBackends/D3D/D3DBase.h +++ b/Source/Core/VideoBackends/D3D/D3DBase.h @@ -40,7 +40,6 @@ void Close(); extern ID3D11Device* device; extern ID3D11DeviceContext* context; -extern IDXGISwapChain* swapchain; extern HWND hWnd; extern bool bFrameInProgress; @@ -59,6 +58,9 @@ bool BGRATexturesSupported(); unsigned int GetMaxTextureSize(); +HRESULT SetFullscreenState(bool enable_fullscreen); +HRESULT GetFullscreenState(bool* fullscreen_state); + // Ihis function will assign a name to the given resource. // The DirectX debug layer will make it easier to identify resources that way, // e.g. when listing up all resources who have unreleased references. diff --git a/Source/Core/VideoBackends/D3D/Render.cpp b/Source/Core/VideoBackends/D3D/Render.cpp index 551d40b95c..e712bed4db 100644 --- a/Source/Core/VideoBackends/D3D/Render.cpp +++ b/Source/Core/VideoBackends/D3D/Render.cpp @@ -943,10 +943,10 @@ void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbHeight,const EFBRectangl bool fullscreen_changed = s_last_fullscreen_mode != fullscreen; - BOOL fullscreen_state; - if (SUCCEEDED(D3D::swapchain->GetFullscreenState(&fullscreen_state, nullptr))) + bool fullscreen_state; + if (SUCCEEDED(D3D::GetFullscreenState(&fullscreen_state))) { - if (!!fullscreen_state != fullscreen && Host_RendererHasFocus()) + 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 @@ -985,7 +985,7 @@ void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbHeight,const EFBRectangl if (fullscreen_changed) { s_last_fullscreen_mode = fullscreen; - D3D::swapchain->SetFullscreenState(fullscreen, nullptr); + D3D::SetFullscreenState(fullscreen); // Notify the host that it is safe to exit fullscreen if (!fullscreen)