Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Windows high-dpi / DPI scaling support #5778

Merged
merged 11 commits into from
Jun 11, 2022

Conversation

ericwa
Copy link
Contributor

@ericwa ericwa commented Jun 9, 2022

Description

This PR builds on top of #5393 to finish adding high DPI support on Windows. In this PR, our own "SDL" coordinate system (in DPI-scaled points) is established - so SDL window positions, sizes, mouse events, etc. are all in this new coordinate system.

Behaviour

Assuming the new hint SDL_WINDOWS_DPI_SCALING is set to 1:

  • Creating a window that's 640x480 (as the size passed to SDL_CreateWindow), on a display with 125% scaling set in Windows display settings, will create a window with an 800x600 client area (in pixels). Dragging it to a second monitor that uses 100% scaling will resize the client area to 640x480 pixels.

  • SDL_WINDOWEVENT_SIZE_CHANGED is emitted when a window's DPI changes. It always sends the window size in points, even as the client area size in pixels is changing due to DPI changes. This matches SDL's behaviour on macOS, I believe.

  • SDL displays have their bounds position specified in pixels, but size in DPI-scaled points.

  • Display modes returned by SDL are currently always in pixels (technically violating the SDL documentation, which says they're points)

    • This is something @slime73 and I have discussed a bit in the past. To expand on what this means, my 4K monitor set to use 125% scaling (in Windows settings), which translates to a point size of 3072x1728

      Currently, this PR will return SDL display modes for 3840x2160 (pixels) but not 3072x1728 (points).
      The way Windows (ChangeDisplaySettingsExW) treats the issue is, any 3840x2160 pixel modes will return 120 DPI (=125% scale) as the monitor DPI when you change to those modes (given that I'm using 125% scaling on the desktop), and any other modes will return 96 DPI (=100% scale).

      So, if we followed the docs and returned modes in points, 3840x2160 would not be listed in the mode list but rather 3072x1728. The rest of the modes would be the expected ones 2560x1440, 1920x1080, etc.

      We could follow the docs strictly and return points - though not having a 3840x2160 mode on a 4K monitor seems strange to me, and we currently lack an API to query the pixel size of a display mode (if they're truly given as points).

SDL_WINDOWS_DPI_SCALING hint

The new DPI scaling is opt-in with a hint SDL_WINDOWS_DPI_SCALING=1. Setting this hint should be all that's needed for high DPI support if a game is already written with SDL's macOS/Wayland DPI awareness support in mind (i.e., as long as it uses SDL_GL_GetDrawableSize/SDL_GetRendererOutputSize() and doesn't assume SDL_GetWindowSize() is the drawable size in pixels).

Without setting SDL_WINDOWS_DPI_SCALING=1, behaviour is as before (games that don't declare any DPI awareness will get Windows-provided "bitmap scaling" on a >100% scaled monitor. Games that declare DPI awareness somehow (manifest, calling SetProcessDpiAwareness, etc.) will continue to get 1 SDL unit = 1 pixel.)

Setting the hint SDL_WINDOWS_DPI_SCALING=1 should cooperate with the DPI awareness being already set (or not) - if the process is not already DPI aware, SDL will attempt to enable "per-monitor V2", and if that's not available on the current version of Windows, fall back to older methods (the implementation used for this is from my earlier PR #5393). If the game is already DPI aware, and SDL_WINDOWS_DPI_SCALING=1 is requested, we'll use whatever the awareness was - the SDL_WINDOWS_DPI_SCALING=1 codepaths handle any of the dpi awareness levels (system, permonitor, permonitorv2).

The window flag SDL_WINDOW_ALLOW_HIGHDPI is not used by this PR, although I did make the SDL_WINDOWS_DPI_SCALING=1 hint also force set the ALLOW_HIGHDPI flag on windows, in case application code is checking for that hint. It would be ideal if we could just use the window flag and not need a new hint but it doesn't look like that's an option. (In a previous discussion of my WIP patch there was a suggestion to try always enabling DPI awareness, then if an SDL window is created without the ALLOW_HIGHDPI flag, we could use the windows API's for setting DPI awareness per window to opt out of DPI awareness on those windows and use OS scaling. I tried this and couldn't get it to work, at least on Windows 10/Nvidia drivers - for OpenGL at least, the drivers seem to only care about the process DPI awareness setting and not respect the per-window settings. I couldn't find any bug reports or indication that anyone else has ever tried this approach either.)

Implementation Comments

The changes fall into the following categories:

  • Updating the Windows SDL renderer backends to remove the assumption that SDL_GetWindowSize returns the backbuffer size in pixels (instead calling WIN_GetDrawableSize, a wrapper around GetClientRect) - this part is pretty straightforward.
  • Calling conversion functions anywhere we transfer positions or sizes between Windows and SDL, to convert between pixels/points e.g. WIN_ClientPointToSDL (converts pixels -> points), WIN_ScreenPointFromSDL converts a SDL screen space coordinate like a window position, or a global mouse position to a Windows screen coordinate.
    • This is a likely source of bugs, if I missed a place in SDL's Windows code that should have a conversion.
  • Debug logging guarded by #ifdef HIGHDPI_DEBUG. As I've been maintaining / working on this patch on and off for several years now, I found it important to be able to turn on detailed logging with a #define. Also some things are more or less impossible to debug traditionally with breakpoints (e.g. exclusive fullscreen mode), so having detailed logging was imporatant.
    • That said - I'm fine with reducing the amount of #ifdef HIGHDPI_DEBUG logging if it seems excessive
  • Implementing the coordinate conversion functions. The ones for points in the client area are straightforward (WIN_ClientPointToSDL, WIN_ClientPointFromSDL) because we have a cached DPI value for the window.

Known bugs

  • Calling SDL_SetWindowPosition when a window is overlapping 2 screens with different DPI scales can cause it to grow/shrink
    • Only when the target location is also around the seam between the monitors - won't happen when centering on a display
    • Can reproduce this with testwm2 by placing the window on the seam between two monitors, then using the "Shift+Up/Down" arrow key bindings.
    • I think what's going on here is WIN_AdjustWindowRectWithStyle -> WIN_ScreenPointFromSDL is guessing a DPI based on the upper-left corner of the window's client area, which is different than the DPI Windows considers the window to have.

Testing

To give ideas of how to test this, or areas to test that I've missed, here's what I've typically been trying:

  • Windows 10, 21H2

  • Nvidia 512.77

  • My monitor setup:

    • primary monitor: 3840x1260 pixels at (0, 0), 125% scale
    • secondary monitor, positioned to the right: 2560x1440 pixels at (3840,278), 100% scale
  • SDL test apps with different renderer / graphics API's:

    • All of these I launch with environment variable SDL_WINDOWS_DPI_SCALING=1
    • testwm2 --renderer direct3d11
    • testwm2 --renderer direct3d
    • testwm2 --renderer opengl
    • testwm2 --min-geometry 640x480 --max-geometry 800x600
    • testgl2
    • testvulkan
    • testgles2
    • testautomation
    • testautomation --filter video_setWindowCenteredOnDisplay
  • Use cases I test:

    • Cases where the window should resize respecting the scale factor, but keep its window size in SDL units:
      • Change the scale factor in Windows of the 4K monitor e.g. from 125% to 150%
      • Drag the window between monitors
      • Use the Alt+left/right keybind in the SDL demo apps to move the window between monitors
    • Ctrl+enter key bind to enter/leave exclusive fullscreen
      • Make sure window size is restored correctly even on highdpi monitor
    • Alt+enter to enter/leave desktop fullscreen
      • Make sure window size is restored correctly even on highdpi monitor

Existing Issue(s)

#4908
#2119

ericwa added 10 commits March 9, 2022 21:42
The hint allows setting a specific DPI awareness ("unaware", "system", "permonitor", "permonitorv2").

This is the first part of High-DPI support on Windows ( libsdl-org#2119 ).
It doesn't implement a virtualized SDL coordinate system, which will be
addressed in a later commit. (This hint could be useful for SDL apps
that want 1 SDL unit = 1 pixel, though.)

Detecting and behaving correctly under per-monitor V2
(calling AdjustWindowRectExForDpi where needed) should fix the
following issues:

libsdl-org#3286
libsdl-org#4712
If the move results in a DPI change, we need to allow the window to resize (e.g. AdjustWindowRectExForDpi frame sizes are different).

- WM_DPICHANGED: Don't assume WM_GETDPISCALEDSIZE is always called for PMv2 awareness - it's only called during interactive dragging.

- WIN_AdjustWindowRectWithStyle: always calculate final window size including frame based on the destination rect,
not based on the current window DPI.

- Update wmmsg.h to include WM_GETDPISCALEDSIZE (for WMMSG_DEBUG)

- WIN_AdjustWindowRectWithStyle: add optional logging

- WM_GETMINMAXINFO: add optional HIGHDPI_DEBUG logging

- WM_DPICHANGED: fix potentially clobbering data->expected_resize

Together these changes fix the following scenario:
- launch testwm2 with the SDL_WINDOWS_DPI_AWARENESS=permonitorv2 environment variable
- Windows 10 21H2 (OS Build 19044.1706)
- Left (primary) monitor: 3840x2160, 125% scaling
- Right (secondary) monitor: 2560x1440, 100% scaling

- Alt+Enter, Alt+Enter (to enter + leave desktop fullscreen), Alt+Right (to move window to right monitor). Ensure the window client area stays 640x480. Drag the window back to the 125% monitor, ensure client area stays 640x480.
…tartup if defined

document some additional quirks
Adds hint "SDL_WINDOWS_DPI_SCALING" which can be set to "1" to
change the SDL coordinate system units to be DPI-scaled points, rather
than pixels everywhere.

This means windows will be appropriately sized, even when created on
high-DPI displays with scaling.

e.g. requesting a 640x480 window from SDL, on a display with 125%
scaling in Windows display settings, will create a window with an
800x600 client area (in pixels).

Setting this to "1" implicitly requests process DPI awareness
(setting SDL_WINDOWS_DPI_AWARENESS is unnecessary),
and forces SDL_WINDOW_ALLOW_HIGHDPI on all windows.
…NT_SIZE_CHANGED, not SDL_WINDOWEVENT_RESIZED

Fixes bug with viewport not updating when moving window between monitors with different scale
factors on Windows (this should also fix the same issue on other OS'es, though untested)
@Clownacy
Copy link
Contributor

Clownacy commented Jun 9, 2022

So SDL_WINDOW_ALLOW_HIGHDPI doesn't work because driver support for per-window DPI settings on Windows is broken, meaning that a program-wide SDL_WINDOWS_DPI_AWARENESS hint must be used instead?

For the sake of having a consistent API across all supported platforms, would it be worth adding a new function to SDL's API to set high-DPI support program-wide, to somewhat replace SDL_WINDOW_ALLOW_HIGHDPI since it refuses to work universally? I can't imagine that many people use multiple windows with differing DPIs, so I don't think that this is an unacceptable compromise.

@ericwa
Copy link
Contributor Author

ericwa commented Jun 9, 2022

Yeah, exactly. Unifying the ways of declaring High-DPI support across platforms was my initial goal as well, e.g. instead of SDL_WINDOWS_DPI_AWARENESS the hint could be SDL_ALLOW_HIGHDPI, and it could activate this PR's code on Windows, and the SDL_WINDOW_ALLOW_HIGHDPI codepaths on macOS/Wayland.

@slouken
Copy link
Collaborator

slouken commented Jun 9, 2022

@ericwa, @icculus, @slime73, can we set up a Zoom call this weekend to go over this in more detail? When works best for you guys?

@ericwa
Copy link
Contributor Author

ericwa commented Jun 10, 2022

Sure, yeah. I'm in UTC-7/Mountain. Pretty open Saturday or Sunday.

@icculus
Copy link
Collaborator

icculus commented Jun 10, 2022

I can be around whenever, with a little advance notice.

@slouken
Copy link
Collaborator

slouken commented Jun 10, 2022

Sam Lantinga is inviting you to a scheduled Zoom meeting.

Topic: Sam Lantinga's Zoom Meeting
Time: Jun 11, 2022 10:00 AM Pacific Time (US and Canada)

Join Zoom Meeting
https://valve.zoom.us/j/96337212424?pwd=ZXNZOFhMcDNoUSs1Ylcwc1hJVFd3Zz09

Meeting ID: 963 3721 2424
Passcode: 509348
One tap mobile
+12532158782,,96337212424#,,,,*509348# US (Tacoma)
+13462487799,,96337212424#,,,,*509348# US (Houston)

Dial by your location
+1 253 215 8782 US (Tacoma)
+1 346 248 7799 US (Houston)
+1 669 900 9128 US (San Jose)
+1 646 558 8656 US (New York)
+1 301 715 8592 US (Washington DC)
+1 312 626 6799 US (Chicago)
833 548 0276 US Toll-free
833 548 0282 US Toll-free
877 853 5247 US Toll-free
888 788 0099 US Toll-free
Meeting ID: 963 3721 2424
Passcode: 509348
Find your local number: https://valve.zoom.us/u/a6VlLqLK0

@ericwa
Copy link
Contributor Author

ericwa commented Jun 10, 2022

Sure, that works!

@icculus
Copy link
Collaborator

icculus commented Jun 10, 2022

Ok, it's on my calendar!

@slime73
Copy link
Contributor

slime73 commented Jun 11, 2022

Works for me

@slouken slouken merged commit e09551b into libsdl-org:main Jun 11, 2022
@sezero
Copy link
Contributor

sezero commented Jun 11, 2022

Does SDL_render_d3d12.c not need the same touch as d3d and d3d11 renderers?

@ericwa
Copy link
Contributor Author

ericwa commented Jun 12, 2022

Looks like it will need the same change, yeah

@sezero
Copy link
Contributor

sezero commented Jun 13, 2022

Is the following good then? (not tested)

diff --git a/src/render/direct3d12/SDL_render_d3d12.c b/src/render/direct3d12/SDL_render_d3d12.c
index a358a098d..b263e882e 100644
--- a/src/render/direct3d12/SDL_render_d3d12.c
+++ b/src/render/direct3d12/SDL_render_d3d12.c
@@ -240,7 +240,6 @@ static const GUID SDL_IID_ID3D12InfoQueue = { 0x0742a90b, 0xc387, 0x483f, { 0xb9
 #endif
 
 
-
 UINT
 D3D12_Align(UINT location, UINT alignment)
 {
@@ -485,6 +484,13 @@ D3D12_DestroyRenderer(SDL_Renderer * renderer)
     SDL_free(renderer);
 }
 
+static int
+D3D12_GetOutputSize(SDL_Renderer *renderer, int *w, int *h)
+{
+    WIN_GetDrawableSize(renderer->window, w, h);
+    return 0;
+}
+
 static D3D12_BLEND
 GetBlendFunc(SDL_BlendFactor factor)
 {
@@ -1211,7 +1217,7 @@ D3D12_CreateWindowSizeDependentResources(SDL_Renderer * renderer)
     /* The width and height of the swap chain must be based on the display's
      * non-rotated size.
      */
-    SDL_GetWindowSize(renderer->window, &w, &h);
+    WIN_GetDrawableSize(renderer->window, &w, &h);
     data->rotation = D3D12_GetCurrentRotation();
     if (D3D12_IsDisplayRotated90Degrees(data->rotation)) {
         int tmp = w;
@@ -2936,6 +2942,7 @@ D3D12_CreateRenderer(SDL_Window * window, Uint32 flags)
     data->identity = MatrixIdentity();
 
     renderer->WindowEvent = D3D12_WindowEvent;
+    renderer->GetOutputSize = D3D12_GetOutputSize;
     renderer->SupportsBlendMode = D3D12_SupportsBlendMode;
     renderer->CreateTexture = D3D12_CreateTexture;
     renderer->UpdateTexture = D3D12_UpdateTexture;

@PJB3005
Copy link
Contributor

PJB3005 commented Jun 19, 2022

@ericwa I'm trying to implement SDL2 support into my game now that this PR is merged and I'm running into some issues. I'm not sure whether I'm just missing something or what, or whether I should file a PR for this instead:

  • There's no API I can see to request the scaling factor for a window directly. Currently I'm just doing GetDisplayDPI(GetDisplay(window)) and then diving the DPI values by 96 which seems to work, but it would probably be nicer if there was an explicit function for this that returns a float scale or something like GLFW's does.
  • Since there's no explicit scale factor change event (like GLFW) I'm just relying on this updating in SDL_WINDOWEVENT_SIZE_CHANGED. This doesn't seem to work very consistently though when dragged across monitor: in some cases SDL_GL_GetDrawableSize and GetDisplayDPI(GetDisplay(window)) are not yet updated when this event is fired. (I am using an event callback here to avoid locking up my game during the resize).

@ericwa
Copy link
Contributor Author

ericwa commented Jun 19, 2022

@ericwa I'm trying to implement SDL2 support into my game now that this PR is merged and I'm running into some issues. I'm not sure whether I'm just missing something or what, or whether I should file a PR for this instead:

  • There's no API I can see to request the scaling factor for a window directly. Currently I'm just doing GetDisplayDPI(GetDisplay(window)) and then diving the DPI values by 96 which seems to work, but it would probably be nicer if there was an explicit function for this that returns a float scale or something like GLFW's does.

Cool, thanks for trying it out.

I think the best approach currently is to call SDL_GL_GetDrawableSize() (assuming OpenGL) to get the pixels and SDL_GetWindowSize() to get the point size and divide them - this will work correctly on all SDL backends - Wayland/macOS/Windows (with SDL_WINDOWS_DPI_SCALING=1).

There's this previous feature request for adding a convenience API: #3580

BTW which specific functions are you referring to with GetDisplayDPI() and GetDisplay()?

  • Since there's no explicit scale factor change event (like GLFW) I'm just relying on this updating in SDL_WINDOWEVENT_SIZE_CHANGED. This doesn't seem to work very consistently though when dragged across monitor: in some cases SDL_GL_GetDrawableSize and GetDisplayDPI(GetDisplay(window)) are not yet updated when this event is fired. (I am using an event callback here to avoid locking up my game during the resize).

The intended way of doing this is to listen for SDL_WINDOWEVENT_SIZE_CHANGED and call SDL_GL_GetDrawableSize to recompute the scale factor. (One thing to watch out for, the width/height included with the SIZE_CHANGED events are in points, which I found kind of counterintuitive.)

I should note that I haven't seen cases where calling SDL_GL_GetDrawableSize in response to SDL_WINDOWEVENT_SIZE_CHANGED gives you an out of date value. However I've also never tried the Windows highdpi support with the event callback.

@PJB3005
Copy link
Contributor

PJB3005 commented Jun 20, 2022

I think the best approach currently is to call SDL_GL_GetDrawableSize() (assuming OpenGL) to get the pixels and SDL_GetWindowSize() to get the point size and divide them

Alright, though I hope this isn't a permanent solution due to integer rounding errors and such.

BTW which specific functions are you referring to with GetDisplayDPI() and GetDisplay()?

SDL_GetWindowDisplayIndex() and SDL_GetDisplayDPI(), my bad.

(One thing to watch out for, the width/height included with the SIZE_CHANGED events are in points, which I found kind of counterintuitive.)

I'm pretty sure this isn't the problem but I'm not sure what you mean with this. Is it not just virtual scaled pixels (i.e. not physical drawable pixels)?

@slime73
Copy link
Contributor

slime73 commented Jun 20, 2022

I hope this isn't a permanent solution due to integer rounding errors and such.

There shouldn't be any integer rounding errors if you do appropriate casting before the division.

With GetDisplayDPI, keep in mind that it might not match the user's expected scaling factor (especially across different monitors with slightly different DPI and viewing distances).

@PJB3005
Copy link
Contributor

PJB3005 commented Jun 20, 2022

There shouldn't be any integer rounding errors if you do appropriate casting before the division.

The problem is that SDL2's coordinate space is still integers right now. If you have something like a 2px wide window, this kind of test would give you a 2px drawable = 100% scale, even when the scale is actually 125%.

However I've also never tried the Windows highdpi support with the event callback.

I found the problem. I'll send a PR with it fixed and also look into the SDL_GetWindowDPI().

By the way, isn't base DPI value on macOS 72 instead of 96? If so that might make it annoying to derive scale factor from for cross-plat apps since the base is different between macOS/Windows.

@PJB3005
Copy link
Contributor

PJB3005 commented Jun 20, 2022

With GetDisplayDPI, keep in mind that it might not match the user's expected scaling factor (especially across different monitors with slightly different DPI and viewing distances).

Yeah, that's the problem. I had hoped that it'd work, since the docs say it's the monitor containing the central pixel of the window (which IIRC is also what Windows uses as metric to decide DPI) but alas.

@slime73
Copy link
Contributor

slime73 commented Jun 20, 2022

that's the problem

It's not meant to be used for determining DPI scale factors (whereas GetWindowSize and GetDrawableSize are) - I'm curious if your integer issue manifests in non-contrived situations though, since those APIs are basically the same as what half the operating systems provide to native app developers.

(It'd be good to know the most useful approach to take for SDL3 or whatever.)

@PJB3005
Copy link
Contributor

PJB3005 commented Jun 20, 2022

I'm curious if your integer issue manifests in non-contrived situations though, since those APIs are basically the same as what half the operating systems provide to native app developers.

Windows provides an exact integer DPI value, so this is not a problem there. Obviously it's a contrived example but it still feels important to report the actual data the OS returns instead of guessing. I don't even think Windows has a DPI-scaled GetWindowSize because of how DPI-awareness was implemented on win32 apps.

@slime73
Copy link
Contributor

slime73 commented Jun 20, 2022

What I mean is: it's not actually possible to create a 2x2 window (on many operating systems at least, maybe depending on window flags). I wonder if the possible-and-used-in-practice window sizes would ever run into that problem or not.

Also Windows is just one backend of many, SDL has to work across several different implementation choices from different OS authors (as Eric discovered when trying to fit SDL's existing APIs with Windows' DPI scaling model).

@PJB3005
Copy link
Contributor

PJB3005 commented Jun 20, 2022

I wonder if the possible-and-used-in-practice window sizes would ever run into that problem or not.

Probably not, but providing exact values is still nice. For example with this inaccurate system for fetching DPI I would need to manually do slight rounding on SDL2's values to account for this error, because otherwise my engine would constantly see changing content scales during window resize (which means re-rendering fonts and all that noise). With the exact value returned from the OS this is not an issue at all.

Also Windows is just one backend of many, SDL has to work across several different implementation choices from different OS authors

So obviously SDL2 covers more platforms here, but I checked GLFW's source for how they get their values and Windows, macOS, and Wayland all get exact integral scaling values (not int scaling factor but without float error) from their respective API to work with. I think it's worth providing for the platforms that do have it, both for accuracy and convenience. (I didn't even bother to check X11 since I know that platform is a broken joke for DPI scaling).

On this note, I cross-checked both SDL2 and GLFW for how SDL2's display DPI values are reported on macOS and... am I right they're exact DPI values? On Windows, SDL_GetDisplayDPI() returns values like 96, 120 based on user-configured UI scale factor (also, it doesn't use SDL_ComputeDiagonalDPI so the diagonal values make no sense). From what I can tell checking the code for macOS, SDL_GetDisplayDPI() instead returns exact DPI values based on monitor size and resolution.

This makes SDL_GetDisplayDPI() inconsistent across platform, and completely unsuitable for calculating content scale factors for "how much should I scale the text in my UI". The Windows behavior should be made to give actual monitor DPI instead of content scale, and a different API should be introduced for content scale factors.

@slime73
Copy link
Contributor

slime73 commented Jun 20, 2022

[SDL_GetDisplayDPI is] completely unsuitable for calculating content scale factors for "how much should I scale the text in my UI".

I don't think it was ever intended for that use case (as I've said above). That being said I've personally never felt like it had a lot of legit use at all, aside from confusing people who did actually want DPI scale factors.

@PJB3005
Copy link
Contributor

PJB3005 commented Jun 20, 2022

That being said I've personally never felt like it had a lot of legit use at all

One good use of exact DPI values is something like a 100% zoom scale on a PDF reader, so the user can have an idea of the exact size of the A4 page or whatever. Otherwise nothing much comes up in my mind.

aside from confusing people who did actually want DPI scale factors.

I guess it doesn't help that on Windows it returns a value that looks like it's intended for that right now 😅

PJB3005 added a commit to PJB3005/SDL that referenced this pull request Jun 20, 2022
Analogous to glfwGetWindowContentScale().

See comments on libsdl-org#5778
@ericwa
Copy link
Contributor Author

ericwa commented Jun 20, 2022

(One thing to watch out for, the width/height included with the SIZE_CHANGED events are in points, which I found kind of counterintuitive.)

I'm pretty sure this isn't the problem but I'm not sure what you mean with this. Is it not just virtual scaled pixels (i.e. not physical drawable pixels)?

Yeah - I was just commenting that the size included with SDL_WINDOWEVENT_SIZE_CHANGED is not physical pixels, e.g. if SDL_GetWindowSize is 640x480, and you drag between a 125% and 100% scaled monitors, the SDL_WINDOWEVENT_SIZE_CHANGED event data will have a size of 640x480 on both monitors.

@ericwa
Copy link
Contributor Author

ericwa commented Jun 21, 2022

That being said I've personally never felt like it had a lot of legit use at all, aside from confusing people who did actually want DPI scale factors.

Yeah, I agree, it's questionable how useful the physical DPI is, but I guess we can wrap what the OS provides. (Maybe it's accurate on Apple hardware?)

However, there's an unfortunate disagreement between SDL backends - on Windows, SDL_GetDisplayDPI has always returned the user's scale factor (it's in units where 96 means 100%):
(looks like it was introduced in 61c7415 ). The Windows API we're using (GetDpiForMonitor) can also query "angular DPI" and "raw DPI".

I just double checked on macOS - SDL is returning an actual "pixels per inch" value based on the physical screen size returned by CGDisplayScreenSize - so, completely different than what we do on Windows. :-(

@ericwa ericwa mentioned this pull request Jun 23, 2022
10 tasks
PJB3005 added a commit to PJB3005/SDL that referenced this pull request Oct 5, 2022
Analogous to glfwGetWindowContentScale().

See comments on libsdl-org#5778
PJB3005 added a commit to PJB3005/SDL that referenced this pull request Oct 5, 2022
Analogous to glfwGetWindowContentScale().

See comments on libsdl-org#5778
PJB3005 added a commit to PJB3005/SDL that referenced this pull request Oct 5, 2022
Analogous to glfwGetWindowContentScale().

See comments on libsdl-org#5778
PJB3005 added a commit to PJB3005/SDL that referenced this pull request Nov 10, 2022
Analogous to glfwGetWindowContentScale().

See comments on libsdl-org#5778
PJB3005 added a commit to PJB3005/SDL that referenced this pull request Nov 10, 2022
Analogous to glfwGetWindowContentScale().

See comments on libsdl-org#5778
@slime73 slime73 mentioned this pull request Feb 10, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

7 participants