render: Add floating point versions of various draw APIs. SDL-ryan-batching-renderer
authorRyan C. Gordon <icculus@icculus.org>
Tue, 23 Oct 2018 01:34:03 -0400
branchSDL-ryan-batching-renderer
changeset 123522b1707cc57fc
parent 12351 3c003852825a
child 12367 8256aaaafe54
render: Add floating point versions of various draw APIs.
include/SDL_rect.h
include/SDL_render.h
src/dynapi/SDL_dynapi_overrides.h
src/dynapi/SDL_dynapi_procs.h
src/render/SDL_render.c
src/render/SDL_sysrender.h
     1.1 --- a/include/SDL_rect.h	Thu Oct 18 12:05:05 2018 -0400
     1.2 +++ b/include/SDL_rect.h	Tue Oct 23 01:34:03 2018 -0400
     1.3 @@ -40,7 +40,7 @@
     1.4  #endif
     1.5  
     1.6  /**
     1.7 - *  \brief  The structure that defines a point
     1.8 + *  \brief  The structure that defines a point (integer)
     1.9   *
    1.10   *  \sa SDL_EnclosePoints
    1.11   *  \sa SDL_PointInRect
    1.12 @@ -52,7 +52,20 @@
    1.13  } SDL_Point;
    1.14  
    1.15  /**
    1.16 - *  \brief A rectangle, with the origin at the upper left.
    1.17 + *  \brief  The structure that defines a point (floating point)
    1.18 + *
    1.19 + *  \sa SDL_EnclosePoints
    1.20 + *  \sa SDL_PointInRect
    1.21 + */
    1.22 +typedef struct SDL_FPoint
    1.23 +{
    1.24 +    float x;
    1.25 +    float y;
    1.26 +} SDL_FPoint;
    1.27 +
    1.28 +
    1.29 +/**
    1.30 + *  \brief A rectangle, with the origin at the upper left (integer).
    1.31   *
    1.32   *  \sa SDL_RectEmpty
    1.33   *  \sa SDL_RectEquals
    1.34 @@ -67,6 +80,19 @@
    1.35      int w, h;
    1.36  } SDL_Rect;
    1.37  
    1.38 +
    1.39 +/**
    1.40 + *  \brief A rectangle, with the origin at the upper left (floating point).
    1.41 + */
    1.42 +typedef struct SDL_FRect
    1.43 +{
    1.44 +    float x;
    1.45 +    float y;
    1.46 +    float w;
    1.47 +    float h;
    1.48 +} SDL_FRect;
    1.49 +
    1.50 +
    1.51  /**
    1.52   *  \brief Returns true if point resides inside a rectangle.
    1.53   */
     2.1 --- a/include/SDL_render.h	Thu Oct 18 12:05:05 2018 -0400
     2.2 +++ b/include/SDL_render.h	Tue Oct 23 01:34:03 2018 -0400
     2.3 @@ -835,6 +835,148 @@
     2.4                                             const SDL_Point *center,
     2.5                                             const SDL_RendererFlip flip);
     2.6  
     2.7 +
     2.8 +/**
     2.9 + *  \brief Draw a point on the current rendering target.
    2.10 + *
    2.11 + *  \param renderer The renderer which should draw a point.
    2.12 + *  \param x The x coordinate of the point.
    2.13 + *  \param y The y coordinate of the point.
    2.14 + *
    2.15 + *  \return 0 on success, or -1 on error
    2.16 + */
    2.17 +extern DECLSPEC int SDLCALL SDL_RenderDrawPointF(SDL_Renderer * renderer,
    2.18 +                                                 float x, float y);
    2.19 +
    2.20 +/**
    2.21 + *  \brief Draw multiple points on the current rendering target.
    2.22 + *
    2.23 + *  \param renderer The renderer which should draw multiple points.
    2.24 + *  \param points The points to draw
    2.25 + *  \param count The number of points to draw
    2.26 + *
    2.27 + *  \return 0 on success, or -1 on error
    2.28 + */
    2.29 +extern DECLSPEC int SDLCALL SDL_RenderDrawPointsF(SDL_Renderer * renderer,
    2.30 +                                                  const SDL_FPoint * points,
    2.31 +                                                  int count);
    2.32 +
    2.33 +/**
    2.34 + *  \brief Draw a line on the current rendering target.
    2.35 + *
    2.36 + *  \param renderer The renderer which should draw a line.
    2.37 + *  \param x1 The x coordinate of the start point.
    2.38 + *  \param y1 The y coordinate of the start point.
    2.39 + *  \param x2 The x coordinate of the end point.
    2.40 + *  \param y2 The y coordinate of the end point.
    2.41 + *
    2.42 + *  \return 0 on success, or -1 on error
    2.43 + */
    2.44 +extern DECLSPEC int SDLCALL SDL_RenderDrawLineF(SDL_Renderer * renderer,
    2.45 +                                                float x1, float y1, float x2, float y2);
    2.46 +
    2.47 +/**
    2.48 + *  \brief Draw a series of connected lines on the current rendering target.
    2.49 + *
    2.50 + *  \param renderer The renderer which should draw multiple lines.
    2.51 + *  \param points The points along the lines
    2.52 + *  \param count The number of points, drawing count-1 lines
    2.53 + *
    2.54 + *  \return 0 on success, or -1 on error
    2.55 + */
    2.56 +extern DECLSPEC int SDLCALL SDL_RenderDrawLinesF(SDL_Renderer * renderer,
    2.57 +                                                const SDL_FPoint * points,
    2.58 +                                                int count);
    2.59 +
    2.60 +/**
    2.61 + *  \brief Draw a rectangle on the current rendering target.
    2.62 + *
    2.63 + *  \param renderer The renderer which should draw a rectangle.
    2.64 + *  \param rect A pointer to the destination rectangle, or NULL to outline the entire rendering target.
    2.65 + *
    2.66 + *  \return 0 on success, or -1 on error
    2.67 + */
    2.68 +extern DECLSPEC int SDLCALL SDL_RenderDrawRectF(SDL_Renderer * renderer,
    2.69 +                                               const SDL_FRect * rect);
    2.70 +
    2.71 +/**
    2.72 + *  \brief Draw some number of rectangles on the current rendering target.
    2.73 + *
    2.74 + *  \param renderer The renderer which should draw multiple rectangles.
    2.75 + *  \param rects A pointer to an array of destination rectangles.
    2.76 + *  \param count The number of rectangles.
    2.77 + *
    2.78 + *  \return 0 on success, or -1 on error
    2.79 + */
    2.80 +extern DECLSPEC int SDLCALL SDL_RenderDrawRectsF(SDL_Renderer * renderer,
    2.81 +                                                 const SDL_FRect * rects,
    2.82 +                                                 int count);
    2.83 +
    2.84 +/**
    2.85 + *  \brief Fill a rectangle on the current rendering target with the drawing color.
    2.86 + *
    2.87 + *  \param renderer The renderer which should fill a rectangle.
    2.88 + *  \param rect A pointer to the destination rectangle, or NULL for the entire
    2.89 + *              rendering target.
    2.90 + *
    2.91 + *  \return 0 on success, or -1 on error
    2.92 + */
    2.93 +extern DECLSPEC int SDLCALL SDL_RenderFillRectF(SDL_Renderer * renderer,
    2.94 +                                                const SDL_FRect * rect);
    2.95 +
    2.96 +/**
    2.97 + *  \brief Fill some number of rectangles on the current rendering target with the drawing color.
    2.98 + *
    2.99 + *  \param renderer The renderer which should fill multiple rectangles.
   2.100 + *  \param rects A pointer to an array of destination rectangles.
   2.101 + *  \param count The number of rectangles.
   2.102 + *
   2.103 + *  \return 0 on success, or -1 on error
   2.104 + */
   2.105 +extern DECLSPEC int SDLCALL SDL_RenderFillRectsF(SDL_Renderer * renderer,
   2.106 +                                                 const SDL_FRect * rects,
   2.107 +                                                 int count);
   2.108 +
   2.109 +/**
   2.110 + *  \brief Copy a portion of the texture to the current rendering target.
   2.111 + *
   2.112 + *  \param renderer The renderer which should copy parts of a texture.
   2.113 + *  \param texture The source texture.
   2.114 + *  \param srcrect   A pointer to the source rectangle, or NULL for the entire
   2.115 + *                   texture.
   2.116 + *  \param dstrect   A pointer to the destination rectangle, or NULL for the
   2.117 + *                   entire rendering target.
   2.118 + *
   2.119 + *  \return 0 on success, or -1 on error
   2.120 + */
   2.121 +extern DECLSPEC int SDLCALL SDL_RenderCopyF(SDL_Renderer * renderer,
   2.122 +                                            SDL_Texture * texture,
   2.123 +                                            const SDL_Rect * srcrect,
   2.124 +                                            const SDL_FRect * dstrect);
   2.125 +
   2.126 +/**
   2.127 + *  \brief Copy a portion of the source texture to the current rendering target, rotating it by angle around the given center
   2.128 + *
   2.129 + *  \param renderer The renderer which should copy parts of a texture.
   2.130 + *  \param texture The source texture.
   2.131 + *  \param srcrect   A pointer to the source rectangle, or NULL for the entire
   2.132 + *                   texture.
   2.133 + *  \param dstrect   A pointer to the destination rectangle, or NULL for the
   2.134 + *                   entire rendering target.
   2.135 + *  \param angle    An angle in degrees that indicates the rotation that will be applied to dstrect, rotating it in a clockwise direction
   2.136 + *  \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).
   2.137 + *  \param flip     An SDL_RendererFlip value stating which flipping actions should be performed on the texture
   2.138 + *
   2.139 + *  \return 0 on success, or -1 on error
   2.140 + */
   2.141 +extern DECLSPEC int SDLCALL SDL_RenderCopyExF(SDL_Renderer * renderer,
   2.142 +                                            SDL_Texture * texture,
   2.143 +                                            const SDL_Rect * srcrect,
   2.144 +                                            const SDL_FRect * dstrect,
   2.145 +                                            const double angle,
   2.146 +                                            const SDL_FPoint *center,
   2.147 +                                            const SDL_RendererFlip flip);
   2.148 +
   2.149  /**
   2.150   *  \brief Read pixels from the current rendering target.
   2.151   *
     3.1 --- a/src/dynapi/SDL_dynapi_overrides.h	Thu Oct 18 12:05:05 2018 -0400
     3.2 +++ b/src/dynapi/SDL_dynapi_overrides.h	Tue Oct 23 01:34:03 2018 -0400
     3.3 @@ -697,3 +697,13 @@
     3.4  #define SDL_IsTablet SDL_IsTablet_REAL
     3.5  #define SDL_GetDisplayOrientation SDL_GetDisplayOrientation_REAL
     3.6  #define SDL_RenderFlush SDL_RenderFlush_REAL
     3.7 +#define SDL_RenderDrawPointF SDL_RenderDrawPointF_REAL
     3.8 +#define SDL_RenderDrawPointsF SDL_RenderDrawPointsF_REAL
     3.9 +#define SDL_RenderDrawLineF SDL_RenderDrawLineF_REAL
    3.10 +#define SDL_RenderDrawLinesF SDL_RenderDrawLinesF_REAL
    3.11 +#define SDL_RenderDrawRectF SDL_RenderDrawRectF_REAL
    3.12 +#define SDL_RenderDrawRectsF SDL_RenderDrawRectsF_REAL
    3.13 +#define SDL_RenderFillRectF SDL_RenderFillRectF_REAL
    3.14 +#define SDL_RenderFillRectsF SDL_RenderFillRectsF_REAL
    3.15 +#define SDL_RenderCopyF SDL_RenderCopyF_REAL
    3.16 +#define SDL_RenderCopyExF SDL_RenderCopyExF_REAL
     4.1 --- a/src/dynapi/SDL_dynapi_procs.h	Thu Oct 18 12:05:05 2018 -0400
     4.2 +++ b/src/dynapi/SDL_dynapi_procs.h	Tue Oct 23 01:34:03 2018 -0400
     4.3 @@ -739,3 +739,13 @@
     4.4  SDL_DYNAPI_PROC(SDL_bool,SDL_IsTablet,(void),(),return)
     4.5  SDL_DYNAPI_PROC(SDL_DisplayOrientation,SDL_GetDisplayOrientation,(int a),(a),return)
     4.6  SDL_DYNAPI_PROC(int,SDL_RenderFlush,(SDL_Renderer *a),(a),return)
     4.7 +SDL_DYNAPI_PROC(int,SDL_RenderDrawPointF,(SDL_Renderer *a, float b, float c),(a,b,c),return)
     4.8 +SDL_DYNAPI_PROC(int,SDL_RenderDrawPointsF,(SDL_Renderer *a, const SDL_FPoint *b, int c),(a,b,c),return)
     4.9 +SDL_DYNAPI_PROC(int,SDL_RenderDrawLineF,(SDL_Renderer *a, float b, float c, float d, float e),(a,b,c,d,e),return)
    4.10 +SDL_DYNAPI_PROC(int,SDL_RenderDrawLinesF,(SDL_Renderer *a, const SDL_FPoint *b, int c),(a,b,c),return)
    4.11 +SDL_DYNAPI_PROC(int,SDL_RenderDrawRectF,(SDL_Renderer *a, const SDL_FRect *b),(a,b),return)
    4.12 +SDL_DYNAPI_PROC(int,SDL_RenderDrawRectsF,(SDL_Renderer *a, const SDL_FRect *b, int c),(a,b,c),return)
    4.13 +SDL_DYNAPI_PROC(int,SDL_RenderFillRectF,(SDL_Renderer *a, const SDL_FRect *b),(a,b),return)
    4.14 +SDL_DYNAPI_PROC(int,SDL_RenderFillRectsF,(SDL_Renderer *a, const SDL_FRect *b, int c),(a,b,c),return)
    4.15 +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)
    4.16 +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)
     5.1 --- a/src/render/SDL_render.c	Thu Oct 18 12:05:05 2018 -0400
     5.2 +++ b/src/render/SDL_render.c	Tue Oct 23 01:34:03 2018 -0400
     5.3 @@ -2157,31 +2157,37 @@
     5.4      return retval < 0 ? retval : FlushRenderCommandsIfNotBatching(renderer);
     5.5  }
     5.6  
     5.7 +
     5.8 +/* !!! FIXME: delete all the duplicate code for the integer versions in 2.1,
     5.9 +   !!! FIXME:  making the floating point versions the only available APIs. */
    5.10 +
    5.11  int
    5.12  SDL_RenderDrawPoint(SDL_Renderer * renderer, int x, int y)
    5.13  {
    5.14 -    SDL_Point point;
    5.15 -    int retval;
    5.16 -
    5.17 -    point.x = x;
    5.18 -    point.y = y;
    5.19 -    retval = SDL_RenderDrawPoints(renderer, &point, 1);
    5.20 -    return retval < 0 ? retval : FlushRenderCommandsIfNotBatching(renderer);
    5.21 +    const SDL_FPoint fpoint = { (float) x, (float) y };
    5.22 +    return SDL_RenderDrawPointsF(renderer, &fpoint, 1);
    5.23 +}
    5.24 +
    5.25 +int
    5.26 +SDL_RenderDrawPointF(SDL_Renderer * renderer, float x, float y)
    5.27 +{
    5.28 +    const SDL_FPoint fpoint = { x, y };
    5.29 +    return SDL_RenderDrawPointsF(renderer, &fpoint, 1);
    5.30  }
    5.31  
    5.32  static int
    5.33  RenderDrawPointsWithRects(SDL_Renderer * renderer,
    5.34 -                     const SDL_Point * points, int count)
    5.35 +                          const SDL_Point * points, const int count)
    5.36  {
    5.37 -    SDL_FRect *frects;
    5.38 -    int i;
    5.39      int retval = -1;
    5.40      SDL_bool isstack;
    5.41 -
    5.42 -    frects = SDL_small_alloc(SDL_FRect, count, &isstack);
    5.43 +    SDL_FRect *frects = SDL_small_alloc(SDL_FRect, count, &isstack);
    5.44 +    int i;
    5.45 +
    5.46      if (!frects) {
    5.47          return SDL_OutOfMemory();
    5.48      }
    5.49 +
    5.50      for (i = 0; i < count; ++i) {
    5.51          frects[i].x = points[i].x * renderer->scale.x;
    5.52          frects[i].y = points[i].y * renderer->scale.y;
    5.53 @@ -2239,21 +2245,93 @@
    5.54      return retval < 0 ? retval : FlushRenderCommandsIfNotBatching(renderer);
    5.55  }
    5.56  
    5.57 +static int
    5.58 +RenderDrawPointsWithRectsF(SDL_Renderer * renderer,
    5.59 +                           const SDL_FPoint * fpoints, const int count)
    5.60 +{
    5.61 +    int retval = -1;
    5.62 +    SDL_bool isstack;
    5.63 +    SDL_FRect *frects = SDL_small_alloc(SDL_FRect, count, &isstack);
    5.64 +    int i;
    5.65 +
    5.66 +    if (!frects) {
    5.67 +        return SDL_OutOfMemory();
    5.68 +    }
    5.69 +
    5.70 +    for (i = 0; i < count; ++i) {
    5.71 +        frects[i].x = fpoints[i].x * renderer->scale.x;
    5.72 +        frects[i].y = fpoints[i].y * renderer->scale.y;
    5.73 +        frects[i].w = renderer->scale.x;
    5.74 +        frects[i].h = renderer->scale.y;
    5.75 +    }
    5.76 +
    5.77 +    retval = QueueCmdFillRects(renderer, frects, count);
    5.78 +
    5.79 +    SDL_small_free(frects, isstack);
    5.80 +
    5.81 +    return retval < 0 ? retval : FlushRenderCommandsIfNotBatching(renderer);
    5.82 +}
    5.83 +
    5.84 +int
    5.85 +SDL_RenderDrawPointsF(SDL_Renderer * renderer,
    5.86 +                      const SDL_FPoint * points, int count)
    5.87 +{
    5.88 +    SDL_FPoint *fpoints;
    5.89 +    int i;
    5.90 +    int retval;
    5.91 +    SDL_bool isstack;
    5.92 +
    5.93 +    CHECK_RENDERER_MAGIC(renderer, -1);
    5.94 +
    5.95 +    if (!points) {
    5.96 +        return SDL_SetError("SDL_RenderDrawFPoints(): Passed NULL points");
    5.97 +    }
    5.98 +    if (count < 1) {
    5.99 +        return 0;
   5.100 +    }
   5.101 +
   5.102 +    /* Don't draw while we're hidden */
   5.103 +    if (renderer->hidden) {
   5.104 +        return 0;
   5.105 +    }
   5.106 +
   5.107 +    if (renderer->scale.x != 1.0f || renderer->scale.y != 1.0f) {
   5.108 +        return RenderDrawPointsWithRectsF(renderer, points, count);
   5.109 +    }
   5.110 +
   5.111 +    fpoints = SDL_small_alloc(SDL_FPoint, count, &isstack);
   5.112 +    if (!fpoints) {
   5.113 +        return SDL_OutOfMemory();
   5.114 +    }
   5.115 +    for (i = 0; i < count; ++i) {
   5.116 +        fpoints[i].x = points[i].x * renderer->scale.x;
   5.117 +        fpoints[i].y = points[i].y * renderer->scale.y;
   5.118 +    }
   5.119 +
   5.120 +    retval = QueueCmdDrawPoints(renderer, fpoints, count);
   5.121 +
   5.122 +    SDL_small_free(fpoints, isstack);
   5.123 +
   5.124 +    return retval < 0 ? retval : FlushRenderCommandsIfNotBatching(renderer);
   5.125 +}
   5.126 +
   5.127  int
   5.128  SDL_RenderDrawLine(SDL_Renderer * renderer, int x1, int y1, int x2, int y2)
   5.129  {
   5.130 -    SDL_Point points[2];
   5.131 -
   5.132 -    points[0].x = x1;
   5.133 -    points[0].y = y1;
   5.134 -    points[1].x = x2;
   5.135 -    points[1].y = y2;
   5.136 -    return SDL_RenderDrawLines(renderer, points, 2);
   5.137 +    const SDL_FPoint points[2] = { { (float) x1, (float) y1 }, { (float) x2, (float) y2 } };
   5.138 +    return SDL_RenderDrawLinesF(renderer, points, 2);
   5.139 +}
   5.140 +
   5.141 +int
   5.142 +SDL_RenderDrawLineF(SDL_Renderer * renderer, float x1, float y1, float x2, float y2)
   5.143 +{
   5.144 +    const SDL_FPoint points[2] = { { x1, y1 }, { x2, y2 } };
   5.145 +    return SDL_RenderDrawLinesF(renderer, points, 2);
   5.146  }
   5.147  
   5.148  static int
   5.149  RenderDrawLinesWithRects(SDL_Renderer * renderer,
   5.150 -                     const SDL_Point * points, int count)
   5.151 +                     const SDL_Point * points, const int count)
   5.152  {
   5.153      SDL_FRect *frect;
   5.154      SDL_FRect *frects;
   5.155 @@ -2306,6 +2384,61 @@
   5.156      return retval < 0 ? retval : FlushRenderCommandsIfNotBatching(renderer);
   5.157  }
   5.158  
   5.159 +static int
   5.160 +RenderDrawLinesWithRectsF(SDL_Renderer * renderer,
   5.161 +                          const SDL_FPoint * points, const int count)
   5.162 +{
   5.163 +    SDL_FRect *frect;
   5.164 +    SDL_FRect *frects;
   5.165 +    SDL_FPoint fpoints[2];
   5.166 +    int i, nrects = 0;
   5.167 +    int retval = 0;
   5.168 +    SDL_bool isstack;
   5.169 +
   5.170 +    frects = SDL_small_alloc(SDL_FRect, count-1, &isstack);
   5.171 +    if (!frects) {
   5.172 +        return SDL_OutOfMemory();
   5.173 +    }
   5.174 +
   5.175 +    for (i = 0; i < count-1; ++i) {
   5.176 +        if (points[i].x == points[i+1].x) {
   5.177 +            const int minY = SDL_min(points[i].y, points[i+1].y);
   5.178 +            const int maxY = SDL_max(points[i].y, points[i+1].y);
   5.179 +
   5.180 +            frect = &frects[nrects++];
   5.181 +            frect->x = points[i].x * renderer->scale.x;
   5.182 +            frect->y = minY * renderer->scale.y;
   5.183 +            frect->w = renderer->scale.x;
   5.184 +            frect->h = (maxY - minY + 1) * renderer->scale.y;
   5.185 +        } else if (points[i].y == points[i+1].y) {
   5.186 +            const int minX = SDL_min(points[i].x, points[i+1].x);
   5.187 +            const int maxX = SDL_max(points[i].x, points[i+1].x);
   5.188 +
   5.189 +            frect = &frects[nrects++];
   5.190 +            frect->x = minX * renderer->scale.x;
   5.191 +            frect->y = points[i].y * renderer->scale.y;
   5.192 +            frect->w = (maxX - minX + 1) * renderer->scale.x;
   5.193 +            frect->h = renderer->scale.y;
   5.194 +        } else {
   5.195 +            /* FIXME: We can't use a rect for this line... */
   5.196 +            fpoints[0].x = points[i].x * renderer->scale.x;
   5.197 +            fpoints[0].y = points[i].y * renderer->scale.y;
   5.198 +            fpoints[1].x = points[i+1].x * renderer->scale.x;
   5.199 +            fpoints[1].y = points[i+1].y * renderer->scale.y;
   5.200 +            retval += QueueCmdDrawLines(renderer, fpoints, 2);
   5.201 +        }
   5.202 +    }
   5.203 +
   5.204 +    retval += QueueCmdFillRects(renderer, frects, nrects);
   5.205 +
   5.206 +    SDL_small_free(frects, isstack);
   5.207 +
   5.208 +    if (retval < 0) {
   5.209 +        retval = -1;
   5.210 +    }
   5.211 +    return retval < 0 ? retval : FlushRenderCommandsIfNotBatching(renderer);
   5.212 +}
   5.213 +
   5.214  int
   5.215  SDL_RenderDrawLines(SDL_Renderer * renderer,
   5.216                      const SDL_Point * points, int count)
   5.217 @@ -2350,19 +2483,82 @@
   5.218  }
   5.219  
   5.220  int
   5.221 +SDL_RenderDrawLinesF(SDL_Renderer * renderer,
   5.222 +                     const SDL_FPoint * points, int count)
   5.223 +{
   5.224 +    SDL_FPoint *fpoints;
   5.225 +    int i;
   5.226 +    int retval;
   5.227 +    SDL_bool isstack;
   5.228 +
   5.229 +    CHECK_RENDERER_MAGIC(renderer, -1);
   5.230 +
   5.231 +    if (!points) {
   5.232 +        return SDL_SetError("SDL_RenderDrawLines(): Passed NULL points");
   5.233 +    }
   5.234 +    if (count < 2) {
   5.235 +        return 0;
   5.236 +    }
   5.237 +
   5.238 +    /* Don't draw while we're hidden */
   5.239 +    if (renderer->hidden) {
   5.240 +        return 0;
   5.241 +    }
   5.242 +
   5.243 +    if (renderer->scale.x != 1.0f || renderer->scale.y != 1.0f) {
   5.244 +        return RenderDrawLinesWithRectsF(renderer, points, count);
   5.245 +    }
   5.246 +
   5.247 +    fpoints = SDL_small_alloc(SDL_FPoint, count, &isstack);
   5.248 +    if (!fpoints) {
   5.249 +        return SDL_OutOfMemory();
   5.250 +    }
   5.251 +    for (i = 0; i < count; ++i) {
   5.252 +        fpoints[i].x = points[i].x * renderer->scale.x;
   5.253 +        fpoints[i].y = points[i].y * renderer->scale.y;
   5.254 +    }
   5.255 +
   5.256 +    retval = QueueCmdDrawLines(renderer, fpoints, count);
   5.257 +
   5.258 +    SDL_small_free(fpoints, isstack);
   5.259 +
   5.260 +    return retval < 0 ? retval : FlushRenderCommandsIfNotBatching(renderer);
   5.261 +}
   5.262 +
   5.263 +int
   5.264  SDL_RenderDrawRect(SDL_Renderer * renderer, const SDL_Rect * rect)
   5.265  {
   5.266 -    SDL_Rect full_rect;
   5.267 -    SDL_Point points[5];
   5.268 +    SDL_FRect frect;
   5.269 +    SDL_FRect *prect = NULL;
   5.270 +
   5.271 +    if (rect) {
   5.272 +        frect.x = (float) rect->x;
   5.273 +        frect.y = (float) rect->y;
   5.274 +        frect.w = (float) rect->w;
   5.275 +        frect.h = (float) rect->h;
   5.276 +        prect = &frect;
   5.277 +    }
   5.278 +
   5.279 +    return SDL_RenderDrawRectF(renderer, prect);
   5.280 +}
   5.281 +
   5.282 +int
   5.283 +SDL_RenderDrawRectF(SDL_Renderer * renderer, const SDL_FRect * rect)
   5.284 +{
   5.285 +    SDL_FRect frect;
   5.286 +    SDL_FPoint points[5];
   5.287  
   5.288      CHECK_RENDERER_MAGIC(renderer, -1);
   5.289  
   5.290      /* If 'rect' == NULL, then outline the whole surface */
   5.291      if (!rect) {
   5.292 -        SDL_RenderGetViewport(renderer, &full_rect);
   5.293 -        full_rect.x = 0;
   5.294 -        full_rect.y = 0;
   5.295 -        rect = &full_rect;
   5.296 +        SDL_Rect r;
   5.297 +        SDL_RenderGetViewport(renderer, &r);
   5.298 +        frect.x = 0.0f;
   5.299 +        frect.y = 0.0f;
   5.300 +        frect.w = (float) r.w;
   5.301 +        frect.h = (float) r.h;
   5.302 +        rect = &frect;
   5.303      }
   5.304  
   5.305      points[0].x = rect->x;
   5.306 @@ -2375,7 +2571,7 @@
   5.307      points[3].y = rect->y+rect->h-1;
   5.308      points[4].x = rect->x;
   5.309      points[4].y = rect->y;
   5.310 -    return SDL_RenderDrawLines(renderer, points, 5);
   5.311 +    return SDL_RenderDrawLinesF(renderer, points, 5);
   5.312  }
   5.313  
   5.314  int
   5.315 @@ -2407,20 +2603,75 @@
   5.316  }
   5.317  
   5.318  int
   5.319 +SDL_RenderDrawRectsF(SDL_Renderer * renderer,
   5.320 +                     const SDL_FRect * rects, int count)
   5.321 +{
   5.322 +    int i;
   5.323 +
   5.324 +    CHECK_RENDERER_MAGIC(renderer, -1);
   5.325 +
   5.326 +    if (!rects) {
   5.327 +        return SDL_SetError("SDL_RenderDrawRects(): Passed NULL rects");
   5.328 +    }
   5.329 +    if (count < 1) {
   5.330 +        return 0;
   5.331 +    }
   5.332 +
   5.333 +    /* Don't draw while we're hidden */
   5.334 +    if (renderer->hidden) {
   5.335 +        return 0;
   5.336 +    }
   5.337 +
   5.338 +    for (i = 0; i < count; ++i) {
   5.339 +        if (SDL_RenderDrawRectF(renderer, &rects[i]) < 0) {
   5.340 +            return -1;
   5.341 +        }
   5.342 +    }
   5.343 +    return 0;
   5.344 +}
   5.345 +
   5.346 +int
   5.347  SDL_RenderFillRect(SDL_Renderer * renderer, const SDL_Rect * rect)
   5.348  {
   5.349 -    SDL_Rect full_rect = { 0, 0, 0, 0 };
   5.350 +    SDL_FRect frect;
   5.351 +
   5.352 +    CHECK_RENDERER_MAGIC(renderer, -1);
   5.353 +
   5.354 +    /* If 'rect' == NULL, then outline the whole surface */
   5.355 +    if (rect) {
   5.356 +        frect.x = (float) rect->x;
   5.357 +        frect.y = (float) rect->y;
   5.358 +        frect.w = (float) rect->w;
   5.359 +        frect.h = (float) rect->h;
   5.360 +    } else {
   5.361 +        SDL_Rect r;
   5.362 +        SDL_RenderGetViewport(renderer, &r);
   5.363 +        frect.x = 0.0f;
   5.364 +        frect.y = 0.0f;
   5.365 +        frect.w = (float) r.w;
   5.366 +        frect.h = (float) r.h;
   5.367 +    }
   5.368 +    return SDL_RenderFillRectsF(renderer, &frect, 1);
   5.369 +}
   5.370 +
   5.371 +int
   5.372 +SDL_RenderFillRectF(SDL_Renderer * renderer, const SDL_FRect * rect)
   5.373 +{
   5.374 +    SDL_FRect frect;
   5.375  
   5.376      CHECK_RENDERER_MAGIC(renderer, -1);
   5.377  
   5.378      /* If 'rect' == NULL, then outline the whole surface */
   5.379      if (!rect) {
   5.380 -        SDL_RenderGetViewport(renderer, &full_rect);
   5.381 -        full_rect.x = 0;
   5.382 -        full_rect.y = 0;
   5.383 -        rect = &full_rect;
   5.384 +        SDL_Rect r;
   5.385 +        SDL_RenderGetViewport(renderer, &r);
   5.386 +        frect.x = 0.0f;
   5.387 +        frect.y = 0.0f;
   5.388 +        frect.w = (float) r.w;
   5.389 +        frect.h = (float) r.h;
   5.390 +        rect = &frect;
   5.391      }
   5.392 -    return SDL_RenderFillRects(renderer, rect, 1);
   5.393 +    return SDL_RenderFillRectsF(renderer, rect, 1);
   5.394  }
   5.395  
   5.396  int
   5.397 @@ -2465,12 +2716,123 @@
   5.398  }
   5.399  
   5.400  int
   5.401 +SDL_RenderFillRectsF(SDL_Renderer * renderer,
   5.402 +                     const SDL_FRect * rects, int count)
   5.403 +{
   5.404 +    SDL_FRect *frects;
   5.405 +    int i;
   5.406 +    int retval;
   5.407 +    SDL_bool isstack;
   5.408 +
   5.409 +    CHECK_RENDERER_MAGIC(renderer, -1);
   5.410 +
   5.411 +    if (!rects) {
   5.412 +        return SDL_SetError("SDL_RenderFillFRects(): Passed NULL rects");
   5.413 +    }
   5.414 +    if (count < 1) {
   5.415 +        return 0;
   5.416 +    }
   5.417 +
   5.418 +    /* Don't draw while we're hidden */
   5.419 +    if (renderer->hidden) {
   5.420 +        return 0;
   5.421 +    }
   5.422 +
   5.423 +    frects = SDL_small_alloc(SDL_FRect, count, &isstack);
   5.424 +    if (!frects) {
   5.425 +        return SDL_OutOfMemory();
   5.426 +    }
   5.427 +    for (i = 0; i < count; ++i) {
   5.428 +        frects[i].x = rects[i].x * renderer->scale.x;
   5.429 +        frects[i].y = rects[i].y * renderer->scale.y;
   5.430 +        frects[i].w = rects[i].w * renderer->scale.x;
   5.431 +        frects[i].h = rects[i].h * renderer->scale.y;
   5.432 +    }
   5.433 +
   5.434 +    retval = QueueCmdFillRects(renderer, frects, count);
   5.435 +
   5.436 +    SDL_small_free(frects, isstack);
   5.437 +
   5.438 +    return retval < 0 ? retval : FlushRenderCommandsIfNotBatching(renderer);
   5.439 +}
   5.440 +
   5.441 +/* !!! FIXME: move this to a public API if we want to do float versions of all of these later */
   5.442 +SDL_FORCE_INLINE SDL_bool SDL_FRectEmpty(const SDL_FRect *r)
   5.443 +{
   5.444 +    return ((!r) || (r->w <= 0.0f) || (r->h <= 0.0f)) ? SDL_TRUE : SDL_FALSE;
   5.445 +}
   5.446 +
   5.447 +/* !!! FIXME: move this to a public API if we want to do float versions of all of these later */
   5.448 +static SDL_bool
   5.449 +SDL_HasIntersectionF(const SDL_FRect * A, const SDL_FRect * B)
   5.450 +{
   5.451 +    float Amin, Amax, Bmin, Bmax;
   5.452 +
   5.453 +    if (!A) {
   5.454 +        SDL_InvalidParamError("A");
   5.455 +        return SDL_FALSE;
   5.456 +    }
   5.457 +
   5.458 +    if (!B) {
   5.459 +        SDL_InvalidParamError("B");
   5.460 +        return SDL_FALSE;
   5.461 +    }
   5.462 +
   5.463 +    /* Special cases for empty rects */
   5.464 +    if (SDL_FRectEmpty(A) || SDL_FRectEmpty(B)) {
   5.465 +        return SDL_FALSE;
   5.466 +    }
   5.467 +
   5.468 +    /* Horizontal intersection */
   5.469 +    Amin = A->x;
   5.470 +    Amax = Amin + A->w;
   5.471 +    Bmin = B->x;
   5.472 +    Bmax = Bmin + B->w;
   5.473 +    if (Bmin > Amin)
   5.474 +        Amin = Bmin;
   5.475 +    if (Bmax < Amax)
   5.476 +        Amax = Bmax;
   5.477 +    if (Amax <= Amin)
   5.478 +        return SDL_FALSE;
   5.479 +
   5.480 +    /* Vertical intersection */
   5.481 +    Amin = A->y;
   5.482 +    Amax = Amin + A->h;
   5.483 +    Bmin = B->y;
   5.484 +    Bmax = Bmin + B->h;
   5.485 +    if (Bmin > Amin)
   5.486 +        Amin = Bmin;
   5.487 +    if (Bmax < Amax)
   5.488 +        Amax = Bmax;
   5.489 +    if (Amax <= Amin)
   5.490 +        return SDL_FALSE;
   5.491 +
   5.492 +    return SDL_TRUE;
   5.493 +}
   5.494 +
   5.495 +int
   5.496  SDL_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
   5.497                 const SDL_Rect * srcrect, const SDL_Rect * dstrect)
   5.498  {
   5.499 -    SDL_Rect real_srcrect = { 0, 0, 0, 0 };
   5.500 -    SDL_Rect real_dstrect = { 0, 0, 0, 0 };
   5.501 -    SDL_FRect frect;
   5.502 +    SDL_FRect dstfrect;
   5.503 +    SDL_FRect *pdstfrect = NULL;
   5.504 +    if (dstrect) {
   5.505 +        dstfrect.x = (float) dstrect->x;
   5.506 +        dstfrect.y = (float) dstrect->y;
   5.507 +        dstfrect.w = (float) dstrect->w;
   5.508 +        dstfrect.h = (float) dstrect->h;
   5.509 +        pdstfrect = &dstfrect;
   5.510 +    }
   5.511 +    return SDL_RenderCopyF(renderer, texture, srcrect, pdstfrect);
   5.512 +}
   5.513 +
   5.514 +int
   5.515 +SDL_RenderCopyF(SDL_Renderer * renderer, SDL_Texture * texture,
   5.516 +                const SDL_Rect * srcrect, const SDL_FRect * dstrect)
   5.517 +{
   5.518 +    SDL_Rect real_srcrect;
   5.519 +    SDL_FRect real_dstrect;
   5.520 +    SDL_Rect r;
   5.521      int retval;
   5.522  
   5.523      CHECK_RENDERER_MAGIC(renderer, -1);
   5.524 @@ -2495,11 +2857,13 @@
   5.525          }
   5.526      }
   5.527  
   5.528 -    SDL_RenderGetViewport(renderer, &real_dstrect);
   5.529 -    real_dstrect.x = 0;
   5.530 -    real_dstrect.y = 0;
   5.531 +    SDL_RenderGetViewport(renderer, &r);
   5.532 +    real_dstrect.x = 0.0f;
   5.533 +    real_dstrect.y = 0.0f;
   5.534 +    real_dstrect.w = (float) r.w;
   5.535 +    real_dstrect.h = (float) r.h;
   5.536      if (dstrect) {
   5.537 -        if (!SDL_HasIntersection(dstrect, &real_dstrect)) {
   5.538 +        if (!SDL_HasIntersectionF(dstrect, &real_dstrect)) {
   5.539              return 0;
   5.540          }
   5.541          real_dstrect = *dstrect;
   5.542 @@ -2509,31 +2873,56 @@
   5.543          texture = texture->native;
   5.544      }
   5.545  
   5.546 -    frect.x = real_dstrect.x * renderer->scale.x;
   5.547 -    frect.y = real_dstrect.y * renderer->scale.y;
   5.548 -    frect.w = real_dstrect.w * renderer->scale.x;
   5.549 -    frect.h = real_dstrect.h * renderer->scale.y;
   5.550 +    real_dstrect.x *= renderer->scale.x;
   5.551 +    real_dstrect.y *= renderer->scale.y;
   5.552 +    real_dstrect.w *= renderer->scale.x;
   5.553 +    real_dstrect.h *= renderer->scale.y;
   5.554  
   5.555      texture->last_command_generation = renderer->render_command_generation;
   5.556  
   5.557 -    retval = QueueCmdCopy(renderer, texture, &real_srcrect, &frect);
   5.558 +    retval = QueueCmdCopy(renderer, texture, &real_srcrect, &real_dstrect);
   5.559      return retval < 0 ? retval : FlushRenderCommandsIfNotBatching(renderer);
   5.560  }
   5.561  
   5.562 -
   5.563  int
   5.564  SDL_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture,
   5.565                 const SDL_Rect * srcrect, const SDL_Rect * dstrect,
   5.566                 const double angle, const SDL_Point *center, const SDL_RendererFlip flip)
   5.567  {
   5.568 -    SDL_Rect real_srcrect = { 0, 0, 0, 0 };
   5.569 -    SDL_Rect real_dstrect = { 0, 0, 0, 0 };
   5.570 -    SDL_Point real_center;
   5.571 -    SDL_FRect frect;
   5.572 +    SDL_FRect dstfrect;
   5.573 +    SDL_FRect *pdstfrect = NULL;
   5.574      SDL_FPoint fcenter;
   5.575 +    SDL_FPoint *pfcenter = NULL;
   5.576 +
   5.577 +    if (dstrect) {
   5.578 +        dstfrect.x = (float) dstrect->x;
   5.579 +        dstfrect.y = (float) dstrect->y;
   5.580 +        dstfrect.w = (float) dstrect->w;
   5.581 +        dstfrect.h = (float) dstrect->h;
   5.582 +        pdstfrect = &dstfrect;
   5.583 +    }
   5.584 +
   5.585 +    if (center) {
   5.586 +        fcenter.x = (float) center->x;
   5.587 +        fcenter.y = (float) center->y;
   5.588 +        pfcenter = &fcenter;
   5.589 +    }
   5.590 +
   5.591 +    return SDL_RenderCopyExF(renderer, texture, srcrect, pdstfrect, angle, pfcenter, flip);
   5.592 +}
   5.593 +
   5.594 +int
   5.595 +SDL_RenderCopyExF(SDL_Renderer * renderer, SDL_Texture * texture,
   5.596 +               const SDL_Rect * srcrect, const SDL_FRect * dstrect,
   5.597 +               const double angle, const SDL_FPoint *center, const SDL_RendererFlip flip)
   5.598 +{
   5.599 +    SDL_Rect real_srcrect;
   5.600 +    SDL_FRect real_dstrect;
   5.601 +    SDL_FPoint real_center;
   5.602 +    int retval;
   5.603  
   5.604      if (flip == SDL_FLIP_NONE && (int)(angle/360) == angle/360) { /* fast path when we don't need rotation or flipping */
   5.605 -        return SDL_RenderCopy(renderer, texture, srcrect, dstrect);
   5.606 +        return SDL_RenderCopyF(renderer, texture, srcrect, dstrect);
   5.607      }
   5.608  
   5.609      CHECK_RENDERER_MAGIC(renderer, -1);
   5.610 @@ -2565,9 +2954,12 @@
   5.611      if (dstrect) {
   5.612          real_dstrect = *dstrect;
   5.613      } else {
   5.614 -        SDL_RenderGetViewport(renderer, &real_dstrect);
   5.615 -        real_dstrect.x = 0;
   5.616 -        real_dstrect.y = 0;
   5.617 +        SDL_Rect r;
   5.618 +        SDL_RenderGetViewport(renderer, &r);
   5.619 +        real_dstrect.x = 0.0f;
   5.620 +        real_dstrect.y = 0.0f;
   5.621 +        real_dstrect.w = (float) r.w;
   5.622 +        real_dstrect.h = (float) r.h;
   5.623      }
   5.624  
   5.625      if (texture->native) {
   5.626 @@ -2577,21 +2969,22 @@
   5.627      if (center) {
   5.628          real_center = *center;
   5.629      } else {
   5.630 -        real_center.x = real_dstrect.w/2;
   5.631 -        real_center.y = real_dstrect.h/2;
   5.632 +        real_center.x = real_dstrect.w / 2.0f;
   5.633 +        real_center.y = real_dstrect.h / 2.0f;
   5.634      }
   5.635  
   5.636 -    frect.x = real_dstrect.x * renderer->scale.x;
   5.637 -    frect.y = real_dstrect.y * renderer->scale.y;
   5.638 -    frect.w = real_dstrect.w * renderer->scale.x;
   5.639 -    frect.h = real_dstrect.h * renderer->scale.y;
   5.640 -
   5.641 -    fcenter.x = real_center.x * renderer->scale.x;
   5.642 -    fcenter.y = real_center.y * renderer->scale.y;
   5.643 +    real_dstrect.x *= renderer->scale.x;
   5.644 +    real_dstrect.y *= renderer->scale.y;
   5.645 +    real_dstrect.w *= renderer->scale.x;
   5.646 +    real_dstrect.h *= renderer->scale.y;
   5.647 +
   5.648 +    real_center.x *= renderer->scale.x;
   5.649 +    real_center.y *= renderer->scale.y;
   5.650  
   5.651      texture->last_command_generation = renderer->render_command_generation;
   5.652  
   5.653 -    return QueueCmdCopyEx(renderer, texture, &real_srcrect, &frect, angle, &fcenter, flip);
   5.654 +    retval = QueueCmdCopyEx(renderer, texture, &real_srcrect, &real_dstrect, angle, &real_center, flip);
   5.655 +    return retval < 0 ? retval : FlushRenderCommandsIfNotBatching(renderer);
   5.656  }
   5.657  
   5.658  int
     6.1 --- a/src/render/SDL_sysrender.h	Thu Oct 18 12:05:05 2018 -0400
     6.2 +++ b/src/render/SDL_sysrender.h	Tue Oct 23 01:34:03 2018 -0400
     6.3 @@ -39,20 +39,6 @@
     6.4      SDL_ScaleModeBest
     6.5  } SDL_ScaleMode;
     6.6  
     6.7 -typedef struct
     6.8 -{
     6.9 -    float x;
    6.10 -    float y;
    6.11 -} SDL_FPoint;
    6.12 -
    6.13 -typedef struct
    6.14 -{
    6.15 -    float x;
    6.16 -    float y;
    6.17 -    float w;
    6.18 -    float h;
    6.19 -} SDL_FRect;
    6.20 -
    6.21  /* Define the SDL texture structure */
    6.22  struct SDL_Texture
    6.23  {