SDL: Renderer logical size is now implemented as a render target

From dcd17f547324a143d66d79e3b586577a7da558ed Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Fri, 3 Feb 2023 12:25:46 -0800
Subject: [PATCH] Renderer logical size is now implemented as a render target

This fixes rounding errors with coordinate scaling and gives more flexibility in the presentation, as well as making it easy to maintain device independent resolution as windows move between different pixel density displays.

By default when a renderer is created, it will match the window size so window coordinates and render coordinates are 1-1.

Mouse and touch events are no longer filtered to change their coordinates, instead you can call SDL_ConvertEventToRenderCoordinates() to explicitly map event coordinates into the rendering viewport.

SDL_RenderWindowToLogical() and SDL_RenderLogicalToWindow() have been renamed SDL_RenderCoordinatesFromWindow() and SDL_RenderCoordinatesToWindow() and take floating point coordinates in both directions.

The viewport, clipping state, and scale for render targets are now persistent and will remain set whenever they are active.
---
 build-scripts/SDL_migration.cocci        |   58 +-
 docs/README-ios.md                       |   19 +-
 docs/README-migration.md                 |   28 +-
 include/SDL3/SDL_hints.h                 |   22 -
 include/SDL3/SDL_oldnames.h              |   18 +-
 include/SDL3/SDL_render.h                |  272 +++---
 include/SDL3/SDL_test_common.h           |    2 +
 include/SDL3/SDL_video.h                 |   10 +-
 src/dynapi/SDL_dynapi.sym                |   20 +-
 src/dynapi/SDL_dynapi_overrides.h        |   20 +-
 src/dynapi/SDL_dynapi_procs.h            |   24 +-
 src/render/SDL_render.c                  | 1116 ++++++++++++----------
 src/render/SDL_sysrender.h               |   69 +-
 src/render/direct3d/SDL_render_d3d.c     |   11 +-
 src/render/direct3d11/SDL_render_d3d11.c |   23 +-
 src/render/direct3d12/SDL_render_d3d12.c |   19 +-
 src/render/metal/SDL_render_metal.m      |    4 +-
 src/render/opengl/SDL_render_gl.c        |   19 +-
 src/render/opengles2/SDL_render_gles2.c  |   13 +-
 src/render/ps2/SDL_render_ps2.c          |    2 +-
 src/render/psp/SDL_render_psp.c          |    4 +-
 src/render/software/SDL_render_sw.c      |    2 +-
 src/render/vitagxm/SDL_render_vita_gxm.c |    6 +-
 src/test/SDL_test_common.c               |  135 ++-
 test/gamepadmap.c                        |    4 +-
 test/testautomation_render.c             |   35 +-
 test/testgamepad.c                       |    4 +-
 test/testwm.c                            |    2 +-
 28 files changed, 1082 insertions(+), 879 deletions(-)
 mode change 100644 => 100755 src/render/SDL_render.c

diff --git a/build-scripts/SDL_migration.cocci b/build-scripts/SDL_migration.cocci
index e8b7200e3e39..76d72f90808b 100644
--- a/build-scripts/SDL_migration.cocci
+++ b/build-scripts/SDL_migration.cocci
@@ -294,9 +294,12 @@ expression e1, e2, e3;
 @@
 typedef PFN_vkGetInstanceProcAddr;
 @@
+(
+  (PFN_vkGetInstanceProcAddr)SDL_Vulkan_GetVkGetInstanceProcAddr()
+|
 + (PFN_vkGetInstanceProcAddr)
   SDL_Vulkan_GetVkGetInstanceProcAddr()
-
+)
 
 // SDL_PauseAudioDevice / SDL_PlayAudioDevice
 @@
@@ -716,7 +719,8 @@ expression e1, e2, e3, e4, e5, e6, e7, e8, e9;
 @@
 // SDL_CreateRenderer:
 // 2nd argument changed from int (default=-1) to const char* (default=NULL)
-expression e1, e2, e3;
+expression e1, e3;
+int e2;
 @@
 
 (
@@ -1774,15 +1778,12 @@ typedef SDL_GameControllerButtonBind, SDL_GamepadBinding;
 + SDL_GetRenderClipRect
   (...)
 @@
+SDL_Renderer *renderer;
+int *w;
+int *h;
 @@
-- SDL_RenderGetIntegerScale
-+ SDL_GetRenderIntegerScale
-  (...)
-@@
-@@
-- SDL_RenderGetLogicalSize
-+ SDL_GetRenderLogicalSize
-  (...)
+- SDL_RenderGetLogicalSize(renderer, w, h)
++ SDL_GetRenderLogicalPresentation(renderer, w, h, NULL, NULL)
 @@
 @@
 - SDL_RenderGetMetalCommandEncoder
@@ -1819,15 +1820,17 @@ typedef SDL_GameControllerButtonBind, SDL_GamepadBinding;
 + SDL_SetRenderClipRect
   (...)
 @@
+SDL_Renderer *renderer;
+expression w;
+expression h;
 @@
-- SDL_RenderSetIntegerScale
-+ SDL_SetRenderIntegerScale
-  (...)
-@@
-@@
-- SDL_RenderSetLogicalSize
-+ SDL_SetRenderLogicalSize
-  (...)
+(
+- SDL_RenderSetLogicalSize(renderer, 0, 0)
++ SDL_SetRenderLogicalPresentation(renderer, 0, 0, SDL_LOGICAL_PRESENTATION_DISABLED, SDL_ScaleModeNearest)
+|
+- SDL_RenderSetLogicalSize(renderer, w, h)
++ SDL_SetRenderLogicalPresentation(renderer, w, h, SDL_LOGICAL_PRESENTATION_LETTERBOX, SDL_ScaleModeLinear)
+)
 @@
 @@
 - SDL_RenderSetScale
@@ -2328,10 +2331,6 @@ expression e;
   (...)
 @@
 @@
-- SDL_WINDOW_FULLSCREEN
-+ SDL_WINDOW_FULLSCREEN_EXCLUSIVE
-@@
-@@
 - SDL_WINDOW_INPUT_GRABBED
 + SDL_WINDOW_MOUSE_GRABBED
 @@
@@ -2374,3 +2373,18 @@ SDL_DisplayMode e;
 - SDL_GetClosestDisplayMode
 + SDL_GetClosestFullscreenDisplayMode
   (...)
+@@
+@@
+- SDL_GetRendererOutputSize
++ SDL_GetCurrentRenderOutputSizeInPixels
+  (...)
+@@
+@@
+- SDL_RenderWindowToLogical
++ SDL_RenderCoordinatesFromWindow
+  (...)
+@@
+@@
+- SDL_RenderLogicalToWindow
++ SDL_RenderCoordinatesToWindow
+  (...)
diff --git a/docs/README-ios.md b/docs/README-ios.md
index d5e4914b5951..3cdb81e81277 100644
--- a/docs/README-ios.md
+++ b/docs/README-ios.md
@@ -41,16 +41,15 @@ size their content based on screen coordinates / points rather than pixels,
 as this allows different iOS devices to have different pixel densities
 (Retina versus non-Retina screens, etc.) without apps caring too much.
 
-By default SDL will not use the full pixel density of the screen on
-Retina/high-dpi capable devices. Use the SDL_WINDOW_ALLOW_HIGHDPI flag when
-creating your window to enable high-dpi support.
-
-When high-dpi support is enabled, SDL_GetWindowSize() and display mode sizes
-will still be in "screen coordinates" rather than pixels, but the window will
-have a much greater pixel density when the device supports it, and the
-SDL_GetWindowSizeInPixels() or SDL_GetRendererOutputSize() functions (depending
-on whether the SDL_Render API is used) can be queried to determine the size in
-pixels of the drawable screen framebuffer.
+SDL_GetWindowSize() and mouse coordinates are in screen coordinates rather
+than pixels, but the window will have a much greater pixel density when the
+device supports it, and the SDL_GetWindowSizeInPixels() can be called to
+determine the size in pixels of the drawable screen framebuffer.
+
+The SDL 2D rendering API will automatically handle this for you, by default
+providing a rendering area in screen coordinates, and you can call
+SDL_SetRenderLogicalPresentation() to gain access to the higher density
+resolution.
 
 Some OpenGL ES functions such as glViewport expect sizes in pixels rather than
 sizes in screen coordinates. When doing 2D rendering with OpenGL ES, an
diff --git a/docs/README-migration.md b/docs/README-migration.md
index a60f97e64aec..7a9552a2c092 100644
--- a/docs/README-migration.md
+++ b/docs/README-migration.md
@@ -341,10 +341,12 @@ functionality to your app and aid migration. That is located in the
 SDL_AddHintCallback() now returns a standard int result instead of void, returning 0 if the function succeeds or a negative error code if there was an error.
 
 The following hints have been removed:
-* SDL_HINT_IDLE_TIMER_DISABLED (use SDL_DisableScreenSaver instead)
-* SDL_HINT_VIDEO_X11_FORCE_EGL (use SDL_HINT_VIDEO_FORCE_EGL instead)
-* SDL_HINT_VIDEO_X11_XINERAMA (Xinerama no longer supported by the X11 backend)
-* SDL_HINT_VIDEO_X11_XVIDMODE (Xvidmode no longer supported by the X11 backend)
+* SDL_HINT_IDLE_TIMER_DISABLED - use SDL_DisableScreenSaver instead
+* SDL_HINT_MOUSE_RELATIVE_SCALING - mouse coordinates are no longer automatically scaled by the SDL renderer
+* SDL_HINT_RENDER_LOGICAL_SIZE_MODE - the logical size mode is explicitly set with SDL_SetRenderLogicalPresentation()
+* SDL_HINT_VIDEO_X11_FORCE_EGL - use SDL_HINT_VIDEO_FORCE_EGL instead
+* SDL_HINT_VIDEO_X11_XINERAMA - Xinerama no longer supported by the X11 backend
+* SDL_HINT_VIDEO_X11_XVIDMODE - Xvidmode no longer supported by the X11 backend
 
 * Renamed hints SDL_HINT_VIDEODRIVER and SDL_HINT_AUDIODRIVER to SDL_HINT_VIDEO_DRIVER and SDL_HINT_AUDIO_DRIVER
 * Renamed environment variables SDL_VIDEODRIVER and SDL_AUDIODRIVER to SDL_VIDEO_DRIVER and SDL_AUDIO_DRIVER
@@ -594,9 +596,16 @@ which index is the "opengl" or whatnot driver, you can just pass that string dir
 here, now. Passing NULL is the same as passing -1 here in SDL2, to signify you want SDL
 to decide for you.
 
-SDL_RenderWindowToLogical() and SDL_RenderLogicalToWindow() take floating point coordinates in both directions.
+Mouse and touch events are no longer filtered to change their coordinates, instead you
+can call SDL_ConvertEventToRenderCoordinates() to explicitly map event coordinates into
+the rendering viewport.
+
+SDL_RenderWindowToLogical() and SDL_RenderLogicalToWindow() have been renamed SDL_RenderCoordinatesFromWindow() and SDL_RenderCoordinatesToWindow() and take floating point coordinates in both directions.
+
+The viewport, clipping state, and scale for render targets are now persistent and will remain set whenever they are active.
 
 The following functions have been renamed:
+* SDL_GetRendererOutputSize() => SDL_GetCurrentRenderOutputSize()
 * SDL_RenderCopyExF() => SDL_RenderTextureRotated()
 * SDL_RenderCopyF() => SDL_RenderTexture()
 * SDL_RenderDrawLineF() => SDL_RenderLine()
@@ -609,19 +618,21 @@ The following functions have been renamed:
 * SDL_RenderFillRectsF() => SDL_RenderFillRects()
 * SDL_RenderGetClipRect() => SDL_GetRenderClipRect()
 * SDL_RenderGetIntegerScale() => SDL_GetRenderIntegerScale()
-* SDL_RenderGetLogicalSize() => SDL_GetRenderLogicalSize()
+* SDL_RenderGetLogicalSize() => SDL_GetRenderLogicalPresentation()
 * SDL_RenderGetMetalCommandEncoder() => SDL_GetRenderMetalCommandEncoder()
 * SDL_RenderGetMetalLayer() => SDL_GetRenderMetalLayer()
 * SDL_RenderGetScale() => SDL_GetRenderScale()
 * SDL_RenderGetViewport() => SDL_GetRenderViewport()
 * SDL_RenderGetWindow() => SDL_GetRenderWindow()
 * SDL_RenderIsClipEnabled() => SDL_RenderClipEnabled()
+* SDL_RenderLogicalToWindow() => SDL_RenderCoordinatesToWindow()
 * SDL_RenderSetClipRect() => SDL_SetRenderClipRect()
 * SDL_RenderSetIntegerScale() => SDL_SetRenderIntegerScale()
-* SDL_RenderSetLogicalSize() => SDL_SetRenderLogicalSize()
+* SDL_RenderSetLogicalSize() => SDL_SetRenderLogicalPresentation()
 * SDL_RenderSetScale() => SDL_SetRenderScale()
 * SDL_RenderSetVSync() => SDL_SetRenderVSync()
 * SDL_RenderSetViewport() => SDL_SetRenderViewport()
+* SDL_RenderWindowToLogical() => SDL_RenderCoordinatesFromWindow()
 
 The following functions have been removed:
 * SDL_RenderCopy()
@@ -634,6 +645,9 @@ The following functions have been removed:
 * SDL_RenderDrawRects()
 * SDL_RenderFillRect()
 * SDL_RenderFillRects()
+* SDL_RenderGetIntegerScale()
+* SDL_RenderSetIntegerScale() - this is now explicit with SDL_LOGICAL_PRESENTATION_INTEGER_SCALE
+* SDL_RenderTargetSupported() - render targets are always supported
 
 ## SDL_rwops.h
 
diff --git a/include/SDL3/SDL_hints.h b/include/SDL3/SDL_hints.h
index 1a5237be54bf..f041bcc64b55 100644
--- a/include/SDL3/SDL_hints.h
+++ b/include/SDL3/SDL_hints.h
@@ -1143,17 +1143,6 @@ extern "C" {
  */
 #define SDL_HINT_MOUSE_RELATIVE_MODE_WARP    "SDL_MOUSE_RELATIVE_MODE_WARP"
 
-/**
- *  \brief  A variable controlling whether relative mouse motion is affected by renderer scaling
- *
- *  This variable can be set to the following values:
- *    "0"       - Relative motion is unaffected by display scale or renderer's logical size
- *    "1"       - Relative motion is scaled according to display scale scaling and logical size
- *
- *  By default relative mouse deltas are affected by display scale and renderer scaling
- */
-#define SDL_HINT_MOUSE_RELATIVE_SCALING "SDL_MOUSE_RELATIVE_SCALING"
-
 /**
  *  \brief  A variable setting the scale for mouse motion, in floating point, when the mouse is in relative mode
  */
@@ -1399,17 +1388,6 @@ extern "C" {
  */
 #define SDL_HINT_RENDER_DRIVER              "SDL_RENDER_DRIVER"
 
-/**
- *  \brief  A variable controlling the scaling policy for SDL_SetRenderLogicalSize.
- *
- *  This variable can be set to the following values:
- *    "0" or "letterbox" - Uses letterbox/sidebars to fit the entire rendering on screen
- *    "1" or "overscan"  - Will zoom the rendering so it fills the entire screen, allowing edges to be drawn offscreen
- *
- *  By default letterbox is used
- */
-#define SDL_HINT_RENDER_LOGICAL_SIZE_MODE       "SDL_RENDER_LOGICAL_SIZE_MODE"
-
 /**
  *  \brief  A variable controlling whether the OpenGL render driver uses shaders if they are available.
  *
diff --git a/include/SDL3/SDL_oldnames.h b/include/SDL3/SDL_oldnames.h
index 0a663fc6fcd2..570c81af7d6e 100644
--- a/include/SDL3/SDL_oldnames.h
+++ b/include/SDL3/SDL_oldnames.h
@@ -345,6 +345,7 @@
 #define SDL_UnionRect SDL_GetRectUnion
 
 /* ##SDL_render.h */
+#define SDL_GetRendererOutputSize SDL_GetCurrentRenderOutputSize
 #define SDL_RenderCopyExF SDL_RenderTextureRotated
 #define SDL_RenderCopyF SDL_RenderTexture
 #define SDL_RenderDrawLineF SDL_RenderLine
@@ -356,20 +357,20 @@
 #define SDL_RenderFillRectF SDL_RenderFillRect
 #define SDL_RenderFillRectsF SDL_RenderFillRects
 #define SDL_RenderGetClipRect SDL_GetRenderClipRect
-#define SDL_RenderGetIntegerScale SDL_GetRenderIntegerScale
-#define SDL_RenderGetLogicalSize SDL_GetRenderLogicalSize
+#define SDL_RenderGetLogicalSize SDL_GetRenderLogicalPresentation
 #define SDL_RenderGetMetalCommandEncoder SDL_GetRenderMetalCommandEncoder
 #define SDL_RenderGetMetalLayer SDL_GetRenderMetalLayer
 #define SDL_RenderGetScale SDL_GetRenderScale
 #define SDL_RenderGetViewport SDL_GetRenderViewport
 #define SDL_RenderGetWindow SDL_GetRenderWindow
 #define SDL_RenderIsClipEnabled SDL_RenderClipEnabled
+#define SDL_RenderLogicalToWindow SDL_RenderCoordinatesToWindow
 #define SDL_RenderSetClipRect SDL_SetRenderClipRect
-#define SDL_RenderSetIntegerScale SDL_SetRenderIntegerScale
-#define SDL_RenderSetLogicalSize SDL_SetRenderLogicalSize
+#define SDL_RenderSetLogicalSize SDL_SetRenderLogicalPresentation
 #define SDL_RenderSetScale SDL_SetRenderScale
 #define SDL_RenderSetVSync SDL_SetRenderVSync
 #define SDL_RenderSetViewport SDL_SetRenderViewport
+#define SDL_RenderWindowToLogical SDL_RenderCoordinatesFromWindow
 
 /* ##SDL_rwops.h */
 #define RW_SEEK_CUR SDL_RW_SEEK_CUR
@@ -730,6 +731,7 @@
 #define SDL_UnionRect SDL_UnionRect_renamed_SDL_GetRectUnion
 
 /* ##SDL_render.h */
+#define SDL_GetRendererOutputSize SDL_GetRendererOutputSize_renamed_SDL_GetCurrentRenderOutputSize
 #define SDL_RenderCopyExF SDL_RenderCopyExF_renamed_SDL_RenderTextureRotated
 #define SDL_RenderCopyF SDL_RenderCopyF_renamed_SDL_RenderTexture
 #define SDL_RenderDrawLineF SDL_RenderDrawLineF_renamed_SDL_RenderLine
@@ -741,20 +743,20 @@
 #define SDL_RenderFillRectF SDL_RenderFillRectF_renamed_SDL_RenderFillRect
 #define SDL_RenderFillRectsF SDL_RenderFillRectsF_renamed_SDL_RenderFillRects
 #define SDL_RenderGetClipRect SDL_RenderGetClipRect_renamed_SDL_GetRenderClipRect
-#define SDL_RenderGetIntegerScale SDL_RenderGetIntegerScale_renamed_SDL_GetRenderIntegerScale
-#define SDL_RenderGetLogicalSize SDL_RenderGetLogicalSize_renamed_SDL_GetRenderLogicalSize
+#define SDL_RenderGetLogicalSize SDL_RenderGetLogicalSize_renamed_SDL_GetRenderLogicalPresentation
 #define SDL_RenderGetMetalCommandEncoder SDL_RenderGetMetalCommandEncoder_renamed_SDL_GetRenderMetalCommandEncoder
 #define SDL_RenderGetMetalLayer SDL_RenderGetMetalLayer_renamed_SDL_GetRenderMetalLayer
 #define SDL_RenderGetScale SDL_RenderGetScale_renamed_SDL_GetRenderScale
 #define SDL_RenderGetViewport SDL_RenderGetViewport_renamed_SDL_GetRenderViewport
 #define SDL_RenderGetWindow SDL_RenderGetWindow_renamed_SDL_GetRenderWindow
 #define SDL_RenderIsClipEnabled SDL_RenderIsClipEnabled_renamed_SDL_RenderClipEnabled
+#define SDL_RenderLogicalToWindow SDL_RenderLogicalToWindow_renamed_SDL_RenderCoordinatesToWindow
 #define SDL_RenderSetClipRect SDL_RenderSetClipRect_renamed_SDL_SetRenderClipRect
-#define SDL_RenderSetIntegerScale SDL_RenderSetIntegerScale_renamed_SDL_SetRenderIntegerScale
-#define SDL_RenderSetLogicalSize SDL_RenderSetLogicalSize_renamed_SDL_SetRenderLogicalSize
+#define SDL_RenderSetLogicalSize SDL_RenderSetLogicalSize_renamed_SDL_SetRenderLogicalPresentation
 #define SDL_RenderSetScale SDL_RenderSetScale_renamed_SDL_SetRenderScale
 #define SDL_RenderSetVSync SDL_RenderSetVSync_renamed_SDL_SetRenderVSync
 #define SDL_RenderSetViewport SDL_RenderSetViewport_renamed_SDL_SetRenderViewport
+#define SDL_RenderWindowToLogical SDL_RenderWindowToLogical_renamed_SDL_RenderCoordinatesFromWindow
 
 /* ##SDL_rwops.h */
 #define RW_SEEK_CUR RW_SEEK_CUR_renamed_SDL_RW_SEEK_CUR
diff --git a/include/SDL3/SDL_render.h b/include/SDL3/SDL_render.h
index ded0f973b697..7bd32c6463d7 100644
--- a/include/SDL3/SDL_render.h
+++ b/include/SDL3/SDL_render.h
@@ -68,8 +68,6 @@ typedef enum
                                                      acceleration */
     SDL_RENDERER_PRESENTVSYNC = 0x00000004,     /**< Present is synchronized
                                                      with the refresh rate */
-    SDL_RENDERER_TARGETTEXTURE = 0x00000008     /**< The renderer supports
-                                                     rendering to texture */
 } SDL_RendererFlags;
 
 /**
@@ -135,6 +133,19 @@ typedef enum
     SDL_FLIP_VERTICAL = 0x00000002     /**< flip vertically */
 } SDL_RendererFlip;
 
+/**
+ * How the logical size is mapped to the output
+ */
+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 screen coordinates */
+    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 */
+    SDL_LOGICAL_PRESENTATION_INTEGER_SCALE,  /**< The rendered content is scaled up by integer multiples to fit the output resolution */
+} SDL_RendererLogicalPresentation;
+
 /**
  * A structure representing rendering state
  */
@@ -223,6 +234,10 @@ 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 screen coordinates,
+ * but you can call SDL_SetRenderLogicalPresentation() to enable high DPI
+ * rendering or 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
  *             initialize the first one supporting the requested flags
@@ -300,24 +315,62 @@ 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 screen coordinates of a rendering context.
+ *
+ * This returns the true output size in screen coordinates, ignoring any
+ * render targets or logical size and presentation.
+ *
+ * \param renderer the rendering context
+ * \param w a pointer filled in with the width in screen coordinates
+ * \param h a pointer filled in with the height in screen coordinates
+ * \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.
  *
- * Due to high-dpi displays, you might end up with a rendering context that
- * has more pixels than the window that contains it, so use this instead of
- * SDL_GetWindowSize() to decide how much drawing area you have.
+ * This returns the true output size in pixels, ignoring any render targets
+ * or logical size and presentation.
+ *
+ * \param renderer the rendering context
+ * \param w a pointer filled in with the width in pixels
+ * \param h a pointer filled in with the height in pixels
+ * \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_GetRenderOutputSize(SDL_Renderer *renderer, int *w, int *h);
+
+/**
+ * Get the current output size in pixels of a rendering context.
+ *
+ * If a rendering target is active, this will return the size of the
+ * rendering target in pixels, otherwise if a logical size is set, it will
+ * return the logical size, otherwise it will return the value of
+ * SDL_GetRenderOutputSize().
  *
  * \param renderer the rendering context
- * \param w an int filled with the width
- * \param h an int filled with the height
+ * \param w a pointer filled in with the current width
+ * \param h a pointer filled in with the current height
  * \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_GetRenderOutputSize
  * \sa SDL_GetRenderer
  */
-extern DECLSPEC int SDLCALL SDL_GetRendererOutputSize(SDL_Renderer *renderer, int *w, int *h);
+extern DECLSPEC int SDLCALL SDL_GetCurrentRenderOutputSize(SDL_Renderer *renderer, int *w, int *h);
 
 /**
  * Create a texture for a rendering context.
@@ -736,18 +789,6 @@ extern DECLSPEC int SDLCALL SDL_LockTextureToSurface(SDL_Texture *texture,
  */
 extern DECLSPEC void SDLCALL SDL_UnlockTexture(SDL_Texture *texture);
 
-/**
- * Determine whether a renderer supports the use of render targets.
- *
- * \param renderer the renderer that will be checked
- * \returns SDL_TRUE if supported or SDL_FALSE if not.
- *
- * \since This function is available since SDL 3.0.0.
- *
- * \sa SDL_SetRenderTarget
- */
-extern DECLSPEC SDL_bool SDLCALL SDL_RenderTargetSupported(SDL_Renderer *renderer);
-
 /**
  * Set a texture as the current rendering target.
  *
@@ -788,92 +829,116 @@ extern DECLSPEC int SDLCALL SDL_SetRenderTarget(SDL_Renderer *renderer, SDL_Text
 extern DECLSPEC SDL_Texture *SDLCALL SDL_GetRenderTarget(SDL_Renderer *renderer);
 
 /**
- * Set a device independent resolution for rendering.
+ * Set a device independent resolution and presentation mode for rendering.
+ *
+ * This function sets the width and height of the logical rendering output.
+ * A render target is created at the specified size and used for rendering
+ * and then copied to the output during presentation.
  *
- * This function uses the viewport and scaling functionality to allow a fixed
- * logical resolution for rendering, regardless of the actual output
- * resolution. If the actual output resolution doesn't have the same aspect
- * ratio the output rendering will be centered within the output display.
+ * When a renderer is created, the logical size is set to match the window
+ * size in screen coordinates. The actual output size may be higher pixel
+ * density, and can be queried with SDL_GetRenderOutputSize().
  *
- * If the output display is a window, mouse and touch events in the window
- * will be filtered and scaled so they seem to arrive within the logical
- * resolution. The SDL_HINT_MOUSE_RELATIVE_SCALING hint controls whether
- * relative motion events are also scaled.
+ * 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.
  *
- * If this function results in scaling or subpixel drawing by the rendering
- * backend, it will be handled using the appropriate quality hints.
+ * You can convert coordinates in an event into rendering coordinates using
+ * SDL_ConvertEventToRenderCoordinates().
  *
- * \param renderer the renderer for which resolution should be set
+ * \param renderer the rendering context
  * \param w the width of the logical resolution
  * \param h the height of the logical resolution
+ * \param mode the presentation mode used
+ * \param scale_mode the scale mode used
  * \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_GetRenderLogicalSize
+ * \sa SDL_ConvertEventToRenderCoordinates
+ * \sa SDL_GetRenderLogicalPresentation
  */
-extern DECLSPEC int SDLCALL SDL_SetRenderLogicalSize(SDL_Renderer *renderer, int w, int h);
+extern DECLSPEC int SDLCALL SDL_SetRenderLogicalPresentation(SDL_Renderer *renderer, int w, int h, SDL_RendererLogicalPresentation mode, SDL_ScaleMode scale_mode);
 
 /**
- * Get device independent resolution for rendering.
- *
- * When using the main rendering target (eg no target texture is set): this
- * may return 0 for `w` and `h` if the SDL_Renderer has never had its logical
- * size set by SDL_SetRenderLogicalSize(). Otherwise it returns the logical
- * width and height.
+ * Get device independent resolution and presentation mode for rendering.
  *
- * When using a target texture: Never return 0 for `w` and `h` at first. Then
- * it returns the logical width and height that are set.
+ * This function gets the width and height of the logical rendering output,
+ * or the output size in pixels if a logical resolution is not enabled.
  *
- * \param renderer a rendering context
+ * \param renderer the rendering context
  * \param w an int to be filled with the width
  * \param h an int to be filled with the height
+ * \param mode a pointer filled in with the presentation mode
+ * \param scale_mode a pointer filled in with the scale mode
+ * \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_SetRenderLogicalSize
+ * \sa SDL_SetRenderLogicalPresentation
  */
-extern DECLSPEC void SDLCALL SDL_GetRenderLogicalSize(SDL_Renderer *renderer, int *w, int *h);
+extern DECLSPEC int SDLCALL SDL_GetRenderLogicalPresentation(SDL_Renderer *renderer, int *w, int *h, SDL_RendererLogicalPresentation *mode, SDL_ScaleMode *scale_mode);
 
 /**
- * Set whether to force integer scales for resolution-independent rendering.
+ * Get a point in render coordinates when given a point in window coordinates.
  *
- * This function restricts the logical viewport to integer values - that is,
- * when a resolution is between two multiples of a logical size, the viewport
- * size is rounded down to the lower multiple.
+ * \param renderer the rendering context
+ * \param window_x the x coordinate in window coordinates
+ * \param window_y the y coordinate in window coordinates
+ * \param x a pointer filled with the x coordinate in render coordinates
+ * \param y a pointer filled with the y coordinate in render coordinates
+ * \returns 0 on success or a negative error code on failure; call
+ *          SDL_GetError() for more information.
  *
- * \param renderer the renderer for which integer scaling should be set
- * \param enable enable or disable the integer scaling for rendering
+ * \since This function is available since SDL 3.0.0.
+ *
+ * \sa SDL_SetRenderLogicalPresentation
+ * \sa SDL_SetRenderScale
+ */
+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 when given a point in render coordinates.
+ *
+ * \param renderer the rendering context
+ * \param x the x coordinate in render coordinates
+ * \param y the y coordinate in render coordinates
+ * \param window_x a pointer filled with the x coordinate in window coordinates
+ * \param window_y a pointer filled with the y coordinate in window coordinates
  * \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_GetRenderIntegerScale
- * \sa SDL_SetRenderLogicalSize
+ * \sa SDL_SetRenderLogicalPresentation
+ * \sa SDL_SetRenderScale
  */
-extern DECLSPEC int SDLCALL SDL_SetRenderIntegerScale(SDL_Renderer *renderer, SDL_bool enable);
+extern DECLSPEC int SDLCALL SDL_RenderCoordinatesToWindow(SDL_Renderer *renderer, float x, float y, float *window_x, float *window_y);
 
 /**
- * Get whether integer scales are forced for resolution-independent rendering.
+ * Convert the coordinates in an event to render coordinates.
+ *
+ * Touch coordinates are converted from normalized coordinates in the window
+ * to non-normalized rendering coordinates.
  *
- * \param renderer the renderer from which integer scaling should be queried
- * \returns SDL_TRUE if integer scales are forced or SDL_FALSE if not and on
- *          failure; call SDL_GetError() for more information.
+ * Once converted, the coordinates may be outside the rendering area.
+ *
+ * \param renderer the rendering context
+ * \param event the event to modify
+ * \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_SetRenderIntegerScale
+ * \sa SDL_GetRenderCoordinatesFromWindowCoordinates
  */
-extern DECLSPEC SDL_bool SDLCALL SDL_GetRenderIntegerScale(SDL_Renderer *renderer);
+extern DECLSPEC int SDLCALL SDL_ConvertEventToRenderCoordinates(SDL_Renderer *renderer, SDL_Event *event);
 
 /**
  * Set the drawing area for rendering on the current target.
  *
- * When the window is resized, the viewport is reset to fill the entire new
- * window size.
- *
  * \param renderer the rendering context
  * \param rect the SDL_Rect structure representing the drawing area, or NULL
  *             to set the viewport to the entire target
@@ -891,18 +956,19 @@ extern DECLSPEC int SDLCALL SDL_SetRenderViewport(SDL_Renderer *renderer, const
  *
  * \param renderer the rendering context
  * \param rect an SDL_Rect structure filled in with the current drawing area
+ * \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_SetRenderViewport
  */
-extern DECLSPEC void SDLCALL SDL_GetRenderViewport(SDL_Renderer *renderer, SDL_Rect *rect);
+extern DECLSPEC int SDLCALL SDL_GetRenderViewport(SDL_Renderer *renderer, SDL_Rect *rect);
 
 /**
  * Set the clip rectangle for rendering on the specified target.
  *
- * \param renderer the rendering context for which clip rectangle should be
- *                 set
+ * \param renderer the rendering context
  * \param rect an SDL_Rect structure representing the clip area, relative to
  *             the viewport, or NULL to disable clipping
  * \returns 0 on success or a negative error code on failure; call
@@ -918,22 +984,23 @@ extern DECLSPEC int SDLCALL SDL_SetRenderClipRect(SDL_Renderer *renderer, const
 /**
  * Get the clip rectangle for the current target.
  *
- * \param renderer the rendering context from which clip rectangle should be
- *    

(Patch may be truncated, please check the link at the top of this post.)