فهرست منبع

render: Add floating point versions of various draw APIs.

Ryan C. Gordon 6 سال پیش
والد
کامیت
8340b0f0e2
6فایلهای تغییر یافته به همراه643 افزوده شده و 76 حذف شده
  1. 28 2
      include/SDL_rect.h
  2. 142 0
      include/SDL_render.h
  3. 10 0
      src/dynapi/SDL_dynapi_overrides.h
  4. 10 0
      src/dynapi/SDL_dynapi_procs.h
  5. 453 60
      src/render/SDL_render.c
  6. 0 14
      src/render/SDL_sysrender.h

+ 28 - 2
include/SDL_rect.h

@@ -40,7 +40,7 @@ extern "C" {
 #endif
 
 /**
- *  \brief  The structure that defines a point
+ *  \brief  The structure that defines a point (integer)
  *
  *  \sa SDL_EnclosePoints
  *  \sa SDL_PointInRect
@@ -52,7 +52,20 @@ typedef struct SDL_Point
 } SDL_Point;
 
 /**
- *  \brief A rectangle, with the origin at the upper left.
+ *  \brief  The structure that defines a point (floating point)
+ *
+ *  \sa SDL_EnclosePoints
+ *  \sa SDL_PointInRect
+ */
+typedef struct SDL_FPoint
+{
+    float x;
+    float y;
+} SDL_FPoint;
+
+
+/**
+ *  \brief A rectangle, with the origin at the upper left (integer).
  *
  *  \sa SDL_RectEmpty
  *  \sa SDL_RectEquals
@@ -67,6 +80,19 @@ typedef struct SDL_Rect
     int w, h;
 } SDL_Rect;
 
+
+/**
+ *  \brief A rectangle, with the origin at the upper left (floating point).
+ */
+typedef struct SDL_FRect
+{
+    float x;
+    float y;
+    float w;
+    float h;
+} SDL_FRect;
+
+
 /**
  *  \brief Returns true if point resides inside a rectangle.
  */

+ 142 - 0
include/SDL_render.h

@@ -835,6 +835,148 @@ extern DECLSPEC int SDLCALL SDL_RenderCopyEx(SDL_Renderer * renderer,
                                            const SDL_Point *center,
                                            const SDL_RendererFlip flip);
 
+
+/**
+ *  \brief Draw a point on the current rendering target.
+ *
+ *  \param renderer The renderer which should draw a point.
+ *  \param x The x coordinate of the point.
+ *  \param y The y coordinate of the point.
+ *
+ *  \return 0 on success, or -1 on error
+ */
+extern DECLSPEC int SDLCALL SDL_RenderDrawPointF(SDL_Renderer * renderer,
+                                                 float x, float y);
+
+/**
+ *  \brief Draw multiple points on the current rendering target.
+ *
+ *  \param renderer The renderer which should draw multiple points.
+ *  \param points The points to draw
+ *  \param count The number of points to draw
+ *
+ *  \return 0 on success, or -1 on error
+ */
+extern DECLSPEC int SDLCALL SDL_RenderDrawPointsF(SDL_Renderer * renderer,
+                                                  const SDL_FPoint * points,
+                                                  int count);
+
+/**
+ *  \brief Draw a line on the current rendering target.
+ *
+ *  \param renderer The renderer which should draw a line.
+ *  \param x1 The x coordinate of the start point.
+ *  \param y1 The y coordinate of the start point.
+ *  \param x2 The x coordinate of the end point.
+ *  \param y2 The y coordinate of the end point.
+ *
+ *  \return 0 on success, or -1 on error
+ */
+extern DECLSPEC int SDLCALL SDL_RenderDrawLineF(SDL_Renderer * renderer,
+                                                float x1, float y1, float x2, float y2);
+
+/**
+ *  \brief Draw a series of connected lines on the current rendering target.
+ *
+ *  \param renderer The renderer which should draw multiple lines.
+ *  \param points The points along the lines
+ *  \param count The number of points, drawing count-1 lines
+ *
+ *  \return 0 on success, or -1 on error
+ */
+extern DECLSPEC int SDLCALL SDL_RenderDrawLinesF(SDL_Renderer * renderer,
+                                                const SDL_FPoint * points,
+                                                int count);
+
+/**
+ *  \brief Draw a rectangle on the current rendering target.
+ *
+ *  \param renderer The renderer which should draw a rectangle.
+ *  \param rect A pointer to the destination rectangle, or NULL to outline the entire rendering target.
+ *
+ *  \return 0 on success, or -1 on error
+ */
+extern DECLSPEC int SDLCALL SDL_RenderDrawRectF(SDL_Renderer * renderer,
+                                               const SDL_FRect * rect);
+
+/**
+ *  \brief Draw some number of rectangles on the current rendering target.
+ *
+ *  \param renderer The renderer which should draw multiple rectangles.
+ *  \param rects A pointer to an array of destination rectangles.
+ *  \param count The number of rectangles.
+ *
+ *  \return 0 on success, or -1 on error
+ */
+extern DECLSPEC int SDLCALL SDL_RenderDrawRectsF(SDL_Renderer * renderer,
+                                                 const SDL_FRect * rects,
+                                                 int count);
+
+/**
+ *  \brief Fill a rectangle on the current rendering target with the drawing color.
+ *
+ *  \param renderer The renderer which should fill a rectangle.
+ *  \param rect A pointer to the destination rectangle, or NULL for the entire
+ *              rendering target.
+ *
+ *  \return 0 on success, or -1 on error
+ */
+extern DECLSPEC int SDLCALL SDL_RenderFillRectF(SDL_Renderer * renderer,
+                                                const SDL_FRect * rect);
+
+/**
+ *  \brief Fill some number of rectangles on the current rendering target with the drawing color.
+ *
+ *  \param renderer The renderer which should fill multiple rectangles.
+ *  \param rects A pointer to an array of destination rectangles.
+ *  \param count The number of rectangles.
+ *
+ *  \return 0 on success, or -1 on error
+ */
+extern DECLSPEC int SDLCALL SDL_RenderFillRectsF(SDL_Renderer * renderer,
+                                                 const SDL_FRect * rects,
+                                                 int count);
+
+/**
+ *  \brief Copy a portion of the texture to the current rendering target.
+ *
+ *  \param renderer The renderer which should copy parts of a texture.
+ *  \param texture The source texture.
+ *  \param srcrect   A pointer to the source rectangle, or NULL for the entire
+ *                   texture.
+ *  \param dstrect   A pointer to the destination rectangle, or NULL for the
+ *                   entire rendering target.
+ *
+ *  \return 0 on success, or -1 on error
+ */
+extern DECLSPEC int SDLCALL SDL_RenderCopyF(SDL_Renderer * renderer,
+                                            SDL_Texture * texture,
+                                            const SDL_Rect * srcrect,
+                                            const SDL_FRect * dstrect);
+
+/**
+ *  \brief Copy a portion of the source texture to the current rendering target, rotating it by angle around the given center
+ *
+ *  \param renderer The renderer which should copy parts of a texture.
+ *  \param texture The source texture.
+ *  \param srcrect   A pointer to the source rectangle, or NULL for the entire
+ *                   texture.
+ *  \param dstrect   A pointer to the destination rectangle, or NULL for the
+ *                   entire rendering target.
+ *  \param angle    An angle in degrees that indicates the rotation that will be applied to dstrect, rotating it in a clockwise direction
+ *  \param center   A pointer to a point indicating the point around which dstrect will be rotated (if NULL, rotation will be done around dstrect.w/2, dstrect.h/2).
+ *  \param flip     An SDL_RendererFlip value stating which flipping actions should be performed on the texture
+ *
+ *  \return 0 on success, or -1 on error
+ */
+extern DECLSPEC int SDLCALL SDL_RenderCopyExF(SDL_Renderer * renderer,
+                                            SDL_Texture * texture,
+                                            const SDL_Rect * srcrect,
+                                            const SDL_FRect * dstrect,
+                                            const double angle,
+                                            const SDL_FPoint *center,
+                                            const SDL_RendererFlip flip);
+
 /**
  *  \brief Read pixels from the current rendering target.
  *

+ 10 - 0
src/dynapi/SDL_dynapi_overrides.h

@@ -697,3 +697,13 @@
 #define SDL_IsTablet SDL_IsTablet_REAL
 #define SDL_GetDisplayOrientation SDL_GetDisplayOrientation_REAL
 #define SDL_RenderFlush SDL_RenderFlush_REAL
+#define SDL_RenderDrawPointF SDL_RenderDrawPointF_REAL
+#define SDL_RenderDrawPointsF SDL_RenderDrawPointsF_REAL
+#define SDL_RenderDrawLineF SDL_RenderDrawLineF_REAL
+#define SDL_RenderDrawLinesF SDL_RenderDrawLinesF_REAL
+#define SDL_RenderDrawRectF SDL_RenderDrawRectF_REAL
+#define SDL_RenderDrawRectsF SDL_RenderDrawRectsF_REAL
+#define SDL_RenderFillRectF SDL_RenderFillRectF_REAL
+#define SDL_RenderFillRectsF SDL_RenderFillRectsF_REAL
+#define SDL_RenderCopyF SDL_RenderCopyF_REAL
+#define SDL_RenderCopyExF SDL_RenderCopyExF_REAL

+ 10 - 0
src/dynapi/SDL_dynapi_procs.h

@@ -739,3 +739,13 @@ SDL_DYNAPI_PROC(void,SDL_SensorUpdate,(void),(),)
 SDL_DYNAPI_PROC(SDL_bool,SDL_IsTablet,(void),(),return)
 SDL_DYNAPI_PROC(SDL_DisplayOrientation,SDL_GetDisplayOrientation,(int a),(a),return)
 SDL_DYNAPI_PROC(int,SDL_RenderFlush,(SDL_Renderer *a),(a),return)
+SDL_DYNAPI_PROC(int,SDL_RenderDrawPointF,(SDL_Renderer *a, float b, float c),(a,b,c),return)
+SDL_DYNAPI_PROC(int,SDL_RenderDrawPointsF,(SDL_Renderer *a, const SDL_FPoint *b, int c),(a,b,c),return)
+SDL_DYNAPI_PROC(int,SDL_RenderDrawLineF,(SDL_Renderer *a, float b, float c, float d, float e),(a,b,c,d,e),return)
+SDL_DYNAPI_PROC(int,SDL_RenderDrawLinesF,(SDL_Renderer *a, const SDL_FPoint *b, int c),(a,b,c),return)
+SDL_DYNAPI_PROC(int,SDL_RenderDrawRectF,(SDL_Renderer *a, const SDL_FRect *b),(a,b),return)
+SDL_DYNAPI_PROC(int,SDL_RenderDrawRectsF,(SDL_Renderer *a, const SDL_FRect *b, int c),(a,b,c),return)
+SDL_DYNAPI_PROC(int,SDL_RenderFillRectF,(SDL_Renderer *a, const SDL_FRect *b),(a,b),return)
+SDL_DYNAPI_PROC(int,SDL_RenderFillRectsF,(SDL_Renderer *a, const SDL_FRect *b, int c),(a,b,c),return)
+SDL_DYNAPI_PROC(int,SDL_RenderCopyF,(SDL_Renderer *a, SDL_Texture *b, const SDL_Rect *c, const SDL_FRect *d),(a,b,c,d),return)
+SDL_DYNAPI_PROC(int,SDL_RenderCopyExF,(SDL_Renderer *a, SDL_Texture *b, const SDL_Rect *c, const SDL_FRect *d, const double e, const SDL_FPoint *f, const SDL_RendererFlip g),(a,b,c,d,e,f,g),return)

+ 453 - 60
src/render/SDL_render.c

@@ -2157,31 +2157,37 @@ SDL_RenderClear(SDL_Renderer * renderer)
     return retval < 0 ? retval : FlushRenderCommandsIfNotBatching(renderer);
 }
 
+
+/* !!! FIXME: delete all the duplicate code for the integer versions in 2.1,
+   !!! FIXME:  making the floating point versions the only available APIs. */
+
 int
 SDL_RenderDrawPoint(SDL_Renderer * renderer, int x, int y)
 {
-    SDL_Point point;
-    int retval;
+    const SDL_FPoint fpoint = { (float) x, (float) y };
+    return SDL_RenderDrawPointsF(renderer, &fpoint, 1);
+}
 
-    point.x = x;
-    point.y = y;
-    retval = SDL_RenderDrawPoints(renderer, &point, 1);
-    return retval < 0 ? retval : FlushRenderCommandsIfNotBatching(renderer);
+int
+SDL_RenderDrawPointF(SDL_Renderer * renderer, float x, float y)
+{
+    const SDL_FPoint fpoint = { x, y };
+    return SDL_RenderDrawPointsF(renderer, &fpoint, 1);
 }
 
 static int
 RenderDrawPointsWithRects(SDL_Renderer * renderer,
-                     const SDL_Point * points, int count)
+                          const SDL_Point * points, const int count)
 {
-    SDL_FRect *frects;
-    int i;
     int retval = -1;
     SDL_bool isstack;
+    SDL_FRect *frects = SDL_small_alloc(SDL_FRect, count, &isstack);
+    int i;
 
-    frects = SDL_small_alloc(SDL_FRect, count, &isstack);
     if (!frects) {
         return SDL_OutOfMemory();
     }
+
     for (i = 0; i < count; ++i) {
         frects[i].x = points[i].x * renderer->scale.x;
         frects[i].y = points[i].y * renderer->scale.y;
@@ -2239,21 +2245,148 @@ SDL_RenderDrawPoints(SDL_Renderer * renderer,
     return retval < 0 ? retval : FlushRenderCommandsIfNotBatching(renderer);
 }
 
+static int
+RenderDrawPointsWithRectsF(SDL_Renderer * renderer,
+                           const SDL_FPoint * fpoints, const int count)
+{
+    int retval = -1;
+    SDL_bool isstack;
+    SDL_FRect *frects = SDL_small_alloc(SDL_FRect, count, &isstack);
+    int i;
+
+    if (!frects) {
+        return SDL_OutOfMemory();
+    }
+
+    for (i = 0; i < count; ++i) {
+        frects[i].x = fpoints[i].x * renderer->scale.x;
+        frects[i].y = fpoints[i].y * renderer->scale.y;
+        frects[i].w = renderer->scale.x;
+        frects[i].h = renderer->scale.y;
+    }
+
+    retval = QueueCmdFillRects(renderer, frects, count);
+
+    SDL_small_free(frects, isstack);
+
+    return retval < 0 ? retval : FlushRenderCommandsIfNotBatching(renderer);
+}
+
+int
+SDL_RenderDrawPointsF(SDL_Renderer * renderer,
+                      const SDL_FPoint * points, int count)
+{
+    SDL_FPoint *fpoints;
+    int i;
+    int retval;
+    SDL_bool isstack;
+
+    CHECK_RENDERER_MAGIC(renderer, -1);
+
+    if (!points) {
+        return SDL_SetError("SDL_RenderDrawFPoints(): Passed NULL points");
+    }
+    if (count < 1) {
+        return 0;
+    }
+
+    /* Don't draw while we're hidden */
+    if (renderer->hidden) {
+        return 0;
+    }
+
+    if (renderer->scale.x != 1.0f || renderer->scale.y != 1.0f) {
+        return RenderDrawPointsWithRectsF(renderer, points, count);
+    }
+
+    fpoints = SDL_small_alloc(SDL_FPoint, count, &isstack);
+    if (!fpoints) {
+        return SDL_OutOfMemory();
+    }
+    for (i = 0; i < count; ++i) {
+        fpoints[i].x = points[i].x * renderer->scale.x;
+        fpoints[i].y = points[i].y * renderer->scale.y;
+    }
+
+    retval = QueueCmdDrawPoints(renderer, fpoints, count);
+
+    SDL_small_free(fpoints, isstack);
+
+    return retval < 0 ? retval : FlushRenderCommandsIfNotBatching(renderer);
+}
+
 int
 SDL_RenderDrawLine(SDL_Renderer * renderer, int x1, int y1, int x2, int y2)
 {
-    SDL_Point points[2];
+    const SDL_FPoint points[2] = { { (float) x1, (float) y1 }, { (float) x2, (float) y2 } };
+    return SDL_RenderDrawLinesF(renderer, points, 2);
+}
 
-    points[0].x = x1;
-    points[0].y = y1;
-    points[1].x = x2;
-    points[1].y = y2;
-    return SDL_RenderDrawLines(renderer, points, 2);
+int
+SDL_RenderDrawLineF(SDL_Renderer * renderer, float x1, float y1, float x2, float y2)
+{
+    const SDL_FPoint points[2] = { { x1, y1 }, { x2, y2 } };
+    return SDL_RenderDrawLinesF(renderer, points, 2);
 }
 
 static int
 RenderDrawLinesWithRects(SDL_Renderer * renderer,
-                     const SDL_Point * points, int count)
+                     const SDL_Point * points, const int count)
+{
+    SDL_FRect *frect;
+    SDL_FRect *frects;
+    SDL_FPoint fpoints[2];
+    int i, nrects = 0;
+    int retval = 0;
+    SDL_bool isstack;
+
+    frects = SDL_small_alloc(SDL_FRect, count-1, &isstack);
+    if (!frects) {
+        return SDL_OutOfMemory();
+    }
+
+    for (i = 0; i < count-1; ++i) {
+        if (points[i].x == points[i+1].x) {
+            const int minY = SDL_min(points[i].y, points[i+1].y);
+            const int maxY = SDL_max(points[i].y, points[i+1].y);
+
+            frect = &frects[nrects++];
+            frect->x = points[i].x * renderer->scale.x;
+            frect->y = minY * renderer->scale.y;
+            frect->w = renderer->scale.x;
+            frect->h = (maxY - minY + 1) * renderer->scale.y;
+        } else if (points[i].y == points[i+1].y) {
+            const int minX = SDL_min(points[i].x, points[i+1].x);
+            const int maxX = SDL_max(points[i].x, points[i+1].x);
+
+            frect = &frects[nrects++];
+            frect->x = minX * renderer->scale.x;
+            frect->y = points[i].y * renderer->scale.y;
+            frect->w = (maxX - minX + 1) * renderer->scale.x;
+            frect->h = renderer->scale.y;
+        } else {
+            /* FIXME: We can't use a rect for this line... */
+            fpoints[0].x = points[i].x * renderer->scale.x;
+            fpoints[0].y = points[i].y * renderer->scale.y;
+            fpoints[1].x = points[i+1].x * renderer->scale.x;
+            fpoints[1].y = points[i+1].y * renderer->scale.y;
+            retval += QueueCmdDrawLines(renderer, fpoints, 2);
+        }
+    }
+
+    retval += QueueCmdFillRects(renderer, frects, nrects);
+
+    SDL_small_free(frects, isstack);
+
+    if (retval < 0) {
+        retval = -1;
+    }
+    return retval < 0 ? retval : FlushRenderCommandsIfNotBatching(renderer);
+}
+
+static int
+RenderDrawLinesWithRectsF(SDL_Renderer * renderer,
+                          const SDL_FPoint * points, const int count)
 {
     SDL_FRect *frect;
     SDL_FRect *frects;
@@ -2349,20 +2482,83 @@ SDL_RenderDrawLines(SDL_Renderer * renderer,
     return retval < 0 ? retval : FlushRenderCommandsIfNotBatching(renderer);
 }
 
+int
+SDL_RenderDrawLinesF(SDL_Renderer * renderer,
+                     const SDL_FPoint * points, int count)
+{
+    SDL_FPoint *fpoints;
+    int i;
+    int retval;
+    SDL_bool isstack;
+
+    CHECK_RENDERER_MAGIC(renderer, -1);
+
+    if (!points) {
+        return SDL_SetError("SDL_RenderDrawLines(): Passed NULL points");
+    }
+    if (count < 2) {
+        return 0;
+    }
+
+    /* Don't draw while we're hidden */
+    if (renderer->hidden) {
+        return 0;
+    }
+
+    if (renderer->scale.x != 1.0f || renderer->scale.y != 1.0f) {
+        return RenderDrawLinesWithRectsF(renderer, points, count);
+    }
+
+    fpoints = SDL_small_alloc(SDL_FPoint, count, &isstack);
+    if (!fpoints) {
+        return SDL_OutOfMemory();
+    }
+    for (i = 0; i < count; ++i) {
+        fpoints[i].x = points[i].x * renderer->scale.x;
+        fpoints[i].y = points[i].y * renderer->scale.y;
+    }
+
+    retval = QueueCmdDrawLines(renderer, fpoints, count);
+
+    SDL_small_free(fpoints, isstack);
+
+    return retval < 0 ? retval : FlushRenderCommandsIfNotBatching(renderer);
+}
+
 int
 SDL_RenderDrawRect(SDL_Renderer * renderer, const SDL_Rect * rect)
 {
-    SDL_Rect full_rect;
-    SDL_Point points[5];
+    SDL_FRect frect;
+    SDL_FRect *prect = NULL;
+
+    if (rect) {
+        frect.x = (float) rect->x;
+        frect.y = (float) rect->y;
+        frect.w = (float) rect->w;
+        frect.h = (float) rect->h;
+        prect = &frect;
+    }
+
+    return SDL_RenderDrawRectF(renderer, prect);
+}
+
+int
+SDL_RenderDrawRectF(SDL_Renderer * renderer, const SDL_FRect * rect)
+{
+    SDL_FRect frect;
+    SDL_FPoint points[5];
 
     CHECK_RENDERER_MAGIC(renderer, -1);
 
     /* If 'rect' == NULL, then outline the whole surface */
     if (!rect) {
-        SDL_RenderGetViewport(renderer, &full_rect);
-        full_rect.x = 0;
-        full_rect.y = 0;
-        rect = &full_rect;
+        SDL_Rect r;
+        SDL_RenderGetViewport(renderer, &r);
+        frect.x = 0.0f;
+        frect.y = 0.0f;
+        frect.w = (float) r.w;
+        frect.h = (float) r.h;
+        rect = &frect;
     }
 
     points[0].x = rect->x;
@@ -2375,7 +2571,7 @@ SDL_RenderDrawRect(SDL_Renderer * renderer, const SDL_Rect * rect)
     points[3].y = rect->y+rect->h-1;
     points[4].x = rect->x;
     points[4].y = rect->y;
-    return SDL_RenderDrawLines(renderer, points, 5);
+    return SDL_RenderDrawLinesF(renderer, points, 5);
 }
 
 int
@@ -2406,21 +2602,76 @@ SDL_RenderDrawRects(SDL_Renderer * renderer,
     return 0;
 }
 
+int
+SDL_RenderDrawRectsF(SDL_Renderer * renderer,
+                     const SDL_FRect * rects, int count)
+{
+    int i;
+
+    CHECK_RENDERER_MAGIC(renderer, -1);
+
+    if (!rects) {
+        return SDL_SetError("SDL_RenderDrawRects(): Passed NULL rects");
+    }
+    if (count < 1) {
+        return 0;
+    }
+
+    /* Don't draw while we're hidden */
+    if (renderer->hidden) {
+        return 0;
+    }
+
+    for (i = 0; i < count; ++i) {
+        if (SDL_RenderDrawRectF(renderer, &rects[i]) < 0) {
+            return -1;
+        }
+    }
+    return 0;
+}
+
 int
 SDL_RenderFillRect(SDL_Renderer * renderer, const SDL_Rect * rect)
 {
-    SDL_Rect full_rect = { 0, 0, 0, 0 };
+    SDL_FRect frect;
+
+    CHECK_RENDERER_MAGIC(renderer, -1);
+
+    /* If 'rect' == NULL, then outline the whole surface */
+    if (rect) {
+        frect.x = (float) rect->x;
+        frect.y = (float) rect->y;
+        frect.w = (float) rect->w;
+        frect.h = (float) rect->h;
+    } else {
+        SDL_Rect r;
+        SDL_RenderGetViewport(renderer, &r);
+        frect.x = 0.0f;
+        frect.y = 0.0f;
+        frect.w = (float) r.w;
+        frect.h = (float) r.h;
+    }
+    return SDL_RenderFillRectsF(renderer, &frect, 1);
+}
+
+int
+SDL_RenderFillRectF(SDL_Renderer * renderer, const SDL_FRect * rect)
+{
+    SDL_FRect frect;
 
     CHECK_RENDERER_MAGIC(renderer, -1);
 
     /* If 'rect' == NULL, then outline the whole surface */
     if (!rect) {
-        SDL_RenderGetViewport(renderer, &full_rect);
-        full_rect.x = 0;
-        full_rect.y = 0;
-        rect = &full_rect;
+        SDL_Rect r;
+        SDL_RenderGetViewport(renderer, &r);
+        frect.x = 0.0f;
+        frect.y = 0.0f;
+        frect.w = (float) r.w;
+        frect.h = (float) r.h;
+        rect = &frect;
     }
-    return SDL_RenderFillRects(renderer, rect, 1);
+    return SDL_RenderFillRectsF(renderer, rect, 1);
 }
 
 int
@@ -2464,13 +2715,124 @@ SDL_RenderFillRects(SDL_Renderer * renderer,
     return retval < 0 ? retval : FlushRenderCommandsIfNotBatching(renderer);
 }
 
+int
+SDL_RenderFillRectsF(SDL_Renderer * renderer,
+                     const SDL_FRect * rects, int count)
+{
+    SDL_FRect *frects;
+    int i;
+    int retval;
+    SDL_bool isstack;
+
+    CHECK_RENDERER_MAGIC(renderer, -1);
+
+    if (!rects) {
+        return SDL_SetError("SDL_RenderFillFRects(): Passed NULL rects");
+    }
+    if (count < 1) {
+        return 0;
+    }
+
+    /* Don't draw while we're hidden */
+    if (renderer->hidden) {
+        return 0;
+    }
+
+    frects = SDL_small_alloc(SDL_FRect, count, &isstack);
+    if (!frects) {
+        return SDL_OutOfMemory();
+    }
+    for (i = 0; i < count; ++i) {
+        frects[i].x = rects[i].x * renderer->scale.x;
+        frects[i].y = rects[i].y * renderer->scale.y;
+        frects[i].w = rects[i].w * renderer->scale.x;
+        frects[i].h = rects[i].h * renderer->scale.y;
+    }
+
+    retval = QueueCmdFillRects(renderer, frects, count);
+
+    SDL_small_free(frects, isstack);
+
+    return retval < 0 ? retval : FlushRenderCommandsIfNotBatching(renderer);
+}
+
+/* !!! FIXME: move this to a public API if we want to do float versions of all of these later */
+SDL_FORCE_INLINE SDL_bool SDL_FRectEmpty(const SDL_FRect *r)
+{
+    return ((!r) || (r->w <= 0.0f) || (r->h <= 0.0f)) ? SDL_TRUE : SDL_FALSE;
+}
+
+/* !!! FIXME: move this to a public API if we want to do float versions of all of these later */
+static SDL_bool
+SDL_HasIntersectionF(const SDL_FRect * A, const SDL_FRect * B)
+{
+    float Amin, Amax, Bmin, Bmax;
+
+    if (!A) {
+        SDL_InvalidParamError("A");
+        return SDL_FALSE;
+    }
+
+    if (!B) {
+        SDL_InvalidParamError("B");
+        return SDL_FALSE;
+    }
+
+    /* Special cases for empty rects */
+    if (SDL_FRectEmpty(A) || SDL_FRectEmpty(B)) {
+        return SDL_FALSE;
+    }
+
+    /* Horizontal intersection */
+    Amin = A->x;
+    Amax = Amin + A->w;
+    Bmin = B->x;
+    Bmax = Bmin + B->w;
+    if (Bmin > Amin)
+        Amin = Bmin;
+    if (Bmax < Amax)
+        Amax = Bmax;
+    if (Amax <= Amin)
+        return SDL_FALSE;
+
+    /* Vertical intersection */
+    Amin = A->y;
+    Amax = Amin + A->h;
+    Bmin = B->y;
+    Bmax = Bmin + B->h;
+    if (Bmin > Amin)
+        Amin = Bmin;
+    if (Bmax < Amax)
+        Amax = Bmax;
+    if (Amax <= Amin)
+        return SDL_FALSE;
+
+    return SDL_TRUE;
+}
+
 int
 SDL_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
                const SDL_Rect * srcrect, const SDL_Rect * dstrect)
 {
-    SDL_Rect real_srcrect = { 0, 0, 0, 0 };
-    SDL_Rect real_dstrect = { 0, 0, 0, 0 };
-    SDL_FRect frect;
+    SDL_FRect dstfrect;
+    SDL_FRect *pdstfrect = NULL;
+    if (dstrect) {
+        dstfrect.x = (float) dstrect->x;
+        dstfrect.y = (float) dstrect->y;
+        dstfrect.w = (float) dstrect->w;
+        dstfrect.h = (float) dstrect->h;
+        pdstfrect = &dstfrect;
+    }
+    return SDL_RenderCopyF(renderer, texture, srcrect, pdstfrect);
+}
+
+int
+SDL_RenderCopyF(SDL_Renderer * renderer, SDL_Texture * texture,
+                const SDL_Rect * srcrect, const SDL_FRect * dstrect)
+{
+    SDL_Rect real_srcrect;
+    SDL_FRect real_dstrect;
+    SDL_Rect r;
     int retval;
 
     CHECK_RENDERER_MAGIC(renderer, -1);
@@ -2495,11 +2857,13 @@ SDL_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
         }
     }
 
-    SDL_RenderGetViewport(renderer, &real_dstrect);
-    real_dstrect.x = 0;
-    real_dstrect.y = 0;
+    SDL_RenderGetViewport(renderer, &r);
+    real_dstrect.x = 0.0f;
+    real_dstrect.y = 0.0f;
+    real_dstrect.w = (float) r.w;
+    real_dstrect.h = (float) r.h;
     if (dstrect) {
-        if (!SDL_HasIntersection(dstrect, &real_dstrect)) {
+        if (!SDL_HasIntersectionF(dstrect, &real_dstrect)) {
             return 0;
         }
         real_dstrect = *dstrect;
@@ -2509,31 +2873,56 @@ SDL_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
         texture = texture->native;
     }
 
-    frect.x = real_dstrect.x * renderer->scale.x;
-    frect.y = real_dstrect.y * renderer->scale.y;
-    frect.w = real_dstrect.w * renderer->scale.x;
-    frect.h = real_dstrect.h * renderer->scale.y;
+    real_dstrect.x *= renderer->scale.x;
+    real_dstrect.y *= renderer->scale.y;
+    real_dstrect.w *= renderer->scale.x;
+    real_dstrect.h *= renderer->scale.y;
 
     texture->last_command_generation = renderer->render_command_generation;
 
-    retval = QueueCmdCopy(renderer, texture, &real_srcrect, &frect);
+    retval = QueueCmdCopy(renderer, texture, &real_srcrect, &real_dstrect);
     return retval < 0 ? retval : FlushRenderCommandsIfNotBatching(renderer);
 }
 
-
 int
 SDL_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture,
                const SDL_Rect * srcrect, const SDL_Rect * dstrect,
                const double angle, const SDL_Point *center, const SDL_RendererFlip flip)
 {
-    SDL_Rect real_srcrect = { 0, 0, 0, 0 };
-    SDL_Rect real_dstrect = { 0, 0, 0, 0 };
-    SDL_Point real_center;
-    SDL_FRect frect;
+    SDL_FRect dstfrect;
+    SDL_FRect *pdstfrect = NULL;
     SDL_FPoint fcenter;
+    SDL_FPoint *pfcenter = NULL;
+
+    if (dstrect) {
+        dstfrect.x = (float) dstrect->x;
+        dstfrect.y = (float) dstrect->y;
+        dstfrect.w = (float) dstrect->w;
+        dstfrect.h = (float) dstrect->h;
+        pdstfrect = &dstfrect;
+    }
+
+    if (center) {
+        fcenter.x = (float) center->x;
+        fcenter.y = (float) center->y;
+        pfcenter = &fcenter;
+    }
+
+    return SDL_RenderCopyExF(renderer, texture, srcrect, pdstfrect, angle, pfcenter, flip);
+}
+
+int
+SDL_RenderCopyExF(SDL_Renderer * renderer, SDL_Texture * texture,
+               const SDL_Rect * srcrect, const SDL_FRect * dstrect,
+               const double angle, const SDL_FPoint *center, const SDL_RendererFlip flip)
+{
+    SDL_Rect real_srcrect;
+    SDL_FRect real_dstrect;
+    SDL_FPoint real_center;
+    int retval;
 
     if (flip == SDL_FLIP_NONE && (int)(angle/360) == angle/360) { /* fast path when we don't need rotation or flipping */
-        return SDL_RenderCopy(renderer, texture, srcrect, dstrect);
+        return SDL_RenderCopyF(renderer, texture, srcrect, dstrect);
     }
 
     CHECK_RENDERER_MAGIC(renderer, -1);
@@ -2565,9 +2954,12 @@ SDL_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture,
     if (dstrect) {
         real_dstrect = *dstrect;
     } else {
-        SDL_RenderGetViewport(renderer, &real_dstrect);
-        real_dstrect.x = 0;
-        real_dstrect.y = 0;
+        SDL_Rect r;
+        SDL_RenderGetViewport(renderer, &r);
+        real_dstrect.x = 0.0f;
+        real_dstrect.y = 0.0f;
+        real_dstrect.w = (float) r.w;
+        real_dstrect.h = (float) r.h;
     }
 
     if (texture->native) {
@@ -2577,21 +2969,22 @@ SDL_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture,
     if (center) {
         real_center = *center;
     } else {
-        real_center.x = real_dstrect.w/2;
-        real_center.y = real_dstrect.h/2;
+        real_center.x = real_dstrect.w / 2.0f;
+        real_center.y = real_dstrect.h / 2.0f;
     }
 
-    frect.x = real_dstrect.x * renderer->scale.x;
-    frect.y = real_dstrect.y * renderer->scale.y;
-    frect.w = real_dstrect.w * renderer->scale.x;
-    frect.h = real_dstrect.h * renderer->scale.y;
+    real_dstrect.x *= renderer->scale.x;
+    real_dstrect.y *= renderer->scale.y;
+    real_dstrect.w *= renderer->scale.x;
+    real_dstrect.h *= renderer->scale.y;
 
-    fcenter.x = real_center.x * renderer->scale.x;
-    fcenter.y = real_center.y * renderer->scale.y;
+    real_center.x *= renderer->scale.x;
+    real_center.y *= renderer->scale.y;
 
     texture->last_command_generation = renderer->render_command_generation;
 
-    return QueueCmdCopyEx(renderer, texture, &real_srcrect, &frect, angle, &fcenter, flip);
+    retval = QueueCmdCopyEx(renderer, texture, &real_srcrect, &real_dstrect, angle, &real_center, flip);
+    return retval < 0 ? retval : FlushRenderCommandsIfNotBatching(renderer);
 }
 
 int

+ 0 - 14
src/render/SDL_sysrender.h

@@ -39,20 +39,6 @@ typedef enum
     SDL_ScaleModeBest
 } SDL_ScaleMode;
 
-typedef struct
-{
-    float x;
-    float y;
-} SDL_FPoint;
-
-typedef struct
-{
-    float x;
-    float y;
-    float w;
-    float h;
-} SDL_FRect;
-
 /* Define the SDL texture structure */
 struct SDL_Texture
 {