Added SDL_GetRenderSafeArea()

This commit is contained in:
Sam Lantinga 2024-07-24 17:14:00 -07:00
parent eb09264076
commit cf8b158ccb
7 changed files with 81 additions and 4 deletions

View File

@ -1443,6 +1443,26 @@ extern SDL_DECLSPEC int SDLCALL SDL_GetRenderViewport(SDL_Renderer *renderer, SD
*/
extern SDL_DECLSPEC SDL_bool SDLCALL SDL_RenderViewportSet(SDL_Renderer *renderer);
/**
* Get the safe area for rendering within the current viewport.
*
* Some devices have portions of the screen which are partially obscured or
* not interactive, possibly due to on-screen controls, curved edges, camera
* notches, TV overscan, etc. This function provides the area of the current
* viewport which is safe to have interactible content. You should continue rendering
* into the rest of the render target, but it should not contain visually important
* or interactible content.
*
* \param renderer the rendering context.
* \param rect a pointer filled in with the area that is safe for
* interactive content.
* \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.
*/
extern SDL_DECLSPEC int SDLCALL SDL_GetRenderSafeArea(SDL_Renderer *renderer, SDL_Rect *rect);
/**
* Set the clip rectangle for rendering on the specified target.
*

View File

@ -401,6 +401,7 @@ SDL3_0.0.0 {
SDL_GetRenderMetalCommandEncoder;
SDL_GetRenderMetalLayer;
SDL_GetRenderOutputSize;
SDL_GetRenderSafeArea;
SDL_GetRenderScale;
SDL_GetRenderTarget;
SDL_GetRenderVSync;

View File

@ -426,6 +426,7 @@
#define SDL_GetRenderMetalCommandEncoder SDL_GetRenderMetalCommandEncoder_REAL
#define SDL_GetRenderMetalLayer SDL_GetRenderMetalLayer_REAL
#define SDL_GetRenderOutputSize SDL_GetRenderOutputSize_REAL
#define SDL_GetRenderSafeArea SDL_GetRenderSafeArea_REAL
#define SDL_GetRenderScale SDL_GetRenderScale_REAL
#define SDL_GetRenderTarget SDL_GetRenderTarget_REAL
#define SDL_GetRenderVSync SDL_GetRenderVSync_REAL

View File

@ -446,6 +446,7 @@ SDL_DYNAPI_PROC(int,SDL_GetRenderLogicalPresentationRect,(SDL_Renderer *a, SDL_F
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)
SDL_DYNAPI_PROC(int,SDL_GetRenderSafeArea,(SDL_Renderer *a, SDL_Rect *b),(a,b),return)
SDL_DYNAPI_PROC(int,SDL_GetRenderScale,(SDL_Renderer *a, float *b, float *c),(a,b,c),return)
SDL_DYNAPI_PROC(SDL_Texture*,SDL_GetRenderTarget,(SDL_Renderer *a),(a),return)
SDL_DYNAPI_PROC(int,SDL_GetRenderVSync,(SDL_Renderer *a, int *b),(a,b),return)

View File

@ -2999,6 +2999,53 @@ static void GetRenderViewportSize(SDL_Renderer *renderer, SDL_FRect *rect)
}
}
int SDL_GetRenderSafeArea(SDL_Renderer *renderer, SDL_Rect *rect)
{
if (rect) {
SDL_zerop(rect);
}
CHECK_RENDERER_MAGIC(renderer, -1);
if (renderer->target || !renderer->window) {
// The entire viewport is safe for rendering
return SDL_GetRenderViewport(renderer, rect);
}
if (rect) {
// Get the window safe rect
SDL_Rect safe;
if (SDL_GetWindowSafeArea(renderer->window, &safe) < 0) {
return -1;
}
// Convert the coordinates into the render space
float minx = (float)safe.x;
float miny = (float)safe.y;
float maxx = (float)safe.x + safe.w;
float maxy = (float)safe.y + safe.h;
if (SDL_RenderCoordinatesFromWindow(renderer, minx, miny, &minx, &miny) < 0 ||
SDL_RenderCoordinatesFromWindow(renderer, maxx, maxy, &maxx, &maxy) < 0) {
return -1;
}
rect->x = (int)SDL_ceilf(minx);
rect->y = (int)SDL_ceilf(miny);
rect->w = (int)SDL_ceilf(maxx - minx);
rect->h = (int)SDL_ceilf(maxy - miny);
// Clip with the viewport
SDL_Rect viewport;
if (SDL_GetRenderViewport(renderer, &viewport) < 0) {
return -1;
}
if (!SDL_GetRectIntersection(rect, &viewport, rect)) {
return SDL_SetError("No safe area within viewport");
}
}
return 0;
}
int SDL_SetRenderClipRect(SDL_Renderer *renderer, const SDL_Rect *rect)
{
CHECK_RENDERER_MAGIC(renderer, -1)

View File

@ -81,7 +81,9 @@ static void MoveSprites(SDL_Renderer *renderer, SDL_Texture *sprite)
SDL_FRect *position, *velocity;
/* Query the sizes */
SDL_GetRenderViewport(renderer, &viewport);
SDL_SetRenderViewport(renderer, NULL);
SDL_GetRenderSafeArea(renderer, &viewport);
SDL_SetRenderViewport(renderer, &viewport);
/* Cycle the color and alpha, if desired */
if (cycle_color) {
@ -424,6 +426,7 @@ int SDL_AppIterate(void *appstate)
int SDL_AppInit(void **appstate, int argc, char *argv[])
{
SDL_Rect safe_area;
int i;
Uint64 seed;
const char *icon = "icon.bmp";
@ -556,6 +559,8 @@ int SDL_AppInit(void **appstate, int argc, char *argv[])
}
/* Position sprites and set their velocities using the fuzzer */
/* Really we should be using per-window safe area, but this is fine for a simple test */
SDL_GetRenderSafeArea(state->renderers[0], &safe_area);
if (iterations >= 0) {
/* Deterministic seed - used for visual tests */
seed = (Uint64)iterations;
@ -565,8 +570,8 @@ int SDL_AppInit(void **appstate, int argc, char *argv[])
}
SDLTest_FuzzerInit(seed);
for (i = 0; i < num_sprites; ++i) {
positions[i].x = (float)SDLTest_RandomIntegerInRange(0, (int)(state->window_w - sprite_w));
positions[i].y = (float)SDLTest_RandomIntegerInRange(0, (int)(state->window_h - sprite_h));
positions[i].x = (float)SDLTest_RandomIntegerInRange(0, (int)(safe_area.w - sprite_w));
positions[i].y = (float)SDLTest_RandomIntegerInRange(0, (int)(safe_area.h - sprite_h));
positions[i].w = sprite_w;
positions[i].h = sprite_h;
velocities[i].x = 0;

View File

@ -226,7 +226,9 @@ static void loop(void)
SDL_Rect viewport;
SDL_FRect menurect;
SDL_GetRenderViewport(renderer, &viewport);
SDL_SetRenderViewport(renderer, NULL);
SDL_GetRenderSafeArea(renderer, &viewport);
SDL_SetRenderViewport(renderer, &viewport);
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
SDL_RenderClear(renderer);