[Scummvm-git-logs] scummvm master -> 8c560fe94f717c7148defaf249aaa56d6cd003b5

sev- noreply at scummvm.org
Mon Jun 13 13:09:11 UTC 2022


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

Summary:
709175d835 GRAPHICS: Optimized managed surface blit in transparent/opaque pixel case
8c560fe94f GRAPHICS: Fix redundant color loads


Commit: 709175d8359b0e7aaef0bee23e6ac2651359734d
    https://github.com/scummvm/scummvm/commit/709175d8359b0e7aaef0bee23e6ac2651359734d
Author: elasota (ejlasota at gmail.com)
Date: 2022-06-13T15:09:08+02:00

Commit Message:
GRAPHICS: Optimized managed surface blit in transparent/opaque pixel case

Changed paths:
    graphics/managed_surface.cpp


diff --git a/graphics/managed_surface.cpp b/graphics/managed_surface.cpp
index 62be470f760..155efe82103 100644
--- a/graphics/managed_surface.cpp
+++ b/graphics/managed_surface.cpp
@@ -279,19 +279,31 @@ void ManagedSurface::blitFromInner(const Surface &src, const Common::Rect &srcRe
 	const int scaleX = SCALE_THRESHOLD * srcRect.width() / destRect.width();
 	const int scaleY = SCALE_THRESHOLD * srcRect.height() / destRect.height();
 
-	uint destPixel;
-	byte rSrc, gSrc, bSrc, aSrc;
-	byte aDest = 0, rDest = 0, gDest = 0, bDest = 0;
-
 	if (!srcRect.isValidRect())
 		return;
 
-	if (format != src.format) {
+	// Copy format so compiler can optimize better.
+	// This should allow it to do some loop optimizations and condition hoisting as it can tell nothing
+	// inside of the loop will clobber the format.
+	Graphics::PixelFormat destFormat = format;
+	Graphics::PixelFormat srcFormat = src.format;
+
+	bool isSameFormat = (destFormat == srcFormat);
+	if (!isSameFormat) {
 		// When the pixel format differs, the destination must be non-paletted
-		assert(format.bytesPerPixel == 2 || format.bytesPerPixel == 3
-			|| format.bytesPerPixel == 4);
-		assert(src.format.bytesPerPixel == 2 || src.format.bytesPerPixel == 4
-			|| (src.format.bytesPerPixel == 1 && srcPalette));
+		assert(destFormat.bytesPerPixel == 2 || destFormat.bytesPerPixel == 3
+			|| destFormat.bytesPerPixel == 4);
+		assert(srcFormat.bytesPerPixel == 2 || srcFormat.bytesPerPixel == 4
+			|| (srcFormat.bytesPerPixel == 1 && srcPalette));
+	}
+
+
+	uint32 alphaMask = 0;
+	if (srcFormat.bytesPerPixel == 1) {
+		alphaMask = 0xff000000u;
+	} else {
+		if (srcFormat.aBits() > 0)
+			alphaMask = (((static_cast<uint32>(1) << (srcFormat.aBits() - 1)) - 1) * 2 + 1) << srcFormat.aShift;
 	}
 
 	const bool noScale = scaleX == SCALE_THRESHOLD && scaleY == SCALE_THRESHOLD;
@@ -303,7 +315,7 @@ void ManagedSurface::blitFromInner(const Surface &src, const Common::Rect &srcRe
 
 		// For paletted format, assume the palette is the same and there is no transparency.
 		// We can thus do a straight copy of the pixels.
-		if (format.bytesPerPixel == 1 && noScale) {
+		if (destFormat.bytesPerPixel == 1 && noScale) {
 			int width = srcRect.width();
 			if (destRect.left + width > w)
 				width = w - destRect.left;
@@ -322,65 +334,101 @@ void ManagedSurface::blitFromInner(const Surface &src, const Common::Rect &srcRe
 			if (destX < 0 || destX >= w)
 				continue;
 
-			const byte *srcVal = &srcP[scaleXCtr / SCALE_THRESHOLD * src.format.bytesPerPixel];
-			byte *destVal = &destP[xCtr * format.bytesPerPixel];
-			if (format.bytesPerPixel == 1) {
+			const byte *srcVal = &srcP[scaleXCtr / SCALE_THRESHOLD * srcFormat.bytesPerPixel];
+			byte *destVal = &destP[xCtr * destFormat.bytesPerPixel];
+			if (destFormat.bytesPerPixel == 1) {
 				*destVal = *srcVal;
 				continue;
 			}
 
-			if (src.format.bytesPerPixel == 1) {
+			uint32 col = 0;
+			if (srcFormat.bytesPerPixel == 1) {
 				assert(srcPalette != nullptr);	// Catch the cases when palette is missing
 				// Get the palette color
-				const uint32 col = srcPalette[*srcVal];
-				rSrc = col & 0xff;
-				gSrc = (col >> 8) & 0xff;
-				bSrc = (col >> 16) & 0xff;
-				aSrc = (col >> 24) & 0xff;
+				col = srcPalette[*srcVal];
 			} else {
 				// Use the src's pixel format to split up the source pixel
-				src.format.colorToARGB(src.format.bytesPerPixel == 2
-					? *(const uint16 *)srcVal : *(const uint32 *)srcVal,
-					aSrc, rSrc, gSrc, bSrc);
+				if (srcFormat.bytesPerPixel == 2)
+					col = *reinterpret_cast<const uint16 *>(srcVal);
+				else
+					col = *reinterpret_cast<const uint32 *>(srcVal);
 			}
 
-			if (aSrc == 0) {
+			const bool isOpaque = ((col & alphaMask) == alphaMask);
+
+			uint32 destPixel = 0;
+
+			// Need to check isOpaque in case alpha mask is 0
+			if (!isOpaque && (col & alphaMask) == 0) {
 				// Completely transparent, so skip
 				continue;
-			} else if (aSrc == 0xff) {
-				// Completely opaque, so copy RGB values over
-				aDest = aSrc;
-				rDest = rSrc;
-				gDest = gSrc;
-				bDest = bSrc;
+			} else if (isOpaque && isSameFormat) {
+				// Completely opaque, same format, copy the entire value
+				destPixel = col;
 			} else {
-				// Partially transparent, so calculate new pixel colors
-				if (format.bytesPerPixel == 2) {
-					uint32 destColor = *(uint16 *)destVal;
-					format.colorToARGB(destColor, aDest, rDest, gDest, bDest);
-				} else if (format.bytesPerPixel == 4) {
-					uint32 destColor = *(uint32 *)destVal;
-					format.colorToARGB(destColor, aDest, rDest, gDest, bDest);
+				byte rSrc, gSrc, bSrc, aSrc;
+				byte aDest = 0, rDest = 0, gDest = 0, bDest = 0;
+
+				// Different format or partially transparent
+				if (srcFormat.bytesPerPixel == 1) {
+					assert(srcPalette != nullptr); // Catch the cases when palette is missing
+					// Get the palette color
+					col = srcPalette[*srcVal];
+					rSrc = col & 0xff;
+					gSrc = (col >> 8) & 0xff;
+					bSrc = (col >> 16) & 0xff;
+					aSrc = (col >> 24) & 0xff;
+				} else {
+					if (srcFormat.bytesPerPixel == 2)
+						col = *reinterpret_cast<const uint16 *>(srcVal);
+					else
+						col = *reinterpret_cast<const uint32 *>(srcVal);
+
+					srcFormat.colorToARGB(col, aSrc, rSrc, gSrc, bSrc);
+				}
+
+				if (isOpaque) {
+					aDest = aSrc;
+					rDest = rSrc;
+					gDest = gSrc;
+					bDest = bSrc;
 				} else {
-					aDest = 0xFF;
-					rDest = destVal[0];
-					gDest = destVal[1];
-					bDest = destVal[2];
+					// Partially transparent, so calculate new pixel colors
+					if (destFormat.bytesPerPixel == 2) {
+						uint32 destColor = *reinterpret_cast<uint16 *>(destVal);
+					} else if (format.bytesPerPixel == 4) {
+						uint32 destColor = *reinterpret_cast<uint32 *>(destVal);
+						destFormat.colorToARGB(destColor, aDest, rDest, gDest, bDest);
+					} else {
+						aDest = 0xFF;
+						rDest = destVal[0];
+						gDest = destVal[1];
+						bDest = destVal[2];
+					}
+
+					if (aDest == 0xff) {
+						// Opaque target
+						rDest = (((rDest * (255 - aSrc) + rSrc * aSrc) * (257 * 257)) >> 24) & 0xff;
+						gDest = (((gDest * (255 - aSrc) + gSrc * aSrc) * (257 * 257)) >> 24) & 0xff;
+						bDest = (((bDest * (255 - aSrc) + bSrc * aSrc) * (257 * 257)) >> 24) & 0xff;
+					} else {
+						// Translucent target
+						double sAlpha = (double)aSrc / 255.0;
+						double dAlpha = (double)aDest / 255.0;
+						dAlpha *= (1.0 - sAlpha);
+						rDest = static_cast<uint8>((rSrc * sAlpha + rDest * dAlpha) / (sAlpha + dAlpha));
+						gDest = static_cast<uint8>((gSrc * sAlpha + gDest * dAlpha) / (sAlpha + dAlpha));
+						bDest = static_cast<uint8>((bSrc * sAlpha + bDest * dAlpha) / (sAlpha + dAlpha));
+						aDest = static_cast<uint8>(255. * (sAlpha + dAlpha));
+					}
 				}
 
-				double sAlpha = (double)aSrc / 255.0;
-				double dAlpha = (double)aDest / 255.0;
-				dAlpha *= (1.0 - sAlpha);
-				rDest = static_cast<uint8>((rSrc * sAlpha + rDest * dAlpha) / (sAlpha + dAlpha));
-				gDest = static_cast<uint8>((gSrc * sAlpha + gDest * dAlpha) / (sAlpha + dAlpha));
-				bDest = static_cast<uint8>((bSrc * sAlpha + bDest * dAlpha) / (sAlpha + dAlpha));
-				aDest = static_cast<uint8>(255. * (sAlpha + dAlpha));
+				destPixel = destFormat.ARGBToColor(aDest, rDest, gDest, bDest);
 			}
 
-			destPixel = format.ARGBToColor(aDest, rDest, gDest, bDest);
-			if (format.bytesPerPixel == 2)
+			if (destFormat.bytesPerPixel == 2)
 				*(uint16 *)destVal = destPixel;
-			else if (format.bytesPerPixel == 4)
+			else if (destFormat.bytesPerPixel == 4)
 				*(uint32 *)destVal = destPixel;
 			else
 				WRITE_UINT24(destVal, destPixel);


Commit: 8c560fe94f717c7148defaf249aaa56d6cd003b5
    https://github.com/scummvm/scummvm/commit/8c560fe94f717c7148defaf249aaa56d6cd003b5
Author: elasota (ejlasota at gmail.com)
Date: 2022-06-13T15:09:08+02:00

Commit Message:
GRAPHICS: Fix redundant color loads

Changed paths:
    graphics/managed_surface.cpp


diff --git a/graphics/managed_surface.cpp b/graphics/managed_surface.cpp
index 155efe82103..afba39d35b8 100644
--- a/graphics/managed_surface.cpp
+++ b/graphics/managed_surface.cpp
@@ -371,19 +371,11 @@ void ManagedSurface::blitFromInner(const Surface &src, const Common::Rect &srcRe
 
 				// Different format or partially transparent
 				if (srcFormat.bytesPerPixel == 1) {
-					assert(srcPalette != nullptr); // Catch the cases when palette is missing
-					// Get the palette color
-					col = srcPalette[*srcVal];
 					rSrc = col & 0xff;
 					gSrc = (col >> 8) & 0xff;
 					bSrc = (col >> 16) & 0xff;
 					aSrc = (col >> 24) & 0xff;
 				} else {
-					if (srcFormat.bytesPerPixel == 2)
-						col = *reinterpret_cast<const uint16 *>(srcVal);
-					else
-						col = *reinterpret_cast<const uint32 *>(srcVal);
-
 					srcFormat.colorToARGB(col, aSrc, rSrc, gSrc, bSrc);
 				}
 




More information about the Scummvm-git-logs mailing list