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;