GPUDevice: Enumerate fullscreen modes if using SDL

This commit is contained in:
Stenzek
2026-02-16 18:54:39 +10:00
parent 0d0bd69ada
commit d5eb3e10ea
12 changed files with 130 additions and 6 deletions

View File

@@ -3816,6 +3816,9 @@ void FullscreenUI::DrawGraphicsSettingsPage()
options.emplace_back(FSUI_STR("Default"), current_adapter.has_value() && current_adapter->empty());
for (const GPUDevice::AdapterInfo& adapter : s_settings_locals.graphics_adapter_list_cache)
{
if (adapter.name.empty())
continue;
const bool checked = (current_adapter.has_value() && current_adapter.value() == adapter.name);
options.emplace_back(adapter.name, checked);
}

View File

@@ -683,6 +683,9 @@ void GraphicsSettingsWidget::populateGPUAdaptersAndResolutions(RenderAPI render_
const std::string current_adapter_name = m_dialog->getEffectiveStringValue("GPU", "Adapter", "");
for (const GPUDevice::AdapterInfo& adapter : m_adapters)
{
if (adapter.name.empty())
continue;
const QString qadaptername = QString::fromStdString(adapter.name);
m_ui.adapter->addItem(qadaptername, QVariant(qadaptername));
if (adapter.name == current_adapter_name)

View File

@@ -200,6 +200,7 @@ if(NOT ANDROID)
sdl_audio_stream.cpp
sdl_input_source.cpp
sdl_input_source.h
sdl_video_helpers.h
)
if(ENABLE_OPENGL)
target_sources(util PRIVATE

View File

@@ -37,6 +37,7 @@ LOG_CHANNEL(GPUDevice);
#endif
#ifdef ENABLE_OPENGL
#include "opengl_context.h"
#include "opengl_device.h"
#endif
@@ -394,8 +395,7 @@ std::optional<GPUDevice::AdapterInfoList> GPUDevice::GetAdapterListForAPI(Render
#ifdef ENABLE_OPENGL
case RenderAPI::OpenGL:
case RenderAPI::OpenGLES:
// No way of querying.
ret = AdapterInfoList();
ret = OpenGLContext::GetAdapterList(window_type, error);
break;
#endif

View File

@@ -210,3 +210,13 @@ std::unique_ptr<OpenGLContext> OpenGLContext::Create(WindowInfo& wi, SurfaceHand
return context;
}
GPUDevice::AdapterInfoList OpenGLContext::GetAdapterList(WindowInfoType window_type, Error* error)
{
#ifdef ENABLE_SDL
if (window_type == WindowInfoType::SDL)
return OpenGLContextSDL::GetAdapterList(window_type, error);
#endif
return {};
}

View File

@@ -3,6 +3,7 @@
#pragma once
#include "gpu_device.h"
#include "window_info.h"
#include "common/types.h"
@@ -52,6 +53,8 @@ public:
static std::unique_ptr<OpenGLContext> Create(WindowInfo& wi, SurfaceHandle* surface, bool prefer_gles_context,
Error* error);
static GPUDevice::AdapterInfoList GetAdapterList(WindowInfoType window_type, Error* error);
protected:
Version m_version = {};
};

View File

@@ -1,16 +1,17 @@
// SPDX-FileCopyrightText: 2019-2024 Connor McLaughlin <stenzek@gmail.com>
// SPDX-FileCopyrightText: 2019-2026 Connor McLaughlin <stenzek@gmail.com>
// SPDX-License-Identifier: CC-BY-NC-ND-4.0
#include "opengl_context_sdl.h"
#include "gpu_texture.h"
#include "opengl_loader.h"
#include "sdl_video_helpers.h"
#include "common/assert.h"
#include "common/error.h"
#include "common/log.h"
#include "common/scoped_guard.h"
#include "SDL3/SDL.h"
#include <SDL3/SDL.h>
LOG_CHANNEL(GPUDevice);
@@ -35,6 +36,26 @@ std::unique_ptr<OpenGLContext> OpenGLContextSDL::Create(WindowInfo& wi, SurfaceH
return context;
}
GPUDevice::AdapterInfoList OpenGLContextSDL::GetAdapterList(WindowInfoType window_type, Error* error)
{
std::vector<GPUDevice::ExclusiveFullscreenMode> fullscreen_modes = SDLVideoHelpers::GetFullscreenModeList();
if (fullscreen_modes.empty())
{
// no point adding anything if no modes
return {};
}
// Set some reasonable defaults, since we don't know this until we actually create the context.
GPUDevice::AdapterInfoList ret;
GPUDevice::AdapterInfo& ai = ret.emplace_back();
ai.driver_type = GPUDriverType::Unknown;
ai.max_multisamples = 8;
ai.supports_sample_shading = true;
ai.max_texture_size = 16384;
ai.fullscreen_modes = std::move(fullscreen_modes);
return ret;
}
bool OpenGLContextSDL::Initialize(WindowInfo& wi, SurfaceHandle* surface, std::span<const Version> versions_to_try,
bool share_context, Error* error)
{

View File

@@ -19,6 +19,7 @@ public:
static std::unique_ptr<OpenGLContext> Create(WindowInfo& wi, SurfaceHandle* surface,
std::span<const Version> versions_to_try, Error* error);
static GPUDevice::AdapterInfoList GetAdapterList(WindowInfoType window_type, Error* error);
void* GetProcAddress(const char* name) override;
SurfaceHandle CreateSurface(WindowInfo& wi, Error* error = nullptr) override;

View File

@@ -0,0 +1,54 @@
// SPDX-FileCopyrightText: 2019-2026 Connor McLaughlin <stenzek@gmail.com>
// SPDX-License-Identifier: CC-BY-NC-ND-4.0
#pragma once
#include "gpu_device.h"
#include "common/error.h"
#include "common/log.h"
#include <SDL3/SDL.h>
#include <algorithm>
namespace SDLVideoHelpers {
inline std::vector<GPUDevice::ExclusiveFullscreenMode> GetFullscreenModeList()
{
int display_count = 0;
const SDL_DisplayID* const displays = SDL_GetDisplays(&display_count);
if (display_count <= 0)
{
GENERIC_LOG(Log::Channel::SDL, Log::Level::Error, Log::Color::Default, "SDL_GetDisplays() returned no displays: {}",
SDL_GetError());
return {};
}
std::vector<GPUDevice::ExclusiveFullscreenMode> modes;
for (int i = 0; i < display_count; i++)
{
int dm_count = 0;
const SDL_DisplayMode* const* const dms = SDL_GetFullscreenDisplayModes(displays[i], &dm_count);
if (dm_count <= 0)
{
GENERIC_LOG(Log::Channel::SDL, Log::Level::Error, Log::Color::Default,
"SDL_GetFullscreenDisplayModes() returned no modes for display {}: {}", displays[i], SDL_GetError());
continue;
}
modes.reserve(modes.size() + static_cast<size_t>(dm_count));
for (int j = 0; j < dm_count; j++)
{
const SDL_DisplayMode* const dm = dms[j];
const GPUDevice::ExclusiveFullscreenMode mode{static_cast<u32>(dm->w), static_cast<u32>(dm->h), dm->refresh_rate};
if (std::ranges::find(modes, mode) == modes.end())
modes.push_back(mode);
}
}
return modes;
}
} // namespace SDLVideoHelpers

View File

@@ -92,6 +92,7 @@
<ClInclude Include="postprocessing_shader_fx.h" />
<ClInclude Include="postprocessing_shader_glsl.h" />
<ClInclude Include="postprocessing_shader_slang.h" />
<ClInclude Include="sdl_video_helpers.h" />
<ClInclude Include="sdl_input_source.h" />
<ClInclude Include="shadergen.h" />
<ClInclude Include="shiftjis.h" />

View File

@@ -82,6 +82,7 @@
<ClInclude Include="core_audio_stream.h" />
<ClInclude Include="vulkan_headers.h" />
<ClInclude Include="gpu_types.h" />
<ClInclude Include="sdl_video_helpers.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="state_wrapper.cpp" />

View File

@@ -16,6 +16,7 @@
#include "common/log.h"
#ifdef ENABLE_SDL
#include "sdl_video_helpers.h"
#include <SDL3/SDL_vulkan.h>
#endif
@@ -58,6 +59,8 @@ static void LockedDestroyVulkanInstance();
static bool SelectInstanceExtensions(VulkanDevice::ExtensionList* extension_list, WindowInfoType wtype,
bool debug_instance, Error* error);
static std::vector<GPUDevice::ExclusiveFullscreenMode> EnumerateFullscreenModes(WindowInfoType wtype);
VKAPI_ATTR static VkBool32 VKAPI_CALL DebugMessengerCallback(VkDebugUtilsMessageSeverityFlagBitsEXT severity,
VkDebugUtilsMessageTypeFlagsEXT messageType,
const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData,
@@ -735,6 +738,16 @@ VulkanLoader::GPUList VulkanLoader::EnumerateGPUs(Error* error)
return gpus;
}
std::vector<GPUDevice::ExclusiveFullscreenMode> VulkanLoader::EnumerateFullscreenModes(WindowInfoType wtype)
{
#ifdef ENABLE_SDL
if (wtype == WindowInfoType::SDL)
return SDLVideoHelpers::GetFullscreenModeList();
#endif
return {};
}
bool VulkanLoader::IsSuitableDefaultRenderer(WindowInfoType window_type)
{
#ifdef __ANDROID__
@@ -834,6 +847,7 @@ GPUDriverType VulkanLoader::GuessDriverType(const VkPhysicalDeviceProperties& de
std::optional<GPUDevice::AdapterInfoList> VulkanLoader::GetAdapterList(WindowInfoType window_type, Error* error)
{
std::optional<GPUDevice::AdapterInfoList> ret;
std::vector<GPUDevice::ExclusiveFullscreenMode> fullscreen_modes;
GPUList gpus;
{
const std::lock_guard lock(s_locals.mutex);
@@ -842,6 +856,7 @@ std::optional<GPUDevice::AdapterInfoList> VulkanLoader::GetAdapterList(WindowInf
if (s_locals.instance != VK_NULL_HANDLE)
{
gpus = EnumerateGPUs(error);
fullscreen_modes = EnumerateFullscreenModes(window_type);
}
else
{
@@ -851,6 +866,7 @@ std::optional<GPUDevice::AdapterInfoList> VulkanLoader::GetAdapterList(WindowInf
return ret;
gpus = EnumerateGPUs(error);
fullscreen_modes = EnumerateFullscreenModes(window_type);
LockedReleaseVulkanInstance();
}
@@ -858,8 +874,18 @@ std::optional<GPUDevice::AdapterInfoList> VulkanLoader::GetAdapterList(WindowInf
ret.emplace();
ret->reserve(gpus.size());
for (auto& [physical_device, adapter_info] : gpus)
ret->push_back(std::move(adapter_info));
for (size_t i = 0; i < gpus.size(); i++)
{
GPUDevice::AdapterInfo& ai = gpus[i].second;
// splat fullscreen modes across gpus
if (i == (gpus.size() - 1))
ai.fullscreen_modes = std::move(fullscreen_modes);
else
ai.fullscreen_modes = fullscreen_modes;
ret->push_back(std::move(ai));
}
return ret;
}