[Scummvm-git-logs] scummvm master -> cae08a64c232907849945e0e851f22c628b19c31

sev- noreply at scummvm.org
Thu Dec 22 22:08:58 UTC 2022


This automated email contains information about 1 new commit which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .

Summary:
cae08a64c2 GRAPHICS: Optimize TransparentSurface blitting when using alpha-only modulation


Commit: cae08a64c232907849945e0e851f22c628b19c31
    https://github.com/scummvm/scummvm/commit/cae08a64c232907849945e0e851f22c628b19c31
Author: Cameron Cawley (ccawley2011 at gmail.com)
Date: 2022-12-22T23:08:55+01:00

Commit Message:
GRAPHICS: Optimize TransparentSurface blitting when using alpha-only modulation

Changed paths:
    graphics/transparent_surface.cpp


diff --git a/graphics/transparent_surface.cpp b/graphics/transparent_surface.cpp
index cdb07946483..f94effffa5d 100644
--- a/graphics/transparent_surface.cpp
+++ b/graphics/transparent_surface.cpp
@@ -39,6 +39,12 @@ static const int kGModShift = 16;//img->format.gShift;
 static const int kRModShift = 24;//img->format.rShift;
 static const int kAModShift = 0;//img->format.aShift;
 
+static const uint32 kBModMask = 0x0000ff00;
+static const uint32 kGModMask = 0x00ff0000;
+static const uint32 kRModMask = 0xff000000;
+static const uint32 kAModMask = 0x000000ff;
+static const uint32 kRGBModMask = (kRModMask | kGModMask | kBModMask);
+
 #ifdef SCUMM_LITTLE_ENDIAN
 static const int kAIndex = 0;
 static const int kBIndex = 1;
@@ -52,13 +58,6 @@ static const int kGIndex = 1;
 static const int kRIndex = 0;
 #endif
 
-void doBlitOpaqueFast(byte *ino, byte *outo, uint32 width, uint32 height, uint32 pitch, int32 inStep, int32 inoStep);
-void doBlitBinaryFast(byte *ino, byte *outo, uint32 width, uint32 height, uint32 pitch, int32 inStep, int32 inoStep);
-void doBlitAlphaBlend(byte *ino, byte *outo, uint32 width, uint32 height, uint32 pitch, int32 inStep, int32 inoStep, uint32 color);
-void doBlitAdditiveBlend(byte *ino, byte *outo, uint32 width, uint32 height, uint32 pitch, int32 inStep, int32 inoStep, uint32 color);
-void doBlitSubtractiveBlend(byte *ino, byte *outo, uint32 width, uint32 height, uint32 pitch, int32 inStep, int32 inoStep, uint32 color);
-void doBlitMultiplyBlend(byte *ino, byte *outo, uint32 width, uint32 height, uint32 pitch, int32 inStep, int32 inoStep, uint32 color);
-
 TransparentSurface::TransparentSurface() : Surface(), _alphaMode(ALPHA_FULL) {}
 
 TransparentSurface::TransparentSurface(const Surface &surf, bool copyData) : Surface(), _alphaMode(ALPHA_FULL) {
@@ -79,7 +78,7 @@ TransparentSurface::TransparentSurface(const Surface &surf, bool copyData) : Sur
 /**
  * Optimized version of doBlit to be used w/opaque blitting (no alpha).
  */
-void doBlitOpaqueFast(byte *ino, byte *outo, uint32 width, uint32 height, uint32 pitch, int32 inStep, int32 inoStep) {
+static void doBlitOpaqueFast(byte *ino, byte *outo, uint32 width, uint32 height, uint32 pitch, int32 inStep, int32 inoStep) {
 
 	byte *in;
 	byte *out;
@@ -100,7 +99,7 @@ void doBlitOpaqueFast(byte *ino, byte *outo, uint32 width, uint32 height, uint32
 /**
  * Optimized version of doBlit to be used w/binary blitting (blit or no-blit, no blending).
  */
-void doBlitBinaryFast(byte *ino, byte *outo, uint32 width, uint32 height, uint32 pitch, int32 inStep, int32 inoStep) {
+static void doBlitBinaryFast(byte *ino, byte *outo, uint32 width, uint32 height, uint32 pitch, int32 inStep, int32 inoStep) {
 
 	byte *in;
 	byte *out;
@@ -135,60 +134,59 @@ void doBlitBinaryFast(byte *ino, byte *outo, uint32 width, uint32 height, uint32
  * @inoStep width in bytes of every row on the *input* surface / kind of like pitch
  * @color colormod in 0xAARRGGBB format - 0xFFFFFFFF for no colormod
  */
-void doBlitAlphaBlend(byte *ino, byte *outo, uint32 width, uint32 height, uint32 pitch, int32 inStep, int32 inoStep, uint32 color) {
+template<bool rgbmod, bool alphamod>
+static void doBlitAlphaBlendImpl(byte *ino, byte *outo, uint32 width, uint32 height, uint32 pitch, int32 inStep, int32 inoStep, uint32 color) {
+
 	byte *in;
 	byte *out;
 
-	if (color == 0xffffffff) {
-
-		for (uint32 i = 0; i < height; i++) {
-			out = outo;
-			in = ino;
-			for (uint32 j = 0; j < width; j++) {
+	byte ca = alphamod ? ((color >> kAModShift) & 0xFF) : 255;
+	byte cr = rgbmod   ? ((color >> kRModShift) & 0xFF) : 255;
+	byte cg = rgbmod   ? ((color >> kGModShift) & 0xFF) : 255;
+	byte cb = rgbmod   ? ((color >> kBModShift) & 0xFF) : 255;
 
-				if (in[kAIndex] != 0) {
-					out[kAIndex] = 255;
-					out[kRIndex] = ((in[kRIndex] * in[kAIndex]) + out[kRIndex] * (255 - in[kAIndex])) >> 8;
-					out[kGIndex] = ((in[kGIndex] * in[kAIndex]) + out[kGIndex] * (255 - in[kAIndex])) >> 8;
-					out[kBIndex] = ((in[kBIndex] * in[kAIndex]) + out[kBIndex] * (255 - in[kAIndex])) >> 8;
-				}
+	for (uint32 i = 0; i < height; i++) {
+		out = outo;
+		in = ino;
+		for (uint32 j = 0; j < width; j++) {
 
-				in += inStep;
-				out += 4;
-			}
-			outo += pitch;
-			ino += inoStep;
-		}
-	} else {
+			uint32 ina = in[kAIndex] * ca >> 8;
 
-		byte ca = (color >> kAModShift) & 0xFF;
-		byte cr = (color >> kRModShift) & 0xFF;
-		byte cg = (color >> kGModShift) & 0xFF;
-		byte cb = (color >> kBModShift) & 0xFF;
+			if (ina != 0) {
+				uint outb = (out[kBIndex] * (255 - ina) >> 8);
+				uint outg = (out[kGIndex] * (255 - ina) >> 8);
+				uint outr = (out[kRIndex] * (255 - ina) >> 8);
 
-		for (uint32 i = 0; i < height; i++) {
-			out = outo;
-			in = ino;
-			for (uint32 j = 0; j < width; j++) {
+				out[kAIndex] = 255;
+				out[kBIndex] = outb + (in[kBIndex] * ina * cb >> 16);
+				out[kGIndex] = outg + (in[kGIndex] * ina * cg >> 16);
+				out[kRIndex] = outr + (in[kRIndex] * ina * cr >> 16);
+			}
 
-				uint32 ina = in[kAIndex] * ca >> 8;
+			in += inStep;
+			out += 4;
+		}
+		outo += pitch;
+		ino += inoStep;
+	}
+}
 
-				if (ina != 0) {
-					out[kAIndex] = 255;
-					out[kBIndex] = (out[kBIndex] * (255 - ina) >> 8);
-					out[kGIndex] = (out[kGIndex] * (255 - ina) >> 8);
-					out[kRIndex] = (out[kRIndex] * (255 - ina) >> 8);
+static void doBlitAlphaBlend(byte *ino, byte *outo, uint32 width, uint32 height, uint32 pitch, int32 inStep, int32 inoStep, uint32 color) {
 
-					out[kBIndex] = out[kBIndex] + (in[kBIndex] * ina * cb >> 16);
-					out[kGIndex] = out[kGIndex] + (in[kGIndex] * ina * cg >> 16);
-					out[kRIndex] = out[kRIndex] + (in[kRIndex] * ina * cr >> 16);
-				}
+	bool rgbmod   = ((color & kRGBModMask) != kRGBModMask);
+	bool alphamod = ((color & kAModMask)   != kAModMask);
 
-				in += inStep;
-				out += 4;
-			}
-			outo += pitch;
-			ino += inoStep;
+	if (rgbmod) {
+		if (alphamod) {
+			doBlitAlphaBlendImpl<true, true>(ino, outo, width, height, pitch, inStep, inoStep, color);
+		} else {
+			doBlitAlphaBlendImpl<true, false>(ino, outo, width, height, pitch, inStep, inoStep, color);
+		}
+	} else {
+		if (alphamod) {
+			doBlitAlphaBlendImpl<false, true>(ino, outo, width, height, pitch, inStep, inoStep, color);
+		} else {
+			doBlitAlphaBlendImpl<false, false>(ino, outo, width, height, pitch, inStep, inoStep, color);
 		}
 	}
 }
@@ -196,43 +194,25 @@ void doBlitAlphaBlend(byte *ino, byte *outo, uint32 width, uint32 height, uint32
 /**
  * Optimized version of doBlit to be used with additive blended blitting
  */
-void doBlitAdditiveBlend(byte *ino, byte *outo, uint32 width, uint32 height, uint32 pitch, int32 inStep, int32 inoStep, uint32 color) {
+template<bool rgbmod, bool alphamod>
+static void doBlitAdditiveBlendImpl(byte *ino, byte *outo, uint32 width, uint32 height, uint32 pitch, int32 inStep, int32 inoStep, uint32 color) {
+
 	byte *in;
 	byte *out;
 
-	if (color == 0xffffffff) {
-
-		for (uint32 i = 0; i < height; i++) {
-			out = outo;
-			in = ino;
-			for (uint32 j = 0; j < width; j++) {
+	byte ca = alphamod ? ((color >> kAModShift) & 0xFF) : 255;
+	byte cr = rgbmod   ? ((color >> kRModShift) & 0xFF) : 255;
+	byte cg = rgbmod   ? ((color >> kGModShift) & 0xFF) : 255;
+	byte cb = rgbmod   ? ((color >> kBModShift) & 0xFF) : 255;
 
-				if (in[kAIndex] != 0) {
-					out[kRIndex] = MIN((in[kRIndex] * in[kAIndex] >> 8) + out[kRIndex], 255);
-					out[kGIndex] = MIN((in[kGIndex] * in[kAIndex] >> 8) + out[kGIndex], 255);
-					out[kBIndex] = MIN((in[kBIndex] * in[kAIndex] >> 8) + out[kBIndex], 255);
-				}
-
-				in += inStep;
-				out += 4;
-			}
-			outo += pitch;
-			ino += inoStep;
-		}
-	} else {
-
-		byte ca = (color >> kAModShift) & 0xFF;
-		byte cr = (color >> kRModShift) & 0xFF;
-		byte cg = (color >> kGModShift) & 0xFF;
-		byte cb = (color >> kBModShift) & 0xFF;
-
-		for (uint32 i = 0; i < height; i++) {
-			out = outo;
-			in = ino;
-			for (uint32 j = 0; j < width; j++) {
+	for (uint32 i = 0; i < height; i++) {
+		out = outo;
+		in = ino;
+		for (uint32 j = 0; j < width; j++) {
 
-				uint32 ina = in[kAIndex] * ca >> 8;
+			uint32 ina = in[kAIndex] * ca >> 8;
 
+			if (ina != 0) {
 				if (cb != 255) {
 					out[kBIndex] = MIN<uint>(out[kBIndex] + ((in[kBIndex] * cb * ina) >> 16), 255u);
 				} else {
@@ -250,12 +230,33 @@ void doBlitAdditiveBlend(byte *ino, byte *outo, uint32 width, uint32 height, uin
 				} else {
 					out[kRIndex] = MIN<uint>(out[kRIndex] + (in[kRIndex] * ina >> 8), 255u);
 				}
-
-				in += inStep;
-				out += 4;
 			}
-			outo += pitch;
-			ino += inoStep;
+
+			in += inStep;
+			out += 4;
+		}
+
+		outo += pitch;
+		ino += inoStep;
+	}
+}
+
+static void doBlitAdditiveBlend(byte *ino, byte *outo, uint32 width, uint32 height, uint32 pitch, int32 inStep, int32 inoStep, uint32 color) {
+
+	bool rgbmod   = ((color & kRGBModMask) != kRGBModMask);
+	bool alphamod = ((color & kAModMask)   != kAModMask);
+
+	if (rgbmod) {
+		if (alphamod) {
+			doBlitAdditiveBlendImpl<true, true>(ino, outo, width, height, pitch, inStep, inoStep, color);
+		} else {
+			doBlitAdditiveBlendImpl<true, false>(ino, outo, width, height, pitch, inStep, inoStep, color);
+		}
+	} else {
+		if (alphamod) {
+			doBlitAdditiveBlendImpl<false, true>(ino, outo, width, height, pitch, inStep, inoStep, color);
+		} else {
+			doBlitAdditiveBlendImpl<false, false>(ino, outo, width, height, pitch, inStep, inoStep, color);
 		}
 	}
 }
@@ -263,106 +264,81 @@ void doBlitAdditiveBlend(byte *ino, byte *outo, uint32 width, uint32 height, uin
 /**
  * Optimized version of doBlit to be used with subtractive blended blitting
  */
-void doBlitSubtractiveBlend(byte *ino, byte *outo, uint32 width, uint32 height, uint32 pitch, int32 inStep, int32 inoStep, uint32 color) {
+template<bool rgbmod>
+static void doBlitSubtractiveBlendImpl(byte *ino, byte *outo, uint32 width, uint32 height, uint32 pitch, int32 inStep, int32 inoStep, uint32 color) {
+
 	byte *in;
 	byte *out;
 
-	if (color == 0xffffffff) {
-
-		for (uint32 i = 0; i < height; i++) {
-			out = outo;
-			in = ino;
-			for (uint32 j = 0; j < width; j++) {
+	byte cr = rgbmod   ? ((color >> kRModShift) & 0xFF) : 255;
+	byte cg = rgbmod   ? ((color >> kGModShift) & 0xFF) : 255;
+	byte cb = rgbmod   ? ((color >> kBModShift) & 0xFF) : 255;
 
-				if (in[kAIndex] != 0) {
-					out[kRIndex] = MAX(out[kRIndex] - ((in[kRIndex] * out[kRIndex]) * in[kAIndex] >> 16), 0);
-					out[kGIndex] = MAX(out[kGIndex] - ((in[kGIndex] * out[kGIndex]) * in[kAIndex] >> 16), 0);
-					out[kBIndex] = MAX(out[kBIndex] - ((in[kBIndex] * out[kBIndex]) * in[kAIndex] >> 16), 0);
-				}
+	for (uint32 i = 0; i < height; i++) {
+		out = outo;
+		in = ino;
+		for (uint32 j = 0; j < width; j++) {
 
-				in += inStep;
-				out += 4;
+			out[kAIndex] = 255;
+			if (cb != 255) {
+				out[kBIndex] = MAX(out[kBIndex] - ((in[kBIndex] * cb  * (out[kBIndex]) * in[kAIndex]) >> 24), 0);
+			} else {
+				out[kBIndex] = MAX(out[kBIndex] - (in[kBIndex] * (out[kBIndex]) * in[kAIndex] >> 16), 0);
 			}
-			outo += pitch;
-			ino += inoStep;
-		}
-	} else {
 
-		byte cr = (color >> kRModShift) & 0xFF;
-		byte cg = (color >> kGModShift) & 0xFF;
-		byte cb = (color >> kBModShift) & 0xFF;
+			if (cg != 255) {
+				out[kGIndex] = MAX(out[kGIndex] - ((in[kGIndex] * cg  * (out[kGIndex]) * in[kAIndex]) >> 24), 0);
+			} else {
+				out[kGIndex] = MAX(out[kGIndex] - (in[kGIndex] * (out[kGIndex]) * in[kAIndex] >> 16), 0);
+			}
 
-		for (uint32 i = 0; i < height; i++) {
-			out = outo;
-			in = ino;
-			for (uint32 j = 0; j < width; j++) {
+			if (cr != 255) {
+				out[kRIndex] = MAX(out[kRIndex] - ((in[kRIndex] * cr * (out[kRIndex]) * in[kAIndex]) >> 24), 0);
+			} else {
+				out[kRIndex] = MAX(out[kRIndex] - (in[kRIndex] * (out[kRIndex]) * in[kAIndex] >> 16), 0);
+			}
 
-				out[kAIndex] = 255;
-				if (cb != 255) {
-					out[kBIndex] = MAX(out[kBIndex] - ((in[kBIndex] * cb  * (out[kBIndex]) * in[kAIndex]) >> 24), 0);
-				} else {
-					out[kBIndex] = MAX(out[kBIndex] - (in[kBIndex] * (out[kBIndex]) * in[kAIndex] >> 16), 0);
-				}
+			in += inStep;
+			out += 4;
+		}
+		outo += pitch;
+		ino += inoStep;
+	}
+}
 
-				if (cg != 255) {
-					out[kGIndex] = MAX(out[kGIndex] - ((in[kGIndex] * cg  * (out[kGIndex]) * in[kAIndex]) >> 24), 0);
-				} else {
-					out[kGIndex] = MAX(out[kGIndex] - (in[kGIndex] * (out[kGIndex]) * in[kAIndex] >> 16), 0);
-				}
+static void doBlitSubtractiveBlend(byte *ino, byte *outo, uint32 width, uint32 height, uint32 pitch, int32 inStep, int32 inoStep, uint32 color) {
 
-				if (cr != 255) {
-					out[kRIndex] = MAX(out[kRIndex] - ((in[kRIndex] * cr * (out[kRIndex]) * in[kAIndex]) >> 24), 0);
-				} else {
-					out[kRIndex] = MAX(out[kRIndex] - (in[kRIndex] * (out[kRIndex]) * in[kAIndex] >> 16), 0);
-				}
+	bool rgbmod   = ((color & kRGBModMask) != kRGBModMask);
 
-				in += inStep;
-				out += 4;
-			}
-			outo += pitch;
-			ino += inoStep;
-		}
+	if (rgbmod) {
+		doBlitSubtractiveBlendImpl<true>(ino, outo, width, height, pitch, inStep, inoStep, color);
+	} else {
+		doBlitSubtractiveBlendImpl<false>(ino, outo, width, height, pitch, inStep, inoStep, color);
 	}
 }
 
 /**
  * Optimized version of doBlit to be used with multiply blended blitting
  */
-void doBlitMultiplyBlend(byte *ino, byte *outo, uint32 width, uint32 height, uint32 pitch, int32 inStep, int32 inoStep, uint32 color) {
+template<bool rgbmod, bool alphamod>
+static void doBlitMultiplyBlendImpl(byte *ino, byte *outo, uint32 width, uint32 height, uint32 pitch, int32 inStep, int32 inoStep, uint32 color) {
+
 	byte *in;
 	byte *out;
 
-	if (color == 0xffffffff) {
-		for (uint32 i = 0; i < height; i++) {
-			out = outo;
-			in = ino;
-			for (uint32 j = 0; j < width; j++) {
-
-				if (in[kAIndex] != 0) {
-					out[kRIndex] = MIN((in[kRIndex] * in[kAIndex] >> 8) * out[kRIndex] >> 8, 255);
-					out[kGIndex] = MIN((in[kGIndex] * in[kAIndex] >> 8) * out[kGIndex] >> 8, 255);
-					out[kBIndex] = MIN((in[kBIndex] * in[kAIndex] >> 8) * out[kBIndex] >> 8, 255);
-				}
+	byte ca = alphamod ? ((color >> kAModShift) & 0xFF) : 255;
+	byte cr = rgbmod   ? ((color >> kRModShift) & 0xFF) : 255;
+	byte cg = rgbmod   ? ((color >> kGModShift) & 0xFF) : 255;
+	byte cb = rgbmod   ? ((color >> kBModShift) & 0xFF) : 255;
 
-				in += inStep;
-				out += 4;
-			}
-			outo += pitch;
-			ino += inoStep;
-		}
-	} else {
-		byte ca = (color >> kAModShift) & 0xFF;
-		byte cr = (color >> kRModShift) & 0xFF;
-		byte cg = (color >> kGModShift) & 0xFF;
-		byte cb = (color >> kBModShift) & 0xFF;
-
-		for (uint32 i = 0; i < height; i++) {
-			out = outo;
-			in = ino;
-			for (uint32 j = 0; j < width; j++) {
+	for (uint32 i = 0; i < height; i++) {
+		out = outo;
+		in = ino;
+		for (uint32 j = 0; j < width; j++) {
 
-				uint32 ina = in[kAIndex] * ca >> 8;
+			uint32 ina = in[kAIndex] * ca >> 8;
 
+			if (ina != 0) {
 				if (cb != 255) {
 					out[kBIndex] = MIN<uint>(out[kBIndex] * ((in[kBIndex] * cb * ina) >> 16) >> 8, 255u);
 				} else {
@@ -380,17 +356,37 @@ void doBlitMultiplyBlend(byte *ino, byte *outo, uint32 width, uint32 height, uin
 				} else {
 					out[kRIndex] = MIN<uint>(out[kRIndex] * (in[kRIndex] * ina >> 8) >> 8, 255u);
 				}
-
-				in += inStep;
-				out += 4;
 			}
-			outo += pitch;
-			ino += inoStep;
+
+			in += inStep;
+			out += 4;
 		}
+		outo += pitch;
+		ino += inoStep;
 	}
 
 }
 
+static void doBlitMultiplyBlend(byte *ino, byte *outo, uint32 width, uint32 height, uint32 pitch, int32 inStep, int32 inoStep, uint32 color) {
+
+	bool rgbmod   = ((color & kRGBModMask) != kRGBModMask);
+	bool alphamod = ((color & kAModMask)   != kAModMask);
+
+	if (rgbmod) {
+		if (alphamod) {
+			doBlitMultiplyBlendImpl<true, true>(ino, outo, width, height, pitch, inStep, inoStep, color);
+		} else {
+			doBlitMultiplyBlendImpl<true, false>(ino, outo, width, height, pitch, inStep, inoStep, color);
+		}
+	} else {
+		if (alphamod) {
+			doBlitMultiplyBlendImpl<false, true>(ino, outo, width, height, pitch, inStep, inoStep, color);
+		} else {
+			doBlitMultiplyBlendImpl<false, false>(ino, outo, width, height, pitch, inStep, inoStep, color);
+		}
+	}
+}
+
 Common::Rect TransparentSurface::blit(Graphics::Surface &target, int posX, int posY, int flipping, Common::Rect *pPartRect, uint color, int width, int height, TSpriteBlendMode blendMode) {
 
 	Common::Rect retSize;




More information about the Scummvm-git-logs mailing list