@@ -74,6 +74,24 @@ VmaAllocator Graphics::getVmaAllocator() const
7474 return vmaAllocator;
7575}
7676
77+ // Calling Window::getSettings is the correct abstracted way to do this, but
78+ // it also does a bunch more work which we want to avoid.
79+ static bool isWindowFullscreenExclusive ()
80+ {
81+ auto window = Module::getInstance<love::window::Window>(Module::M_WINDOW );
82+ if (window == nullptr )
83+ return false ;
84+
85+ SDL_Window *handle = (SDL_Window *)window->getHandle ();
86+ if (handle == nullptr )
87+ return false ;
88+
89+ if ((SDL_GetWindowFlags (handle) & SDL_WINDOW_FULLSCREEN ) != SDL_WINDOW_FULLSCREEN )
90+ return false ;
91+
92+ return SDL_GetWindowFullscreenMode (handle) != nullptr ;
93+ }
94+
7795static void checkOptionalInstanceExtensions (OptionalInstanceExtensions& ext)
7896{
7997 uint32_t count;
@@ -592,6 +610,21 @@ void Graphics::present(void *screenshotCallbackdata)
592610 }
593611 }
594612
613+ #ifdef VK_EXT_full_screen_exclusive
614+ if (optionalDeviceExtensions.fullscreenExclusive )
615+ {
616+ // TODO: We really don't want to query this every frame, it has performance
617+ // costs including calling into system code. But SDL doesn't yet provide an
618+ // event for it: https://github.com/libsdl-org/SDL/issues/15850
619+ bool fullscreenExclusive = isWindowFullscreenExclusive ();
620+ if (windowIsFullscreenExclusive != fullscreenExclusive)
621+ {
622+ windowIsFullscreenExclusive = fullscreenExclusive;
623+ requestSwapchainRecreation ();
624+ }
625+ }
626+ #endif
627+
595628 if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR || swapChainRecreationRequested)
596629 {
597630 swapChainRecreationRequested = false ;
@@ -1783,6 +1816,10 @@ static void findOptionalDeviceExtensions(VkPhysicalDevice physicalDevice, Option
17831816 optionalDeviceExtensions.shaderFloatControls = true ;
17841817 if (strcmp (extension.extensionName , VK_KHR_SPIRV_1_4_EXTENSION_NAME ) == 0 )
17851818 optionalDeviceExtensions.spirv14 = true ;
1819+ #ifdef VK_EXT_full_screen_exclusive
1820+ if (strcmp (extension.extensionName , VK_EXT_FULL_SCREEN_EXCLUSIVE_EXTENSION_NAME ) == 0 )
1821+ optionalDeviceExtensions.fullscreenExclusive = true ;
1822+ #endif
17861823 }
17871824}
17881825
@@ -1845,6 +1882,10 @@ void Graphics::createLogicalDevice()
18451882 enabledExtensions.push_back (VK_KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME );
18461883 if (optionalDeviceExtensions.spirv14 )
18471884 enabledExtensions.push_back (VK_KHR_SPIRV_1_4_EXTENSION_NAME );
1885+ #ifdef VK_EXT_full_screen_exclusive
1886+ if (optionalDeviceExtensions.fullscreenExclusive )
1887+ enabledExtensions.push_back (VK_EXT_FULL_SCREEN_EXCLUSIVE_EXTENSION_NAME );
1888+ #endif
18481889 if (deviceApiVersion >= VK_API_VERSION_1_1 )
18491890 enabledExtensions.push_back (VK_KHR_BIND_MEMORY_2_EXTENSION_NAME );
18501891
@@ -2023,6 +2064,25 @@ void Graphics::createSwapChain()
20232064 createInfo.clipped = VK_TRUE ;
20242065 createInfo.oldSwapchain = swapChain;
20252066
2067+ #ifdef VK_EXT_full_screen_exclusive
2068+ VkSurfaceFullScreenExclusiveInfoEXT exclusiveInfo = {};
2069+ exclusiveInfo.sType = VK_STRUCTURE_TYPE_SURFACE_FULL_SCREEN_EXCLUSIVE_INFO_EXT ;
2070+
2071+ if (optionalDeviceExtensions.fullscreenExclusive )
2072+ {
2073+ // This should in theory help Windows graphics drivers avoid treating
2074+ // desktop-fullscreen like exclusive-fullscreen, which should reduce
2075+ // issues with programs that interact with the window (e.g. screen recorders).
2076+ windowIsFullscreenExclusive = isWindowFullscreenExclusive ();
2077+ if (windowIsFullscreenExclusive)
2078+ exclusiveInfo.fullScreenExclusive = VK_FULL_SCREEN_EXCLUSIVE_ALLOWED_EXT ;
2079+ else
2080+ exclusiveInfo.fullScreenExclusive = VK_FULL_SCREEN_EXCLUSIVE_DISALLOWED_EXT ;
2081+
2082+ createInfo.pNext = &exclusiveInfo;
2083+ }
2084+ #endif
2085+
20262086 VkSwapchainKHR newSwapChain = VK_NULL_HANDLE ;
20272087 VkResult result = vkCreateSwapchainKHR (device, &createInfo, nullptr , &newSwapChain);
20282088
0 commit comments