Commits

Lenard Lindstrom  committed 1826c72

BLEND_RGBA_xxx and more BLEND_xxx tests; related bug fixes
(mostly 24 bit surface related)

  • Participants
  • Parent commits b89b475

Comments (0)

Files changed (4)

File src/alphablit.c

     SDL_PixelFormat *src;
     Uint8          *table;
     SDL_PixelFormat *dst;
+    Uint32          src_flags;
+    Uint32          dst_flags;
 } SDL_BlitInfo;
 
 static void alphablit_alpha (SDL_BlitInfo * info);
         info.d_skip = dst->pitch - info.d_width * dst->format->BytesPerPixel;
         info.src = src->format;
         info.dst = dst->format;
+	info.src_flags = src->flags;
+	info.dst_flags = dst->flags;
 
         switch (the_args)
         {
 
         case PYGAME_BLEND_RGBA_ADD:
         {
-            blit_blend_rgba_add (&info);
-            break;
+	    blit_blend_rgba_add (&info);
+	    break;
         }
         case PYGAME_BLEND_RGBA_SUB:
         {
     Uint32          pixel;
     Uint32          tmp;
 
-    if (srcbpp == 4 && dstbpp == 4)
+    if (!(info->dst_flags & SDL_SRCALPHA && dstfmt->Amask))
+    {
+	blit_blend_add (info);
+	return;
+    }
+
+    if (srcbpp == 4 && dstbpp == 4 &&
+	srcfmt->Rmask == dstfmt->Rmask &&
+	srcfmt->Gmask == dstfmt->Gmask &&
+	srcfmt->Bmask == dstfmt->Bmask &&
+	srcfmt->Amask == dstfmt->Amask &&
+	info->src_flags & SDL_SRCALPHA)
     {
         while (height--)
         {
     Uint32          pixel;
     Sint32          tmp2;
 
-    if (srcbpp == 4 && dstbpp == 4)
+    if (!(info->dst_flags & SDL_SRCALPHA && dstfmt->Amask))
+    {
+	blit_blend_sub (info);
+	return;
+    }
+
+    if (srcbpp == 4 && dstbpp == 4 &&
+	srcfmt->Rmask == dstfmt->Rmask &&
+	srcfmt->Gmask == dstfmt->Gmask &&
+	srcfmt->Bmask == dstfmt->Bmask &&
+	srcfmt->Amask == dstfmt->Amask &&
+	info->src_flags & SDL_SRCALPHA)
     {
         while (height--)
         {
     Uint32          pixel;
     Uint32          tmp;
 
-    if (srcfmt->BytesPerPixel == 4 && dstfmt->BytesPerPixel == 4)
+    if (!(info->dst_flags & SDL_SRCALPHA && dstfmt->Amask))
+    {
+	blit_blend_mul (info);
+	return;
+    }
+
+    if (srcbpp == 4 && dstbpp == 4 &&
+	srcfmt->Rmask == dstfmt->Rmask &&
+	srcfmt->Gmask == dstfmt->Gmask &&
+	srcfmt->Bmask == dstfmt->Bmask &&
+	srcfmt->Amask == dstfmt->Amask &&
+	info->src_flags & SDL_SRCALPHA)
     {
         while (height--)
         {
     Uint8           dR, dG, dB, dA, sR, sG, sB, sA;
     Uint32          pixel;
 
-    if (srcfmt->BytesPerPixel == 4 && dstfmt->BytesPerPixel == 4)
+    if (!(info->dst_flags & SDL_SRCALPHA && dstfmt->Amask))
+    {
+	blit_blend_min (info);
+	return;
+    }
+
+    if (srcbpp == 4 && dstbpp == 4 &&
+	srcfmt->Rmask == dstfmt->Rmask &&
+	srcfmt->Gmask == dstfmt->Gmask &&
+	srcfmt->Bmask == dstfmt->Bmask &&
+	srcfmt->Amask == dstfmt->Amask &&
+	info->src_flags & SDL_SRCALPHA)
     {
         while (height--)
         {
     Uint8           dR, dG, dB, dA, sR, sG, sB, sA;
     Uint32          pixel;
 
-    if (srcfmt->BytesPerPixel == 4 && dstfmt->BytesPerPixel == 4)
+    if (!(info->dst_flags & SDL_SRCALPHA && dstfmt->Amask))
+    {
+	blit_blend_max (info);
+	return;
+    }
+
+    if (srcbpp == 4 && dstbpp == 4 &&
+	srcfmt->Rmask == dstfmt->Rmask &&
+	srcfmt->Gmask == dstfmt->Gmask &&
+	srcfmt->Bmask == dstfmt->Bmask &&
+	srcfmt->Amask == dstfmt->Amask &&
+	info->src_flags & SDL_SRCALPHA)
     {
         while (height--)
         {
     Uint32          pixel;
     Uint32          tmp;
 
-    if (srcbpp == 4 && dstbpp == 4)
+    if (srcbpp == 4 && dstbpp == 4 &&
+	srcfmt->Rmask == dstfmt->Rmask &&
+	srcfmt->Gmask == dstfmt->Gmask &&
+	srcfmt->Bmask == dstfmt->Bmask &&
+	srcfmt->Amask == dstfmt->Amask &&
+	!(info->src_flags & SDL_SRCALPHA))
     {
         while (height--)
         {
 	else if (dstbpp == 3)
 	{
 	    size_t offsetR, offsetG, offsetB;
-	    SET_OFFSETS_24(offsetR, offsetG, offsetB, dstfmt);
+	    SET_OFFSETS_24 (offsetR, offsetG, offsetB, dstfmt);
 	    while (height--)
 	    {
 		LOOP_UNROLLED4(
 	else if (dstbpp == 3)
 	{
 	    size_t offsetR, offsetG, offsetB;
-	    SET_OFFSETS_24(offsetR, offsetG, offsetB, dstfmt);
+	    SET_OFFSETS_24 (offsetR, offsetG, offsetB, dstfmt);
 	    while (height--)
 	    {
 		LOOP_UNROLLED4(
     Uint32          pixel;
     Sint32          tmp2;
 
-    if (srcbpp == 4 && dstbpp == 4)
+    if (srcbpp == 4 && dstbpp == 4 &&
+	srcfmt->Rmask == dstfmt->Rmask &&
+	srcfmt->Gmask == dstfmt->Gmask &&
+	srcfmt->Bmask == dstfmt->Bmask &&
+	srcfmt->Amask == dstfmt->Amask &&
+	!(info->src_flags & SDL_SRCALPHA))
     {
         while (height--)
         {
 	else if (dstbpp == 3)
 	{
 	    size_t offsetR, offsetG, offsetB;
-	    SET_OFFSETS_24(offsetR, offsetG, offsetB, dstfmt);
+	    SET_OFFSETS_24 (offsetR, offsetG, offsetB, dstfmt);
 	    while (height--)
 	    {
 		LOOP_UNROLLED4(
 	else if (dstbpp == 3)
         {
 	    size_t offsetR, offsetG, offsetB;
-	    SET_OFFSETS_24(offsetR, offsetG, offsetB, dstfmt);
+	    SET_OFFSETS_24 (offsetR, offsetG, offsetB, dstfmt);
             while (height--)
             {
                 LOOP_UNROLLED4(
     Uint32          pixel;
     Uint32          tmp;
 
-    if (srcfmt->BytesPerPixel == 4 && dstfmt->BytesPerPixel == 4)
+    if (srcbpp == 4 && dstbpp == 4 &&
+	srcfmt->Rmask == dstfmt->Rmask &&
+	srcfmt->Gmask == dstfmt->Gmask &&
+	srcfmt->Bmask == dstfmt->Bmask &&
+	srcfmt->Amask == dstfmt->Amask &&
+	!(info->src_flags & SDL_SRCALPHA))
     {
         while (height--)
         {
 	else if (dstbpp == 3)
 	{
 	    size_t offsetR, offsetG, offsetB;
-	    SET_OFFSETS_24(offsetR, offsetG, offsetB, dstfmt);
+	    SET_OFFSETS_24 (offsetR, offsetG, offsetB, dstfmt);
 	    while (height--)
 	    {
 		LOOP_UNROLLED4(
 	else if (dstbpp == 3)
 	{
 	    size_t offsetR, offsetG, offsetB;
-	    SET_OFFSETS_24(offsetR, offsetG, offsetB, dstfmt);
+	    SET_OFFSETS_24 (offsetR, offsetG, offsetB, dstfmt);
 	    while (height--)
 	    {
 		LOOP_UNROLLED4(
     Uint8           dR, dG, dB, dA, sR, sG, sB, sA;
     Uint32          pixel;
 
-    if (srcfmt->BytesPerPixel == 4 && dstfmt->BytesPerPixel == 4)
+    if (srcbpp == 4 && dstbpp == 4 &&
+	srcfmt->Rmask == dstfmt->Rmask &&
+	srcfmt->Gmask == dstfmt->Gmask &&
+	srcfmt->Bmask == dstfmt->Bmask &&
+	srcfmt->Amask == dstfmt->Amask &&
+	!(info->src_flags & SDL_SRCALPHA))
     {
         while (height--)
         {
 	else if (dstbpp == 3)
 	{
 	    size_t offsetR, offsetG, offsetB;
-	    SET_OFFSETS_24(offsetR, offsetG, offsetB, dstfmt);
+	    SET_OFFSETS_24 (offsetR, offsetG, offsetB, dstfmt);
 	    while (height--)
 	    {
 		LOOP_UNROLLED4(
 	else if (dstbpp == 3)
 	{
 	    size_t offsetR, offsetG, offsetB;
-	    SET_OFFSETS_24(offsetR, offsetG, offsetB, dstfmt);
+	    SET_OFFSETS_24 (offsetR, offsetG, offsetB, dstfmt);
 	    while (height--)
 	    {
 		LOOP_UNROLLED4(
     Uint8           dR, dG, dB, dA, sR, sG, sB, sA;
     Uint32          pixel;
 
-    if (srcfmt->BytesPerPixel == 4 && dstfmt->BytesPerPixel == 4)
+    if (srcbpp == 4 && dstbpp == 4 &&
+	srcfmt->Rmask == dstfmt->Rmask &&
+	srcfmt->Gmask == dstfmt->Gmask &&
+	srcfmt->Bmask == dstfmt->Bmask &&
+	srcfmt->Amask == dstfmt->Amask &&
+	!(info->src_flags & SDL_SRCALPHA))
     {
         while (height--)
         {
 	else if (dstbpp == 3)
 	{
 	    size_t offsetR, offsetG, offsetB;
-	    SET_OFFSETS_24(offsetR, offsetG, offsetB, dstfmt);
+	    SET_OFFSETS_24 (offsetR, offsetG, offsetB, dstfmt);
 	    while (height--)
 	    {
 		LOOP_UNROLLED4(
 	else if (dstbpp == 3)
 	{
 	    size_t offsetR, offsetG, offsetB;
-	    SET_OFFSETS_24(offsetR, offsetG, offsetB, dstfmt);
+	    SET_OFFSETS_24 (offsetR, offsetG, offsetB, dstfmt);
 	    while (height--)
 	    {
 		LOOP_UNROLLED4(

File src/surface.h

     break;                                        \
     }
 
-#define GET_PIXELVALS(_sR, _sG, _sB, _sA, px, fmt)                    \
+#define GET_PIXELVALS(_sR, _sG, _sB, _sA, px, fmt)		      \
     _sR = ((px & fmt->Rmask) >> fmt->Rshift);                         \
     _sR = (_sR << fmt->Rloss) + (_sR >> (8 - (fmt->Rloss << 1)));     \
     _sG = ((px & fmt->Gmask) >> fmt->Gshift);                         \

File src/surface_fill.c

 #include "surface.h"
 
 
-
 static int
-surface_fill_blend_rgba_add (SDL_Surface *surface, SDL_Rect *rect, Uint32 color)
+surface_fill_blend_add (SDL_Surface *surface, SDL_Rect *rect, Uint32 color)
 {
     Uint8 *pixels;
     int width = rect->w;
             LOOP_UNROLLED4(
             {
                 GET_PIXELVALS_1 (sR, sG, sB, sA, pixels, fmt);
+                BLEND_ADD (tmp, cR, cG, cB, cA, sR, sG, sB, sA);
+                *pixels = SDL_MapRGBA (fmt, sR, sG, sB, sA);
+                pixels += bpp;
+            }, n, width);
+            pixels += skip;
+        }
+        result = 0;
+        break;
+    }
+    case 3:
+    {
+	size_t offsetR, offsetG, offsetB;
+	SET_OFFSETS_24 (offsetR, offsetG, offsetB, fmt);
+        GET_PIXELVALS (cR, cG, cB, cA, color, fmt);
+        while (height--)
+        {
+            LOOP_UNROLLED4(
+            {
+                GET_PIXEL (pixel, bpp, pixels);
+                GET_PIXELVALS (sR, sG, sB, sA, pixel, fmt);
+                BLEND_ADD (tmp, cR, cG, cB, cA, sR, sG, sB, sA);
+		pixels[offsetR] = sR;
+		pixels[offsetG] = sG;
+		pixels[offsetB] = sB;
+                pixels += bpp;
+            }, n, width);
+            pixels += skip;
+        }
+        result = 0;
+	break;
+    }
+    default:
+    {
+        GET_PIXELVALS (cR, cG, cB, cA, color, fmt);
+        /*
+        printf ("Color: %d, %d, %d, %d, BPP is: %d\n", cR, cG, cB, cA, bpp);
+        */
+        while (height--)
+        {
+            LOOP_UNROLLED4(
+            {
+                GET_PIXEL (pixel, bpp, pixels);
+                GET_PIXELVALS (sR, sG, sB, sA, pixel, fmt);
+                BLEND_ADD (tmp, cR, cG, cB, cA, sR, sG, sB, sA);
+                CREATE_PIXEL(pixels, sR, sG, sB, sA, bpp, fmt);
+                pixels += bpp;
+            }, n, width);
+            pixels += skip;
+        }
+        result = 0;
+        break;
+    }
+    }
+    return result;
+}
+
+static int
+surface_fill_blend_sub (SDL_Surface *surface, SDL_Rect *rect, Uint32 color)
+{
+    Uint8 *pixels;
+    int width = rect->w;
+    int height = rect->h;
+    int skip;
+    int bpp;
+    int n;
+    SDL_PixelFormat *fmt;
+    Uint8 sR, sG, sB, sA, cR, cG, cB, cA;
+    Uint32 pixel;
+    Sint32 tmp2;
+    int result = -1;
+
+    bpp = surface->format->BytesPerPixel;
+    fmt = surface->format;
+    pixels = (Uint8 *) surface->pixels + surface->offset +
+        (Uint16) rect->y * surface->pitch + (Uint16) rect->x * bpp;
+    skip = surface->pitch - width * bpp;
+
+    switch (bpp)
+    {
+    case 1:
+    {
+        SDL_GetRGBA (color, fmt, &cR, &cG, &cB, &cA);
+        while (height--)
+        {
+            LOOP_UNROLLED4(
+            {
+                GET_PIXELVALS_1 (sR, sG, sB, sA, pixels, fmt);
+                BLEND_SUB (tmp2, cR, cG, cB, cA, sR, sG, sB, sA);
+                *pixels = SDL_MapRGBA (fmt, sR, sG, sB, sA);
+                pixels += bpp;
+            }, n, width);
+            pixels += skip;
+        }
+        result = 0;
+        break;
+    }
+    case 3:
+    {
+	size_t offsetR, offsetG, offsetB;
+	SET_OFFSETS_24 (offsetR, offsetG, offsetB, fmt);
+        GET_PIXELVALS (cR, cG, cB, cA, color, fmt);
+        while (height--)
+        {
+            LOOP_UNROLLED4(
+            {
+                GET_PIXEL (pixel, bpp, pixels);
+                GET_PIXELVALS (sR, sG, sB, sA, pixel, fmt);
+                BLEND_SUB (tmp2, cR, cG, cB, cA, sR, sG, sB, sA);
+		pixels[offsetR] = sR;
+		pixels[offsetG] = sG;
+		pixels[offsetB] = sB;
+                pixels += bpp;
+            }, n, width);
+            pixels += skip;
+        }
+        result = 0;
+	break;
+    }
+    default:
+    {
+        GET_PIXELVALS (cR, cG, cB, cA, color, fmt);
+        /*
+        printf ("Color: %d, %d, %d, %d, BPP is: %d\n", cR, cG, cB, cA, bpp);
+        */
+        while (height--)
+        {
+            LOOP_UNROLLED4(
+            {
+                GET_PIXEL (pixel, bpp, pixels);
+                GET_PIXELVALS (sR, sG, sB, sA, pixel, fmt);
+                BLEND_SUB (tmp2, cR, cG, cB, cA, sR, sG, sB, sA);
+                CREATE_PIXEL(pixels, sR, sG, sB, sA, bpp, fmt);
+                pixels += bpp;
+            }, n, width);
+            pixels += skip;
+        }
+        result = 0;
+        break;
+    }
+    }
+    return result;
+}
+
+static int
+surface_fill_blend_mult (SDL_Surface *surface, SDL_Rect *rect, Uint32 color)
+{
+    Uint8 *pixels;
+    int width = rect->w;
+    int height = rect->h;
+    int skip;
+    int bpp;
+    int n;
+    SDL_PixelFormat *fmt;
+    Uint8 sR, sG, sB, sA, cR, cG, cB, cA;
+    Uint32 pixel;
+    int result = -1;
+
+    bpp = surface->format->BytesPerPixel;
+    fmt = surface->format;
+    pixels = (Uint8 *) surface->pixels + surface->offset +
+        (Uint16) rect->y * surface->pitch + (Uint16) rect->x * bpp;
+    skip = surface->pitch - width * bpp;
+
+    switch (bpp)
+    {
+    case 1:
+    {
+        SDL_GetRGBA (color, fmt, &cR, &cG, &cB, &cA);
+        while (height--)
+        {
+            LOOP_UNROLLED4(
+            {
+                GET_PIXELVALS_1 (sR, sG, sB, sA, pixels, fmt);
+                BLEND_MULT (cR, cG, cB, cA, sR, sG, sB, sA);
+                *pixels = SDL_MapRGBA (fmt, sR, sG, sB, sA);
+                pixels += bpp;
+            }, n, width);
+            pixels += skip;
+        }
+        result = 0;
+        break;
+    }
+    case 3:
+    {
+	size_t offsetR, offsetG, offsetB;
+	SET_OFFSETS_24 (offsetR, offsetG, offsetB, fmt);
+        GET_PIXELVALS (cR, cG, cB, cA, color, fmt);
+        while (height--)
+        {
+            LOOP_UNROLLED4(
+            {
+                GET_PIXEL (pixel, bpp, pixels);
+                GET_PIXELVALS (sR, sG, sB, sA, pixel, fmt);
+                BLEND_MULT (cR, cG, cB, cA, sR, sG, sB, sA);
+		pixels[offsetR] = sR;
+		pixels[offsetG] = sG;
+		pixels[offsetB] = sB;
+                pixels += bpp;
+            }, n, width);
+            pixels += skip;
+        }
+        result = 0;
+	break;
+    }
+    default:
+    {
+        GET_PIXELVALS (cR, cG, cB, cA, color, fmt);
+        /*
+        printf ("Color: %d, %d, %d, %d, BPP is: %d\n", cR, cG, cB, cA, bpp);
+        */
+        while (height--)
+        {
+            LOOP_UNROLLED4(
+            {
+                GET_PIXEL (pixel, bpp, pixels);
+                GET_PIXELVALS (sR, sG, sB, sA, pixel, fmt);
+                BLEND_MULT (cR, cG, cB, cA, sR, sG, sB, sA);
+                CREATE_PIXEL(pixels, sR, sG, sB, sA, bpp, fmt);
+                pixels += bpp;
+            }, n, width);
+            pixels += skip;
+        }
+        result = 0;
+        break;
+    }
+    }
+    return result;
+}
+
+static int
+surface_fill_blend_min (SDL_Surface *surface, SDL_Rect *rect, Uint32 color)
+{
+    Uint8 *pixels;
+    int width = rect->w;
+    int height = rect->h;
+    int skip;
+    int bpp;
+    int n;
+    SDL_PixelFormat *fmt;
+    Uint8 sR, sG, sB, sA, cR, cG, cB, cA;
+    Uint32 pixel;
+    int result = -1;
+
+    bpp = surface->format->BytesPerPixel;
+    fmt = surface->format;
+    pixels = (Uint8 *) surface->pixels + surface->offset +
+        (Uint16) rect->y * surface->pitch + (Uint16) rect->x * bpp;
+    skip = surface->pitch - width * bpp;
+
+    switch (bpp)
+    {
+    case 1:
+    {
+        SDL_GetRGBA (color, fmt, &cR, &cG, &cB, &cA);
+        while (height--)
+        {
+            LOOP_UNROLLED4(
+            {
+                GET_PIXELVALS_1 (sR, sG, sB, sA, pixels, fmt);
+                BLEND_MIN (cR, cG, cB, cA, sR, sG, sB, sA);
+                *pixels = SDL_MapRGBA (fmt, sR, sG, sB, sA);
+                pixels += bpp;
+            }, n, width);
+            pixels += skip;
+        }
+        result = 0;
+        break;
+    }
+    case 3:
+    {
+	size_t offsetR, offsetG, offsetB;
+	SET_OFFSETS_24 (offsetR, offsetG, offsetB, fmt);
+        GET_PIXELVALS (cR, cG, cB, cA, color, fmt);
+        while (height--)
+        {
+            LOOP_UNROLLED4(
+            {
+                GET_PIXEL (pixel, bpp, pixels);
+                GET_PIXELVALS (sR, sG, sB, sA, pixel, fmt);
+                BLEND_MIN (cR, cG, cB, cA, sR, sG, sB, sA);
+		pixels[offsetR] = sR;
+		pixels[offsetG] = sG;
+		pixels[offsetB] = sB;
+                pixels += bpp;
+            }, n, width);
+            pixels += skip;
+        }
+        result = 0;
+	break;
+    }
+    default:
+    {
+        GET_PIXELVALS (cR, cG, cB, cA, color, fmt);
+        /*
+        printf ("Color: %d, %d, %d, %d, BPP is: %d\n", cR, cG, cB, cA, bpp);
+        */
+        while (height--)
+        {
+            LOOP_UNROLLED4(
+            {
+                GET_PIXEL (pixel, bpp, pixels);
+                GET_PIXELVALS (sR, sG, sB, sA, pixel, fmt);
+                BLEND_MIN (cR, cG, cB, cA, sR, sG, sB, sA);
+                CREATE_PIXEL(pixels, sR, sG, sB, sA, bpp, fmt);
+                pixels += bpp;
+            }, n, width);
+            pixels += skip;
+        }
+        result = 0;
+        break;
+    }
+    }
+    return result;
+}
+
+static int
+surface_fill_blend_max (SDL_Surface *surface, SDL_Rect *rect, Uint32 color)
+{
+    Uint8 *pixels;
+    int width = rect->w;
+    int height = rect->h;
+    int skip;
+    int bpp;
+    int n;
+    SDL_PixelFormat *fmt;
+    Uint8 sR, sG, sB, sA, cR, cG, cB, cA;
+    Uint32 pixel;
+    int result = -1;
+
+    bpp = surface->format->BytesPerPixel;
+    fmt = surface->format;
+    pixels = (Uint8 *) surface->pixels + surface->offset +
+        (Uint16) rect->y * surface->pitch + (Uint16) rect->x * bpp;
+    skip = surface->pitch - width * bpp;
+
+    switch (bpp)
+    {
+    case 1:
+    {
+        SDL_GetRGBA (color, fmt, &cR, &cG, &cB, &cA);
+        while (height--)
+        {
+            LOOP_UNROLLED4(
+            {
+                GET_PIXELVALS_1 (sR, sG, sB, sA, pixels, fmt);
+                BLEND_MAX (cR, cG, cB, cA, sR, sG, sB, sA);
+                *pixels = SDL_MapRGBA (fmt, sR, sG, sB, sA);
+                pixels += bpp;
+            }, n, width);
+            pixels += skip;
+        }
+        result = 0;
+        break;
+    }
+    case 3:
+    {
+	size_t offsetR, offsetG, offsetB;
+	SET_OFFSETS_24 (offsetR, offsetG, offsetB, fmt);
+        GET_PIXELVALS (cR, cG, cB, cA, color, fmt);
+        while (height--)
+        {
+            LOOP_UNROLLED4(
+            {
+                GET_PIXEL (pixel, bpp, pixels);
+                GET_PIXELVALS (sR, sG, sB, sA, pixel, fmt);
+                BLEND_MAX (cR, cG, cB, cA, sR, sG, sB, sA);
+		pixels[offsetR] = sR;
+		pixels[offsetG] = sG;
+		pixels[offsetB] = sB;
+                pixels += bpp;
+            }, n, width);
+            pixels += skip;
+        }
+        result = 0;
+	break;
+    }
+    default:
+    {
+        GET_PIXELVALS (cR, cG, cB, cA, color, fmt);
+        /*
+        printf ("Color: %d, %d, %d, %d, BPP is: %d\n", cR, cG, cB, cA, bpp);
+        */
+        while (height--)
+        {
+            LOOP_UNROLLED4(
+            {
+                GET_PIXEL (pixel, bpp, pixels);
+                GET_PIXELVALS (sR, sG, sB, sA, pixel, fmt);
+                BLEND_MAX (cR, cG, cB, cA, sR, sG, sB, sA);
+                CREATE_PIXEL(pixels, sR, sG, sB, sA, bpp, fmt);
+                pixels += bpp;
+            }, n, width);
+            pixels += skip;
+        }
+        result = 0;
+        break;
+    }
+    }
+    return result;
+}
+
+
+/* ------------------------- */
+
+static int
+surface_fill_blend_rgba_add (SDL_Surface *surface, SDL_Rect *rect, Uint32 color)
+{
+    Uint8 *pixels;
+    int width = rect->w;
+    int height = rect->h;
+    int skip;
+    int bpp = surface->format->BytesPerPixel;
+    int n;
+    SDL_PixelFormat *fmt = surface->format;
+    Uint8 sR, sG, sB, sA, cR, cG, cB, cA;
+    Uint32 pixel;
+    Uint32 tmp;
+    int result = -1;
+
+    if (!(surface->flags & SDL_SRCALPHA && fmt->Amask))
+    {
+	return surface_fill_blend_add (surface, rect, color);
+    }
+
+    pixels = (Uint8 *) surface->pixels + surface->offset +
+        (Uint16) rect->y * surface->pitch + (Uint16) rect->x * bpp;
+    skip = surface->pitch - width * bpp;
+
+    switch (bpp)
+    {
+    case 1:
+    {
+        SDL_GetRGBA (color, fmt, &cR, &cG, &cB, &cA);
+        while (height--)
+        {
+            LOOP_UNROLLED4(
+            {
+                GET_PIXELVALS_1 (sR, sG, sB, sA, pixels, fmt);
                 BLEND_RGBA_ADD (tmp, cR, cG, cB, cA, sR, sG, sB, sA);
                 *pixels = SDL_MapRGBA (fmt, sR, sG, sB, sA);
                 pixels += bpp;
     int width = rect->w;
     int height = rect->h;
     int skip;
-    int bpp;
+    int bpp = surface->format->BytesPerPixel;
     int n;
-    SDL_PixelFormat *fmt;
+    SDL_PixelFormat *fmt = surface->format;
     Uint8 sR, sG, sB, sA, cR, cG, cB, cA;
     Uint32 pixel;
-    Uint32 tmp;
+    Sint32 tmp2;
     int result = -1;
 
-    bpp = surface->format->BytesPerPixel;
-    fmt = surface->format;
+    if (!(surface->flags & SDL_SRCALPHA && fmt->Amask))
+    {
+	return surface_fill_blend_sub (surface, rect, color);
+    }
+
     pixels = (Uint8 *) surface->pixels + surface->offset +
         (Uint16) rect->y * surface->pitch + (Uint16) rect->x * bpp;
     skip = surface->pitch - width * bpp;
             LOOP_UNROLLED4(
             {
                 GET_PIXELVALS_1 (sR, sG, sB, sA, pixels, fmt);
-                BLEND_RGBA_SUB (tmp, cR, cG, cB, cA, sR, sG, sB, sA);
+                BLEND_RGBA_SUB (tmp2, cR, cG, cB, cA, sR, sG, sB, sA);
                 *pixels = SDL_MapRGBA (fmt, sR, sG, sB, sA);
                 pixels += bpp;
             }, n, width);
             {
                 GET_PIXEL (pixel, bpp, pixels);
                 GET_PIXELVALS (sR, sG, sB, sA, pixel, fmt);
-                BLEND_RGBA_SUB (tmp, cR, cG, cB, cA, sR, sG, sB, sA);
+                BLEND_RGBA_SUB (tmp2, cR, cG, cB, cA, sR, sG, sB, sA);
                 CREATE_PIXEL(pixels, sR, sG, sB, sA, bpp, fmt);
                 pixels += bpp;
             }, n, width);
     int width = rect->w;
     int height = rect->h;
     int skip;
-    int bpp;
+    int bpp = surface->format->BytesPerPixel;
     int n;
-    SDL_PixelFormat *fmt;
+    SDL_PixelFormat *fmt = surface->format;
     Uint8 sR, sG, sB, sA, cR, cG, cB, cA;
     Uint32 pixel;
     int result = -1;
 
-    bpp = surface->format->BytesPerPixel;
-    fmt = surface->format;
+    if (!(surface->flags & SDL_SRCALPHA && fmt->Amask))
+    {
+	return surface_fill_blend_mult (surface, rect, color);
+    }
+
     pixels = (Uint8 *) surface->pixels + surface->offset +
         (Uint16) rect->y * surface->pitch + (Uint16) rect->x * bpp;
     skip = surface->pitch - width * bpp;
     int width = rect->w;
     int height = rect->h;
     int skip;
-    int bpp;
+    int bpp = surface->format->BytesPerPixel;
     int n;
-    SDL_PixelFormat *fmt;
+    SDL_PixelFormat *fmt = surface->format;
     Uint8 sR, sG, sB, sA, cR, cG, cB, cA;
     Uint32 pixel;
     int result = -1;
 
-    bpp = surface->format->BytesPerPixel;
-    fmt = surface->format;
+    if (!(surface->flags & SDL_SRCALPHA && fmt->Amask))
+    {
+	return surface_fill_blend_min (surface, rect, color);
+    }
+
     pixels = (Uint8 *) surface->pixels + surface->offset +
         (Uint16) rect->y * surface->pitch + (Uint16) rect->x * bpp;
     skip = surface->pitch - width * bpp;
     int width = rect->w;
     int height = rect->h;
     int skip;
-    int bpp;
+    int bpp = surface->format->BytesPerPixel;
     int n;
-    SDL_PixelFormat *fmt;
+    SDL_PixelFormat *fmt = surface->format;
     Uint8 sR, sG, sB, sA, cR, cG, cB, cA;
     Uint32 pixel;
     int result = -1;
 
-    bpp = surface->format->BytesPerPixel;
-    fmt = surface->format;
+    if (!(surface->flags & SDL_SRCALPHA && fmt->Amask))
+    {
+	return surface_fill_blend_max (surface, rect, color);
+    }
+
     pixels = (Uint8 *) surface->pixels + surface->offset +
         (Uint16) rect->y * surface->pitch + (Uint16) rect->x * bpp;
     skip = surface->pitch - width * bpp;
 }
 
 
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-// -------------------------
-
-
-
-static int
-surface_fill_blend_add (SDL_Surface *surface, SDL_Rect *rect, Uint32 color)
-{
-    Uint8 *pixels;
-    int width = rect->w;
-    int height = rect->h;
-    int skip;
-    int bpp;
-    int n;
-    SDL_PixelFormat *fmt;
-    Uint8 sR, sG, sB, sA, cR, cG, cB, cA;
-    Uint32 pixel;
-    Uint32 tmp;
-    int result = -1;
-
-    bpp = surface->format->BytesPerPixel;
-    fmt = surface->format;
-    pixels = (Uint8 *) surface->pixels + surface->offset +
-        (Uint16) rect->y * surface->pitch + (Uint16) rect->x * bpp;
-    skip = surface->pitch - width * bpp;
-
-    switch (bpp)
-    {
-    case 1:
-    {
-        SDL_GetRGBA (color, fmt, &cR, &cG, &cB, &cA);
-        while (height--)
-        {
-            LOOP_UNROLLED4(
-            {
-                GET_PIXELVALS_1 (sR, sG, sB, sA, pixels, fmt);
-                BLEND_ADD (tmp, cR, cG, cB, cA, sR, sG, sB, sA);
-                *pixels = SDL_MapRGBA (fmt, sR, sG, sB, sA);
-                pixels += bpp;
-            }, n, width);
-            pixels += skip;
-        }
-        result = 0;
-        break;
-    }
-    default:
-    {
-        GET_PIXELVALS (cR, cG, cB, cA, color, fmt);
-        /*
-        printf ("Color: %d, %d, %d, %d, BPP is: %d\n", cR, cG, cB, cA, bpp);
-        */
-        while (height--)
-        {
-            LOOP_UNROLLED4(
-            {
-                GET_PIXEL (pixel, bpp, pixels);
-                GET_PIXELVALS (sR, sG, sB, sA, pixel, fmt);
-                BLEND_ADD (tmp, cR, cG, cB, cA, sR, sG, sB, sA);
-                CREATE_PIXEL(pixels, sR, sG, sB, sA, bpp, fmt);
-                pixels += bpp;
-            }, n, width);
-            pixels += skip;
-        }
-        result = 0;
-        break;
-    }
-    }
-    return result;
-}
-
-static int
-surface_fill_blend_sub (SDL_Surface *surface, SDL_Rect *rect, Uint32 color)
-{
-    Uint8 *pixels;
-    int width = rect->w;
-    int height = rect->h;
-    int skip;
-    int bpp;
-    int n;
-    SDL_PixelFormat *fmt;
-    Uint8 sR, sG, sB, sA, cR, cG, cB, cA;
-    Uint32 pixel;
-    Uint32 tmp;
-    int result = -1;
-
-    bpp = surface->format->BytesPerPixel;
-    fmt = surface->format;
-    pixels = (Uint8 *) surface->pixels + surface->offset +
-        (Uint16) rect->y * surface->pitch + (Uint16) rect->x * bpp;
-    skip = surface->pitch - width * bpp;
-
-    switch (bpp)
-    {
-    case 1:
-    {
-        SDL_GetRGBA (color, fmt, &cR, &cG, &cB, &cA);
-        while (height--)
-        {
-            LOOP_UNROLLED4(
-            {
-                GET_PIXELVALS_1 (sR, sG, sB, sA, pixels, fmt);
-                BLEND_SUB (tmp, cR, cG, cB, cA, sR, sG, sB, sA);
-                *pixels = SDL_MapRGBA (fmt, sR, sG, sB, sA);
-                pixels += bpp;
-            }, n, width);
-            pixels += skip;
-        }
-        result = 0;
-        break;
-    }
-    default:
-    {
-        GET_PIXELVALS (cR, cG, cB, cA, color, fmt);
-        /*
-        printf ("Color: %d, %d, %d, %d, BPP is: %d\n", cR, cG, cB, cA, bpp);
-        */
-        while (height--)
-        {
-            LOOP_UNROLLED4(
-            {
-                GET_PIXEL (pixel, bpp, pixels);
-                GET_PIXELVALS (sR, sG, sB, sA, pixel, fmt);
-                BLEND_SUB (tmp, cR, cG, cB, cA, sR, sG, sB, sA);
-                CREATE_PIXEL(pixels, sR, sG, sB, sA, bpp, fmt);
-                pixels += bpp;
-            }, n, width);
-            pixels += skip;
-        }
-        result = 0;
-        break;
-    }
-    }
-    return result;
-}
-
-static int
-surface_fill_blend_mult (SDL_Surface *surface, SDL_Rect *rect, Uint32 color)
-{
-    Uint8 *pixels;
-    int width = rect->w;
-    int height = rect->h;
-    int skip;
-    int bpp;
-    int n;
-    SDL_PixelFormat *fmt;
-    Uint8 sR, sG, sB, sA, cR, cG, cB, cA;
-    Uint32 pixel;
-    int result = -1;
-
-    bpp = surface->format->BytesPerPixel;
-    fmt = surface->format;
-    pixels = (Uint8 *) surface->pixels + surface->offset +
-        (Uint16) rect->y * surface->pitch + (Uint16) rect->x * bpp;
-    skip = surface->pitch - width * bpp;
-
-    switch (bpp)
-    {
-    case 1:
-    {
-        SDL_GetRGBA (color, fmt, &cR, &cG, &cB, &cA);
-        while (height--)
-        {
-            LOOP_UNROLLED4(
-            {
-                GET_PIXELVALS_1 (sR, sG, sB, sA, pixels, fmt);
-                BLEND_MULT (cR, cG, cB, cA, sR, sG, sB, sA);
-                *pixels = SDL_MapRGBA (fmt, sR, sG, sB, sA);
-                pixels += bpp;
-            }, n, width);
-            pixels += skip;
-        }
-        result = 0;
-        break;
-    }
-    default:
-    {
-        GET_PIXELVALS (cR, cG, cB, cA, color, fmt);
-        /*
-        printf ("Color: %d, %d, %d, %d, BPP is: %d\n", cR, cG, cB, cA, bpp);
-        */
-        while (height--)
-        {
-            LOOP_UNROLLED4(
-            {
-                GET_PIXEL (pixel, bpp, pixels);
-                GET_PIXELVALS (sR, sG, sB, sA, pixel, fmt);
-                BLEND_MULT (cR, cG, cB, cA, sR, sG, sB, sA);
-                CREATE_PIXEL(pixels, sR, sG, sB, sA, bpp, fmt);
-                pixels += bpp;
-            }, n, width);
-            pixels += skip;
-        }
-        result = 0;
-        break;
-    }
-    }
-    return result;
-}
-
-static int
-surface_fill_blend_min (SDL_Surface *surface, SDL_Rect *rect, Uint32 color)
-{
-    Uint8 *pixels;
-    int width = rect->w;
-    int height = rect->h;
-    int skip;
-    int bpp;
-    int n;
-    SDL_PixelFormat *fmt;
-    Uint8 sR, sG, sB, sA, cR, cG, cB, cA;
-    Uint32 pixel;
-    int result = -1;
-
-    bpp = surface->format->BytesPerPixel;
-    fmt = surface->format;
-    pixels = (Uint8 *) surface->pixels + surface->offset +
-        (Uint16) rect->y * surface->pitch + (Uint16) rect->x * bpp;
-    skip = surface->pitch - width * bpp;
-
-    switch (bpp)
-    {
-    case 1:
-    {
-        SDL_GetRGBA (color, fmt, &cR, &cG, &cB, &cA);
-        while (height--)
-        {
-            LOOP_UNROLLED4(
-            {
-                GET_PIXELVALS_1 (sR, sG, sB, sA, pixels, fmt);
-                BLEND_MIN (cR, cG, cB, cA, sR, sG, sB, sA);
-                *pixels = SDL_MapRGBA (fmt, sR, sG, sB, sA);
-                pixels += bpp;
-            }, n, width);
-            pixels += skip;
-        }
-        result = 0;
-        break;
-    }
-    default:
-    {
-        GET_PIXELVALS (cR, cG, cB, cA, color, fmt);
-        /*
-        printf ("Color: %d, %d, %d, %d, BPP is: %d\n", cR, cG, cB, cA, bpp);
-        */
-        while (height--)
-        {
-            LOOP_UNROLLED4(
-            {
-                GET_PIXEL (pixel, bpp, pixels);
-                GET_PIXELVALS (sR, sG, sB, sA, pixel, fmt);
-                BLEND_MIN (cR, cG, cB, cA, sR, sG, sB, sA);
-                CREATE_PIXEL(pixels, sR, sG, sB, sA, bpp, fmt);
-                pixels += bpp;
-            }, n, width);
-            pixels += skip;
-        }
-        result = 0;
-        break;
-    }
-    }
-    return result;
-}
-
-static int
-surface_fill_blend_max (SDL_Surface *surface, SDL_Rect *rect, Uint32 color)
-{
-    Uint8 *pixels;
-    int width = rect->w;
-    int height = rect->h;
-    int skip;
-    int bpp;
-    int n;
-    SDL_PixelFormat *fmt;
-    Uint8 sR, sG, sB, sA, cR, cG, cB, cA;
-    Uint32 pixel;
-    int result = -1;
-
-    bpp = surface->format->BytesPerPixel;
-    fmt = surface->format;
-    pixels = (Uint8 *) surface->pixels + surface->offset +
-        (Uint16) rect->y * surface->pitch + (Uint16) rect->x * bpp;
-    skip = surface->pitch - width * bpp;
-
-    switch (bpp)
-    {
-    case 1:
-    {
-        SDL_GetRGBA (color, fmt, &cR, &cG, &cB, &cA);
-        while (height--)
-        {
-            LOOP_UNROLLED4(
-            {
-                GET_PIXELVALS_1 (sR, sG, sB, sA, pixels, fmt);
-                BLEND_MAX (cR, cG, cB, cA, sR, sG, sB, sA);
-                *pixels = SDL_MapRGBA (fmt, sR, sG, sB, sA);
-                pixels += bpp;
-            }, n, width);
-            pixels += skip;
-        }
-        result = 0;
-        break;
-    }
-    default:
-    {
-        GET_PIXELVALS (cR, cG, cB, cA, color, fmt);
-        /*
-        printf ("Color: %d, %d, %d, %d, BPP is: %d\n", cR, cG, cB, cA, bpp);
-        */
-        while (height--)
-        {
-            LOOP_UNROLLED4(
-            {
-                GET_PIXEL (pixel, bpp, pixels);
-                GET_PIXELVALS (sR, sG, sB, sA, pixel, fmt);
-                BLEND_MAX (cR, cG, cB, cA, sR, sG, sB, sA);
-                CREATE_PIXEL(pixels, sR, sG, sB, sA, bpp, fmt);
-                pixels += bpp;
-            }, n, width);
-            pixels += skip;
-        }
-        result = 0;
-        break;
-    }
-    }
-    return result;
-}
-
 int
 surface_fill_blend (SDL_Surface *surface, SDL_Rect *rect, Uint32 color,
                     int blendargs)

File test/surface_test.py

           # will be slower to modify, but quicker to blit as a source.
           # 
 
+        s = pygame.Surface((1,1), SRCALHPA, 32)
+        s.fill((1, 2, 3, 4))
+        s.set_alpha(None)
+        self.failUnlessEqual(s.get_at((0, 0)), (1, 2, 3, 255))
         self.fail() 
 
     def todo_test_set_palette(self):
 
         self.fail()
 
-class SurfaceBlitBlendTest (unittest.TestCase):
+class SurfaceBlendTest (unittest.TestCase):
 
     test_palette = [(0, 0, 0, 255),
-                    (10, 30, 60, 255),
-                    (25, 75, 100, 255),
-                    (100, 150, 200, 255),
+                    (10, 30, 60, 0),
+                    (25, 75, 100, 128),
+                    (100, 150, 200, 200),
                     (0, 100, 200, 255)]
     surf_size = (10, 12)
     test_points = [((0, 0), 1), ((4, 5), 1), ((9, 0), 2),
     def tearDown(self):
         pygame.quit()
 
-    def test_blend(self):
+    def test_blit_blend(self):
         sources = [self._make_src_surface(8),
                    self._make_src_surface(16),
                    self._make_src_surface(16, srcalpha=True),
                    self._make_src_surface(24),
                    self._make_src_surface(32),
                    self._make_src_surface(32, srcalpha=True)]
-        destinations = [self._make_surface(16),
+        destinations = [#self._make_surface(8),
+                        self._make_surface(16),
+                        self._make_surface(16, srcalpha=True),
+                        self._make_surface(24),
+                        self._make_surface(32),
+                        self._make_surface(32, srcalpha=True)]
+        blend = [('BLEND_ADD', (0, 25, 100, 255),
+                  lambda a, b: min(a + b, 255)),
+                 ('BLEND_SUB', (0, 25, 100, 100),
+                  lambda a, b: max(a - b, 0)),
+                 ('BLEND_MULT', (0, 7, 100, 0),
+                  lambda a, b: (a * b) // 256),
+                 ('BLEND_MIN', (0, 255, 0, 255), min),
+                 ('BLEND_MAX', (0, 255, 0, 255), max)]
+
+        for src in sources:
+            src_palette = [src.unmap_rgb(src.map_rgb(c))
+                           for c in self.test_palette]
+            for dst in destinations:
+                for blend_name, dst_color, op in blend:
+                    dc = dst.unmap_rgb(dst.map_rgb(dst_color))
+                    p = []
+                    for sc in src_palette:
+                        c = [op(dc[i], sc[i]) for i in range(3)]
+                        if dst.get_masks()[3]:
+                            c.append(dc[3])
+                        else:
+                            c.append(255)
+                        c = dst.unmap_rgb(dst.map_rgb(c))
+                        p.append(c)
+                    dst.fill(dst_color)
+                    dst.blit(src,
+                              (0, 0),
+                              special_flags=getattr(pygame, blend_name))
+                    self._assert_surface(dst, p,
+                                         (", op: %s, src bpp: %i"
+                                          ", src flags: %i" %
+                                          (blend_name,
+                                           src.get_bitsize(),
+                                           src.get_flags())))
+
+        src = self._make_src_surface(32)
+        masks = src.get_masks()
+        dst = pygame.Surface(src.get_size(), 0, 32,
+                             [masks[1], masks[2], masks[0], masks[3]])
+        for blend_name, dst_color, op in blend:
+            p = []
+            for src_color in self.test_palette:
+                c = [op(dst_color[i], src_color[i]) for i in range(3)]
+                c.append(255)
+                p.append(tuple(c))
+            dst.fill(dst_color)
+            dst.blit(src,
+                     (0, 0),
+                     special_flags=getattr(pygame, blend_name))
+            self._assert_surface(dst, p, ", %s" % blend_name)
+
+    def test_blit_blend_rgba(self):
+        sources = [self._make_src_surface(8),
+                   self._make_src_surface(16),
+                   self._make_src_surface(16, srcalpha=True),
+                   self._make_src_surface(24),
+                   self._make_src_surface(32),
+                   self._make_src_surface(32, srcalpha=True)]
+        destinations = [#self._make_surface(8),
+                        self._make_surface(16),
+                        self._make_surface(16, srcalpha=True),
+                        self._make_surface(24),
+                        self._make_surface(32),
+                        self._make_surface(32, srcalpha=True)]
+        blend = [('BLEND_RGBA_ADD', (0, 25, 100, 255),
+                  lambda a, b: min(a + b, 255)),
+                 ('BLEND_RGBA_SUB', (0, 25, 100, 255),
+                  lambda a, b: max(a - b, 0)),
+                 ('BLEND_RGBA_MULT', (0, 7, 100, 255),
+                  lambda a, b: (a * b) // 256),
+                 ('BLEND_RGBA_MIN', (0, 255, 0, 255), min),
+                 ('BLEND_RGBA_MAX', (0, 255, 0, 255), max)]
+
+        for src in sources:
+            src_palette = [src.unmap_rgb(src.map_rgb(c))
+                           for c in self.test_palette]
+            for dst in destinations:
+                for blend_name, dst_color, op in blend:
+                    dc = dst.unmap_rgb(dst.map_rgb(dst_color))
+                    p = []
+                    for sc in src_palette:
+                        c = [op(dc[i], sc[i]) for i in range(4)]
+                        if not dst.get_masks()[3]:
+                            c[3] = 255
+                        c = dst.unmap_rgb(dst.map_rgb(c))
+                        p.append(c)
+                    dst.fill(dst_color)
+                    dst.blit(src,
+                              (0, 0),
+                              special_flags=getattr(pygame, blend_name))
+                    self._assert_surface(dst, p,
+                                         (", op: %s, src bpp: %i"
+                                          ", src flags: %i" %
+                                          (blend_name,
+                                           src.get_bitsize(),
+                                           src.get_flags())))
+
+        src = self._make_src_surface(32, srcalpha=True)
+        masks = src.get_masks()
+        dst = pygame.Surface(src.get_size(), SRCALPHA, 32,
+                             [masks[1], masks[2], masks[3], masks[0]])
+        for blend_name, dst_color, op in blend:
+            p = [tuple([op(dst_color[i], src_color[i]) for i in range(4)])
+                 for src_color in self.test_palette]
+            dst.fill(dst_color)
+            dst.blit(src,
+                     (0, 0),
+                     special_flags=getattr(pygame, blend_name))
+            self._assert_surface(dst, p, ", %s" % blend_name)
+
+    def todo_test_GET_PIXELVALS(self):
+        # surface.h GET_PIXELVALS bug regarding whether of not
+        # a surface has per-pixel alpha. Looking at the Amask
+        # is not enough. The surface's SRCALPHA flag must also
+        # be considered.
+        src = self._make_surface(32, srcalpha=True)
+        src.fill((0, 0, 0, 128))
+        src.set_alpha(None)  # Clear SRCALPHA flag.
+        dst = self._make_surface(32, srcalpha=True)
+        dst.blit(src, (0, 0), special_flags=BLEND_RGBA_ADD)
+        self.failUnlessEqual(dst.get_at((0, 0)), (0, 0, 0, 255))
+        
+    def test_fill_blend(self):
+        destinations = [#self._make_surface(8),
+                        self._make_surface(16),
                         self._make_surface(16, srcalpha=True),
                         self._make_surface(24),
                         self._make_surface(32),
                  ('BLEND_MIN', (0, 255, 0, 255), min),
                  ('BLEND_MAX', (0, 255, 0, 255), max)]
 
-        dest_color = [0, 25, 100, 255]
-        for src in sources:
-            src_palette = [src.unmap_rgb(src.map_rgb(c))
+        for dst in destinations:
+            dst_palette = [dst.unmap_rgb(dst.map_rgb(c))
                            for c in self.test_palette]
-            for dest in destinations:
-                for blend_name, dest_color, op in blend:
-                    dc = dest.unmap_rgb(dest.map_rgb(dest_color))
-                    p = []
-                    for sc in src_palette:
-                        c = [op(dc[i], sc[i]) for i in range(3)]
+            for blend_name, fill_color, op in blend:
+                fc = dst.unmap_rgb(dst.map_rgb(fill_color))
+                self._fill_surface(dst)
+                p = []
+                for dc in dst_palette:
+                    c = [op(dc[i], fc[i]) for i in range(3)]
+                    if dst.get_masks()[3]:
+                        c.append(dc[3])
+                    else:
                         c.append(255)
-                        c = dest.unmap_rgb(dest.map_rgb(c))
-                        p.append(c)
-                    dest.fill(dest_color)
-                    dest.blit(src,
-                              (0, 0),
-                              special_flags=getattr(pygame, blend_name))
-                    self._assert_surface(dest, p,
-                                         (", op: %s, src bpp: %i"
-                                          ", src flags: %i" %
-                                          (blend_name,
-                                           src.get_bitsize(),
-                                           src.get_flags())))
+                    c = dst.unmap_rgb(dst.map_rgb(c))
+                    p.append(c)
+                dst.fill(fill_color, special_flags=getattr(pygame, blend_name))
+                self._assert_surface(dst, p, ", %s" % blend_name)
 
-    def todo_test_blend_rgb(self):
-        self.fail()
+    def test_fill_blend_rgba(self):
+        destinations = [#self._make_surface(8),
+                        self._make_surface(16),
+                        self._make_surface(16, srcalpha=True),
+                        self._make_surface(24),
+                        self._make_surface(32),
+                        self._make_surface(32, srcalpha=True)]
+        blend = [('BLEND_RGBA_ADD', (0, 25, 100, 255),
+                  lambda a, b: min(a + b, 255)),
+                 ('BLEND_RGBA_SUB', (0, 25, 100, 255),
+                  lambda a, b: max(a - b, 0)),
+                 ('BLEND_RGBA_MULT', (0, 7, 100, 255),
+                  lambda a, b: (a * b) // 256),
+                 ('BLEND_RGBA_MIN', (0, 255, 0, 255), min),
+                 ('BLEND_RGBA_MAX', (0, 255, 0, 255), max)]
 
-    def todo_test_blend_rgba(self):
-        self.fail()
+        for dst in destinations:
+            dst_palette = [dst.unmap_rgb(dst.map_rgb(c))
+                           for c in self.test_palette]
+            for blend_name, fill_color, op in blend:
+                fc = dst.unmap_rgb(dst.map_rgb(fill_color))
+                self._fill_surface(dst)
+                p = []
+                for dc in dst_palette:
+                    c = [op(dc[i], fc[i]) for i in range(4)]
+                    if not dst.get_masks()[3]:
+                        c[3] = 255
+                    c = dst.unmap_rgb(dst.map_rgb(c))
+                    p.append(c)
+                dst.fill(fill_color, special_flags=getattr(pygame, blend_name))
+                self._assert_surface(dst, p, ", %s" % blend_name)
 
 if __name__ == '__main__':
     unittest.main()