WIP - Windows high-DPI support

Hi, I wanted to share my progress on implementing high-DPI support for Windows.

I’m hosting the code on github, and I imagine it’s going to need further development before it’s ready to be merged.


Here is the current patch: windows-highdpi-may25.diff (41.9 KB)

It’s (unfortunately) a fairly large and invasive patch, so I wanted to start a discussion and ask if anyone wants to help test.

Here is an overview:

  • The overall goal of the patch is to allow drawing at the monitor’s native resolution, while making SDL act the same as when it was DPI-unaware on a high-DPI monitor with Windows providing DPI virtualization. i.e. if you have a 640x480 window and drag it between a 100% scaled and 200% scaled monitors, the SDL window size stays 640x480, but when it’s on the 200% monitor, the SDL_GL_GetDrawableSize function will return 1280x960.

  • Instead of the SDL_WINDOW_ALLOW_HIGHDPI window flag, you need to use a new hint, SDL_HINT_VIDEO_HIGHDPI_ENABLED, because until recently, DPI awareness was a process-wide setting on Windows. If SDL only supported high DPI on Win 10 Anniversary Update and later, we could stick with the window flag. I adjusted the testcommon code so passing the --allow-highdpi flag enables the new hint instead of the window flag.

  • This should work on Vista and higher, although so far I’ve only been developing and testing on Windows 10 Creators Update. The major changes in Windows’s high DPI support were 8.1 getting per-monitor scaling support, and Windows 10 Anniversary Update getting the ability to change DPI awareness temporarily/per-window, which I’m not taking advantage of here.

  • To motivate some of the design, I did most of my testing with the following configuration:

    • On the left, the primary monitor, a 2880x1800 monitor with 200% scaling (what windows calls 192dpi) and a virtual size of 1440x900.
    • On the right, a 1920x1080 monitor with 100% scaling (96dpi). Windows considers this monitor’s origin to be at (2880, 0)

An important thing to note about Windows’s DPI virtualization is, in DPI unaware applications (e.g. SDL without this patch), windows on my right monitor have their X coordinates start at 2880. DPI unaware applications see the left monitor as extending from (0, 0) to (1440, 900), so this means there is a big gap in the coordinate system between the left (200% scaled) monitor and the right monitor.

My patch implements this same behaviour when you enable DPI awareness, so the monitor bounds reported by SDL remain the same whether DPI awareness is disabled / enabled, and SDL window positions/sizes should give you the same apparent position/size when DPI awareness is on/off. (try launching the SDL test applications with --info all)

That’s all that comes to mind for now; any feedback/questions are welcome :slight_smile:

I won’t have time to look at this until the weekend, but I just wanted to quickly say - good job and thanks! Doing something like this has been on my TODO list for a while. I’m glad I was beaten to the punch. :slight_smile:

The DPI flag situation is a bit unfortunate (due to Microsoft’s API choices)…

High DPI is also necessary to fix issues with window sizes when a user selects a Text/Scale option in newer versions of Windows that are greater than 100% (Ie setting 125% on a 1080p tv 32" tv so the text is actually legible in the OS from a distance)

This seems to be an issue with most id Tech and SDL based idTech games.

This seems to be an issue with most id Tech and SDL based idTech games.

Yeah - in Quakespasm we force DPI awareness on, so the game’s window is tiny on high-dpi displays. The initial reason we did that was to workaround https://bugzilla.libsdl.org/show_bug.cgi?id=2713

We also had that problem in another game using a totally different
engine (C4), not using SDL. (We fixed it by calling
SetProcessDPIAware(ness), similar to Erics snippet here:


)

Maybe the common denominator is OpenGL?

Cheers,
Daniel

Hi!

Do you have any update on this feature?

Could you please give an update on the state of this feature? When do you plan to merge it?

Having the same scaling issues with the Windows build of ProjectM which is using SDL v2.0.9.0

Windows seems to treat the programs using this library as non scalable and thus giving them a “fake” resolution depending on the scaling chosen. So on my 3840x2160 display, at 150-175% it fullscreens to 2560x1440, at 200% 1920x1080, and at 300% 1280x720

As I said on the github page I found a workaround, but that causes the window to act weirdly when in windowed mode. So I would gladly welcome high-DPI to be implemented

Eric, this looks pretty good and I’m surprised it has not been merged yet and that this feature is still missing 3 years later. Is there anything that could be done to expedite this? Have the maintainers provided any feedback about your patch? Personally, I’d try to keep using the SDL_WINDOW_ALLOW_HIGHDPI window flag for consistency with other backends, which do not require an API change.

The latest feedback is in this thread: https://bugzilla.libsdl.org/show_bug.cgi?id=3281#c18

However I’m not aware of any progress since the last comment. I suppose any extra help (given the discussion in the comments there) would be appreciated. :slight_smile:

2 Likes

Could you please give update on this issue? The conversation about this topic on bugzilla/github stopped over a year ago.

This is a crucial feature, since most users have high dpi displays nowdays. Despite most gamers use windows, SDL_WINDOW_ALLOW_HIGHDPI is only available on OSX and Linux.

I have 125% scaling factor on my machine. Unfortunately if I create a window with SDL_WINDOW_ALLOW_HIGHDPI, it is just scaled up, it is blurry, and SDL_GetDisplayDPI gives me 96.

I could fix it by enabling “dpi awareness” in Visual Studio, so I get the correct values from SDL_GetDisplayDPI. But if I create a 800x600 window, the SDL_GL_GetDrawableSize is 800x600. Shouldn’t it be 1000x750 instead?

I am also afraid, that if I fix it somehow and release the game, then once you patch it someday, my game will be buggy if someone uses it with an updated version of SDL2.dll .

What about the float mouse coordinates? It was mentioned in the discussion, but I was not able to find anything about it,

(EDIT: there was a post made today in this thread but it’s gone now for me. I guess they deleted it?)

There are no updates to give because no one has worked on it, as far as I know.

SDL is open source and relies partly on outside contributions, such as Eric’s work. If someone who has the time and ability is willing to rebase his work onto the latest SDL and continue it, I’m sure that would be appreciated by a lot of people.

1 Like