Browse Source

Added SDL_BLENDMODE_BLEND_PREMULTIPLIED and SDL_BLENDMODE_ADD_PREMULTIPLIED

Fixes https://github.com/libsdl-org/SDL/issues/2485
Sam Lantinga 1 year ago
parent
commit
df573391b1

+ 26 - 20
include/SDL3/SDL_blendmode.h

@@ -41,8 +41,9 @@ extern "C" {
 /**
  * A set of blend modes used in drawing operations.
  *
- * Note that additional values may be obtained from
- * SDL_ComposeCustomBlendMode.
+ * These predefined blend modes are supported everywhere.
+ *
+ * Additional values may be obtained from SDL_ComposeCustomBlendMode.
  *
  * \since This datatype is available since SDL 3.0.0.
  *
@@ -50,20 +51,25 @@ extern "C" {
  */
 typedef Uint32 SDL_BlendMode;
 
-#define SDL_BLENDMODE_NONE      0x00000000u /**< no blending
-                                                 dstRGBA = srcRGBA */
-#define SDL_BLENDMODE_BLEND     0x00000001u /**< alpha blending
-                                                 dstRGB = (srcRGB * srcA) + (dstRGB * (1-srcA))
-                                                 dstA = srcA + (dstA * (1-srcA)) */
-#define SDL_BLENDMODE_ADD       0x00000002u /**< additive blending
-                                                 dstRGB = (srcRGB * srcA) + dstRGB
-                                                 dstA = dstA */
-#define SDL_BLENDMODE_MOD       0x00000004u /**< color modulate
-                                                 dstRGB = srcRGB * dstRGB
-                                                 dstA = dstA */
-#define SDL_BLENDMODE_MUL       0x00000008u /**< color multiply
-                                                 dstRGB = (srcRGB * dstRGB) + (dstRGB * (1-srcA))
-                                                 dstA = dstA */
+#define SDL_BLENDMODE_NONE                  0x00000000u /**< no blending
+                                                             dstRGBA = srcRGBA */
+#define SDL_BLENDMODE_BLEND                 0x00000001u /**< alpha blending
+                                                             dstRGB = (srcRGB * srcA) + (dstRGB * (1-srcA))
+                                                             dstA = srcA + (dstA * (1-srcA)) */
+#define SDL_BLENDMODE_BLEND_PREMULTIPLIED   0x00000010u /**< pre-multiplied alpha blending
+                                                             dstRGBA = srcRGBA + (dstRGBA * (1-srcA)) */
+#define SDL_BLENDMODE_ADD                   0x00000002u /**< additive blending
+                                                             dstRGB = (srcRGB * srcA) + dstRGB
+                                                             dstA = dstA */
+#define SDL_BLENDMODE_ADD_PREMULTIPLIED     0x00000020u /**< pre-multiplied additive blending
+                                                             dstRGB = srcRGB + dstRGB
+                                                             dstA = dstA */
+#define SDL_BLENDMODE_MOD                   0x00000004u /**< color modulate
+                                                             dstRGB = srcRGB * dstRGB
+                                                             dstA = dstA */
+#define SDL_BLENDMODE_MUL                   0x00000008u /**< color multiply
+                                                             dstRGB = (srcRGB * dstRGB) + (dstRGB * (1-srcA))
+                                                             dstA = dstA */
 #define SDL_BLENDMODE_INVALID   0x7FFFFFFFu
 
 /**
@@ -75,10 +81,10 @@ typedef Uint32 SDL_BlendMode;
 typedef enum SDL_BlendOperation
 {
     SDL_BLENDOPERATION_ADD              = 0x1,  /**< dst + src: supported by all renderers */
-    SDL_BLENDOPERATION_SUBTRACT         = 0x2,  /**< src - dst : supported by D3D9, D3D11, OpenGL, OpenGLES */
-    SDL_BLENDOPERATION_REV_SUBTRACT     = 0x3,  /**< dst - src : supported by D3D9, D3D11, OpenGL, OpenGLES */
-    SDL_BLENDOPERATION_MINIMUM          = 0x4,  /**< min(dst, src) : supported by D3D9, D3D11 */
-    SDL_BLENDOPERATION_MAXIMUM          = 0x5   /**< max(dst, src) : supported by D3D9, D3D11 */
+    SDL_BLENDOPERATION_SUBTRACT         = 0x2,  /**< src - dst : supported by D3D, OpenGL, OpenGLES, and Vulkan */
+    SDL_BLENDOPERATION_REV_SUBTRACT     = 0x3,  /**< dst - src : supported by D3D, OpenGL, OpenGLES, and Vulkan */
+    SDL_BLENDOPERATION_MINIMUM          = 0x4,  /**< min(dst, src) : supported by D3D, OpenGL, OpenGLES, and Vulkan */
+    SDL_BLENDOPERATION_MAXIMUM          = 0x5   /**< max(dst, src) : supported by D3D, OpenGL, OpenGLES, and Vulkan */
 } SDL_BlendOperation;
 
 /**

+ 22 - 0
src/render/SDL_render.c

@@ -83,10 +83,18 @@ this should probably be removed at some point in the future.  --ryan. */
     SDL_COMPOSE_BLENDMODE(SDL_BLENDFACTOR_SRC_ALPHA, SDL_BLENDFACTOR_ONE_MINUS_SRC_ALPHA, SDL_BLENDOPERATION_ADD, \
                           SDL_BLENDFACTOR_ONE, SDL_BLENDFACTOR_ONE_MINUS_SRC_ALPHA, SDL_BLENDOPERATION_ADD)
 
+#define SDL_BLENDMODE_BLEND_PREMULTIPLIED_FULL                                                              \
+    SDL_COMPOSE_BLENDMODE(SDL_BLENDFACTOR_ONE, SDL_BLENDFACTOR_ONE_MINUS_SRC_ALPHA, SDL_BLENDOPERATION_ADD, \
+                          SDL_BLENDFACTOR_ONE, SDL_BLENDFACTOR_ONE_MINUS_SRC_ALPHA, SDL_BLENDOPERATION_ADD)
+
 #define SDL_BLENDMODE_ADD_FULL                                                                    \
     SDL_COMPOSE_BLENDMODE(SDL_BLENDFACTOR_SRC_ALPHA, SDL_BLENDFACTOR_ONE, SDL_BLENDOPERATION_ADD, \
                           SDL_BLENDFACTOR_ZERO, SDL_BLENDFACTOR_ONE, SDL_BLENDOPERATION_ADD)
 
+#define SDL_BLENDMODE_ADD_PREMULTIPLIED_FULL                                                 \
+    SDL_COMPOSE_BLENDMODE(SDL_BLENDFACTOR_ONE,  SDL_BLENDFACTOR_ONE, SDL_BLENDOPERATION_ADD, \
+                          SDL_BLENDFACTOR_ZERO, SDL_BLENDFACTOR_ONE, SDL_BLENDOPERATION_ADD)
+
 #define SDL_BLENDMODE_MOD_FULL                                                                     \
     SDL_COMPOSE_BLENDMODE(SDL_BLENDFACTOR_ZERO, SDL_BLENDFACTOR_SRC_COLOR, SDL_BLENDOPERATION_ADD, \
                           SDL_BLENDFACTOR_ZERO, SDL_BLENDFACTOR_ONE, SDL_BLENDOPERATION_ADD)
@@ -1234,7 +1242,9 @@ static SDL_bool IsSupportedBlendMode(SDL_Renderer *renderer, SDL_BlendMode blend
     /* These are required to be supported by all renderers */
     case SDL_BLENDMODE_NONE:
     case SDL_BLENDMODE_BLEND:
+    case SDL_BLENDMODE_BLEND_PREMULTIPLIED:
     case SDL_BLENDMODE_ADD:
+    case SDL_BLENDMODE_ADD_PREMULTIPLIED:
     case SDL_BLENDMODE_MOD:
     case SDL_BLENDMODE_MUL:
         return SDL_TRUE;
@@ -4682,9 +4692,15 @@ static SDL_BlendMode SDL_GetShortBlendMode(SDL_BlendMode blendMode)
     if (blendMode == SDL_BLENDMODE_BLEND_FULL) {
         return SDL_BLENDMODE_BLEND;
     }
+    if (blendMode == SDL_BLENDMODE_BLEND_PREMULTIPLIED_FULL) {
+        return SDL_BLENDMODE_BLEND_PREMULTIPLIED;
+    }
     if (blendMode == SDL_BLENDMODE_ADD_FULL) {
         return SDL_BLENDMODE_ADD;
     }
+    if (blendMode == SDL_BLENDMODE_ADD_PREMULTIPLIED_FULL) {
+        return SDL_BLENDMODE_ADD_PREMULTIPLIED;
+    }
     if (blendMode == SDL_BLENDMODE_MOD_FULL) {
         return SDL_BLENDMODE_MOD;
     }
@@ -4702,9 +4718,15 @@ static SDL_BlendMode SDL_GetLongBlendMode(SDL_BlendMode blendMode)
     if (blendMode == SDL_BLENDMODE_BLEND) {
         return SDL_BLENDMODE_BLEND_FULL;
     }
+    if (blendMode == SDL_BLENDMODE_BLEND_PREMULTIPLIED) {
+        return SDL_BLENDMODE_BLEND_PREMULTIPLIED_FULL;
+    }
     if (blendMode == SDL_BLENDMODE_ADD) {
         return SDL_BLENDMODE_ADD_FULL;
     }
+    if (blendMode == SDL_BLENDMODE_ADD_PREMULTIPLIED) {
+        return SDL_BLENDMODE_ADD_PREMULTIPLIED_FULL;
+    }
     if (blendMode == SDL_BLENDMODE_MOD) {
         return SDL_BLENDMODE_MOD_FULL;
     }

+ 14 - 0
src/render/ps2/SDL_render_ps2.c

@@ -416,12 +416,26 @@ static void PS2_SetBlendMode(PS2_RenderData *data, int blendMode)
         data->gsGlobal->PrimAlphaEnable = GS_SETTING_ON;
         break;
     }
+    case SDL_BLENDMODE_BLEND_PREMULTIPLIED:
+    {
+        /* FIXME: What are the settings for this? */
+        gsKit_set_primalpha(data->gsGlobal, GS_SETREG_ALPHA(A_COLOR_SOURCE, A_COLOR_DEST, A_ALPHA_SOURCE, A_COLOR_DEST, 0), 0);
+        data->gsGlobal->PrimAlphaEnable = GS_SETTING_ON;
+        break;
+    }
     case SDL_BLENDMODE_ADD:
     {
         gsKit_set_primalpha(data->gsGlobal, GS_SETREG_ALPHA(A_COLOR_SOURCE, A_COLOR_NULL, A_ALPHA_FIX, A_COLOR_DEST, 0x80), 0);
         data->gsGlobal->PrimAlphaEnable = GS_SETTING_ON;
         break;
     }
+    case SDL_BLENDMODE_ADD_PREMULTIPLIED:
+    {
+        /* FIXME: What are the settings for this? */
+        gsKit_set_primalpha(data->gsGlobal, GS_SETREG_ALPHA(A_COLOR_SOURCE, A_COLOR_NULL, A_ALPHA_FIX, A_COLOR_DEST, 0x80), 0);
+        data->gsGlobal->PrimAlphaEnable = GS_SETTING_ON;
+        break;
+    }
     case SDL_BLENDMODE_MUL:
     case SDL_BLENDMODE_MOD:
     {

+ 10 - 0
src/render/psp/SDL_render_psp.c

@@ -990,11 +990,21 @@ static void PSP_SetBlendState(PSP_RenderData *data, PSP_BlendState *state)
             sceGuBlendFunc(GU_ADD, GU_SRC_ALPHA, GU_ONE_MINUS_SRC_ALPHA, 0, 0);
             sceGuEnable(GU_BLEND);
             break;
+        case SDL_BLENDMODE_BLEND_PREMULTIPLIED:
+            sceGuTexFunc(GU_TFX_MODULATE , GU_TCC_RGBA);
+            sceGuBlendFunc(GU_ADD, GU_FIX, GU_ONE_MINUS_SRC_ALPHA, 0x00FFFFFF, 0 );
+            sceGuEnable(GU_BLEND);
+            break;
         case SDL_BLENDMODE_ADD:
             sceGuTexFunc(GU_TFX_MODULATE, GU_TCC_RGBA);
             sceGuBlendFunc(GU_ADD, GU_SRC_ALPHA, GU_FIX, 0, 0x00FFFFFF);
             sceGuEnable(GU_BLEND);
             break;
+        case SDL_BLENDMODE_ADD_PREMULTIPLIED:
+            sceGuTexFunc(GU_TFX_MODULATE, GU_TCC_RGBA);
+            sceGuBlendFunc(GU_ADD, GU_FIX, GU_FIX, 0, 0x00FFFFFF);
+            sceGuEnable(GU_BLEND);
+            break;
         case SDL_BLENDMODE_MOD:
             sceGuTexFunc(GU_TFX_MODULATE, GU_TCC_RGBA);
             sceGuBlendFunc(GU_ADD, GU_FIX, GU_SRC_COLOR, 0, 0);

+ 28 - 0
src/render/software/SDL_blendfillrect.c

@@ -34,7 +34,11 @@ static int SDL_BlendFillRect_RGB555(SDL_Surface *dst, const SDL_Rect *rect,
     case SDL_BLENDMODE_BLEND:
         FILLRECT(Uint16, DRAW_SETPIXEL_BLEND_RGB555);
         break;
+    case SDL_BLENDMODE_BLEND_PREMULTIPLIED:
+        FILLRECT(Uint16, DRAW_SETPIXEL_BLEND_CLAMPED_RGB555);
+        break;
     case SDL_BLENDMODE_ADD:
+    case SDL_BLENDMODE_ADD_PREMULTIPLIED:
         FILLRECT(Uint16, DRAW_SETPIXEL_ADD_RGB555);
         break;
     case SDL_BLENDMODE_MOD:
@@ -59,7 +63,11 @@ static int SDL_BlendFillRect_RGB565(SDL_Surface *dst, const SDL_Rect *rect,
     case SDL_BLENDMODE_BLEND:
         FILLRECT(Uint16, DRAW_SETPIXEL_BLEND_RGB565);
         break;
+    case SDL_BLENDMODE_BLEND_PREMULTIPLIED:
+        FILLRECT(Uint16, DRAW_SETPIXEL_BLEND_CLAMPED_RGB565);
+        break;
     case SDL_BLENDMODE_ADD:
+    case SDL_BLENDMODE_ADD_PREMULTIPLIED:
         FILLRECT(Uint16, DRAW_SETPIXEL_ADD_RGB565);
         break;
     case SDL_BLENDMODE_MOD:
@@ -84,7 +92,11 @@ static int SDL_BlendFillRect_XRGB8888(SDL_Surface *dst, const SDL_Rect *rect,
     case SDL_BLENDMODE_BLEND:
         FILLRECT(Uint32, DRAW_SETPIXEL_BLEND_XRGB8888);
         break;
+    case SDL_BLENDMODE_BLEND_PREMULTIPLIED:
+        FILLRECT(Uint32, DRAW_SETPIXEL_BLEND_CLAMPED_XRGB8888);
+        break;
     case SDL_BLENDMODE_ADD:
+    case SDL_BLENDMODE_ADD_PREMULTIPLIED:
         FILLRECT(Uint32, DRAW_SETPIXEL_ADD_XRGB8888);
         break;
     case SDL_BLENDMODE_MOD:
@@ -109,7 +121,11 @@ static int SDL_BlendFillRect_ARGB8888(SDL_Surface *dst, const SDL_Rect *rect,
     case SDL_BLENDMODE_BLEND:
         FILLRECT(Uint32, DRAW_SETPIXEL_BLEND_ARGB8888);
         break;
+    case SDL_BLENDMODE_BLEND_PREMULTIPLIED:
+        FILLRECT(Uint32, DRAW_SETPIXEL_BLEND_CLAMPED_ARGB8888);
+        break;
     case SDL_BLENDMODE_ADD:
+    case SDL_BLENDMODE_ADD_PREMULTIPLIED:
         FILLRECT(Uint32, DRAW_SETPIXEL_ADD_ARGB8888);
         break;
     case SDL_BLENDMODE_MOD:
@@ -137,7 +153,11 @@ static int SDL_BlendFillRect_RGB(SDL_Surface *dst, const SDL_Rect *rect,
         case SDL_BLENDMODE_BLEND:
             FILLRECT(Uint16, DRAW_SETPIXEL_BLEND_RGB);
             break;
+        case SDL_BLENDMODE_BLEND_PREMULTIPLIED:
+            FILLRECT(Uint16, DRAW_SETPIXEL_BLEND_CLAMPED_RGB);
+            break;
         case SDL_BLENDMODE_ADD:
+        case SDL_BLENDMODE_ADD_PREMULTIPLIED:
             FILLRECT(Uint16, DRAW_SETPIXEL_ADD_RGB);
             break;
         case SDL_BLENDMODE_MOD:
@@ -156,7 +176,11 @@ static int SDL_BlendFillRect_RGB(SDL_Surface *dst, const SDL_Rect *rect,
         case SDL_BLENDMODE_BLEND:
             FILLRECT(Uint32, DRAW_SETPIXEL_BLEND_RGB);
             break;
+        case SDL_BLENDMODE_BLEND_PREMULTIPLIED:
+            FILLRECT(Uint32, DRAW_SETPIXEL_BLEND_CLAMPED_RGB);
+            break;
         case SDL_BLENDMODE_ADD:
+        case SDL_BLENDMODE_ADD_PREMULTIPLIED:
             FILLRECT(Uint32, DRAW_SETPIXEL_ADD_RGB);
             break;
         case SDL_BLENDMODE_MOD:
@@ -187,7 +211,11 @@ static int SDL_BlendFillRect_RGBA(SDL_Surface *dst, const SDL_Rect *rect,
         case SDL_BLENDMODE_BLEND:
             FILLRECT(Uint32, DRAW_SETPIXEL_BLEND_RGBA);
             break;
+        case SDL_BLENDMODE_BLEND_PREMULTIPLIED:
+            FILLRECT(Uint32, DRAW_SETPIXEL_BLEND_CLAMPED_RGBA);
+            break;
         case SDL_BLENDMODE_ADD:
+        case SDL_BLENDMODE_ADD_PREMULTIPLIED:
             FILLRECT(Uint32, DRAW_SETPIXEL_ADD_RGBA);
             break;
         case SDL_BLENDMODE_MOD:

+ 126 - 0
src/render/software/SDL_blendline.c

@@ -51,7 +51,11 @@ static void SDL_BlendLine_RGB2(SDL_Surface *dst, int x1, int y1, int x2, int y2,
         case SDL_BLENDMODE_BLEND:
             HLINE(Uint16, DRAW_SETPIXEL_BLEND_RGB, draw_end);
             break;
+        case SDL_BLENDMODE_BLEND_PREMULTIPLIED:
+            HLINE(Uint16, DRAW_SETPIXEL_BLEND_CLAMPED_RGB, draw_end);
+            break;
         case SDL_BLENDMODE_ADD:
+        case SDL_BLENDMODE_ADD_PREMULTIPLIED:
             HLINE(Uint16, DRAW_SETPIXEL_ADD_RGB, draw_end);
             break;
         case SDL_BLENDMODE_MOD:
@@ -69,7 +73,11 @@ static void SDL_BlendLine_RGB2(SDL_Surface *dst, int x1, int y1, int x2, int y2,
         case SDL_BLENDMODE_BLEND:
             VLINE(Uint16, DRAW_SETPIXEL_BLEND_RGB, draw_end);
             break;
+        case SDL_BLENDMODE_BLEND_PREMULTIPLIED:
+            VLINE(Uint16, DRAW_SETPIXEL_BLEND_CLAMPED_RGB, draw_end);
+            break;
         case SDL_BLENDMODE_ADD:
+        case SDL_BLENDMODE_ADD_PREMULTIPLIED:
             VLINE(Uint16, DRAW_SETPIXEL_ADD_RGB, draw_end);
             break;
         case SDL_BLENDMODE_MOD:
@@ -87,7 +95,11 @@ static void SDL_BlendLine_RGB2(SDL_Surface *dst, int x1, int y1, int x2, int y2,
         case SDL_BLENDMODE_BLEND:
             DLINE(Uint16, DRAW_SETPIXEL_BLEND_RGB, draw_end);
             break;
+        case SDL_BLENDMODE_BLEND_PREMULTIPLIED:
+            DLINE(Uint16, DRAW_SETPIXEL_BLEND_CLAMPED_RGB, draw_end);
+            break;
         case SDL_BLENDMODE_ADD:
+        case SDL_BLENDMODE_ADD_PREMULTIPLIED:
             DLINE(Uint16, DRAW_SETPIXEL_ADD_RGB, draw_end);
             break;
         case SDL_BLENDMODE_MOD:
@@ -107,7 +119,13 @@ static void SDL_BlendLine_RGB2(SDL_Surface *dst, int x1, int y1, int x2, int y2,
                    DRAW_SETPIXELXY2_BLEND_RGB, DRAW_SETPIXELXY2_BLEND_RGB,
                    draw_end);
             break;
+        case SDL_BLENDMODE_BLEND_PREMULTIPLIED:
+            AALINE(x1, y1, x2, y2,
+                   DRAW_SETPIXELXY2_BLEND_CLAMPED_RGB, DRAW_SETPIXELXY2_BLEND_CLAMPED_RGB,
+                   draw_end);
+            break;
         case SDL_BLENDMODE_ADD:
+        case SDL_BLENDMODE_ADD_PREMULTIPLIED:
             AALINE(x1, y1, x2, y2,
                    DRAW_SETPIXELXY2_ADD_RGB, DRAW_SETPIXELXY2_ADD_RGB,
                    draw_end);
@@ -155,7 +173,11 @@ static void SDL_BlendLine_RGB555(SDL_Surface *dst, int x1, int y1, int x2, int y
         case SDL_BLENDMODE_BLEND:
             HLINE(Uint16, DRAW_SETPIXEL_BLEND_RGB555, draw_end);
             break;
+        case SDL_BLENDMODE_BLEND_PREMULTIPLIED:
+            HLINE(Uint16, DRAW_SETPIXEL_BLEND_CLAMPED_RGB555, draw_end);
+            break;
         case SDL_BLENDMODE_ADD:
+        case SDL_BLENDMODE_ADD_PREMULTIPLIED:
             HLINE(Uint16, DRAW_SETPIXEL_ADD_RGB555, draw_end);
             break;
         case SDL_BLENDMODE_MOD:
@@ -173,7 +195,11 @@ static void SDL_BlendLine_RGB555(SDL_Surface *dst, int x1, int y1, int x2, int y
         case SDL_BLENDMODE_BLEND:
             VLINE(Uint16, DRAW_SETPIXEL_BLEND_RGB555, draw_end);
             break;
+        case SDL_BLENDMODE_BLEND_PREMULTIPLIED:
+            VLINE(Uint16, DRAW_SETPIXEL_BLEND_CLAMPED_RGB555, draw_end);
+            break;
         case SDL_BLENDMODE_ADD:
+        case SDL_BLENDMODE_ADD_PREMULTIPLIED:
             VLINE(Uint16, DRAW_SETPIXEL_ADD_RGB555, draw_end);
             break;
         case SDL_BLENDMODE_MOD:
@@ -191,7 +217,11 @@ static void SDL_BlendLine_RGB555(SDL_Surface *dst, int x1, int y1, int x2, int y
         case SDL_BLENDMODE_BLEND:
             DLINE(Uint16, DRAW_SETPIXEL_BLEND_RGB555, draw_end);
             break;
+        case SDL_BLENDMODE_BLEND_PREMULTIPLIED:
+            DLINE(Uint16, DRAW_SETPIXEL_BLEND_CLAMPED_RGB555, draw_end);
+            break;
         case SDL_BLENDMODE_ADD:
+        case SDL_BLENDMODE_ADD_PREMULTIPLIED:
             DLINE(Uint16, DRAW_SETPIXEL_ADD_RGB555, draw_end);
             break;
         case SDL_BLENDMODE_MOD:
@@ -211,7 +241,13 @@ static void SDL_BlendLine_RGB555(SDL_Surface *dst, int x1, int y1, int x2, int y
                    DRAW_SETPIXELXY_BLEND_RGB555, DRAW_SETPIXELXY_BLEND_RGB555,
                    draw_end);
             break;
+        case SDL_BLENDMODE_BLEND_PREMULTIPLIED:
+            AALINE(x1, y1, x2, y2,
+                   DRAW_SETPIXELXY_BLEND_CLAMPED_RGB555, DRAW_SETPIXELXY_BLEND_CLAMPED_RGB555,
+                   draw_end);
+            break;
         case SDL_BLENDMODE_ADD:
+        case SDL_BLENDMODE_ADD_PREMULTIPLIED:
             AALINE(x1, y1, x2, y2,
                    DRAW_SETPIXELXY_ADD_RGB555, DRAW_SETPIXELXY_ADD_RGB555,
                    draw_end);
@@ -259,7 +295,11 @@ static void SDL_BlendLine_RGB565(SDL_Surface *dst, int x1, int y1, int x2, int y
         case SDL_BLENDMODE_BLEND:
             HLINE(Uint16, DRAW_SETPIXEL_BLEND_RGB565, draw_end);
             break;
+        case SDL_BLENDMODE_BLEND_PREMULTIPLIED:
+            HLINE(Uint16, DRAW_SETPIXEL_BLEND_CLAMPED_RGB565, draw_end);
+            break;
         case SDL_BLENDMODE_ADD:
+        case SDL_BLENDMODE_ADD_PREMULTIPLIED:
             HLINE(Uint16, DRAW_SETPIXEL_ADD_RGB565, draw_end);
             break;
         case SDL_BLENDMODE_MOD:
@@ -277,7 +317,11 @@ static void SDL_BlendLine_RGB565(SDL_Surface *dst, int x1, int y1, int x2, int y
         case SDL_BLENDMODE_BLEND:
             VLINE(Uint16, DRAW_SETPIXEL_BLEND_RGB565, draw_end);
             break;
+        case SDL_BLENDMODE_BLEND_PREMULTIPLIED:
+            VLINE(Uint16, DRAW_SETPIXEL_BLEND_CLAMPED_RGB565, draw_end);
+            break;
         case SDL_BLENDMODE_ADD:
+        case SDL_BLENDMODE_ADD_PREMULTIPLIED:
             VLINE(Uint16, DRAW_SETPIXEL_ADD_RGB565, draw_end);
             break;
         case SDL_BLENDMODE_MOD:
@@ -295,7 +339,11 @@ static void SDL_BlendLine_RGB565(SDL_Surface *dst, int x1, int y1, int x2, int y
         case SDL_BLENDMODE_BLEND:
             DLINE(Uint16, DRAW_SETPIXEL_BLEND_RGB565, draw_end);
             break;
+        case SDL_BLENDMODE_BLEND_PREMULTIPLIED:
+            DLINE(Uint16, DRAW_SETPIXEL_BLEND_CLAMPED_RGB565, draw_end);
+            break;
         case SDL_BLENDMODE_ADD:
+        case SDL_BLENDMODE_ADD_PREMULTIPLIED:
             DLINE(Uint16, DRAW_SETPIXEL_ADD_RGB565, draw_end);
             break;
         case SDL_BLENDMODE_MOD:
@@ -315,7 +363,13 @@ static void SDL_BlendLine_RGB565(SDL_Surface *dst, int x1, int y1, int x2, int y
                    DRAW_SETPIXELXY_BLEND_RGB565, DRAW_SETPIXELXY_BLEND_RGB565,
                    draw_end);
             break;
+        case SDL_BLENDMODE_BLEND_PREMULTIPLIED:
+            AALINE(x1, y1, x2, y2,
+                   DRAW_SETPIXELXY_BLEND_CLAMPED_RGB565, DRAW_SETPIXELXY_BLEND_CLAMPED_RGB565,
+                   draw_end);
+            break;
         case SDL_BLENDMODE_ADD:
+        case SDL_BLENDMODE_ADD_PREMULTIPLIED:
             AALINE(x1, y1, x2, y2,
                    DRAW_SETPIXELXY_ADD_RGB565, DRAW_SETPIXELXY_ADD_RGB565,
                    draw_end);
@@ -364,7 +418,11 @@ static void SDL_BlendLine_RGB4(SDL_Surface *dst, int x1, int y1, int x2, int y2,
         case SDL_BLENDMODE_BLEND:
             HLINE(Uint32, DRAW_SETPIXEL_BLEND_RGB, draw_end);
             break;
+        case SDL_BLENDMODE_BLEND_PREMULTIPLIED:
+            HLINE(Uint32, DRAW_SETPIXEL_BLEND_CLAMPED_RGB, draw_end);
+            break;
         case SDL_BLENDMODE_ADD:
+        case SDL_BLENDMODE_ADD_PREMULTIPLIED:
             HLINE(Uint32, DRAW_SETPIXEL_ADD_RGB, draw_end);
             break;
         case SDL_BLENDMODE_MOD:
@@ -382,7 +440,11 @@ static void SDL_BlendLine_RGB4(SDL_Surface *dst, int x1, int y1, int x2, int y2,
         case SDL_BLENDMODE_BLEND:
             VLINE(Uint32, DRAW_SETPIXEL_BLEND_RGB, draw_end);
             break;
+        case SDL_BLENDMODE_BLEND_PREMULTIPLIED:
+            VLINE(Uint32, DRAW_SETPIXEL_BLEND_CLAMPED_RGB, draw_end);
+            break;
         case SDL_BLENDMODE_ADD:
+        case SDL_BLENDMODE_ADD_PREMULTIPLIED:
             VLINE(Uint32, DRAW_SETPIXEL_ADD_RGB, draw_end);
             break;
         case SDL_BLENDMODE_MOD:
@@ -400,7 +462,11 @@ static void SDL_BlendLine_RGB4(SDL_Surface *dst, int x1, int y1, int x2, int y2,
         case SDL_BLENDMODE_BLEND:
             DLINE(Uint32, DRAW_SETPIXEL_BLEND_RGB, draw_end);
             break;
+        case SDL_BLENDMODE_BLEND_PREMULTIPLIED:
+            DLINE(Uint32, DRAW_SETPIXEL_BLEND_CLAMPED_RGB, draw_end);
+            break;
         case SDL_BLENDMODE_ADD:
+        case SDL_BLENDMODE_ADD_PREMULTIPLIED:
             DLINE(Uint32, DRAW_SETPIXEL_ADD_RGB, draw_end);
             break;
         case SDL_BLENDMODE_MOD:
@@ -420,7 +486,13 @@ static void SDL_BlendLine_RGB4(SDL_Surface *dst, int x1, int y1, int x2, int y2,
                    DRAW_SETPIXELXY4_BLEND_RGB, DRAW_SETPIXELXY4_BLEND_RGB,
                    draw_end);
             break;
+        case SDL_BLENDMODE_BLEND_PREMULTIPLIED:
+            AALINE(x1, y1, x2, y2,
+                   DRAW_SETPIXELXY4_BLEND_CLAMPED_RGB, DRAW_SETPIXELXY4_BLEND_CLAMPED_RGB,
+                   draw_end);
+            break;
         case SDL_BLENDMODE_ADD:
+        case SDL_BLENDMODE_ADD_PREMULTIPLIED:
             AALINE(x1, y1, x2, y2,
                    DRAW_SETPIXELXY4_ADD_RGB, DRAW_SETPIXELXY4_ADD_RGB,
                    draw_end);
@@ -469,7 +541,11 @@ static void SDL_BlendLine_RGBA4(SDL_Surface *dst, int x1, int y1, int x2, int y2
         case SDL_BLENDMODE_BLEND:
             HLINE(Uint32, DRAW_SETPIXEL_BLEND_RGBA, draw_end);
             break;
+        case SDL_BLENDMODE_BLEND_PREMULTIPLIED:
+            HLINE(Uint32, DRAW_SETPIXEL_BLEND_CLAMPED_RGBA, draw_end);
+            break;
         case SDL_BLENDMODE_ADD:
+        case SDL_BLENDMODE_ADD_PREMULTIPLIED:
             HLINE(Uint32, DRAW_SETPIXEL_ADD_RGBA, draw_end);
             break;
         case SDL_BLENDMODE_MOD:
@@ -487,7 +563,11 @@ static void SDL_BlendLine_RGBA4(SDL_Surface *dst, int x1, int y1, int x2, int y2
         case SDL_BLENDMODE_BLEND:
             VLINE(Uint32, DRAW_SETPIXEL_BLEND_RGBA, draw_end);
             break;
+        case SDL_BLENDMODE_BLEND_PREMULTIPLIED:
+            VLINE(Uint32, DRAW_SETPIXEL_BLEND_CLAMPED_RGBA, draw_end);
+            break;
         case SDL_BLENDMODE_ADD:
+        case SDL_BLENDMODE_ADD_PREMULTIPLIED:
             VLINE(Uint32, DRAW_SETPIXEL_ADD_RGBA, draw_end);
             break;
         case SDL_BLENDMODE_MOD:
@@ -505,7 +585,11 @@ static void SDL_BlendLine_RGBA4(SDL_Surface *dst, int x1, int y1, int x2, int y2
         case SDL_BLENDMODE_BLEND:
             DLINE(Uint32, DRAW_SETPIXEL_BLEND_RGBA, draw_end);
             break;
+        case SDL_BLENDMODE_BLEND_PREMULTIPLIED:
+            DLINE(Uint32, DRAW_SETPIXEL_BLEND_CLAMPED_RGBA, draw_end);
+            break;
         case SDL_BLENDMODE_ADD:
+        case SDL_BLENDMODE_ADD_PREMULTIPLIED:
             DLINE(Uint32, DRAW_SETPIXEL_ADD_RGBA, draw_end);
             break;
         case SDL_BLENDMODE_MOD:
@@ -525,7 +609,13 @@ static void SDL_BlendLine_RGBA4(SDL_Surface *dst, int x1, int y1, int x2, int y2
                    DRAW_SETPIXELXY4_BLEND_RGBA, DRAW_SETPIXELXY4_BLEND_RGBA,
                    draw_end);
             break;
+        case SDL_BLENDMODE_BLEND_PREMULTIPLIED:
+            AALINE(x1, y1, x2, y2,
+                   DRAW_SETPIXELXY4_BLEND_CLAMPED_RGBA, DRAW_SETPIXELXY4_BLEND_CLAMPED_RGBA,
+                   draw_end);
+            break;
         case SDL_BLENDMODE_ADD:
+        case SDL_BLENDMODE_ADD_PREMULTIPLIED:
             AALINE(x1, y1, x2, y2,
                    DRAW_SETPIXELXY4_ADD_RGBA, DRAW_SETPIXELXY4_ADD_RGBA,
                    draw_end);
@@ -573,7 +663,11 @@ static void SDL_BlendLine_XRGB8888(SDL_Surface *dst, int x1, int y1, int x2, int
         case SDL_BLENDMODE_BLEND:
             HLINE(Uint32, DRAW_SETPIXEL_BLEND_XRGB8888, draw_end);
             break;
+        case SDL_BLENDMODE_BLEND_PREMULTIPLIED:
+            HLINE(Uint32, DRAW_SETPIXEL_BLEND_CLAMPED_XRGB8888, draw_end);
+            break;
         case SDL_BLENDMODE_ADD:
+        case SDL_BLENDMODE_ADD_PREMULTIPLIED:
             HLINE(Uint32, DRAW_SETPIXEL_ADD_XRGB8888, draw_end);
             break;
         case SDL_BLENDMODE_MOD:
@@ -591,7 +685,11 @@ static void SDL_BlendLine_XRGB8888(SDL_Surface *dst, int x1, int y1, int x2, int
         case SDL_BLENDMODE_BLEND:
             VLINE(Uint32, DRAW_SETPIXEL_BLEND_XRGB8888, draw_end);
             break;
+        case SDL_BLENDMODE_BLEND_PREMULTIPLIED:
+            VLINE(Uint32, DRAW_SETPIXEL_BLEND_CLAMPED_XRGB8888, draw_end);
+            break;
         case SDL_BLENDMODE_ADD:
+        case SDL_BLENDMODE_ADD_PREMULTIPLIED:
             VLINE(Uint32, DRAW_SETPIXEL_ADD_XRGB8888, draw_end);
             break;
         case SDL_BLENDMODE_MOD:
@@ -609,7 +707,11 @@ static void SDL_BlendLine_XRGB8888(SDL_Surface *dst, int x1, int y1, int x2, int
         case SDL_BLENDMODE_BLEND:
             DLINE(Uint32, DRAW_SETPIXEL_BLEND_XRGB8888, draw_end);
             break;
+        case SDL_BLENDMODE_BLEND_PREMULTIPLIED:
+            DLINE(Uint32, DRAW_SETPIXEL_BLEND_CLAMPED_XRGB8888, draw_end);
+            break;
         case SDL_BLENDMODE_ADD:
+        case SDL_BLENDMODE_ADD_PREMULTIPLIED:
             DLINE(Uint32, DRAW_SETPIXEL_ADD_XRGB8888, draw_end);
             break;
         case SDL_BLENDMODE_MOD:
@@ -629,7 +731,13 @@ static void SDL_BlendLine_XRGB8888(SDL_Surface *dst, int x1, int y1, int x2, int
                    DRAW_SETPIXELXY_BLEND_XRGB8888, DRAW_SETPIXELXY_BLEND_XRGB8888,
                    draw_end);
             break;
+        case SDL_BLENDMODE_BLEND_PREMULTIPLIED:
+            AALINE(x1, y1, x2, y2,
+                   DRAW_SETPIXELXY_BLEND_CLAMPED_XRGB8888, DRAW_SETPIXELXY_BLEND_CLAMPED_XRGB8888,
+                   draw_end);
+            break;
         case SDL_BLENDMODE_ADD:
+        case SDL_BLENDMODE_ADD_PREMULTIPLIED:
             AALINE(x1, y1, x2, y2,
                    DRAW_SETPIXELXY_ADD_XRGB8888, DRAW_SETPIXELXY_ADD_XRGB8888,
                    draw_end);
@@ -677,7 +785,11 @@ static void SDL_BlendLine_ARGB8888(SDL_Surface *dst, int x1, int y1, int x2, int
         case SDL_BLENDMODE_BLEND:
             HLINE(Uint32, DRAW_SETPIXEL_BLEND_ARGB8888, draw_end);
             break;
+        case SDL_BLENDMODE_BLEND_PREMULTIPLIED:
+            HLINE(Uint32, DRAW_SETPIXEL_BLEND_CLAMPED_ARGB8888, draw_end);
+            break;
         case SDL_BLENDMODE_ADD:
+        case SDL_BLENDMODE_ADD_PREMULTIPLIED:
             HLINE(Uint32, DRAW_SETPIXEL_ADD_ARGB8888, draw_end);
             break;
         case SDL_BLENDMODE_MOD:
@@ -695,7 +807,11 @@ static void SDL_BlendLine_ARGB8888(SDL_Surface *dst, int x1, int y1, int x2, int
         case SDL_BLENDMODE_BLEND:
             VLINE(Uint32, DRAW_SETPIXEL_BLEND_ARGB8888, draw_end);
             break;
+        case SDL_BLENDMODE_BLEND_PREMULTIPLIED:
+            VLINE(Uint32, DRAW_SETPIXEL_BLEND_CLAMPED_ARGB8888, draw_end);
+            break;
         case SDL_BLENDMODE_ADD:
+        case SDL_BLENDMODE_ADD_PREMULTIPLIED:
             VLINE(Uint32, DRAW_SETPIXEL_ADD_ARGB8888, draw_end);
             break;
         case SDL_BLENDMODE_MOD:
@@ -713,7 +829,11 @@ static void SDL_BlendLine_ARGB8888(SDL_Surface *dst, int x1, int y1, int x2, int
         case SDL_BLENDMODE_BLEND:
             DLINE(Uint32, DRAW_SETPIXEL_BLEND_ARGB8888, draw_end);
             break;
+        case SDL_BLENDMODE_BLEND_PREMULTIPLIED:
+            DLINE(Uint32, DRAW_SETPIXEL_BLEND_CLAMPED_ARGB8888, draw_end);
+            break;
         case SDL_BLENDMODE_ADD:
+        case SDL_BLENDMODE_ADD_PREMULTIPLIED:
             DLINE(Uint32, DRAW_SETPIXEL_ADD_ARGB8888, draw_end);
             break;
         case SDL_BLENDMODE_MOD:
@@ -733,7 +853,13 @@ static void SDL_BlendLine_ARGB8888(SDL_Surface *dst, int x1, int y1, int x2, int
                    DRAW_SETPIXELXY_BLEND_ARGB8888, DRAW_SETPIXELXY_BLEND_ARGB8888,
                    draw_end);
             break;
+        case SDL_BLENDMODE_BLEND_PREMULTIPLIED:
+            AALINE(x1, y1, x2, y2,
+                   DRAW_SETPIXELXY_BLEND_CLAMPED_ARGB8888, DRAW_SETPIXELXY_BLEND_CLAMPED_ARGB8888,
+                   draw_end);
+            break;
         case SDL_BLENDMODE_ADD:
+        case SDL_BLENDMODE_ADD_PREMULTIPLIED:
             AALINE(x1, y1, x2, y2,
                    DRAW_SETPIXELXY_ADD_ARGB8888, DRAW_SETPIXELXY_ADD_ARGB8888,
                    draw_end);

+ 28 - 0
src/render/software/SDL_blendpoint.c

@@ -34,7 +34,11 @@ static int SDL_BlendPoint_RGB555(SDL_Surface *dst, int x, int y, SDL_BlendMode b
     case SDL_BLENDMODE_BLEND:
         DRAW_SETPIXELXY_BLEND_RGB555(x, y);
         break;
+    case SDL_BLENDMODE_BLEND_PREMULTIPLIED:
+        DRAW_SETPIXELXY_BLEND_CLAMPED_RGB555(x, y);
+        break;
     case SDL_BLENDMODE_ADD:
+    case SDL_BLENDMODE_ADD_PREMULTIPLIED:
         DRAW_SETPIXELXY_ADD_RGB555(x, y);
         break;
     case SDL_BLENDMODE_MOD:
@@ -59,7 +63,11 @@ static int SDL_BlendPoint_RGB565(SDL_Surface *dst, int x, int y, SDL_BlendMode b
     case SDL_BLENDMODE_BLEND:
         DRAW_SETPIXELXY_BLEND_RGB565(x, y);
         break;
+    case SDL_BLENDMODE_BLEND_PREMULTIPLIED:
+        DRAW_SETPIXELXY_BLEND_CLAMPED_RGB565(x, y);
+        break;
     case SDL_BLENDMODE_ADD:
+    case SDL_BLENDMODE_ADD_PREMULTIPLIED:
         DRAW_SETPIXELXY_ADD_RGB565(x, y);
         break;
     case SDL_BLENDMODE_MOD:
@@ -84,7 +92,11 @@ static int SDL_BlendPoint_XRGB8888(SDL_Surface *dst, int x, int y, SDL_BlendMode
     case SDL_BLENDMODE_BLEND:
         DRAW_SETPIXELXY_BLEND_XRGB8888(x, y);
         break;
+    case SDL_BLENDMODE_BLEND_PREMULTIPLIED:
+        DRAW_SETPIXELXY_BLEND_CLAMPED_XRGB8888(x, y);
+        break;
     case SDL_BLENDMODE_ADD:
+    case SDL_BLENDMODE_ADD_PREMULTIPLIED:
         DRAW_SETPIXELXY_ADD_XRGB8888(x, y);
         break;
     case SDL_BLENDMODE_MOD:
@@ -109,7 +121,11 @@ static int SDL_BlendPoint_ARGB8888(SDL_Surface *dst, int x, int y, SDL_BlendMode
     case SDL_BLENDMODE_BLEND:
         DRAW_SETPIXELXY_BLEND_ARGB8888(x, y);
         break;
+    case SDL_BLENDMODE_BLEND_PREMULTIPLIED:
+        DRAW_SETPIXELXY_BLEND_CLAMPED_ARGB8888(x, y);
+        break;
     case SDL_BLENDMODE_ADD:
+    case SDL_BLENDMODE_ADD_PREMULTIPLIED:
         DRAW_SETPIXELXY_ADD_ARGB8888(x, y);
         break;
     case SDL_BLENDMODE_MOD:
@@ -137,7 +153,11 @@ static int SDL_BlendPoint_RGB(SDL_Surface *dst, int x, int y, SDL_BlendMode blen
         case SDL_BLENDMODE_BLEND:
             DRAW_SETPIXELXY2_BLEND_RGB(x, y);
             break;
+        case SDL_BLENDMODE_BLEND_PREMULTIPLIED:
+            DRAW_SETPIXELXY2_BLEND_CLAMPED_RGB(x, y);
+            break;
         case SDL_BLENDMODE_ADD:
+        case SDL_BLENDMODE_ADD_PREMULTIPLIED:
             DRAW_SETPIXELXY2_ADD_RGB(x, y);
             break;
         case SDL_BLENDMODE_MOD:
@@ -156,7 +176,11 @@ static int SDL_BlendPoint_RGB(SDL_Surface *dst, int x, int y, SDL_BlendMode blen
         case SDL_BLENDMODE_BLEND:
             DRAW_SETPIXELXY4_BLEND_RGB(x, y);
             break;
+        case SDL_BLENDMODE_BLEND_PREMULTIPLIED:
+            DRAW_SETPIXELXY4_BLEND_CLAMPED_RGB(x, y);
+            break;
         case SDL_BLENDMODE_ADD:
+        case SDL_BLENDMODE_ADD_PREMULTIPLIED:
             DRAW_SETPIXELXY4_ADD_RGB(x, y);
             break;
         case SDL_BLENDMODE_MOD:
@@ -187,7 +211,11 @@ static int SDL_BlendPoint_RGBA(SDL_Surface *dst, int x, int y, SDL_BlendMode ble
         case SDL_BLENDMODE_BLEND:
             DRAW_SETPIXELXY4_BLEND_RGBA(x, y);
             break;
+        case SDL_BLENDMODE_BLEND_PREMULTIPLIED:
+            DRAW_SETPIXELXY4_BLEND_CLAMPED_RGBA(x, y);
+            break;
         case SDL_BLENDMODE_ADD:
+        case SDL_BLENDMODE_ADD_PREMULTIPLIED:
             DRAW_SETPIXELXY4_ADD_RGBA(x, y);
             break;
         case SDL_BLENDMODE_MOD:

+ 64 - 0
src/render/software/SDL_draw.h

@@ -60,6 +60,25 @@
         setpixel;                               \
     } while (0)
 
+#define DRAW_SETPIXEL_BLEND_CLAMPED(getpixel, setpixel) \
+    do {                                                \
+        unsigned sr, sg, sb, sa = 0xFF;                 \
+        getpixel;                                       \
+        sr = DRAW_MUL(inva, sr) + r;                    \
+        if (sr > 0xff)                                  \
+            sr = 0xff;                                  \
+        sg = DRAW_MUL(inva, sg) + g;                    \
+        if (sg > 0xff)                                  \
+            sg = 0xff;                                  \
+        sb = DRAW_MUL(inva, sb) + b;                    \
+        if (sb > 0xff)                                  \
+            sb = 0xff;                                  \
+        sa = DRAW_MUL(inva, sa) + a;                    \
+        if (sa > 0xff)                                  \
+            sa = 0xff;                                  \
+        setpixel;                                       \
+    } while (0)
+
 #define DRAW_SETPIXEL_ADD(getpixel, setpixel) \
     do {                                      \
         unsigned sr, sg, sb, sa;              \
@@ -122,6 +141,10 @@
     DRAW_SETPIXEL_BLEND(RGB_FROM_RGB555(*pixel, sr, sg, sb), \
                         RGB555_FROM_RGB(*pixel, sr, sg, sb))
 
+#define DRAW_SETPIXEL_BLEND_CLAMPED_RGB555                           \
+    DRAW_SETPIXEL_BLEND_CLAMPED(RGB_FROM_RGB555(*pixel, sr, sg, sb), \
+                                RGB555_FROM_RGB(*pixel, sr, sg, sb))
+
 #define DRAW_SETPIXEL_ADD_RGB555                           \
     DRAW_SETPIXEL_ADD(RGB_FROM_RGB555(*pixel, sr, sg, sb), \
                       RGB555_FROM_RGB(*pixel, sr, sg, sb))
@@ -140,6 +163,9 @@
 #define DRAW_SETPIXELXY_BLEND_RGB555(x, y) \
     DRAW_SETPIXELXY(x, y, Uint16, 2, DRAW_SETPIXEL_BLEND_RGB555)
 
+#define DRAW_SETPIXELXY_BLEND_CLAMPED_RGB555(x, y) \
+    DRAW_SETPIXELXY(x, y, Uint16, 2, DRAW_SETPIXEL_BLEND_CLAMPED_RGB555)
+
 #define DRAW_SETPIXELXY_ADD_RGB555(x, y) \
     DRAW_SETPIXELXY(x, y, Uint16, 2, DRAW_SETPIXEL_ADD_RGB555)
 
@@ -160,6 +186,10 @@
     DRAW_SETPIXEL_BLEND(RGB_FROM_RGB565(*pixel, sr, sg, sb), \
                         RGB565_FROM_RGB(*pixel, sr, sg, sb))
 
+#define DRAW_SETPIXEL_BLEND_CLAMPED_RGB565                           \
+    DRAW_SETPIXEL_BLEND_CLAMPED(RGB_FROM_RGB565(*pixel, sr, sg, sb), \
+                                RGB565_FROM_RGB(*pixel, sr, sg, sb))
+
 #define DRAW_SETPIXEL_ADD_RGB565                           \
     DRAW_SETPIXEL_ADD(RGB_FROM_RGB565(*pixel, sr, sg, sb), \
                       RGB565_FROM_RGB(*pixel, sr, sg, sb))
@@ -178,6 +208,9 @@
 #define DRAW_SETPIXELXY_BLEND_RGB565(x, y) \
     DRAW_SETPIXELXY(x, y, Uint16, 2, DRAW_SETPIXEL_BLEND_RGB565)
 
+#define DRAW_SETPIXELXY_BLEND_CLAMPED_RGB565(x, y) \
+    DRAW_SETPIXELXY(x, y, Uint16, 2, DRAW_SETPIXEL_BLEND_CLAMPED_RGB565)
+
 #define DRAW_SETPIXELXY_ADD_RGB565(x, y) \
     DRAW_SETPIXELXY(x, y, Uint16, 2, DRAW_SETPIXEL_ADD_RGB565)
 
@@ -198,6 +231,10 @@
     DRAW_SETPIXEL_BLEND(RGB_FROM_XRGB8888(*pixel, sr, sg, sb), \
                         XRGB8888_FROM_RGB(*pixel, sr, sg, sb))
 
+#define DRAW_SETPIXEL_BLEND_CLAMPED_XRGB8888                           \
+    DRAW_SETPIXEL_BLEND_CLAMPED(RGB_FROM_XRGB8888(*pixel, sr, sg, sb), \
+                                XRGB8888_FROM_RGB(*pixel, sr, sg, sb))
+
 #define DRAW_SETPIXEL_ADD_XRGB8888                           \
     DRAW_SETPIXEL_ADD(RGB_FROM_XRGB8888(*pixel, sr, sg, sb), \
                       XRGB8888_FROM_RGB(*pixel, sr, sg, sb))
@@ -216,6 +253,9 @@
 #define DRAW_SETPIXELXY_BLEND_XRGB8888(x, y) \
     DRAW_SETPIXELXY(x, y, Uint32, 4, DRAW_SETPIXEL_BLEND_XRGB8888)
 
+#define DRAW_SETPIXELXY_BLEND_CLAMPED_XRGB8888(x, y) \
+    DRAW_SETPIXELXY(x, y, Uint32, 4, DRAW_SETPIXEL_BLEND_CLAMPED_XRGB8888)
+
 #define DRAW_SETPIXELXY_ADD_XRGB8888(x, y) \
     DRAW_SETPIXELXY(x, y, Uint32, 4, DRAW_SETPIXEL_ADD_XRGB8888)
 
@@ -236,6 +276,10 @@
     DRAW_SETPIXEL_BLEND(RGBA_FROM_ARGB8888(*pixel, sr, sg, sb, sa), \
                         ARGB8888_FROM_RGBA(*pixel, sr, sg, sb, sa))
 
+#define DRAW_SETPIXEL_BLEND_CLAMPED_ARGB8888                                \
+    DRAW_SETPIXEL_BLEND_CLAMPED(RGBA_FROM_ARGB8888(*pixel, sr, sg, sb, sa), \
+                                ARGB8888_FROM_RGBA(*pixel, sr, sg, sb, sa))
+
 #define DRAW_SETPIXEL_ADD_ARGB8888                                \
     DRAW_SETPIXEL_ADD(RGBA_FROM_ARGB8888(*pixel, sr, sg, sb, sa), \
                       ARGB8888_FROM_RGBA(*pixel, sr, sg, sb, sa))
@@ -254,6 +298,9 @@
 #define DRAW_SETPIXELXY_BLEND_ARGB8888(x, y) \
     DRAW_SETPIXELXY(x, y, Uint32, 4, DRAW_SETPIXEL_BLEND_ARGB8888)
 
+#define DRAW_SETPIXELXY_BLEND_CLAMPED_ARGB8888(x, y) \
+    DRAW_SETPIXELXY(x, y, Uint32, 4, DRAW_SETPIXEL_BLEND_CLAMPED_ARGB8888)
+
 #define DRAW_SETPIXELXY_ADD_ARGB8888(x, y) \
     DRAW_SETPIXELXY(x, y, Uint32, 4, DRAW_SETPIXEL_ADD_ARGB8888)
 
@@ -274,6 +321,10 @@
     DRAW_SETPIXEL_BLEND(RGB_FROM_PIXEL(*pixel, fmt, sr, sg, sb), \
                         PIXEL_FROM_RGB(*pixel, fmt, sr, sg, sb))
 
+#define DRAW_SETPIXEL_BLEND_CLAMPED_RGB                                  \
+    DRAW_SETPIXEL_BLEND_CLAMPED(RGB_FROM_PIXEL(*pixel, fmt, sr, sg, sb), \
+                                PIXEL_FROM_RGB(*pixel, fmt, sr, sg, sb))
+
 #define DRAW_SETPIXEL_ADD_RGB                                  \
     DRAW_SETPIXEL_ADD(RGB_FROM_PIXEL(*pixel, fmt, sr, sg, sb), \
                       PIXEL_FROM_RGB(*pixel, fmt, sr, sg, sb))
@@ -295,9 +346,15 @@
 #define DRAW_SETPIXELXY2_BLEND_RGB(x, y) \
     DRAW_SETPIXELXY(x, y, Uint16, 2, DRAW_SETPIXEL_BLEND_RGB)
 
+#define DRAW_SETPIXELXY2_BLEND_CLAMPED_RGB(x, y) \
+    DRAW_SETPIXELXY(x, y, Uint16, 2, DRAW_SETPIXEL_BLEND_CLAMPED_RGB)
+
 #define DRAW_SETPIXELXY4_BLEND_RGB(x, y) \
     DRAW_SETPIXELXY(x, y, Uint32, 4, DRAW_SETPIXEL_BLEND_RGB)
 
+#define DRAW_SETPIXELXY4_BLEND_CLAMPED_RGB(x, y) \
+    DRAW_SETPIXELXY(x, y, Uint32, 4, DRAW_SETPIXEL_BLEND_CLAMPED_RGB)
+
 #define DRAW_SETPIXELXY2_ADD_RGB(x, y) \
     DRAW_SETPIXELXY(x, y, Uint16, 2, DRAW_SETPIXEL_ADD_RGB)
 
@@ -327,6 +384,10 @@
     DRAW_SETPIXEL_BLEND(RGBA_FROM_PIXEL(*pixel, fmt, sr, sg, sb, sa), \
                         PIXEL_FROM_RGBA(*pixel, fmt, sr, sg, sb, sa))
 
+#define DRAW_SETPIXEL_BLEND_CLAMPED_RGBA                                      \
+    DRAW_SETPIXEL_BLEND_CLAMPED(RGBA_FROM_PIXEL(*pixel, fmt, sr, sg, sb, sa), \
+                                PIXEL_FROM_RGBA(*pixel, fmt, sr, sg, sb, sa))
+
 #define DRAW_SETPIXEL_ADD_RGBA                                      \
     DRAW_SETPIXEL_ADD(RGBA_FROM_PIXEL(*pixel, fmt, sr, sg, sb, sa), \
                       PIXEL_FROM_RGBA(*pixel, fmt, sr, sg, sb, sa))
@@ -345,6 +406,9 @@
 #define DRAW_SETPIXELXY4_BLEND_RGBA(x, y) \
     DRAW_SETPIXELXY(x, y, Uint32, 4, DRAW_SETPIXEL_BLEND_RGBA)
 
+#define DRAW_SETPIXELXY4_BLEND_CLAMPED_RGBA(x, y) \
+    DRAW_SETPIXELXY(x, y, Uint32, 4, DRAW_SETPIXEL_BLEND_CLAMPED_RGBA)
+
 #define DRAW_SETPIXELXY4_ADD_RGBA(x, y) \
     DRAW_SETPIXELXY(x, y, Uint32, 4, DRAW_SETPIXEL_ADD_RGBA)
 

+ 1 - 1
src/video/SDL_RLEaccel.c

@@ -1400,7 +1400,7 @@ int SDL_RLESurface(SDL_Surface *surface)
     /* Pass on combinations not supported */
     if ((flags & SDL_COPY_MODULATE_COLOR) ||
         ((flags & SDL_COPY_MODULATE_ALPHA) && SDL_ISPIXELFORMAT_ALPHA(surface->format)) ||
-        (flags & (SDL_COPY_ADD | SDL_COPY_MOD | SDL_COPY_MUL)) ||
+        (flags & (SDL_COPY_BLEND_PREMULTIPLIED | SDL_COPY_ADD | SDL_COPY_ADD_PREMULTIPLIED | SDL_COPY_MOD | SDL_COPY_MUL)) ||
         (flags & SDL_COPY_NEAREST)) {
         return -1;
     }

+ 1 - 1
src/video/SDL_blit.c

@@ -125,7 +125,7 @@ static SDL_bool SDL_UseAltivecPrefetch(void)
 static SDL_BlitFunc SDL_ChooseBlitFunc(SDL_PixelFormat src_format, SDL_PixelFormat dst_format, int flags,
                                        SDL_BlitFuncEntry *entries)
 {
-    int i, flagcheck = (flags & (SDL_COPY_MODULATE_COLOR | SDL_COPY_MODULATE_ALPHA | SDL_COPY_BLEND | SDL_COPY_ADD | SDL_COPY_MOD | SDL_COPY_MUL | SDL_COPY_COLORKEY | SDL_COPY_NEAREST));
+    int i, flagcheck = (flags & (SDL_COPY_MODULATE_COLOR | SDL_COPY_MODULATE_ALPHA | SDL_COPY_BLEND | SDL_COPY_BLEND_PREMULTIPLIED | SDL_COPY_ADD | SDL_COPY_ADD_PREMULTIPLIED | SDL_COPY_MOD | SDL_COPY_MUL | SDL_COPY_COLORKEY | SDL_COPY_NEAREST));
     static unsigned int features = 0x7fffffff;
 
     /* Get the available CPU features */

+ 14 - 12
src/video/SDL_blit.h

@@ -28,18 +28,20 @@ extern const Uint8 *SDL_expand_byte[9];
 extern const Uint16 SDL_expand_byte_10[];
 
 /* SDL blit copy flags */
-#define SDL_COPY_MODULATE_COLOR 0x00000001
-#define SDL_COPY_MODULATE_ALPHA 0x00000002
-#define SDL_COPY_BLEND          0x00000010
-#define SDL_COPY_ADD            0x00000020
-#define SDL_COPY_MOD            0x00000040
-#define SDL_COPY_MUL            0x00000080
-#define SDL_COPY_COLORKEY       0x00000100
-#define SDL_COPY_NEAREST        0x00000200
-#define SDL_COPY_RLE_DESIRED    0x00001000
-#define SDL_COPY_RLE_COLORKEY   0x00002000
-#define SDL_COPY_RLE_ALPHAKEY   0x00004000
-#define SDL_COPY_RLE_MASK       (SDL_COPY_RLE_DESIRED | SDL_COPY_RLE_COLORKEY | SDL_COPY_RLE_ALPHAKEY)
+#define SDL_COPY_MODULATE_COLOR         0x00000001
+#define SDL_COPY_MODULATE_ALPHA         0x00000002
+#define SDL_COPY_BLEND                  0x00000010
+#define SDL_COPY_BLEND_PREMULTIPLIED    0x00000020
+#define SDL_COPY_ADD                    0x00000040
+#define SDL_COPY_ADD_PREMULTIPLIED      0x00000080
+#define SDL_COPY_MOD                    0x00000100
+#define SDL_COPY_MUL                    0x00000200
+#define SDL_COPY_COLORKEY               0x00000400
+#define SDL_COPY_NEAREST                0x00000800
+#define SDL_COPY_RLE_DESIRED            0x00001000
+#define SDL_COPY_RLE_COLORKEY           0x00002000
+#define SDL_COPY_RLE_ALPHAKEY           0x00004000
+#define SDL_COPY_RLE_MASK               (SDL_COPY_RLE_DESIRED | SDL_COPY_RLE_COLORKEY | SDL_COPY_RLE_ALPHAKEY)
 
 /* SDL blit CPU flags */
 #define SDL_CPU_ANY                0x00000000

File diff suppressed because it is too large
+ 338 - 132
src/video/SDL_blit_auto.c


+ 21 - 4
src/video/SDL_blit_slow.c

@@ -134,7 +134,7 @@ void SDL_Blit_Slow(SDL_BlitInfo *info)
                     continue;
                 }
             }
-            if ((flags & (SDL_COPY_BLEND | SDL_COPY_ADD | SDL_COPY_MOD | SDL_COPY_MUL))) {
+            if ((flags & (SDL_COPY_BLEND | SDL_COPY_BLEND_PREMULTIPLIED | SDL_COPY_ADD | SDL_COPY_ADD_PREMULTIPLIED | SDL_COPY_MOD | SDL_COPY_MUL))) {
                 switch (dst_access) {
                 case SlowBlitPixelAccess_RGB:
                     DISEMBLE_RGB(dst, dstbpp, dst_fmt, dstpixel, dstR, dstG, dstB);
@@ -181,14 +181,13 @@ void SDL_Blit_Slow(SDL_BlitInfo *info)
                 srcA = (srcA * modulateA) / 255;
             }
             if (flags & (SDL_COPY_BLEND | SDL_COPY_ADD)) {
-                /* This goes away if we ever use premultiplied alpha */
                 if (srcA < 255) {
                     srcR = (srcR * srcA) / 255;
                     srcG = (srcG * srcA) / 255;
                     srcB = (srcB * srcA) / 255;
                 }
             }
-            switch (flags & (SDL_COPY_BLEND | SDL_COPY_ADD | SDL_COPY_MOD | SDL_COPY_MUL)) {
+            switch (flags & (SDL_COPY_BLEND | SDL_COPY_BLEND_PREMULTIPLIED | SDL_COPY_ADD | SDL_COPY_ADD_PREMULTIPLIED | SDL_COPY_MOD | SDL_COPY_MUL)) {
             case 0:
                 dstR = srcR;
                 dstG = srcG;
@@ -201,7 +200,26 @@ void SDL_Blit_Slow(SDL_BlitInfo *info)
                 dstB = srcB + ((255 - srcA) * dstB) / 255;
                 dstA = srcA + ((255 - srcA) * dstA) / 255;
                 break;
+            case SDL_COPY_BLEND_PREMULTIPLIED:
+                dstR = srcR + ((255 - srcA) * dstR) / 255;
+                if (dstR > 255) {
+                    dstR = 255;
+                }
+                dstG = srcG + ((255 - srcA) * dstG) / 255;
+                if (dstG > 255) {
+                    dstG = 255;
+                }
+                dstB = srcB + ((255 - srcA) * dstB) / 255;
+                if (dstB > 255) {
+                    dstB = 255;
+                }
+                dstA = srcA + ((255 - srcA) * dstA) / 255;
+                if (dstA > 255) {
+                    dstA = 255;
+                }
+                break;
             case SDL_COPY_ADD:
+            case SDL_COPY_ADD_PREMULTIPLIED:
                 dstR = srcR + dstR;
                 if (dstR > 255) {
                     dstR = 255;
@@ -869,7 +887,6 @@ void SDL_Blit_Slow_Float(SDL_BlitInfo *info)
                 srcA = (srcA * modulateA) / 255;
             }
             if (flags & (SDL_COPY_BLEND | SDL_COPY_ADD)) {
-                /* This goes away if we ever use premultiplied alpha */
                 if (srcA < 1.0f) {
                     srcR = (srcR * srcA);
                     srcG = (srcG * srcA);

+ 15 - 3
src/video/SDL_surface.c

@@ -708,16 +708,22 @@ int SDL_SetSurfaceBlendMode(SDL_Surface *surface, SDL_BlendMode blendMode)
 
     status = 0;
     flags = surface->internal->map.info.flags;
-    surface->internal->map.info.flags &= ~(SDL_COPY_BLEND | SDL_COPY_ADD | SDL_COPY_MOD | SDL_COPY_MUL);
+    surface->internal->map.info.flags &= ~(SDL_COPY_BLEND | SDL_COPY_BLEND_PREMULTIPLIED | SDL_COPY_ADD | SDL_COPY_ADD_PREMULTIPLIED | SDL_COPY_MOD | SDL_COPY_MUL);
     switch (blendMode) {
     case SDL_BLENDMODE_NONE:
         break;
     case SDL_BLENDMODE_BLEND:
         surface->internal->map.info.flags |= SDL_COPY_BLEND;
         break;
+    case SDL_BLENDMODE_BLEND_PREMULTIPLIED:
+        surface->internal->map.info.flags |= SDL_COPY_BLEND_PREMULTIPLIED;
+        break;
     case SDL_BLENDMODE_ADD:
         surface->internal->map.info.flags |= SDL_COPY_ADD;
         break;
+    case SDL_BLENDMODE_ADD_PREMULTIPLIED:
+        surface->internal->map.info.flags |= SDL_COPY_ADD_PREMULTIPLIED;
+        break;
     case SDL_BLENDMODE_MOD:
         surface->internal->map.info.flags |= SDL_COPY_MOD;
         break;
@@ -746,13 +752,19 @@ int SDL_GetSurfaceBlendMode(SDL_Surface *surface, SDL_BlendMode *blendMode)
         return 0;
     }
 
-    switch (surface->internal->map.info.flags & (SDL_COPY_BLEND | SDL_COPY_ADD | SDL_COPY_MOD | SDL_COPY_MUL)) {
+    switch (surface->internal->map.info.flags & (SDL_COPY_BLEND | SDL_COPY_BLEND_PREMULTIPLIED | SDL_COPY_ADD | SDL_COPY_ADD_PREMULTIPLIED | SDL_COPY_MOD | SDL_COPY_MUL)) {
     case SDL_COPY_BLEND:
         *blendMode = SDL_BLENDMODE_BLEND;
         break;
+    case SDL_COPY_BLEND_PREMULTIPLIED:
+        *blendMode = SDL_BLENDMODE_BLEND_PREMULTIPLIED;
+        break;
     case SDL_COPY_ADD:
         *blendMode = SDL_BLENDMODE_ADD;
         break;
+    case SDL_COPY_ADD_PREMULTIPLIED:
+        *blendMode = SDL_BLENDMODE_ADD_PREMULTIPLIED;
+        break;
     case SDL_COPY_MOD:
         *blendMode = SDL_BLENDMODE_MOD;
         break;
@@ -1088,7 +1100,7 @@ int SDL_BlitSurfaceUncheckedScaled(SDL_Surface *src, const SDL_Rect *srcrect,
                                    SDL_ScaleMode scaleMode)
 {
     static const Uint32 complex_copy_flags = (SDL_COPY_MODULATE_COLOR | SDL_COPY_MODULATE_ALPHA |
-                                              SDL_COPY_BLEND | SDL_COPY_ADD | SDL_COPY_MOD | SDL_COPY_MUL |
+                                              SDL_COPY_BLEND | SDL_COPY_BLEND_PREMULTIPLIED | SDL_COPY_ADD | SDL_COPY_ADD_PREMULTIPLIED | SDL_COPY_MOD | SDL_COPY_MUL |
                                               SDL_COPY_COLORKEY);
 
     if (scaleMode != SDL_SCALEMODE_NEAREST && scaleMode != SDL_SCALEMODE_LINEAR && scaleMode != SDL_SCALEMODE_BEST) {

+ 54 - 12
src/video/sdlgenblit.pl

@@ -38,6 +38,7 @@ my @dst_formats = (
     "XRGB8888",
     "XBGR8888",
     "ARGB8888",
+    "ABGR8888",
 );
 
 my %format_size = (
@@ -327,7 +328,6 @@ __EOF__
         if (!$A_is_const_FF) {
             print FILE <<__EOF__;
             if (flags & (SDL_COPY_BLEND|SDL_COPY_ADD)) {
-                /* This goes away if we ever use premultiplied alpha */
                 if (${s}A < 255) {
                     MULT_DIV_255(${s}R, ${s}A, ${s}R);
                     MULT_DIV_255(${s}G, ${s}A, ${s}G);
@@ -337,7 +337,7 @@ __EOF__
 __EOF__
         }
         print FILE <<__EOF__;
-            switch (flags & (SDL_COPY_BLEND|SDL_COPY_ADD|SDL_COPY_MOD|SDL_COPY_MUL)) {
+            switch (flags & (SDL_COPY_BLEND | SDL_COPY_BLEND_PREMULTIPLIED | SDL_COPY_ADD | SDL_COPY_ADD_PREMULTIPLIED | SDL_COPY_MOD | SDL_COPY_MUL)) {
             case SDL_COPY_BLEND:
 __EOF__
         if ($A_is_const_FF) {
@@ -369,9 +369,47 @@ __EOF__
             }
         }
 
+        print FILE <<__EOF__;
+                break;
+            case SDL_COPY_BLEND_PREMULTIPLIED:
+__EOF__
+        if ($A_is_const_FF) {
+            print FILE <<__EOF__;
+                ${d}R = ${s}R;
+                ${d}G = ${s}G;
+                ${d}B = ${s}B;
+__EOF__
+        } else {
+            print FILE <<__EOF__;
+                MULT_DIV_255((255 - ${s}A), ${d}R, ${d}R);
+                ${d}R += ${s}R;
+                if (${d}R > 255) ${d}R = 255;
+                MULT_DIV_255((255 - ${s}A), ${d}G, ${d}G);
+                ${d}G += ${s}G;
+                if (${d}G > 255) ${d}G = 255;
+                MULT_DIV_255((255 - ${s}A), ${d}B, ${d}B);
+                ${d}B += ${s}B;
+                if (${d}B > 255) ${d}B = 255;
+__EOF__
+        }
+        if ( $dst_has_alpha ) {
+            if ($A_is_const_FF) {
+                print FILE <<__EOF__;
+                ${d}A = 0xFF;
+__EOF__
+            } else {
+                print FILE <<__EOF__;
+                MULT_DIV_255((255 - ${s}A), ${d}A, ${d}A);
+                ${d}A += ${s}A;
+                if (${d}A > 255) ${d}A = 255;
+__EOF__
+            }
+        }
+
         print FILE <<__EOF__;
                 break;
             case SDL_COPY_ADD:
+            case SDL_COPY_ADD_PREMULTIPLIED:
                 ${d}R = ${s}R + ${d}R; if (${d}R > 255) ${d}R = 255;
                 ${d}G = ${s}G + ${d}G; if (${d}G > 255) ${d}G = 255;
                 ${d}B = ${s}B + ${d}B; if (${d}B > 255) ${d}B = 255;
@@ -391,15 +429,19 @@ __EOF__
 __EOF__
         } else {
             print FILE <<__EOF__;
-                MULT_DIV_255(${d}R, (255 - ${s}A), ${d}R);
-                ${d}R += (${s}R * ${d}R);
-                if (${d}R > 255) ${d}R = 255;
-                MULT_DIV_255(${d}B, (255 - ${s}A), ${d}B);
-                ${d}B += (${s}B * ${d}B);
-                if (${d}B > 255) ${d}B = 255;
-                MULT_DIV_255(${d}G, (255 - ${s}A), ${d}G);
-                ${d}G += (${s}G * ${d}G);
-                if (${d}G > 255) ${d}G = 255;
+                {
+                    Uint32 tmp1, tmp2;
+
+                    MULT_DIV_255(${s}R, ${d}R, tmp1);
+                    MULT_DIV_255(${d}R, (255 - ${s}A), tmp2);
+                    ${d}R = tmp1 + tmp2; if (${d}R > 255) ${d}R = 255;
+                    MULT_DIV_255(${s}G, ${d}G, tmp1);
+                    MULT_DIV_255(${d}G, (255 - ${s}A), tmp2);
+                    ${d}G = tmp1 + tmp2; if (${d}G > 255) ${d}G = 255;
+                    MULT_DIV_255(${s}B, ${d}B, tmp1);
+                    MULT_DIV_255(${d}B, (255 - ${s}A), tmp2);
+                    ${d}B = tmp1 + tmp2; if (${d}B > 255) ${d}B = 255;
+                }
 __EOF__
         }
 
@@ -624,7 +666,7 @@ __EOF__
                                 }
                             }
                             if ( $blend ) {
-                                $flag = "SDL_COPY_BLEND | SDL_COPY_ADD | SDL_COPY_MOD | SDL_COPY_MUL";
+                                $flag = "SDL_COPY_BLEND | SDL_COPY_BLEND_PREMULTIPLIED | SDL_COPY_ADD | SDL_COPY_ADD_PREMULTIPLIED | SDL_COPY_MOD | SDL_COPY_MUL";
                                 if ( $flags eq "" ) {
                                     $flags = $flag;
                                 } else {

File diff suppressed because it is too large
+ 1704 - 719
test/testautomation_images.c


+ 3 - 1
test/testautomation_images.h

@@ -26,8 +26,10 @@ typedef struct SDLTest_SurfaceImage_s {
 SDL_Surface *SDLTest_ImageBlit(void);
 SDL_Surface *SDLTest_ImageBlitColor(void);
 SDL_Surface *SDLTest_ImageBlitAlpha(void);
-SDL_Surface *SDLTest_ImageBlitBlendAdd(void);
 SDL_Surface *SDLTest_ImageBlitBlend(void);
+SDL_Surface *SDLTest_ImageBlitBlendPremultiplied(void);
+SDL_Surface *SDLTest_ImageBlitBlendAdd(void);
+SDL_Surface *SDLTest_ImageBlitBlendAddPremultiplied(void);
 SDL_Surface *SDLTest_ImageBlitBlendMod(void);
 SDL_Surface *SDLTest_ImageBlitBlendNone(void);
 SDL_Surface *SDLTest_ImageBlitBlendAll(void);

+ 43 - 0
test/testautomation_render.c

@@ -702,6 +702,17 @@ static int render_testBlitBlend(void *arg)
     SDL_DestroySurface(referenceSurface);
     referenceSurface = NULL;
 
+    /* Test Blend Premultiplied. */
+    testBlitBlendMode(tface, SDL_BLENDMODE_BLEND_PREMULTIPLIED);
+    referenceSurface = SDLTest_ImageBlitBlendPremultiplied();
+
+    /* Compare, then Present */
+    compare(referenceSurface, ALLOWABLE_ERROR_BLENDED);
+    SDL_RenderPresent(renderer);
+
+    SDL_DestroySurface(referenceSurface);
+    referenceSurface = NULL;
+
     /* Test Add. */
     testBlitBlendMode(tface, SDL_BLENDMODE_ADD);
     referenceSurface = SDLTest_ImageBlitBlendAdd();
@@ -713,6 +724,17 @@ static int render_testBlitBlend(void *arg)
     SDL_DestroySurface(referenceSurface);
     referenceSurface = NULL;
 
+    /* Test Add Premultiplied. */
+    testBlitBlendMode(tface, SDL_BLENDMODE_ADD_PREMULTIPLIED);
+    referenceSurface = SDLTest_ImageBlitBlendAddPremultiplied();
+
+    /* Compare, then Present */
+    compare(referenceSurface, ALLOWABLE_ERROR_BLENDED);
+    SDL_RenderPresent(renderer);
+
+    SDL_DestroySurface(referenceSurface);
+    referenceSurface = NULL;
+
     /* Test Mod. */
     testBlitBlendMode(tface, SDL_BLENDMODE_MOD);
     referenceSurface = SDLTest_ImageBlitBlendMod();
@@ -1154,6 +1176,15 @@ hasBlendModes(void)
     if (!isSupported(ret)) {
         fail = 1;
     }
+   ret = SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND_PREMULTIPLIED );
+   if (!isSupported(ret))
+      fail = 1;
+   ret = SDL_GetRenderDrawBlendMode(renderer, &mode );
+   if (!isSupported(ret))
+      fail = 1;
+   ret = (mode != SDL_BLENDMODE_BLEND_PREMULTIPLIED);
+   if (!isSupported(ret))
+      fail = 1;
     ret = SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_ADD);
     if (!isSupported(ret)) {
         fail = 1;
@@ -1166,6 +1197,18 @@ hasBlendModes(void)
     if (!isSupported(ret)) {
         fail = 1;
     }
+    ret = SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_ADD_PREMULTIPLIED);
+    if (!isSupported(ret)) {
+        fail = 1;
+    }
+    ret = SDL_GetRenderDrawBlendMode(renderer, &mode);
+    if (!isSupported(ret)) {
+        fail = 1;
+    }
+    ret = (mode != SDL_BLENDMODE_ADD_PREMULTIPLIED);
+    if (!isSupported(ret)) {
+        fail = 1;
+    }
     ret = SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_MOD);
     if (!isSupported(ret)) {
         fail = 1;

+ 57 - 3
test/testautomation_surface.c

@@ -523,6 +523,28 @@ static int surface_testBlitBlendBlend(void *arg)
     return TEST_COMPLETED;
 }
 
+/**
+ * @brief Tests some more blitting routines.
+ */
+static int surface_testBlitBlendPremultiplied(void *arg)
+{
+   int ret;
+   SDL_Surface *compareSurface;
+
+   /* Blend premultiplied blitting */
+   testBlitBlendMode(SDL_BLENDMODE_BLEND_PREMULTIPLIED);
+
+   /* Verify result by comparing surfaces */
+   compareSurface = SDLTest_ImageBlitBlendPremultiplied();
+   ret = SDLTest_CompareSurfaces( testSurface, compareSurface, 0 );
+   SDLTest_AssertCheck(ret == 0, "Validate result from SDLTest_CompareSurfaces, expected: 0, got: %i", ret);
+
+   /* Clean up. */
+   SDL_DestroySurface(compareSurface);
+
+   return TEST_COMPLETED;
+}
+
 /**
  * Tests some more blitting routines.
  */
@@ -545,6 +567,28 @@ static int surface_testBlitBlendAdd(void *arg)
     return TEST_COMPLETED;
 }
 
+/**
+ * Tests some more blitting routines.
+ */
+static int surface_testBlitBlendAddPremultiplied(void *arg)
+{
+    int ret;
+    SDL_Surface *compareSurface;
+
+    /* Add blitting */
+    testBlitBlendMode(SDL_BLENDMODE_ADD_PREMULTIPLIED);
+
+    /* Verify result by comparing surfaces */
+    compareSurface = SDLTest_ImageBlitBlendAddPremultiplied();
+    ret = SDLTest_CompareSurfaces(testSurface, compareSurface, 0);
+    SDLTest_AssertCheck(ret == 0, "Validate result from SDLTest_CompareSurfaces, expected: 0, got: %i", ret);
+
+    /* Clean up. */
+    SDL_DestroySurface(compareSurface);
+
+    return TEST_COMPLETED;
+}
+
 /**
  * Tests some more blitting routines.
  */
@@ -958,10 +1002,20 @@ static const SDLTest_TestCaseReference surfaceTest10 = {
 
 /* TODO: rewrite test case, define new test data and re-enable; current implementation fails */
 static const SDLTest_TestCaseReference surfaceTest11 = {
-    (SDLTest_TestCaseFp)surface_testBlitBlendAdd, "surface_testBlitBlendAdd", "Tests blitting routines with add blending mode.", TEST_DISABLED
+    (SDLTest_TestCaseFp)surface_testBlitBlendPremultiplied, "surface_testBlitBlendPremultiplied", "Tests blitting routines with premultiplied blending mode.", TEST_DISABLED
 };
 
+/* TODO: rewrite test case, define new test data and re-enable; current implementation fails */
 static const SDLTest_TestCaseReference surfaceTest12 = {
+    (SDLTest_TestCaseFp)surface_testBlitBlendAdd, "surface_testBlitBlendAdd", "Tests blitting routines with add blending mode.", TEST_DISABLED
+};
+
+/* TODO: rewrite test case, define new test data and re-enable; current implementation fails */
+static const SDLTest_TestCaseReference surfaceTest13 = {
+    (SDLTest_TestCaseFp)surface_testBlitBlendAddPremultiplied, "surface_testBlitBlendAddPremultiplied", "Tests blitting routines with premultiplied add blending mode.", TEST_DISABLED
+};
+
+static const SDLTest_TestCaseReference surfaceTest14 = {
     (SDLTest_TestCaseFp)surface_testBlitBlendMod, "surface_testBlitBlendMod", "Tests blitting routines with mod blending mode.", TEST_ENABLED
 };
 
@@ -981,8 +1035,8 @@ static const SDLTest_TestCaseReference surfaceTestPalette = {
 static const SDLTest_TestCaseReference *surfaceTests[] = {
     &surfaceTest1, &surfaceTest2, &surfaceTest3, &surfaceTest4, &surfaceTest5,
     &surfaceTest6, &surfaceTest7, &surfaceTest8, &surfaceTest9, &surfaceTest10,
-    &surfaceTest11, &surfaceTest12, &surfaceTestOverflow, &surfaceTestFlip,
-    &surfaceTestPalette, NULL
+    &surfaceTest11, &surfaceTest12, &surfaceTest13, &surfaceTest14,
+    &surfaceTestOverflow, &surfaceTestFlip, &surfaceTestPalette, NULL
 };
 
 /* Surface test suite (global) */

+ 7 - 1
test/testdraw.c

@@ -243,9 +243,15 @@ int main(int argc, char *argv[])
                     } else if (SDL_strcasecmp(argv[i + 1], "blend") == 0) {
                         blendMode = SDL_BLENDMODE_BLEND;
                         consumed = 2;
+                    } else if (SDL_strcasecmp(argv[i + 1], "blend_premultiplied") == 0) {
+                        blendMode = SDL_BLENDMODE_BLEND_PREMULTIPLIED;
+                        consumed = 2;
                     } else if (SDL_strcasecmp(argv[i + 1], "add") == 0) {
                         blendMode = SDL_BLENDMODE_ADD;
                         consumed = 2;
+                    } else if (SDL_strcasecmp(argv[i + 1], "add_premultiplied") == 0) {
+                        blendMode = SDL_BLENDMODE_ADD_PREMULTIPLIED;
+                        consumed = 2;
                     } else if (SDL_strcasecmp(argv[i + 1], "mod") == 0) {
                         blendMode = SDL_BLENDMODE_MOD;
                         consumed = 2;
@@ -267,7 +273,7 @@ int main(int argc, char *argv[])
         }
         if (consumed < 0) {
             static const char *options[] = {
-                "[--blend none|blend|add|mod|mul]",
+                "[--blend none|blend|blend_premultiplied|add|add_premultiplied|mod|mul]",
                 "[--cyclecolor]",
                 "[--cyclealpha]",
                 "[num_objects]",

+ 7 - 1
test/testintersections.c

@@ -312,9 +312,15 @@ int main(int argc, char *argv[])
                     } else if (SDL_strcasecmp(argv[i + 1], "blend") == 0) {
                         blendMode = SDL_BLENDMODE_BLEND;
                         consumed = 2;
+                    } else if (SDL_strcasecmp(argv[i + 1], "blend_premultiplied") == 0) {
+                        blendMode = SDL_BLENDMODE_BLEND_PREMULTIPLIED;
+                        consumed = 2;
                     } else if (SDL_strcasecmp(argv[i + 1], "add") == 0) {
                         blendMode = SDL_BLENDMODE_ADD;
                         consumed = 2;
+                    } else if (SDL_strcasecmp(argv[i + 1], "add_premultiplied") == 0) {
+                        blendMode = SDL_BLENDMODE_ADD_PREMULTIPLIED;
+                        consumed = 2;
                     } else if (SDL_strcasecmp(argv[i + 1], "mod") == 0) {
                         blendMode = SDL_BLENDMODE_MOD;
                         consumed = 2;
@@ -338,7 +344,7 @@ int main(int argc, char *argv[])
             }
         }
         if (consumed < 0) {
-            static const char *options[] = { "[--blend none|blend|add|mod|mul]", "[--cyclecolor]", "[--cyclealpha]", "[count]", NULL };
+            static const char *options[] = { "[--blend none|blend|blend_premultiplied|add|add_premultiplied|mod|mul]", "[--cyclecolor]", "[--cyclealpha]", "[count]", NULL };
             SDLTest_CommonLogUsage(state, argv[0], options);
             return 1;
         }

+ 7 - 1
test/testsprite.c

@@ -451,9 +451,15 @@ int SDL_AppInit(void **appstate, int argc, char *argv[])
                     } else if (SDL_strcasecmp(argv[i + 1], "blend") == 0) {
                         blendMode = SDL_BLENDMODE_BLEND;
                         consumed = 2;
+                    } else if (SDL_strcasecmp(argv[i + 1], "blend_premultiplied") == 0) {
+                        blendMode = SDL_BLENDMODE_BLEND_PREMULTIPLIED;
+                        consumed = 2;
                     } else if (SDL_strcasecmp(argv[i + 1], "add") == 0) {
                         blendMode = SDL_BLENDMODE_ADD;
                         consumed = 2;
+                    } else if (SDL_strcasecmp(argv[i + 1], "add_premultiplied") == 0) {
+                        blendMode = SDL_BLENDMODE_ADD_PREMULTIPLIED;
+                        consumed = 2;
                     } else if (SDL_strcasecmp(argv[i + 1], "mod") == 0) {
                         blendMode = SDL_BLENDMODE_MOD;
                         consumed = 2;
@@ -506,7 +512,7 @@ int SDL_AppInit(void **appstate, int argc, char *argv[])
         }
         if (consumed < 0) {
             static const char *options[] = {
-                "[--blend none|blend|add|mod|mul|sub]",
+                "[--blend none|blend|blend_premultiplied|add|add_premultiplied|mod|mul|sub]",
                 "[--cyclecolor]",
                 "[--cyclealpha]",
                 "[--suspend-when-occluded]",

Some files were not shown because too many files changed in this diff