# SDL: Added floating point versions of cliprect and viewport render functions

**URL:** <https://discourse.libsdl.org/t/sdl-added-floating-point-versions-of-cliprect-and-viewport-render-functions/69311>\
**Category:** SDL Commits\
**Created:** [September 13, 2026, 6:46pm UTC](https://discourse.libsdl.org/t/sdl-added-floating-point-versions-of-cliprect-and-viewport-render-functions/69311 "2026-09-13T18:46:31Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![SDLPushPostBot](https://discourse.libsdl.org/user_avatar/discourse.libsdl.org/sdlpushpostbot/32/4370_2.png) [@SDLPushPostBot](https://discourse.libsdl.org/u/SDLPushPostBot)\
**Post date:** [September 13, 2026, 6:46pm UTC](https://discourse.libsdl.org/t/sdl-added-floating-point-versions-of-cliprect-and-viewport-render-functions/69311/1 "2026-09-13T18:46:31Z")

</div>

> <https://github.com/libsdl-org/SDL/commit/33b4a9d915947d2482366622fc4f97c944254775>
>
> Fixes https://github.com/libsdl-org/SDL/issues/14654

```diff
From 33b4a9d915947d2482366622fc4f97c944254775 Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Sun, 13 Sep 2026 11:32:31 -0700
Subject: [PATCH] Added floating point versions of cliprect and viewport render
 functions

Fixes https://github.com/libsdl-org/SDL/issues/14654
---
 include/SDL3/SDL_render.h | 97 ++++++++++++++++++++++++++++++
 src/dynapi/SDL_dynapi.exports | 4 ++
 src/dynapi/SDL_dynapi.sym | 4 ++
 src/dynapi/SDL_dynapi_overrides.h | 4 ++
 src/dynapi/SDL_dynapi_procs.h | 4 ++
 src/render/SDL_render.c | 98 +++++++++++++++++++++++++------
 src/render/SDL_sysrender.h | 4 +-
 7 files changed, 194 insertions(+), 21 deletions(-)

diff --git a/include/SDL3/SDL_render.h b/include/SDL3/SDL_render.h
index 579cea3dac0af..bb2a298139c3f 100644
--- a/include/SDL3/SDL_render.h
+++ b/include/SDL3/SDL_render.h
@@ -1823,6 +1823,7 @@ extern SDL_DECLSPEC bool SDLCALL SDL_ConvertEventToRenderCoordinates(SDL_Rendere
  *
  * \sa SDL_GetRenderViewport
  * \sa SDL_RenderViewportSet
+ * \sa SDL_SetRenderViewportFloat
  */
 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.
  *
+ * \sa SDL_GetRenderViewportFloat
  * \sa SDL_RenderViewportSet
  * \sa SDL_SetRenderViewport
  */
 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.
  *
@@ -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.
  *
  * \sa SDL_GetRenderViewport
+ * \sa SDL_GetRenderViewportFloat
  * \sa SDL_SetRenderViewport
+ * \sa SDL_SetRenderViewportFloat
  */
 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_RenderClipEnabled
+ * \sa SDL_SetRenderClipRectFloat
  */
 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.
  *
+ * \sa SDL_GetRenderClipRectFloat
  * \sa SDL_RenderClipEnabled
  * \sa SDL_SetRenderClipRect
  */
 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.
  *
@@ -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.
  *
  * \sa SDL_GetRenderClipRect
+ * \sa SDL_GetRenderClipRectFloat
  * \sa SDL_SetRenderClipRect
+ * \sa SDL_SetRenderClipRectFloat
  */
 extern SDL_DECLSPEC bool SDLCALL SDL_RenderClipEnabled(SDL_Renderer *renderer);
 
diff --git a/src/dynapi/SDL_dynapi.exports b/src/dynapi/SDL_dynapi.exports
index a06f0f21d6434..5d5df5d17c520 100644
--- a/src/dynapi/SDL_dynapi.exports
+++ b/src/dynapi/SDL_dynapi.exports
@@ -1307,3 +1307,7 @@ _SDL_SetJoystickSensorEnabled
 _SDL_JoystickSensorEnabled
 _SDL_GetJoystickSensorDataRate
 _SDL_GetJoystickSensorData
+_SDL_SetRenderViewportFloat
+_SDL_GetRenderViewportFloat
+_SDL_SetRenderClipRectFloat
+_SDL_GetRenderClipRectFloat
diff --git a/src/dynapi/SDL_dynapi.sym b/src/dynapi/SDL_dynapi.sym
index 6e0354148122d..63864e372b4d7 100644
--- a/src/dynapi/SDL_dynapi.sym
+++ b/src/dynapi/SDL_dynapi.sym
@@ -1308,6 +1308,10 @@ SDL3_0.0.0 {
     SDL_JoystickSensorEnabled;
     SDL_GetJoystickSensorDataRate;
     SDL_GetJoystickSensorData;
+ SDL_SetRenderViewportFloat;
+ SDL_GetRenderViewportFloat;
+ SDL_SetRenderClipRectFloat;
+ SDL_GetRenderClipRectFloat;
     # 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 1f8ba18a01e59..d8deffc20e275 100644
--- a/src/dynapi/SDL_dynapi_overrides.h
+++ b/src/dynapi/SDL_dynapi_overrides.h
@@ -1334,3 +1334,7 @@
 #define SDL_JoystickSensorEnabled SDL_JoystickSensorEnabled_REAL
 #define SDL_GetJoystickSensorDataRate SDL_GetJoystickSensorDataRate_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
diff --git a/src/dynapi/SDL_dynapi_procs.h b/src/dynapi/SDL_dynapi_procs.h
index 6bf988441a21b..cd2fc200a2784 100644
--- a/src/dynapi/SDL_dynapi_procs.h
+++ b/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(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_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)
diff --git a/src/render/SDL_render.c b/src/render/SDL_render.c
index 059eaf5f6d804..51516b6ef6975 100644
--- a/src/render/SDL_render.c
+++ b/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_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.y = 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->view.pixel_w = w;
     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.y = 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)
+{
+ 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);
 
     SDL_RenderViewState *view = renderer->view;
     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");
         }
         SDL_copyp(&view->viewport, rect);
     } 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);
 
     return QueueCmdSetViewport(renderer);
 }
 
-bool SDL_GetRenderViewport(SDL_Renderer *renderer, SDL_Rect *rect)
+bool SDL_GetRenderViewportFloat(SDL_Renderer *renderer, SDL_FRect *rect)
 {
     if (rect) {
         SDL_zerop(rect);
@@ -3190,15 +3221,15 @@ bool SDL_GetRenderViewport(SDL_Renderer *renderer, SDL_Rect *rect)
         const SDL_RenderViewState *view = renderer->view;
         rect->x = view->viewport.x;
         rect->y = view->viewport.y;
- if (view->viewport.w >= 0) {
+ if (view->viewport.w >= 0.0f) {
             rect->w = view->viewport.w;
         } 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;
         } else {
- rect->h = (int)SDL_ceilf(view->pixel_h / view->current_scale.y);
+ rect->h = view->pixel_h / view->current_scale.y;
         }
     }
     return true;
@@ -3209,7 +3240,7 @@ bool SDL_RenderViewportSet(SDL_Renderer *renderer)
     CHECK_RENDERER_MAGIC(renderer, false);
 
     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)
@@ -3221,14 +3252,14 @@ static void GetRenderViewportSize(SDL_Renderer *renderer, SDL_FRect *rect)
     rect->x = 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 {
         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 {
         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)
+{
+ 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);
 
     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;
         SDL_copyp(&view->clip_rect, rect);
     } else {
@@ -3298,7 +3358,7 @@ bool SDL_SetRenderClipRect(SDL_Renderer *renderer, const SDL_Rect *rect)
     return QueueCmdSetClipRect(renderer);
 }
 
-bool SDL_GetRenderClipRect(SDL_Renderer *renderer, SDL_Rect *rect)
+bool SDL_GetRenderClipRectFloat(SDL_Renderer *renderer, SDL_FRect *rect)
 {
     if (rect) {
         SDL_zerop(rect);
diff --git a/src/render/SDL_sysrender.h b/src/render/SDL_sysrender.h
index 6642fe693ab11..552999ad46bfc 100644
--- a/src/render/SDL_sysrender.h
+++ b/src/render/SDL_sysrender.h
@@ -52,9 +52,9 @@ typedef struct SDL_RenderViewState
 {
     int pixel_w;
     int pixel_h;
- SDL_Rect viewport;
+ SDL_FRect viewport;
     SDL_Rect pixel_viewport;
- SDL_Rect clip_rect;
+ SDL_FRect clip_rect;
     SDL_Rect pixel_clip_rect;
     bool clipping_enabled;
     SDL_FPoint scale;

```
