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