Added interfaces for batch drawing of points, lines and rects:
authorSam Lantinga <slouken@libsdl.org>
Wed, 09 Dec 2009 15:56:56 +0000
changeset 3536 0267b8b1595c
parent 3535 b403f790df65
child 3537 e897a4a9f578
Added interfaces for batch drawing of points, lines and rects: SDL_DrawPoints() SDL_BlendPoints() SDL_BlendLines() SDL_DrawLines() SDL_FillRects() SDL_BlendRects() SDL_RenderPoints() SDL_RenderLines() SDL_RenderRects() Renamed SDL_RenderFill() to SDL_RenderRect()
include/SDL_compat.h
include/SDL_rect.h
include/SDL_surface.h
include/SDL_video.h
src/video/SDL_blendline.c
src/video/SDL_blendpoint.c
src/video/SDL_blendrect.c
src/video/SDL_draw.h
src/video/SDL_drawline.c
src/video/SDL_drawpoint.c
src/video/SDL_fillrect.c
src/video/SDL_rect.c
src/video/SDL_renderer_gl.c
src/video/SDL_renderer_gles.c
src/video/SDL_renderer_sw.c
src/video/SDL_sysvideo.h
src/video/SDL_video.c
src/video/dummy/SDL_nullrender.c
src/video/win32/SDL_d3drender.c
src/video/win32/SDL_gdirender.c
test/automated/render/render.c
test/testdraw2.c
test/testintersections.c
test/testnative.c
test/testsprite2.c
test/testspriteminimal.c
--- a/include/SDL_compat.h	Mon Dec 07 10:08:24 2009 +0000
+++ b/include/SDL_compat.h	Wed Dec 09 15:56:56 2009 +0000
@@ -350,6 +350,8 @@
 extern DECLSPEC void SDLCALL SDL_GetKeyRepeat(int *delay, int *interval);
 extern DECLSPEC int SDLCALL SDL_EnableUNICODE(int enable);
 
+#define SDL_RenderFill  SDL_RenderRect
+
 /*@}*//*Compatibility*/
 
 /* Ends C function definitions when using C++ */
--- a/include/SDL_rect.h	Mon Dec 07 10:08:24 2009 +0000
+++ b/include/SDL_rect.h	Wed Dec 09 15:56:56 2009 +0000
@@ -43,6 +43,17 @@
 #endif
 
 /**
+ *  \brief  The structure that defines a point
+ *
+ *  \sa SDL_EnclosePoints
+ */
+typedef struct
+{
+    int x;
+    int y;
+} SDL_Point;
+
+/**
  *  \brief A rectangle, with the origin at the upper left.
  *  
  *  \sa SDL_RectEmpty
@@ -50,6 +61,7 @@
  *  \sa SDL_HasIntersection
  *  \sa SDL_IntersectRect
  *  \sa SDL_UnionRect
+ *  \sa SDL_EnclosePoints
  */
 typedef struct SDL_Rect
 {
@@ -93,6 +105,16 @@
                                            SDL_Rect * result);
 
 /**
+ *  \brief Calculate a minimal rectangle enclosing a set of points
+ *
+ *  \return SDL_TRUE if any points were within the clipping rect
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_EnclosePoints(const SDL_Point * points,
+                                                   int count,
+                                                   const SDL_Rect * clip,
+                                                   SDL_Rect * result);
+
+/**
  *  \brief Calculate the intersection of a rectangle and line segment.
  *  
  *  \return SDL_TRUE if there is an intersection, SDL_FALSE otherwise.
--- a/include/SDL_surface.h	Mon Dec 07 10:08:24 2009 +0000
+++ b/include/SDL_surface.h	Wed Dec 09 15:56:56 2009 +0000
@@ -405,6 +405,8 @@
  */
 extern DECLSPEC int SDLCALL SDL_DrawPoint
     (SDL_Surface * dst, int x, int y, Uint32 color);
+extern DECLSPEC int SDLCALL SDL_DrawPoints
+    (SDL_Surface * dst, const SDL_Point * points, int count, Uint32 color);
 
 /**
  *  Blends a point with an RGBA value.
@@ -415,8 +417,11 @@
  *  \return 0 on success, or -1 on error.
  */
 extern DECLSPEC int SDLCALL SDL_BlendPoint
-    (SDL_Surface * dst, int x, int y, int blendMode,
-     Uint8 r, Uint8 g, Uint8 b, Uint8 a);
+    (SDL_Surface * dst, int x, int y,
+     int blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a);
+extern DECLSPEC int SDLCALL SDL_BlendPoints
+    (SDL_Surface * dst, const SDL_Point * points, int count,
+     int blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a);
 
 /**
  *  Draws a line with \c color.
@@ -428,6 +433,8 @@
  */
 extern DECLSPEC int SDLCALL SDL_DrawLine
     (SDL_Surface * dst, int x1, int y1, int x2, int y2, Uint32 color);
+extern DECLSPEC int SDLCALL SDL_DrawLines
+    (SDL_Surface * dst, const SDL_Point * points, int count, Uint32 color);
 
 /**
  *  Blends an RGBA value along a line.
@@ -435,16 +442,16 @@
  *  \return 0 on success, or -1 on error.
  */
 extern DECLSPEC int SDLCALL SDL_BlendLine
-    (SDL_Surface * dst, int x1, int y1, int x2, int y2, int blendMode,
-     Uint8 r, Uint8 g, Uint8 b, Uint8 a);
+    (SDL_Surface * dst, int x1, int y1, int x2, int y2,
+     int blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a);
+extern DECLSPEC int SDLCALL SDL_BlendLines
+    (SDL_Surface * dst, const SDL_Point * points, int count,
+     int blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a);
 
 /**
  *  Performs a fast fill of the given rectangle with \c color.
  *  
- *  The given rectangle is clipped to the destination surface clip area
- *  and the final fill rectangle is saved in the passed in pointer.
- *  
- *  If \c dstrect is NULL, the whole surface will be filled with \c color.
+ *  If \c rect is NULL, the whole surface will be filled with \c color.
  *  
  *  The color should be a pixel of the format used by the surface, and 
  *  can be generated by the SDL_MapRGB() function.
@@ -452,21 +459,23 @@
  *  \return 0 on success, or -1 on error.
  */
 extern DECLSPEC int SDLCALL SDL_FillRect
-    (SDL_Surface * dst, SDL_Rect * dstrect, Uint32 color);
+    (SDL_Surface * dst, const SDL_Rect * rect, Uint32 color);
+extern DECLSPEC int SDLCALL SDL_FillRects
+    (SDL_Surface * dst, const SDL_Rect ** rects, int count, Uint32 color);
 
 /**
  *  Blends an RGBA value into the given rectangle.
  *  
- *  The given rectangle is clipped to the destination surface clip area
- *  and the final fill rectangle is saved in the passed in pointer.
- *  
- *  If \c dstrect is NULL, the whole surface will be filled with \c color.
+ *  If \c rect is NULL, the whole surface will be filled with \c color.
  *  
  *  \return This function returns 0 on success, or -1 on error.
  */
 extern DECLSPEC int SDLCALL SDL_BlendRect
-    (SDL_Surface * dst, SDL_Rect * dstrect, int blendMode, Uint8 r, Uint8 g,
-     Uint8 b, Uint8 a);
+    (SDL_Surface * dst, const SDL_Rect * rect,
+     int blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a);
+extern DECLSPEC int SDLCALL SDL_BlendRects
+    (SDL_Surface * dst, const SDL_Rect ** rects, int count,
+     int blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a);
 
 /**
  *  Performs a fast blit from the source surface to the destination surface.
--- a/include/SDL_video.h	Mon Dec 07 10:08:24 2009 +0000
+++ b/include/SDL_video.h	Wed Dec 09 15:56:56 2009 +0000
@@ -1148,6 +1148,17 @@
 extern DECLSPEC int SDLCALL SDL_RenderPoint(int x, int y);
 
 /**
+ *  \brief Draw some number of points on the current rendering target.
+ *  
+ *  \param points The points to draw
+ *  \param count The number of points to draw
+ *  
+ *  \return 0 on success, or -1 if there is no rendering context current.
+ */
+extern DECLSPEC int SDLCALL SDL_RenderPoints(const SDL_Point * points,
+                                             int count);
+
+/**
  *  \brief Draw a line on the current rendering target.
  *  
  *  \param x1 The x coordinate of the start point.
@@ -1160,6 +1171,17 @@
 extern DECLSPEC int SDLCALL SDL_RenderLine(int x1, int y1, int x2, int y2);
 
 /**
+ *  \brief Draw a series of connected lines on the current rendering target.
+ *  
+ *  \param points The points along the lines
+ *  \param count The number of points, drawing count-1 lines
+ *  
+ *  \return 0 on success, or -1 if there is no rendering context current.
+ */
+extern DECLSPEC int SDLCALL SDL_RenderLines(const SDL_Point * points,
+                                            int count);
+
+/**
  *  \brief Fill the current rendering target with the drawing color.
  *  
  *  \param rect A pointer to the destination rectangle, or NULL for the entire 
@@ -1167,7 +1189,17 @@
  *  
  *  \return 0 on success, or -1 if there is no rendering context current.
  */
-extern DECLSPEC int SDLCALL SDL_RenderFill(const SDL_Rect * rect);
+extern DECLSPEC int SDLCALL SDL_RenderRect(const SDL_Rect * rect);
+
+/**
+ *  \brief Fill some number of rectangles in the current rendering target with the drawing color.
+ *  
+ *  \param rects A pointer to an array of destination rectangles.
+ *  \param count The number of rectangles.
+ *  
+ *  \return 0 on success, or -1 if there is no rendering context current.
+ */
+extern DECLSPEC int SDLCALL SDL_RenderRects(const SDL_Rect ** rect, int count);
 
 /**
  *  \brief Copy a portion of the texture to the current rendering target.
--- a/src/video/SDL_blendline.c	Mon Dec 07 10:08:24 2009 +0000
+++ b/src/video/SDL_blendline.c	Wed Dec 09 15:56:56 2009 +0000
@@ -195,8 +195,6 @@
 SDL_BlendLine(SDL_Surface * dst, int x1, int y1, int x2, int y2,
               int blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
 {
-    SDL_PixelFormat *fmt = dst->format;
-
     /* This function doesn't work on surfaces < 8 bpp */
     if (dst->format->BitsPerPixel < 8) {
         SDL_SetError("SDL_BlendLine(): Unsupported surface format");
@@ -209,32 +207,31 @@
     }
 
 
-    if ((blendMode == SDL_BLENDMODE_BLEND)
-        || (blendMode == SDL_BLENDMODE_ADD)) {
+    if (blendMode == SDL_BLENDMODE_BLEND || blendMode == SDL_BLENDMODE_ADD) {
         r = DRAW_MUL(r, a);
         g = DRAW_MUL(g, a);
         b = DRAW_MUL(b, a);
     }
 
-    switch (fmt->BitsPerPixel) {
+    switch (dst->format->BitsPerPixel) {
     case 15:
-        switch (fmt->Rmask) {
+        switch (dst->format->Rmask) {
         case 0x7C00:
             return SDL_BlendLine_RGB555(dst, x1, y1, x2, y2, blendMode, r, g,
                                         b, a);
         }
         break;
     case 16:
-        switch (fmt->Rmask) {
+        switch (dst->format->Rmask) {
         case 0xF800:
             return SDL_BlendLine_RGB565(dst, x1, y1, x2, y2, blendMode, r, g,
                                         b, a);
         }
         break;
     case 32:
-        switch (fmt->Rmask) {
+        switch (dst->format->Rmask) {
         case 0x00FF0000:
-            if (!fmt->Amask) {
+            if (!dst->format->Amask) {
                 return SDL_BlendLine_RGB888(dst, x1, y1, x2, y2, blendMode, r,
                                             g, b, a);
             } else {
@@ -243,15 +240,97 @@
             }
             break;
         }
+        break;
     default:
         break;
     }
 
-    if (!fmt->Amask) {
+    if (!dst->format->Amask) {
         return SDL_BlendLine_RGB(dst, x1, y1, x2, y2, blendMode, r, g, b, a);
     } else {
         return SDL_BlendLine_RGBA(dst, x1, y1, x2, y2, blendMode, r, g, b, a);
     }
 }
 
+int
+SDL_BlendLines(SDL_Surface * dst, const SDL_Point * points, int count,
+               int blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
+{
+    int i;
+    int x1, y1;
+    int x2, y2;
+    int (*func)(SDL_Surface * dst, int x1, int y1, int x2, int y2,
+                int blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a) = NULL;
+    int status = 0;
+
+    if (!dst) {
+        SDL_SetError("Passed NULL destination surface");
+        return -1;
+    }
+
+    /* This function doesn't work on surfaces < 8 bpp */
+    if (dst->format->BitsPerPixel < 8) {
+        SDL_SetError("SDL_BlendLines(): Unsupported surface format");
+        return -1;
+    }
+
+    if (blendMode == SDL_BLENDMODE_BLEND || blendMode == SDL_BLENDMODE_ADD) {
+        r = DRAW_MUL(r, a);
+        g = DRAW_MUL(g, a);
+        b = DRAW_MUL(b, a);
+    }
+
+    /* FIXME: Does this function pointer slow things down significantly? */
+    switch (dst->format->BitsPerPixel) {
+    case 15:
+        switch (dst->format->Rmask) {
+        case 0x7C00:
+            func = SDL_BlendLine_RGB555;
+        }
+        break;
+    case 16:
+        switch (dst->format->Rmask) {
+        case 0xF800:
+            func = SDL_BlendLine_RGB565;
+        }
+        break;
+    case 32:
+        switch (dst->format->Rmask) {
+        case 0x00FF0000:
+            if (!dst->format->Amask) {
+                func = SDL_BlendLine_RGB888;
+            } else {
+                func = SDL_BlendLine_ARGB8888;
+            }
+            break;
+        }
+    default:
+        break;
+    }
+
+    if (!func) {
+        if (!dst->format->Amask) {
+            func = SDL_BlendLine_RGB;
+        } else {
+            func = SDL_BlendLine_RGBA;
+        }
+    }
+
+    for (i = 1; i < count; ++i) {
+        x1 = points[i-1].x;
+        y1 = points[i-1].y;
+        x2 = points[i].x;
+        y2 = points[i].y;
+
+        /* Perform clipping */
+        /* FIXME: We don't actually want to clip, as it may change line slope */
+        if (!SDL_IntersectRectAndLine(&dst->clip_rect, &x1, &y1, &x2, &y2)) {
+            continue;
+        }
+
+        status = func(dst, x1, y1, x2, y2, blendMode, r, g, b, a);
+    }
+    return status;
+}
+
 /* vi: set ts=4 sw=4 expandtab: */
--- a/src/video/SDL_blendpoint.c	Mon Dec 07 10:08:24 2009 +0000
+++ b/src/video/SDL_blendpoint.c	Wed Dec 09 15:56:56 2009 +0000
@@ -195,12 +195,15 @@
 SDL_BlendPoint(SDL_Surface * dst, int x, int y, int blendMode, Uint8 r,
                Uint8 g, Uint8 b, Uint8 a)
 {
-    SDL_PixelFormat *fmt = dst->format;
+    if (!dst) {
+        SDL_SetError("Passed NULL destination surface");
+        return -1;
+    }
 
     /* This function doesn't work on surfaces < 8 bpp */
     if (dst->format->BitsPerPixel < 8) {
         SDL_SetError("SDL_BlendPoint(): Unsupported surface format");
-        return (-1);
+        return -1;
     }
 
     /* Perform clipping */
@@ -210,30 +213,29 @@
         return 0;
     }
 
-    if ((blendMode == SDL_BLENDMODE_BLEND)
-        || (blendMode == SDL_BLENDMODE_ADD)) {
+    if (blendMode == SDL_BLENDMODE_BLEND || blendMode == SDL_BLENDMODE_ADD) {
         r = DRAW_MUL(r, a);
         g = DRAW_MUL(g, a);
         b = DRAW_MUL(b, a);
     }
 
-    switch (fmt->BitsPerPixel) {
+    switch (dst->format->BitsPerPixel) {
     case 15:
-        switch (fmt->Rmask) {
+        switch (dst->format->Rmask) {
         case 0x7C00:
             return SDL_BlendPoint_RGB555(dst, x, y, blendMode, r, g, b, a);
         }
         break;
     case 16:
-        switch (fmt->Rmask) {
+        switch (dst->format->Rmask) {
         case 0xF800:
             return SDL_BlendPoint_RGB565(dst, x, y, blendMode, r, g, b, a);
         }
         break;
     case 32:
-        switch (fmt->Rmask) {
+        switch (dst->format->Rmask) {
         case 0x00FF0000:
-            if (!fmt->Amask) {
+            if (!dst->format->Amask) {
                 return SDL_BlendPoint_RGB888(dst, x, y, blendMode, r, g, b,
                                              a);
             } else {
@@ -242,15 +244,101 @@
             }
             break;
         }
+        break;
     default:
         break;
     }
 
-    if (!fmt->Amask) {
+    if (!dst->format->Amask) {
         return SDL_BlendPoint_RGB(dst, x, y, blendMode, r, g, b, a);
     } else {
         return SDL_BlendPoint_RGBA(dst, x, y, blendMode, r, g, b, a);
     }
 }
 
+int
+SDL_BlendPoints(SDL_Surface * dst, const SDL_Point * points, int count,
+                int blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
+{
+    int minx, miny;
+    int maxx, maxy;
+    int i;
+    int x, y;
+    int (*func)(SDL_Surface * dst, int x, int y,
+                int blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a) = NULL;
+    int status = 0;
+
+    if (!dst) {
+        SDL_SetError("Passed NULL destination surface");
+        return -1;
+    }
+
+    /* This function doesn't work on surfaces < 8 bpp */
+    if (dst->format->BitsPerPixel < 8) {
+        SDL_SetError("SDL_BlendPoints(): Unsupported surface format");
+        return (-1);
+    }
+
+    if (blendMode == SDL_BLENDMODE_BLEND || blendMode == SDL_BLENDMODE_ADD) {
+        r = DRAW_MUL(r, a);
+        g = DRAW_MUL(g, a);
+        b = DRAW_MUL(b, a);
+    }
+
+    /* FIXME: Does this function pointer slow things down significantly? */
+    switch (dst->format->BitsPerPixel) {
+    case 15:
+        switch (dst->format->Rmask) {
+        case 0x7C00:
+            func = SDL_BlendPoint_RGB555;
+            break;
+        }
+        break;
+    case 16:
+        switch (dst->format->Rmask) {
+        case 0xF800:
+            func = SDL_BlendPoint_RGB565;
+            break;
+        }
+        break;
+    case 32:
+        switch (dst->format->Rmask) {
+        case 0x00FF0000:
+            if (!dst->format->Amask) {
+                func = SDL_BlendPoint_RGB888;
+            } else {
+                func = SDL_BlendPoint_ARGB8888;
+            }
+            break;
+        }
+        break;
+    default:
+        break;
+    }
+
+    if (!func) {
+        if (!dst->format->Amask) {
+            func = SDL_BlendPoint_RGB;
+        } else {
+            func = SDL_BlendPoint_RGBA;
+        }
+    }
+
+    minx = dst->clip_rect.x;
+    maxx = dst->clip_rect.x + dst->clip_rect.w - 1;
+    miny = dst->clip_rect.y;
+    maxy = dst->clip_rect.y + dst->clip_rect.h - 1;
+
+    for (i = 0; i < count; ++i) {
+        x = points[i].x;
+        y = points[i].y;
+
+        if (x < minx || x > maxx || y < miny || y > maxy) {
+            continue;
+        }
+        status = func(dst, x, y, blendMode, r, g, b, a);
+    }
+    return status;
+}
+
 /* vi: set ts=4 sw=4 expandtab: */
--- a/src/video/SDL_blendrect.c	Mon Dec 07 10:08:24 2009 +0000
+++ b/src/video/SDL_blendrect.c	Wed Dec 09 15:56:56 2009 +0000
@@ -25,7 +25,7 @@
 #include "SDL_draw.h"
 
 static int
-SDL_BlendRect_RGB555(SDL_Surface * dst, SDL_Rect * dstrect, int blendMode,
+SDL_BlendRect_RGB555(SDL_Surface * dst, const SDL_Rect * rect, int blendMode,
                      Uint8 r, Uint8 g, Uint8 b, Uint8 a)
 {
     unsigned inva = 0xff - a;
@@ -48,7 +48,7 @@
 }
 
 static int
-SDL_BlendRect_RGB565(SDL_Surface * dst, SDL_Rect * dstrect, int blendMode,
+SDL_BlendRect_RGB565(SDL_Surface * dst, const SDL_Rect * rect, int blendMode,
                      Uint8 r, Uint8 g, Uint8 b, Uint8 a)
 {
     unsigned inva = 0xff - a;
@@ -71,7 +71,7 @@
 }
 
 static int
-SDL_BlendRect_RGB888(SDL_Surface * dst, SDL_Rect * dstrect, int blendMode,
+SDL_BlendRect_RGB888(SDL_Surface * dst, const SDL_Rect * rect, int blendMode,
                      Uint8 r, Uint8 g, Uint8 b, Uint8 a)
 {
     unsigned inva = 0xff - a;
@@ -94,7 +94,7 @@
 }
 
 static int
-SDL_BlendRect_ARGB8888(SDL_Surface * dst, SDL_Rect * dstrect, int blendMode,
+SDL_BlendRect_ARGB8888(SDL_Surface * dst, const SDL_Rect * rect, int blendMode,
                        Uint8 r, Uint8 g, Uint8 b, Uint8 a)
 {
     unsigned inva = 0xff - a;
@@ -117,7 +117,7 @@
 }
 
 static int
-SDL_BlendRect_RGB(SDL_Surface * dst, SDL_Rect * dstrect, int blendMode,
+SDL_BlendRect_RGB(SDL_Surface * dst, const SDL_Rect * rect, int blendMode,
                   Uint8 r, Uint8 g, Uint8 b, Uint8 a)
 {
     SDL_PixelFormat *fmt = dst->format;
@@ -163,7 +163,7 @@
 }
 
 static int
-SDL_BlendRect_RGBA(SDL_Surface * dst, SDL_Rect * dstrect, int blendMode,
+SDL_BlendRect_RGBA(SDL_Surface * dst, const SDL_Rect * rect, int blendMode,
                    Uint8 r, Uint8 g, Uint8 b, Uint8 a)
 {
     SDL_PixelFormat *fmt = dst->format;
@@ -193,68 +193,155 @@
 }
 
 int
-SDL_BlendRect(SDL_Surface * dst, SDL_Rect * dstrect, int blendMode, Uint8 r,
-              Uint8 g, Uint8 b, Uint8 a)
+SDL_BlendRect(SDL_Surface * dst, const SDL_Rect * rect,
+              int blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
 {
-    SDL_PixelFormat *fmt = dst->format;
+    SDL_Rect clipped;
 
-    /* This function doesn't work on surfaces < 8 bpp */
-    if (fmt->BitsPerPixel < 8) {
-        SDL_SetError("SDL_BlendRect(): Unsupported surface format");
-        return (-1);
+    if (!dst) {
+        SDL_SetError("Passed NULL destination surface");
+        return -1;
     }
 
-    /* If 'dstrect' == NULL, then fill the whole surface */
-    if (dstrect) {
-        /* Perform clipping */
-        if (!SDL_IntersectRect(dstrect, &dst->clip_rect, dstrect)) {
-            return (0);
-        }
-    } else {
-        dstrect = &dst->clip_rect;
+    /* This function doesn't work on surfaces < 8 bpp */
+    if (dst->format->BitsPerPixel < 8) {
+        SDL_SetError("SDL_BlendRect(): Unsupported surface format");
+        return -1;
     }
 
-    if ((blendMode == SDL_BLENDMODE_BLEND)
-        || (blendMode == SDL_BLENDMODE_ADD)) {
+    /* If 'rect' == NULL, then fill the whole surface */
+    if (rect) {
+        /* Perform clipping */
+        if (!SDL_IntersectRect(rect, &dst->clip_rect, &clipped)) {
+            return 0;
+        }
+        rect = &clipped;
+    } else {
+        rect = &dst->clip_rect;
+    }
+
+    if (blendMode == SDL_BLENDMODE_BLEND || blendMode == SDL_BLENDMODE_ADD) {
         r = DRAW_MUL(r, a);
         g = DRAW_MUL(g, a);
         b = DRAW_MUL(b, a);
     }
 
-    switch (fmt->BitsPerPixel) {
+    switch (dst->format->BitsPerPixel) {
     case 15:
-        switch (fmt->Rmask) {
+        switch (dst->format->Rmask) {
         case 0x7C00:
-            return SDL_BlendRect_RGB555(dst, dstrect, blendMode, r, g, b, a);
+            return SDL_BlendRect_RGB555(dst, rect, blendMode, r, g, b, a);
         }
         break;
     case 16:
-        switch (fmt->Rmask) {
+        switch (dst->format->Rmask) {
         case 0xF800:
-            return SDL_BlendRect_RGB565(dst, dstrect, blendMode, r, g, b, a);
+            return SDL_BlendRect_RGB565(dst, rect, blendMode, r, g, b, a);
         }
         break;
     case 32:
-        switch (fmt->Rmask) {
+        switch (dst->format->Rmask) {
         case 0x00FF0000:
-            if (!fmt->Amask) {
-                return SDL_BlendRect_RGB888(dst, dstrect, blendMode, r, g, b,
-                                            a);
+            if (!dst->format->Amask) {
+                return SDL_BlendRect_RGB888(dst, rect, blendMode, r, g, b, a);
             } else {
-                return SDL_BlendRect_ARGB8888(dst, dstrect, blendMode, r, g,
-                                              b, a);
+                return SDL_BlendRect_ARGB8888(dst, rect, blendMode, r, g, b, a);
             }
             break;
         }
+        break;
     default:
         break;
     }
 
-    if (!fmt->Amask) {
-        return SDL_BlendRect_RGB(dst, dstrect, blendMode, r, g, b, a);
+    if (!dst->format->Amask) {
+        return SDL_BlendRect_RGB(dst, rect, blendMode, r, g, b, a);
     } else {
-        return SDL_BlendRect_RGBA(dst, dstrect, blendMode, r, g, b, a);
+        return SDL_BlendRect_RGBA(dst, rect, blendMode, r, g, b, a);
     }
 }
 
+int
+SDL_BlendRects(SDL_Surface * dst, const SDL_Rect ** rects, int count,
+               int blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
+{
+    SDL_Rect clipped;
+    int i;
+    int (*func)(SDL_Surface * dst, const SDL_Rect * rect,
+                int blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a) = NULL;
+    int status = 0;
+
+    if (!dst) {
+        SDL_SetError("Passed NULL destination surface");
+        return -1;
+    }
+
+    /* This function doesn't work on surfaces < 8 bpp */
+    if (dst->format->BitsPerPixel < 8) {
+        SDL_SetError("SDL_BlendRects(): Unsupported surface format");
+        return -1;
+    }
+
+    if (blendMode == SDL_BLENDMODE_BLEND || blendMode == SDL_BLENDMODE_ADD) {
+        r = DRAW_MUL(r, a);
+        g = DRAW_MUL(g, a);
+        b = DRAW_MUL(b, a);
+    }
+
+    /* FIXME: Does this function pointer slow things down significantly? */
+    switch (dst->format->BitsPerPixel) {
+    case 15:
+        switch (dst->format->Rmask) {
+        case 0x7C00:
+            func = SDL_BlendRect_RGB555;
+        }
+        break;
+    case 16:
+        switch (dst->format->Rmask) {
+        case 0xF800:
+            func = SDL_BlendRect_RGB565;
+        }
+        break;
+    case 32:
+        switch (dst->format->Rmask) {
+        case 0x00FF0000:
+            if (!dst->format->Amask) {
+                func = SDL_BlendRect_RGB888;
+            } else {
+                func = SDL_BlendRect_ARGB8888;
+            }
+            break;
+        }
+        break;
+    default:
+        break;
+    }
+
+    if (!func) {
+        if (!dst->format->Amask) {
+            func = SDL_BlendRect_RGB;
+        } else {
+            func = SDL_BlendRect_RGBA;
+        }
+    }
+
+    for (i = 0; i < count; ++i) {
+        const SDL_Rect * rect = rects[i];
+
+        /* If 'rect' == NULL, then fill the whole surface */
+        if (rect) {
+            /* Perform clipping */
+            if (!SDL_IntersectRect(rect, &dst->clip_rect, &clipped)) {
+                continue;
+            }
+            rect = &clipped;
+        } else {
+            rect = &dst->clip_rect;
+        }
+
+        status = func(dst, rect, blendMode, r, g, b, a);
+    }
+    return status;
+}
+
 /* vi: set ts=4 sw=4 expandtab: */
--- a/src/video/SDL_draw.h	Mon Dec 07 10:08:24 2009 +0000
+++ b/src/video/SDL_draw.h	Wed Dec 09 15:56:56 2009 +0000
@@ -346,11 +346,11 @@
 
 #define FILLRECT(type, op) \
 do { \
-    int width = dstrect->w; \
-    int height = dstrect->h; \
+    int width = rect->w; \
+    int height = rect->h; \
     int pitch = (dst->pitch / dst->format->BytesPerPixel); \
     int skip = pitch - width; \
-    type *pixel = (type *)dst->pixels + dstrect->y * pitch + dstrect->x; \
+    type *pixel = (type *)dst->pixels + rect->y * pitch + rect->x; \
     while (height--) { \
         { int n = (width+3)/4; \
             switch (width & 3) { \
--- a/src/video/SDL_drawline.c	Mon Dec 07 10:08:24 2009 +0000
+++ b/src/video/SDL_drawline.c	Wed Dec 09 15:56:56 2009 +0000
@@ -27,13 +27,19 @@
 int
 SDL_DrawLine(SDL_Surface * dst, int x1, int y1, int x2, int y2, Uint32 color)
 {
+    if (!dst) {
+        SDL_SetError("Passed NULL destination surface");
+        return -1;
+    }
+
     /* This function doesn't work on surfaces < 8 bpp */
     if (dst->format->BitsPerPixel < 8) {
         SDL_SetError("SDL_DrawLine(): Unsupported surface format");
-        return (-1);
+        return -1;
     }
 
     /* Perform clipping */
+    /* FIXME: We don't actually want to clip, as it may change line slope */
     if (!SDL_IntersectRectAndLine(&dst->clip_rect, &x1, &y1, &x2, &y2)) {
         return (0);
     }
@@ -55,4 +61,55 @@
     return 0;
 }
 
+int
+SDL_DrawLines(SDL_Surface * dst, const SDL_Point * points, int count,
+              Uint32 color)
+{
+    int i;
+
+    if (!dst) {
+        SDL_SetError("Passed NULL destination surface");
+        return -1;
+    }
+
+    /* This function doesn't work on surfaces < 8 bpp */
+    if (dst->format->BitsPerPixel < 8) {
+        SDL_SetError("SDL_DrawLine(): Unsupported surface format");
+        return -1;
+    }
+
+    if (count < 2) {
+        return 0;
+    }
+
+    for (i = 1; i < count; ++i) {
+        int x1 = points[i-1].x;
+        int y1 = points[i-1].y;
+        int x2 = points[i].x;
+        int y2 = points[i].y;
+
+        /* Perform clipping */
+        /* FIXME: We don't actually want to clip, as it may change line slope */
+        if (!SDL_IntersectRectAndLine(&dst->clip_rect, &x1, &y1, &x2, &y2)) {
+            continue;
+        }
+
+        switch (dst->format->BytesPerPixel) {
+        case 1:
+            DRAWLINE(x1, y1, x2, y2, DRAW_FASTSETPIXEL1);
+            break;
+        case 2:
+            DRAWLINE(x1, y1, x2, y2, DRAW_FASTSETPIXEL2);
+            break;
+        case 3:
+            SDL_Unsupported();
+            return -1;
+        case 4:
+            DRAWLINE(x1, y1, x2, y2, DRAW_FASTSETPIXEL4);
+            break;
+        }
+    }
+    return 0;
+}
+
 /* vi: set ts=4 sw=4 expandtab: */
--- a/src/video/SDL_drawpoint.c	Mon Dec 07 10:08:24 2009 +0000
+++ b/src/video/SDL_drawpoint.c	Wed Dec 09 15:56:56 2009 +0000
@@ -27,10 +27,15 @@
 int
 SDL_DrawPoint(SDL_Surface * dst, int x, int y, Uint32 color)
 {
+    if (!dst) {
+        SDL_SetError("Passed NULL destination surface");
+        return -1;
+    }
+
     /* This function doesn't work on surfaces < 8 bpp */
     if (dst->format->BitsPerPixel < 8) {
         SDL_SetError("SDL_DrawPoint(): Unsupported surface format");
-        return (-1);
+        return -1;
     }
 
     /* Perform clipping */
@@ -57,4 +62,55 @@
     return 0;
 }
 
+int
+SDL_DrawPoints(SDL_Surface * dst, const SDL_Point * points, int count,
+               Uint32 color)
+{
+    int minx, miny;
+    int maxx, maxy;
+    int i;
+    int x, y;
+
+    if (!dst) {
+        SDL_SetError("Passed NULL destination surface");
+        return -1;
+    }
+
+    /* This function doesn't work on surfaces < 8 bpp */
+    if (dst->format->BitsPerPixel < 8) {
+        SDL_SetError("SDL_DrawPoints(): Unsupported surface format");
+        return -1;
+    }
+
+    minx = dst->clip_rect.x;
+    maxx = dst->clip_rect.x + dst->clip_rect.w - 1;
+    miny = dst->clip_rect.y;
+    maxy = dst->clip_rect.y + dst->clip_rect.h - 1;
+
+    for (i = 0; i < count; ++i) {
+        x = points[i].x;
+        y = points[i].y;
+
+        if (x < minx || x > maxx || y < miny || y > maxy) {
+            continue;
+        }
+
+        switch (dst->format->BytesPerPixel) {
+        case 1:
+            DRAW_FASTSETPIXEL1(x, y);
+            break;
+        case 2:
+            DRAW_FASTSETPIXEL2(x, y);
+            break;
+        case 3:
+            SDL_Unsupported();
+            return -1;
+        case 4:
+            DRAW_FASTSETPIXEL4(x, y);
+            break;
+        }
+    }
+    return 0;
+}
+
 /* vi: set ts=4 sw=4 expandtab: */
--- a/src/video/SDL_fillrect.c	Mon Dec 07 10:08:24 2009 +0000
+++ b/src/video/SDL_fillrect.c	Wed Dec 09 15:56:56 2009 +0000
@@ -310,24 +310,31 @@
  * This function performs a fast fill of the given rectangle with 'color'
  */
 int
-SDL_FillRect(SDL_Surface * dst, SDL_Rect * dstrect, Uint32 color)
+SDL_FillRect(SDL_Surface * dst, const SDL_Rect * rect, Uint32 color)
 {
+    SDL_Rect clipped;
     Uint8 *pixels;
 
+    if (!dst) {
+        SDL_SetError("Passed NULL destination surface");
+        return -1;
+    }
+
     /* This function doesn't work on surfaces < 8 bpp */
     if (dst->format->BitsPerPixel < 8) {
         SDL_SetError("SDL_FillRect(): Unsupported surface format");
-        return (-1);
+        return -1;
     }
 
-    /* If 'dstrect' == NULL, then fill the whole surface */
-    if (dstrect) {
+    /* If 'rect' == NULL, then fill the whole surface */
+    if (rect) {
         /* Perform clipping */
-        if (!SDL_IntersectRect(dstrect, &dst->clip_rect, dstrect)) {
-            return (0);
+        if (!SDL_IntersectRect(rect, &dst->clip_rect, &clipped)) {
+            return 0;
         }
+        rect = &clipped;
     } else {
-        dstrect = &dst->clip_rect;
+        rect = &dst->clip_rect;
     }
 
     /* Perform software fill */
@@ -336,9 +343,8 @@
         return (-1);
     }
 
-    pixels =
-        (Uint8 *) dst->pixels + dstrect->y * dst->pitch +
-        dstrect->x * dst->format->BytesPerPixel;
+    pixels = (Uint8 *) dst->pixels + rect->y * dst->pitch +
+                                     rect->x * dst->format->BytesPerPixel;
 
     switch (dst->format->BytesPerPixel) {
     case 1:
@@ -347,19 +353,17 @@
             color |= (color << 16);
 #ifdef __SSE__
             if (SDL_HasSSE()) {
-                SDL_FillRect1SSE(pixels, dst->pitch, color, dstrect->w,
-                                 dstrect->h);
+                SDL_FillRect1SSE(pixels, dst->pitch, color, rect->w, rect->h);
                 break;
             }
 #endif
 #ifdef __MMX__
             if (SDL_HasMMX()) {
-                SDL_FillRect1MMX(pixels, dst->pitch, color, dstrect->w,
-                                 dstrect->h);
+                SDL_FillRect1MMX(pixels, dst->pitch, color, rect->w, rect->h);
                 break;
             }
 #endif
-            SDL_FillRect1(pixels, dst->pitch, color, dstrect->w, dstrect->h);
+            SDL_FillRect1(pixels, dst->pitch, color, rect->w, rect->h);
             break;
         }
 
@@ -368,26 +372,24 @@
             color |= (color << 16);
 #ifdef __SSE__
             if (SDL_HasSSE()) {
-                SDL_FillRect2SSE(pixels, dst->pitch, color, dstrect->w,
-                                 dstrect->h);
+                SDL_FillRect2SSE(pixels, dst->pitch, color, rect->w, rect->h);
                 break;
             }
 #endif
 #ifdef __MMX__
             if (SDL_HasMMX()) {
-                SDL_FillRect2MMX(pixels, dst->pitch, color, dstrect->w,
-                                 dstrect->h);
+                SDL_FillRect2MMX(pixels, dst->pitch, color, rect->w, rect->h);
                 break;
             }
 #endif
-            SDL_FillRect2(pixels, dst->pitch, color, dstrect->w, dstrect->h);
+            SDL_FillRect2(pixels, dst->pitch, color, rect->w, rect->h);
             break;
         }
 
     case 3:
         /* 24-bit RGB is a slow path, at least for now. */
         {
-            SDL_FillRect3(pixels, dst->pitch, color, dstrect->w, dstrect->h);
+            SDL_FillRect3(pixels, dst->pitch, color, rect->w, rect->h);
             break;
         }
 
@@ -395,25 +397,36 @@
         {
 #ifdef __SSE__
             if (SDL_HasSSE()) {
-                SDL_FillRect4SSE(pixels, dst->pitch, color, dstrect->w,
-                                 dstrect->h);
+                SDL_FillRect4SSE(pixels, dst->pitch, color, rect->w, rect->h);
                 break;
             }
 #endif
 #ifdef __MMX__
             if (SDL_HasMMX()) {
-                SDL_FillRect4MMX(pixels, dst->pitch, color, dstrect->w,
-                                 dstrect->h);
+                SDL_FillRect4MMX(pixels, dst->pitch, color, rect->w, rect->h);
                 break;
             }
 #endif
-            SDL_FillRect4(pixels, dst->pitch, color, dstrect->w, dstrect->h);
+            SDL_FillRect4(pixels, dst->pitch, color, rect->w, rect->h);
             break;
         }
     }
 
     /* We're done! */
-    return (0);
+    return 0;
+}
+
+int
+SDL_FillRects(SDL_Surface * dst, const SDL_Rect ** rects, int count,
+              Uint32 color)
+{
+    int i;
+    int status = 0;
+
+    for (i = 0; i < count; ++i) {
+        status = SDL_FillRect(dst, rects[i], color);
+    }
+    return status;
 }
 
 /* vi: set ts=4 sw=4 expandtab: */
--- a/src/video/SDL_rect.c	Mon Dec 07 10:08:24 2009 +0000
+++ b/src/video/SDL_rect.c	Wed Dec 09 15:56:56 2009 +0000
@@ -119,6 +119,84 @@
 }
 
 SDL_bool
+SDL_EnclosePoints(const SDL_Point * points, int count, const SDL_Rect * clip,
+                  SDL_Rect * result)
+{
+    int minx, miny;
+    int maxx, maxy;
+    int x, y, i;
+
+    if (count < 1) {
+        return SDL_FALSE;
+    }
+
+    if (clip) {
+        SDL_bool added = SDL_FALSE;
+        int clip_minx = clip->x;
+        int clip_miny = clip->y;
+        int clip_maxx = clip->x+clip->w-1;
+        int clip_maxy = clip->y+clip->h-1;
+
+        for (i = 0; i < count; ++i) {
+            x = points[i].x;
+            y = points[i].y;
+
+            if (x < clip_minx || x > clip_maxx ||
+                y < clip_miny || y > clip_maxy) {
+                continue;
+            }
+            if (!added) {
+                minx = maxx = x;
+                miny = maxy = y;
+                added = SDL_TRUE;
+                continue;
+            }
+            if (x < minx) {
+                minx = x;
+            } else if (x > maxx) {
+                maxx = x;
+            }
+            if (y < miny) {
+                miny = y;
+            } else if (y > maxy) {
+                maxy = y;
+            }
+        }
+        if (!added) {
+            return SDL_FALSE;
+        }
+    } else {
+        /* No clipping, always add the first point */
+        minx = maxx = points[0].x;
+        miny = maxy = points[0].y;
+
+        for (i = 1; i < count; ++i) {
+            x = points[i].x;
+            y = points[i].y;
+
+            if (x < minx) {
+                minx = x;
+            } else if (x > maxx) {
+                maxx = x;
+            }
+            if (y < miny) {
+                miny = y;
+            } else if (y > maxy) {
+                maxy = y;
+            }
+        }
+    }
+
+    if (result) {
+        result->x = minx;
+        result->y = miny;
+        result->w = (maxx-minx)+1;
+        result->h = (maxy-miny)+1;
+    }
+    return SDL_TRUE;
+}
+
+SDL_bool
 SDL_IntersectRectAndLine(const SDL_Rect * rect, int *X1, int *Y1, int *X2,
                          int *Y2)
 {
--- a/src/video/SDL_renderer_gl.c	Mon Dec 07 10:08:24 2009 +0000
+++ b/src/video/SDL_renderer_gl.c	Wed Dec 09 15:56:56 2009 +0000
@@ -96,10 +96,12 @@
 static void GL_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture);
 static void GL_DirtyTexture(SDL_Renderer * renderer, SDL_Texture * texture,
                             int numrects, const SDL_Rect * rects);
-static int GL_RenderPoint(SDL_Renderer * renderer, int x, int y);
-static int GL_RenderLine(SDL_Renderer * renderer, int x1, int y1, int x2,
-                         int y2);
-static int GL_RenderFill(SDL_Renderer * renderer, const SDL_Rect * rect);
+static int GL_RenderPoints(SDL_Renderer * renderer, const SDL_Point * points,
+                           int count);
+static int GL_RenderLines(SDL_Renderer * renderer, const SDL_Point * points,
+                          int count);
+static int GL_RenderRects(SDL_Renderer * renderer, const SDL_Rect ** rects,
+                          int count);
 static int GL_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
                          const SDL_Rect * srcrect, const SDL_Rect * dstrect);
 static int GL_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
@@ -304,9 +306,9 @@
     renderer->LockTexture = GL_LockTexture;
     renderer->UnlockTexture = GL_UnlockTexture;
     renderer->DirtyTexture = GL_DirtyTexture;
-    renderer->RenderPoint = GL_RenderPoint;
-    renderer->RenderLine = GL_RenderLine;
-    renderer->RenderFill = GL_RenderFill;
+    renderer->RenderPoints = GL_RenderPoints;
+    renderer->RenderLines = GL_RenderLines;
+    renderer->RenderRects = GL_RenderRects;
     renderer->RenderCopy = GL_RenderCopy;
     renderer->RenderReadPixels = GL_RenderReadPixels;
     renderer->RenderWritePixels = GL_RenderWritePixels;
@@ -1112,9 +1114,10 @@
 }
 
 static int
-GL_RenderPoint(SDL_Renderer * renderer, int x, int y)
+GL_RenderPoints(SDL_Renderer * renderer, const SDL_Point * points, int count)
 {
     GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
+    int i;
 
     GL_SetBlendMode(data, renderer->blendMode, 1);
 
@@ -1124,16 +1127,19 @@
                     (GLfloat) renderer->a * inv255f);
 
     data->glBegin(GL_POINTS);
-    data->glVertex2f(0.5f + x, 0.5f + y);
+    for (i = 0; i < count; ++i) {
+        data->glVertex2f(0.5f + points[i].x, 0.5f + points[i].y);
+    }
     data->glEnd();
 
     return 0;
 }
 
 static int
-GL_RenderLine(SDL_Renderer * renderer, int x1, int y1, int x2, int y2)
+GL_RenderLines(SDL_Renderer * renderer, const SDL_Point * points, int count)
 {
     GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
+    int i;
 
     GL_SetBlendMode(data, renderer->blendMode, 1);
 
@@ -1142,43 +1148,61 @@
                     (GLfloat) renderer->b * inv255f,
                     (GLfloat) renderer->a * inv255f);
 
-    data->glBegin(GL_LINES);
-    data->glVertex2f(0.5f + x1, 0.5f + y1);
-    data->glVertex2f(0.5f + x2, 0.5f + y2);
-    data->glEnd();
+    if (count > 2 && 
+        points[0].x == points[count-1].x && points[0].y == points[count-1].y) {
+        data->glBegin(GL_LINE_LOOP);
+        /* GL_LINE_LOOP takes care of the final segment */
+        --count;
+        for (i = 0; i < count; ++i) {
+            data->glVertex2f(0.5f + points[i].x, 0.5f + points[i].y);
+        }
+        data->glEnd();
+    } else {
+        data->glBegin(GL_LINE_STRIP);
+        for (i = 0; i < count; ++i) {
+            data->glVertex2f(0.5f + points[i].x, 0.5f + points[i].y);
+        }
+        data->glEnd();
 
-    /* The line is half open, so we need one more point to complete the line.
-     * http://www.opengl.org/documentation/specs/version1.1/glspec1.1/node47.html
-     * If we have to, we can use vertical line and horizontal line textures
-     * for vertical and horizontal lines, and then create custom textures
-     * for diagonal lines and software render those.  It's terrible, but at
-     * least it would be pixel perfect.
-     */
-    data->glBegin(GL_POINTS);
+        /* The line is half open, so we need one more point to complete it.
+         * http://www.opengl.org/documentation/specs/version1.1/glspec1.1/node47.html
+         * If we have to, we can use vertical line and horizontal line textures
+         * for vertical and horizontal lines, and then create custom textures
+         * for diagonal lines and software render those.  It's terrible, but at
+         * least it would be pixel perfect.
+         */
+        data->glBegin(GL_POINTS);
 #if defined(__APPLE__) || defined(__WIN32__)
-    /* Mac OS X and Windows seem to always leave the second point open */
-    data->glVertex2f(0.5f + x2, 0.5f + y2);
+        /* Mac OS X and Windows seem to always leave the second point open */
+        data->glVertex2f(0.5f + points[count-1].x, 0.5f + points[count-1].y);
 #else
-    /* Linux seems to leave the right-most or bottom-most point open */
-    if (x1 > x2) {
-        data->glVertex2f(0.5f + x1, 0.5f + y1);
-    } else if (x2 > x1) {
-        data->glVertex2f(0.5f + x2, 0.5f + y2);
-    } else if (y1 > y2) {
-        data->glVertex2f(0.5f + x1, 0.5f + y1);
-    } else if (y2 > y1) {
-        data->glVertex2f(0.5f + x2, 0.5f + y2);
+        /* Linux seems to leave the right-most or bottom-most point open */
+        int x1 = points[0].x;
+        int y1 = points[0].y;
+        int x2 = points[count-1].x;
+        int y2 = points[count-1].y;
+
+        if (x1 > x2) {
+            data->glVertex2f(0.5f + x1, 0.5f + y1);
+        } else if (x2 > x1) {
+            data->glVertex2f(0.5f + x2, 0.5f + y2);
+        } else if (y1 > y2) {
+            data->glVertex2f(0.5f + x1, 0.5f + y1);
+        } else if (y2 > y1) {
+            data->glVertex2f(0.5f + x2, 0.5f + y2);
+        }
+#endif
+        data->glEnd();
     }
-#endif
-    data->glEnd();
 
     return 0;
 }
 
 static int
-GL_RenderFill(SDL_Renderer * renderer, const SDL_Rect * rect)
+GL_RenderRects(SDL_Renderer * renderer, const SDL_Rect ** rects, int count)
 {
     GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
+    int i;
 
     GL_SetBlendMode(data, renderer->blendMode, 1);
 
@@ -1187,7 +1211,11 @@
                     (GLfloat) renderer->b * inv255f,
                     (GLfloat) renderer->a * inv255f);
 
-    data->glRecti(rect->x, rect->y, rect->x + rect->w, rect->y + rect->h);
+    for (i = 0; i < count; ++i) {
+        const SDL_Rect *rect = rects[i];
+
+        data->glRecti(rect->x, rect->y, rect->x + rect->w, rect->y + rect->h);
+    }
 
     return 0;
 }
--- a/src/video/SDL_renderer_gles.c	Mon Dec 07 10:08:24 2009 +0000
+++ b/src/video/SDL_renderer_gles.c	Wed Dec 09 15:56:56 2009 +0000
@@ -85,10 +85,12 @@
                                SDL_Texture * texture);
 static void GLES_DirtyTexture(SDL_Renderer * renderer, SDL_Texture * texture,
                               int numrects, const SDL_Rect * rects);
-static int GLES_RenderPoint(SDL_Renderer * renderer, int x, int y);
-static int GLES_RenderLine(SDL_Renderer * renderer, int x1, int y1, int x2,
-                           int y2);
-static int GLES_RenderFill(SDL_Renderer * renderer, const SDL_Rect * rect);
+static int GLES_RenderPoints(SDL_Renderer * renderer, const SDL_Point * points,
+                             int count);
+static int GLES_RenderLines(SDL_Renderer * renderer, const SDL_Point * points,
+                            int count);
+static int GLES_RenderRects(SDL_Renderer * renderer, const SDL_Rect ** rects,
+                            int count);
 static int GLES_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
                            const SDL_Rect * srcrect,
                            const SDL_Rect * dstrect);
@@ -242,9 +244,9 @@
     renderer->LockTexture = GLES_LockTexture;
     renderer->UnlockTexture = GLES_UnlockTexture;
     renderer->DirtyTexture = GLES_DirtyTexture;
-    renderer->RenderPoint = GLES_RenderPoint;
-    renderer->RenderLine = GLES_RenderLine;
-    renderer->RenderFill = GLES_RenderFill;
+    renderer->RenderPoints = GLES_RenderPoints;
+    renderer->RenderLines = GLES_RenderLines;
+    renderer->RenderRects = GLES_RenderRects;
     renderer->RenderCopy = GLES_RenderCopy;
     renderer->RenderPresent = GLES_RenderPresent;
     renderer->DestroyTexture = GLES_DestroyTexture;
@@ -641,7 +643,7 @@
 }
 
 static int
-GLES_RenderPoint(SDL_Renderer * renderer, int x, int y)
+GLES_RenderPoints(SDL_Renderer * renderer, const SDL_Point * points, int count)
 {
     GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
 
@@ -652,20 +654,16 @@
                     (GLfloat) renderer->b * inv255f,
                     (GLfloat) renderer->a * inv255f);
 
-    GLshort vertices[2];
-    vertices[0] = x;
-    vertices[1] = y;
-
-    data->glVertexPointer(2, GL_SHORT, 0, vertices);
+    data->glVertexPointer(2, GL_INT, 0, points);
     data->glEnableClientState(GL_VERTEX_ARRAY);
-    data->glDrawArrays(GL_POINTS, 0, 1);
+    data->glDrawArrays(GL_POINTS, 0, count);
     data->glDisableClientState(GL_VERTEX_ARRAY);
 
     return 0;
 }
 
 static int
-GLES_RenderLine(SDL_Renderer * renderer, int x1, int y1, int x2, int y2)
+GLES_RenderLines(SDL_Renderer * renderer, const SDL_Point * points, int count)
 {
     GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
 
@@ -676,24 +674,26 @@
                     (GLfloat) renderer->b * inv255f,
                     (GLfloat) renderer->a * inv255f);
 
-    GLshort vertices[4];
-    vertices[0] = x1;
-    vertices[1] = y1;
-    vertices[2] = x2;
-    vertices[3] = y2;
-
-    data->glVertexPointer(2, GL_SHORT, 0, vertices);
+    data->glVertexPointer(2, GL_INT, 0, points);
     data->glEnableClientState(GL_VERTEX_ARRAY);
-    data->glDrawArrays(GL_LINES, 0, 2);
+    if (count > 2 && 
+        points[0].x == points[count-1].x && points[0].y == points[count-1].y) {
+        /* GL_LINE_LOOP takes care of the final segment */
+        --count;
+        data->glDrawArrays(GL_LINE_LOOP, 0, count);
+    } else {
+        data->glDrawArrays(GL_LINE_STRIP, 0, count);
+    }
     data->glDisableClientState(GL_VERTEX_ARRAY);
 
     return 0;
 }
 
 static int
-GLES_RenderFill(SDL_Renderer * renderer, const SDL_Rect * rect)
+GLES_RenderRects(SDL_Renderer * renderer, const SDL_Rect ** rects, int count)
 {
     GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
+    int i;
 
     GLES_SetBlendMode(data, renderer->blendMode, 1);
 
@@ -702,24 +702,26 @@
                     (GLfloat) renderer->b * inv255f,
                     (GLfloat) renderer->a * inv255f);
 
-    GLshort minx = rect->x;
-    GLshort maxx = rect->x + rect->w;
-    GLshort miny = rect->y;
-    GLshort maxy = rect->y + rect->h;
+    data->glEnableClientState(GL_VERTEX_ARRAY);
+    for (i = 0; i < count; ++i) {
+        const SDL_Rect *rect = rects[i];
+        GLshort minx = rect->x;
+        GLshort maxx = rect->x + rect->w;
+        GLshort miny = rect->y;
+        GLshort maxy = rect->y + rect->h;
+        GLshort vertices[8];
+        vertices[0] = minx;
+        vertices[1] = miny;
+        vertices[2] = maxx;
+        vertices[3] = miny;
+        vertices[4] = minx;
+        vertices[5] = maxy;
+        vertices[6] = maxx;
+        vertices[7] = maxy;
 
-    GLshort vertices[8];
-    vertices[0] = minx;
-    vertices[1] = miny;
-    vertices[2] = maxx;
-    vertices[3] = miny;
-    vertices[4] = minx;
-    vertices[5] = maxy;
-    vertices[6] = maxx;
-    vertices[7] = maxy;
-
-    data->glVertexPointer(2, GL_SHORT, 0, vertices);
-    data->glEnableClientState(GL_VERTEX_ARRAY);
-    data->glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+        data->glVertexPointer(2, GL_SHORT, 0, vertices);
+        data->glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+    }
     data->glDisableClientState(GL_VERTEX_ARRAY);
 
     return 0;
--- a/src/video/SDL_renderer_sw.c	Mon Dec 07 10:08:24 2009 +0000
+++ b/src/video/SDL_renderer_sw.c	Wed Dec 09 15:56:56 2009 +0000
@@ -59,10 +59,12 @@
                           const SDL_Rect * rect, int markDirty, void **pixels,
                           int *pitch);
 static void SW_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture);
-static int SW_RenderPoint(SDL_Renderer * renderer, int x, int y);
-static int SW_RenderLine(SDL_Renderer * renderer, int x1, int y1, int x2,
-                         int y2);
-static int SW_RenderFill(SDL_Renderer * renderer, const SDL_Rect * rect);
+static int SW_RenderPoints(SDL_Renderer * renderer, const SDL_Point * points,
+                           int count);
+static int SW_RenderLines(SDL_Renderer * renderer, const SDL_Point * points,
+                          int count);
+static int SW_RenderRects(SDL_Renderer * renderer, const SDL_Rect ** rects,
+                          int count);
 static int SW_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
                          const SDL_Rect * srcrect, const SDL_Rect * dstrect);
 static int SW_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
@@ -228,9 +230,9 @@
     renderer->ActivateRenderer = SW_ActivateRenderer;
     renderer->DisplayModeChanged = SW_DisplayModeChanged;
 
-    renderer->RenderPoint = SW_RenderPoint;
-    renderer->RenderLine = SW_RenderLine;
-    renderer->RenderFill = SW_RenderFill;
+    renderer->RenderPoints = SW_RenderPoints;
+    renderer->RenderLines = SW_RenderLines;
+    renderer->RenderRects = SW_RenderRects;
     renderer->RenderCopy = SW_RenderCopy;
     renderer->RenderReadPixels = SW_RenderReadPixels;
     renderer->RenderWritePixels = SW_RenderWritePixels;
@@ -537,156 +539,189 @@
 }
 
 static int
-SW_RenderPoint(SDL_Renderer * renderer, int x, int y)
+SW_RenderPoints(SDL_Renderer * renderer, const SDL_Point * points, int count)
 {
     SW_RenderData *data = (SW_RenderData *) renderer->driverdata;
+    SDL_Texture *texture = data->texture[data->current_texture];
     SDL_Rect rect;
-    int status;
+    int i;
+    int x, y;
+    int status = 0;
 
-    rect.x = x;
-    rect.y = y;
-    rect.w = 1;
-    rect.h = 1;
+    /* Get the smallest rectangle that contains everything */
+    rect.x = 0;
+    rect.y = 0;
+    rect.w = texture->w;
+    rect.h = texture->h;
+    if (!SDL_EnclosePoints(points, count, &rect, &rect)) {
+        /* Nothing to draw */
+        return 0;
+    }
 
     if (data->renderer->info.flags & SDL_RENDERER_PRESENTCOPY) {
         SDL_AddDirtyRect(&data->dirty, &rect);
     }
 
-    if (data->renderer->LockTexture(data->renderer,
-                                    data->texture[data->current_texture],
-                                    &rect, 1,
+    if (data->renderer->LockTexture(data->renderer, texture, &rect, 1,
                                     &data->surface.pixels,
                                     &data->surface.pitch) < 0) {
         return -1;
     }
 
-    data->surface.w = 1;
-    data->surface.h = 1;
-    data->surface.clip_rect.w = 1;
-    data->surface.clip_rect.h = 1;
+    data->surface.clip_rect.w = data->surface.w = rect.w;
+    data->surface.clip_rect.h = data->surface.h = rect.h;
 
+    /* Draw the points! */
     if (renderer->blendMode == SDL_BLENDMODE_NONE ||
         renderer->blendMode == SDL_BLENDMODE_MASK) {
-        Uint32 color =
-            SDL_MapRGBA(data->surface.format, renderer->r, renderer->g,
-                        renderer->b, renderer->a);
+        Uint32 color = SDL_MapRGBA(data->surface.format,
+                                   renderer->r, renderer->g, renderer->b,
+                                   renderer->a);
+
+        for (i = 0; i < count; ++i) {
+            x = points[i].x - rect.x;
+            y = points[i].y - rect.y;
 
-        status = SDL_DrawPoint(&data->surface, 0, 0, color);
+            status = SDL_DrawPoint(&data->surface, x, y, color);
+        }
     } else {
-        status =
-            SDL_BlendPoint(&data->surface, 0, 0, renderer->blendMode,
-                           renderer->r, renderer->g, renderer->b,
-                           renderer->a);
+        for (i = 0; i < count; ++i) {
+            x = points[i].x - rect.x;
+            y = points[i].y - rect.y;
+
+            status = SDL_BlendPoint(&data->surface, x, y,
+                                    renderer->blendMode,
+                                    renderer->r, renderer->g, renderer->b,
+                                    renderer->a);
+        }
     }
 
-    data->renderer->UnlockTexture(data->renderer,
-                                  data->texture[data->current_texture]);
+    data->renderer->UnlockTexture(data->renderer, texture);
+
     return status;
 }
 
 static int
-SW_RenderLine(SDL_Renderer * renderer, int x1, int y1, int x2, int y2)
+SW_RenderLines(SDL_Renderer * renderer, const SDL_Point * points, int count)
 {
     SW_RenderData *data = (SW_RenderData *) renderer->driverdata;
-    SDL_Rect rect;
-    int status;
+    SDL_Texture *texture = data->texture[data->current_texture];
+    SDL_Rect clip, rect;
+    int i;
+    int x1, y1, x2, y2;
+    int status = 0;
 
-    if (x1 < x2) {
-        rect.x = x1;
-        rect.w = (x2 - x1) + 1;
-        x2 -= x1;
-        x1 = 0;
-    } else {
-        rect.x = x2;
-        rect.w = (x1 - x2) + 1;
-        x1 -= x2;
-        x2 = 0;
-    }
-    if (y1 < y2) {
-        rect.y = y1;
-        rect.h = (y2 - y1) + 1;
-        y2 -= y1;
-        y1 = 0;
-    } else {
-        rect.y = y2;
-        rect.h = (y1 - y2) + 1;
-        y1 -= y2;
-        y2 = 0;
+    /* Get the smallest rectangle that contains everything */
+    clip.x = 0;
+    clip.y = 0;
+    clip.w = texture->w;
+    clip.h = texture->h;
+    SDL_EnclosePoints(points, count, NULL, &rect);
+    if (!SDL_IntersectRect(&rect, &clip, &rect)) {
+        /* Nothing to draw */
+        return 0;
     }
 
     if (data->renderer->info.flags & SDL_RENDERER_PRESENTCOPY) {
         SDL_AddDirtyRect(&data->dirty, &rect);
     }
 
-    if (data->renderer->LockTexture(data->renderer,
-                                    data->texture[data->current_texture],
-                                    &rect, 1,
+    if (data->renderer->LockTexture(data->renderer, texture, &rect, 1,
                                     &data->surface.pixels,
                                     &data->surface.pitch) < 0) {
         return -1;
     }
 
-    data->surface.w = rect.w;
-    data->surface.h = rect.h;
-    data->surface.clip_rect.w = rect.w;
-    data->surface.clip_rect.h = rect.h;
+    data->surface.clip_rect.w = data->surface.w = rect.w;
+    data->surface.clip_rect.h = data->surface.h = rect.h;
 
+    /* Draw the points! */
     if (renderer->blendMode == SDL_BLENDMODE_NONE ||
         renderer->blendMode == SDL_BLENDMODE_MASK) {
-        Uint32 color =
-            SDL_MapRGBA(data->surface.format, renderer->r, renderer->g,
-                        renderer->b, renderer->a);
+        Uint32 color = SDL_MapRGBA(data->surface.format,
+                                   renderer->r, renderer->g, renderer->b,
+                                   renderer->a);
+
+        for (i = 1; i < count; ++i) {
+            x1 = points[i-1].x - rect.x;
+            y1 = points[i-1].y - rect.y;
+            x2 = points[i].x - rect.x;
+            y2 = points[i].y - rect.y;
 
-        status = SDL_DrawLine(&data->surface, x1, y1, x2, y2, color);
+            status = SDL_DrawLine(&data->surface, x1, y1, x2, y2, color);
+        }
     } else {
-        status =
-            SDL_BlendLine(&data->surface, x1, y1, x2, y2, renderer->blendMode,
-                          renderer->r, renderer->g, renderer->b, renderer->a);
+        for (i = 1; i < count; ++i) {
+            x1 = points[i-1].x - rect.x;
+            y1 = points[i-1].y - rect.y;
+            x2 = points[i].x - rect.x;
+            y2 = points[i].y - rect.y;
+
+            status = SDL_BlendLine(&data->surface, x1, y1, x2, y2,
+                                   renderer->blendMode,
+                                   renderer->r, renderer->g, renderer->b,
+                                   renderer->a);
+        }
     }
 
-    data->renderer->UnlockTexture(data->renderer,
-                                  data->texture[data->current_texture]);
+    data->renderer->UnlockTexture(data->renderer, texture);
+
     return status;
 }
 
 static int
-SW_RenderFill(SDL_Renderer * renderer, const SDL_Rect * rect)
+SW_RenderRects(SDL_Renderer * renderer, const SDL_Rect ** rects, int count)
 {
     SW_RenderData *data = (SW_RenderData *) renderer->driverdata;
-    SDL_Rect real_rect;
-    int status;
+    SDL_Texture *texture = data->texture[data->current_texture];
+    SDL_Rect clip, rect;
+    Uint32 color = 0;
+    int i;
+    int status = 0;
 
-    if (data->renderer->info.flags & SDL_RENDERER_PRESENTCOPY) {
-        SDL_AddDirtyRect(&data->dirty, rect);
-    }
+    clip.x = 0;
+    clip.y = 0;
+    clip.w = texture->w;
+    clip.h = texture->h;
 
-    if (data->renderer->LockTexture(data->renderer,
-                                    data->texture[data->current_texture],
-                                    rect, 1, &data->surface.pixels,
-                                    &data->surface.pitch) < 0) {
-        return -1;
+    if (renderer->blendMode == SDL_BLENDMODE_NONE ||
+        renderer->blendMode == SDL_BLENDMODE_MASK) {
+        color = SDL_MapRGBA(data->surface.format,
+                            renderer->r, renderer->g, renderer->b,
+                            renderer->a);
     }
 
-    data->surface.w = rect->w;
-    data->surface.h = rect->h;
-    data->surface.clip_rect.w = rect->w;
-    data->surface.clip_rect.h = rect->h;
-    real_rect = data->surface.clip_rect;
+    for (i = 0; i < count; ++i) {
+        if (!SDL_IntersectRect(rects[i], &clip, &rect)) {
+            /* Nothing to draw */
+            continue;
+        }
+
+        if (data->renderer->info.flags & SDL_RENDERER_PRESENTCOPY) {
+            SDL_AddDirtyRect(&data->dirty, &rect);
+        }
+
+        if (data->renderer->LockTexture(data->renderer, texture, &rect, 1,
+                                        &data->surface.pixels,
+                                        &data->surface.pitch) < 0) {
+            return -1;
+        }
 
-    if (renderer->blendMode == SDL_BLENDMODE_NONE) {
-        Uint32 color =
-            SDL_MapRGBA(data->surface.format, renderer->r, renderer->g,
-                        renderer->b, renderer->a);
+        data->surface.clip_rect.w = data->surface.w = rect.w;
+        data->surface.clip_rect.h = data->surface.h = rect.h;
 
-        status = SDL_FillRect(&data->surface, &real_rect, color);
-    } else {
-        status =
-            SDL_BlendRect(&data->surface, &real_rect, renderer->blendMode,
-                          renderer->r, renderer->g, renderer->b, renderer->a);
+        if (renderer->blendMode == SDL_BLENDMODE_NONE ||
+            renderer->blendMode == SDL_BLENDMODE_MASK) {
+            status = SDL_FillRect(&data->surface, NULL, color);
+        } else {
+            status = SDL_BlendRect(&data->surface, NULL,
+                                   renderer->blendMode,
+                                   renderer->r, renderer->g, renderer->b,
+                                   renderer->a);
+        }
+
+        data->renderer->UnlockTexture(data->renderer, texture);
     }
-
-    data->renderer->UnlockTexture(data->renderer,
-                                  data->texture[data->current_texture]);
     return status;
 }
 
--- a/src/video/SDL_sysvideo.h	Mon Dec 07 10:08:24 2009 +0000
+++ b/src/video/SDL_sysvideo.h	Wed Dec 09 15:56:56 2009 +0000
@@ -90,10 +90,12 @@
                           int numrects, const SDL_Rect * rects);
     int (*SetDrawColor) (SDL_Renderer * renderer);
     int (*SetDrawBlendMode) (SDL_Renderer * renderer);
-    int (*RenderPoint) (SDL_Renderer * renderer, int x, int y);
-    int (*RenderLine) (SDL_Renderer * renderer, int x1, int y1, int x2,
-                       int y2);
-    int (*RenderFill) (SDL_Renderer * renderer, const SDL_Rect * rect);
+    int (*RenderPoints) (SDL_Renderer * renderer, const SDL_Point * points,
+                         int count);
+    int (*RenderLines) (SDL_Renderer * renderer, const SDL_Point * points,
+                        int count);
+    int (*RenderRects) (SDL_Renderer * renderer, const SDL_Rect ** rects,
+                        int count);
     int (*RenderCopy) (SDL_Renderer * renderer, SDL_Texture * texture,
                        const SDL_Rect * srcrect, const SDL_Rect * dstrect);
     int (*RenderReadPixels) (SDL_Renderer * renderer, const SDL_Rect * rect,
--- a/src/video/SDL_video.c	Mon Dec 07 10:08:24 2009 +0000
+++ b/src/video/SDL_video.c	Wed Dec 09 15:56:56 2009 +0000
@@ -2485,82 +2485,118 @@
 int
 SDL_RenderPoint(int x, int y)
 {
+    SDL_Point point;
+
+    point.x = x;
+    point.y = y;
+    return SDL_RenderPoints(&point, 1);
+}
+
+int
+SDL_RenderPoints(const SDL_Point * points, int count)
+{
     SDL_Renderer *renderer;
-    SDL_Window *window;
+
+    if (!points) {
+        SDL_SetError("SDL_RenderPoints(): Passed NULL points");
+        return -1;
+    }
 
     renderer = SDL_GetCurrentRenderer(SDL_TRUE);
     if (!renderer) {
         return -1;
     }
-    if (!renderer->RenderPoint) {
+    if (!renderer->RenderPoints) {
         SDL_Unsupported();
         return -1;
     }
-    window = SDL_GetWindowFromID(renderer->window);
-    if (x < 0 || y < 0 || x >= window->w || y >= window->h) {
+    if (count < 1) {
         return 0;
     }
-    return renderer->RenderPoint(renderer, x, y);
+    return renderer->RenderPoints(renderer, points, count);
 }
 
 int
 SDL_RenderLine(int x1, int y1, int x2, int y2)
 {
+    SDL_Point points[2];
+
+    points[0].x = x1;
+    points[0].y = y1;
+    points[1].x = x2;
+    points[1].y = y2;
+    return SDL_RenderLines(points, 2);
+}
+
+int
+SDL_RenderLines(const SDL_Point * points, int count)
+{
     SDL_Renderer *renderer;
-    SDL_Window *window;
-    SDL_Rect real_rect;
-
-    if (x1 == x2 && y1 == y2) {
-        return SDL_RenderPoint(x1, y1);
+
+    if (!points) {
+        SDL_SetError("SDL_RenderLines(): Passed NULL points");
+        return -1;
     }
 
     renderer = SDL_GetCurrentRenderer(SDL_TRUE);
     if (!renderer) {
         return -1;
     }
-    if (!renderer->RenderLine) {
+    if (!renderer->RenderLines) {
         SDL_Unsupported();
         return -1;
     }
-    window = SDL_GetWindowFromID(renderer->window);
-
-    real_rect.x = 0;
-    real_rect.y = 0;
-    real_rect.w = window->w;
-    real_rect.h = window->h;
-    if (!SDL_IntersectRectAndLine(&real_rect, &x1, &y1, &x2, &y2)) {
-        return (0);
-    }
-    return renderer->RenderLine(renderer, x1, y1, x2, y2);
+    if (count < 2) {
+        return 0;
+    }
+    return renderer->RenderLines(renderer, points, count);
 }
 
 int
-SDL_RenderFill(const SDL_Rect * rect)
+SDL_RenderRect(const SDL_Rect * rect)
+{
+    return SDL_RenderRects(&rect, 1);
+}
+
+int
+SDL_RenderRects(const SDL_Rect ** rects, int count)
 {
     SDL_Renderer *renderer;
-    SDL_Window *window;
-    SDL_Rect real_rect;
+    int i;
+
+    if (!rects) {
+        SDL_SetError("SDL_RenderRects(): Passed NULL rects");
+        return -1;
+    }
 
     renderer = SDL_GetCurrentRenderer(SDL_TRUE);
     if (!renderer) {
         return -1;
     }
-    if (!renderer->RenderFill) {
+    if (!renderer->RenderRects) {
         SDL_Unsupported();
         return -1;
     }
-    window = SDL_GetWindowFromID(renderer->window);
-
-    real_rect.x = 0;
-    real_rect.y = 0;
-    real_rect.w = window->w;
-    real_rect.h = window->h;
-    if (rect) {
-        if (!SDL_IntersectRect(rect, &real_rect, &real_rect)) {
-            return 0;
+    if (count < 1) {
+        return 0;
+    }
+    /* Check for NULL rect, which means fill entire window */
+    for (i = 0; i < count; ++i) {
+        if (rects[i] == NULL) {
+            SDL_Window *window;
+            SDL_Rect full_rect;
+            SDL_Rect *rect;
+
+            window = SDL_GetWindowFromID(renderer->window);
+            full_rect.x = 0;
+            full_rect.y = 0;
+            full_rect.w = window->w;
+            full_rect.h = window->h;
+            rect = &full_rect;
+            return renderer->RenderRects(renderer, &rect, 1);
         }
     }
-    return renderer->RenderFill(renderer, &real_rect);
+    return renderer->RenderRects(renderer, rects, count);
 }
 
 int
--- a/src/video/dummy/SDL_nullrender.c	Mon Dec 07 10:08:24 2009 +0000
+++ b/src/video/dummy/SDL_nullrender.c	Wed Dec 09 15:56:56 2009 +0000
@@ -31,11 +31,12 @@
 
 static SDL_Renderer *SDL_DUMMY_CreateRenderer(SDL_Window * window,
                                               Uint32 flags);
-static int SDL_DUMMY_RenderPoint(SDL_Renderer * renderer, int x, int y);
-static int SDL_DUMMY_RenderLine(SDL_Renderer * renderer, int x1, int y1,
-                                int x2, int y2);
-static int SDL_DUMMY_RenderFill(SDL_Renderer * renderer,
-                                const SDL_Rect * rect);
+static int SDL_DUMMY_RenderPoints(SDL_Renderer * renderer,
+                                  const SDL_Point * points, int count);
+static int SDL_DUMMY_RenderLines(SDL_Renderer * renderer,
+                                 const SDL_Point * points, int count);
+static int SDL_DUMMY_RenderRects(SDL_Renderer * renderer,
+                                 const SDL_Rect ** rects, int count);
 static int SDL_DUMMY_RenderCopy(SDL_Renderer * renderer,
                                 SDL_Texture * texture,
                                 const SDL_Rect * srcrect,
@@ -99,9 +100,9 @@
     }
     SDL_zerop(data);
 
-    renderer->RenderPoint = SDL_DUMMY_RenderPoint;
-    renderer->RenderLine = SDL_DUMMY_RenderLine;
-    renderer->RenderFill = SDL_DUMMY_RenderFill;
+    renderer->RenderPoints = SDL_DUMMY_RenderPoints;
+    renderer->RenderLines = SDL_DUMMY_RenderLines;
+    renderer->RenderRects = SDL_DUMMY_RenderRects;
     renderer->RenderCopy = SDL_DUMMY_RenderCopy;
     renderer->RenderReadPixels = SDL_DUMMY_RenderReadPixels;
     renderer->RenderWritePixels = SDL_DUMMY_RenderWritePixels;
@@ -139,72 +140,70 @@
 }
 
 static int
-SDL_DUMMY_RenderPoint(SDL_Renderer * renderer, int x, int y)
+SDL_DUMMY_RenderPoints(SDL_Renderer * renderer,
+                       const SDL_Point * points, int count)
 {
     SDL_DUMMY_RenderData *data =
         (SDL_DUMMY_RenderData *) renderer->driverdata;
     SDL_Surface *target = data->screens[data->current_screen];
-    int status;
 
     if (renderer->blendMode == SDL_BLENDMODE_NONE ||
         renderer->blendMode == SDL_BLENDMODE_MASK) {
-        Uint32 color =
-            SDL_MapRGBA(target->format, renderer->r, renderer->g, renderer->b,
-                        renderer->a);
+        Uint32 color = SDL_MapRGBA(target->format,
+                                   renderer->r, renderer->g, renderer->b,
+                                   renderer->a);
 
-        status = SDL_DrawPoint(target, x, y, color);
+        return SDL_DrawPoints(target, points, count, color);
     } else {
-        status =
-            SDL_BlendPoint(target, x, y, renderer->blendMode, renderer->r,
-                           renderer->g, renderer->b, renderer->a);
+        return SDL_BlendPoints(target, points, count, renderer->blendMode,
+                               renderer->r, renderer->g, renderer->b,
+                               renderer->a);
     }
-    return status;
 }
 
 static int
-SDL_DUMMY_RenderLine(SDL_Renderer * renderer, int x1, int y1, int x2, int y2)
+SDL_DUMMY_RenderLines(SDL_Renderer * renderer,
+                      const SDL_Point * points, int count)
 {
     SDL_DUMMY_RenderData *data =
         (SDL_DUMMY_RenderData *) renderer->driverdata;
     SDL_Surface *target = data->screens[data->current_screen];
-    int status;
 
     if (renderer->blendMode == SDL_BLENDMODE_NONE ||
         renderer->blendMode == SDL_BLENDMODE_MASK) {
-        Uint32 color =
-            SDL_MapRGBA(target->format, renderer->r, renderer->g, renderer->b,
-                        renderer->a);
+        Uint32 color = SDL_MapRGBA(target->format,
+                                   renderer->r, renderer->g, renderer->b,
+                                   renderer->a);
 
-        status = SDL_DrawLine(target, x1, y1, x2, y2, color);
+        return SDL_DrawLines(target, points, count, color);
     } else {
-        status =
-            SDL_BlendLine(target, x1, y1, x2, y2, renderer->blendMode,
-                          renderer->r, renderer->g, renderer->b, renderer->a);
+        return SDL_BlendLines(target, points, count, renderer->blendMode,
+                              renderer->r, renderer->g, renderer->b,
+                              renderer->a);
     }
-    return status;
 }
 
 static int
-SDL_DUMMY_RenderFill(SDL_Renderer * renderer, const SDL_Rect * rect)
+SDL_DUMMY_RenderRects(SDL_Renderer * renderer, const SDL_Rect ** rects,
+                      int count)
 {
     SDL_DUMMY_RenderData *data =
         (SDL_DUMMY_RenderData *) renderer->driverdata;
     SDL_Surface *target = data->screens[data->current_screen];
-    SDL_Rect real_rect = *rect;
-    int status;
 
-    if (renderer->blendMode == SDL_BLENDMODE_NONE) {
-        Uint32 color =
-            SDL_MapRGBA(target->format, renderer->r, renderer->g, renderer->b,
-                        renderer->a);
+    if (renderer->blendMode == SDL_BLENDMODE_NONE ||
+        renderer->blendMode == SDL_BLENDMODE_MASK) {
+        Uint32 color = SDL_MapRGBA(target->format,
+                                   renderer->r, renderer->g, renderer->b,
+                                   renderer->a);
 
-        status = SDL_FillRect(target, &real_rect, color);
+        return SDL_FillRects(target, rects, count, color);
     } else {
-        status =
-            SDL_BlendRect(target, &real_rect, renderer->blendMode,
-                          renderer->r, renderer->g, renderer->b, renderer->a);
+        return SDL_BlendRects(target, rects, count,
+                              renderer->blendMode,
+                              renderer->r, renderer->g, renderer->b,
+                              renderer->a);
     }
-    return status;
 }
 
 static int
--- a/src/video/win32/SDL_d3drender.c	Mon Dec 07 10:08:24 2009 +0000
+++ b/src/video/win32/SDL_d3drender.c	Wed Dec 09 15:56:56 2009 +0000
@@ -66,10 +66,12 @@
 static void D3D_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture);
 static void D3D_DirtyTexture(SDL_Renderer * renderer, SDL_Texture * texture,
                              int numrects, const SDL_Rect * rects);
-static int D3D_RenderPoint(SDL_Renderer * renderer, int x, int y);
-static int D3D_RenderLine(SDL_Renderer * renderer, int x1, int y1, int x2,
-                          int y2);
-static int D3D_RenderFill(SDL_Renderer * renderer, const SDL_Rect * rect);
+static int D3D_RenderPoints(SDL_Renderer * renderer, const SDL_Point * points,
+                            int count);
+static int D3D_RenderLines(SDL_Renderer * renderer, const SDL_Point * points,
+                           int count);
+static int D3D_RenderRects(SDL_Renderer * renderer, const SDL_Rect ** rects,
+                           int count);
 static int D3D_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
                           const SDL_Rect * srcrect, const SDL_Rect * dstrect);
 static int D3D_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
@@ -407,9 +409,9 @@
     renderer->LockTexture = D3D_LockTexture;
     renderer->UnlockTexture = D3D_UnlockTexture;
     renderer->DirtyTexture = D3D_DirtyTexture;
-    renderer->RenderPoint = D3D_RenderPoint;
-    renderer->RenderLine = D3D_RenderLine;
-    renderer->RenderFill = D3D_RenderFill;
+    renderer->RenderPoints = D3D_RenderPoints;
+    renderer->RenderLines = D3D_RenderLines;
+    renderer->RenderRects = D3D_RenderRects;
     renderer->RenderCopy = D3D_RenderCopy;
     renderer->RenderReadPixels = D3D_RenderReadPixels;
     renderer->RenderWritePixels = D3D_RenderWritePixels;
@@ -927,11 +929,12 @@
 }
 
 static int
-D3D_RenderPoint(SDL_Renderer * renderer, int x, int y)
+D3D_RenderPoints(SDL_Renderer * renderer, const SDL_Point * points, int count)
 {
     D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
     DWORD color;
-    Vertex vertices[1];
+    Vertex *vertices;
+    int i;
     HRESULT result;
 
     if (data->beginScene) {
@@ -939,15 +942,52 @@
         data->beginScene = SDL_FALSE;
     }
 
+    D3D_SetBlendMode(data, renderer->blendMode);
+
+    result =
+        IDirect3DDevice9_SetTexture(data->device, 0,
+                                    (IDirect3DBaseTexture9 *) 0);
+    if (FAILED(result)) {
+        D3D_SetError("SetTexture()", result);
+        return -1;
+    }
+
     color = D3DCOLOR_ARGB(renderer->a, renderer->r, renderer->g, renderer->b);
 
-    vertices[0].x = (float) x;
-    vertices[0].y = (float) y;
-    vertices[0].z = 0.0f;
-    vertices[0].rhw = 1.0f;
-    vertices[0].color = color;
-    vertices[0].u = 0.0f;
-    vertices[0].v = 0.0f;
+    vertices = SDL_stack_alloc(Vertex, count);
+    for (i = 0; i < count; ++i) {
+        vertices[i].x = (float) points[i].x;
+        vertices[i].y = (float) points[i].y;
+        vertices[i].z = 0.0f;
+        vertices[i].rhw = 1.0f;
+        vertices[i].color = color;
+        vertices[i].u = 0.0f;
+        vertices[i].v = 0.0f;
+    }
+    result =
+        IDirect3DDevice9_DrawPrimitiveUP(data->device, D3DPT_POINTLIST, count,
+                                         vertices, sizeof(*vertices));
+    SDL_stack_free(vertices);
+    if (FAILED(result)) {
+        D3D_SetError("DrawPrimitiveUP()", result);
+        return -1;
+    }
+    return 0;
+}
+
+static int
+D3D_RenderLines(SDL_Renderer * renderer, const SDL_Point * points, int count)
+{
+    D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
+    DWORD color;
+    Vertex *vertices;
+    int i;
+    HRESULT result;
+
+    if (data->beginScene) {
+        IDirect3DDevice9_BeginScene(data->device);
+        data->beginScene = SDL_FALSE;
+    }
 
     D3D_SetBlendMode(data, renderer->blendMode);
 
@@ -958,9 +998,23 @@
         D3D_SetError("SetTexture()", result);
         return -1;
     }
+
+    color = D3DCOLOR_ARGB(renderer->a, renderer->r, renderer->g, renderer->b);
+
+    vertices = SDL_stack_alloc(Vertex, count);
+    for (i = 0; i < count; ++i) {
+        vertices[i].x = (float) points[i].x;
+        vertices[i].y = (float) points[i].y;
+        vertices[i].z = 0.0f;
+        vertices[i].rhw = 1.0f;
+        vertices[i].color = color;
+        vertices[i].u = 0.0f;
+        vertices[i].v = 0.0f;
+    }
     result =
-        IDirect3DDevice9_DrawPrimitiveUP(data->device, D3DPT_POINTLIST, 1,
+        IDirect3DDevice9_DrawPrimitiveUP(data->device, D3DPT_LINESTRIP, count,
                                          vertices, sizeof(*vertices));
+    SDL_stack_free(vertices);
     if (FAILED(result)) {
         D3D_SetError("DrawPrimitiveUP()", result);
         return -1;
@@ -969,11 +1023,13 @@
 }
 
 static int
-D3D_RenderLine(SDL_Renderer * renderer, int x1, int y1, int x2, int y2)
+D3D_RenderRects(SDL_Renderer * renderer, const SDL_Rect ** rects, int count)
 {
     D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
     DWORD color;
-    Vertex vertices[2];
+    int i;
+    float minx, miny, maxx, maxy;
+    Vertex vertices[4];
     HRESULT result;
 
     if (data->beginScene) {
@@ -981,24 +1037,6 @@
         data->beginScene = SDL_FALSE;
     }
 
-    color = D3DCOLOR_ARGB(renderer->a, renderer->r, renderer->g, renderer->b);
-
-    vertices[0].x = (float) x1;
-    vertices[0].y = (float) y1;
-    vertices[0].z = 0.0f;
-    vertices[0].rhw = 1.0f;
-    vertices[0].color = color;
-    vertices[0].u = 0.0f;
-    vertices[0].v = 0.0f;
-
-    vertices[1].x = (float) x2;
-    vertices[1].y = (float) y2;
-    vertices[1].z = 0.0f;
-    vertices[1].rhw = 1.0f;
-    vertices[1].color = color;
-    vertices[1].u = 0.0f;
-    vertices[1].v = 0.0f;
-
     D3D_SetBlendMode(data, renderer->blendMode);
 
     result =
@@ -1008,84 +1046,56 @@
         D3D_SetError("SetTexture()", result);
         return -1;
     }
-    result =
-        IDirect3DDevice9_DrawPrimitiveUP(data->device, D3DPT_LINELIST, 1,
-                                         vertices, sizeof(*vertices));
-    if (FAILED(result)) {
-        D3D_SetError("DrawPrimitiveUP()", result);
-        return -1;
-    }
-    return 0;
-}
-
-static int
-D3D_RenderFill(SDL_Renderer * renderer, const SDL_Rect * rect)
-{
-    D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;
-    float minx, miny, maxx, maxy;
-    DWORD color;
-    Vertex vertices[4];
-    HRESULT result;
-
-    if (data->beginScene) {
-        IDirect3DDevice9_BeginScene(data->device);
-        data->beginScene = SDL_FALSE;
-    }
-
-    minx = (float) rect->x;
-    miny = (float) rect->y;
-    maxx = (float) rect->x + rect->w;
-    maxy = (float) rect->y + rect->h;
 
     color = D3DCOLOR_ARGB(renderer->a, renderer->r, renderer->g, renderer->b);
 
-    vertices[0].x = minx;
-    vertices[0].y = miny;
-    vertices[0].z = 0.0f;
-    vertices[0].rhw = 1.0f;
-    vertices[0].color = color;
-    vertices[0].u = 0.0f;
-    vertices[0].v = 0.0f;
+    for (i = 0; i < count; ++i) {
+        const SDL_Rect *rect = rects[i];
+
+        minx = (float) rect->x;
+        miny = (float) rect->y;
+        maxx = (float) rect->x + rect->w;
+        maxy = (float) rect->y + rect->h;
 
-    vertices[1].x = maxx;
-    vertices[1].y = miny;
-    vertices[1].z = 0.0f;
-    vertices[1].rhw = 1.0f;
-    vertices[1].color = color;
-    vertices[1].u = 0.0f;
-    vertices[1].v = 0.0f;
+        vertices[0].x = minx;
+        vertices[0].y = miny;
+        vertices[0].z = 0.0f;
+        vertices[0].rhw = 1.0f;
+        vertices[0].color = color;
+        vertices[0].u = 0.0f;
+        vertices[0].v = 0.0f;
 
-    vertices[2].x = maxx;
-    vertices[2].y = maxy;
-    vertices[2].z = 0.0f;
-    vertices[2].rhw = 1.0f;
-    vertices[2].color = color;
-    vertices[2].u = 0.0f;
-    vertices[2].v = 0.0f;
+        vertices[1].x = maxx;
+        vertices[1].y = miny;
+        vertices[1].z = 0.0f;
+        vertices[1].rhw = 1.0f;
+        vertices[1].color = color;
+        vertices[1].u = 0.0f;
+        vertices[1].v = 0.0f;
 
-    vertices[3].x = minx;
-    vertices[3].y = maxy;
-    vertices[3].z = 0.0f;
-    vertices[3].rhw = 1.0f;
-    vertices[3].color = color;
-    vertices[3].u = 0.0f;
-    vertices[3].v = 0.0f;
-
-    D3D_SetBlendMode(data, renderer->blendMode);
+        vertices[2].x = maxx;
+        vertices[2].y = maxy;
+        vertices[2].z = 0.0f;
+        vertices[2].rhw = 1.0f;
+        vertices[2].color = color;
+        vertices[2].u = 0.0f;
+        vertices[2].v = 0.0f;
 
-    result =
-        IDirect3DDevice9_SetTexture(data->device, 0,
-                                    (IDirect3DBaseTexture9 *) 0);
-    if (FAILED(result)) {
-        D3D_SetError("SetTexture()", result);
-        return -1;
-    }
-    result =
-        IDirect3DDevice9_DrawPrimitiveUP(data->device, D3DPT_TRIANGLEFAN, 2,
-                                         vertices, sizeof(*vertices));
-    if (FAILED(result)) {
-        D3D_SetError("DrawPrimitiveUP()", result);
-        return -1;
+        vertices[3].x = minx;
+        vertices[3].y = maxy;
+        vertices[3].z = 0.0f;
+        vertices[3].rhw = 1.0f;
+        vertices[3].color = color;
+        vertices[3].u = 0.0f;
+        vertices[3].v = 0.0f;
+
+        result =
+            IDirect3DDevice9_DrawPrimitiveUP(data->device, D3DPT_TRIANGLEFAN,
+                                             2, vertices, sizeof(*vertices));
+        if (FAILED(result)) {
+            D3D_SetError("DrawPrimitiveUP()", result);
+            return -1;
+        }
     }
     return 0;
 }
--- a/src/video/win32/SDL_gdirender.c	Mon Dec 07 10:08:24 2009 +0000
+++ b/src/video/win32/SDL_gdirender.c	Wed Dec 09 15:56:56 2009 +0000
@@ -61,10 +61,12 @@
                            void **pixels, int *pitch);
 static void GDI_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture);
 static int GDI_SetDrawBlendMode(SDL_Renderer * renderer);
-static int GDI_RenderPoint(SDL_Renderer * renderer, int x, int y);
-static int GDI_RenderLine(SDL_Renderer * renderer, int x1, int y1, int x2,
-                          int y2);
-static int GDI_RenderFill(SDL_Renderer * renderer, const SDL_Rect * rect);
+static int GDI_RenderPoints(SDL_Renderer * renderer, const SDL_Point * points,
+                            int count);
+static int GDI_RenderLines(SDL_Renderer * renderer, const SDL_Point * points,
+                           int count);
+static int GDI_RenderRects(SDL_Renderer * renderer, const SDL_Rect ** rects,
+                           int count);
 static int GDI_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
                           const SDL_Rect * srcrect, const SDL_Rect * dstrect);
 static int GDI_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
@@ -192,9 +194,9 @@
     renderer->LockTexture = GDI_LockTexture;
     renderer->UnlockTexture = GDI_UnlockTexture;
     renderer->SetDrawBlendMode = GDI_SetDrawBlendMode;
-    renderer->RenderPoint = GDI_RenderPoint;
-    renderer->RenderLine = GDI_RenderLine;
-    renderer->RenderFill = GDI_RenderFill;
+    renderer->RenderPoints = GDI_RenderPoints;
+    renderer->RenderLines = GDI_RenderLines;
+    renderer->RenderRects = GDI_RenderRects;
     renderer->RenderCopy = GDI_RenderCopy;
     renderer->RenderReadPixels = GDI_RenderReadPixels;
     renderer->RenderWritePixels = GDI_RenderWritePixels;
@@ -685,96 +687,128 @@
 }
 
 static int
-GDI_RenderPoint(SDL_Renderer * renderer, int x, int y)
+GDI_RenderPoints(SDL_Renderer * renderer, const SDL_Point * points, int count)
 {
     GDI_RenderData *data = (GDI_RenderData *) renderer->driverdata;
+    int i;
+    COLORREF color;
 
     if (data->makedirty) {
+        /* Get the smallest rectangle that contains everything */
+        SDL_Window *window = SDL_GetWindowFromID(renderer->window);
         SDL_Rect rect;
 
-        rect.x = x;
-        rect.y = y;
-        rect.w = 1;
-        rect.h = 1;
+        rect.x = 0;
+        rect.y = 0;
+        rect.w = window->w;
+        rect.h = window->h;
+        if (!SDL_EnclosePoints(points, count, &rect, &rect)) {
+            /* Nothing to draw */
+            return 0;
+        }
 
         SDL_AddDirtyRect(&data->dirty, &rect);
     }
 
-    SetPixel(data->current_hdc, x, y,
-             RGB(renderer->r, renderer->g, renderer->b));
+    color = RGB(renderer->r, renderer->g, renderer->b);
+    for (i = 0; i < count; ++i) {
+        SetPixel(data->current_hdc, points[i].x, points[i].y, color);
+    }
+
     return 0;
 }
 
 static int
-GDI_RenderLine(SDL_Renderer * renderer, int x1, int y1, int x2, int y2)
+GDI_RenderLines(SDL_Renderer * renderer, const SDL_Point * points, int count)
 {
     GDI_RenderData *data = (GDI_RenderData *) renderer->driverdata;
-    POINT points[2];
     HPEN pen;
     BOOL status;
 
     if (data->makedirty) {
-        SDL_Rect rect;
+        /* Get the smallest rectangle that contains everything */
+        SDL_Window *window = SDL_GetWindowFromID(renderer->window);
+        SDL_Rect clip, rect;
 
-        if (x1 < x2) {
-            rect.x = x1;
-            rect.w = (x2 - x1) + 1;
-        } else {
-            rect.x = x2;
-            rect.w = (x1 - x2) + 1;
+        clip.x = 0;
+        clip.y = 0;
+        clip.w = window->w;
+        clip.h = window->h;
+        SDL_EnclosePoints(points, count, NULL, &rect);
+        if (!SDL_IntersectRect(&rect, &clip, &rect)) {
+            /* Nothing to draw */
+            return 0;
         }
-        if (y1 < y2) {
-            rect.y = y1;
-            rect.h = (y2 - y1) + 1;
-        } else {
-            rect.y = y2;
-            rect.h = (y1 - y2) + 1;
-        }
+
         SDL_AddDirtyRect(&data->dirty, &rect);
     }
 
     /* Should we cache the pen? .. it looks like GDI does for us. :) */
     pen = CreatePen(PS_SOLID, 1, RGB(renderer->r, renderer->g, renderer->b));
     SelectObject(data->current_hdc, pen);
-    points[0].x = x1;
-    points[0].y = y1;
-    points[1].x = x2;
-    points[1].y = y2;
-    status = Polyline(data->current_hdc, points, 2);
+    {
+        LPPOINT p = SDL_stack_alloc(POINT, count);
+        int i;
+
+        for (i = 0; i < count; ++i) {
+            p[i].x = points[i].x;
+            p[i].y = points[i].y;
+        }
+        status = Polyline(data->current_hdc, p, count);
+        SDL_stack_free(p);
+    }
     DeleteObject(pen);
 
     /* Need to close the endpoint of the line */
-    SetPixel(data->current_hdc, x2, y2,
-             RGB(renderer->r, renderer->g, renderer->b));
+    if (points[0].x != points[count-1].x || points[0].y != points[count-1].y) {
+        SetPixel(data->current_hdc, points[count-1].x, points[count-1].y,
+                 RGB(renderer->r, renderer->g, renderer->b));
+    }
 
     if (!status) {
-        WIN_SetError("FillRect()");
+        WIN_SetError("Polyline()");
         return -1;
     }
     return 0;
 }
 
 static int
-GDI_RenderFill(SDL_Renderer * renderer, const SDL_Rect * rect)
+GDI_RenderRects(SDL_Renderer * renderer, const SDL_Rect ** rects, int count)
 {
     GDI_RenderData *data = (GDI_RenderData *) renderer->driverdata;
     RECT rc;
     HBRUSH brush;
-    int status;
+    int i, status = 1;
 
     if (data->makedirty) {
-        SDL_AddDirtyRect(&data->dirty, rect);
-    }
+        SDL_Window *window = SDL_GetWindowFromID(renderer->window);
+        SDL_Rect clip, rect;
 
-    rc.left = rect->x;
-    rc.top = rect->y;
-    rc.right = rect->x + rect->w;
-    rc.bottom = rect->y + rect->h;
+        clip.x = 0;
+        clip.y = 0;
+        clip.w = window->w;
+        clip.h = window->h;
+
+        for (i = 0; i < count; ++i) {
+            if (SDL_IntersectRect(rects[i], &clip, &rect)) {
+                SDL_AddDirtyRect(&data->dirty, &rect);
+            }
+        }
+    }
 
     /* Should we cache the brushes? .. it looks like GDI does for us. :) */
     brush = CreateSolidBrush(RGB(renderer->r, renderer->g, renderer->b));
     SelectObject(data->current_hdc, brush);
-    status = FillRect(data->current_hdc, &rc, brush);
+    for (i = 0; i < count; ++i) {
+        const SDL_Rect *rect = rects[i];
+
+        rc.left = rect->x;
+        rc.top = rect->y;
+        rc.right = rect->x + rect->w;
+        rc.bottom = rect->y + rect->h;
+
+        status &= FillRect(data->current_hdc, &rc, brush);
+    }
     DeleteObject(brush);
 
     if (!status) {
--- a/test/automated/render/render.c	Mon Dec 07 10:08:24 2009 +0000
+++ b/test/automated/render/render.c	Wed Dec 09 15:56:56 2009 +0000
@@ -340,9 +340,9 @@
    */
 
    /* Clear screen. */
-   ret = SDL_RenderFill( NULL );
+   ret = SDL_RenderRect( NULL );
    /*
-   if (SDL_ATassert( "SDL_RenderFill", ret == 0))
+   if (SDL_ATassert( "SDL_RenderRect", ret == 0))
       return -1;
    */
 
@@ -387,7 +387,7 @@
    ret = SDL_SetRenderDrawColor( 13, 73, 200, SDL_ALPHA_OPAQUE );
    if (SDL_ATassert( "SDL_SetRenderDrawColor", ret == 0))
       return -1;
-   ret = SDL_RenderFill( &rect );
+   ret = SDL_RenderRect( &rect );
    if (SDL_ATassert( "SDL_RenderRect", ret == 0))
       return -1;
 
@@ -399,7 +399,7 @@
    ret = SDL_SetRenderDrawColor( 200, 0, 100, SDL_ALPHA_OPAQUE );
    if (SDL_ATassert( "SDL_SetRenderDrawColor", ret == 0))
       return -1;
-   ret = SDL_RenderFill( &rect );
+   ret = SDL_RenderRect( &rect );
    if (SDL_ATassert( "SDL_RenderRect", ret == 0))
       return -1;
 
@@ -480,8 +480,8 @@
    ret = SDL_SetRenderDrawBlendMode( SDL_BLENDMODE_NONE );
    if (SDL_ATassert( "SDL_SetRenderDrawBlendMode", ret == 0))
       return -1;
-   ret = SDL_RenderFill( NULL );
-   if (SDL_ATassert( "SDL_RenderFill", ret == 0))
+   ret = SDL_RenderRect( NULL );
+   if (SDL_ATassert( "SDL_RenderRect", ret == 0))
       return -1;
    rect.x = 10;
    rect.y = 25;
@@ -493,8 +493,8 @@
    ret = SDL_SetRenderDrawBlendMode( SDL_BLENDMODE_ADD );
    if (SDL_ATassert( "SDL_SetRenderDrawBlendMode", ret == 0))
       return -1;
-   ret = SDL_RenderFill( &rect );
-   if (SDL_ATassert( "SDL_RenderFill", ret == 0))
+   ret = SDL_RenderRect( &rect );
+   if (SDL_ATassert( "SDL_RenderRect", ret == 0))
       return -1;
    rect.x = 30;
    rect.y = 40;
@@ -506,8 +506,8 @@
    ret = SDL_SetRenderDrawBlendMode( SDL_BLENDMODE_BLEND );
    if (SDL_ATassert( "SDL_SetRenderDrawBlendMode", ret == 0))
       return -1;
-   ret = SDL_RenderFill( &rect );
-   if (SDL_ATassert( "SDL_RenderFill", ret == 0))
+   ret = SDL_RenderRect( &rect );
+   if (SDL_ATassert( "SDL_RenderRect", ret == 0))
       return -1;
    rect.x = 25;
    rect.y = 25;
@@ -519,8 +519,8 @@
    ret = SDL_SetRenderDrawBlendMode( SDL_BLENDMODE_MOD );
    if (SDL_ATassert( "SDL_SetRenderDrawBlendMode", ret == 0))
       return -1;
-   ret = SDL_RenderFill( &rect );
-   if (SDL_ATassert( "SDL_RenderFill", ret == 0))
+   ret = SDL_RenderRect( &rect );
+   if (SDL_ATassert( "SDL_RenderRect", ret == 0))
       return -1;
 
    /* Draw blended lines, lines for everyone. */
--- a/test/testdraw2.c	Mon Dec 07 10:08:24 2009 +0000
+++ b/test/testdraw2.c	Wed Dec 09 15:56:56 2009 +0000
@@ -159,7 +159,7 @@
         rect.h = rand() % (window_h / 2);
         rect.x = (rand() % window_w) - (rect.w / 2);
         rect.y = (rand() % window_w) - (rect.h / 2);
-        SDL_RenderFill(&rect);
+        SDL_RenderRect(&rect);
     }
     SDL_SetRenderDrawBlendMode(SDL_BLENDMODE_NONE);
 }
@@ -231,7 +231,7 @@
     for (i = 0; i < state->num_windows; ++i) {
         SDL_SelectRenderer(state->windows[i]);
         SDL_SetRenderDrawColor(0xA0, 0xA0, 0xA0, 0xFF);
-        SDL_RenderFill(NULL);
+        SDL_RenderRect(NULL);
     }
 
     srand(time(NULL));
@@ -251,7 +251,7 @@
                 case SDL_WINDOWEVENT_EXPOSED:
                     SDL_SelectRenderer(event.window.windowID);
                     SDL_SetRenderDrawColor(0xA0, 0xA0, 0xA0, 0xFF);
-                    SDL_RenderFill(NULL);
+                    SDL_RenderRect(NULL);
                     break;
                 }
                 break;
@@ -262,7 +262,7 @@
         for (i = 0; i < state->num_windows; ++i) {
             SDL_SelectRenderer(state->windows[i]);
             SDL_SetRenderDrawColor(0xA0, 0xA0, 0xA0, 0xFF);
-            SDL_RenderFill(NULL);
+            SDL_RenderRect(NULL);
 
             DrawRects(state->windows[i]);
             DrawLines(state->windows[i]);
--- a/test/testintersections.c	Mon Dec 07 10:08:24 2009 +0000
+++ b/test/testintersections.c	Wed Dec 09 15:56:56 2009 +0000
@@ -150,7 +150,7 @@
     SDL_SetRenderDrawBlendMode(SDL_BLENDMODE_NONE);
     for (i = 0; i < num_rects; ++i) {
         SDL_SetRenderDrawColor(255, 127, 0, 255);
-        SDL_RenderFill(&rects[i]);
+        SDL_RenderRect(&rects[i]);
     }
     SDL_SetRenderDrawBlendMode(SDL_BLENDMODE_NONE);
 }
@@ -197,7 +197,7 @@
             SDL_Rect r;
             if (SDL_IntersectRect(&rects[i], &rects[j], &r)) {
                 SDL_SetRenderDrawColor(255, 200, 0, 255);
-                SDL_RenderFill(&r);
+                SDL_RenderRect(&r);
             }
         }
 
@@ -272,7 +272,7 @@
     for (i = 0; i < state->num_windows; ++i) {
         SDL_SelectRenderer(state->windows[i]);
         SDL_SetRenderDrawColor(0xA0, 0xA0, 0xA0, 0xFF);
-        SDL_RenderFill(NULL);
+        SDL_RenderRect(NULL);
     }
 
     srand(time(NULL));
@@ -326,7 +326,7 @@
                 case SDL_WINDOWEVENT_EXPOSED:
                     SDL_SelectRenderer(event.window.windowID);
                     SDL_SetRenderDrawColor(0xA0, 0xA0, 0xA0, 0xFF);
-                    SDL_RenderFill(NULL);
+                    SDL_RenderRect(NULL);
                     break;
                 }
                 break;
@@ -337,7 +337,7 @@
         for (i = 0; i < state->num_windows; ++i) {
             SDL_SelectRenderer(state->windows[i]);
             SDL_SetRenderDrawColor(0xA0, 0xA0, 0xA0, 0xFF);
-            SDL_RenderFill(NULL);
+            SDL_RenderRect(NULL);
 
             DrawRects(state->windows[i]);
             DrawPoints(state->windows[i]);
--- a/test/testnative.c	Mon Dec 07 10:08:24 2009 +0000
+++ b/test/testnative.c	Wed Dec 09 15:56:56 2009 +0000
@@ -83,7 +83,7 @@
     /* Move the sprite, bounce at the wall, and draw */
     n = 0;
     SDL_SetRenderDrawColor(0xA0, 0xA0, 0xA0, 0xFF);
-    SDL_RenderFill(NULL);
+    SDL_RenderRect(NULL);
     for (i = 0; i < NUM_SPRITES; ++i) {
         position = &positions[i];
         velocity = &velocities[i];
@@ -158,7 +158,7 @@
     /* Clear the window, load the sprite and go! */
     SDL_SelectRenderer(window);
     SDL_SetRenderDrawColor(0xA0, 0xA0, 0xA0, 0xFF);
-    SDL_RenderFill(NULL);
+    SDL_RenderRect(NULL);
 
     sprite = LoadSprite(window, "icon.bmp");
     if (!sprite) {
@@ -199,7 +199,7 @@
                 case SDL_WINDOWEVENT_EXPOSED:
                     SDL_SelectRenderer(event.window.windowID);
                     SDL_SetRenderDrawColor(0xA0, 0xA0, 0xA0, 0xFF);
-                    SDL_RenderFill(NULL);
+                    SDL_RenderRect(NULL);
                     break;
                 }
                 break;
--- a/test/testsprite2.c	Mon Dec 07 10:08:24 2009 +0000
+++ b/test/testsprite2.c	Wed Dec 09 15:56:56 2009 +0000
@@ -141,7 +141,7 @@
 
     /* Draw a gray background */
     SDL_SetRenderDrawColor(0xA0, 0xA0, 0xA0, 0xFF);
-    SDL_RenderFill(NULL);
+    SDL_RenderRect(NULL);
 
     /* Test points */
     SDL_SetRenderDrawColor(0xFF, 0x00, 0x00, 0xFF);
@@ -163,25 +163,25 @@
     temp.y = 1;
     temp.w = sprite_w;
     temp.h = sprite_h;
-    SDL_RenderFill(&temp);
+    SDL_RenderRect(&temp);
     SDL_RenderCopy(sprite, NULL, &temp);
     temp.x = window_w-sprite_w-1;
     temp.y = 1;
     temp.w = sprite_w;
     temp.h = sprite_h;
-    SDL_RenderFill(&temp);
+    SDL_RenderRect(&temp);
     SDL_RenderCopy(sprite, NULL, &temp);
     temp.x = 1;
     temp.y = window_h-sprite_h-1;
     temp.w = sprite_w;
     temp.h = sprite_h;
-    SDL_RenderFill(&temp);
+    SDL_RenderRect(&temp);
     SDL_RenderCopy(sprite, NULL, &temp);
     temp.x = window_w-sprite_w-1;
     temp.y = window_h-sprite_h-1;
     temp.w = sprite_w;
     temp.h = sprite_h;
-    SDL_RenderFill(&temp);
+    SDL_RenderRect(&temp);
     SDL_RenderCopy(sprite, NULL, &temp);
 
     /* Test diagonal lines */
@@ -304,7 +304,7 @@
     for (i = 0; i < state->num_windows; ++i) {
         SDL_SelectRenderer(state->windows[i]);
         SDL_SetRenderDrawColor(0xA0, 0xA0, 0xA0, 0xFF);
-        SDL_RenderFill(NULL);
+        SDL_RenderRect(NULL);
     }
     if (LoadSprite("icon.bmp") < 0) {
         quit(2);
@@ -350,7 +350,7 @@
                 case SDL_WINDOWEVENT_EXPOSED:
                     SDL_SelectRenderer(event.window.windowID);
                     SDL_SetRenderDrawColor(0xA0, 0xA0, 0xA0, 0xFF);
-                    SDL_RenderFill(NULL);
+                    SDL_RenderRect(NULL);
                     break;
                 }
                 break;
--- a/test/testspriteminimal.c	Mon Dec 07 10:08:24 2009 +0000
+++ b/test/testspriteminimal.c	Wed Dec 09 15:56:56 2009 +0000
@@ -87,7 +87,7 @@
 
     /* Draw a gray background */
     SDL_SetRenderDrawColor(0xA0, 0xA0, 0xA0, 0xFF);
-    SDL_RenderFill(NULL);
+    SDL_RenderRect(NULL);
 
     /* Move the sprite, bounce at the wall, and draw */
     for (i = 0; i < NUM_SPRITES; ++i) {