Compare commits

..

9 Commits

Author SHA1 Message Date
Stenzek
5a7c855256 FullscreenUI: Use command/option key icons on MacOS
And the Windows icon on Windows.
2026-02-18 17:18:03 +10:00
Stenzek
9f94d6b0a0 OpenGLDevice: Fix incorrect SDL MakeCurrent()/DoneCurrent() usage
Too bad multiple windows on a single aren't supported properly.

Should just rip this whole thing out.
2026-02-16 22:49:00 +10:00
Stenzek
6a4ae21f33 VulkanDevice: Destroy context on zero refs with SDL window type
If it's not destroyed, it prevents OpenGL contexts from being created
without any errors...
2026-02-16 22:49:00 +10:00
Stenzek
3b17273281 CMake: Ensure resources directory exists before rcc
Fixes spurious build failures on low core count machines.
2026-02-16 22:49:00 +10:00
Stenzek
5add36e4ef GameDB: Add sort names for NFS/NASCAR games 2026-02-16 22:43:21 +10:00
Stenzek
91ba5ab2ed GameDB: Add NeGconRumble to a bunch of supported games 2026-02-16 22:43:21 +10:00
Stenzek
7a0fee0532 FullscreenUI: Fix mode list not populating on default adapter 2026-02-16 22:43:21 +10:00
Stenzek
d5eb3e10ea GPUDevice: Enumerate fullscreen modes if using SDL 2026-02-16 22:43:21 +10:00
Stenzek
0d0bd69ada Mini: Set fullscreen display mode on "windows" on kmsdrm
Allow the user to choose the display mode.
2026-02-16 22:43:21 +10:00
6 changed files with 48 additions and 26 deletions

View File

@@ -295,8 +295,6 @@
#define ICON_PF_KEY_TILDE "\xF0\x9F\xB3\x99"
#define ICON_PF_KEY_DASH "\xF0\x9F\xB3\x9A"
#define ICON_PF_KEY_EQUAL "\xF0\x9F\xB3\x9B"
#define ICON_PF_KEY_LEFT_ALT "\xF0\x9F\xB3\x9C"
#define ICON_PF_KEY_RIGHT_ALT "\xF0\x9F\xB3\x9D"
#define ICON_PF_KEY_LEFT_CTRL "\xF0\x9F\xB3\x9E"
#define ICON_PF_KEY_RIGHT_CTRL "\xF0\x9F\xB3\x9F"
#define ICON_PF_KEY_LEFT_SHIFT "\xF0\x9F\xB3\xA0"
@@ -379,7 +377,6 @@
#define ICON_PF_DUALSHOCK_CONTROLLER "\xF0\x9F\xB3\xA4"
#define ICON_PF_PLAYSTATION "\xF0\x9F\xB3\xA5"
#define ICON_PF_XBOX "\xF0\x9F\xB3\xA6"
#define ICON_PF_KEY_SUPER "\xF0\x9F\xB3\xA7"
#define ICON_PF_KEY_NUMPAD_1 "\xF0\x9F\xB3\xA8"
#define ICON_PF_KEY_NUMPAD_2 "\xF0\x9F\xB3\xA9"
#define ICON_PF_KEY_NUMPAD_3 "\xF0\x9F\xB3\xAA"
@@ -397,7 +394,20 @@
#define ICON_PF_KEY_NUMPAD_DIVIDE "\xF0\x9F\xB3\xB6"
#define ICON_PF_KEY_NUMPAD_MULTIPLY "\xF0\x9F\xB3\xB7"
#define ICON_PF_KEY_NUMPAD_EQUAL "\xF0\x9F\xB3\xB8"
#define ICON_PF_KEY_OPTION "\xF0\x9F\xB3\xB9"
#define ICON_PF_KEY_COMMAND "\xF0\x9F\xB3\xBA"
#define ICON_PF_MENU "\xF0\x9F\xB3\xBB"
#define ICON_PF_KEY_MINUS "\xF0\x9F\xB3\xBC"
// Platform specific keys.
#if defined(_WIN32)
#define ICON_PF_KEY_SUPER "\xE2\x90\xAA"
#define ICON_PF_KEY_LEFT_ALT "\xF0\x9F\xB3\x9C"
#define ICON_PF_KEY_RIGHT_ALT "\xF0\x9F\xB3\x9D"
#elif defined(__APPLE__)
#define ICON_PF_KEY_SUPER "\xF0\x9F\xB3\xBA"
#define ICON_PF_KEY_LEFT_ALT "\xF0\x9F\xB3\xB9"
#define ICON_PF_KEY_RIGHT_ALT "\xF0\x9F\xB3\xB9"
#else
#define ICON_PF_KEY_SUPER "\xF0\x9F\xB3\xA7"
#define ICON_PF_KEY_LEFT_ALT "\xF0\x9F\xB3\x9C"
#define ICON_PF_KEY_RIGHT_ALT "\xF0\x9F\xB3\x9D"
#endif

View File

@@ -4070,10 +4070,7 @@ void FullscreenUI::DrawGraphicsSettingsPage()
else
bsi->SetStringValue("GPU", "FullscreenMode", value);
SetSettingsChanged(bsi);
Host::RunOnCoreThread([]() {
if (VideoThread::IsFullscreen())
VideoThread::RecreateRenderWindow();
});
ShowToast(OSDMessageType::Info, std::string(), FSUI_STR("Resolution change will be applied after restarting."));
};
OpenChoiceDialog(FSUI_ICONVSTR(ICON_FA_TV, "Fullscreen Resolution"), false, std::move(options),
std::move(callback));

View File

@@ -611,6 +611,7 @@ TRANSLATE_NOOP("FullscreenUI", "Reset Settings");
TRANSLATE_NOOP("FullscreenUI", "Resets all configuration to defaults (including bindings).");
TRANSLATE_NOOP("FullscreenUI", "Resets all settings to the defaults.");
TRANSLATE_NOOP("FullscreenUI", "Resets memory card directory to default (user directory).");
TRANSLATE_NOOP("FullscreenUI", "Resolution change will be applied after restarting.");
TRANSLATE_NOOP("FullscreenUI", "Restart Game");
TRANSLATE_NOOP("FullscreenUI", "Restore Defaults");
TRANSLATE_NOOP("FullscreenUI", "Resume Game");

View File

@@ -95,6 +95,7 @@ static std::string GetWindowTitle(const std::string& game_title);
static std::optional<WindowInfo> TranslateSDLWindowInfo(SDL_Window* win, Error* error);
static bool GetSavedPlatformWindowGeometry(s32* x, s32* y, s32* width, s32* height);
static void SavePlatformWindowGeometry(s32 x, s32 y, s32 width, s32 height);
static void DestroySDLWindow();
struct SDLHostState
{
@@ -510,6 +511,9 @@ std::optional<WindowInfo> Host::AcquireRenderWindow(RenderAPI render_api, bool f
std::optional<WindowInfo> wi;
Host::RunOnUIThread([render_api, fullscreen, error, &wi]() {
// Don't try to create multiple windows, kmsdrm breaks.
DestroySDLWindow();
const std::string window_title = GetWindowTitle(System::GetGameTitle());
const SDL_PropertiesID props = SDL_CreateProperties();
SDL_SetStringProperty(props, SDL_PROP_WINDOW_CREATE_TITLE_STRING, window_title.c_str());
@@ -628,27 +632,34 @@ void Host::ReleaseRenderWindow()
return;
Host::RunOnUIThread([]() {
if (!(SDL_GetWindowFlags(s_state.sdl_window) & SDL_WINDOW_FULLSCREEN))
{
int window_x = SDL_WINDOWPOS_UNDEFINED, window_y = SDL_WINDOWPOS_UNDEFINED;
int window_width = DEFAULT_WINDOW_WIDTH, window_height = DEFAULT_WINDOW_HEIGHT;
SDL_GetWindowPosition(s_state.sdl_window, &window_x, &window_y);
SDL_GetWindowSize(s_state.sdl_window, &window_width, &window_height);
MiniHost::SavePlatformWindowGeometry(window_x, window_y, window_width, window_height);
}
SDL_DestroyWindow(s_state.sdl_window);
s_state.sdl_window = nullptr;
DestroySDLWindow();
s_state.platform_window_updated.Post();
});
s_state.platform_window_updated.Wait();
}
void MiniHost::DestroySDLWindow()
{
if (!s_state.sdl_window)
return;
if (!(SDL_GetWindowFlags(s_state.sdl_window) & SDL_WINDOW_FULLSCREEN))
{
int window_x = SDL_WINDOWPOS_UNDEFINED, window_y = SDL_WINDOWPOS_UNDEFINED;
int window_width = DEFAULT_WINDOW_WIDTH, window_height = DEFAULT_WINDOW_HEIGHT;
SDL_GetWindowPosition(s_state.sdl_window, &window_x, &window_y);
SDL_GetWindowSize(s_state.sdl_window, &window_width, &window_height);
MiniHost::SavePlatformWindowGeometry(window_x, window_y, window_width, window_height);
}
SDL_DestroyWindow(s_state.sdl_window);
s_state.sdl_window = nullptr;
}
bool Host::CanChangeFullscreenMode(bool new_fullscreen_state)
{
return true;
return !MiniHost::s_state.use_window_fullscreen_mode;
}
void Host::BeginTextInput()

View File

@@ -301,7 +301,7 @@ if(NOT APPLE)
add_dependencies(duckstation-qt duckstation-qt-rcc)
# Need to ensure the resources directory exists, it might not. Happens when low CPU count and parallel builds.
add_custom_target(duckstation-qt-rcc-mkdir COMMAND ${CMAKE_COMMAND} -E create_directory "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/resources")
add_custom_target(duckstation-qt-rcc-mkdir COMMAND ${CMAKE_COMMAND} -E make_directory "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/resources")
add_dependencies(duckstation-qt-rcc duckstation-qt-rcc-mkdir)
else()
set(RCC_FILE "${CMAKE_CURRENT_BINARY_DIR}/duckstation-qt.rcc")

View File

@@ -124,7 +124,10 @@ OpenGLContext::SurfaceHandle OpenGLContextSDL::CreateSurface(WindowInfo& wi, Err
void OpenGLContextSDL::DestroySurface(SurfaceHandle handle)
{
// cleaned up on window destruction?
// cleaned up on window destruction? but we still need to clear current
SDL_Window* const window = static_cast<SDL_Window*>(handle);
if (m_current_window == window)
DoneCurrent();
}
void OpenGLContextSDL::ResizeSurface(WindowInfo& wi, SurfaceHandle handle)
@@ -159,7 +162,7 @@ bool OpenGLContextSDL::MakeCurrent(SurfaceHandle surface, Error* error /* = null
if (m_current_window == window)
return true;
if (SDL_GL_MakeCurrent(window, m_context) != 0)
if (!SDL_GL_MakeCurrent(window, m_context))
{
ERROR_LOG("SDL_GL_MakeCurrent() failed: {}", SDL_GetError());
return false;
@@ -171,7 +174,7 @@ bool OpenGLContextSDL::MakeCurrent(SurfaceHandle surface, Error* error /* = null
bool OpenGLContextSDL::DoneCurrent()
{
if (SDL_GL_MakeCurrent(nullptr, nullptr) != 0)
if (!SDL_GL_MakeCurrent(nullptr, nullptr))
return false;
m_current_window = nullptr;