Added stubs for software implementations of blending fills and line drawing
authorSam Lantinga <slouken@libsdl.org>
Sat, 20 Dec 2008 13:14:28 +0000
changeset 2888 32e8bbba1e94
parent 2887 f8c0c5ef6d54
child 2889 67f84eb26ea1
Added stubs for software implementations of blending fills and line drawing
include/SDL_surface.h
src/video/SDL_blendline.c
src/video/SDL_blendrect.c
src/video/SDL_drawline.c
src/video/SDL_fill.c
src/video/SDL_fillrect.c
src/video/SDL_renderer_sw.c
src/video/dummy/SDL_nullrender.c
src/video/x11/SDL_x11render.c
--- a/include/SDL_surface.h	Sat Dec 20 12:32:53 2008 +0000
+++ b/include/SDL_surface.h	Sat Dec 20 13:14:28 2008 +0000
@@ -366,6 +366,23 @@
     (SDL_Surface * src, SDL_PixelFormat * fmt, Uint32 flags);
 
 /*
+ * This function draws a line with 'color'
+ * The color should be a pixel of the format used by the surface, and 
+ * can be generated by the SDL_MapRGB() function.
+ * This function returns 0 on success, or -1 on error.
+ */
+extern DECLSPEC int SDLCALL SDL_DrawLine
+    (SDL_Surface * dst, int x1, int y1, int x2, int y2, Uint32 color);
+
+/*
+ * This function blends an RGBA value along a line
+ * This function returns 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);
+
+/*
  * This function performs a fast fill of the given rectangle with 'color'
  * The given rectangle is clipped to the destination surface clip area
  * and the final fill rectangle is saved in the passed in pointer.
@@ -378,6 +395,17 @@
     (SDL_Surface * dst, SDL_Rect * dstrect, Uint32 color);
 
 /*
+ * This function 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 'dstrect' is NULL, the whole surface will be filled with 'color'
+ * 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);
+
+/*
  * This performs a fast blit from the source surface to the destination
  * surface.  It assumes that the source and destination rectangles are
  * the same size.  If either 'srcrect' or 'dstrect' are NULL, the entire
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/video/SDL_blendline.c	Sat Dec 20 13:14:28 2008 +0000
@@ -0,0 +1,49 @@
+/*
+    SDL - Simple DirectMedia Layer
+    Copyright (C) 1997-2009 Sam Lantinga
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+    Sam Lantinga
+    slouken@libsdl.org
+*/
+#include "SDL_config.h"
+
+#include "SDL_video.h"
+#include "SDL_blit.h"
+
+
+int
+SDL_BlendLine(SDL_Surface * dst, int x1, int y1, int x2, int y2,
+              int blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
+{
+    /* This function doesn't work on surfaces < 8 bpp */
+    if (dst->format->BitsPerPixel < 8) {
+        SDL_SetError("SDL_BlendLine(): Unsupported surface format");
+        return (-1);
+    }
+
+    /* Perform clipping */
+    /* FIXME
+       if (!SDL_IntersectRect(dstrect, &dst->clip_rect, dstrect)) {
+       return (0);
+       }
+     */
+
+    SDL_Unsupported();
+    return -1;
+}
+
+/* vi: set ts=4 sw=4 expandtab: */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/video/SDL_blendrect.c	Sat Dec 20 13:14:28 2008 +0000
@@ -0,0 +1,52 @@
+/*
+    SDL - Simple DirectMedia Layer
+    Copyright (C) 1997-2009 Sam Lantinga
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+    Sam Lantinga
+    slouken@libsdl.org
+*/
+#include "SDL_config.h"
+
+#include "SDL_video.h"
+#include "SDL_blit.h"
+
+
+int
+SDL_BlendRect(SDL_Surface * dst, SDL_Rect * dstrect, int blendMode, Uint8 r,
+              Uint8 g, Uint8 b, Uint8 a)
+{
+    /* This function doesn't work on surfaces < 8 bpp */
+    if (dst->format->BitsPerPixel < 8) {
+        SDL_SetError("SDL_BlendRect(): Unsupported surface format");
+        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;
+    }
+
+    SDL_Unsupported();
+    return -1;
+}
+
+/* vi: set ts=4 sw=4 expandtab: */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/video/SDL_drawline.c	Sat Dec 20 13:14:28 2008 +0000
@@ -0,0 +1,48 @@
+/*
+    SDL - Simple DirectMedia Layer
+    Copyright (C) 1997-2009 Sam Lantinga
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+    Sam Lantinga
+    slouken@libsdl.org
+*/
+#include "SDL_config.h"
+
+#include "SDL_video.h"
+#include "SDL_blit.h"
+
+
+int
+SDL_DrawLine(SDL_Surface * dst, int x1, int y1, int x2, int y2, Uint32 color)
+{
+    /* This function doesn't work on surfaces < 8 bpp */
+    if (dst->format->BitsPerPixel < 8) {
+        SDL_SetError("SDL_DrawLine(): Unsupported surface format");
+        return (-1);
+    }
+
+    /* Perform clipping */
+    /* FIXME
+       if (!SDL_IntersectRect(dstrect, &dst->clip_rect, dstrect)) {
+       return (0);
+       }
+     */
+
+    SDL_Unsupported();
+    return -1;
+}
+
+/* vi: set ts=4 sw=4 expandtab: */
--- a/src/video/SDL_fill.c	Sat Dec 20 12:32:53 2008 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,365 +0,0 @@
-/*
-    SDL - Simple DirectMedia Layer
-    Copyright (C) 1997-2009 Sam Lantinga
-
-    This library is free software; you can redistribute it and/or
-    modify it under the terms of the GNU Lesser General Public
-    License as published by the Free Software Foundation; either
-    version 2.1 of the License, or (at your option) any later version.
-
-    This library is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-    Lesser General Public License for more details.
-
-    You should have received a copy of the GNU Lesser General Public
-    License along with this library; if not, write to the Free Software
-    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-
-    Sam Lantinga
-    slouken@libsdl.org
-*/
-#include "SDL_config.h"
-
-#include "SDL_video.h"
-#include "SDL_blit.h"
-
-
-#ifdef __SSE__
-/* *INDENT-OFF* */
-
-#ifdef _MSC_VER
-#define SSE_BEGIN \
-    __m128 c128; \
-    c128.m128_u32[0] = color; \
-    c128.m128_u32[1] = color; \
-    c128.m128_u32[2] = color; \
-    c128.m128_u32[3] = color;
-#else
-#define SSE_BEGIN \
-    DECLARE_ALIGNED(Uint32, cccc[4], 16); \
-    cccc[0] = color; \
-    cccc[1] = color; \
-    cccc[2] = color; \
-    cccc[3] = color; \
-    __m128 c128 = *(__m128 *)cccc;
-#endif
-
-#define SSE_WORK \
-    for (i = n / 64; i--;) { \
-        _mm_stream_ps((float *)(p+0), c128); \
-        _mm_stream_ps((float *)(p+16), c128); \
-        _mm_stream_ps((float *)(p+32), c128); \
-        _mm_stream_ps((float *)(p+48), c128); \
-        p += 64; \
-    }
-
-#define SSE_END
-
-#define DEFINE_SSE_FILLRECT(bpp, type) \
-static void \
-SDL_FillRect##bpp##SSE(Uint8 *pixels, int pitch, Uint32 color, int w, int h) \
-{ \
-    SSE_BEGIN; \
- \
-    while (h--) { \
-        int i, n = w * bpp; \
-        Uint8 *p = pixels; \
- \
-        if (n > 15) { \
-            int adjust = 16 - ((uintptr_t)p & 15); \
-            if (adjust < 16) { \
-                n -= adjust; \
-                adjust /= bpp; \
-                while (adjust--) { \
-                    *((type *)p) = (type)color; \
-                    p += bpp; \
-                } \
-            } \
-            SSE_WORK; \
-        } \
-        if (n & 63) { \
-            int remainder = (n & 63); \
-            remainder /= bpp; \
-            while (remainder--) { \
-                *((type *)p) = (type)color; \
-                p += bpp; \
-            } \
-        } \
-        pixels += pitch; \
-    } \
- \
-    SSE_END; \
-}
-
-DEFINE_SSE_FILLRECT(1, Uint8)
-DEFINE_SSE_FILLRECT(2, Uint16)
-DEFINE_SSE_FILLRECT(4, Uint32)
-
-/* *INDENT-ON* */
-#endif /* __SSE__ */
-
-#ifdef __MMX__
-/* *INDENT-OFF* */
-
-#define MMX_BEGIN \
-    __m64 c64 = _mm_set_pi32(color, color)
-
-#define MMX_WORK \
-    for (i = n / 64; i--;) { \
-        _mm_stream_pi((__m64 *)(p+0), c64); \
-        _mm_stream_pi((__m64 *)(p+8), c64); \
-        _mm_stream_pi((__m64 *)(p+16), c64); \
-        _mm_stream_pi((__m64 *)(p+24), c64); \
-        _mm_stream_pi((__m64 *)(p+32), c64); \
-        _mm_stream_pi((__m64 *)(p+40), c64); \
-        _mm_stream_pi((__m64 *)(p+48), c64); \
-        _mm_stream_pi((__m64 *)(p+56), c64); \
-        p += 64; \
-    }
-
-#define MMX_END \
-    _mm_empty()
-
-#define DEFINE_MMX_FILLRECT(bpp, type) \
-static void \
-SDL_FillRect##bpp##MMX(Uint8 *pixels, int pitch, Uint32 color, int w, int h) \
-{ \
-    MMX_BEGIN; \
- \
-    while (h--) { \
-        int i, n = w * bpp; \
-        Uint8 *p = pixels; \
- \
-        if (n > 7) { \
-            int adjust = 8 - ((uintptr_t)p & 7); \
-            if (adjust < 8) { \
-                n -= adjust; \
-                adjust /= bpp; \
-                while (adjust--) { \
-                    *((type *)p) = (type)color; \
-                    p += bpp; \
-                } \
-            } \
-            MMX_WORK; \
-        } \
-        if (n & 63) { \
-            int remainder = (n & 63); \
-            remainder /= bpp; \
-            while (remainder--) { \
-                *((type *)p) = (type)color; \
-                p += bpp; \
-            } \
-        } \
-        pixels += pitch; \
-    } \
- \
-    MMX_END; \
-}
-
-DEFINE_MMX_FILLRECT(1, Uint8)
-DEFINE_MMX_FILLRECT(2, Uint16)
-DEFINE_MMX_FILLRECT(4, Uint32)
-
-/* *INDENT-ON* */
-#endif /* __MMX__ */
-
-static void
-SDL_FillRect1(Uint8 * pixels, int pitch, Uint32 color, int w, int h)
-{
-    while (h--) {
-        int n = w;
-        Uint8 *p = pixels;
-
-        if (n > 3) {
-            switch ((uintptr_t) p & 3) {
-            case 1:
-                *p++ = (Uint8) color;
-                --n;
-            case 2:
-                *p++ = (Uint8) color;
-                --n;
-            case 3:
-                *p++ = (Uint8) color;
-                --n;
-            }
-            SDL_memset4(p, color, (n >> 2));
-        }
-        if (n & 3) {
-            p += (n & ~3);
-            switch (n & 3) {
-            case 3:
-                *p++ = (Uint8) color;
-            case 2:
-                *p++ = (Uint8) color;
-            case 1:
-                *p++ = (Uint8) color;
-            }
-        }
-        pixels += pitch;
-    }
-}
-
-static void
-SDL_FillRect2(Uint8 * pixels, int pitch, Uint32 color, int w, int h)
-{
-    while (h--) {
-        int n = w;
-        Uint16 *p = (Uint16 *) pixels;
-
-        if (n > 1) {
-            if ((uintptr_t) p & 2) {
-                *p++ = (Uint16) color;
-                --n;
-            }
-            SDL_memset4(p, color, (n >> 1));
-        }
-        if (n & 1) {
-            p[n - 1] = (Uint16) color;
-        }
-        pixels += pitch;
-    }
-}
-
-static void
-SDL_FillRect3(Uint8 * pixels, int pitch, Uint32 color, int w, int h)
-{
-    Uint8 r = (Uint8) ((color >> 16) & 0xFF);
-    Uint8 g = (Uint8) ((color >> 8) & 0xFF);
-    Uint8 b = (Uint8) (color & 0xFF);
-
-    while (h--) {
-        int n = w;
-        Uint8 *p = pixels;
-
-        while (n--) {
-            *p++ = r;
-            *p++ = g;
-            *p++ = b;
-        }
-        pixels += pitch;
-    }
-}
-
-static void
-SDL_FillRect4(Uint8 * pixels, int pitch, Uint32 color, int w, int h)
-{
-    while (h--) {
-        SDL_memset4(pixels, color, w);
-        pixels += pitch;
-    }
-}
-
-/* 
- * This function performs a fast fill of the given rectangle with 'color'
- */
-int
-SDL_FillRect(SDL_Surface * dst, SDL_Rect * dstrect, Uint32 color)
-{
-    Uint8 *pixels;
-
-    /* This function doesn't work on surfaces < 8 bpp */
-    if (dst->format->BitsPerPixel < 8) {
-        SDL_SetError("SDL_FillRect(): Unsupported surface format");
-        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;
-    }
-
-    /* Perform software fill */
-    if (!dst->pixels) {
-        SDL_SetError("SDL_FillRect(): You must lock the surface");
-        return (-1);
-    }
-
-    pixels =
-        (Uint8 *) dst->pixels + dstrect->y * dst->pitch +
-        dstrect->x * dst->format->BytesPerPixel;
-
-    switch (dst->format->BytesPerPixel) {
-    case 1:
-        {
-            color |= (color << 8);
-            color |= (color << 16);
-#ifdef __SSE__
-            if (SDL_HasSSE()) {
-                SDL_FillRect1SSE(pixels, dst->pitch, color, dstrect->w,
-                                 dstrect->h);
-                break;
-            }
-#endif
-#ifdef __MMX__
-            if (SDL_HasMMX()) {
-                SDL_FillRect1MMX(pixels, dst->pitch, color, dstrect->w,
-                                 dstrect->h);
-                break;
-            }
-#endif
-            SDL_FillRect1(pixels, dst->pitch, color, dstrect->w, dstrect->h);
-            break;
-        }
-
-    case 2:
-        {
-            color |= (color << 16);
-#ifdef __SSE__
-            if (SDL_HasSSE()) {
-                SDL_FillRect2SSE(pixels, dst->pitch, color, dstrect->w,
-                                 dstrect->h);
-                break;
-            }
-#endif
-#ifdef __MMX__
-            if (SDL_HasMMX()) {
-                SDL_FillRect2MMX(pixels, dst->pitch, color, dstrect->w,
-                                 dstrect->h);
-                break;
-            }
-#endif
-            SDL_FillRect2(pixels, dst->pitch, color, dstrect->w, dstrect->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);
-            break;
-        }
-
-    case 4:
-        {
-#ifdef __SSE__
-            if (SDL_HasSSE()) {
-                SDL_FillRect4SSE(pixels, dst->pitch, color, dstrect->w,
-                                 dstrect->h);
-                break;
-            }
-#endif
-#ifdef __MMX__
-            if (SDL_HasMMX()) {
-                SDL_FillRect4MMX(pixels, dst->pitch, color, dstrect->w,
-                                 dstrect->h);
-                break;
-            }
-#endif
-            SDL_FillRect4(pixels, dst->pitch, color, dstrect->w, dstrect->h);
-            break;
-        }
-    }
-
-    SDL_UnlockSurface(dst);
-
-    /* We're done! */
-    return (0);
-}
-
-/* vi: set ts=4 sw=4 expandtab: */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/video/SDL_fillrect.c	Sat Dec 20 13:14:28 2008 +0000
@@ -0,0 +1,365 @@
+/*
+    SDL - Simple DirectMedia Layer
+    Copyright (C) 1997-2009 Sam Lantinga
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+    Sam Lantinga
+    slouken@libsdl.org
+*/
+#include "SDL_config.h"
+
+#include "SDL_video.h"
+#include "SDL_blit.h"
+
+
+#ifdef __SSE__
+/* *INDENT-OFF* */
+
+#ifdef _MSC_VER
+#define SSE_BEGIN \
+    __m128 c128; \
+    c128.m128_u32[0] = color; \
+    c128.m128_u32[1] = color; \
+    c128.m128_u32[2] = color; \
+    c128.m128_u32[3] = color;
+#else
+#define SSE_BEGIN \
+    DECLARE_ALIGNED(Uint32, cccc[4], 16); \
+    cccc[0] = color; \
+    cccc[1] = color; \
+    cccc[2] = color; \
+    cccc[3] = color; \
+    __m128 c128 = *(__m128 *)cccc;
+#endif
+
+#define SSE_WORK \
+    for (i = n / 64; i--;) { \
+        _mm_stream_ps((float *)(p+0), c128); \
+        _mm_stream_ps((float *)(p+16), c128); \
+        _mm_stream_ps((float *)(p+32), c128); \
+        _mm_stream_ps((float *)(p+48), c128); \
+        p += 64; \
+    }
+
+#define SSE_END
+
+#define DEFINE_SSE_FILLRECT(bpp, type) \
+static void \
+SDL_FillRect##bpp##SSE(Uint8 *pixels, int pitch, Uint32 color, int w, int h) \
+{ \
+    SSE_BEGIN; \
+ \
+    while (h--) { \
+        int i, n = w * bpp; \
+        Uint8 *p = pixels; \
+ \
+        if (n > 15) { \
+            int adjust = 16 - ((uintptr_t)p & 15); \
+            if (adjust < 16) { \
+                n -= adjust; \
+                adjust /= bpp; \
+                while (adjust--) { \
+                    *((type *)p) = (type)color; \
+                    p += bpp; \
+                } \
+            } \
+            SSE_WORK; \
+        } \
+        if (n & 63) { \
+            int remainder = (n & 63); \
+            remainder /= bpp; \
+            while (remainder--) { \
+                *((type *)p) = (type)color; \
+                p += bpp; \
+            } \
+        } \
+        pixels += pitch; \
+    } \
+ \
+    SSE_END; \
+}
+
+DEFINE_SSE_FILLRECT(1, Uint8)
+DEFINE_SSE_FILLRECT(2, Uint16)
+DEFINE_SSE_FILLRECT(4, Uint32)
+
+/* *INDENT-ON* */
+#endif /* __SSE__ */
+
+#ifdef __MMX__
+/* *INDENT-OFF* */
+
+#define MMX_BEGIN \
+    __m64 c64 = _mm_set_pi32(color, color)
+
+#define MMX_WORK \
+    for (i = n / 64; i--;) { \
+        _mm_stream_pi((__m64 *)(p+0), c64); \
+        _mm_stream_pi((__m64 *)(p+8), c64); \
+        _mm_stream_pi((__m64 *)(p+16), c64); \
+        _mm_stream_pi((__m64 *)(p+24), c64); \
+        _mm_stream_pi((__m64 *)(p+32), c64); \
+        _mm_stream_pi((__m64 *)(p+40), c64); \
+        _mm_stream_pi((__m64 *)(p+48), c64); \
+        _mm_stream_pi((__m64 *)(p+56), c64); \
+        p += 64; \
+    }
+
+#define MMX_END \
+    _mm_empty()
+
+#define DEFINE_MMX_FILLRECT(bpp, type) \
+static void \
+SDL_FillRect##bpp##MMX(Uint8 *pixels, int pitch, Uint32 color, int w, int h) \
+{ \
+    MMX_BEGIN; \
+ \
+    while (h--) { \
+        int i, n = w * bpp; \
+        Uint8 *p = pixels; \
+ \
+        if (n > 7) { \
+            int adjust = 8 - ((uintptr_t)p & 7); \
+            if (adjust < 8) { \
+                n -= adjust; \
+                adjust /= bpp; \
+                while (adjust--) { \
+                    *((type *)p) = (type)color; \
+                    p += bpp; \
+                } \
+            } \
+            MMX_WORK; \
+        } \
+        if (n & 63) { \
+            int remainder = (n & 63); \
+            remainder /= bpp; \
+            while (remainder--) { \
+                *((type *)p) = (type)color; \
+                p += bpp; \
+            } \
+        } \
+        pixels += pitch; \
+    } \
+ \
+    MMX_END; \
+}
+
+DEFINE_MMX_FILLRECT(1, Uint8)
+DEFINE_MMX_FILLRECT(2, Uint16)
+DEFINE_MMX_FILLRECT(4, Uint32)
+
+/* *INDENT-ON* */
+#endif /* __MMX__ */
+
+static void
+SDL_FillRect1(Uint8 * pixels, int pitch, Uint32 color, int w, int h)
+{
+    while (h--) {
+        int n = w;
+        Uint8 *p = pixels;
+
+        if (n > 3) {
+            switch ((uintptr_t) p & 3) {
+            case 1:
+                *p++ = (Uint8) color;
+                --n;
+            case 2:
+                *p++ = (Uint8) color;
+                --n;
+            case 3:
+                *p++ = (Uint8) color;
+                --n;
+            }
+            SDL_memset4(p, color, (n >> 2));
+        }
+        if (n & 3) {
+            p += (n & ~3);
+            switch (n & 3) {
+            case 3:
+                *p++ = (Uint8) color;
+            case 2:
+                *p++ = (Uint8) color;
+            case 1:
+                *p++ = (Uint8) color;
+            }
+        }
+        pixels += pitch;
+    }
+}
+
+static void
+SDL_FillRect2(Uint8 * pixels, int pitch, Uint32 color, int w, int h)
+{
+    while (h--) {
+        int n = w;
+        Uint16 *p = (Uint16 *) pixels;
+
+        if (n > 1) {
+            if ((uintptr_t) p & 2) {
+                *p++ = (Uint16) color;
+                --n;
+            }
+            SDL_memset4(p, color, (n >> 1));
+        }
+        if (n & 1) {
+            p[n - 1] = (Uint16) color;
+        }
+        pixels += pitch;
+    }
+}
+
+static void
+SDL_FillRect3(Uint8 * pixels, int pitch, Uint32 color, int w, int h)
+{
+    Uint8 r = (Uint8) ((color >> 16) & 0xFF);
+    Uint8 g = (Uint8) ((color >> 8) & 0xFF);
+    Uint8 b = (Uint8) (color & 0xFF);
+
+    while (h--) {
+        int n = w;
+        Uint8 *p = pixels;
+
+        while (n--) {
+            *p++ = r;
+            *p++ = g;
+            *p++ = b;
+        }
+        pixels += pitch;
+    }
+}
+
+static void
+SDL_FillRect4(Uint8 * pixels, int pitch, Uint32 color, int w, int h)
+{
+    while (h--) {
+        SDL_memset4(pixels, color, w);
+        pixels += pitch;
+    }
+}
+
+/* 
+ * This function performs a fast fill of the given rectangle with 'color'
+ */
+int
+SDL_FillRect(SDL_Surface * dst, SDL_Rect * dstrect, Uint32 color)
+{
+    Uint8 *pixels;
+
+    /* This function doesn't work on surfaces < 8 bpp */
+    if (dst->format->BitsPerPixel < 8) {
+        SDL_SetError("SDL_FillRect(): Unsupported surface format");
+        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;
+    }
+
+    /* Perform software fill */
+    if (!dst->pixels) {
+        SDL_SetError("SDL_FillRect(): You must lock the surface");
+        return (-1);
+    }
+
+    pixels =
+        (Uint8 *) dst->pixels + dstrect->y * dst->pitch +
+        dstrect->x * dst->format->BytesPerPixel;
+
+    switch (dst->format->BytesPerPixel) {
+    case 1:
+        {
+            color |= (color << 8);
+            color |= (color << 16);
+#ifdef __SSE__
+            if (SDL_HasSSE()) {
+                SDL_FillRect1SSE(pixels, dst->pitch, color, dstrect->w,
+                                 dstrect->h);
+                break;
+            }
+#endif
+#ifdef __MMX__
+            if (SDL_HasMMX()) {
+                SDL_FillRect1MMX(pixels, dst->pitch, color, dstrect->w,
+                                 dstrect->h);
+                break;
+            }
+#endif
+            SDL_FillRect1(pixels, dst->pitch, color, dstrect->w, dstrect->h);
+            break;
+        }
+
+    case 2:
+        {
+            color |= (color << 16);
+#ifdef __SSE__
+            if (SDL_HasSSE()) {
+                SDL_FillRect2SSE(pixels, dst->pitch, color, dstrect->w,
+                                 dstrect->h);
+                break;
+            }
+#endif
+#ifdef __MMX__
+            if (SDL_HasMMX()) {
+                SDL_FillRect2MMX(pixels, dst->pitch, color, dstrect->w,
+                                 dstrect->h);
+                break;
+            }
+#endif
+            SDL_FillRect2(pixels, dst->pitch, color, dstrect->w, dstrect->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);
+            break;
+        }
+
+    case 4:
+        {
+#ifdef __SSE__
+            if (SDL_HasSSE()) {
+                SDL_FillRect4SSE(pixels, dst->pitch, color, dstrect->w,
+                                 dstrect->h);
+                break;
+            }
+#endif
+#ifdef __MMX__
+            if (SDL_HasMMX()) {
+                SDL_FillRect4MMX(pixels, dst->pitch, color, dstrect->w,
+                                 dstrect->h);
+                break;
+            }
+#endif
+            SDL_FillRect4(pixels, dst->pitch, color, dstrect->w, dstrect->h);
+            break;
+        }
+    }
+
+    SDL_UnlockSurface(dst);
+
+    /* We're done! */
+    return (0);
+}
+
+/* vi: set ts=4 sw=4 expandtab: */
--- a/src/video/SDL_renderer_sw.c	Sat Dec 20 12:32:53 2008 +0000
+++ b/src/video/SDL_renderer_sw.c	Sat Dec 20 13:14:28 2008 +0000
@@ -60,6 +60,9 @@
                           int *pitch);
 static void SW_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture);
 static int SW_SetDrawColor(SDL_Renderer * renderer);
+static int SW_SetDrawBlendMode(SDL_Renderer * renderer);
+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_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
                          const SDL_Rect * srcrect, const SDL_Rect * dstrect);
@@ -223,11 +226,8 @@
     renderer->DisplayModeChanged = SW_DisplayModeChanged;
 
     renderer->SetDrawColor = SW_SetDrawColor;
-    /* FIXME : Implement
-       renderer->SetDrawBlendMode = GL_SetDrawBlendMode;
-       renderer->RenderLine = GL_RenderLine;
-     */
-
+    renderer->SetDrawBlendMode = SW_SetDrawBlendMode;
+    renderer->RenderLine = SW_RenderLine;
     renderer->RenderFill = SW_RenderFill;
     renderer->RenderCopy = SW_RenderCopy;
     renderer->RenderPresent = SW_RenderPresent;
@@ -532,10 +532,65 @@
 }
 
 static int
+SW_SetDrawBlendMode(SDL_Renderer * renderer)
+{
+    return 0;
+}
+
+static int
+SW_RenderLine(SDL_Renderer * renderer, int x1, int y1, int x2, int y2)
+{
+    SW_RenderData *data = (SW_RenderData *) renderer->driverdata;
+    int status;
+
+    if (data->renderer->info.flags & SDL_RENDERER_PRESENTCOPY) {
+        SDL_Rect rect;
+
+        if (x1 < x2) {
+            rect.x = x1;
+            rect.w = (x2 - x1) + 1;
+        } else {
+            rect.x = x2;
+            rect.w = (x1 - x2) + 1;
+        }
+        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);
+    }
+
+    if (data->renderer->LockTexture(data->renderer,
+                                    data->texture[data->current_texture],
+                                    NULL, 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);
+
+        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);
+    }
+
+    data->renderer->UnlockTexture(data->renderer,
+                                  data->texture[data->current_texture]);
+    return status;
+}
+
+static int
 SW_RenderFill(SDL_Renderer * renderer, const SDL_Rect * rect)
 {
     SW_RenderData *data = (SW_RenderData *) renderer->driverdata;
-    Uint32 color;
     SDL_Rect real_rect;
     int status;
 
@@ -543,22 +598,30 @@
         SDL_AddDirtyRect(&data->dirty, rect);
     }
 
-    color = SDL_MapRGBA(data->surface.format,
-                        renderer->r, renderer->g, renderer->b, renderer->a);
-
     if (data->renderer->LockTexture(data->renderer,
                                     data->texture[data->current_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;
     real_rect = data->surface.clip_rect;
 
-    status = SDL_FillRect(&data->surface, &real_rect, color);
+    if (renderer->blendMode == SDL_BLENDMODE_NONE) {
+        Uint32 color =
+            SDL_MapRGBA(data->surface.format, renderer->r, renderer->g,
+                        renderer->b, renderer->a);
+
+        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);
+    }
 
     data->renderer->UnlockTexture(data->renderer,
                                   data->texture[data->current_texture]);
--- a/src/video/dummy/SDL_nullrender.c	Sat Dec 20 12:32:53 2008 +0000
+++ b/src/video/dummy/SDL_nullrender.c	Sat Dec 20 13:14:28 2008 +0000
@@ -32,6 +32,9 @@
 static SDL_Renderer *SDL_DUMMY_CreateRenderer(SDL_Window * window,
                                               Uint32 flags);
 static int SDL_DUMMY_SetDrawColor(SDL_Renderer * renderer);
+static int SDL_DUMMY_SetDrawBlendMode(SDL_Renderer * renderer);
+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_RenderCopy(SDL_Renderer * renderer,
@@ -90,6 +93,8 @@
     SDL_zerop(data);
 
     renderer->SetDrawColor = SDL_DUMMY_SetDrawColor;
+    renderer->SetDrawBlendMode = SDL_DUMMY_SetDrawBlendMode;
+    renderer->RenderLine = SDL_DUMMY_RenderLine;
     renderer->RenderFill = SDL_DUMMY_RenderFill;
     renderer->RenderCopy = SDL_DUMMY_RenderCopy;
     renderer->RenderPresent = SDL_DUMMY_RenderPresent;
@@ -132,18 +137,54 @@
 }
 
 static int
+SDL_DUMMY_SetDrawBlendMode(SDL_Renderer * renderer)
+{
+    return 0;
+}
+
+static int
+SDL_DUMMY_RenderLine(SDL_Renderer * renderer, int x1, int y1, int x2, int y2)
+{
+    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) {
+        Uint32 color =
+            SDL_MapRGBA(target->format, renderer->r, renderer->g, renderer->b,
+                        renderer->a);
+
+        status = SDL_DrawLine(target, x1, y1, x2, y2, color);
+    } else {
+        status =
+            SDL_BlendLine(target, x1, y1, x2, y2, 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_RenderData *data =
         (SDL_DUMMY_RenderData *) renderer->driverdata;
     SDL_Surface *target = data->screens[data->current_screen];
-    Uint32 color;
     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);
 
-    color = SDL_MapRGBA(target->format,
-                        renderer->r, renderer->g, renderer->b, renderer->a);
-
-    return SDL_FillRect(target, &real_rect, color);
+        status = SDL_FillRect(target, &real_rect, color);
+    } else {
+        status =
+            SDL_BlendRect(target, &real_rect, renderer->blendMode,
+                          renderer->r, renderer->g, renderer->b, renderer->a);
+    }
+    return status;
 }
 
 static int
--- a/src/video/x11/SDL_x11render.c	Sat Dec 20 12:32:53 2008 +0000
+++ b/src/video/x11/SDL_x11render.c	Sat Dec 20 13:14:28 2008 +0000
@@ -597,6 +597,7 @@
 {
     X11_RenderData *data = (X11_RenderData *) renderer->driverdata;
     unsigned long foreground;
+
     if (data->makedirty) {
         SDL_Rect rect;