Răsfoiți Sursa

Added floating point versions of cliprect and viewport render functions

Fixes https://github.com/libsdl-org/SDL/issues/14654
Sam Lantinga 5 zile în urmă
părinte
comite
33b4a9d915

+ 97 - 0
include/SDL3/SDL_render.h

@@ -1823,6 +1823,7 @@ extern SDL_DECLSPEC bool SDLCALL SDL_ConvertEventToRenderCoordinates(SDL_Rendere
  *
  *
  * \sa SDL_GetRenderViewport
  * \sa SDL_GetRenderViewport
  * \sa SDL_RenderViewportSet
  * \sa SDL_RenderViewportSet
+ * \sa SDL_SetRenderViewportFloat
  */
  */
 extern SDL_DECLSPEC bool SDLCALL SDL_SetRenderViewport(SDL_Renderer *renderer, const SDL_Rect *rect);
 extern SDL_DECLSPEC bool SDLCALL SDL_SetRenderViewport(SDL_Renderer *renderer, const SDL_Rect *rect);
 
 
@@ -1841,11 +1842,59 @@ extern SDL_DECLSPEC bool SDLCALL SDL_SetRenderViewport(SDL_Renderer *renderer, c
  *
  *
  * \since This function is available since SDL 3.2.0.
  * \since This function is available since SDL 3.2.0.
  *
  *
+ * \sa SDL_GetRenderViewportFloat
  * \sa SDL_RenderViewportSet
  * \sa SDL_RenderViewportSet
  * \sa SDL_SetRenderViewport
  * \sa SDL_SetRenderViewport
  */
  */
 extern SDL_DECLSPEC bool SDLCALL SDL_GetRenderViewport(SDL_Renderer *renderer, SDL_Rect *rect);
 extern SDL_DECLSPEC bool SDLCALL SDL_GetRenderViewport(SDL_Renderer *renderer, SDL_Rect *rect);
 
 
+/**
+ * Set the drawing area for rendering on the current target.
+ *
+ * Drawing will clip to this area (separately from any clipping done with
+ * SDL_SetRenderClipRect), and the top left of the area will become coordinate
+ * (0, 0) for future drawing commands.
+ *
+ * The area's width and height must be >= 0.
+ *
+ * Each render target has its own viewport. This function sets the viewport
+ * for the current render target.
+ *
+ * \param renderer the rendering context.
+ * \param rect the SDL_FRect structure representing the drawing area, or NULL
+ *             to set the viewport to the entire target.
+ * \returns true on success or false on failure; call SDL_GetError() for more
+ *          information.
+ *
+ * \threadsafety This function should only be called on the main thread.
+ *
+ * \since This function is available since SDL 3.6.0.
+ *
+ * \sa SDL_GetRenderViewportFloat
+ * \sa SDL_RenderViewportSet
+ */
+extern SDL_DECLSPEC bool SDLCALL SDL_SetRenderViewportFloat(SDL_Renderer *renderer, const SDL_FRect *rect);
+
+/**
+ * Get the drawing area for the current target.
+ *
+ * Each render target has its own viewport. This function gets the viewport
+ * for the current render target.
+ *
+ * \param renderer the rendering context.
+ * \param rect an SDL_FRect structure filled in with the current drawing area.
+ * \returns true on success or false on failure; call SDL_GetError() for more
+ *          information.
+ *
+ * \threadsafety This function should only be called on the main thread.
+ *
+ * \since This function is available since SDL 3.6.0.
+ *
+ * \sa SDL_RenderViewportSet
+ * \sa SDL_SetRenderViewportFloat
+ */
+extern SDL_DECLSPEC bool SDLCALL SDL_GetRenderViewportFloat(SDL_Renderer *renderer, SDL_FRect *rect);
+
 /**
 /**
  * Return whether an explicit rectangle was set as the viewport.
  * Return whether an explicit rectangle was set as the viewport.
  *
  *
@@ -1864,7 +1913,9 @@ extern SDL_DECLSPEC bool SDLCALL SDL_GetRenderViewport(SDL_Renderer *renderer, S
  * \since This function is available since SDL 3.2.0.
  * \since This function is available since SDL 3.2.0.
  *
  *
  * \sa SDL_GetRenderViewport
  * \sa SDL_GetRenderViewport
+ * \sa SDL_GetRenderViewportFloat
  * \sa SDL_SetRenderViewport
  * \sa SDL_SetRenderViewport
+ * \sa SDL_SetRenderViewportFloat
  */
  */
 extern SDL_DECLSPEC bool SDLCALL SDL_RenderViewportSet(SDL_Renderer *renderer);
 extern SDL_DECLSPEC bool SDLCALL SDL_RenderViewportSet(SDL_Renderer *renderer);
 
 
@@ -1908,6 +1959,7 @@ extern SDL_DECLSPEC bool SDLCALL SDL_GetRenderSafeArea(SDL_Renderer *renderer, S
  *
  *
  * \sa SDL_GetRenderClipRect
  * \sa SDL_GetRenderClipRect
  * \sa SDL_RenderClipEnabled
  * \sa SDL_RenderClipEnabled
+ * \sa SDL_SetRenderClipRectFloat
  */
  */
 extern SDL_DECLSPEC bool SDLCALL SDL_SetRenderClipRect(SDL_Renderer *renderer, const SDL_Rect *rect);
 extern SDL_DECLSPEC bool SDLCALL SDL_SetRenderClipRect(SDL_Renderer *renderer, const SDL_Rect *rect);
 
 
@@ -1927,11 +1979,54 @@ extern SDL_DECLSPEC bool SDLCALL SDL_SetRenderClipRect(SDL_Renderer *renderer, c
  *
  *
  * \since This function is available since SDL 3.2.0.
  * \since This function is available since SDL 3.2.0.
  *
  *
+ * \sa SDL_GetRenderClipRectFloat
  * \sa SDL_RenderClipEnabled
  * \sa SDL_RenderClipEnabled
  * \sa SDL_SetRenderClipRect
  * \sa SDL_SetRenderClipRect
  */
  */
 extern SDL_DECLSPEC bool SDLCALL SDL_GetRenderClipRect(SDL_Renderer *renderer, SDL_Rect *rect);
 extern SDL_DECLSPEC bool SDLCALL SDL_GetRenderClipRect(SDL_Renderer *renderer, SDL_Rect *rect);
 
 
+/**
+ * Set the clip rectangle for rendering on the specified target.
+ *
+ * Each render target has its own clip rectangle. This function sets the
+ * cliprect for the current render target.
+ *
+ * \param renderer the rendering context.
+ * \param rect an SDL_FRect structure representing the clip area, relative to
+ *             the viewport, or NULL to disable clipping.
+ * \returns true on success or false on failure; call SDL_GetError() for more
+ *          information.
+ *
+ * \threadsafety This function should only be called on the main thread.
+ *
+ * \since This function is available since SDL 3.6.0.
+ *
+ * \sa SDL_GetRenderClipRectFloat
+ * \sa SDL_RenderClipEnabled
+ */
+extern SDL_DECLSPEC bool SDLCALL SDL_SetRenderClipRectFloat(SDL_Renderer *renderer, const SDL_FRect *rect);
+
+/**
+ * Get the clip rectangle for the current target.
+ *
+ * Each render target has its own clip rectangle. This function gets the
+ * cliprect for the current render target.
+ *
+ * \param renderer the rendering context.
+ * \param rect an SDL_FRect structure filled in with the current clipping area
+ *             or an empty rectangle if clipping is disabled.
+ * \returns true on success or false on failure; call SDL_GetError() for more
+ *          information.
+ *
+ * \threadsafety This function should only be called on the main thread.
+ *
+ * \since This function is available since SDL 3.6.0.
+ *
+ * \sa SDL_RenderClipEnabled
+ * \sa SDL_SetRenderClipRectFloat
+ */
+extern SDL_DECLSPEC bool SDLCALL SDL_GetRenderClipRectFloat(SDL_Renderer *renderer, SDL_FRect *rect);
+
 /**
 /**
  * Get whether clipping is enabled on the given render target.
  * Get whether clipping is enabled on the given render target.
  *
  *
@@ -1947,7 +2042,9 @@ extern SDL_DECLSPEC bool SDLCALL SDL_GetRenderClipRect(SDL_Renderer *renderer, S
  * \since This function is available since SDL 3.2.0.
  * \since This function is available since SDL 3.2.0.
  *
  *
  * \sa SDL_GetRenderClipRect
  * \sa SDL_GetRenderClipRect
+ * \sa SDL_GetRenderClipRectFloat
  * \sa SDL_SetRenderClipRect
  * \sa SDL_SetRenderClipRect
+ * \sa SDL_SetRenderClipRectFloat
  */
  */
 extern SDL_DECLSPEC bool SDLCALL SDL_RenderClipEnabled(SDL_Renderer *renderer);
 extern SDL_DECLSPEC bool SDLCALL SDL_RenderClipEnabled(SDL_Renderer *renderer);
 
 

+ 4 - 0
src/dynapi/SDL_dynapi.exports

@@ -1307,3 +1307,7 @@ _SDL_SetJoystickSensorEnabled
 _SDL_JoystickSensorEnabled
 _SDL_JoystickSensorEnabled
 _SDL_GetJoystickSensorDataRate
 _SDL_GetJoystickSensorDataRate
 _SDL_GetJoystickSensorData
 _SDL_GetJoystickSensorData
+_SDL_SetRenderViewportFloat
+_SDL_GetRenderViewportFloat
+_SDL_SetRenderClipRectFloat
+_SDL_GetRenderClipRectFloat

+ 4 - 0
src/dynapi/SDL_dynapi.sym

@@ -1308,6 +1308,10 @@ SDL3_0.0.0 {
     SDL_JoystickSensorEnabled;
     SDL_JoystickSensorEnabled;
     SDL_GetJoystickSensorDataRate;
     SDL_GetJoystickSensorDataRate;
     SDL_GetJoystickSensorData;
     SDL_GetJoystickSensorData;
+    SDL_SetRenderViewportFloat;
+    SDL_GetRenderViewportFloat;
+    SDL_SetRenderClipRectFloat;
+    SDL_GetRenderClipRectFloat;
     # extra symbols go here (don't modify this line)
     # extra symbols go here (don't modify this line)
   local: *;
   local: *;
 };
 };

+ 4 - 0
src/dynapi/SDL_dynapi_overrides.h

@@ -1334,3 +1334,7 @@
 #define SDL_JoystickSensorEnabled SDL_JoystickSensorEnabled_REAL
 #define SDL_JoystickSensorEnabled SDL_JoystickSensorEnabled_REAL
 #define SDL_GetJoystickSensorDataRate SDL_GetJoystickSensorDataRate_REAL
 #define SDL_GetJoystickSensorDataRate SDL_GetJoystickSensorDataRate_REAL
 #define SDL_GetJoystickSensorData SDL_GetJoystickSensorData_REAL
 #define SDL_GetJoystickSensorData SDL_GetJoystickSensorData_REAL
+#define SDL_SetRenderViewportFloat SDL_SetRenderViewportFloat_REAL
+#define SDL_GetRenderViewportFloat SDL_GetRenderViewportFloat_REAL
+#define SDL_SetRenderClipRectFloat SDL_SetRenderClipRectFloat_REAL
+#define SDL_GetRenderClipRectFloat SDL_GetRenderClipRectFloat_REAL

+ 4 - 0
src/dynapi/SDL_dynapi_procs.h

@@ -1342,3 +1342,7 @@ SDL_DYNAPI_PROC(bool,SDL_SetJoystickSensorEnabled,(SDL_Joystick *a,SDL_SensorTyp
 SDL_DYNAPI_PROC(bool,SDL_JoystickSensorEnabled,(SDL_Joystick *a,SDL_SensorType b),(a,b),return)
 SDL_DYNAPI_PROC(bool,SDL_JoystickSensorEnabled,(SDL_Joystick *a,SDL_SensorType b),(a,b),return)
 SDL_DYNAPI_PROC(float,SDL_GetJoystickSensorDataRate,(SDL_Joystick *a,SDL_SensorType b),(a,b),return)
 SDL_DYNAPI_PROC(float,SDL_GetJoystickSensorDataRate,(SDL_Joystick *a,SDL_SensorType b),(a,b),return)
 SDL_DYNAPI_PROC(bool,SDL_GetJoystickSensorData,(SDL_Joystick *a,SDL_SensorType b,float *c,int d),(a,b,c,d),return)
 SDL_DYNAPI_PROC(bool,SDL_GetJoystickSensorData,(SDL_Joystick *a,SDL_SensorType b,float *c,int d),(a,b,c,d),return)
+SDL_DYNAPI_PROC(bool,SDL_SetRenderViewportFloat,(SDL_Renderer *a,const SDL_FRect *b),(a,b),return)
+SDL_DYNAPI_PROC(bool,SDL_GetRenderViewportFloat,(SDL_Renderer *a,SDL_FRect *b),(a,b),return)
+SDL_DYNAPI_PROC(bool,SDL_SetRenderClipRectFloat,(SDL_Renderer *a,const SDL_FRect *b),(a,b),return)
+SDL_DYNAPI_PROC(bool,SDL_GetRenderClipRectFloat,(SDL_Renderer *a,SDL_FRect *b),(a,b),return)

+ 79 - 19
src/render/SDL_render.c

@@ -1165,8 +1165,8 @@ SDL_Renderer *SDL_CreateRendererWithProperties(SDL_PropertiesID props)
         renderer->main_view.pixel_w = surface->w;
         renderer->main_view.pixel_w = surface->w;
         renderer->main_view.pixel_h = surface->h;
         renderer->main_view.pixel_h = surface->h;
     }
     }
-    renderer->main_view.viewport.w = -1;
-    renderer->main_view.viewport.h = -1;
+    renderer->main_view.viewport.w = -1.0f;
+    renderer->main_view.viewport.h = -1.0f;
     renderer->main_view.scale.x = 1.0f;
     renderer->main_view.scale.x = 1.0f;
     renderer->main_view.scale.y = 1.0f;
     renderer->main_view.scale.y = 1.0f;
     renderer->main_view.logical_scale.x = 1.0f;
     renderer->main_view.logical_scale.x = 1.0f;
@@ -1558,8 +1558,8 @@ SDL_Texture *SDL_CreateTextureWithProperties(SDL_Renderer *renderer, SDL_Propert
     texture->scaleMode = renderer->scale_mode;
     texture->scaleMode = renderer->scale_mode;
     texture->view.pixel_w = w;
     texture->view.pixel_w = w;
     texture->view.pixel_h = h;
     texture->view.pixel_h = h;
-    texture->view.viewport.w = -1;
-    texture->view.viewport.h = -1;
+    texture->view.viewport.w = -1.0f;
+    texture->view.viewport.h = -1.0f;
     texture->view.scale.x = 1.0f;
     texture->view.scale.x = 1.0f;
     texture->view.scale.y = 1.0f;
     texture->view.scale.y = 1.0f;
     texture->view.logical_scale.x = 1.0f;
     texture->view.logical_scale.x = 1.0f;
@@ -3160,25 +3160,56 @@ bool SDL_ConvertEventToRenderCoordinates(SDL_Renderer *renderer, SDL_Event *even
 }
 }
 
 
 bool SDL_SetRenderViewport(SDL_Renderer *renderer, const SDL_Rect *rect)
 bool SDL_SetRenderViewport(SDL_Renderer *renderer, const SDL_Rect *rect)
+{
+    if (rect) {
+        SDL_FRect frect;
+        SDL_RectToFRect(rect, &frect);
+        return SDL_SetRenderViewportFloat(renderer, &frect);
+    } else {
+        return SDL_SetRenderViewportFloat(renderer, NULL);
+    }
+}
+
+bool SDL_GetRenderViewport(SDL_Renderer *renderer, SDL_Rect *rect)
+{
+    if (rect) {
+        SDL_zerop(rect);
+    }
+
+    SDL_FRect frect;
+    if (SDL_GetRenderViewportFloat(renderer, &frect)) {
+        if (rect) {
+            rect->x = (int)SDL_floorf(frect.x);
+            rect->y = (int)SDL_floorf(frect.y);
+            rect->w = (int)SDL_ceilf(frect.w);
+            rect->h = (int)SDL_ceilf(frect.h);
+        }
+        return true;
+    } else {
+        return false;
+    }
+}
+
+bool SDL_SetRenderViewportFloat(SDL_Renderer *renderer, const SDL_FRect *rect)
 {
 {
     CHECK_RENDERER_MAGIC(renderer, false);
     CHECK_RENDERER_MAGIC(renderer, false);
 
 
     SDL_RenderViewState *view = renderer->view;
     SDL_RenderViewState *view = renderer->view;
     if (rect) {
     if (rect) {
-        if ((rect->w < 0) || (rect->h < 0)) {
+        if ((rect->w < 0.0f) || (rect->h < 0.0f)) {
             return SDL_SetError("rect has a negative size");
             return SDL_SetError("rect has a negative size");
         }
         }
         SDL_copyp(&view->viewport, rect);
         SDL_copyp(&view->viewport, rect);
     } else {
     } else {
-        view->viewport.x = view->viewport.y = 0;
-        view->viewport.w = view->viewport.h = -1;
+        view->viewport.x = view->viewport.y = 0.0f;
+        view->viewport.w = view->viewport.h = -1.0f;
     }
     }
     UpdatePixelViewport(renderer, view);
     UpdatePixelViewport(renderer, view);
 
 
     return QueueCmdSetViewport(renderer);
     return QueueCmdSetViewport(renderer);
 }
 }
 
 
-bool SDL_GetRenderViewport(SDL_Renderer *renderer, SDL_Rect *rect)
+bool SDL_GetRenderViewportFloat(SDL_Renderer *renderer, SDL_FRect *rect)
 {
 {
     if (rect) {
     if (rect) {
         SDL_zerop(rect);
         SDL_zerop(rect);
@@ -3190,15 +3221,15 @@ bool SDL_GetRenderViewport(SDL_Renderer *renderer, SDL_Rect *rect)
         const SDL_RenderViewState *view = renderer->view;
         const SDL_RenderViewState *view = renderer->view;
         rect->x = view->viewport.x;
         rect->x = view->viewport.x;
         rect->y = view->viewport.y;
         rect->y = view->viewport.y;
-        if (view->viewport.w >= 0) {
+        if (view->viewport.w >= 0.0f) {
             rect->w = view->viewport.w;
             rect->w = view->viewport.w;
         } else {
         } else {
-            rect->w = (int)SDL_ceilf(view->pixel_w / view->current_scale.x);
+            rect->w = view->pixel_w / view->current_scale.x;
         }
         }
-        if (view->viewport.h >= 0) {
+        if (view->viewport.h >= 0.0f) {
             rect->h = view->viewport.h;
             rect->h = view->viewport.h;
         } else {
         } else {
-            rect->h = (int)SDL_ceilf(view->pixel_h / view->current_scale.y);
+            rect->h = view->pixel_h / view->current_scale.y;
         }
         }
     }
     }
     return true;
     return true;
@@ -3209,7 +3240,7 @@ bool SDL_RenderViewportSet(SDL_Renderer *renderer)
     CHECK_RENDERER_MAGIC(renderer, false);
     CHECK_RENDERER_MAGIC(renderer, false);
 
 
     const SDL_RenderViewState *view = renderer->view;
     const SDL_RenderViewState *view = renderer->view;
-    return (view->viewport.w >= 0 && view->viewport.h >= 0);
+    return (view->viewport.w >= 0.0f && view->viewport.h >= 0.0f);
 }
 }
 
 
 static void GetRenderViewportSize(SDL_Renderer *renderer, SDL_FRect *rect)
 static void GetRenderViewportSize(SDL_Renderer *renderer, SDL_FRect *rect)
@@ -3221,14 +3252,14 @@ static void GetRenderViewportSize(SDL_Renderer *renderer, SDL_FRect *rect)
     rect->x = 0.0f;
     rect->x = 0.0f;
     rect->y = 0.0f;
     rect->y = 0.0f;
 
 
-    if (view->viewport.w >= 0) {
-        rect->w = (float)view->viewport.w;
+    if (view->viewport.w >= 0.0f) {
+        rect->w = view->viewport.w;
     } else {
     } else {
         rect->w = view->pixel_w / scale_x;
         rect->w = view->pixel_w / scale_x;
     }
     }
 
 
-    if (view->viewport.h >= 0) {
-        rect->h = (float)view->viewport.h;
+    if (view->viewport.h >= 0.0f) {
+        rect->h = view->viewport.h;
     } else {
     } else {
         rect->h = view->pixel_h / scale_y;
         rect->h = view->pixel_h / scale_y;
     }
     }
@@ -3282,11 +3313,40 @@ bool SDL_GetRenderSafeArea(SDL_Renderer *renderer, SDL_Rect *rect)
 }
 }
 
 
 bool SDL_SetRenderClipRect(SDL_Renderer *renderer, const SDL_Rect *rect)
 bool SDL_SetRenderClipRect(SDL_Renderer *renderer, const SDL_Rect *rect)
+{
+    if (rect) {
+        SDL_FRect frect;
+        SDL_RectToFRect(rect, &frect);
+        return SDL_SetRenderClipRectFloat(renderer, &frect);
+    } else {
+        return SDL_SetRenderClipRectFloat(renderer, NULL);
+    }
+}
+
+bool SDL_GetRenderClipRect(SDL_Renderer *renderer, SDL_Rect *rect)
+{
+    if (rect) {
+        SDL_zerop(rect);
+    }
+
+    SDL_FRect frect;
+    if (SDL_GetRenderClipRectFloat(renderer, &frect)) {
+        rect->x = (int)SDL_floorf(frect.x);
+        rect->y = (int)SDL_floorf(frect.y);
+        rect->w = (int)SDL_ceilf(frect.w);
+        rect->h = (int)SDL_ceilf(frect.h);
+        return true;
+    } else {
+        return false;
+    }
+}
+
+bool SDL_SetRenderClipRectFloat(SDL_Renderer *renderer, const SDL_FRect *rect)
 {
 {
     CHECK_RENDERER_MAGIC(renderer, false);
     CHECK_RENDERER_MAGIC(renderer, false);
 
 
     SDL_RenderViewState *view = renderer->view;
     SDL_RenderViewState *view = renderer->view;
-    if (rect && rect->w >= 0 && rect->h >= 0) {
+    if (rect && rect->w >= 0.0f && rect->h >= 0.0f) {
         view->clipping_enabled = true;
         view->clipping_enabled = true;
         SDL_copyp(&view->clip_rect, rect);
         SDL_copyp(&view->clip_rect, rect);
     } else {
     } else {
@@ -3298,7 +3358,7 @@ bool SDL_SetRenderClipRect(SDL_Renderer *renderer, const SDL_Rect *rect)
     return QueueCmdSetClipRect(renderer);
     return QueueCmdSetClipRect(renderer);
 }
 }
 
 
-bool SDL_GetRenderClipRect(SDL_Renderer *renderer, SDL_Rect *rect)
+bool SDL_GetRenderClipRectFloat(SDL_Renderer *renderer, SDL_FRect *rect)
 {
 {
     if (rect) {
     if (rect) {
         SDL_zerop(rect);
         SDL_zerop(rect);

+ 2 - 2
src/render/SDL_sysrender.h

@@ -52,9 +52,9 @@ typedef struct SDL_RenderViewState
 {
 {
     int pixel_w;
     int pixel_w;
     int pixel_h;
     int pixel_h;
-    SDL_Rect viewport;
+    SDL_FRect viewport;
     SDL_Rect pixel_viewport;
     SDL_Rect pixel_viewport;
-    SDL_Rect clip_rect;
+    SDL_FRect clip_rect;
     SDL_Rect pixel_clip_rect;
     SDL_Rect pixel_clip_rect;
     bool clipping_enabled;
     bool clipping_enabled;
     SDL_FPoint scale;
     SDL_FPoint scale;