Skip to content

Commit

Permalink
Updated SDL high DPI support
Browse files Browse the repository at this point in the history
We have gotten feedback that abstracting the coordinate system based on the display scale is unexpected and it is difficult to adapt existing applications to the proposed API.

The new approach is to provide the coordinate systems that people expect, but provide additional information that will help applications properly handle high DPI situations.

The concepts needed for high DPI support are documented in README-highdpi.md. An example of automatically adapting the content to display scale changes can be found in SDL_test_common.c, where auto_scale_content is checked.

Also, the SDL_WINDOW_ALLOW_HIGHDPI window flag has been replaced by the SDL_HINT_VIDEO_ENABLE_HIGH_PIXEL_DENSITY hint.

Fixes libsdl-org#7709
  • Loading branch information
slouken committed May 17, 2023
1 parent 642504b commit 10e77ac
Show file tree
Hide file tree
Showing 51 changed files with 506 additions and 881 deletions.
20 changes: 0 additions & 20 deletions build-scripts/SDL_migration.cocci
Original file line number Diff line number Diff line change
Expand Up @@ -2284,26 +2284,6 @@ expression e;
- SDL_WINDOW_INPUT_GRABBED
+ SDL_WINDOW_MOUSE_GRABBED
@@
SDL_DisplayMode *e;
@@
(
- e->w
+ e->screen_w
|
- e->h
+ e->screen_h
)
@@
SDL_DisplayMode e;
@@
(
- e.w
+ e.screen_w
|
- e.h
+ e.screen_h
)
@@
@@
- SDL_GetWindowDisplayIndex
+ SDL_GetDisplayForWindow
Expand Down
18 changes: 18 additions & 0 deletions docs/README-highdpi.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@

SDL 3.0 has new support for high DPI displays

Displays now have a content display scale.

The display scale is the expected scale for content based on the DPI settings of the display. For example, a 4K display might have a 2.0 (200%) display scale, which means that the user expects UI elements to be twice as big on this display, to aid in readability.

The window size is now distinct from the window pixel size.

The window also has a display scale, which is the content display scale relative to the window pixel size.

For example, a 3840x2160 window displayed at 200% on Windows, and a 1920x1080 window on a 2x display on macOS will both have a pixel size of 3840x2160 and a display scale of 2.0.

You can query the window size using SDL_GetWindowSize(), and when this changes you get an SDL_EVENT_WINDOW_RESIZED event.

You can query the window pixel size using SDL_GetWindowSizeInPixels(), and when this changes you get an SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED event. You are guaranteed to get a SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED event when a window is created and resized, and you can use this event to create and resize your graphics context for the window.

You can query the window display scale using SDL_GetWindowDisplayScale(), and when this changes you get an SDL_EVENT_WINDOW_DISPLAY_SCALE_CHANGED event.
8 changes: 4 additions & 4 deletions docs/README-migration.md
Original file line number Diff line number Diff line change
Expand Up @@ -1085,9 +1085,9 @@ The SDL_WINDOWPOS_UNDEFINED_DISPLAY() and SDL_WINDOWPOS_CENTERED_DISPLAY() macro

The SDL_WINDOW_SHOWN flag has been removed. Windows are shown by default and can be created hidden by using the SDL_WINDOW_HIDDEN flag.

The SDL_WINDOW_ALLOW_HIGHDPI flag has been removed. Windows are automatically high DPI aware and their coordinates are in screen space, which may differ from physical pixels on displays using display scaling.
The SDL_WINDOW_ALLOW_HIGHDPI flag has been replaced by the SDL_HINT_VIDEO_ENABLE_HIGH_PIXEL_DENSITY hint, which is enabled by default.

SDL_DisplayMode now includes the pixel size, the screen size and the relationship between the two. For example, a 4K display at 200% scale could have a pixel size of 3840x2160, a screen size of 1920x1080, and a display scale of 2.0.
SDL_DisplayMode now includes the pixel density which can be greater than 1.0 for display modes that have a higher pixel size than the mode size. You should use SDL_GetWindowSizeInPixels() to get the actual pixel size of the window back buffer.

The refresh rate in SDL_DisplayMode is now a float.

Expand All @@ -1100,8 +1100,8 @@ Rather than iterating over display modes using an index, there is a new function
if (modes) {
for (i = 0; i < num_modes; ++i) {
SDL_DisplayMode *mode = modes[i];
SDL_Log("Display %" SDL_PRIu32 " mode %d: %dx%d@%gHz, %d%% scale\n",
display, i, mode->pixel_w, mode->pixel_h, mode->refresh_rate, (int)(mode->display_scale * 100.0f));
SDL_Log("Display %" SDL_PRIu32 " mode %d: %dx%d@%gx %gHz\n",
display, i, mode->w, mode->h, mode->pixel_density, mode->refresh_rate);
}
SDL_free(modes);
}
Expand Down
5 changes: 3 additions & 2 deletions include/SDL3/SDL_events.h
Original file line number Diff line number Diff line change
Expand Up @@ -95,9 +95,9 @@ typedef enum
SDL_EVENT_DISPLAY_CONNECTED, /**< Display has been added to the system */
SDL_EVENT_DISPLAY_DISCONNECTED, /**< Display has been removed from the system */
SDL_EVENT_DISPLAY_MOVED, /**< Display has changed position */
SDL_EVENT_DISPLAY_SCALE_CHANGED, /**< Display has changed desktop display scale */
SDL_EVENT_DISPLAY_CONTENT_SCALE_CHANGED, /**< Display has changed content scale */
SDL_EVENT_DISPLAY_FIRST = SDL_EVENT_DISPLAY_ORIENTATION,
SDL_EVENT_DISPLAY_LAST = SDL_EVENT_DISPLAY_SCALE_CHANGED,
SDL_EVENT_DISPLAY_LAST = SDL_EVENT_DISPLAY_CONTENT_SCALE_CHANGED,

/* Window events */
/* 0x200 was SDL_WINDOWEVENT, reserve the number for sdl2-compat */
Expand All @@ -120,6 +120,7 @@ typedef enum
SDL_EVENT_WINDOW_HIT_TEST, /**< Window had a hit test that wasn't SDL_HITTEST_NORMAL */
SDL_EVENT_WINDOW_ICCPROF_CHANGED, /**< The ICC profile of the window's display has changed */
SDL_EVENT_WINDOW_DISPLAY_CHANGED, /**< Window has been moved to display data1 */
SDL_EVENT_WINDOW_DISPLAY_SCALE_CHANGED, /**< Window display scale has been changed */
SDL_EVENT_WINDOW_DESTROYED, /**< The window with the associated ID is being or has been destroyed. If this message is being handled
in an event watcher, the window handle is still valid and can still be used to retrieve any userdata
associated with the window. Otherwise, the handle has already been destroyed and all resources
Expand Down
11 changes: 11 additions & 0 deletions include/SDL3/SDL_hints.h
Original file line number Diff line number Diff line change
Expand Up @@ -1638,6 +1638,17 @@ extern "C" {
*/
#define SDL_HINT_VIDEO_EXTERNAL_CONTEXT "SDL_VIDEO_EXTERNAL_CONTEXT"

/**
* \brief A variable controlling whether to use high pixel density display modes
*
* The variable can be set to the following values:
* "0" - Disable high pixel density display modes
* "1" - Enable high pixel density display modes
*
* The default value is "1". This hint must be set before display modes are queried and windows are created.
*/
#define SDL_HINT_VIDEO_ENABLE_HIGH_PIXEL_DENSITY "SDL_VIDEO_ENABLE_HIGH_PIXEL_DENSITY"

/**
* \brief A variable that dictates policy for fullscreen Spaces on macOS.
*
Expand Down
36 changes: 5 additions & 31 deletions include/SDL3/SDL_render.h
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,6 @@ typedef enum
typedef enum
{
SDL_LOGICAL_PRESENTATION_DISABLED, /**< There is no logical size in effect */
SDL_LOGICAL_PRESENTATION_MATCH, /**< The rendered content matches the window size in points */
SDL_LOGICAL_PRESENTATION_STRETCH, /**< The rendered content is stretched to the output resolution */
SDL_LOGICAL_PRESENTATION_LETTERBOX, /**< The rendered content is fit to the largest dimension and the other dimension is letterboxed with black bars */
SDL_LOGICAL_PRESENTATION_OVERSCAN, /**< The rendered content is fit to the smallest dimension and the other dimension extends beyond the output bounds */
Expand Down Expand Up @@ -235,9 +234,8 @@ extern DECLSPEC int SDLCALL SDL_CreateWindowAndRenderer(int width, int height, U
* need a specific renderer, specify NULL and SDL will attempt to chooes the
* best option for you, based on what is available on the user's system.
*
* By default the rendering size matches the window size in points, but you
* can call SDL_SetRenderLogicalPresentation() to enable high DPI rendering or
* change the content size and scaling options.
* By default the rendering size matches the window size in pixels, but you
* can call SDL_SetRenderLogicalPresentation() to change the content size and scaling options.
*
* \param window the window where rendering is displayed
* \param name the name of the rendering driver to initialize, or NULL to
Expand Down Expand Up @@ -316,24 +314,6 @@ extern DECLSPEC SDL_Window *SDLCALL SDL_GetRenderWindow(SDL_Renderer *renderer);
*/
extern DECLSPEC int SDLCALL SDL_GetRendererInfo(SDL_Renderer *renderer, SDL_RendererInfo *info);

/**
* Get the output size in points of a rendering context.
*
* This returns the true output size in points, ignoring any render targets or
* logical size and presentation.
*
* \param renderer the rendering context
* \param w a pointer filled in with the width in points
* \param h a pointer filled in with the height in points
* \returns 0 on success or a negative error code on failure; call
* SDL_GetError() for more information.
*
* \since This function is available since SDL 3.0.0.
*
* \sa SDL_GetRenderer
*/
extern DECLSPEC int SDLCALL SDL_GetRenderWindowSize(SDL_Renderer *renderer, int *w, int *h);

/**
* Get the output size in pixels of a rendering context.
*
Expand Down Expand Up @@ -840,13 +820,9 @@ extern DECLSPEC SDL_Texture *SDLCALL SDL_GetRenderTarget(SDL_Renderer *renderer)
* render target is created at the specified size and used for rendering and
* then copied to the output during presentation.
*
* When a renderer is created, the logical size is set to match the window
* size in points. The actual output size may be higher pixel density, and can
* be queried with SDL_GetRenderOutputSize().
*
* You can disable logical coordinates by setting the mode to
* SDL_LOGICAL_PRESENTATION_DISABLED, and in that case you get the full
* resolution of the output window.
* pixel resolution of the output window.
*
* You can convert coordinates in an event into rendering coordinates using
* SDL_ConvertEventToRenderCoordinates().
Expand Down Expand Up @@ -887,8 +863,7 @@ extern DECLSPEC int SDLCALL SDL_SetRenderLogicalPresentation(SDL_Renderer *rende
extern DECLSPEC int SDLCALL SDL_GetRenderLogicalPresentation(SDL_Renderer *renderer, int *w, int *h, SDL_RendererLogicalPresentation *mode, SDL_ScaleMode *scale_mode);

/**
* Get a point in render coordinates when given a point in window coordinates
* (points).
* Get a point in render coordinates when given a point in window coordinates.
*
* \param renderer the rendering context
* \param window_x the x coordinate in window coordinates
Expand All @@ -906,8 +881,7 @@ extern DECLSPEC int SDLCALL SDL_GetRenderLogicalPresentation(SDL_Renderer *rende
extern DECLSPEC int SDLCALL SDL_RenderCoordinatesFromWindow(SDL_Renderer *renderer, float window_x, float window_y, float *x, float *y);

/**
* Get a point in window coordinates (points) when given a point in render
* coordinates.
* Get a point in window coordinates when given a point in render coordinates.
*
* \param renderer the rendering context
* \param x the x coordinate in render coordinates
Expand Down
1 change: 1 addition & 0 deletions include/SDL3/SDL_test_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ typedef struct
int window_maxH;
int logical_w;
int logical_h;
SDL_bool auto_scale_content;
SDL_RendererLogicalPresentation logical_presentation;
SDL_ScaleMode logical_scale_mode;
float scale;
Expand Down
Loading

0 comments on commit 10e77ac

Please sign in to comment.