From 473257cce652773118a0042adbc2636100654b2a Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Sat, 29 Jun 2024 14:12:50 -0700 Subject: [PATCH] Added SDL_GetRenderLogicalPresentationRect() Fixes https://github.com/libsdl-org/SDL/issues/8815 --- include/SDL3/SDL_render.h | 17 +++++++++ src/dynapi/SDL_dynapi.sym | 1 + src/dynapi/SDL_dynapi_overrides.h | 1 + src/dynapi/SDL_dynapi_procs.h | 1 + src/render/SDL_render.c | 27 ++++++++++++++ test/testautomation_render.c | 60 +++++++++++++++++++++++++++++++ 6 files changed, 107 insertions(+) diff --git a/include/SDL3/SDL_render.h b/include/SDL3/SDL_render.h index ee94ee9bb..a7302b681 100644 --- a/include/SDL3/SDL_render.h +++ b/include/SDL3/SDL_render.h @@ -1297,6 +1297,7 @@ extern SDL_DECLSPEC SDL_Texture *SDLCALL SDL_GetRenderTarget(SDL_Renderer *rende * * \sa SDL_ConvertEventToRenderCoordinates * \sa SDL_GetRenderLogicalPresentation + * \sa SDL_GetRenderLogicalPresentationRect */ extern SDL_DECLSPEC int SDLCALL SDL_SetRenderLogicalPresentation(SDL_Renderer *renderer, int w, int h, SDL_RendererLogicalPresentation mode, SDL_ScaleMode scale_mode); @@ -1320,6 +1321,22 @@ extern SDL_DECLSPEC int SDLCALL SDL_SetRenderLogicalPresentation(SDL_Renderer *r */ extern SDL_DECLSPEC int SDLCALL SDL_GetRenderLogicalPresentation(SDL_Renderer *renderer, int *w, int *h, SDL_RendererLogicalPresentation *mode, SDL_ScaleMode *scale_mode); +/** + * Get the final presentation rectangle for rendering. + * + * This function returns the calculated rectangle used for logical presentation, based on the presentation mode and output size. If logical presentation is disabled, it will fill the rectangle with the output size, in pixels. + * + * \param renderer the rendering context. + * \param rect a pointer filled in with the final presentation rectangle, may be NULL. + * \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 + */ +extern SDL_DECLSPEC int SDLCALL SDL_GetRenderLogicalPresentationRect(SDL_Renderer *renderer, SDL_FRect *rect); + /** * Get a point in render coordinates when given a point in window coordinates. * diff --git a/src/dynapi/SDL_dynapi.sym b/src/dynapi/SDL_dynapi.sym index 8ca96c833..b54b9fd05 100644 --- a/src/dynapi/SDL_dynapi.sym +++ b/src/dynapi/SDL_dynapi.sym @@ -393,6 +393,7 @@ SDL3_0.0.0 { SDL_GetRenderDrawColorFloat; SDL_GetRenderDriver; SDL_GetRenderLogicalPresentation; + SDL_GetRenderLogicalPresentationRect; SDL_GetRenderMetalCommandEncoder; SDL_GetRenderMetalLayer; SDL_GetRenderOutputSize; diff --git a/src/dynapi/SDL_dynapi_overrides.h b/src/dynapi/SDL_dynapi_overrides.h index d809adcd7..b8c98467b 100644 --- a/src/dynapi/SDL_dynapi_overrides.h +++ b/src/dynapi/SDL_dynapi_overrides.h @@ -418,6 +418,7 @@ #define SDL_GetRenderDrawColorFloat SDL_GetRenderDrawColorFloat_REAL #define SDL_GetRenderDriver SDL_GetRenderDriver_REAL #define SDL_GetRenderLogicalPresentation SDL_GetRenderLogicalPresentation_REAL +#define SDL_GetRenderLogicalPresentationRect SDL_GetRenderLogicalPresentationRect_REAL #define SDL_GetRenderMetalCommandEncoder SDL_GetRenderMetalCommandEncoder_REAL #define SDL_GetRenderMetalLayer SDL_GetRenderMetalLayer_REAL #define SDL_GetRenderOutputSize SDL_GetRenderOutputSize_REAL diff --git a/src/dynapi/SDL_dynapi_procs.h b/src/dynapi/SDL_dynapi_procs.h index 43b857439..740da8cf6 100644 --- a/src/dynapi/SDL_dynapi_procs.h +++ b/src/dynapi/SDL_dynapi_procs.h @@ -438,6 +438,7 @@ SDL_DYNAPI_PROC(int,SDL_GetRenderDrawColor,(SDL_Renderer *a, Uint8 *b, Uint8 *c, SDL_DYNAPI_PROC(int,SDL_GetRenderDrawColorFloat,(SDL_Renderer *a, float *b, float *c, float *d, float *e),(a,b,c,d,e),return) SDL_DYNAPI_PROC(const char*,SDL_GetRenderDriver,(int a),(a),return) 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(int,SDL_GetRenderLogicalPresentationRect,(SDL_Renderer *a, SDL_FRect *b),(a,b),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(int,SDL_GetRenderOutputSize,(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 index 0b504ca1d..ed705272d 100644 --- a/src/render/SDL_render.c +++ b/src/render/SDL_render.c @@ -2607,6 +2607,33 @@ int SDL_GetRenderLogicalPresentation(SDL_Renderer *renderer, int *w, int *h, SDL return 0; } +int SDL_GetRenderLogicalPresentationRect(SDL_Renderer *renderer, SDL_FRect *rect) +{ + if (rect) { + SDL_zerop(rect); + } + + CHECK_RENDERER_MAGIC(renderer, -1); + + if (rect) { + if (renderer->logical_presentation_mode == SDL_LOGICAL_PRESENTATION_DISABLED) { + int output_w = 0, output_h = 0; + + if (SDL_GetRenderOutputSize(renderer, &output_w, &output_h) < 0) { + return -1; + } + + rect->x = 0.0f; + rect->y = 0.0f; + rect->w = (float)output_w; + rect->h = (float)output_h; + } else { + SDL_copyp(rect, &renderer->logical_dst_rect); + } + } + return 0; +} + static void SDL_RenderLogicalBorders(SDL_Renderer *renderer) { const SDL_FRect *dst = &renderer->logical_dst_rect; diff --git a/test/testautomation_render.c b/test/testautomation_render.c index 704bb41e3..644c6f453 100644 --- a/test/testautomation_render.c +++ b/test/testautomation_render.c @@ -920,6 +920,10 @@ static int render_testLogicalSize(void *arg) SDL_Rect viewport; SDL_FRect rect; int w, h; + int set_w, set_h; + SDL_RendererLogicalPresentation set_presentation_mode; + SDL_ScaleMode set_scale_mode; + SDL_FRect set_rect; const int factor = 2; viewport.x = ((TESTRENDER_SCREEN_W / 4) / factor) * factor; @@ -940,6 +944,20 @@ static int render_testLogicalSize(void *arg) CHECK_FUNC(SDL_SetRenderLogicalPresentation, (renderer, w / factor, h / factor, SDL_LOGICAL_PRESENTATION_LETTERBOX, SDL_SCALEMODE_NEAREST)) + CHECK_FUNC(SDL_GetRenderLogicalPresentation, (renderer, &set_w, &set_h, &set_presentation_mode, &set_scale_mode)) + SDLTest_AssertCheck( + set_w == (w / factor) && + set_h == (h / factor) && + set_presentation_mode == SDL_LOGICAL_PRESENTATION_LETTERBOX && + set_scale_mode == SDL_SCALEMODE_NEAREST, + "Validate result from SDL_GetRenderLogicalPresentation, got %d, %d, %d, %d", set_w, set_h, set_presentation_mode, set_scale_mode); + CHECK_FUNC(SDL_GetRenderLogicalPresentationRect, (renderer, &set_rect)) + SDLTest_AssertCheck( + set_rect.x == 0.0f && + set_rect.y == 0.0f && + set_rect.w == 320.0f && + set_rect.h == 240.0f, + "Validate result from SDL_GetRenderLogicalPresentationRect, got {%g, %g, %gx%g}", set_rect.x, set_rect.y, set_rect.w, set_rect.h); CHECK_FUNC(SDL_SetRenderDrawColor, (renderer, 0, 255, 0, SDL_ALPHA_OPAQUE)) rect.x = (float)viewport.x / factor; rect.y = (float)viewport.y / factor; @@ -949,6 +967,20 @@ static int render_testLogicalSize(void *arg) CHECK_FUNC(SDL_SetRenderLogicalPresentation, (renderer, 0, 0, SDL_LOGICAL_PRESENTATION_DISABLED, SDL_SCALEMODE_NEAREST)) + CHECK_FUNC(SDL_GetRenderLogicalPresentation, (renderer, &set_w, &set_h, &set_presentation_mode, &set_scale_mode)) + SDLTest_AssertCheck( + set_w == 0 && + set_h == 0 && + set_presentation_mode == SDL_LOGICAL_PRESENTATION_DISABLED && + set_scale_mode == SDL_SCALEMODE_NEAREST, + "Validate result from SDL_GetRenderLogicalPresentation, got %d, %d, %d, %d", set_w, set_h, set_presentation_mode, set_scale_mode); + CHECK_FUNC(SDL_GetRenderLogicalPresentationRect, (renderer, &set_rect)) + SDLTest_AssertCheck( + set_rect.x == 0.0f && + set_rect.y == 0.0f && + set_rect.w == 320.0f && + set_rect.h == 240.0f, + "Validate result from SDL_GetRenderLogicalPresentationRect, got {%g, %g, %gx%g}", set_rect.x, set_rect.y, set_rect.w, set_rect.h); /* Check to see if final image matches. */ compare(referenceSurface, ALLOWABLE_ERROR_OPAQUE); @@ -999,11 +1031,39 @@ static int render_testLogicalSize(void *arg) h, SDL_LOGICAL_PRESENTATION_LETTERBOX, SDL_SCALEMODE_LINEAR)) + CHECK_FUNC(SDL_GetRenderLogicalPresentation, (renderer, &set_w, &set_h, &set_presentation_mode, &set_scale_mode)) + SDLTest_AssertCheck( + set_w == w - 2 * (TESTRENDER_SCREEN_W / 4) && + set_h == h && + set_presentation_mode == SDL_LOGICAL_PRESENTATION_LETTERBOX && + set_scale_mode == SDL_SCALEMODE_LINEAR, + "Validate result from SDL_GetRenderLogicalPresentation, got %d, %d, %d, %d", set_w, set_h, set_presentation_mode, set_scale_mode); + CHECK_FUNC(SDL_GetRenderLogicalPresentationRect, (renderer, &set_rect)) + SDLTest_AssertCheck( + set_rect.x == 20.0f && + set_rect.y == 0.0f && + set_rect.w == 280.0f && + set_rect.h == 240.0f, + "Validate result from SDL_GetRenderLogicalPresentationRect, got {%g, %g, %gx%g}", set_rect.x, set_rect.y, set_rect.w, set_rect.h); CHECK_FUNC(SDL_SetRenderDrawColor, (renderer, 0, 255, 0, SDL_ALPHA_OPAQUE)) CHECK_FUNC(SDL_RenderFillRect, (renderer, NULL)) CHECK_FUNC(SDL_SetRenderLogicalPresentation, (renderer, 0, 0, SDL_LOGICAL_PRESENTATION_DISABLED, SDL_SCALEMODE_NEAREST)) + CHECK_FUNC(SDL_GetRenderLogicalPresentation, (renderer, &set_w, &set_h, &set_presentation_mode, &set_scale_mode)) + SDLTest_AssertCheck( + set_w == 0 && + set_h == 0 && + set_presentation_mode == SDL_LOGICAL_PRESENTATION_DISABLED && + set_scale_mode == SDL_SCALEMODE_NEAREST, + "Validate result from SDL_GetRenderLogicalPresentation, got %d, %d, %d, %d", set_w, set_h, set_presentation_mode, set_scale_mode); + CHECK_FUNC(SDL_GetRenderLogicalPresentationRect, (renderer, &set_rect)) + SDLTest_AssertCheck( + set_rect.x == 0.0f && + set_rect.y == 0.0f && + set_rect.w == 320.0f && + set_rect.h == 240.0f, + "Validate result from SDL_GetRenderLogicalPresentationRect, got {%g, %g, %gx%g}", set_rect.x, set_rect.y, set_rect.w, set_rect.h); /* Check to see if final image matches. */ compare(referenceSurface, ALLOWABLE_ERROR_OPAQUE);