Преглед на файлове

Added SDL_GetRenderSafeArea()

Sam Lantinga преди 1 година
родител
ревизия
cf8b158ccb
променени са 7 файла, в които са добавени 81 реда и са изтрити 4 реда
  1. 20 0
      include/SDL3/SDL_render.h
  2. 1 0
      src/dynapi/SDL_dynapi.sym
  3. 1 0
      src/dynapi/SDL_dynapi_overrides.h
  4. 1 0
      src/dynapi/SDL_dynapi_procs.h
  5. 47 0
      src/render/SDL_render.c
  6. 8 3
      test/testsprite.c
  7. 3 1
      test/testwm.c

+ 20 - 0
include/SDL3/SDL_render.h

@@ -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.
  *

+ 1 - 0
src/dynapi/SDL_dynapi.sym

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

+ 1 - 0
src/dynapi/SDL_dynapi_overrides.h

@@ -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

+ 1 - 0
src/dynapi/SDL_dynapi_procs.h

@@ -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)

+ 47 - 0
src/render/SDL_render.c

@@ -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)

+ 8 - 3
test/testsprite.c

@@ -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;

+ 3 - 1
test/testwm.c

@@ -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);