From 6dd5ed8534a767befb91e2fdb72d440fabfc8970 Mon Sep 17 00:00:00 2001 From: Maia Everett Date: Mon, 22 Apr 2024 14:49:55 +0300 Subject: [PATCH] Fix blurry window on native Wayland --- .../DesktopEnvironment/DesktopHelpers.cs | 2 - .../DesktopEnvironment/SdlHelpers.cs | 14 +++ .../DesktopEnvironment/XLVeldridStartup.cs | 88 +++++++++++++++++++ src/XIVLauncher.Core/Program.cs | 12 ++- 4 files changed, 111 insertions(+), 5 deletions(-) create mode 100644 src/XIVLauncher.Core/DesktopEnvironment/XLVeldridStartup.cs diff --git a/src/XIVLauncher.Core/DesktopEnvironment/DesktopHelpers.cs b/src/XIVLauncher.Core/DesktopEnvironment/DesktopHelpers.cs index 79a56b2f..9b26d53d 100644 --- a/src/XIVLauncher.Core/DesktopEnvironment/DesktopHelpers.cs +++ b/src/XIVLauncher.Core/DesktopEnvironment/DesktopHelpers.cs @@ -163,8 +163,6 @@ private static float GetXWaylandScaleFactor() while ((line = process.StandardOutput.ReadLine()) != null) { - Console.WriteLine("L {0}", line); - var match = XrdbRegex().Match(line); if (match != null && match.Success) diff --git a/src/XIVLauncher.Core/DesktopEnvironment/SdlHelpers.cs b/src/XIVLauncher.Core/DesktopEnvironment/SdlHelpers.cs index 14fff817..963dedd3 100644 --- a/src/XIVLauncher.Core/DesktopEnvironment/SdlHelpers.cs +++ b/src/XIVLauncher.Core/DesktopEnvironment/SdlHelpers.cs @@ -1,7 +1,9 @@ using System.Numerics; using System.Runtime.InteropServices; using System.Text; + using Serilog; + using Veldrid.Sdl2; namespace XIVLauncher.Core.DesktopEnvironment; @@ -21,6 +23,11 @@ internal static unsafe partial class SdlHelpers private static int SDL_GetDisplayDPI(int displayIndex, float* ddpi, float* hdpi, float* vdpi) => s_sdl_getDisplayDPI(displayIndex, ddpi, hdpi, vdpi); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + private delegate void SDL_GL_GetDrawableSize_t(SDL_Window SDL2Window, int* w, int* h); + private static SDL_GL_GetDrawableSize_t s_getDrawableSize = Sdl2Native.LoadFunction("SDL_GL_GetDrawableSize"); + private static void SDL_GL_GetDrawableSize(SDL_Window Sdl2Window, int* w, int* h) => s_getDrawableSize(Sdl2Window, w, h); + private static unsafe string GetString(byte* stringStart) { int characters = 0; @@ -51,4 +58,11 @@ public static Vector2 GetDisplayDpiScale() Log.Verbose("SDL reports {0}x{1} DPI", hdpi, vdpi); return new Vector2(hdpi / 96, vdpi / 96); } + + public static Vector2 GetWindowScale(Sdl2Window window) + { + int width, height; + SDL_GL_GetDrawableSize(window.SdlWindowHandle, &width, &height); + return new Vector2((float)width / window.Width, (float)height / window.Height); + } } diff --git a/src/XIVLauncher.Core/DesktopEnvironment/XLVeldridStartup.cs b/src/XIVLauncher.Core/DesktopEnvironment/XLVeldridStartup.cs new file mode 100644 index 00000000..2296f117 --- /dev/null +++ b/src/XIVLauncher.Core/DesktopEnvironment/XLVeldridStartup.cs @@ -0,0 +1,88 @@ +using Veldrid; +using Veldrid.Sdl2; +using Veldrid.StartupUtilities; + +namespace XIVLauncher.Core.DesktopEnvironment; + +// Patched piece of VeldridStartup to pass SDL_WindowFlags.AllowHighDpi to SDL_CreateWindow +public static class XLVeldridStartup +{ + public static void CreateWindowAndGraphicsDevice( + WindowCreateInfo windowCI, + out Sdl2Window window, + out GraphicsDevice gd) + => CreateWindowAndGraphicsDevice( + windowCI, + new GraphicsDeviceOptions(), + VeldridStartup.GetPlatformDefaultBackend(), + out window, + out gd); + + public static void CreateWindowAndGraphicsDevice( + WindowCreateInfo windowCI, + GraphicsDeviceOptions deviceOptions, + out Sdl2Window window, + out GraphicsDevice gd) + => CreateWindowAndGraphicsDevice(windowCI, deviceOptions, VeldridStartup.GetPlatformDefaultBackend(), out window, out gd); + + public static void CreateWindowAndGraphicsDevice( + WindowCreateInfo windowCI, + GraphicsDeviceOptions deviceOptions, + GraphicsBackend preferredBackend, + out Sdl2Window window, + out GraphicsDevice gd) + { + Sdl2Native.SDL_Init(SDLInitFlags.Video); + if (preferredBackend == GraphicsBackend.OpenGL || preferredBackend == GraphicsBackend.OpenGLES) + { + VeldridStartup.SetSDLGLContextAttributes(deviceOptions, preferredBackend); + } + + window = CreateWindow(ref windowCI); + gd = VeldridStartup.CreateGraphicsDevice(window, deviceOptions, preferredBackend); + } + + + public static Sdl2Window CreateWindow(WindowCreateInfo windowCI) => CreateWindow(ref windowCI); + + public static Sdl2Window CreateWindow(ref WindowCreateInfo windowCI) + { + SDL_WindowFlags flags = SDL_WindowFlags.OpenGL | SDL_WindowFlags.Resizable | SDL_WindowFlags.AllowHighDpi + | GetWindowFlags(windowCI.WindowInitialState); + if (windowCI.WindowInitialState != WindowState.Hidden) + { + flags |= SDL_WindowFlags.Shown; + } + Sdl2Window window = new Sdl2Window( + windowCI.WindowTitle, + windowCI.X, + windowCI.Y, + windowCI.WindowWidth, + windowCI.WindowHeight, + flags, + false); + + return window; + } + + private static SDL_WindowFlags GetWindowFlags(WindowState state) + { + switch (state) + { + case WindowState.Normal: + return 0; + case WindowState.FullScreen: + return SDL_WindowFlags.Fullscreen; + case WindowState.Maximized: + return SDL_WindowFlags.Maximized; + case WindowState.Minimized: + return SDL_WindowFlags.Minimized; + case WindowState.BorderlessFullScreen: + return SDL_WindowFlags.FullScreenDesktop; + case WindowState.Hidden: + return SDL_WindowFlags.Hidden; + default: + throw new VeldridException("Invalid WindowState: " + state); + } + } +} diff --git a/src/XIVLauncher.Core/Program.cs b/src/XIVLauncher.Core/Program.cs index 99015b02..0a347c12 100644 --- a/src/XIVLauncher.Core/Program.cs +++ b/src/XIVLauncher.Core/Program.cs @@ -265,16 +265,22 @@ private static void Main(string[] args) var windowWidth = (int)ImGuiHelpers.GetScaled(1280); var windowHeight = (int)ImGuiHelpers.GetScaled(800); - VeldridStartup.CreateWindowAndGraphicsDevice( + XLVeldridStartup.CreateWindowAndGraphicsDevice( new WindowCreateInfo(50, 50, windowWidth, windowHeight, WindowState.Normal, $"XIVLauncher {version}"), new GraphicsDeviceOptions(false, null, true, ResourceBindingModel.Improved, true, true), out window, out gd); + var windowScale = SdlHelpers.GetWindowScale(window).Y; + ImGuiHelpers.GlobalScale *= windowScale; + window.Resized += () => { - gd.MainSwapchain.Resize((uint)window.Width, (uint)window.Height); - bindings.WindowResized(window.Width, window.Height); + var scaledWidth = (int)Math.Round(window.Width * windowScale); + var scaledHeight = (int)Math.Round(window.Height * windowScale); + + gd.MainSwapchain.Resize((uint)scaledWidth, (uint)scaledHeight); + bindings.WindowResized(scaledWidth, scaledHeight); Invalidate(); }; cl = gd.ResourceFactory.CreateCommandList();