Skip to content

Commit

Permalink
[dxgi] Leave fullscreen mode when window looses focus
Browse files Browse the repository at this point in the history
  • Loading branch information
gofman authored and doitsujin committed Sep 17, 2024
1 parent 758dc80 commit ed9ffa6
Show file tree
Hide file tree
Showing 13 changed files with 98 additions and 6 deletions.
2 changes: 1 addition & 1 deletion src/dxgi/dxgi_factory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,7 @@ namespace dxvk {
return hr;
}

frontendSwapChain = new DxgiSwapChain(this, presenter.ptr(), hWnd, &desc, &fsDesc);
frontendSwapChain = new DxgiSwapChain(this, presenter.ptr(), hWnd, &desc, &fsDesc, pDevice);
} else {
Logger::err("DXGI: CreateSwapChainForHwnd: Unsupported device type");
return DXGI_ERROR_UNSUPPORTED;
Expand Down
24 changes: 20 additions & 4 deletions src/dxgi/dxgi_swapchain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,26 @@

#include "../util/util_misc.h"

#include <d3d12.h>

namespace dxvk {

DxgiSwapChain::DxgiSwapChain(
DxgiFactory* pFactory,
IDXGIVkSwapChain* pPresenter,
HWND hWnd,
const DXGI_SWAP_CHAIN_DESC1* pDesc,
const DXGI_SWAP_CHAIN_FULLSCREEN_DESC* pFullscreenDesc)
const DXGI_SWAP_CHAIN_FULLSCREEN_DESC* pFullscreenDesc,
IUnknown* pDevice)
: m_factory (pFactory),
m_window (hWnd),
m_desc (*pDesc),
m_descFs (*pFullscreenDesc),
m_presentId (0u),
m_presenter (pPresenter),
m_monitor (wsi::getWindowMonitor(m_window)) {
m_monitor (wsi::getWindowMonitor(m_window)),
m_is_d3d12(SUCCEEDED(pDevice->QueryInterface(__uuidof(ID3D12CommandQueue), reinterpret_cast<void**>(&Com<ID3D12CommandQueue>())))) {

if (FAILED(m_presenter->GetAdapter(__uuidof(IDXGIAdapter), reinterpret_cast<void**>(&m_adapter))))
throw DxvkError("DXGI: Failed to get adapter for present device");

Expand Down Expand Up @@ -243,7 +248,9 @@ namespace dxvk {
BOOL* pFullscreen,
IDXGIOutput** ppTarget) {
HRESULT hr = S_OK;


if (!m_is_d3d12 && !m_descFs.Windowed && wsi::isOccluded(m_window))
SetFullscreenState(FALSE, nullptr);
if (pFullscreen != nullptr)
*pFullscreen = !m_descFs.Windowed;

Expand Down Expand Up @@ -325,6 +332,10 @@ namespace dxvk {
if (SyncInterval > 4)
return DXGI_ERROR_INVALID_CALL;

if ((m_desc.SwapEffect == DXGI_SWAP_EFFECT_DISCARD || m_desc.SwapEffect == DXGI_SWAP_EFFECT_SEQUENTIAL) && wsi::isMinimized(m_window))
return DXGI_STATUS_OCCLUDED;
bool occluded = !m_descFs.Windowed && wsi::isOccluded(m_window) && !wsi::isMinimized(m_window);

auto options = m_factory->GetOptions();

if (options->syncInterval >= 0)
Expand All @@ -342,7 +353,7 @@ namespace dxvk {
}

if (PresentFlags & DXGI_PRESENT_TEST)
return hr;
return hr == S_OK && occluded ? DXGI_STATUS_OCCLUDED : hr;

if (hr == S_OK) {

Expand All @@ -365,6 +376,11 @@ namespace dxvk {
monitorData->FrameStats.PresentRefreshCount = monitorData->FrameStats.SyncRefreshCount + computeRefreshCount(t0, t1, refreshPeriod);
ReleaseMonitorData();
}
if (occluded) {
if (!(PresentFlags & DXGI_PRESENT_TEST))
SetFullscreenState(FALSE, nullptr);
hr = DXGI_STATUS_OCCLUDED;
}
}

return hr;
Expand Down
4 changes: 3 additions & 1 deletion src/dxgi/dxgi_swapchain.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ namespace dxvk {
IDXGIVkSwapChain* pPresenter,
HWND hWnd,
const DXGI_SWAP_CHAIN_DESC1* pDesc,
const DXGI_SWAP_CHAIN_FULLSCREEN_DESC* pFullscreenDesc);
const DXGI_SWAP_CHAIN_FULLSCREEN_DESC* pFullscreenDesc,
IUnknown* pDevice);

~DxgiSwapChain();

Expand Down Expand Up @@ -198,6 +199,7 @@ namespace dxvk {
double m_frameRateOption = 0.0;
double m_frameRateRefresh = 0.0;
double m_frameRateLimit = 0.0;
bool m_is_d3d12;

DXGI_COLOR_SPACE_TYPE m_colorSpace = DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709;

Expand Down
4 changes: 4 additions & 0 deletions src/wsi/glfw/wsi_platform_glfw.h
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,10 @@ namespace dxvk::wsi {

virtual bool isWindow(HWND hWindow);

virtual bool isMinimized(HWND hWindow);

virtual bool isOccluded(HWND hWindow);

virtual void updateFullscreenWindow(
HMONITOR hMonitor,
HWND hWindow,
Expand Down
12 changes: 12 additions & 0 deletions src/wsi/glfw/wsi_window_glfw.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,18 @@ namespace dxvk::wsi {
return window != nullptr;
}


bool GlfwWsiDriver::isMinimized(HWND hWindow) {
GLFWwindow* window = fromHwnd(hWindow);
return glfwGetWindowAttrib(window, GLFW_ICONIFIED) != 0;
}


bool GlfwWsiDriver::isOccluded(HWND hWindow) {
return false;
}


void GlfwWsiDriver::updateFullscreenWindow(
HMONITOR hMonitor,
HWND hWindow,
Expand Down
4 changes: 4 additions & 0 deletions src/wsi/sdl2/wsi_platform_sdl2.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,10 @@ namespace dxvk::wsi {

virtual bool isWindow(HWND hWindow);

virtual bool isMinimized(HWND hWindow);

virtual bool isOccluded(HWND hWindow);

virtual void updateFullscreenWindow(
HMONITOR hMonitor,
HWND hWindow,
Expand Down
1 change: 1 addition & 0 deletions src/wsi/sdl2/wsi_platform_sdl2_funcs.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ SDL_PROC(int, SDL_GetNumVideoDisplays, (void))
SDL_PROC(int, SDL_GetWindowDisplayIndex, (SDL_Window*))
SDL_PROC(int, SDL_SetWindowDisplayMode, (SDL_Window*, const SDL_DisplayMode*))
SDL_PROC(int, SDL_SetWindowFullscreen, (SDL_Window*, Uint32))
SDL_PROC(SDL_WindowFlags, SDL_GetWindowFlags, (SDL_Window *))
SDL_PROC(void, SDL_GetWindowSize, (SDL_Window*, int*, int*))
SDL_PROC(void, SDL_SetWindowSize, (SDL_Window*, int, int))
SDL_PROC(SDL_bool, SDL_Vulkan_CreateSurface, (SDL_Window*, VkInstance, VkSurfaceKHR*))
Expand Down
11 changes: 11 additions & 0 deletions src/wsi/sdl2/wsi_window_sdl2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,17 @@ namespace dxvk::wsi {
}


bool Sdl2WsiDriver::isMinimized(HWND hWindow) {
SDL_Window* window = fromHwnd(hWindow);
return (SDL_GetWindowFlags(window) & SDL_WINDOW_MINIMIZED) != 0;
}


bool Sdl2WsiDriver::isOccluded(HWND hWindow) {
return false;
}


void Sdl2WsiDriver::updateFullscreenWindow(
HMONITOR hMonitor,
HWND hWindow,
Expand Down
4 changes: 4 additions & 0 deletions src/wsi/win32/wsi_platform_win32.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,10 @@ namespace dxvk::wsi {

virtual bool isWindow(HWND hWindow);

virtual bool isMinimized(HWND hWindow);

virtual bool isOccluded(HWND hWindow);

virtual void updateFullscreenWindow(
HMONITOR hMonitor,
HWND hWindow,
Expand Down
10 changes: 10 additions & 0 deletions src/wsi/win32/wsi_window_win32.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,16 @@ namespace dxvk::wsi {
}


bool Win32WsiDriver::isMinimized(HWND hWindow) {
return (::GetWindowLongW(hWindow, GWL_STYLE) & WS_MINIMIZE) != 0;
}


bool Win32WsiDriver::isOccluded(HWND hWindow) {
return ::GetForegroundWindow() != hWindow;
}


void Win32WsiDriver::updateFullscreenWindow(
HMONITOR hMonitor,
HWND hWindow,
Expand Down
8 changes: 8 additions & 0 deletions src/wsi/wsi_platform.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,14 @@ namespace dxvk::wsi {
return s_driver->isWindow(hWindow);
}

bool isMinimized(HWND hWindow) {
return s_driver->isMinimized(hWindow);
}

bool isOccluded(HWND hWindow) {
return s_driver->isOccluded(hWindow);
}

void updateFullscreenWindow(
HMONITOR hMonitor,
HWND hWindow,
Expand Down
4 changes: 4 additions & 0 deletions src/wsi/wsi_platform.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,10 @@ namespace dxvk::wsi {

virtual bool isWindow(HWND hWindow) = 0;

virtual bool isMinimized(HWND hWindow) = 0;

virtual bool isOccluded(HWND hWindow) = 0;

virtual void updateFullscreenWindow(
HMONITOR hMonitor,
HWND hWindow,
Expand Down
16 changes: 16 additions & 0 deletions src/wsi/wsi_window.h
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,22 @@ namespace dxvk::wsi {
*/
bool isWindow(HWND hWindow);

/**
* \brief Is window minimized?
*
* \param [in] hWindow The window
* \returns Is window minimized?
*/
bool isMinimized(HWND hWindow);

/**
* \brief Is window occluded?
*
* \param [in] hWindow The window
* \returns Is window occluded?
*/
bool isOccluded(HWND hWindow);

/**
* \brief Update a fullscreen window's position/size
*
Expand Down

0 comments on commit ed9ffa6

Please sign in to comment.