From dcd17f547324a143d66d79e3b586577a7da558ed Mon Sep 17 00:00:00 2001 From: Sam Lantinga 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 | 17 +- docs/README-migration.md | 28 +- include/SDL3/SDL_hints.h | 22 - include/SDL3/SDL_oldnames.h | 18 +- include/SDL3/SDL_render.h | 290 +++--- 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 | 1162 ++++++++++++---------- 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, 1113 insertions(+), 910 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 e8b7200e3..76d72f908 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 d5e4914b5..3cdb81e81 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. +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. -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. +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 a60f97e64..7a9552a2c 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 1a5237be5..f041bcc64 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 0a663fc6f..570c81af7 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 ded0f973b..7bd32c646 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 @@ -301,15 +316,14 @@ 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 pixels of a rendering context. + * Get the output size in screen coordinates 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 screen coordinates, ignoring any + * render targets or logical size and presentation. * * \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 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. * @@ -317,7 +331,46 @@ extern DECLSPEC int SDLCALL SDL_GetRendererInfo(SDL_Renderer *renderer, SDL_Rend * * \sa SDL_GetRenderer */ -extern DECLSPEC int SDLCALL SDL_GetRendererOutputSize(SDL_Renderer *renderer, int *w, int *h); +extern DECLSPEC int SDLCALL SDL_GetRenderWindowSize(SDL_Renderer *renderer, int *w, int *h); + +/** + * Get the output size in pixels of a rendering context. + * + * 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 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_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 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. + * 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. * - * 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. + * 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 this function results in scaling or subpixel drawing by the rendering - * backend, it will be handled using the appropriate quality hints. + * 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. * - * \param renderer the renderer for which resolution should be set + * You can convert coordinates in an event into rendering coordinates using + * SDL_ConvertEventToRenderCoordinates(). + * + * \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. + * Get device independent resolution and presentation mode 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. + * 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. * - * 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. - * - * \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 - * - * \since This function is available since SDL 3.0.0. - * - * \sa SDL_SetRenderLogicalSize - */ -extern DECLSPEC void SDLCALL SDL_GetRenderLogicalSize(SDL_Renderer *renderer, int *w, int *h); - -/** - * Set whether to force integer scales for resolution-independent rendering. - * - * 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 renderer for which integer scaling should be set - * \param enable enable or disable the integer scaling for rendering + * \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_GetRenderIntegerScale - * \sa SDL_SetRenderLogicalSize + * \sa SDL_SetRenderLogicalPresentation */ -extern DECLSPEC int SDLCALL SDL_SetRenderIntegerScale(SDL_Renderer *renderer, SDL_bool enable); +extern DECLSPEC int SDLCALL SDL_GetRenderLogicalPresentation(SDL_Renderer *renderer, int *w, int *h, SDL_RendererLogicalPresentation *mode, SDL_ScaleMode *scale_mode); /** - * Get whether integer scales are forced for resolution-independent rendering. + * Get a point in render coordinates when given a point in window 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. + * \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. * * \since This function is available since SDL 3.0.0. * - * \sa SDL_SetRenderIntegerScale + * \sa SDL_SetRenderLogicalPresentation + * \sa SDL_SetRenderScale */ -extern DECLSPEC SDL_bool SDLCALL SDL_GetRenderIntegerScale(SDL_Renderer *renderer); +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_SetRenderLogicalPresentation + * \sa SDL_SetRenderScale + */ +extern DECLSPEC int SDLCALL SDL_RenderCoordinatesToWindow(SDL_Renderer *renderer, float x, float y, float *window_x, float *window_y); + +/** + * Convert the coordinates in an event to render coordinates. + * + * Touch coordinates are converted from normalized coordinates in the window + * to non-normalized rendering coordinates. + * + * 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_GetRenderCoordinatesFromWindowCoordinates + */ +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 - * queried + * \param renderer the rendering context * \param rect an SDL_Rect structure filled in with the current clipping area * or an empty rectangle if clipping is disabled + * \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_RenderClipEnabled * \sa SDL_SetRenderClipRect */ -extern DECLSPEC void SDLCALL SDL_GetRenderClipRect(SDL_Renderer *renderer, SDL_Rect *rect); +extern DECLSPEC int SDLCALL SDL_GetRenderClipRect(SDL_Renderer *renderer, SDL_Rect *rect); /** * Get whether clipping is enabled on the given renderer. * - * \param renderer the renderer from which clip state should be queried + * \param renderer the rendering context * \returns SDL_TRUE if clipping is enabled or SDL_FALSE if not; call * SDL_GetError() for more information. * @@ -944,7 +1011,6 @@ extern DECLSPEC void SDLCALL SDL_GetRenderClipRect(SDL_Renderer *renderer, SDL_R */ extern DECLSPEC SDL_bool SDLCALL SDL_RenderClipEnabled(SDL_Renderer *renderer); - /** * Set the drawing scale for rendering on the current target. * @@ -956,7 +1022,7 @@ extern DECLSPEC SDL_bool SDLCALL SDL_RenderClipEnabled(SDL_Renderer *renderer); * will be handled using the appropriate quality hints. For best results use * integer scaling factors. * - * \param renderer a rendering context + * \param renderer the rendering context * \param scaleX the horizontal scaling factor * \param scaleY the vertical scaling factor * \returns 0 on success or a negative error code on failure; call @@ -965,73 +1031,23 @@ extern DECLSPEC SDL_bool SDLCALL SDL_RenderClipEnabled(SDL_Renderer *renderer); * \since This function is available since SDL 3.0.0. * * \sa SDL_GetRenderScale - * \sa SDL_SetRenderLogicalSize */ extern DECLSPEC int SDLCALL SDL_SetRenderScale(SDL_Renderer *renderer, float scaleX, float scaleY); /** * Get the drawing scale for the current target. * - * \param renderer the renderer from which drawing scale should be queried + * \param renderer the rendering context * \param scaleX a pointer filled in with the horizontal scaling factor * \param scaleY a pointer filled in with the vertical scaling factor + * \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_SetRenderScale */ -extern DECLSPEC void SDLCALL SDL_GetRenderScale(SDL_Renderer *renderer, float *scaleX, float *scaleY); - -/** - * Get logical coordinates of point in renderer when given real coordinates of - * point in window. - * - * Logical coordinates will differ from real coordinates when render is scaled - * and logical renderer size set - * - * \param renderer the renderer from which the logical coordinates should be - * calculated - * \param windowX the real X coordinate in the window - * \param windowY the real Y coordinate in the window - * \param logicalX the pointer filled with the logical x coordinate - * \param logicalY the pointer filled with the logical y coordinate - * - * \since This function is available since SDL 3.0.0. - * - * \sa SDL_GetRenderScale - * \sa SDL_SetRenderScale - * \sa SDL_GetRenderLogicalSize - * \sa SDL_SetRenderLogicalSize - */ -extern DECLSPEC void SDLCALL SDL_RenderWindowToLogical(SDL_Renderer *renderer, - float windowX, float windowY, - float *logicalX, float *logicalY); - - -/** - * Get real coordinates of point in window when given logical coordinates of - * point in renderer. - * - * Logical coordinates will differ from real coordinates when render is scaled - * and logical renderer size set - * - * \param renderer the renderer from which the window coordinates should be - * calculated - * \param logicalX the logical x coordinate - * \param logicalY the logical y coordinate - * \param windowX the pointer filled with the real X coordinate in the window - * \param windowY the pointer filled with the real Y coordinate in the window - * - * \since This function is available since SDL 3.0.0. - * - * \sa SDL_GetRenderScale - * \sa SDL_SetRenderScale - * \sa SDL_GetRenderLogicalSize - * \sa SDL_SetRenderLogicalSize - */ -extern DECLSPEC void SDLCALL SDL_RenderLogicalToWindow(SDL_Renderer *renderer, - float logicalX, float logicalY, - float *windowX, float *windowY); +extern DECLSPEC int SDLCALL SDL_GetRenderScale(SDL_Renderer *renderer, float *scaleX, float *scaleY); /** * Set the color used for drawing operations (Rect, Line and Clear). @@ -1356,8 +1372,8 @@ extern DECLSPEC int SDLCALL SDL_RenderGeometryRaw(SDL_Renderer *renderer, * Bitmap data pads all rows to multiples of 4 bytes). * * \param renderer the rendering context - * \param rect an SDL_Rect structure representing the area to read, or NULL - * for the entire render target + * \param rect an SDL_Rect structure representing the area in pixels relative + * to the to current viewport, or NULL for the entire viewport * \param format an SDL_PixelFormatEnum value of the desired format of the * pixel data, or 0 to use the format of the rendering target * \param pixels a pointer to the pixel data to copy into diff --git a/include/SDL3/SDL_test_common.h b/include/SDL3/SDL_test_common.h index 9b3d7dab6..b7b2df90b 100644 --- a/include/SDL3/SDL_test_common.h +++ b/include/SDL3/SDL_test_common.h @@ -77,6 +77,8 @@ typedef struct int window_maxH; int logical_w; int logical_h; + SDL_RendererLogicalPresentation logical_presentation; + SDL_ScaleMode logical_scale_mode; float scale; int depth; float refresh_rate; diff --git a/include/SDL3/SDL_video.h b/include/SDL3/SDL_video.h index ef5678799..15c1cf48f 100644 --- a/include/SDL3/SDL_video.h +++ b/include/SDL3/SDL_video.h @@ -631,10 +631,10 @@ extern DECLSPEC Uint32 SDLCALL SDL_GetWindowPixelFormat(SDL_Window *window); * The window size in pixels may differ from its size in screen coordinates if * the window is on a high density display (one with an OS scaling factor). * Use SDL_GetWindowSize() to query the client area's size in screen - * coordinates, and SDL_GetWindowSizeInPixels() or SDL_GetRendererOutputSize() + * coordinates, and SDL_GetWindowSizeInPixels() or SDL_GetRenderOutputSize() * to query the drawable size in pixels. Note that the drawable size can vary - * after the window is created and should be queried again when the window is - * resized or moved between displays. + * after the window is created and should be queried again if you get an + * SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED event. * * If the window is set fullscreen, the width and height parameters `w` and * `h` will not be used. However, invalid size parameters (e.g. too large) may @@ -868,7 +868,7 @@ extern DECLSPEC void SDLCALL SDL_SetWindowSize(SDL_Window *window, int w, int h) * * The window size in screen coordinates may differ from the size in pixels if * the window is on a high density display (one with an OS scaling factor). - * Use SDL_GetWindowSizeInPixels() or SDL_GetRendererOutputSize() to get the + * Use SDL_GetWindowSizeInPixels() or SDL_GetRenderOutputSize() to get the * real client area size in pixels. * * \param window the window to query the width and height from @@ -877,8 +877,8 @@ extern DECLSPEC void SDLCALL SDL_SetWindowSize(SDL_Window *window, int w, int h) * * \since This function is available since SDL 3.0.0. * + * \sa SDL_GetRenderOutputSize * \sa SDL_GetWindowSizeInPixels - * \sa SDL_GetRendererOutputSize * \sa SDL_SetWindowSize */ extern DECLSPEC void SDLCALL SDL_GetWindowSize(SDL_Window *window, int *w, int *h); diff --git a/src/dynapi/SDL_dynapi.sym b/src/dynapi/SDL_dynapi.sym index 8547bde20..eb6f9c4f4 100644 --- a/src/dynapi/SDL_dynapi.sym +++ b/src/dynapi/SDL_dynapi.sym @@ -295,17 +295,15 @@ SDL3_0.0.0 { SDL_GetRenderDrawBlendMode; SDL_GetRenderDrawColor; SDL_GetRenderDriver; - SDL_GetRenderIntegerScale; - SDL_GetRenderLogicalSize; + SDL_GetRenderLogicalPresentation; SDL_GetRenderMetalCommandEncoder; SDL_GetRenderMetalLayer; - SDL_GetRenderScale; SDL_GetRenderTarget; SDL_GetRenderViewport; SDL_GetRenderWindow; SDL_GetRenderer; SDL_GetRendererInfo; - SDL_GetRendererOutputSize; + SDL_GetCurrentRenderOutputSize; SDL_GetRevision; SDL_GetScancodeFromKey; SDL_GetScancodeFromName; @@ -526,17 +524,16 @@ SDL3_0.0.0 { SDL_RenderGetD3D12Device; SDL_RenderLine; SDL_RenderLines; - SDL_RenderLogicalToWindow; + SDL_RenderCoordinatesToWindow; SDL_RenderPoint; SDL_RenderPoints; SDL_RenderPresent; SDL_RenderReadPixels; SDL_RenderRect; SDL_RenderRects; - SDL_RenderTargetSupported; SDL_RenderTexture; SDL_RenderTextureRotated; - SDL_RenderWindowToLogical; + SDL_RenderCoordinatesFromWindow; SDL_ReportAssertion; SDL_ResetAssertionReport; SDL_ResetHint; @@ -587,9 +584,7 @@ SDL3_0.0.0 { SDL_SetRenderClipRect; SDL_SetRenderDrawBlendMode; SDL_SetRenderDrawColor; - SDL_SetRenderIntegerScale; - SDL_SetRenderLogicalSize; - SDL_SetRenderScale; + SDL_SetRenderLogicalPresentation; SDL_SetRenderTarget; SDL_SetRenderVSync; SDL_SetRenderViewport; @@ -839,6 +834,11 @@ SDL3_0.0.0 { SDL_GetPrimaryDisplay; SDL_GetFullscreenDisplayModes; SDL_GetClosestFullscreenDisplayMode; + SDL_GetRenderOutputSize; + SDL_ConvertEventToRenderCoordinates; + SDL_SetRenderScale; + SDL_GetRenderScale; + SDL_GetRenderWindowSize; # extra symbols go here (don't modify this line) local: *; }; diff --git a/src/dynapi/SDL_dynapi_overrides.h b/src/dynapi/SDL_dynapi_overrides.h index 92d4019f9..2ec98a0d7 100644 --- a/src/dynapi/SDL_dynapi_overrides.h +++ b/src/dynapi/SDL_dynapi_overrides.h @@ -320,17 +320,15 @@ #define SDL_GetRenderDrawBlendMode SDL_GetRenderDrawBlendMode_REAL #define SDL_GetRenderDrawColor SDL_GetRenderDrawColor_REAL #define SDL_GetRenderDriver SDL_GetRenderDriver_REAL -#define SDL_GetRenderIntegerScale SDL_GetRenderIntegerScale_REAL -#define SDL_GetRenderLogicalSize SDL_GetRenderLogicalSize_REAL +#define SDL_GetRenderLogicalPresentation SDL_GetRenderLogicalPresentation_REAL #define SDL_GetRenderMetalCommandEncoder SDL_GetRenderMetalCommandEncoder_REAL #define SDL_GetRenderMetalLayer SDL_GetRenderMetalLayer_REAL -#define SDL_GetRenderScale SDL_GetRenderScale_REAL #define SDL_GetRenderTarget SDL_GetRenderTarget_REAL #define SDL_GetRenderViewport SDL_GetRenderViewport_REAL #define SDL_GetRenderWindow SDL_GetRenderWindow_REAL #define SDL_GetRenderer SDL_GetRenderer_REAL #define SDL_GetRendererInfo SDL_GetRendererInfo_REAL -#define SDL_GetRendererOutputSize SDL_GetRendererOutputSize_REAL +#define SDL_GetCurrentRenderOutputSize SDL_GetCurrentRenderOutputSize_REAL #define SDL_GetRevision SDL_GetRevision_REAL #define SDL_GetScancodeFromKey SDL_GetScancodeFromKey_REAL #define SDL_GetScancodeFromName SDL_GetScancodeFromName_REAL @@ -551,17 +549,16 @@ #define SDL_RenderGetD3D12Device SDL_RenderGetD3D12Device_REAL #define SDL_RenderLine SDL_RenderLine_REAL #define SDL_RenderLines SDL_RenderLines_REAL -#define SDL_RenderLogicalToWindow SDL_RenderLogicalToWindow_REAL +#define SDL_RenderCoordinatesToWindow SDL_RenderCoordinatesToWindow_REAL #define SDL_RenderPoint SDL_RenderPoint_REAL #define SDL_RenderPoints SDL_RenderPoints_REAL #define SDL_RenderPresent SDL_RenderPresent_REAL #define SDL_RenderReadPixels SDL_RenderReadPixels_REAL #define SDL_RenderRect SDL_RenderRect_REAL #define SDL_RenderRects SDL_RenderRects_REAL -#define SDL_RenderTargetSupported SDL_RenderTargetSupported_REAL #define SDL_RenderTexture SDL_RenderTexture_REAL #define SDL_RenderTextureRotated SDL_RenderTextureRotated_REAL -#define SDL_RenderWindowToLogical SDL_RenderWindowToLogical_REAL +#define SDL_RenderCoordinatesFromWindow SDL_RenderCoordinatesFromWindow_REAL #define SDL_ReportAssertion SDL_ReportAssertion_REAL #define SDL_ResetAssertionReport SDL_ResetAssertionReport_REAL #define SDL_ResetHint SDL_ResetHint_REAL @@ -612,9 +609,7 @@ #define SDL_SetRenderClipRect SDL_SetRenderClipRect_REAL #define SDL_SetRenderDrawBlendMode SDL_SetRenderDrawBlendMode_REAL #define SDL_SetRenderDrawColor SDL_SetRenderDrawColor_REAL -#define SDL_SetRenderIntegerScale SDL_SetRenderIntegerScale_REAL -#define SDL_SetRenderLogicalSize SDL_SetRenderLogicalSize_REAL -#define SDL_SetRenderScale SDL_SetRenderScale_REAL +#define SDL_SetRenderLogicalPresentation SDL_SetRenderLogicalPresentation_REAL #define SDL_SetRenderTarget SDL_SetRenderTarget_REAL #define SDL_SetRenderVSync SDL_SetRenderVSync_REAL #define SDL_SetRenderViewport SDL_SetRenderViewport_REAL @@ -866,3 +861,8 @@ #define SDL_GetPrimaryDisplay SDL_GetPrimaryDisplay_REAL #define SDL_GetFullscreenDisplayModes SDL_GetFullscreenDisplayModes_REAL #define SDL_GetClosestFullscreenDisplayMode SDL_GetClosestFullscreenDisplayMode_REAL +#define SDL_GetRenderOutputSize SDL_GetRenderOutputSize_REAL +#define SDL_ConvertEventToRenderCoordinates SDL_ConvertEventToRenderCoordinates_REAL +#define SDL_SetRenderScale SDL_SetRenderScale_REAL +#define SDL_GetRenderScale SDL_GetRenderScale_REAL +#define SDL_GetRenderWindowSize SDL_GetRenderWindowSize_REAL diff --git a/src/dynapi/SDL_dynapi_procs.h b/src/dynapi/SDL_dynapi_procs.h index 1363f552d..0cc19e370 100644 --- a/src/dynapi/SDL_dynapi_procs.h +++ b/src/dynapi/SDL_dynapi_procs.h @@ -388,21 +388,19 @@ SDL_DYNAPI_PROC(void,SDL_GetRectUnion,(const SDL_Rect *a, const SDL_Rect *b, SDL SDL_DYNAPI_PROC(void,SDL_GetRectUnionFloat,(const SDL_FRect *a, const SDL_FRect *b, SDL_FRect *c),(a,b,c),) SDL_DYNAPI_PROC(SDL_bool,SDL_GetRelativeMouseMode,(void),(),return) SDL_DYNAPI_PROC(Uint32,SDL_GetRelativeMouseState,(float *a, float *b),(a,b),return) -SDL_DYNAPI_PROC(void,SDL_GetRenderClipRect,(SDL_Renderer *a, SDL_Rect *b),(a,b),) +SDL_DYNAPI_PROC(int,SDL_GetRenderClipRect,(SDL_Renderer *a, SDL_Rect *b),(a,b),return) SDL_DYNAPI_PROC(int,SDL_GetRenderDrawBlendMode,(SDL_Renderer *a, SDL_BlendMode *b),(a,b),return) SDL_DYNAPI_PROC(int,SDL_GetRenderDrawColor,(SDL_Renderer *a, Uint8 *b, Uint8 *c, Uint8 *d, Uint8 *e),(a,b,c,d,e),return) SDL_DYNAPI_PROC(const char*,SDL_GetRenderDriver,(int a),(a),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_GetRenderIntegerScale,(SDL_Renderer *a),(a),return) -SDL_DYNAPI_PROC(void,SDL_GetRenderLogicalSize,(SDL_Renderer *a, int *b, int *c),(a,b,c),) +SDL_DYNAPI_PROC(int,SDL_GetRenderLogicalPresentation,(SDL_Renderer *a, int *b, int *c, SDL_RendererLogicalPresentation *d, SDL_ScaleMode *e),(a,b,c,d,e),return) SDL_DYNAPI_PROC(void*,SDL_GetRenderMetalCommandEncoder,(SDL_Renderer *a),(a),return) SDL_DYNAPI_PROC(void*,SDL_GetRenderMetalLayer,(SDL_Renderer *a),(a),return) -SDL_DYNAPI_PROC(void,SDL_GetRenderScale,(SDL_Renderer *a, float *b, float *c),(a,b,c),) SDL_DYNAPI_PROC(SDL_Texture*,SDL_GetRenderTarget,(SDL_Renderer *a),(a),return) -SDL_DYNAPI_PROC(void,SDL_GetRenderViewport,(SDL_Renderer *a, SDL_Rect *b),(a,b),) +SDL_DYNAPI_PROC(int,SDL_GetRenderViewport,(SDL_Renderer *a, SDL_Rect *b),(a,b),return) SDL_DYNAPI_PROC(SDL_Window*,SDL_GetRenderWindow,(SDL_Renderer *a),(a),return) SDL_DYNAPI_PROC(SDL_Renderer*,SDL_GetRenderer,(SDL_Window *a),(a),return) SDL_DYNAPI_PROC(int,SDL_GetRendererInfo,(SDL_Renderer *a, SDL_RendererInfo *b),(a,b),return) -SDL_DYNAPI_PROC(int,SDL_GetRendererOutputSize,(SDL_Renderer *a, int *b, int *c),(a,b,c),return) +SDL_DYNAPI_PROC(int,SDL_GetCurrentRenderOutputSize,(SDL_Renderer *a, int *b, int *c),(a,b,c),return) SDL_DYNAPI_PROC(const char*,SDL_GetRevision,(void),(),return) SDL_DYNAPI_PROC(SDL_Scancode,SDL_GetScancodeFromKey,(SDL_Keycode a),(a),return) SDL_DYNAPI_PROC(SDL_Scancode,SDL_GetScancodeFromName,(const char *a),(a),return) @@ -607,17 +605,16 @@ SDL_DYNAPI_PROC(int,SDL_RenderGeometry,(SDL_Renderer *a, SDL_Texture *b, const S SDL_DYNAPI_PROC(int,SDL_RenderGeometryRaw,(SDL_Renderer *a, SDL_Texture *b, const float *c, int d, const SDL_Color *e, int f, const float *g, int h, int i, const void *j, int k, int l),(a,b,c,d,e,f,g,h,i,j,k,l),return) SDL_DYNAPI_PROC(int,SDL_RenderLine,(SDL_Renderer *a, float b, float c, float d, float e),(a,b,c,d,e),return) SDL_DYNAPI_PROC(int,SDL_RenderLines,(SDL_Renderer *a, const SDL_FPoint *b, int c),(a,b,c),return) -SDL_DYNAPI_PROC(void,SDL_RenderLogicalToWindow,(SDL_Renderer *a, float b, float c, float *d, float *e),(a,b,c,d,e),) +SDL_DYNAPI_PROC(int,SDL_RenderCoordinatesToWindow,(SDL_Renderer *a, float b, float c, float *d, float *e),(a,b,c,d,e),return) SDL_DYNAPI_PROC(int,SDL_RenderPoint,(SDL_Renderer *a, float b, float c),(a,b,c),return) SDL_DYNAPI_PROC(int,SDL_RenderPoints,(SDL_Renderer *a, const SDL_FPoint *b, int c),(a,b,c),return) SDL_DYNAPI_PROC(void,SDL_RenderPresent,(SDL_Renderer *a),(a),) SDL_DYNAPI_PROC(int,SDL_RenderReadPixels,(SDL_Renderer *a, const SDL_Rect *b, Uint32 c, void *d, int e),(a,b,c,d,e),return) SDL_DYNAPI_PROC(int,SDL_RenderRect,(SDL_Renderer *a, const SDL_FRect *b),(a,b),return) SDL_DYNAPI_PROC(int,SDL_RenderRects,(SDL_Renderer *a, const SDL_FRect *b, int c),(a,b,c),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_RenderTargetSupported,(SDL_Renderer *a),(a),return) SDL_DYNAPI_PROC(int,SDL_RenderTexture,(SDL_Renderer *a, SDL_Texture *b, const SDL_Rect *c, const SDL_FRect *d),(a,b,c,d),return) SDL_DYNAPI_PROC(int,SDL_RenderTextureRotated,(SDL_Renderer *a, SDL_Texture *b, const SDL_Rect *c, const SDL_FRect *d, const double e, const SDL_FPoint *f, const SDL_RendererFlip g),(a,b,c,d,e,f,g),return) -SDL_DYNAPI_PROC(void,SDL_RenderWindowToLogical,(SDL_Renderer *a, float b, float c, float *d, float *e),(a,b,c,d,e),) +SDL_DYNAPI_PROC(int,SDL_RenderCoordinatesFromWindow,(SDL_Renderer *a, float b, float c, float *d, float *e),(a,b,c,d,e),return) SDL_DYNAPI_PROC(SDL_AssertState,SDL_ReportAssertion,(SDL_AssertData *a, const char *b, const char *c, int d),(a,b,c,d),return) SDL_DYNAPI_PROC(void,SDL_ResetAssertionReport,(void),(),) SDL_DYNAPI_PROC(SDL_bool,SDL_ResetHint,(const char *a),(a),return) @@ -667,9 +664,7 @@ SDL_DYNAPI_PROC(int,SDL_SetRelativeMouseMode,(SDL_bool a),(a),return) SDL_DYNAPI_PROC(int,SDL_SetRenderClipRect,(SDL_Renderer *a, const SDL_Rect *b),(a,b),return) SDL_DYNAPI_PROC(int,SDL_SetRenderDrawBlendMode,(SDL_Renderer *a, SDL_BlendMode b),(a,b),return) SDL_DYNAPI_PROC(int,SDL_SetRenderDrawColor,(SDL_Renderer *a, Uint8 b, Uint8 c, Uint8 d, Uint8 e),(a,b,c,d,e),return) -SDL_DYNAPI_PROC(int,SDL_SetRenderIntegerScale,(SDL_Renderer *a, SDL_bool b),(a,b),return) -SDL_DYNAPI_PROC(int,SDL_SetRenderLogicalSize,(SDL_Renderer *a, int b, int c),(a,b,c),return) -SDL_DYNAPI_PROC(int,SDL_SetRenderScale,(SDL_Renderer *a, float b, float c),(a,b,c),return) +SDL_DYNAPI_PROC(int,SDL_SetRenderLogicalPresentation,(SDL_Renderer *a, int b, int c, SDL_RendererLogicalPresentation d, SDL_ScaleMode e),(a,b,c,d,e),return) SDL_DYNAPI_PROC(int,SDL_SetRenderTarget,(SDL_Renderer *a, SDL_Texture *b),(a,b),return) SDL_DYNAPI_PROC(int,SDL_SetRenderVSync,(SDL_Renderer *a, int b),(a,b),return) SDL_DYNAPI_PROC(int,SDL_SetRenderViewport,(SDL_Renderer *a, const SDL_Rect *b),(a,b),return) @@ -911,3 +906,8 @@ SDL_DYNAPI_PROC(SDL_DisplayID*,SDL_GetDisplays,(int *a),(a),return) SDL_DYNAPI_PROC(SDL_DisplayID,SDL_GetPrimaryDisplay,(void),(),return) SDL_DYNAPI_PROC(const SDL_DisplayMode**,SDL_GetFullscreenDisplayModes,(SDL_DisplayID a, int *b),(a,b),return) SDL_DYNAPI_PROC(const SDL_DisplayMode*,SDL_GetClosestFullscreenDisplayMode,(SDL_DisplayID a, int b, int c, float d),(a,b,c,d),return) +SDL_DYNAPI_PROC(int,SDL_GetRenderOutputSize,(SDL_Renderer *a, int *b, int *c),(a,b,c),return) +SDL_DYNAPI_PROC(int,SDL_ConvertEventToRenderCoordinates,(SDL_Renderer *a, SDL_Event *b),(a,b),return) +SDL_DYNAPI_PROC(int,SDL_SetRenderScale,(SDL_Renderer *a, float b, float c),(a,b,c),return) +SDL_DYNAPI_PROC(int,SDL_GetRenderScale,(SDL_Renderer *a, float *b, float *c),(a,b,c),return) +SDL_DYNAPI_PROC(int,SDL_GetRenderWindowSize,(SDL_Renderer *a, int *b, int *c),(a,b,c),return) diff --git a/src/render/SDL_render.c b/src/render/SDL_render.c old mode 100644 new mode 100755 index 62df8a6c5..04c3e4200 --- a/src/render/SDL_render.c +++ b/src/render/SDL_render.c @@ -275,8 +275,7 @@ int SDL_RenderFlush(SDL_Renderer *renderer) return FlushRenderCommands(renderer); } -void * -SDL_AllocateRenderVertices(SDL_Renderer *renderer, const size_t numbytes, const size_t alignment, size_t *offset) +void *SDL_AllocateRenderVertices(SDL_Renderer *renderer, const size_t numbytes, const size_t alignment, size_t *offset) { const size_t needed = renderer->vertex_data_used + numbytes + alignment; const size_t current_offset = renderer->vertex_data_used; @@ -339,27 +338,45 @@ static SDL_RenderCommand *AllocateRenderCommand(SDL_Renderer *renderer) return retval; } +static void GetRenderViewportInPixels(SDL_Renderer *renderer, SDL_Rect *rect) +{ + rect->x = (int)SDL_floorf(renderer->view->viewport.x * renderer->view->scale.x); + rect->y = (int)SDL_floorf(renderer->view->viewport.y * renderer->view->scale.y); + if (renderer->view->viewport.w >= 0) { + rect->w = (int)SDL_floorf(renderer->view->viewport.w * renderer->view->scale.x); + } else { + rect->w = renderer->view->pixel_w; + } + if (renderer->view->viewport.h >= 0) { + rect->h = (int)SDL_floorf(renderer->view->viewport.h * renderer->view->scale.y); + } else { + rect->h = renderer->view->pixel_h; + } +} + static int QueueCmdSetViewport(SDL_Renderer *renderer) { + SDL_Rect viewport; int retval = 0; - if (!renderer->viewport_queued || (SDL_memcmp(&renderer->viewport, &renderer->last_queued_viewport, sizeof(SDL_DRect)) != 0)) { + + GetRenderViewportInPixels(renderer, &viewport); + + if (!renderer->viewport_queued || + SDL_memcmp(&viewport, &renderer->last_queued_viewport, sizeof(viewport)) != 0) { SDL_RenderCommand *cmd = AllocateRenderCommand(renderer); - retval = -1; if (cmd != NULL) { cmd->command = SDL_RENDERCMD_SETVIEWPORT; cmd->data.viewport.first = 0; /* render backend will fill this in. */ - /* Convert SDL_DRect to SDL_Rect */ - cmd->data.viewport.rect.x = (int)SDL_floor(renderer->viewport.x); - cmd->data.viewport.rect.y = (int)SDL_floor(renderer->viewport.y); - cmd->data.viewport.rect.w = (int)SDL_floor(renderer->viewport.w); - cmd->data.viewport.rect.h = (int)SDL_floor(renderer->viewport.h); + SDL_copyp(&cmd->data.viewport.rect, &viewport); retval = renderer->QueueSetViewport(renderer, cmd); if (retval < 0) { cmd->command = SDL_RENDERCMD_NO_OP; } else { - SDL_copyp(&renderer->last_queued_viewport, &renderer->viewport); + SDL_copyp(&renderer->last_queued_viewport, &viewport); renderer->viewport_queued = SDL_TRUE; } + } else { + retval = -1; } } return retval; @@ -367,24 +384,27 @@ static int QueueCmdSetViewport(SDL_Renderer *renderer) static int QueueCmdSetClipRect(SDL_Renderer *renderer) { + SDL_Rect clip_rect; int retval = 0; - if ((!renderer->cliprect_queued) || - (renderer->clipping_enabled != renderer->last_queued_cliprect_enabled) || - (SDL_memcmp(&renderer->clip_rect, &renderer->last_queued_cliprect, sizeof(SDL_DRect)) != 0)) { + + clip_rect.x = (int)SDL_floorf(renderer->view->clip_rect.x * renderer->view->scale.x); + clip_rect.y = (int)SDL_floorf(renderer->view->clip_rect.y * renderer->view->scale.y); + clip_rect.w = (int)SDL_floorf(renderer->view->clip_rect.w * renderer->view->scale.x); + clip_rect.h = (int)SDL_floorf(renderer->view->clip_rect.h * renderer->view->scale.y); + + if (!renderer->cliprect_queued || + renderer->view->clipping_enabled != renderer->last_queued_cliprect_enabled || + SDL_memcmp(&clip_rect, &renderer->last_queued_cliprect, sizeof(clip_rect)) != 0) { SDL_RenderCommand *cmd = AllocateRenderCommand(renderer); - if (cmd == NULL) { - retval = -1; - } else { + if (cmd != NULL) { cmd->command = SDL_RENDERCMD_SETCLIPRECT; - cmd->data.cliprect.enabled = renderer->clipping_enabled; - /* Convert SDL_DRect to SDL_Rect */ - cmd->data.cliprect.rect.x = (int)SDL_floor(renderer->clip_rect.x); - cmd->data.cliprect.rect.y = (int)SDL_floor(renderer->clip_rect.y); - cmd->data.cliprect.rect.w = (int)SDL_floor(renderer->clip_rect.w); - cmd->data.cliprect.rect.h = (int)SDL_floor(renderer->clip_rect.h); - SDL_copyp(&renderer->last_queued_cliprect, &renderer->clip_rect); - renderer->last_queued_cliprect_enabled = renderer->clipping_enabled; + cmd->data.cliprect.enabled = renderer->view->clipping_enabled; + SDL_copyp(&cmd->data.cliprect.rect, &clip_rect); + SDL_copyp(&renderer->last_queued_cliprect, &clip_rect); + renderer->last_queued_cliprect_enabled = renderer->view->clipping_enabled; renderer->cliprect_queued = SDL_TRUE; + } else { + retval = -1; } } return retval; @@ -450,7 +470,6 @@ static SDL_RenderCommand *PrepQueueCmdDraw(SDL_Renderer *renderer, const SDL_Ren } if (cmdtype != SDL_RENDERCMD_GEOMETRY) { - /* !!! FIXME: drop this draw if viewport w or h is zero. */ retval = QueueCmdSetDrawColor(renderer, color); } @@ -632,7 +651,20 @@ static int QueueCmdGeometry(SDL_Renderer *renderer, SDL_Texture *texture, return retval; } -static int UpdateLogicalSize(SDL_Renderer *renderer, SDL_bool flush_viewport_cmd); +static void UpdateMainViewDimensions(SDL_Renderer *renderer) +{ + int window_w = 0, window_h = 0; + + SDL_GetRenderWindowSize(renderer, &window_w, &window_h); + SDL_GetRenderOutputSize(renderer, &renderer->main_view.pixel_w, &renderer->main_view.pixel_h); + if (window_w > 0 && window_h > 0) { + renderer->dpi_scale.x = (float)renderer->main_view.pixel_w / window_w; + renderer->dpi_scale.y = (float)renderer->main_view.pixel_h / window_h; + } +} + +static int UpdateLogicalPresentation(SDL_Renderer *renderer); + int SDL_GetNumRenderDrivers(void) { @@ -658,16 +690,6 @@ const char *SDL_GetRenderDriver(int index) #endif } -static void GetWindowViewportValues(SDL_Renderer *renderer, int *logical_w, int *logical_h, SDL_DRect *viewport, SDL_FPoint *scale) -{ - SDL_LockMutex(renderer->target_mutex); - *logical_w = renderer->target ? renderer->logical_w_backup : renderer->logical_w; - *logical_h = renderer->target ? renderer->logical_h_backup : renderer->logical_h; - *viewport = renderer->target ? renderer->viewport_backup : renderer->viewport; - *scale = renderer->target ? renderer->scale_backup : renderer->scale; - SDL_UnlockMutex(renderer->target_mutex); -} - static int SDLCALL SDL_RendererEventWatch(void *userdata, SDL_Event *event) { SDL_Renderer *renderer = (SDL_Renderer *)userdata; @@ -679,64 +701,10 @@ static int SDLCALL SDL_RendererEventWatch(void *userdata, SDL_Event *event) renderer->WindowEvent(renderer, &event->window); } - /* In addition to size changes, we also want to do this block for - * window display changes as well! If the new display has a new DPI, - * we need to update the viewport for the new window/drawable ratio. - */ if (event->type == SDL_EVENT_WINDOW_RESIZED || event->type == SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED) { - /* Make sure we're operating on the default render target */ - SDL_Texture *saved_target = SDL_GetRenderTarget(renderer); - if (saved_target) { - SDL_SetRenderTarget(renderer, NULL); - } - - /* Update the DPI scale if the window has been resized. */ - if (window && renderer->GetOutputSize) { - int window_w, window_h; - int output_w, output_h; - if (renderer->GetOutputSize(renderer, &output_w, &output_h) == 0) { - SDL_GetWindowSize(renderer->window, &window_w, &window_h); - renderer->dpi_scale.x = (float)window_w / output_w; - renderer->dpi_scale.y = (float)window_h / output_h; - } - } - - if (renderer->logical_w) { -#if defined(__ANDROID__) - /* Don't immediatly flush because the app may be in - * background, and the egl context shouldn't be used. */ - SDL_bool flush_viewport_cmd = SDL_FALSE; -#else - SDL_bool flush_viewport_cmd = SDL_TRUE; -#endif - UpdateLogicalSize(renderer, flush_viewport_cmd); - } else { - /* Window was resized, reset viewport */ - int w, h; - - if (renderer->GetOutputSize) { - renderer->GetOutputSize(renderer, &w, &h); - } else { - SDL_GetWindowSize(renderer->window, &w, &h); - } - - renderer->viewport.x = (double)0; - renderer->viewport.y = (double)0; - renderer->viewport.w = (double)w; - renderer->viewport.h = (double)h; - QueueCmdSetViewport(renderer); -#if defined(__ANDROID__) - /* Don't immediatly flush because the app may be in - * background, and the egl context shouldn't be used. */ -#else - FlushRenderCommandsIfNotBatching(renderer); -#endif - } - - if (saved_target) { - SDL_SetRenderTarget(renderer, saved_target); - } + UpdateMainViewDimensions(renderer); + UpdateLogicalPresentation(renderer); } else if (event->type == SDL_EVENT_WINDOW_HIDDEN) { renderer->hidden = SDL_TRUE; } else if (event->type == SDL_EVENT_WINDOW_SHOWN) { @@ -752,110 +720,6 @@ static int SDLCALL SDL_RendererEventWatch(void *userdata, SDL_Event *event) } } } - } else if (event->type == SDL_EVENT_MOUSE_MOTION) { - SDL_Window *window = SDL_GetWindowFromID(event->motion.windowID); - if (window == renderer->window) { - int logical_w, logical_h; - SDL_DRect viewport; - SDL_FPoint scale; - GetWindowViewportValues(renderer, &logical_w, &logical_h, &viewport, &scale); - if (logical_w) { - event->motion.x -= (float)(viewport.x * renderer->dpi_scale.x); - event->motion.y -= (float)(viewport.y * renderer->dpi_scale.y); - event->motion.x /= (scale.x * renderer->dpi_scale.x); - event->motion.y /= (scale.y * renderer->dpi_scale.y); - if (event->motion.xrel != 0.0f && renderer->relative_scaling) { - event->motion.xrel /= (scale.x * renderer->dpi_scale.x); - } - if (event->motion.yrel != 0.0f && renderer->relative_scaling) { - event->motion.yrel /= (scale.y * renderer->dpi_scale.y); - } - } - } - } else if (event->type == SDL_EVENT_MOUSE_BUTTON_DOWN || - event->type == SDL_EVENT_MOUSE_BUTTON_UP) { - SDL_Window *window = SDL_GetWindowFromID(event->button.windowID); - if (window == renderer->window) { - int logical_w, logical_h; - SDL_DRect viewport; - SDL_FPoint scale; - GetWindowViewportValues(renderer, &logical_w, &logical_h, &viewport, &scale); - if (logical_w) { - event->button.x -= (float)(viewport.x * renderer->dpi_scale.x); - event->button.y -= (float)(viewport.y * renderer->dpi_scale.y); - event->button.x /= (scale.x * renderer->dpi_scale.x); - event->button.y /= (scale.y * renderer->dpi_scale.y); - } - } - } else if (event->type == SDL_EVENT_MOUSE_WHEEL) { - SDL_Window *window = SDL_GetWindowFromID(event->button.windowID); - if (window == renderer->window) { - int logical_w, logical_h; - SDL_DRect viewport; - SDL_FPoint scale; - GetWindowViewportValues(renderer, &logical_w, &logical_h, &viewport, &scale); - if (logical_w) { - event->wheel.mouseX -= (float)(viewport.x * renderer->dpi_scale.x); - event->wheel.mouseY -= (float)(viewport.y * renderer->dpi_scale.y); - event->wheel.mouseX /= (scale.x * renderer->dpi_scale.x); - event->wheel.mouseY /= (scale.y * renderer->dpi_scale.y); - } - } - } else if (event->type == SDL_EVENT_FINGER_DOWN || - event->type == SDL_EVENT_FINGER_UP || - event->type == SDL_EVENT_FINGER_MOTION) { - int logical_w, logical_h; - float physical_w, physical_h; - SDL_DRect viewport; - SDL_FPoint scale; - GetWindowViewportValues(renderer, &logical_w, &logical_h, &viewport, &scale); - - /* !!! FIXME: we probably should drop events that are outside of the - !!! FIXME: viewport, but we can't do that from an event watcher, - !!! FIXME: and we would have to track if a touch happened outside - !!! FIXME: the viewport and then slid into it to insert extra - !!! FIXME: events, which is a mess, so for now we just clamp these - !!! FIXME: events to the edge. */ - - if (renderer->GetOutputSize) { - int w, h; - renderer->GetOutputSize(renderer, &w, &h); - physical_w = (float)w; - physical_h = (float)h; - } else { - int w, h; - SDL_GetWindowSize(renderer->window, &w, &h); - physical_w = ((float)w) * renderer->dpi_scale.x; - physical_h = ((float)h) * renderer->dpi_scale.y; - } - - if (physical_w == 0.0f) { /* nowhere for the touch to go, avoid division by zero and put it dead center. */ - event->tfinger.x = 0.5f; - } else { - const float normalized_viewport_x = ((float)viewport.x) / physical_w; - const float normalized_viewport_w = ((float)viewport.w) / physical_w; - if (event->tfinger.x <= normalized_viewport_x) { - event->tfinger.x = 0.0f; /* to the left of the viewport, clamp to the edge. */ - } else if (event->tfinger.x >= (normalized_viewport_x + normalized_viewport_w)) { - event->tfinger.x = 1.0f; /* to the right of the viewport, clamp to the edge. */ - } else { - event->tfinger.x = (event->tfinger.x - normalized_viewport_x) / normalized_viewport_w; - } - } - - if (physical_h == 0.0f) { /* nowhere for the touch to go, avoid division by zero and put it dead center. */ - event->tfinger.y = 0.5f; - } else { - const float normalized_viewport_y = ((float)viewport.y) / physical_h; - const float normalized_viewport_h = ((float)viewport.h) / physical_h; - if (event->tfinger.y <= normalized_viewport_y) { - event->tfinger.y = 0.0f; /* to the left of the viewport, clamp to the edge. */ - } else if (event->tfinger.y >= (normalized_viewport_y + normalized_viewport_h)) { - event->tfinger.y = 1.0f; /* to the right of the viewport, clamp to the edge. */ - } else { - event->tfinger.y = (event->tfinger.y - normalized_viewport_y) / normalized_viewport_h; - } - } } return 0; @@ -934,10 +798,10 @@ static void SDL_CalculateSimulatedVSyncInterval(SDL_Renderer *renderer, SDL_Wind den = (int)(100 * refresh_rate); renderer->simulate_vsync_interval_ns = (SDL_NS_PER_SECOND * num) / den; } + #endif /* !SDL_RENDER_DISABLED */ -SDL_Renderer * -SDL_CreateRenderer(SDL_Window *window, const char *name, Uint32 flags) +SDL_Renderer *SDL_CreateRenderer(SDL_Window *window, const char *name, Uint32 flags) { #if !SDL_RENDER_DISABLED SDL_Renderer *renderer = NULL; @@ -1027,10 +891,14 @@ SDL_CreateRenderer(SDL_Window *window, const char *name, Uint32 flags) renderer->magic = &renderer_magic; renderer->window = window; renderer->target_mutex = SDL_CreateMutex(); - renderer->scale.x = 1.0f; - renderer->scale.y = 1.0f; + renderer->main_view.viewport.w = -1; + renderer->main_view.viewport.h = -1; + renderer->main_view.scale.x = 1.0f; + renderer->main_view.scale.y = 1.0f; + renderer->view = &renderer->main_view; renderer->dpi_scale.x = 1.0f; renderer->dpi_scale.y = 1.0f; + UpdateMainViewDimensions(renderer); /* Default value, if not specified by the renderer back-end */ if (renderer->rect_index_order[0] == 0 && renderer->rect_index_order[1] == 0) { @@ -1045,18 +913,6 @@ SDL_CreateRenderer(SDL_Window *window, const char *name, Uint32 flags) /* new textures start at zero, so we start at 1 so first render doesn't flush by accident. */ renderer->render_command_generation = 1; - if (renderer->GetOutputSize) { - int window_w, window_h; - int output_w, output_h; - if (renderer->GetOutputSize(renderer, &output_w, &output_h) == 0) { - SDL_GetWindowSize(renderer->window, &window_w, &window_h); - renderer->dpi_scale.x = (float)window_w / output_w; - renderer->dpi_scale.y = (float)window_h / output_h; - } - } - - renderer->relative_scaling = SDL_GetHintBoolean(SDL_HINT_MOUSE_RELATIVE_SCALING, SDL_TRUE); - renderer->line_method = SDL_GetRenderLineMethod(); if (SDL_GetWindowFlags(window) & (SDL_WINDOW_HIDDEN | SDL_WINDOW_MINIMIZED)) { @@ -1069,6 +925,8 @@ SDL_CreateRenderer(SDL_Window *window, const char *name, Uint32 flags) SDL_SetRenderViewport(renderer, NULL); + SDL_SetRenderLogicalPresentation(renderer, 0, 0, SDL_LOGICAL_PRESENTATION_MATCH, SDL_ScaleModeLinear); + SDL_AddEventWatch(SDL_RendererEventWatch, renderer); SDL_LogInfo(SDL_LOG_CATEGORY_RENDER, @@ -1092,8 +950,7 @@ error: #endif } -SDL_Renderer * -SDL_CreateSoftwareRenderer(SDL_Surface *surface) +SDL_Renderer *SDL_CreateSoftwareRenderer(SDL_Surface *surface) { #if !SDL_RENDER_DISABLED && SDL_VIDEO_RENDER_SW SDL_Renderer *renderer; @@ -1104,8 +961,15 @@ SDL_CreateSoftwareRenderer(SDL_Surface *surface) VerifyDrawQueueFunctions(renderer); renderer->magic = &renderer_magic; renderer->target_mutex = SDL_CreateMutex(); - renderer->scale.x = 1.0f; - renderer->scale.y = 1.0f; + renderer->main_view.pixel_w = surface->w; + renderer->main_view.pixel_h = surface->h; + renderer->main_view.viewport.w = -1; + renderer->main_view.viewport.h = -1; + renderer->main_view.scale.x = 1.0f; + renderer->main_view.scale.y = 1.0f; + renderer->view = &renderer->main_view; + renderer->dpi_scale.x = 1.0f; + renderer->dpi_scale.y = 1.0f; /* new textures start at zero, so we start at 1 so first render doesn't flush by accident. */ renderer->render_command_generation = 1; @@ -1122,14 +986,12 @@ SDL_CreateSoftwareRenderer(SDL_Surface *surface) #endif /* !SDL_RENDER_DISABLED */ } -SDL_Renderer * -SDL_GetRenderer(SDL_Window *window) +SDL_Renderer *SDL_GetRenderer(SDL_Window *window) { return (SDL_Renderer *)SDL_GetWindowData(window, SDL_WINDOWRENDERDATA); } -SDL_Window * -SDL_GetRenderWindow(SDL_Renderer *renderer) +SDL_Window *SDL_GetRenderWindow(SDL_Renderer *renderer) { CHECK_RENDERER_MAGIC(renderer, NULL); return renderer->window; @@ -1143,16 +1005,29 @@ int SDL_GetRendererInfo(SDL_Renderer *renderer, SDL_RendererInfo *info) return 0; } -int SDL_GetRendererOutputSize(SDL_Renderer *renderer, int *w, int *h) +int SDL_GetRenderWindowSize(SDL_Renderer *renderer, int *w, int *h) { CHECK_RENDERER_MAGIC(renderer, -1); - if (renderer->target) { - return SDL_QueryTexture(renderer->target, NULL, NULL, w, h); + if (renderer->window) { + /*return */SDL_GetWindowSize(renderer->window, w, h); + return 0; } else if (renderer->GetOutputSize) { return renderer->GetOutputSize(renderer, w, h); + } else { + SDL_assert(0 && "This should never happen"); + return SDL_SetError("Renderer doesn't support querying output size"); + } +} + +int SDL_GetRenderOutputSize(SDL_Renderer *renderer, int *w, int *h) +{ + CHECK_RENDERER_MAGIC(renderer, -1); + + if (renderer->GetOutputSize) { + return renderer->GetOutputSize(renderer, w, h); } else if (renderer->window) { - SDL_GetWindowSize(renderer->window, w, h); + SDL_GetWindowSizeInPixels(renderer->window, w, h); return 0; } else { SDL_assert(0 && "This should never happen"); @@ -1160,6 +1035,19 @@ int SDL_GetRendererOutputSize(SDL_Renderer *renderer, int *w, int *h) } } +int SDL_GetCurrentRenderOutputSize(SDL_Renderer *renderer, int *w, int *h) +{ + CHECK_RENDERER_MAGIC(renderer, -1); + + if (w) { + *w = renderer->view->pixel_w; + } + if (h) { + *h = renderer->view->pixel_h; + } + return 0; +} + static SDL_bool IsSupportedBlendMode(SDL_Renderer *renderer, SDL_BlendMode blendMode) { switch (blendMode) { @@ -1228,8 +1116,7 @@ static SDL_ScaleMode SDL_GetScaleMode(void) } } -SDL_Texture * -SDL_CreateTexture(SDL_Renderer *renderer, Uint32 format, int access, int w, int h) +SDL_Texture *SDL_CreateTexture(SDL_Renderer *renderer, Uint32 format, int access, int w, int h) { SDL_Texture *texture; SDL_bool texture_is_fourcc_and_target; @@ -1273,6 +1160,12 @@ SDL_CreateTexture(SDL_Renderer *renderer, Uint32 format, int access, int w, int texture->color.b = 255; texture->color.a = 255; texture->scaleMode = SDL_GetScaleMode(); + texture->view.pixel_w = w; + texture->view.pixel_h = h; + texture->view.viewport.w = -1; + texture->view.viewport.h = -1; + texture->view.scale.x = 1.0f; + texture->view.scale.y = 1.0f; texture->renderer = renderer; texture->next = renderer->textures; if (renderer->textures) { @@ -1339,8 +1232,7 @@ SDL_CreateTexture(SDL_Renderer *renderer, Uint32 format, int access, int w, int return texture; } -SDL_Texture * -SDL_CreateTextureFromSurface(SDL_Renderer *renderer, SDL_Surface *surface) +SDL_Texture *SDL_CreateTextureFromSurface(SDL_Renderer *renderer, SDL_Surface *surface) { const SDL_PixelFormat *fmt; SDL_bool needAlpha; @@ -1623,8 +1515,7 @@ int SDL_SetTextureUserData(SDL_Texture *texture, void *userdata) return 0; } -void * -SDL_GetTextureUserData(SDL_Texture *texture) +void *SDL_GetTextureUserData(SDL_Texture *texture) { CHECK_TEXTURE_MAGIC(texture, NULL); @@ -2145,21 +2036,8 @@ void SDL_UnlockTexture(SDL_Texture *texture) texture->locked_surface = NULL; } -SDL_bool -SDL_RenderTargetSupported(SDL_Renderer *renderer) +static int SDL_SetRenderTargetInternal(SDL_Renderer *renderer, SDL_Texture *texture) { - if (renderer == NULL || !renderer->SetRenderTarget) { - return SDL_FALSE; - } - return (renderer->info.flags & SDL_RENDERER_TARGETTEXTURE) != 0; -} - -int SDL_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture) -{ - if (!SDL_RenderTargetSupported(renderer)) { - return SDL_Unsupported(); - } - /* texture == NULL is valid and means reset the target to the window */ if (texture) { CHECK_TEXTURE_MAGIC(texture, -1); @@ -2184,42 +2062,18 @@ int SDL_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture) SDL_LockMutex(renderer->target_mutex); - if (texture && !renderer->target) { - /* Make a backup of the viewport */ - renderer->viewport_backup = renderer->viewport; - renderer->clip_rect_backup = renderer->clip_rect; - renderer->clipping_enabled_backup = renderer->clipping_enabled; - renderer->scale_backup = renderer->scale; - renderer->logical_w_backup = renderer->logical_w; - renderer->logical_h_backup = renderer->logical_h; - } renderer->target = texture; + if (texture) { + renderer->view = &texture->view; + } else { + renderer->view = &renderer->main_view; + } if (renderer->SetRenderTarget(renderer, texture) < 0) { SDL_UnlockMutex(renderer->target_mutex); return -1; } - if (texture) { - renderer->viewport.x = (double)0; - renderer->viewport.y = (double)0; - renderer->viewport.w = (double)texture->w; - renderer->viewport.h = (double)texture->h; - SDL_zero(renderer->clip_rect); - renderer->clipping_enabled = SDL_FALSE; - renderer->scale.x = 1.0f; - renderer->scale.y = 1.0f; - renderer->logical_w = texture->w; - renderer->logical_h = texture->h; - } else { - renderer->viewport = renderer->viewport_backup; - renderer->clip_rect = renderer->clip_rect_backup; - renderer->clipping_enabled = renderer->clipping_enabled_backup; - renderer->scale = renderer->scale_backup; - renderer->logical_w = renderer->logical_w_backup; - renderer->logical_h = renderer->logical_h_backup; - } - SDL_UnlockMutex(renderer->target_mutex); if (QueueCmdSetViewport(renderer) < 0) { @@ -2233,178 +2087,371 @@ int SDL_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture) return FlushRenderCommandsIfNotBatching(renderer); } -SDL_Texture * -SDL_GetRenderTarget(SDL_Renderer *renderer) +int SDL_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture) +{ + if (texture == NULL && renderer->logical_target) { + return SDL_SetRenderTargetInternal(renderer, renderer->logical_target); + } else { + return SDL_SetRenderTargetInternal(renderer, texture); + } +} + +SDL_Texture *SDL_GetRenderTarget(SDL_Renderer *renderer) { CHECK_RENDERER_MAGIC(renderer, NULL); - return renderer->target; + if (renderer->target == renderer->logical_target) { + return NULL; + } else { + return renderer->target; + } } -static int UpdateLogicalSize(SDL_Renderer *renderer, SDL_bool flush_viewport_cmd) +static int UpdateLogicalPresentation(SDL_Renderer *renderer) { - int w = 1, h = 1; - float want_aspect; - float real_aspect; + int logical_w = 1, logical_h = 1; + int output_w = renderer->main_view.pixel_w; + int output_h = renderer->main_view.pixel_h; + float want_aspect = 1.0f; + float real_aspect = 1.0f; float scale; - SDL_Rect viewport; - /* 0 is for letterbox, 1 is for overscan */ - int scale_policy = 0; - const char *hint; - if (!renderer->logical_w || !renderer->logical_h) { + if (renderer->logical_presentation_mode == SDL_LOGICAL_PRESENTATION_DISABLED) { + /* All done! */ return 0; } - if (SDL_GetRendererOutputSize(renderer, &w, &h) < 0) { - return -1; + + if (renderer->logical_presentation_mode == SDL_LOGICAL_PRESENTATION_MATCH) { + if (SDL_GetRenderWindowSize(renderer, &logical_w, &logical_h) < 0) { + goto error; + } + + if (renderer->logical_target) { + int existing_w, existing_h; + + if (SDL_QueryTexture(renderer->logical_target, NULL, NULL, &existing_w, &existing_h) < 0) { + goto error; + } + if (logical_w != existing_w || logical_h != existing_h) { + SDL_DestroyTexture(renderer->logical_target); + renderer->logical_target = NULL; + } + } + if (!renderer->logical_target) { + renderer->logical_target = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_UNKNOWN, SDL_TEXTUREACCESS_TARGET, logical_w, logical_h); + if (!renderer->logical_target) { + goto error; + } + SDL_SetTextureBlendMode(renderer->logical_target, SDL_BLENDMODE_NONE); + } + } else { + if (SDL_QueryTexture(renderer->logical_target, NULL, NULL, &logical_w, &logical_h) < 0) { + goto error; + } + + want_aspect = (float)logical_w / logical_h; + real_aspect = (float)output_w / output_h; } - hint = SDL_GetHint(SDL_HINT_RENDER_LOGICAL_SIZE_MODE); - if (hint && (*hint == '1' || SDL_strcasecmp(hint, "overscan") == 0)) { -#if SDL_VIDEO_RENDER_D3D - SDL_bool overscan_supported = SDL_TRUE; - /* Unfortunately, Direct3D 9 doesn't support negative viewport numbers - which the overscan implementation relies on. - */ - if (SDL_strcasecmp(SDL_GetCurrentVideoDriver(), "direct3d") == 0) { - overscan_supported = SDL_FALSE; - } - if (overscan_supported) { - scale_policy = 1; - } -#else - scale_policy = 1; -#endif - } + renderer->logical_src_rect.x = 0; + renderer->logical_src_rect.y = 0; + renderer->logical_src_rect.w = logical_w; + renderer->logical_src_rect.h = logical_h; - want_aspect = (float)renderer->logical_w / renderer->logical_h; - real_aspect = (float)w / h; - - /* Clear the scale because we're setting viewport in output coordinates */ - SDL_SetRenderScale(renderer, 1.0f, 1.0f); - - if (renderer->integer_scale) { + if (renderer->logical_presentation_mode == SDL_LOGICAL_PRESENTATION_INTEGER_SCALE) { if (want_aspect > real_aspect) { - scale = (float)(w / renderer->logical_w); /* This an integer division! */ + scale = (float)(output_w / logical_w); /* This an integer division! */ } else { - scale = (float)(h / renderer->logical_h); /* This an integer division! */ + scale = (float)(output_h / logical_h); /* This an integer division! */ } if (scale < 1.0f) { scale = 1.0f; } - viewport.w = (int)SDL_floor(renderer->logical_w * scale); - viewport.x = (w - viewport.w) / 2; - viewport.h = (int)SDL_floor(renderer->logical_h * scale); - viewport.y = (h - viewport.h) / 2; - } else if (SDL_fabs(want_aspect - real_aspect) < 0.0001) { - /* The aspect ratios are the same, just scale appropriately */ - scale = (float)w / renderer->logical_w; + renderer->logical_dst_rect.w = SDL_floorf(logical_w * scale); + renderer->logical_dst_rect.x = (output_w - renderer->logical_dst_rect.w) / 2.0f; + renderer->logical_dst_rect.h = SDL_floorf(logical_h * scale); + renderer->logical_dst_rect.y = (output_h - renderer->logical_dst_rect.h) / 2.0f; + + } else if (renderer->logical_presentation_mode == SDL_LOGICAL_PRESENTATION_MATCH || + renderer->logical_presentation_mode == SDL_LOGICAL_PRESENTATION_STRETCH || + SDL_fabsf(want_aspect - real_aspect) < 0.0001f) { + renderer->logical_dst_rect.x = 0.0f; + renderer->logical_dst_rect.y = 0.0f; + renderer->logical_dst_rect.w = (float)output_w; + renderer->logical_dst_rect.h = (float)output_h; - SDL_zero(viewport); - SDL_GetRendererOutputSize(renderer, &viewport.w, &viewport.h); } else if (want_aspect > real_aspect) { - if (scale_policy == 1) { - /* We want a wider aspect ratio than is available - - zoom so logical height matches the real height - and the width will grow off the screen - */ - scale = (float)h / renderer->logical_h; - viewport.y = 0; - viewport.h = h; - viewport.w = (int)SDL_floor(renderer->logical_w * scale); - viewport.x = (w - viewport.w) / 2; - } else { + if (renderer->logical_presentation_mode == SDL_LOGICAL_PRESENTATION_LETTERBOX) { /* We want a wider aspect ratio than is available - letterbox it */ - scale = (float)w / renderer->logical_w; - viewport.x = 0; - viewport.w = w; - viewport.h = (int)SDL_floor(renderer->logical_h * scale); - viewport.y = (h - viewport.h) / 2; + scale = (float)output_w / logical_w; + renderer->logical_dst_rect.x = 0.0f; + renderer->logical_dst_rect.w = (float)output_w; + renderer->logical_dst_rect.h = SDL_floorf(logical_h * scale); + renderer->logical_dst_rect.y = (output_h - renderer->logical_dst_rect.h) / 2.0f; + } else { /* renderer->logical_presentation_mode == SDL_LOGICAL_PRESENTATION_OVERSCAN */ + /* We want a wider aspect ratio than is available - + zoom so logical height matches the real height + and the width will grow off the screen + */ + scale = (float)output_h / logical_h; + renderer->logical_dst_rect.y = 0.0f; + renderer->logical_dst_rect.h = (float)output_h; + renderer->logical_dst_rect.w = SDL_floorf(logical_w * scale); + renderer->logical_dst_rect.x = (output_w - renderer->logical_dst_rect.w) / 2.0f; } } else { - if (scale_policy == 1) { - /* We want a narrower aspect ratio than is available - - zoom so logical width matches the real width - and the height will grow off the screen - */ - scale = (float)w / renderer->logical_w; - viewport.x = 0; - viewport.w = w; - viewport.h = (int)SDL_floor(renderer->logical_h * scale); - viewport.y = (h - viewport.h) / 2; - } else { + if (renderer->logical_presentation_mode == SDL_LOGICAL_PRESENTATION_LETTERBOX) { /* We want a narrower aspect ratio than is available - use side-bars */ - scale = (float)h / renderer->logical_h; - viewport.y = 0; - viewport.h = h; - viewport.w = (int)SDL_floor(renderer->logical_w * scale); - viewport.x = (w - viewport.w) / 2; + scale = (float)output_h / logical_h; + renderer->logical_dst_rect.y = 0.0f; + renderer->logical_dst_rect.h = (float)output_h; + renderer->logical_dst_rect.w = SDL_floorf(logical_w * scale); + renderer->logical_dst_rect.x = (output_w - renderer->logical_dst_rect.w) / 2.0f; + } else { /* renderer->logical_presentation_mode == SDL_LOGICAL_PRESENTATION_OVERSCAN */ + /* We want a narrower aspect ratio than is available - + zoom so logical width matches the real width + and the height will grow off the screen + */ + scale = (float)output_w / logical_w; + renderer->logical_dst_rect.x = 0.0f; + renderer->logical_dst_rect.w = (float)output_w; + renderer->logical_dst_rect.h = SDL_floorf(logical_h * scale); + renderer->logical_dst_rect.y = (output_h - renderer->logical_dst_rect.h) / 2.0f; } } - /* Set the new viewport */ - renderer->viewport.x = (double)viewport.x * renderer->scale.x; - renderer->viewport.y = (double)viewport.y * renderer->scale.y; - renderer->viewport.w = (double)viewport.w * renderer->scale.x; - renderer->viewport.h = (double)viewport.h * renderer->scale.y; - QueueCmdSetViewport(renderer); - if (flush_viewport_cmd) { - FlushRenderCommandsIfNotBatching(renderer); + SDL_SetTextureScaleMode(renderer->logical_target, renderer->logical_scale_mode); + + if (!renderer->target) { + SDL_SetRenderTarget(renderer, renderer->logical_target); } - /* Set the new scale */ - SDL_SetRenderScale(renderer, scale, scale); + return 0; +error: + SDL_SetRenderLogicalPresentation(renderer, 0, 0, SDL_LOGICAL_PRESENTATION_DISABLED, SDL_ScaleModeNearest); + return -1; +} + +int SDL_SetRenderLogicalPresentation(SDL_Renderer *renderer, int w, int h, SDL_RendererLogicalPresentation mode, SDL_ScaleMode scale_mode) +{ + CHECK_RENDERER_MAGIC(renderer, -1); + + if (mode == SDL_LOGICAL_PRESENTATION_DISABLED) { + if (renderer->logical_target) { + SDL_DestroyTexture(renderer->logical_target); + renderer->logical_target = NULL; + } + } else if (mode != SDL_LOGICAL_PRESENTATION_MATCH) { + if (renderer->logical_target) { + int existing_w, existing_h; + + if (SDL_QueryTexture(renderer->logical_target, NULL, NULL, &existing_w, &existing_h) < 0) { + goto error; + } + if (w != existing_w || h != existing_h) { + SDL_DestroyTexture(renderer->logical_target); + renderer->logical_target = NULL; + } + } + if (!renderer->logical_target) { + renderer->logical_target = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_UNKNOWN, SDL_TEXTUREACCESS_TARGET, w, h); + if (!renderer->logical_target) { + goto error; + } + SDL_SetTextureBlendMode(renderer->logical_target, SDL_BLENDMODE_NONE); + } + } + + renderer->logical_presentation_mode = mode; + renderer->logical_scale_mode = scale_mode; + + return UpdateLogicalPresentation(renderer); + +error: + SDL_SetRenderLogicalPresentation(renderer, 0, 0, SDL_LOGICAL_PRESENTATION_DISABLED, SDL_ScaleModeNearest); + return -1; +} + +int SDL_GetRenderLogicalPresentation(SDL_Renderer *renderer, int *w, int *h, SDL_RendererLogicalPresentation *mode, SDL_ScaleMode *scale_mode) +{ + CHECK_RENDERER_MAGIC(renderer, -1); + + if (renderer->logical_target) { + if (SDL_QueryTexture(renderer->logical_target, NULL, NULL, w, h) < 0) { + return -1; + } + } else { + if (w) { + *w = 0; + } + if (h) { + *h = 0; + } + } + + if (mode) { + *mode = renderer->logical_presentation_mode; + } + if (scale_mode) { + *scale_mode = renderer->logical_scale_mode; + } return 0; } -int SDL_SetRenderLogicalSize(SDL_Renderer *renderer, int w, int h) +int SDL_RenderCoordinatesFromWindow(SDL_Renderer *renderer, float window_x, float window_y, float *x, float *y) +{ + SDL_RenderViewState *view; + float render_x, render_y; + + CHECK_RENDERER_MAGIC(renderer, -1); + + /* Convert from window coordinates to pixels within the window */ + render_x = window_x * renderer->dpi_scale.x; + render_y = window_y * renderer->dpi_scale.y; + + /* Convert from pixels within the window to pixels within the view */ + if (renderer->logical_target) { + const SDL_Rect *src = &renderer->logical_src_rect; + const SDL_FRect *dst = &renderer->logical_dst_rect; + render_x = ((render_x - dst->x) * src->w) / dst->w; + render_y = ((render_y - dst->y) * src->h) / dst->h; + } + + /* Convert from pixels within the view to render coordinates */ + if (renderer->logical_target) { + view = &renderer->logical_target->view; + } else { + view = &renderer->main_view; + } + render_x = (render_x / view->scale.x) - view->viewport.x; + render_y = (render_y / view->scale.y) - view->viewport.y; + + if (x) { + *x = render_x; + } + if (y) { + *y = render_y; + } + return 0; +} + +int SDL_RenderCoordinatesToWindow(SDL_Renderer *renderer, float x, float y, float *window_x, float *window_y) +{ + SDL_RenderViewState *view; + + CHECK_RENDERER_MAGIC(renderer, -1); + + /* Convert from render coordinates to pixels within the view */ + if (renderer->logical_target) { + view = &renderer->logical_target->view; + } else { + view = &renderer->main_view; + } + x = (view->viewport.x + x) * view->scale.x; + y = (view->viewport.y + y) * view->scale.y; + + /* Convert from pixels within the view to pixels within the window */ + if (renderer->logical_target) { + const SDL_Rect *src = &renderer->logical_src_rect; + const SDL_FRect *dst = &renderer->logical_dst_rect; + x = dst->x + ((x * dst->w) / src->w); + y = dst->y + ((y * dst->h) / src->h); + } + + /* Convert from pixels within the window to window coordinates */ + x /= renderer->dpi_scale.x; + y /= renderer->dpi_scale.y; + + if (window_x) { + *window_x = x; + } + if (window_y) { + *window_y = y; + } + return 0; +} + +int SDL_ConvertEventToRenderCoordinates(SDL_Renderer *renderer, SDL_Event *event) { CHECK_RENDERER_MAGIC(renderer, -1); - if (!w || !h) { - /* Clear any previous logical resolution */ - renderer->logical_w = 0; - renderer->logical_h = 0; - SDL_SetRenderViewport(renderer, NULL); - SDL_SetRenderScale(renderer, 1.0f, 1.0f); - return 0; + if (event->type == SDL_EVENT_MOUSE_MOTION) { + SDL_Window *window = SDL_GetWindowFromID(event->motion.windowID); + if (window == renderer->window) { + SDL_RenderCoordinatesFromWindow(renderer, event->motion.x, event->motion.y, &event->motion.x, &event->motion.y); + + if (event->motion.xrel != 0.0f) { + SDL_RenderViewState *view; + + /* Convert from window coordinates to pixels within the window */ + float scale = renderer->dpi_scale.x; + + /* Convert from pixels within the window to pixels within the view */ + if (renderer->logical_target) { + const SDL_Rect *src = &renderer->logical_src_rect; + const SDL_FRect *dst = &renderer->logical_dst_rect; + scale = (scale * src->w) / dst->w; + } + + /* Convert from pixels within the view to render coordinates */ + if (renderer->logical_target) { + view = &renderer->logical_target->view; + } else { + view = &renderer->main_view; + } + scale = (scale / view->scale.x); + + event->motion.xrel *= scale; + } + if (event->motion.yrel != 0.0f) { + SDL_RenderViewState *view; + + /* Convert from window coordinates to pixels within the window */ + float scale = renderer->dpi_scale.y; + + /* Convert from pixels within the window to pixels within the view */ + if (renderer->logical_target) { + const SDL_Rect *src = &renderer->logical_src_rect; + const SDL_FRect *dst = &renderer->logical_dst_rect; + scale = (scale * src->h) / dst->h; + } + + /* Convert from pixels within the view to render coordinates */ + if (renderer->logical_target) { + view = &renderer->logical_target->view; + } else { + view = &renderer->main_view; + } + scale = (scale / view->scale.y); + + event->motion.yrel *= scale; + } + } + } else if (event->type == SDL_EVENT_MOUSE_BUTTON_DOWN || + event->type == SDL_EVENT_MOUSE_BUTTON_UP) { + SDL_Window *window = SDL_GetWindowFromID(event->button.windowID); + if (window == renderer->window) { + SDL_RenderCoordinatesFromWindow(renderer, event->button.x, event->button.y, &event->button.x, &event->button.y); + } + } else if (event->type == SDL_EVENT_MOUSE_WHEEL) { + SDL_Window *window = SDL_GetWindowFromID(event->wheel.windowID); + if (window == renderer->window) { + SDL_RenderCoordinatesFromWindow(renderer, event->wheel.mouseX, event->wheel.mouseY, &event->wheel.mouseX, &event->wheel.mouseY); + } + } else if (event->type == SDL_EVENT_FINGER_DOWN || + event->type == SDL_EVENT_FINGER_UP || + event->type == SDL_EVENT_FINGER_MOTION) { + /* FIXME: Are these events guaranteed to be window relative? */ + int w, h; + if (SDL_GetRenderWindowSize(renderer, &w, &h) < 0) { + return -1; + } + SDL_RenderCoordinatesFromWindow(renderer, event->tfinger.x * w, event->tfinger.y * h, &event->tfinger.x, &event->tfinger.y); } - - renderer->logical_w = w; - renderer->logical_h = h; - - return UpdateLogicalSize(renderer, SDL_TRUE); -} - -void SDL_GetRenderLogicalSize(SDL_Renderer *renderer, int *w, int *h) -{ - CHECK_RENDERER_MAGIC(renderer, ); - - if (w) { - *w = renderer->logical_w; - } - if (h) { - *h = renderer->logical_h; - } -} - -int SDL_SetRenderIntegerScale(SDL_Renderer *renderer, SDL_bool enable) -{ - CHECK_RENDERER_MAGIC(renderer, -1); - - renderer->integer_scale = enable; - - return UpdateLogicalSize(renderer, SDL_TRUE); -} - -SDL_bool SDL_GetRenderIntegerScale(SDL_Renderer *renderer) -{ - CHECK_RENDERER_MAGIC(renderer, SDL_FALSE); - - return renderer->integer_scale; + return 0; } int SDL_SetRenderViewport(SDL_Renderer *renderer, const SDL_Rect *rect) @@ -2413,44 +2460,55 @@ int SDL_SetRenderViewport(SDL_Renderer *renderer, const SDL_Rect *rect) CHECK_RENDERER_MAGIC(renderer, -1); if (rect) { - renderer->viewport.x = (double)rect->x * renderer->scale.x; - renderer->viewport.y = (double)rect->y * renderer->scale.y; - renderer->viewport.w = (double)rect->w * renderer->scale.x; - renderer->viewport.h = (double)rect->h * renderer->scale.y; + renderer->view->viewport.x = rect->x; + renderer->view->viewport.y = rect->y; + renderer->view->viewport.w = rect->w; + renderer->view->viewport.h = rect->h; } else { - int w, h; - if (SDL_GetRendererOutputSize(renderer, &w, &h) < 0) { - return -1; - } - renderer->viewport.x = 0.0; - renderer->viewport.y = 0.0; - /* NOLINTBEGIN(clang-analyzer-core.uninitialized.Assign): SDL_GetRendererOutputSize cannot fail */ - renderer->viewport.w = (double)w; - renderer->viewport.h = (double)h; - /* NOLINTEND(clang-analyzer-core.uninitialized.Assign) */ + renderer->view->viewport.x = 0; + renderer->view->viewport.y = 0; + renderer->view->viewport.w = -1; + renderer->view->viewport.h = -1; } retval = QueueCmdSetViewport(renderer); return retval < 0 ? retval : FlushRenderCommandsIfNotBatching(renderer); } -void SDL_GetRenderViewport(SDL_Renderer *renderer, SDL_Rect *rect) +int SDL_GetRenderViewport(SDL_Renderer *renderer, SDL_Rect *rect) { - CHECK_RENDERER_MAGIC(renderer, ); + CHECK_RENDERER_MAGIC(renderer, -1); if (rect) { - rect->x = (int)SDL_floor(renderer->viewport.x / renderer->scale.x); - rect->y = (int)SDL_floor(renderer->viewport.y / renderer->scale.y); - rect->w = (int)SDL_floor(renderer->viewport.w / renderer->scale.x); - rect->h = (int)SDL_floor(renderer->viewport.h / renderer->scale.y); + rect->x = renderer->view->viewport.x; + rect->y = renderer->view->viewport.y; + if (renderer->view->viewport.w >= 0) { + rect->w = renderer->view->viewport.w; + } else { + rect->w = (int)SDL_ceilf(renderer->view->pixel_w / renderer->view->scale.x); + } + if (renderer->view->viewport.h >= 0) { + rect->h = renderer->view->viewport.h; + } else { + rect->h = (int)SDL_ceilf(renderer->view->pixel_h / renderer->view->scale.y); + } } + return 0; } static void GetRenderViewportSize(SDL_Renderer *renderer, SDL_FRect *rect) { rect->x = 0.0f; rect->y = 0.0f; - rect->w = (float)(renderer->viewport.w / renderer->scale.x); - rect->h = (float)(renderer->viewport.h / renderer->scale.y); + if (renderer->view->viewport.w >= 0) { + rect->w = (float)renderer->view->viewport.w; + } else { + rect->w = renderer->view->pixel_w / renderer->view->scale.x; + } + if (renderer->view->viewport.h >= 0) { + rect->h = (float)renderer->view->viewport.h; + } else { + rect->h = renderer->view->pixel_h / renderer->view->scale.y; + } } int SDL_SetRenderClipRect(SDL_Renderer *renderer, const SDL_Rect *rect) @@ -2459,92 +2517,70 @@ int SDL_SetRenderClipRect(SDL_Renderer *renderer, const SDL_Rect *rect) CHECK_RENDERER_MAGIC(renderer, -1) if (rect && rect->w > 0 && rect->h > 0) { - renderer->clipping_enabled = SDL_TRUE; - renderer->clip_rect.x = (double)rect->x * renderer->scale.x; - renderer->clip_rect.y = (double)rect->y * renderer->scale.y; - renderer->clip_rect.w = (double)rect->w * renderer->scale.x; - renderer->clip_rect.h = (double)rect->h * renderer->scale.y; + renderer->view->clipping_enabled = SDL_TRUE; + renderer->view->clip_rect.x = rect->x; + renderer->view->clip_rect.y = rect->y; + renderer->view->clip_rect.w = rect->w; + renderer->view->clip_rect.h = rect->h; } else { - renderer->clipping_enabled = SDL_FALSE; - SDL_zero(renderer->clip_rect); + renderer->view->clipping_enabled = SDL_FALSE; + SDL_zero(renderer->view->clip_rect); } retval = QueueCmdSetClipRect(renderer); return retval < 0 ? retval : FlushRenderCommandsIfNotBatching(renderer); } -void SDL_GetRenderClipRect(SDL_Renderer *renderer, SDL_Rect *rect) +int SDL_GetRenderClipRect(SDL_Renderer *renderer, SDL_Rect *rect) { - CHECK_RENDERER_MAGIC(renderer, ) + CHECK_RENDERER_MAGIC(renderer, -1) if (rect) { - rect->x = (int)SDL_floor(renderer->clip_rect.x / renderer->scale.x); - rect->y = (int)SDL_floor(renderer->clip_rect.y / renderer->scale.y); - rect->w = (int)SDL_floor(renderer->clip_rect.w / renderer->scale.x); - rect->h = (int)SDL_floor(renderer->clip_rect.h / renderer->scale.y); + rect->x = renderer->view->clip_rect.x; + rect->y = renderer->view->clip_rect.y; + rect->w = renderer->view->clip_rect.w; + rect->h = renderer->view->clip_rect.h; } + return 0; } -SDL_bool -SDL_RenderClipEnabled(SDL_Renderer *renderer) +SDL_bool SDL_RenderClipEnabled(SDL_Renderer *renderer) { CHECK_RENDERER_MAGIC(renderer, SDL_FALSE) - return renderer->clipping_enabled; + return renderer->view->clipping_enabled; } int SDL_SetRenderScale(SDL_Renderer *renderer, float scaleX, float scaleY) { + int retval = 0; + CHECK_RENDERER_MAGIC(renderer, -1); - renderer->scale.x = scaleX; - renderer->scale.y = scaleY; - return 0; + if (renderer->view->scale.x == scaleX && + renderer->view->scale.y == scaleY) { + return 0; + } + + renderer->view->scale.x = scaleX; + renderer->view->scale.y = scaleY; + + /* The scale affects the existing viewport and clip rectangle */ + retval += QueueCmdSetViewport(renderer); + retval += QueueCmdSetClipRect(renderer); + return retval < 0 ? retval : FlushRenderCommandsIfNotBatching(renderer); } -void SDL_GetRenderScale(SDL_Renderer *renderer, float *scaleX, float *scaleY) +int SDL_GetRenderScale(SDL_Renderer *renderer, float *scaleX, float *scaleY) { - CHECK_RENDERER_MAGIC(renderer, ); + CHECK_RENDERER_MAGIC(renderer, -1); if (scaleX) { - *scaleX = renderer->scale.x; + *scaleX = renderer->view->scale.x; } if (scaleY) { - *scaleY = renderer->scale.y; - } -} - -void SDL_RenderWindowToLogical(SDL_Renderer *renderer, float windowX, float windowY, float *logicalX, float *logicalY) -{ - float window_physical_x, window_physical_y; - - CHECK_RENDERER_MAGIC(renderer, ); - - window_physical_x = (windowX / renderer->dpi_scale.x); - window_physical_y = (windowY / renderer->dpi_scale.y); - - if (logicalX) { - *logicalX = (float)((window_physical_x - renderer->viewport.x) / renderer->scale.x); - } - if (logicalY) { - *logicalY = (float)((window_physical_y - renderer->viewport.y) / renderer->scale.y); - } -} - -void SDL_RenderLogicalToWindow(SDL_Renderer *renderer, float logicalX, float logicalY, float *windowX, float *windowY) -{ - float window_physical_x, window_physical_y; - - CHECK_RENDERER_MAGIC(renderer, ); - - window_physical_x = (float)((logicalX * renderer->scale.x) + renderer->viewport.x); - window_physical_y = (float)((logicalY * renderer->scale.y) + renderer->viewport.y); - - if (windowX) { - *windowX = (window_physical_x * renderer->dpi_scale.x); - } - if (windowY) { - *windowY = (window_physical_y * renderer->dpi_scale.y); + *scaleY = renderer->view->scale.y; } + return 0; } int SDL_SetRenderDrawColor(SDL_Renderer *renderer, Uint8 r, Uint8 g, Uint8 b, Uint8 a) @@ -2629,10 +2665,10 @@ static int RenderPointsWithRects(SDL_Renderer *renderer, const SDL_FPoint *fpoin } for (i = 0; i < count; ++i) { - frects[i].x = fpoints[i].x * renderer->scale.x; - frects[i].y = fpoints[i].y * renderer->scale.y; - frects[i].w = renderer->scale.x; - frects[i].h = renderer->scale.y; + frects[i].x = fpoints[i].x * renderer->view->scale.x; + frects[i].y = fpoints[i].y * renderer->view->scale.y; + frects[i].w = renderer->view->scale.x; + frects[i].h = renderer->view->scale.y; } retval = QueueCmdFillRects(renderer, frects, count); @@ -2662,7 +2698,7 @@ int SDL_RenderPoints(SDL_Renderer *renderer, const SDL_FPoint *points, int count } #endif - if (renderer->scale.x != 1.0f || renderer->scale.y != 1.0f) { + if (renderer->view->scale.x != 1.0f || renderer->view->scale.y != 1.0f) { retval = RenderPointsWithRects(renderer, points, count); } else { retval = QueueCmdDrawPoints(renderer, points, count); @@ -2748,7 +2784,7 @@ static int RenderLineBresenham(SDL_Renderer *renderer, int x1, int y1, int x2, i } } - if (renderer->scale.x != 1.0f || renderer->scale.y != 1.0f) { + if (renderer->view->scale.x != 1.0f || renderer->view->scale.y != 1.0f) { retval = RenderPointsWithRects(renderer, points, numpixels); } else { retval = QueueCmdDrawPoints(renderer, points, numpixels); @@ -2762,8 +2798,8 @@ static int RenderLineBresenham(SDL_Renderer *renderer, int x1, int y1, int x2, i static int RenderLinesWithRectsF(SDL_Renderer *renderer, const SDL_FPoint *points, const int count) { - const float scale_x = renderer->scale.x; - const float scale_y = renderer->scale.y; + const float scale_x = renderer->view->scale.x; + const float scale_y = renderer->view->scale.y; SDL_FRect *frect; SDL_FRect *frects; int i, nrects = 0; @@ -2858,8 +2894,8 @@ int SDL_RenderLines(SDL_Renderer *renderer, const SDL_FPoint *points, int count) } else if (renderer->line_method == SDL_RENDERLINEMETHOD_GEOMETRY) { SDL_bool isstack1; SDL_bool isstack2; - const float scale_x = renderer->scale.x; - const float scale_y = renderer->scale.y; + const float scale_x = renderer->view->scale.x; + const float scale_y = renderer->view->scale.y; float *xy = SDL_small_alloc(float, 4 * 2 * count, &isstack1); int *indices = SDL_small_alloc(int, (4) * 3 * (count - 1) + (2) * 3 * (count), &isstack2); @@ -2975,7 +3011,7 @@ int SDL_RenderLines(SDL_Renderer *renderer, const SDL_FPoint *points, int count) SDL_small_free(xy, isstack1); SDL_small_free(indices, isstack2); - } else if (renderer->scale.x != 1.0f || renderer->scale.y != 1.0f) { + } else if (renderer->view->scale.x != 1.0f || renderer->view->scale.y != 1.0f) { retval = RenderLinesWithRectsF(renderer, points, count); } else { retval = QueueCmdDrawLines(renderer, points, count); @@ -3044,7 +3080,7 @@ int SDL_RenderFillRect(SDL_Renderer *renderer, const SDL_FRect *rect) CHECK_RENDERER_MAGIC(renderer, -1); - /* If 'rect' == NULL, then outline the whole surface */ + /* If 'rect' == NULL, then fill the whole surface */ if (rect == NULL) { GetRenderViewportSize(renderer, &frect); rect = &frect; @@ -3080,10 +3116,10 @@ int SDL_RenderFillRects(SDL_Renderer *renderer, const SDL_FRect *rects, int coun return SDL_OutOfMemory(); } for (i = 0; i < count; ++i) { - frects[i].x = rects[i].x * renderer->scale.x; - frects[i].y = rects[i].y * renderer->scale.y; - frects[i].w = rects[i].w * renderer->scale.x; - frects[i].h = rects[i].h * renderer->scale.y; + frects[i].x = rects[i].x * renderer->view->scale.x; + frects[i].y = rects[i].y * renderer->view->scale.y; + frects[i].w = rects[i].w * renderer->view->scale.x; + frects[i].h = rects[i].h * renderer->view->scale.y; } retval = QueueCmdFillRects(renderer, frects, count); @@ -3184,13 +3220,14 @@ int SDL_RenderTexture(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Re xy, xy_stride, &texture->color, 0 /* color_stride */, uv, uv_stride, num_vertices, indices, num_indices, size_indices, - renderer->scale.x, renderer->scale.y); + renderer->view->scale.x, + renderer->view->scale.y); } else { - real_dstrect.x *= renderer->scale.x; - real_dstrect.y *= renderer->scale.y; - real_dstrect.w *= renderer->scale.x; - real_dstrect.h *= renderer->scale.y; + real_dstrect.x *= renderer->view->scale.x; + real_dstrect.y *= renderer->view->scale.y; + real_dstrect.w *= renderer->view->scale.x; + real_dstrect.h *= renderer->view->scale.y; retval = QueueCmdCopy(renderer, texture, &real_srcrect, &real_dstrect); } @@ -3341,10 +3378,13 @@ int SDL_RenderTextureRotated(SDL_Renderer *renderer, SDL_Texture *texture, xy, xy_stride, &texture->color, 0 /* color_stride */, uv, uv_stride, num_vertices, indices, num_indices, size_indices, - renderer->scale.x, renderer->scale.y); + renderer->view->scale.x, + renderer->view->scale.y); } else { - retval = QueueCmdCopyEx(renderer, texture, &real_srcrect, &real_dstrect, angle, &real_center, flip, renderer->scale.x, renderer->scale.y); + retval = QueueCmdCopyEx(renderer, texture, &real_srcrect, &real_dstrect, angle, &real_center, flip, + renderer->view->scale.x, + renderer->view->scale.y); } return retval < 0 ? retval : FlushRenderCommandsIfNotBatching(renderer); } @@ -3696,7 +3736,9 @@ static int SDLCALL SDL_SW_RenderGeometryRaw(SDL_Renderer *renderer, #endif retval = QueueCmdGeometry(renderer, texture, xy, xy_stride, color, color_stride, uv, uv_stride, - num_vertices, prev, 3, 4, renderer->scale.x, renderer->scale.y); + num_vertices, prev, 3, 4, + renderer->view->scale.x, + renderer->view->scale.y); if (retval < 0) { goto end; } else { @@ -3717,7 +3759,9 @@ static int SDLCALL SDL_SW_RenderGeometryRaw(SDL_Renderer *renderer, #endif retval = QueueCmdGeometry(renderer, texture, xy, xy_stride, color, color_stride, uv, uv_stride, - num_vertices, prev, 3, 4, renderer->scale.x, renderer->scale.y); + num_vertices, prev, 3, 4, + renderer->view->scale.x, + renderer->view->scale.y); if (retval < 0) { goto end; } else { @@ -3840,7 +3884,8 @@ int SDL_RenderGeometryRaw(SDL_Renderer *renderer, xy, xy_stride, color, color_stride, uv, uv_stride, num_vertices, indices, num_indices, size_indices, - renderer->scale.x, renderer->scale.y); + renderer->view->scale.x, + renderer->view->scale.y); return retval < 0 ? retval : FlushRenderCommandsIfNotBatching(renderer); } @@ -3865,10 +3910,8 @@ int SDL_RenderReadPixels(SDL_Renderer *renderer, const SDL_Rect *rect, Uint32 fo } } - real_rect.x = (int)SDL_floor(renderer->viewport.x); - real_rect.y = (int)SDL_floor(renderer->viewport.y); - real_rect.w = (int)SDL_floor(renderer->viewport.w); - real_rect.h = (int)SDL_floor(renderer->viewport.h); + GetRenderViewportInPixels(renderer, &real_rect); + if (rect) { if (!SDL_GetRectIntersection(rect, &real_rect, &real_rect)) { return 0; @@ -3913,12 +3956,66 @@ static void SDL_SimulateRenderVSync(SDL_Renderer *renderer) } } +static void SDL_RenderLogicalBorders(SDL_Renderer *renderer) +{ + const SDL_FRect *dst = &renderer->logical_dst_rect; + + if (dst->x > 0.0f || dst->y > 0.0f) { + SDL_BlendMode saved_blend_mode = renderer->blendMode; + SDL_Color saved_color = renderer->color; + + SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_NONE); + SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255); + + if (dst->x > 0.0f) { + SDL_FRect rect; + + rect.x = 0.0f; + rect.y = 0.0f; + rect.w = dst->x; + rect.h = (float)renderer->view->pixel_h; + SDL_RenderFillRect(renderer, &rect); + + rect.x = dst->x + dst->w; + rect.w = (float)renderer->view->pixel_w - rect.x; + SDL_RenderFillRect(renderer, &rect); + } + + if (dst->y > 0.0f) { + SDL_FRect rect; + + rect.x = 0.0f; + rect.y = 0.0f; + rect.w = (float)renderer->view->pixel_w; + rect.h = dst->y; + SDL_RenderFillRect(renderer, &rect); + + rect.y = dst->y + dst->h; + rect.h = (float)renderer->view->pixel_h - rect.y; + SDL_RenderFillRect(renderer, &rect); + } + + SDL_SetRenderDrawBlendMode(renderer, saved_blend_mode); + SDL_SetRenderDrawColor(renderer, saved_color.r, saved_color.g, saved_color.b, saved_color.a); + } +} + void SDL_RenderPresent(SDL_Renderer *renderer) { SDL_bool presented = SDL_TRUE; CHECK_RENDERER_MAGIC(renderer, ); + if (renderer->logical_target) { + SDL_SetRenderTargetInternal(renderer, NULL); + SDL_SetRenderViewport(renderer, NULL); + SDL_SetRenderClipRect(renderer, NULL); + SDL_SetRenderScale(renderer, 1.0f, 1.0f); + SDL_RenderLogicalBorders(renderer); + SDL_RenderTexture(renderer, renderer->logical_target, &renderer->logical_src_rect, &renderer->logical_dst_rect); + SDL_SetRenderTargetInternal(renderer, renderer->logical_target); + } + FlushRenderCommands(renderer); /* time to send everything to the GPU! */ #if DONT_DRAW_WHILE_HIDDEN @@ -3927,7 +4024,7 @@ void SDL_RenderPresent(SDL_Renderer *renderer) presented = SDL_FALSE; } else #endif - if (renderer->RenderPresent(renderer) < 0) { + if (renderer->RenderPresent(renderer) < 0) { presented = SDL_FALSE; } @@ -3945,7 +4042,7 @@ void SDL_DestroyTexture(SDL_Texture *texture) renderer = texture->renderer; if (texture == renderer->target) { - SDL_SetRenderTarget(renderer, NULL); /* implies command queue flush */ + SDL_SetRenderTargetInternal(renderer, NULL); /* implies command queue flush */ } else { FlushRenderCommandsIfTextureNeeded(texture); } @@ -4061,8 +4158,7 @@ int SDL_GL_UnbindTexture(SDL_Texture *texture) return SDL_Unsupported(); } -void * -SDL_GetRenderMetalLayer(SDL_Renderer *renderer) +void *SDL_GetRenderMetalLayer(SDL_Renderer *renderer) { CHECK_RENDERER_MAGIC(renderer, NULL); @@ -4073,8 +4169,7 @@ SDL_GetRenderMetalLayer(SDL_Renderer *renderer) return NULL; } -void * -SDL_GetRenderMetalCommandEncoder(SDL_Renderer *renderer) +void *SDL_GetRenderMetalCommandEncoder(SDL_Renderer *renderer) { CHECK_RENDERER_MAGIC(renderer, NULL); @@ -4125,54 +4220,47 @@ static SDL_BlendMode SDL_GetLongBlendMode(SDL_BlendMode blendMode) return blendMode; } -SDL_BlendMode -SDL_ComposeCustomBlendMode(SDL_BlendFactor srcColorFactor, SDL_BlendFactor dstColorFactor, - SDL_BlendOperation colorOperation, - SDL_BlendFactor srcAlphaFactor, SDL_BlendFactor dstAlphaFactor, - SDL_BlendOperation alphaOperation) +SDL_BlendMode SDL_ComposeCustomBlendMode(SDL_BlendFactor srcColorFactor, SDL_BlendFactor dstColorFactor, + SDL_BlendOperation colorOperation, + SDL_BlendFactor srcAlphaFactor, SDL_BlendFactor dstAlphaFactor, + SDL_BlendOperation alphaOperation) { SDL_BlendMode blendMode = SDL_COMPOSE_BLENDMODE(srcColorFactor, dstColorFactor, colorOperation, srcAlphaFactor, dstAlphaFactor, alphaOperation); return SDL_GetShortBlendMode(blendMode); } -SDL_BlendFactor -SDL_GetBlendModeSrcColorFactor(SDL_BlendMode blendMode) +SDL_BlendFactor SDL_GetBlendModeSrcColorFactor(SDL_BlendMode blendMode) { blendMode = SDL_GetLongBlendMode(blendMode); return (SDL_BlendFactor)(((Uint32)blendMode >> 4) & 0xF); } -SDL_BlendFactor -SDL_GetBlendModeDstColorFactor(SDL_BlendMode blendMode) +SDL_BlendFactor SDL_GetBlendModeDstColorFactor(SDL_BlendMode blendMode) { blendMode = SDL_GetLongBlendMode(blendMode); return (SDL_BlendFactor)(((Uint32)blendMode >> 8) & 0xF); } -SDL_BlendOperation -SDL_GetBlendModeColorOperation(SDL_BlendMode blendMode) +SDL_BlendOperation SDL_GetBlendModeColorOperation(SDL_BlendMode blendMode) { blendMode = SDL_GetLongBlendMode(blendMode); return (SDL_BlendOperation)(((Uint32)blendMode >> 0) & 0xF); } -SDL_BlendFactor -SDL_GetBlendModeSrcAlphaFactor(SDL_BlendMode blendMode) +SDL_BlendFactor SDL_GetBlendModeSrcAlphaFactor(SDL_BlendMode blendMode) { blendMode = SDL_GetLongBlendMode(blendMode); return (SDL_BlendFactor)(((Uint32)blendMode >> 20) & 0xF); } -SDL_BlendFactor -SDL_GetBlendModeDstAlphaFactor(SDL_BlendMode blendMode) +SDL_BlendFactor SDL_GetBlendModeDstAlphaFactor(SDL_BlendMode blendMode) { blendMode = SDL_GetLongBlendMode(blendMode); return (SDL_BlendFactor)(((Uint32)blendMode >> 24) & 0xF); } -SDL_BlendOperation -SDL_GetBlendModeAlphaOperation(SDL_BlendMode blendMode) +SDL_BlendOperation SDL_GetBlendModeAlphaOperation(SDL_BlendMode blendMode) { blendMode = SDL_GetLongBlendMode(blendMode); return (SDL_BlendOperation)(((Uint32)blendMode >> 16) & 0xF); diff --git a/src/render/SDL_sysrender.h b/src/render/SDL_sysrender.h index b9e30546e..c0886661d 100644 --- a/src/render/SDL_sysrender.h +++ b/src/render/SDL_sysrender.h @@ -45,18 +45,31 @@ typedef struct SDL_DRect typedef struct SDL_RenderDriver SDL_RenderDriver; +/* Rendering view state */ +typedef struct SDL_RenderViewState +{ + int pixel_w; + int pixel_h; + SDL_Rect viewport; + SDL_Rect clip_rect; + SDL_bool clipping_enabled; + SDL_FPoint scale; + +} SDL_RenderViewState; + /* Define the SDL texture structure */ struct SDL_Texture { const void *magic; - Uint32 format; /**< The pixel format of the texture */ - int access; /**< SDL_TextureAccess */ - int w; /**< The width of the texture */ - int h; /**< The height of the texture */ - int modMode; /**< The texture modulation mode */ - SDL_BlendMode blendMode; /**< The texture blend mode */ - SDL_ScaleMode scaleMode; /**< The texture scale mode */ - SDL_Color color; /**< Texture modulation values */ + Uint32 format; /**< The pixel format of the texture */ + int access; /**< SDL_TextureAccess */ + int w; /**< The width of the texture */ + int h; /**< The height of the texture */ + int modMode; /**< The texture modulation mode */ + SDL_BlendMode blendMode; /**< The texture blend mode */ + SDL_ScaleMode scaleMode; /**< The texture scale mode */ + SDL_Color color; /**< Texture modulation values */ + SDL_RenderViewState view; /**< Target texture view state */ SDL_Renderer *renderer; @@ -212,37 +225,19 @@ struct SDL_Renderer Uint64 simulate_vsync_interval_ns; Uint64 last_present; - /* The logical resolution for rendering */ - int logical_w; - int logical_h; - int logical_w_backup; - int logical_h_backup; + /* Support for logical output coordinates */ + SDL_Texture *logical_target; + SDL_RendererLogicalPresentation logical_presentation_mode; + SDL_ScaleMode logical_scale_mode; + SDL_Rect logical_src_rect; + SDL_FRect logical_dst_rect; - /* Whether or not to force the viewport to even integer intervals */ - SDL_bool integer_scale; + SDL_RenderViewState *view; + SDL_RenderViewState main_view; - /* The drawable area within the window */ - SDL_DRect viewport; - SDL_DRect viewport_backup; - - /* The clip rectangle within the window */ - SDL_DRect clip_rect; - SDL_DRect clip_rect_backup; - - /* Whether or not the clipping rectangle is used. */ - SDL_bool clipping_enabled; - SDL_bool clipping_enabled_backup; - - /* The render output coordinate scale */ - SDL_FPoint scale; - SDL_FPoint scale_backup; - - /* The pixel to point coordinate scale */ + /* The window pixel to point coordinate scale */ SDL_FPoint dpi_scale; - /* Whether or not to scale relative mouse motion */ - SDL_bool relative_scaling; - /* The method of drawing lines */ SDL_RenderLineMethod line_method; @@ -264,8 +259,8 @@ struct SDL_Renderer SDL_RenderCommand *render_commands_pool; Uint32 render_command_generation; Uint32 last_queued_color; - SDL_DRect last_queued_viewport; - SDL_DRect last_queued_cliprect; + SDL_Rect last_queued_viewport; + SDL_Rect last_queued_cliprect; SDL_bool last_queued_cliprect_enabled; SDL_bool color_queued; SDL_bool viewport_queued; diff --git a/src/render/direct3d/SDL_render_d3d.c b/src/render/direct3d/SDL_render_d3d.c index 64a59ebc6..7e7674848 100644 --- a/src/render/direct3d/SDL_render_d3d.c +++ b/src/render/direct3d/SDL_render_d3d.c @@ -337,12 +337,6 @@ static void D3D_WindowEvent(SDL_Renderer *renderer, const SDL_WindowEvent *event } } -static int D3D_GetOutputSize(SDL_Renderer *renderer, int *w, int *h) -{ - SDL_GetWindowSizeInPixels(renderer->window, w, h); - return 0; -} - static D3DBLEND GetBlendFunc(SDL_BlendFactor factor) { switch (factor) { @@ -1586,7 +1580,6 @@ D3D_CreateRenderer(SDL_Window *window, Uint32 flags) } renderer->WindowEvent = D3D_WindowEvent; - renderer->GetOutputSize = D3D_GetOutputSize; renderer->SupportsBlendMode = D3D_SupportsBlendMode; renderer->CreateTexture = D3D_CreateTexture; renderer->UpdateTexture = D3D_UpdateTexture; @@ -1609,7 +1602,7 @@ D3D_CreateRenderer(SDL_Window *window, Uint32 flags) renderer->DestroyRenderer = D3D_DestroyRenderer; renderer->SetVSync = D3D_SetVSync; renderer->info = D3D_RenderDriver.info; - renderer->info.flags = (SDL_RENDERER_ACCELERATED | SDL_RENDERER_TARGETTEXTURE); + renderer->info.flags = SDL_RENDERER_ACCELERATED; renderer->driverdata = data; SDL_GetWindowSizeInPixels(window, &w, &h); @@ -1727,7 +1720,7 @@ D3D_CreateRenderer(SDL_Window *window, Uint32 flags) SDL_RenderDriver D3D_RenderDriver = { D3D_CreateRenderer, { "direct3d", - (SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_TARGETTEXTURE), + (SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC), 1, { SDL_PIXELFORMAT_ARGB8888 }, 0, diff --git a/src/render/direct3d11/SDL_render_d3d11.c b/src/render/direct3d11/SDL_render_d3d11.c index 2e1121b96..fe77cfa94 100644 --- a/src/render/direct3d11/SDL_render_d3d11.c +++ b/src/render/direct3d11/SDL_render_d3d11.c @@ -1033,14 +1033,6 @@ static void D3D11_WindowEvent(SDL_Renderer *renderer, const SDL_WindowEvent *eve } } -#if !defined(__WINRT__) -static int D3D11_GetOutputSize(SDL_Renderer *renderer, int *w, int *h) -{ - SDL_GetWindowSizeInPixels(renderer->window, w, h); - return 0; -} -#endif - static SDL_bool D3D11_SupportsBlendMode(SDL_Renderer *renderer, SDL_BlendMode blendMode) { SDL_BlendFactor srcColorFactor = SDL_GetBlendModeSrcColorFactor(blendMode); @@ -2324,9 +2316,6 @@ D3D11_CreateRenderer(SDL_Window *window, Uint32 flags) data->identity = MatrixIdentity(); renderer->WindowEvent = D3D11_WindowEvent; -#if !defined(__WINRT__) - renderer->GetOutputSize = D3D11_GetOutputSize; -#endif renderer->SupportsBlendMode = D3D11_SupportsBlendMode; renderer->CreateTexture = D3D11_CreateTexture; renderer->UpdateTexture = D3D11_UpdateTexture; @@ -2349,7 +2338,7 @@ D3D11_CreateRenderer(SDL_Window *window, Uint32 flags) renderer->DestroyTexture = D3D11_DestroyTexture; renderer->DestroyRenderer = D3D11_DestroyRenderer; renderer->info = D3D11_RenderDriver.info; - renderer->info.flags = (SDL_RENDERER_ACCELERATED | SDL_RENDERER_TARGETTEXTURE); + renderer->info.flags = SDL_RENDERER_ACCELERATED; renderer->driverdata = data; #if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP @@ -2394,12 +2383,10 @@ SDL_RenderDriver D3D11_RenderDriver = { D3D11_CreateRenderer, { "direct3d11", - ( - SDL_RENDERER_ACCELERATED | - SDL_RENDERER_PRESENTVSYNC | - SDL_RENDERER_TARGETTEXTURE), /* flags. see SDL_RendererFlags */ - 6, /* num_texture_formats */ - { /* texture_formats */ + (SDL_RENDERER_ACCELERATED | + SDL_RENDERER_PRESENTVSYNC), /* flags. see SDL_RendererFlags */ + 6, /* num_texture_formats */ + { /* texture_formats */ SDL_PIXELFORMAT_ARGB8888, SDL_PIXELFORMAT_RGB888, SDL_PIXELFORMAT_YV12, diff --git a/src/render/direct3d12/SDL_render_d3d12.c b/src/render/direct3d12/SDL_render_d3d12.c index b681a7051..03df5a81e 100644 --- a/src/render/direct3d12/SDL_render_d3d12.c +++ b/src/render/direct3d12/SDL_render_d3d12.c @@ -502,12 +502,6 @@ static void D3D12_DestroyRenderer(SDL_Renderer *renderer) SDL_free(renderer); } -static int D3D12_GetOutputSize(SDL_Renderer *renderer, int *w, int *h) -{ - SDL_GetWindowSizeInPixels(renderer->window, w, h); - return 0; -} - static D3D12_BLEND GetBlendFunc(SDL_BlendFactor factor) { switch (factor) { @@ -2972,7 +2966,6 @@ 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; @@ -2995,7 +2988,7 @@ D3D12_CreateRenderer(SDL_Window *window, Uint32 flags) renderer->DestroyTexture = D3D12_DestroyTexture; renderer->DestroyRenderer = D3D12_DestroyRenderer; renderer->info = D3D12_RenderDriver.info; - renderer->info.flags = (SDL_RENDERER_ACCELERATED | SDL_RENDERER_TARGETTEXTURE); + renderer->info.flags = SDL_RENDERER_ACCELERATED; renderer->driverdata = data; if ((flags & SDL_RENDERER_PRESENTVSYNC)) { @@ -3025,12 +3018,10 @@ SDL_RenderDriver D3D12_RenderDriver = { D3D12_CreateRenderer, { "direct3d12", - ( - SDL_RENDERER_ACCELERATED | - SDL_RENDERER_PRESENTVSYNC | - SDL_RENDERER_TARGETTEXTURE), /* flags. see SDL_RendererFlags */ - 6, /* num_texture_formats */ - { /* texture_formats */ + (SDL_RENDERER_ACCELERATED | + SDL_RENDERER_PRESENTVSYNC), /* flags. see SDL_RendererFlags */ + 6, /* num_texture_formats */ + { /* texture_formats */ SDL_PIXELFORMAT_ARGB8888, SDL_PIXELFORMAT_RGB888, SDL_PIXELFORMAT_YV12, diff --git a/src/render/metal/SDL_render_metal.m b/src/render/metal/SDL_render_metal.m index d3f594fea..a9f778488 100644 --- a/src/render/metal/SDL_render_metal.m +++ b/src/render/metal/SDL_render_metal.m @@ -1911,7 +1911,7 @@ static SDL_Renderer *METAL_CreateRenderer(SDL_Window *window, Uint32 flags) renderer->GetMetalCommandEncoder = METAL_GetMetalCommandEncoder; renderer->info = METAL_RenderDriver.info; - renderer->info.flags = (SDL_RENDERER_ACCELERATED | SDL_RENDERER_TARGETTEXTURE); + renderer->info.flags = SDL_RENDERER_ACCELERATED; renderer->always_batch = SDL_TRUE; @@ -1972,7 +1972,7 @@ SDL_RenderDriver METAL_RenderDriver = { METAL_CreateRenderer, { "metal", - (SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_TARGETTEXTURE), + (SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC), 6, { SDL_PIXELFORMAT_ARGB8888, SDL_PIXELFORMAT_ABGR8888, diff --git a/src/render/opengl/SDL_render_gl.c b/src/render/opengl/SDL_render_gl.c index 4310710fe..05350627f 100644 --- a/src/render/opengl/SDL_render_gl.c +++ b/src/render/opengl/SDL_render_gl.c @@ -331,12 +331,6 @@ static void GL_WindowEvent(SDL_Renderer *renderer, const SDL_WindowEvent *event) } } -static int GL_GetOutputSize(SDL_Renderer *renderer, int *w, int *h) -{ - SDL_GetWindowSizeInPixels(renderer->window, w, h); - return 0; -} - static GLenum GetBlendFunc(SDL_BlendFactor factor) { switch (factor) { @@ -1440,7 +1434,7 @@ static int GL_RenderReadPixels(SDL_Renderer *renderer, const SDL_Rect *rect, return SDL_OutOfMemory(); } - SDL_GetRendererOutputSize(renderer, &w, &h); + SDL_GetCurrentRenderOutputSize(renderer, &w, &h); data->glPixelStorei(GL_PACK_ALIGNMENT, 1); data->glPixelStorei(GL_PACK_ROW_LENGTH, @@ -1749,7 +1743,6 @@ static SDL_Renderer *GL_CreateRenderer(SDL_Window *window, Uint32 flags) } renderer->WindowEvent = GL_WindowEvent; - renderer->GetOutputSize = GL_GetOutputSize; renderer->SupportsBlendMode = GL_SupportsBlendMode; renderer->CreateTexture = GL_CreateTexture; renderer->UpdateTexture = GL_UpdateTexture; @@ -1935,9 +1928,13 @@ static SDL_Renderer *GL_CreateRenderer(SDL_Window *window, Uint32 flags) SDL_GL_GetProcAddress("glBindFramebufferEXT"); data->glCheckFramebufferStatusEXT = (PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC) SDL_GL_GetProcAddress("glCheckFramebufferStatusEXT"); - renderer->info.flags |= SDL_RENDERER_TARGETTEXTURE; + } else { + SDL_SetError("Can't create render targets, GL_EXT_framebuffer_object not available"); + SDL_GL_DeleteContext(data->context); + SDL_free(renderer); + SDL_free(data); + goto error; } - data->framebuffers = NULL; /* Set up parameters for rendering */ data->glMatrixMode(GL_MODELVIEW); @@ -1972,7 +1969,7 @@ error: SDL_RenderDriver GL_RenderDriver = { GL_CreateRenderer, { "opengl", - (SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_TARGETTEXTURE), + (SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC), 4, { SDL_PIXELFORMAT_ARGB8888, SDL_PIXELFORMAT_ABGR8888, diff --git a/src/render/opengles2/SDL_render_gles2.c b/src/render/opengles2/SDL_render_gles2.c index 9a7e6daa4..144c2a624 100644 --- a/src/render/opengles2/SDL_render_gles2.c +++ b/src/render/opengles2/SDL_render_gles2.c @@ -311,12 +311,6 @@ static void GLES2_WindowEvent(SDL_Renderer *renderer, const SDL_WindowEvent *eve } } -static int GLES2_GetOutputSize(SDL_Renderer *renderer, int *w, int *h) -{ - SDL_GetWindowSizeInPixels(renderer->window, w, h); - return 0; -} - static GLenum GetBlendFunc(SDL_BlendFactor factor) { switch (factor) { @@ -1935,7 +1929,7 @@ static int GLES2_RenderReadPixels(SDL_Renderer *renderer, const SDL_Rect *rect, return SDL_OutOfMemory(); } - SDL_GetRendererOutputSize(renderer, &w, &h); + SDL_GetCurrentRenderOutputSize(renderer, &w, &h); data->glReadPixels(rect->x, renderer->target ? rect->y : (h - rect->y) - rect->h, rect->w, rect->h, GL_RGBA, GL_UNSIGNED_BYTE, temp_pixels); @@ -2109,7 +2103,7 @@ static SDL_Renderer *GLES2_CreateRenderer(SDL_Window *window, Uint32 flags) goto error; } renderer->info = GLES2_RenderDriver.info; - renderer->info.flags = (SDL_RENDERER_ACCELERATED | SDL_RENDERER_TARGETTEXTURE); + renderer->info.flags = SDL_RENDERER_ACCELERATED; renderer->driverdata = data; renderer->window = window; @@ -2190,7 +2184,6 @@ static SDL_Renderer *GLES2_CreateRenderer(SDL_Window *window, Uint32 flags) /* Populate the function pointers for the module */ renderer->WindowEvent = GLES2_WindowEvent; - renderer->GetOutputSize = GLES2_GetOutputSize; renderer->SupportsBlendMode = GLES2_SupportsBlendMode; renderer->CreateTexture = GLES2_CreateTexture; renderer->UpdateTexture = GLES2_UpdateTexture; @@ -2272,7 +2265,7 @@ error: SDL_RenderDriver GLES2_RenderDriver = { GLES2_CreateRenderer, { "opengles2", - (SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_TARGETTEXTURE), + (SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC), 4, { SDL_PIXELFORMAT_ARGB8888, SDL_PIXELFORMAT_ABGR8888, diff --git a/src/render/ps2/SDL_render_ps2.c b/src/render/ps2/SDL_render_ps2.c index 7dc019ccb..ca854fc05 100644 --- a/src/render/ps2/SDL_render_ps2.c +++ b/src/render/ps2/SDL_render_ps2.c @@ -665,7 +665,7 @@ SDL_RenderDriver PS2_RenderDriver = { .CreateRenderer = PS2_CreateRenderer, .info = { .name = "PS2 gsKit", - .flags = SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_TARGETTEXTURE, + .flags = (SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC), .num_texture_formats = 2, .texture_formats = { [0] = SDL_PIXELFORMAT_ABGR1555, diff --git a/src/render/psp/SDL_render_psp.c b/src/render/psp/SDL_render_psp.c index 1649e23ba..6d3761278 100644 --- a/src/render/psp/SDL_render_psp.c +++ b/src/render/psp/SDL_render_psp.c @@ -1333,7 +1333,7 @@ PSP_CreateRenderer(SDL_Window *window, Uint32 flags) renderer->DestroyRenderer = PSP_DestroyRenderer; renderer->SetVSync = PSP_SetVSync; renderer->info = PSP_RenderDriver.info; - renderer->info.flags = (SDL_RENDERER_ACCELERATED | SDL_RENDERER_TARGETTEXTURE); + renderer->info.flags = SDL_RENDERER_ACCELERATED; renderer->driverdata = data; renderer->window = window; @@ -1407,7 +1407,7 @@ SDL_RenderDriver PSP_RenderDriver = { .CreateRenderer = PSP_CreateRenderer, .info = { .name = "PSP", - .flags = SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_TARGETTEXTURE, + .flags = (SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC), .num_texture_formats = 4, .texture_formats = { [0] = SDL_PIXELFORMAT_BGR565, diff --git a/src/render/software/SDL_render_sw.c b/src/render/software/SDL_render_sw.c index fe9ad247f..50d99e1c0 100644 --- a/src/render/software/SDL_render_sw.c +++ b/src/render/software/SDL_render_sw.c @@ -1175,7 +1175,7 @@ static SDL_Renderer *SW_CreateRenderer(SDL_Window *window, Uint32 flags) SDL_RenderDriver SW_RenderDriver = { SW_CreateRenderer, { "software", - SDL_RENDERER_SOFTWARE | SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_TARGETTEXTURE, + (SDL_RENDERER_SOFTWARE | SDL_RENDERER_PRESENTVSYNC), 0, { /* formats filled in later */ SDL_PIXELFORMAT_UNKNOWN }, diff --git a/src/render/vitagxm/SDL_render_vita_gxm.c b/src/render/vitagxm/SDL_render_vita_gxm.c index e661e53f2..c267434f0 100644 --- a/src/render/vitagxm/SDL_render_vita_gxm.c +++ b/src/render/vitagxm/SDL_render_vita_gxm.c @@ -102,7 +102,7 @@ SDL_RenderDriver VITA_GXM_RenderDriver = { .CreateRenderer = VITA_GXM_CreateRenderer, .info = { .name = "VITA gxm", - .flags = SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_TARGETTEXTURE, + .flags = (SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC), .num_texture_formats = 8, .texture_formats = { [0] = SDL_PIXELFORMAT_ABGR8888, @@ -253,7 +253,7 @@ VITA_GXM_CreateRenderer(SDL_Window *window, Uint32 flags) renderer->SetVSync = VITA_GXM_SetVSync; renderer->info = VITA_GXM_RenderDriver.info; - renderer->info.flags = (SDL_RENDERER_ACCELERATED | SDL_RENDERER_TARGETTEXTURE); + renderer->info.flags = SDL_RENDERER_ACCELERATED; renderer->driverdata = data; renderer->window = window; @@ -1106,7 +1106,7 @@ static int VITA_GXM_RenderReadPixels(SDL_Renderer *renderer, const SDL_Rect *rec return SDL_OutOfMemory(); } - SDL_GetRendererOutputSize(renderer, &w, &h); + SDL_GetCurrentRenderOutputSize(renderer, &w, &h); read_pixels(rect->x, renderer->target ? rect->y : (h - rect->y) - rect->h, rect->w, rect->h, temp_pixels); diff --git a/src/test/SDL_test_common.c b/src/test/SDL_test_common.c index 726d823ea..e543bdb84 100644 --- a/src/test/SDL_test_common.c +++ b/src/test/SDL_test_common.c @@ -30,6 +30,8 @@ static const char *video_usage[] = { "[--fullscreen | --fullscreen-desktop | --windows N]", "[--title title]", "[--icon icon.bmp]", "[--center | --position X,Y]", "[--geometry WxH]", "[--min-geometry WxH]", "[--max-geometry WxH]", "[--logical WxH]", + "[--logical-presentation disabled|match|stretch|letterbox|overscan|integer_scale]", + "[--logical-scale-quality nearest|linear|best]", "[--scale N]", "[--depth N]", "[--refresh R]", "[--vsync]", "[--noframe]", "[--resizable]", "[--minimize]", "[--maximize]", "[--grab]", "[--keyboard-grab]", "[--hidden]", "[--input-focus]", "[--mouse-focus]", @@ -83,6 +85,8 @@ SDLTest_CommonCreateState(char **argv, Uint32 flags) state->window_y = SDL_WINDOWPOS_UNDEFINED; state->window_w = DEFAULT_WINDOW_WIDTH; state->window_h = DEFAULT_WINDOW_HEIGHT; + state->logical_presentation = SDL_LOGICAL_PRESENTATION_MATCH; + state->logical_scale_mode = SDL_ScaleModeLinear; state->num_windows = 1; state->audiospec.freq = 22050; state->audiospec.format = AUDIO_S16; @@ -399,6 +403,56 @@ int SDLTest_CommonArg(SDLTest_CommonState *state, int index) state->logical_h = SDL_atoi(h); return 2; } + if (SDL_strcasecmp(argv[index], "--logical-presentation") == 0) { + ++index; + if (!argv[index]) { + return -1; + } + if (SDL_strcasecmp(argv[index], "disabled") == 0) { + state->logical_presentation = SDL_LOGICAL_PRESENTATION_DISABLED; + return 2; + } + if (SDL_strcasecmp(argv[index], "match") == 0) { + state->logical_presentation = SDL_LOGICAL_PRESENTATION_MATCH; + return 2; + } + if (SDL_strcasecmp(argv[index], "stretch") == 0) { + state->logical_presentation = SDL_LOGICAL_PRESENTATION_STRETCH; + return 2; + } + if (SDL_strcasecmp(argv[index], "letterbox") == 0) { + state->logical_presentation = SDL_LOGICAL_PRESENTATION_LETTERBOX; + return 2; + } + if (SDL_strcasecmp(argv[index], "overscan") == 0) { + state->logical_presentation = SDL_LOGICAL_PRESENTATION_OVERSCAN; + return 2; + } + if (SDL_strcasecmp(argv[index], "integer_scale") == 0) { + state->logical_presentation = SDL_LOGICAL_PRESENTATION_INTEGER_SCALE; + return 2; + } + return -1; + } + if (SDL_strcasecmp(argv[index], "--logical-scale-quality") == 0) { + ++index; + if (!argv[index]) { + return -1; + } + if (SDL_strcasecmp(argv[index], "nearest") == 0) { + state->logical_scale_mode = SDL_ScaleModeNearest; + return 2; + } + if (SDL_strcasecmp(argv[index], "linear") == 0) { + state->logical_scale_mode = SDL_ScaleModeLinear; + return 2; + } + if (SDL_strcasecmp(argv[index], "best") == 0) { + state->logical_scale_mode = SDL_ScaleModeBest; + return 2; + } + return -1; + } if (SDL_strcasecmp(argv[index], "--scale") == 0) { ++index; if (!argv[index]) { @@ -803,9 +857,6 @@ static void SDLTest_PrintRendererFlag(char *text, size_t maxlen, Uint32 flag) case SDL_RENDERER_PRESENTVSYNC: SDL_snprintfcat(text, maxlen, "PresentVSync"); break; - case SDL_RENDERER_TARGETTEXTURE: - SDL_snprintfcat(text, maxlen, "TargetTexturesSupported"); - break; default: SDL_snprintfcat(text, maxlen, "0x%8.8x", flag); break; @@ -920,6 +971,51 @@ static void SDLTest_PrintPixelFormat(char *text, size_t maxlen, Uint32 format) } } +static void SDLTest_PrintLogicalPresentation(char *text, size_t maxlen, SDL_RendererLogicalPresentation logical_presentation) +{ + switch (logical_presentation) { + case SDL_LOGICAL_PRESENTATION_DISABLED: + SDL_snprintfcat(text, maxlen, "DISABLED"); + break; + case SDL_LOGICAL_PRESENTATION_MATCH: + SDL_snprintfcat(text, maxlen, "MATCH"); + break; + case SDL_LOGICAL_PRESENTATION_STRETCH: + SDL_snprintfcat(text, maxlen, "STRETCH"); + break; + case SDL_LOGICAL_PRESENTATION_LETTERBOX: + SDL_snprintfcat(text, maxlen, "LETTERBOX"); + break; + case SDL_LOGICAL_PRESENTATION_OVERSCAN: + SDL_snprintfcat(text, maxlen, "OVERSCAN"); + break; + case SDL_LOGICAL_PRESENTATION_INTEGER_SCALE: + SDL_snprintfcat(text, maxlen, "INTEGER_SCALE"); + break; + default: + SDL_snprintfcat(text, maxlen, "0x%8.8x", logical_presentation); + break; + } +} + +static void SDLTest_PrintScaleMode(char *text, size_t maxlen, SDL_ScaleMode scale_mode) +{ + switch (scale_mode) { + case SDL_ScaleModeNearest: + SDL_snprintfcat(text, maxlen, "NEAREST"); + break; + case SDL_ScaleModeLinear: + SDL_snprintfcat(text, maxlen, "LINEAR"); + break; + case SDL_ScaleModeBest: + SDL_snprintfcat(text, maxlen, "BEST"); + break; + default: + SDL_snprintfcat(text, maxlen, "0x%8.8x", scale_mode); + break; + } +} + static void SDLTest_PrintRenderer(SDL_RendererInfo *info) { int i, count; @@ -1298,9 +1394,15 @@ SDLTest_CommonInit(SDLTest_CommonState *state) SDL_GetError()); return SDL_FALSE; } - if (state->logical_w && state->logical_h) { - SDL_SetRenderLogicalSize(state->renderers[i], state->logical_w, state->logical_h); - } else if (state->scale != 0.) { + if (state->logical_w == 0 || state->logical_h == 0) { + state->logical_w = state->window_w; + state->logical_h = state->window_h; + } + if (SDL_SetRenderLogicalPresentation(state->renderers[i], state->logical_w, state->logical_h, state->logical_presentation, state->logical_scale_mode) < 0) { + SDL_Log("Couldn't set logical presentation: %s\n", SDL_GetError()); + return SDL_FALSE; + } + if (state->scale != 0.0f) { SDL_SetRenderScale(state->renderers[i], state->scale, state->scale); } if (state->verbose & VERBOSE_RENDER) { @@ -2204,6 +2306,8 @@ void SDLTest_CommonDrawWindowInfo(SDL_Renderer *renderer, SDL_Window *window, fl Uint32 flags; SDL_DisplayID windowDisplayID = SDL_GetDisplayForWindow(window); SDL_RendererInfo info; + SDL_RendererLogicalPresentation logical_presentation; + SDL_ScaleMode logical_scale_mode; /* Video */ @@ -2231,8 +2335,14 @@ void SDLTest_CommonDrawWindowInfo(SDL_Renderer *renderer, SDL_Window *window, fl textY += lineHeight; } - if (0 == SDL_GetRendererOutputSize(renderer, &w, &h)) { - (void)SDL_snprintf(text, sizeof text, "SDL_GetRendererOutputSize: %dx%d", w, h); + if (0 == SDL_GetRenderOutputSize(renderer, &w, &h)) { + (void)SDL_snprintf(text, sizeof text, "SDL_GetRenderOutputSize: %dx%d", w, h); + SDLTest_DrawString(renderer, 0.0f, textY, text); + textY += lineHeight; + } + + if (0 == SDL_GetCurrentRenderOutputSize(renderer, &w, &h)) { + (void)SDL_snprintf(text, sizeof text, "SDL_GetCurrentRenderOutputSize: %dx%d", w, h); SDLTest_DrawString(renderer, 0.0f, textY, text); textY += lineHeight; } @@ -2244,13 +2354,16 @@ void SDLTest_CommonDrawWindowInfo(SDL_Renderer *renderer, SDL_Window *window, fl textY += lineHeight; SDL_GetRenderScale(renderer, &scaleX, &scaleY); - (void)SDL_snprintf(text, sizeof text, "SDL_GetRenderScale: %f,%f", + (void)SDL_snprintf(text, sizeof text, "SDL_GetRenderScale: %g,%g", scaleX, scaleY); SDLTest_DrawString(renderer, 0.0f, textY, text); textY += lineHeight; - SDL_GetRenderLogicalSize(renderer, &w, &h); - (void)SDL_snprintf(text, sizeof text, "SDL_GetRenderLogicalSize: %dx%d", w, h); + SDL_GetRenderLogicalPresentation(renderer, &w, &h, &logical_presentation, &logical_scale_mode); + (void)SDL_snprintf(text, sizeof text, "SDL_GetRenderLogicalPresentation: %dx%d ", w, h); + SDLTest_PrintLogicalPresentation(text, sizeof text, logical_presentation); + SDL_snprintfcat(text, sizeof text, ", "); + SDLTest_PrintScaleMode(text, sizeof text, logical_scale_mode); SDLTest_DrawString(renderer, 0.0f, textY, text); textY += lineHeight; diff --git a/test/gamepadmap.c b/test/gamepadmap.c index c57419634..ed7d8c769 100644 --- a/test/gamepadmap.c +++ b/test/gamepadmap.c @@ -366,7 +366,9 @@ WatchJoystick(SDL_Joystick *joystick) SDL_RaiseWindow(window); /* scale for platforms that don't give you the window size you asked for. */ - SDL_SetRenderLogicalSize(screen, SCREEN_WIDTH, SCREEN_HEIGHT); + SDL_SetRenderLogicalPresentation(screen, SCREEN_WIDTH, SCREEN_HEIGHT, + SDL_LOGICAL_PRESENTATION_LETTERBOX, + SDL_ScaleModeLinear); /* Print info about the joystick we are watching */ name = SDL_GetJoystickName(joystick); diff --git a/test/testautomation_render.c b/test/testautomation_render.c index c7dcd97a6..43e2c3281 100644 --- a/test/testautomation_render.c +++ b/test/testautomation_render.c @@ -890,9 +890,11 @@ int render_testLogicalSize(void *arg) clearScreen(); /* Set the logical size and do a fill operation */ - ret = SDL_GetRendererOutputSize(renderer, &w, &h); + ret = SDL_GetCurrentRenderOutputSize(renderer, &w, &h); SDLTest_AssertCheck(ret == 0, "Validate result from SDL_GetRendererOutputSize, expected: 0, got: %i", ret); - ret = SDL_SetRenderLogicalSize(renderer, w / factor, h / factor); + ret = SDL_SetRenderLogicalPresentation(renderer, w / factor, h / factor, + SDL_LOGICAL_PRESENTATION_LETTERBOX, + SDL_ScaleModeNearest); SDLTest_AssertCheck(ret == 0, "Validate result from SDL_SetRenderLogicalSize, expected: 0, got: %i", ret); ret = SDL_SetRenderDrawColor(renderer, 0, 255, 0, SDL_ALPHA_OPAQUE); SDLTest_AssertCheck(ret == 0, "Validate result from SDL_SetRenderDrawColor, expected: 0, got: %i", ret); @@ -902,7 +904,10 @@ int render_testLogicalSize(void *arg) rect.h = (float)viewport.h / factor; ret = SDL_RenderFillRect(renderer, &rect); SDLTest_AssertCheck(ret == 0, "Validate result from SDL_RenderFillRect, expected: 0, got: %i", ret); - ret = SDL_SetRenderLogicalSize(renderer, 0, 0); + (void)SDL_RenderPresent(renderer); + ret = SDL_SetRenderLogicalPresentation(renderer, 0, 0, + SDL_LOGICAL_PRESENTATION_DISABLED, + SDL_ScaleModeNearest); SDLTest_AssertCheck(ret == 0, "Validate result from SDL_SetRenderLogicalSize, expected: 0, got: %i", ret); /* Check to see if final image matches. */ @@ -912,9 +917,11 @@ int render_testLogicalSize(void *arg) clearScreen(); /* Set the logical size and viewport and do a fill operation */ - ret = SDL_GetRendererOutputSize(renderer, &w, &h); + ret = SDL_GetCurrentRenderOutputSize(renderer, &w, &h); SDLTest_AssertCheck(ret == 0, "Validate result from SDL_GetRendererOutputSize, expected: 0, got: %i", ret); - ret = SDL_SetRenderLogicalSize(renderer, w / factor, h / factor); + ret = SDL_SetRenderLogicalPresentation(renderer, w / factor, h / factor, + SDL_LOGICAL_PRESENTATION_LETTERBOX, + SDL_ScaleModeNearest); SDLTest_AssertCheck(ret == 0, "Validate result from SDL_SetRenderLogicalSize, expected: 0, got: %i", ret); viewport.x = (TESTRENDER_SCREEN_W / 4) / factor; viewport.y = (TESTRENDER_SCREEN_H / 4) / factor; @@ -928,7 +935,10 @@ int render_testLogicalSize(void *arg) SDLTest_AssertCheck(ret == 0, "Validate result from SDL_RenderFillRect, expected: 0, got: %i", ret); ret = SDL_SetRenderViewport(renderer, NULL); SDLTest_AssertCheck(ret == 0, "Validate result from SDL_SetRenderViewport, expected: 0, got: %i", ret); - ret = SDL_SetRenderLogicalSize(renderer, 0, 0); + (void)SDL_RenderPresent(renderer); + ret = SDL_SetRenderLogicalPresentation(renderer, 0, 0, + SDL_LOGICAL_PRESENTATION_DISABLED, + SDL_ScaleModeNearest); SDLTest_AssertCheck(ret == 0, "Validate result from SDL_SetRenderLogicalSize, expected: 0, got: %i", ret); /* Check to see if final image matches. */ @@ -953,15 +963,22 @@ int render_testLogicalSize(void *arg) clearScreen(); /* Set the logical size and do a fill operation */ - ret = SDL_GetRendererOutputSize(renderer, &w, &h); + ret = SDL_GetCurrentRenderOutputSize(renderer, &w, &h); SDLTest_AssertCheck(ret == 0, "Validate result from SDL_GetRendererOutputSize, expected: 0, got: %i", ret); - ret = SDL_SetRenderLogicalSize(renderer, w - 2 * (TESTRENDER_SCREEN_W / 4), h); + ret = SDL_SetRenderLogicalPresentation(renderer, + w - 2 * (TESTRENDER_SCREEN_W / 4), + h, + SDL_LOGICAL_PRESENTATION_LETTERBOX, + SDL_ScaleModeLinear); SDLTest_AssertCheck(ret == 0, "Validate result from SDL_SetRenderLogicalSize, expected: 0, got: %i", ret); ret = SDL_SetRenderDrawColor(renderer, 0, 255, 0, SDL_ALPHA_OPAQUE); SDLTest_AssertCheck(ret == 0, "Validate result from SDL_SetRenderDrawColor, expected: 0, got: %i", ret); ret = SDL_RenderFillRect(renderer, NULL); SDLTest_AssertCheck(ret == 0, "Validate result from SDL_RenderFillRect, expected: 0, got: %i", ret); - ret = SDL_SetRenderLogicalSize(renderer, 0, 0); + (void)SDL_RenderPresent(renderer); + ret = SDL_SetRenderLogicalPresentation(renderer, 0, 0, + SDL_LOGICAL_PRESENTATION_DISABLED, + SDL_ScaleModeNearest); SDLTest_AssertCheck(ret == 0, "Validate result from SDL_SetRenderLogicalSize, expected: 0, got: %i", ret); /* Check to see if final image matches. */ diff --git a/test/testgamepad.c b/test/testgamepad.c index 8182539bc..d2e608a08 100644 --- a/test/testgamepad.c +++ b/test/testgamepad.c @@ -911,7 +911,9 @@ int main(int argc, char *argv[]) SDL_RenderPresent(screen); /* scale for platforms that don't give you the window size you asked for. */ - SDL_SetRenderLogicalSize(screen, SCREEN_WIDTH, SCREEN_HEIGHT); + SDL_SetRenderLogicalPresentation(screen, SCREEN_WIDTH, SCREEN_HEIGHT, + SDL_LOGICAL_PRESENTATION_LETTERBOX, + SDL_ScaleModeLinear); background_front = LoadTexture(screen, "gamepadmap.bmp", SDL_FALSE, NULL, NULL); background_back = LoadTexture(screen, "gamepadmap_back.bmp", SDL_FALSE, NULL, NULL); diff --git a/test/testwm.c b/test/testwm.c index 39ea5813a..3ea5d04d4 100644 --- a/test/testwm.c +++ b/test/testwm.c @@ -71,7 +71,7 @@ draw_modes_menu(SDL_Window *window, SDL_Renderer *renderer, SDL_FRect viewport) float logical_x, logical_y; SDL_GetMouseState(&window_x, &window_y); - SDL_RenderWindowToLogical(renderer, window_x, window_y, &logical_x, &logical_y); + SDL_RenderCoordinatesFromWindow(renderer, window_x, window_y, &logical_x, &logical_y); mouse_pos.x = logical_x; mouse_pos.y = logical_y;