[Scummvm-git-logs] scummvm master -> 74cead5dd963153dc84565cf4a281a91706865b9

sev- noreply at scummvm.org
Sat Sep 17 10:04:54 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:
74cead5dd9 GRAPHICS: Add crossKeyBlit and crossKeyBlitMap


Commit: 74cead5dd963153dc84565cf4a281a91706865b9
    https://github.com/scummvm/scummvm/commit/74cead5dd963153dc84565cf4a281a91706865b9
Author: Cameron Cawley (ccawley2011 at gmail.com)
Date: 2022-09-17T12:04:49+02:00

Commit Message:
GRAPHICS: Add crossKeyBlit and crossKeyBlitMap

Changed paths:
    graphics/conversion.cpp
    graphics/conversion.h


diff --git a/graphics/conversion.cpp b/graphics/conversion.cpp
index 2285e27fb91..ebc0be4ad54 100644
--- a/graphics/conversion.cpp
+++ b/graphics/conversion.cpp
@@ -104,16 +104,18 @@ bool keyBlit(byte *dst, const byte *src,
 
 namespace {
 
-template<typename SrcColor, typename DstColor, bool backward>
+template<typename SrcColor, typename DstColor, bool backward, bool hasKey>
 inline void crossBlitLogic(byte *dst, const byte *src, const uint w, const uint h,
 						   const PixelFormat &srcFmt, const PixelFormat &dstFmt,
-						   const uint srcDelta, const uint dstDelta) {
+						   const uint srcDelta, const uint dstDelta, const uint32 key) {
 	for (uint y = 0; y < h; ++y) {
 		for (uint x = 0; x < w; ++x) {
 			const uint32 color = *(const SrcColor *)src;
-			byte a, r, g, b;
-			srcFmt.colorToARGB(color, a, r, g, b);
-			*(DstColor *)dst = dstFmt.ARGBToColor(a, r, g, b);
+			if (!hasKey || color != key) {
+				byte a, r, g, b;
+				srcFmt.colorToARGB(color, a, r, g, b);
+				*(DstColor *)dst = dstFmt.ARGBToColor(a, r, g, b);
+			}
 
 			if (backward) {
 				src -= sizeof(SrcColor);
@@ -134,12 +136,15 @@ inline void crossBlitLogic(byte *dst, const byte *src, const uint w, const uint
 	}
 }
 
-template<typename DstColor, bool backward>
+template<typename DstColor, bool backward, bool hasKey>
 inline void crossBlitLogic1BppSource(byte *dst, const byte *src, const uint w, const uint h,
-									 const uint srcDelta, const uint dstDelta, const uint32 *map) {
+									 const uint srcDelta, const uint dstDelta, const uint32 *map, const uint32 key) {
 	for (uint y = 0; y < h; ++y) {
 		for (uint x = 0; x < w; ++x) {
-			*(DstColor *)dst = map[*src];
+			const byte color = *src;
+			if (!hasKey || color != key) {
+				*(DstColor *)dst = map[color];
+			}
 
 			if (backward) {
 				src -= 1;
@@ -160,10 +165,10 @@ inline void crossBlitLogic1BppSource(byte *dst, const byte *src, const uint w, c
 	}
 }
 
-template<typename DstColor, bool backward>
+template<typename DstColor, bool backward, bool hasKey>
 inline void crossBlitLogic3BppSource(byte *dst, const byte *src, const uint w, const uint h,
 									 const PixelFormat &srcFmt, const PixelFormat &dstFmt,
-									 const uint srcDelta, const uint dstDelta) {
+									 const uint srcDelta, const uint dstDelta, const uint32 key) {
 	uint32 color;
 	byte r, g, b, a;
 	uint8 *col = (uint8 *)&color;
@@ -173,8 +178,10 @@ inline void crossBlitLogic3BppSource(byte *dst, const byte *src, const uint w, c
 	for (uint y = 0; y < h; ++y) {
 		for (uint x = 0; x < w; ++x) {
 			memcpy(col, src, 3);
-			srcFmt.colorToARGB(color, a, r, g, b);
-			*(DstColor *)dst = dstFmt.ARGBToColor(a, r, g, b);
+			if (!hasKey || color != key) {
+				srcFmt.colorToARGB(color, a, r, g, b);
+				*(DstColor *)dst = dstFmt.ARGBToColor(a, r, g, b);
+			}
 
 			if (backward) {
 				src -= 3;
@@ -221,11 +228,69 @@ bool crossBlit(byte *dst, const byte *src,
 	// TODO: optimized cases for dstDelta of 0
 	if (dstFmt.bytesPerPixel == 2) {
 		if (srcFmt.bytesPerPixel == 2) {
-			crossBlitLogic<uint16, uint16, false>(dst, src, w, h, srcFmt, dstFmt, srcDelta, dstDelta);
+			crossBlitLogic<uint16, uint16, false, false>(dst, src, w, h, srcFmt, dstFmt, srcDelta, dstDelta, 0);
+		} else if (srcFmt.bytesPerPixel == 3) {
+			crossBlitLogic3BppSource<uint16, false, false>(dst, src, w, h, srcFmt, dstFmt, srcDelta, dstDelta, 0);
+		} else {
+			crossBlitLogic<uint32, uint16, false, false>(dst, src, w, h, srcFmt, dstFmt, srcDelta, dstDelta, 0);
+		}
+	} else if (dstFmt.bytesPerPixel == 4) {
+		if (srcFmt.bytesPerPixel == 2) {
+			// We need to blit the surface from bottom right to top left here.
+			// This is neeeded, because when we convert to the same memory
+			// buffer copying the surface from top left to bottom right would
+			// overwrite the source, since we have more bits per destination
+			// color than per source color.
+			dst += h * dstPitch - dstDelta - dstFmt.bytesPerPixel;
+			src += h * srcPitch - srcDelta - srcFmt.bytesPerPixel;
+			crossBlitLogic<uint16, uint32, true, false>(dst, src, w, h, srcFmt, dstFmt, srcDelta, dstDelta, 0);
+		} else if (srcFmt.bytesPerPixel == 3) {
+			// We need to blit the surface from bottom right to top left here.
+			// This is neeeded, because when we convert to the same memory
+			// buffer copying the surface from top left to bottom right would
+			// overwrite the source, since we have more bits per destination
+			// color than per source color.
+			dst += h * dstPitch - dstDelta - dstFmt.bytesPerPixel;
+			src += h * srcPitch - srcDelta - srcFmt.bytesPerPixel;
+			crossBlitLogic3BppSource<uint32, true, false>(dst, src, w, h, srcFmt, dstFmt, srcDelta, dstDelta, 0);
+		} else {
+			crossBlitLogic<uint32, uint32, false, false>(dst, src, w, h, srcFmt, dstFmt, srcDelta, dstDelta, 0);
+		}
+	} else {
+		return false;
+	}
+	return true;
+}
+
+// Function to blit a rect from one color format to another with a transparent color key
+bool crossKeyBlit(byte *dst, const byte *src,
+			   const uint dstPitch, const uint srcPitch,
+			   const uint w, const uint h,
+			   const Graphics::PixelFormat &dstFmt, const Graphics::PixelFormat &srcFmt, const uint32 key) {
+	// Error out if conversion is impossible
+	if ((srcFmt.bytesPerPixel == 1) || (dstFmt.bytesPerPixel == 1)
+			 || (dstFmt.bytesPerPixel == 3)
+			 || (!srcFmt.bytesPerPixel) || (!dstFmt.bytesPerPixel))
+		return false;
+
+	// Don't perform unnecessary conversion
+	if (srcFmt == dstFmt) {
+		keyBlit(dst, src, dstPitch, srcPitch, w, h, dstFmt.bytesPerPixel, key);
+		return true;
+	}
+
+	// Faster, but larger, to provide optimized handling for each case.
+	const uint srcDelta = (srcPitch - w * srcFmt.bytesPerPixel);
+	const uint dstDelta = (dstPitch - w * dstFmt.bytesPerPixel);
+
+	// TODO: optimized cases for dstDelta of 0
+	if (dstFmt.bytesPerPixel == 2) {
+		if (srcFmt.bytesPerPixel == 2) {
+			crossBlitLogic<uint16, uint16, false, true>(dst, src, w, h, srcFmt, dstFmt, srcDelta, dstDelta, key);
 		} else if (srcFmt.bytesPerPixel == 3) {
-			crossBlitLogic3BppSource<uint16, false>(dst, src, w, h, srcFmt, dstFmt, srcDelta, dstDelta);
+			crossBlitLogic3BppSource<uint16, false, true>(dst, src, w, h, srcFmt, dstFmt, srcDelta, dstDelta, key);
 		} else {
-			crossBlitLogic<uint32, uint16, false>(dst, src, w, h, srcFmt, dstFmt, srcDelta, dstDelta);
+			crossBlitLogic<uint32, uint16, false, true>(dst, src, w, h, srcFmt, dstFmt, srcDelta, dstDelta, key);
 		}
 	} else if (dstFmt.bytesPerPixel == 4) {
 		if (srcFmt.bytesPerPixel == 2) {
@@ -236,7 +301,7 @@ bool crossBlit(byte *dst, const byte *src,
 			// color than per source color.
 			dst += h * dstPitch - dstDelta - dstFmt.bytesPerPixel;
 			src += h * srcPitch - srcDelta - srcFmt.bytesPerPixel;
-			crossBlitLogic<uint16, uint32, true>(dst, src, w, h, srcFmt, dstFmt, srcDelta, dstDelta);
+			crossBlitLogic<uint16, uint32, true, true>(dst, src, w, h, srcFmt, dstFmt, srcDelta, dstDelta, key);
 		} else if (srcFmt.bytesPerPixel == 3) {
 			// We need to blit the surface from bottom right to top left here.
 			// This is neeeded, because when we convert to the same memory
@@ -245,9 +310,9 @@ bool crossBlit(byte *dst, const byte *src,
 			// color than per source color.
 			dst += h * dstPitch - dstDelta - dstFmt.bytesPerPixel;
 			src += h * srcPitch - srcDelta - srcFmt.bytesPerPixel;
-			crossBlitLogic3BppSource<uint32, true>(dst, src, w, h, srcFmt, dstFmt, srcDelta, dstDelta);
+			crossBlitLogic3BppSource<uint32, true, true>(dst, src, w, h, srcFmt, dstFmt, srcDelta, dstDelta, key);
 		} else {
-			crossBlitLogic<uint32, uint32, false>(dst, src, w, h, srcFmt, dstFmt, srcDelta, dstDelta);
+			crossBlitLogic<uint32, uint32, false, true>(dst, src, w, h, srcFmt, dstFmt, srcDelta, dstDelta, key);
 		}
 	} else {
 		return false;
@@ -269,7 +334,46 @@ bool crossBlitMap(byte *dst, const byte *src,
 	const uint dstDelta = (dstPitch - w * bytesPerPixel);
 
 	if (bytesPerPixel == 1) {
-		crossBlitLogic1BppSource<uint8, false>(dst, src, w, h, srcDelta, dstDelta, map);
+		crossBlitLogic1BppSource<uint8, false, false>(dst, src, w, h, srcDelta, dstDelta, map, 0);
+	} else if (bytesPerPixel == 2) {
+		// We need to blit the surface from bottom right to top left here.
+		// This is neeeded, because when we convert to the same memory
+		// buffer copying the surface from top left to bottom right would
+		// overwrite the source, since we have more bits per destination
+		// color than per source color.
+		dst += h * dstPitch - dstDelta - bytesPerPixel;
+		src += h * srcPitch - srcDelta - 1;
+		crossBlitLogic1BppSource<uint16, true, false>(dst, src, w, h, srcDelta, dstDelta, map, 0);
+	} else if (bytesPerPixel == 4) {
+		// We need to blit the surface from bottom right to top left here.
+		// This is neeeded, because when we convert to the same memory
+		// buffer copying the surface from top left to bottom right would
+		// overwrite the source, since we have more bits per destination
+		// color than per source color.
+		dst += h * dstPitch - dstDelta - bytesPerPixel;
+		src += h * srcPitch - srcDelta - 1;
+		crossBlitLogic1BppSource<uint32, true, false>(dst, src, w, h, srcDelta, dstDelta, map, 0);
+	} else {
+		return false;
+	}
+	return true;
+}
+
+// Function to blit a rect from one color format to another using a map with a transparent color key
+bool crossKeyBlitMap(byte *dst, const byte *src,
+			   const uint dstPitch, const uint srcPitch,
+			   const uint w, const uint h,
+			   const uint bytesPerPixel, const uint32 *map, const uint32 key) {
+	// Error out if conversion is impossible
+	if ((bytesPerPixel == 3) || (!bytesPerPixel))
+		return false;
+
+	// Faster, but larger, to provide optimized handling for each case.
+	const uint srcDelta = (srcPitch - w);
+	const uint dstDelta = (dstPitch - w * bytesPerPixel);
+
+	if (bytesPerPixel == 1) {
+		crossBlitLogic1BppSource<uint8, false, true>(dst, src, w, h, srcDelta, dstDelta, map, key);
 	} else if (bytesPerPixel == 2) {
 		// We need to blit the surface from bottom right to top left here.
 		// This is neeeded, because when we convert to the same memory
@@ -278,7 +382,7 @@ bool crossBlitMap(byte *dst, const byte *src,
 		// color than per source color.
 		dst += h * dstPitch - dstDelta - bytesPerPixel;
 		src += h * srcPitch - srcDelta - 1;
-		crossBlitLogic1BppSource<uint16, true>(dst, src, w, h, srcDelta, dstDelta, map);
+		crossBlitLogic1BppSource<uint16, true, true>(dst, src, w, h, srcDelta, dstDelta, map, key);
 	} else if (bytesPerPixel == 4) {
 		// We need to blit the surface from bottom right to top left here.
 		// This is neeeded, because when we convert to the same memory
@@ -287,7 +391,7 @@ bool crossBlitMap(byte *dst, const byte *src,
 		// color than per source color.
 		dst += h * dstPitch - dstDelta - bytesPerPixel;
 		src += h * srcPitch - srcDelta - 1;
-		crossBlitLogic1BppSource<uint32, true>(dst, src, w, h, srcDelta, dstDelta, map);
+		crossBlitLogic1BppSource<uint32, true, true>(dst, src, w, h, srcDelta, dstDelta, map, key);
 	} else {
 		return false;
 	}
diff --git a/graphics/conversion.h b/graphics/conversion.h
index 0908884d116..dccd9f756cf 100644
--- a/graphics/conversion.h
+++ b/graphics/conversion.h
@@ -99,6 +99,7 @@ bool keyBlit(byte *dst, const byte *src,
 			   const uint dstPitch, const uint srcPitch,
 			   const uint w, const uint h,
 			   const uint bytesPerPixel, const uint32 key);
+
 /**
  * Blits a rectangle from one graphical format to another.
  *
@@ -126,11 +127,44 @@ bool crossBlit(byte *dst, const byte *src,
 			   const uint w, const uint h,
 			   const Graphics::PixelFormat &dstFmt, const Graphics::PixelFormat &srcFmt);
 
+/**
+ * Blits a rectangle from one graphical format to another with a transparent color key.
+ *
+ * @param dst		the buffer which will recieve the converted graphics data
+ * @param src		the buffer containing the original graphics data
+ * @param dstPitch	width in bytes of one full line of the dest buffer
+ * @param srcPitch	width in bytes of one full line of the source buffer
+ * @param w			the width of the graphics data
+ * @param h			the height of the graphics data
+ * @param dstFmt	the desired pixel format
+ * @param srcFmt	the original pixel format
+ * @param key			the transparent color key in the original pixel format
+ * @return			true if conversion completes successfully,
+ *					false if there is an error.
+ *
+ * @note Blitting to a 3Bpp destination is not supported
+ * @note This can convert a surface in place, regardless of the
+ *       source and destination format, as long as there is enough
+ *       space for the destination. The dstPitch / srcPitch ratio
+ *       must at least equal the dstBpp / srcBpp ratio for
+ *       dstPitch >= srcPitch and at most dstBpp / srcBpp for
+ *       dstPitch < srcPitch though.
+ */
+bool crossKeyBlit(byte *dst, const byte *src,
+			   const uint dstPitch, const uint srcPitch,
+			   const uint w, const uint h,
+			   const Graphics::PixelFormat &dstFmt, const Graphics::PixelFormat &srcFmt, const uint32 key);
+
 bool crossBlitMap(byte *dst, const byte *src,
 			   const uint dstPitch, const uint srcPitch,
 			   const uint w, const uint h,
 			   const uint bytesPerPixel, const uint32 *map);
 
+bool crossKeyBlitMap(byte *dst, const byte *src,
+			   const uint dstPitch, const uint srcPitch,
+			   const uint w, const uint h,
+			   const uint bytesPerPixel, const uint32 *map, const uint32 key);
+
 bool scaleBlit(byte *dst, const byte *src,
 			   const uint dstPitch, const uint srcPitch,
 			   const uint dstW, const uint dstH,




More information about the Scummvm-git-logs mailing list