[Scummvm-cvs-logs] scummvm master -> c2971374cdb189dbf9f72953a970d0769648e5ae

lordhoto lordhoto at gmail.com
Mon Oct 8 23:20:55 CEST 2012


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

Summary:
05d24e892c GRAPHICS: Clean up crossBlit a bit.
ea1bcaad33 GRAPHICS: Refactor crossBlit logic into a template.
a0f46e9396 GRAPHICS: Remove 3Bpp destination support in crossBlit.
3a55adbf5e GRAPHICS: Fix a bug in crossBlit with 3Bpp source.
0d78d46a0e GRAPHICS: Remove crossBlit's dstBpp >= srcBpp limitation.
a92a509ac8 GRAPHICS: Allow in-place conversion with any color formats in crossBlit.
e8cf0adf95 GRAPHICS: Slight cleanup in crossBlit code.
eeb3959259 GRAPHICS: Add an in-place Surface PixelFormat conversion.
a1e56adad8 GUI: Use in-place Surface conversion in widget code.
c2971374cd Merge pull request #257 from lordhoto/graphics-conversion


Commit: 05d24e892c15a0bc2a8a923927125098704f42db
    https://github.com/scummvm/scummvm/commit/05d24e892c15a0bc2a8a923927125098704f42db
Author: Johannes Schickel (lordhoto at scummvm.org)
Date: 2012-08-27T17:27:47-07:00

Commit Message:
GRAPHICS: Clean up crossBlit a bit.

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



diff --git a/graphics/conversion.cpp b/graphics/conversion.cpp
index 713a06e..705f672 100644
--- a/graphics/conversion.cpp
+++ b/graphics/conversion.cpp
@@ -27,8 +27,10 @@ namespace Graphics {
 // TODO: YUV to RGB conversion function
 
 // Function to blit a rect from one color format to another
-bool crossBlit(byte *dst, const byte *src, int dstpitch, int srcpitch,
-						int w, int h, const Graphics::PixelFormat &dstFmt, const Graphics::PixelFormat &srcFmt) {
+bool crossBlit(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) {
 	// Error out if conversion is impossible
 	if ((srcFmt.bytesPerPixel == 1) || (dstFmt.bytesPerPixel == 1)
 			 || (!srcFmt.bytesPerPixel) || (!dstFmt.bytesPerPixel)
@@ -37,32 +39,31 @@ bool crossBlit(byte *dst, const byte *src, int dstpitch, int srcpitch,
 
 	// Don't perform unnecessary conversion
 	if (srcFmt == dstFmt) {
-		if (dst == src)
-			return true;
-		if (dstpitch == srcpitch && ((w * dstFmt.bytesPerPixel) == dstpitch)) {
-			memcpy(dst,src,dstpitch * h);
-			return true;
-		} else {
-			for (int i = 0; i < h; i++) {
-				memcpy(dst,src,w * dstFmt.bytesPerPixel);
-				dst += dstpitch;
-				src += srcpitch;
+		if (dst != src) {
+			if (dstPitch == srcPitch && ((w * dstFmt.bytesPerPixel) == dstPitch)) {
+				memcpy(dst, src, dstPitch * h);
+			} else {
+				for (uint i = 0; i < h; ++i) {
+					memcpy(dst, src, w * dstFmt.bytesPerPixel);
+					dst += dstPitch;
+					src += srcPitch;
+				}
 			}
-			return true;
 		}
+
+		return true;
 	}
 
 	// Faster, but larger, to provide optimized handling for each case.
-	int srcDelta, dstDelta;
-	srcDelta = (srcpitch - w * srcFmt.bytesPerPixel);
-	dstDelta = (dstpitch - w * dstFmt.bytesPerPixel);
+	const uint srcDelta = (srcPitch - w * srcFmt.bytesPerPixel);
+	const uint dstDelta = (dstPitch - w * dstFmt.bytesPerPixel);
 
 	// TODO: optimized cases for dstDelta of 0
 	uint8 r, g, b, a;
 	if (dstFmt.bytesPerPixel == 2) {
 		uint16 color;
-		for (int y = 0; y < h; y++) {
-			for (int x = 0; x < w; x++, src += 2, dst += 2) {
+		for (uint y = 0; y < h; ++y) {
+			for (uint x = 0; x < w; ++x, src += 2, dst += 2) {
 				color = *(const uint16 *)src;
 				srcFmt.colorToARGB(color, a, r, g, b);
 				color = dstFmt.ARGBToColor(a, r, g, b);
@@ -78,8 +79,8 @@ bool crossBlit(byte *dst, const byte *src, int dstpitch, int srcpitch,
 		col++;
 #endif
 		if (srcFmt.bytesPerPixel == 2) {
-			for (int y = 0; y < h; y++) {
-				for (int x = 0; x < w; x++, src += 2, dst += 3) {
+			for (uint y = 0; y < h; ++y) {
+				for (uint x = 0; x < w; ++x, src += 2, dst += 3) {
 					color = *(const uint16 *)src;
 					srcFmt.colorToARGB(color, a, r, g, b);
 					color = dstFmt.ARGBToColor(a, r, g, b);
@@ -89,8 +90,8 @@ bool crossBlit(byte *dst, const byte *src, int dstpitch, int srcpitch,
 				dst += dstDelta;
 			}
 		} else {
-			for (int y = 0; y < h; y++) {
-				for (int x = 0; x < w; x++, src += 3, dst += 3) {
+			for (uint y = 0; y < h; ++y) {
+				for (uint x = 0; x < w; ++x, src += 3, dst += 3) {
 					memcpy(col, src, 3);
 					srcFmt.colorToARGB(color, a, r, g, b);
 					color = dstFmt.ARGBToColor(a, r, g, b);
@@ -103,8 +104,8 @@ bool crossBlit(byte *dst, const byte *src, int dstpitch, int srcpitch,
 	} else if (dstFmt.bytesPerPixel == 4) {
 		uint32 color;
 		if (srcFmt.bytesPerPixel == 2) {
-			for (int y = 0; y < h; y++) {
-				for (int x = 0; x < w; x++, src += 2, dst += 4) {
+			for (uint y = 0; y < h; ++y) {
+				for (uint x = 0; x < w; ++x, src += 2, dst += 4) {
 					color = *(const uint16 *)src;
 					srcFmt.colorToARGB(color, a, r, g, b);
 					color = dstFmt.ARGBToColor(a, r, g, b);
@@ -118,8 +119,8 @@ bool crossBlit(byte *dst, const byte *src, int dstpitch, int srcpitch,
 #ifdef SCUMM_BIG_ENDIAN
 			col++;
 #endif
-			for (int y = 0; y < h; y++) {
-				for (int x = 0; x < w; x++, src += 2, dst += 4) {
+			for (uint y = 0; y < h; ++y) {
+				for (uint x = 0; x < w; ++x, src += 2, dst += 4) {
 					memcpy(col, src, 3);
 					srcFmt.colorToARGB(color, a, r, g, b);
 					color = dstFmt.ARGBToColor(a, r, g, b);
@@ -129,8 +130,8 @@ bool crossBlit(byte *dst, const byte *src, int dstpitch, int srcpitch,
 				dst += dstDelta;
 			}
 		} else {
-			for (int y = 0; y < h; y++) {
-				for (int x = 0; x < w; x++, src += 4, dst += 4) {
+			for (uint y = 0; y < h; ++y) {
+				for (uint x = 0; x < w; ++x, src += 4, dst += 4) {
 					color = *(const uint32 *)src;
 					srcFmt.colorToARGB(color, a, r, g, b);
 					color = dstFmt.ARGBToColor(a, r, g, b);
diff --git a/graphics/conversion.h b/graphics/conversion.h
index 6babc76..c25f413 100644
--- a/graphics/conversion.h
+++ b/graphics/conversion.h
@@ -66,8 +66,10 @@ inline static void RGB2YUV(byte r, byte g, byte b, byte &y, byte &u, byte &v) {
  *		 destination format have the same bytedepth.
  *
  */
-bool crossBlit(byte *dst, const byte *src, int dstpitch, int srcpitch,
-						int w, int h, const Graphics::PixelFormat &dstFmt, const Graphics::PixelFormat &srcFmt);
+bool crossBlit(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);
 
 } // End of namespace Graphics
 


Commit: ea1bcaad3380132356adb567826e74e587c389cd
    https://github.com/scummvm/scummvm/commit/ea1bcaad3380132356adb567826e74e587c389cd
Author: Johannes Schickel (lordhoto at scummvm.org)
Date: 2012-08-27T17:27:47-07:00

Commit Message:
GRAPHICS: Refactor crossBlit logic into a template.

Changed paths:
    graphics/conversion.cpp



diff --git a/graphics/conversion.cpp b/graphics/conversion.cpp
index 705f672..7b6bda30 100644
--- a/graphics/conversion.cpp
+++ b/graphics/conversion.cpp
@@ -26,6 +26,29 @@ namespace Graphics {
 
 // TODO: YUV to RGB conversion function
 
+namespace {
+
+template<typename SrcColor, typename DstColor>
+FORCEINLINE 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) {
+	for (uint y = 0; y < h; ++y) {
+		for (uint x = 0; x < w; ++x) {
+			uint32 color = *(const SrcColor *)src;
+			byte a, r, g, b;
+			srcFmt.colorToARGB(color, a, r, g, b);
+			color = dstFmt.ARGBToColor(a, r, g, b);
+			*(DstColor *)dst = color;
+			src += sizeof(SrcColor);
+			dst += sizeof(DstColor);
+		}
+		src += srcDelta;
+		dst += dstDelta;
+	}
+}
+
+} // End of anonymous namespace
+
 // Function to blit a rect from one color format to another
 bool crossBlit(byte *dst, const byte *src,
                const uint dstPitch, const uint srcPitch,
@@ -59,21 +82,11 @@ bool crossBlit(byte *dst, const byte *src,
 	const uint dstDelta = (dstPitch - w * dstFmt.bytesPerPixel);
 
 	// TODO: optimized cases for dstDelta of 0
-	uint8 r, g, b, a;
 	if (dstFmt.bytesPerPixel == 2) {
-		uint16 color;
-		for (uint y = 0; y < h; ++y) {
-			for (uint x = 0; x < w; ++x, src += 2, dst += 2) {
-				color = *(const uint16 *)src;
-				srcFmt.colorToARGB(color, a, r, g, b);
-				color = dstFmt.ARGBToColor(a, r, g, b);
-				*(uint16 *)dst = color;
-			}
-			src += srcDelta;
-			dst += dstDelta;
-		}
+		crossBlitLogic<uint16, uint16>(dst, src, w, h, srcFmt, dstFmt, srcDelta, dstDelta);
 	} else if (dstFmt.bytesPerPixel == 3) {
 		uint32 color;
+		uint8 r, g, b, a;
 		uint8 *col = (uint8 *) &color;
 #ifdef SCUMM_BIG_ENDIAN
 		col++;
@@ -102,19 +115,11 @@ bool crossBlit(byte *dst, const byte *src,
 			}
 		}
 	} else if (dstFmt.bytesPerPixel == 4) {
-		uint32 color;
 		if (srcFmt.bytesPerPixel == 2) {
-			for (uint y = 0; y < h; ++y) {
-				for (uint x = 0; x < w; ++x, src += 2, dst += 4) {
-					color = *(const uint16 *)src;
-					srcFmt.colorToARGB(color, a, r, g, b);
-					color = dstFmt.ARGBToColor(a, r, g, b);
-					*(uint32 *)dst = color;
-				}
-				src += srcDelta;
-				dst += dstDelta;
-			}
+			crossBlitLogic<uint16, uint32>(dst, src, w, h, srcFmt, dstFmt, srcDelta, dstDelta);
 		} else if (srcFmt.bytesPerPixel == 3) {
+			uint32 color;
+			byte r, g, b, a;
 			uint8 *col = (uint8 *)&color;
 #ifdef SCUMM_BIG_ENDIAN
 			col++;
@@ -130,16 +135,7 @@ bool crossBlit(byte *dst, const byte *src,
 				dst += dstDelta;
 			}
 		} else {
-			for (uint y = 0; y < h; ++y) {
-				for (uint x = 0; x < w; ++x, src += 4, dst += 4) {
-					color = *(const uint32 *)src;
-					srcFmt.colorToARGB(color, a, r, g, b);
-					color = dstFmt.ARGBToColor(a, r, g, b);
-					*(uint32 *)dst = color;
-				}
-				src += srcDelta;
-				dst += dstDelta;
-			}
+			crossBlitLogic<uint32, uint32>(dst, src, w, h, srcFmt, dstFmt, srcDelta, dstDelta);
 		}
 	} else {
 		return false;


Commit: a0f46e9396861b9eb4ab8adebcbc4739e44b9716
    https://github.com/scummvm/scummvm/commit/a0f46e9396861b9eb4ab8adebcbc4739e44b9716
Author: Johannes Schickel (lordhoto at scummvm.org)
Date: 2012-08-27T17:27:47-07:00

Commit Message:
GRAPHICS: Remove 3Bpp destination support in crossBlit.

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



diff --git a/graphics/conversion.cpp b/graphics/conversion.cpp
index 7b6bda30..84f9bcb 100644
--- a/graphics/conversion.cpp
+++ b/graphics/conversion.cpp
@@ -56,6 +56,7 @@ bool crossBlit(byte *dst, const byte *src,
                const Graphics::PixelFormat &dstFmt, const Graphics::PixelFormat &srcFmt) {
 	// Error out if conversion is impossible
 	if ((srcFmt.bytesPerPixel == 1) || (dstFmt.bytesPerPixel == 1)
+			 || (dstFmt.bytesPerPixel == 3)
 			 || (!srcFmt.bytesPerPixel) || (!dstFmt.bytesPerPixel)
 			 || (srcFmt.bytesPerPixel > dstFmt.bytesPerPixel))
 		return false;
@@ -84,36 +85,6 @@ bool crossBlit(byte *dst, const byte *src,
 	// TODO: optimized cases for dstDelta of 0
 	if (dstFmt.bytesPerPixel == 2) {
 		crossBlitLogic<uint16, uint16>(dst, src, w, h, srcFmt, dstFmt, srcDelta, dstDelta);
-	} else if (dstFmt.bytesPerPixel == 3) {
-		uint32 color;
-		uint8 r, g, b, a;
-		uint8 *col = (uint8 *) &color;
-#ifdef SCUMM_BIG_ENDIAN
-		col++;
-#endif
-		if (srcFmt.bytesPerPixel == 2) {
-			for (uint y = 0; y < h; ++y) {
-				for (uint x = 0; x < w; ++x, src += 2, dst += 3) {
-					color = *(const uint16 *)src;
-					srcFmt.colorToARGB(color, a, r, g, b);
-					color = dstFmt.ARGBToColor(a, r, g, b);
-					memcpy(dst, col, 3);
-				}
-				src += srcDelta;
-				dst += dstDelta;
-			}
-		} else {
-			for (uint y = 0; y < h; ++y) {
-				for (uint x = 0; x < w; ++x, src += 3, dst += 3) {
-					memcpy(col, src, 3);
-					srcFmt.colorToARGB(color, a, r, g, b);
-					color = dstFmt.ARGBToColor(a, r, g, b);
-					memcpy(dst, col, 3);
-				}
-				src += srcDelta;
-				dst += dstDelta;
-			}
-		}
 	} else if (dstFmt.bytesPerPixel == 4) {
 		if (srcFmt.bytesPerPixel == 2) {
 			crossBlitLogic<uint16, uint32>(dst, src, w, h, srcFmt, dstFmt, srcDelta, dstDelta);
diff --git a/graphics/conversion.h b/graphics/conversion.h
index c25f413..8fcb6ba 100644
--- a/graphics/conversion.h
+++ b/graphics/conversion.h
@@ -59,6 +59,7 @@ inline static void RGB2YUV(byte r, byte g, byte b, byte &y, byte &u, byte &v) {
  * @return			true if conversion completes successfully,
  *					false if there is an error.
  *
+ * @note Blitting to a 3Bpp destination is not supported
  * @note This implementation currently arbitrarily requires that the
  *		 destination's format have at least as high a bytedepth as
  *		 the source's.


Commit: 3a55adbf5eaf2d80b48de4ff680452996cc3d1a8
    https://github.com/scummvm/scummvm/commit/3a55adbf5eaf2d80b48de4ff680452996cc3d1a8
Author: Johannes Schickel (lordhoto at scummvm.org)
Date: 2012-08-27T17:27:48-07:00

Commit Message:
GRAPHICS: Fix a bug in crossBlit with 3Bpp source.

Formerly it added 2 to the source pixel pointer instead of 3.

Changed paths:
    graphics/conversion.cpp



diff --git a/graphics/conversion.cpp b/graphics/conversion.cpp
index 84f9bcb..db99679 100644
--- a/graphics/conversion.cpp
+++ b/graphics/conversion.cpp
@@ -96,7 +96,7 @@ bool crossBlit(byte *dst, const byte *src,
 			col++;
 #endif
 			for (uint y = 0; y < h; ++y) {
-				for (uint x = 0; x < w; ++x, src += 2, dst += 4) {
+				for (uint x = 0; x < w; ++x, src += 3, dst += 4) {
 					memcpy(col, src, 3);
 					srcFmt.colorToARGB(color, a, r, g, b);
 					color = dstFmt.ARGBToColor(a, r, g, b);


Commit: 0d78d46a0e82af81681727a94e01ff5f309887fa
    https://github.com/scummvm/scummvm/commit/0d78d46a0e82af81681727a94e01ff5f309887fa
Author: Johannes Schickel (lordhoto at scummvm.org)
Date: 2012-08-27T17:27:48-07:00

Commit Message:
GRAPHICS: Remove crossBlit's dstBpp >= srcBpp limitation.

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



diff --git a/graphics/conversion.cpp b/graphics/conversion.cpp
index db99679..ece1f75 100644
--- a/graphics/conversion.cpp
+++ b/graphics/conversion.cpp
@@ -22,6 +22,8 @@
 #include "graphics/conversion.h"
 #include "graphics/pixelformat.h"
 
+#include "common/endian.h"
+
 namespace Graphics {
 
 // TODO: YUV to RGB conversion function
@@ -47,6 +49,30 @@ FORCEINLINE void crossBlitLogic(byte *dst, const byte *src, const uint w, const
 	}
 }
 
+template<typename DstColor>
+FORCEINLINE 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) {
+	uint32 color;
+	byte r, g, b, a;
+	uint8 *col = (uint8 *)&color;
+#ifdef SCUMM_BIG_ENDIAN
+	col++;
+#endif
+	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);
+			color = dstFmt.ARGBToColor(a, r, g, b);
+			*(DstColor *)dst = color;
+			src += 3;
+			dst += sizeof(DstColor);
+		}
+		src += srcDelta;
+		dst += dstDelta;
+	}
+}
+
 } // End of anonymous namespace
 
 // Function to blit a rect from one color format to another
@@ -57,8 +83,7 @@ bool crossBlit(byte *dst, const byte *src,
 	// Error out if conversion is impossible
 	if ((srcFmt.bytesPerPixel == 1) || (dstFmt.bytesPerPixel == 1)
 			 || (dstFmt.bytesPerPixel == 3)
-			 || (!srcFmt.bytesPerPixel) || (!dstFmt.bytesPerPixel)
-			 || (srcFmt.bytesPerPixel > dstFmt.bytesPerPixel))
+			 || (!srcFmt.bytesPerPixel) || (!dstFmt.bytesPerPixel))
 		return false;
 
 	// Don't perform unnecessary conversion
@@ -84,27 +109,18 @@ bool crossBlit(byte *dst, const byte *src,
 
 	// TODO: optimized cases for dstDelta of 0
 	if (dstFmt.bytesPerPixel == 2) {
-		crossBlitLogic<uint16, uint16>(dst, src, w, h, srcFmt, dstFmt, srcDelta, dstDelta);
+		if (srcFmt.bytesPerPixel == 2) {
+			crossBlitLogic<uint16, uint16>(dst, src, w, h, srcFmt, dstFmt, srcDelta, dstDelta);
+		} else if (srcFmt.bytesPerPixel == 3) {
+			crossBlitLogic3BppSource<uint16>(dst, src, w, h, srcFmt, dstFmt, srcDelta, dstDelta);
+		} else {
+			crossBlitLogic<uint32, uint16>(dst, src, w, h, srcFmt, dstFmt, srcDelta, dstDelta);
+		}
 	} else if (dstFmt.bytesPerPixel == 4) {
 		if (srcFmt.bytesPerPixel == 2) {
 			crossBlitLogic<uint16, uint32>(dst, src, w, h, srcFmt, dstFmt, srcDelta, dstDelta);
 		} else if (srcFmt.bytesPerPixel == 3) {
-			uint32 color;
-			byte r, g, b, a;
-			uint8 *col = (uint8 *)&color;
-#ifdef SCUMM_BIG_ENDIAN
-			col++;
-#endif
-			for (uint y = 0; y < h; ++y) {
-				for (uint x = 0; x < w; ++x, src += 3, dst += 4) {
-					memcpy(col, src, 3);
-					srcFmt.colorToARGB(color, a, r, g, b);
-					color = dstFmt.ARGBToColor(a, r, g, b);
-					*(uint32 *)dst = color;
-				}
-				src += srcDelta;
-				dst += dstDelta;
-			}
+			crossBlitLogic3BppSource<uint32>(dst, src, w, h, srcFmt, dstFmt, srcDelta, dstDelta);
 		} else {
 			crossBlitLogic<uint32, uint32>(dst, src, w, h, srcFmt, dstFmt, srcDelta, dstDelta);
 		}
diff --git a/graphics/conversion.h b/graphics/conversion.h
index 8fcb6ba..0dce3cf 100644
--- a/graphics/conversion.h
+++ b/graphics/conversion.h
@@ -60,9 +60,6 @@ inline static void RGB2YUV(byte r, byte g, byte b, byte &y, byte &u, byte &v) {
  *					false if there is an error.
  *
  * @note Blitting to a 3Bpp destination is not supported
- * @note This implementation currently arbitrarily requires that the
- *		 destination's format have at least as high a bytedepth as
- *		 the source's.
  * @note This can convert a rectangle in place, if the source and
  *		 destination format have the same bytedepth.
  *


Commit: a92a509ac844fdad796748848d1143b27547173f
    https://github.com/scummvm/scummvm/commit/a92a509ac844fdad796748848d1143b27547173f
Author: Johannes Schickel (lordhoto at scummvm.org)
Date: 2012-08-27T17:27:48-07:00

Commit Message:
GRAPHICS: Allow in-place conversion with any color formats in crossBlit.

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



diff --git a/graphics/conversion.cpp b/graphics/conversion.cpp
index ece1f75..27a44f4 100644
--- a/graphics/conversion.cpp
+++ b/graphics/conversion.cpp
@@ -30,7 +30,7 @@ namespace Graphics {
 
 namespace {
 
-template<typename SrcColor, typename DstColor>
+template<typename SrcColor, typename DstColor, bool backward>
 FORCEINLINE 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) {
@@ -41,15 +41,27 @@ FORCEINLINE void crossBlitLogic(byte *dst, const byte *src, const uint w, const
 			srcFmt.colorToARGB(color, a, r, g, b);
 			color = dstFmt.ARGBToColor(a, r, g, b);
 			*(DstColor *)dst = color;
-			src += sizeof(SrcColor);
-			dst += sizeof(DstColor);
+
+			if (backward) {
+				src -= sizeof(SrcColor);
+				dst -= sizeof(DstColor);
+			} else {
+				src += sizeof(SrcColor);
+				dst += sizeof(DstColor);
+			}
+		}
+
+		if (backward) {
+			src -= srcDelta;
+			dst -= dstDelta;
+		} else {
+			src += srcDelta;
+			dst += dstDelta;
 		}
-		src += srcDelta;
-		dst += dstDelta;
 	}
 }
 
-template<typename DstColor>
+template<typename DstColor, bool backward>
 FORCEINLINE 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) {
@@ -65,11 +77,23 @@ FORCEINLINE void crossBlitLogic3BppSource(byte *dst, const byte *src, const uint
 			srcFmt.colorToARGB(color, a, r, g, b);
 			color = dstFmt.ARGBToColor(a, r, g, b);
 			*(DstColor *)dst = color;
-			src += 3;
-			dst += sizeof(DstColor);
+
+			if (backward) {
+				src -= 3;
+				dst -= sizeof(DstColor);
+			} else {
+				src += 3;
+				dst += sizeof(DstColor);
+			}
+		}
+
+		if (backward) {
+			src -= srcDelta;
+			dst -= dstDelta;
+		} else {
+			src += srcDelta;
+			dst += dstDelta;
 		}
-		src += srcDelta;
-		dst += dstDelta;
 	}
 }
 
@@ -110,19 +134,33 @@ 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>(dst, src, w, h, srcFmt, dstFmt, srcDelta, dstDelta);
+			crossBlitLogic<uint16, uint16, false>(dst, src, w, h, srcFmt, dstFmt, srcDelta, dstDelta);
 		} else if (srcFmt.bytesPerPixel == 3) {
-			crossBlitLogic3BppSource<uint16>(dst, src, w, h, srcFmt, dstFmt, srcDelta, dstDelta);
+			crossBlitLogic3BppSource<uint16, false>(dst, src, w, h, srcFmt, dstFmt, srcDelta, dstDelta);
 		} else {
-			crossBlitLogic<uint32, uint16>(dst, src, w, h, srcFmt, dstFmt, srcDelta, dstDelta);
+			crossBlitLogic<uint32, uint16, false>(dst, src, w, h, srcFmt, dstFmt, srcDelta, dstDelta);
 		}
 	} else if (dstFmt.bytesPerPixel == 4) {
 		if (srcFmt.bytesPerPixel == 2) {
-			crossBlitLogic<uint16, uint32>(dst, src, w, h, srcFmt, dstFmt, srcDelta, dstDelta);
+			// 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>(dst, src, w, h, srcFmt, dstFmt, srcDelta, dstDelta);
 		} else if (srcFmt.bytesPerPixel == 3) {
-			crossBlitLogic3BppSource<uint32>(dst, src, w, h, srcFmt, dstFmt, srcDelta, dstDelta);
+			// 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>(dst, src, w, h, srcFmt, dstFmt, srcDelta, dstDelta);
 		} else {
-			crossBlitLogic<uint32, uint32>(dst, src, w, h, srcFmt, dstFmt, srcDelta, dstDelta);
+			crossBlitLogic<uint32, uint32, false>(dst, src, w, h, srcFmt, dstFmt, srcDelta, dstDelta);
 		}
 	} else {
 		return false;
diff --git a/graphics/conversion.h b/graphics/conversion.h
index 0dce3cf..28e64a9 100644
--- a/graphics/conversion.h
+++ b/graphics/conversion.h
@@ -60,9 +60,12 @@ inline static void RGB2YUV(byte r, byte g, byte b, byte &y, byte &u, byte &v) {
  *					false if there is an error.
  *
  * @note Blitting to a 3Bpp destination is not supported
- * @note This can convert a rectangle in place, if the source and
- *		 destination format have the same bytedepth.
- *
+ * @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 crossBlit(byte *dst, const byte *src,
                const uint dstPitch, const uint srcPitch,


Commit: e8cf0adf95217d4eedec526df960a8cdd46cc28f
    https://github.com/scummvm/scummvm/commit/e8cf0adf95217d4eedec526df960a8cdd46cc28f
Author: Johannes Schickel (lordhoto at scummvm.org)
Date: 2012-08-27T17:27:48-07:00

Commit Message:
GRAPHICS: Slight cleanup in crossBlit code.

Changed paths:
    graphics/conversion.cpp



diff --git a/graphics/conversion.cpp b/graphics/conversion.cpp
index 27a44f4..fec1d24 100644
--- a/graphics/conversion.cpp
+++ b/graphics/conversion.cpp
@@ -36,11 +36,10 @@ FORCEINLINE void crossBlitLogic(byte *dst, const byte *src, const uint w, const
                               const uint srcDelta, const uint dstDelta) {
 	for (uint y = 0; y < h; ++y) {
 		for (uint x = 0; x < w; ++x) {
-			uint32 color = *(const SrcColor *)src;
+			const uint32 color = *(const SrcColor *)src;
 			byte a, r, g, b;
 			srcFmt.colorToARGB(color, a, r, g, b);
-			color = dstFmt.ARGBToColor(a, r, g, b);
-			*(DstColor *)dst = color;
+			*(DstColor *)dst = dstFmt.ARGBToColor(a, r, g, b);
 
 			if (backward) {
 				src -= sizeof(SrcColor);
@@ -75,8 +74,7 @@ FORCEINLINE void crossBlitLogic3BppSource(byte *dst, const byte *src, const uint
 		for (uint x = 0; x < w; ++x) {
 			memcpy(col, src, 3);
 			srcFmt.colorToARGB(color, a, r, g, b);
-			color = dstFmt.ARGBToColor(a, r, g, b);
-			*(DstColor *)dst = color;
+			*(DstColor *)dst = dstFmt.ARGBToColor(a, r, g, b);
 
 			if (backward) {
 				src -= 3;


Commit: eeb39592599815875a736fdbef67204c2036e935
    https://github.com/scummvm/scummvm/commit/eeb39592599815875a736fdbef67204c2036e935
Author: Johannes Schickel (lordhoto at scummvm.org)
Date: 2012-08-27T17:27:48-07:00

Commit Message:
GRAPHICS: Add an in-place Surface PixelFormat conversion.

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



diff --git a/graphics/surface.cpp b/graphics/surface.cpp
index c0f1046..1604eaa 100644
--- a/graphics/surface.cpp
+++ b/graphics/surface.cpp
@@ -26,6 +26,7 @@
 #include "common/textconsole.h"
 #include "graphics/primitives.h"
 #include "graphics/surface.h"
+#include "graphics/conversion.h"
 
 namespace Graphics {
 
@@ -271,6 +272,72 @@ void Surface::move(int dx, int dy, int height) {
 	}
 }
 
+void Surface::convertToInPlace(const PixelFormat &dstFormat, const byte *palette) {
+	// Do not convert to the same format and ignore empty surfaces.
+	if (format == dstFormat || pixels == 0) {
+		return;
+	}
+
+	if (format.bytesPerPixel == 0 || format.bytesPerPixel > 4)
+		error("Surface::convertToInPlace(): Can only convert from 1Bpp, 2Bpp, 3Bpp, and 4Bpp");
+
+	if (dstFormat.bytesPerPixel != 2 && dstFormat.bytesPerPixel != 4)
+		error("Surface::convertToInPlace(): Can only convert to 2Bpp and 4Bpp");
+
+	// In case the surface data needs more space allocate it.
+	if (dstFormat.bytesPerPixel > format.bytesPerPixel) {
+		void *const newPixels = realloc(pixels, w * h * dstFormat.bytesPerPixel);
+		if (!newPixels) {
+			error("Surface::convertToInPlace(): Out of memory");
+		}
+		pixels = newPixels;
+	}
+
+	// We take advantage of the fact that pitch is always w * format.bytesPerPixel.
+	// This is assured by the logic of Surface::create.
+
+	// We need to handle 1 Bpp surfaces special here.
+	if (format.bytesPerPixel == 1) {
+		assert(palette);
+
+		for (int y = h; y > 0; --y) {
+			const byte *srcRow = (const byte *)pixels + y * pitch - 1;
+			byte *dstRow = (byte *)pixels + y * w * dstFormat.bytesPerPixel - dstFormat.bytesPerPixel;
+
+			for (int x = 0; x < w; x++) {
+				byte index = *srcRow--;
+				byte r = palette[index * 3];
+				byte g = palette[index * 3 + 1];
+				byte b = palette[index * 3 + 2];
+
+				uint32 color = dstFormat.RGBToColor(r, g, b);
+
+				if (dstFormat.bytesPerPixel == 2)
+					*((uint16 *)dstRow) = color;
+				else
+					*((uint32 *)dstRow) = color;
+
+				dstRow -= dstFormat.bytesPerPixel;
+			}
+		}
+	} else {
+		crossBlit((byte *)pixels, (const byte *)pixels, w * dstFormat.bytesPerPixel, pitch, w, h, dstFormat, format);
+	}
+
+	// In case the surface data got smaller, free up some memory.
+	if (dstFormat.bytesPerPixel < format.bytesPerPixel) {
+		void *const newPixels = realloc(pixels, w * h * dstFormat.bytesPerPixel);
+		if (!newPixels) {
+			error("Surface::convertToInPlace(): Freeing memory failed");
+		}
+		pixels = newPixels;
+	}
+
+	// Update the surface specific data.
+	format = dstFormat;
+	pitch = w * dstFormat.bytesPerPixel;
+}
+
 Graphics::Surface *Surface::convertTo(const PixelFormat &dstFormat, const byte *palette) const {
 	assert(pixels);
 
diff --git a/graphics/surface.h b/graphics/surface.h
index eb8d1ac..eaf62f8 100644
--- a/graphics/surface.h
+++ b/graphics/surface.h
@@ -137,6 +137,20 @@ struct Surface {
 	/**
 	 * Convert the data to another pixel format.
 	 *
+	 * This works in-place. This means it will not create an additional buffer
+	 * for the conversion process. The value of pixels might change though.
+	 *
+	 * Note that you should only use this, when you created the Surface data via
+	 * create! Otherwise this function has undefined behavior.
+	 *
+	 * @param dstFormat The desired format
+	 * @param palette   The palette (in RGB888), if the source format has a Bpp of 1
+	 */
+	void convertToInPlace(const PixelFormat &dstFormat, const byte *palette = 0);
+
+	/**
+	 * Convert the data to another pixel format.
+	 *
 	 * The calling code must call free on the returned surface and then delete
 	 * it.
 	 *


Commit: a1e56adad8eb8ed4c8de5850fb2c81af9adb9585
    https://github.com/scummvm/scummvm/commit/a1e56adad8eb8ed4c8de5850fb2c81af9adb9585
Author: Johannes Schickel (lordhoto at scummvm.org)
Date: 2012-08-27T17:28:17-07:00

Commit Message:
GUI: Use in-place Surface conversion in widget code.

Changed paths:
    gui/widget.cpp
    gui/widget.h



diff --git a/gui/widget.cpp b/gui/widget.cpp
index 9046bcc..c5ca628 100644
--- a/gui/widget.cpp
+++ b/gui/widget.cpp
@@ -376,7 +376,7 @@ void ButtonWidget::wantTickle(bool tickled) {
 
 PicButtonWidget::PicButtonWidget(GuiObject *boss, int x, int y, int w, int h, const char *tooltip, uint32 cmd, uint8 hotkey)
 	: ButtonWidget(boss, x, y, w, h, "", tooltip, cmd, hotkey),
-	  _gfx(new Graphics::Surface()), _alpha(256), _transparency(false) {
+	  _gfx(), _alpha(256), _transparency(false) {
 
 	setFlags(WIDGET_ENABLED/* | WIDGET_BORDER*/ | WIDGET_CLEARBG);
 	_type = kButtonWidget;
@@ -384,18 +384,17 @@ PicButtonWidget::PicButtonWidget(GuiObject *boss, int x, int y, int w, int h, co
 
 PicButtonWidget::PicButtonWidget(GuiObject *boss, const Common::String &name, const char *tooltip, uint32 cmd, uint8 hotkey)
 	: ButtonWidget(boss, name, "", tooltip, cmd, hotkey),
-	  _gfx(new Graphics::Surface()), _alpha(256), _transparency(false) {
+	  _gfx(), _alpha(256), _transparency(false) {
 	setFlags(WIDGET_ENABLED/* | WIDGET_BORDER*/ | WIDGET_CLEARBG);
 	_type = kButtonWidget;
 }
 
 PicButtonWidget::~PicButtonWidget() {
-	_gfx->free();
-	delete _gfx;
+	_gfx.free();
 }
 
 void PicButtonWidget::setGfx(const Graphics::Surface *gfx) {
-	_gfx->free();
+	_gfx.free();
 
 	if (!gfx || !gfx->pixels)
 		return;
@@ -411,7 +410,7 @@ void PicButtonWidget::setGfx(const Graphics::Surface *gfx) {
 		return;
 	}
 
-	_gfx->copyFrom(*gfx);
+	_gfx.copyFrom(*gfx);
 }
 
 void PicButtonWidget::setGfx(int w, int h, int r, int g, int b) {
@@ -422,29 +421,26 @@ void PicButtonWidget::setGfx(int w, int h, int r, int g, int b) {
 
 	const Graphics::PixelFormat &requiredFormat = g_gui.theme()->getPixelFormat();
 
-	_gfx->free();
-	_gfx->create(w, h, requiredFormat);
-	_gfx->fillRect(Common::Rect(0, 0, w, h), _gfx->format.RGBToColor(r, g, b));
+	_gfx.free();
+	_gfx.create(w, h, requiredFormat);
+	_gfx.fillRect(Common::Rect(0, 0, w, h), _gfx.format.RGBToColor(r, g, b));
 }
 
 void PicButtonWidget::drawWidget() {
 	g_gui.theme()->drawButton(Common::Rect(_x, _y, _x+_w, _y+_h), "", _state, getFlags());
 
-	if (_gfx->pixels) {
+	if (_gfx.pixels) {
 		// Check whether the set up surface needs to be converted to the GUI
 		// color format.
 		const Graphics::PixelFormat &requiredFormat = g_gui.theme()->getPixelFormat();
-		if (_gfx->format != requiredFormat) {
-			Graphics::Surface *converted = _gfx->convertTo(requiredFormat);
-			_gfx->free();
-			delete _gfx;
-			_gfx = converted;
+		if (_gfx.format != requiredFormat) {
+			_gfx.convertToInPlace(requiredFormat);
 		}
 
-		const int x = _x + (_w - _gfx->w) / 2;
-		const int y = _y + (_h - _gfx->h) / 2;
+		const int x = _x + (_w - _gfx.w) / 2;
+		const int y = _y + (_h - _gfx.h) / 2;
 
-		g_gui.theme()->drawSurface(Common::Rect(x, y, x + _gfx->w,  y + _gfx->h), *_gfx, _state, _alpha, _transparency);
+		g_gui.theme()->drawSurface(Common::Rect(x, y, x + _gfx.w,  y + _gfx.h), _gfx, _state, _alpha, _transparency);
 	}
 }
 
@@ -632,24 +628,23 @@ int SliderWidget::posToValue(int pos) {
 #pragma mark -
 
 GraphicsWidget::GraphicsWidget(GuiObject *boss, int x, int y, int w, int h, const char *tooltip)
-	: Widget(boss, x, y, w, h, tooltip), _gfx(new Graphics::Surface()), _alpha(256), _transparency(false) {
+	: Widget(boss, x, y, w, h, tooltip), _gfx(), _alpha(256), _transparency(false) {
 	setFlags(WIDGET_ENABLED | WIDGET_CLEARBG);
 	_type = kGraphicsWidget;
 }
 
 GraphicsWidget::GraphicsWidget(GuiObject *boss, const Common::String &name, const char *tooltip)
-	: Widget(boss, name, tooltip), _gfx(new Graphics::Surface()), _alpha(256), _transparency(false) {
+	: Widget(boss, name, tooltip), _gfx(), _alpha(256), _transparency(false) {
 	setFlags(WIDGET_ENABLED | WIDGET_CLEARBG);
 	_type = kGraphicsWidget;
 }
 
 GraphicsWidget::~GraphicsWidget() {
-	_gfx->free();
-	delete _gfx;
+	_gfx.free();
 }
 
 void GraphicsWidget::setGfx(const Graphics::Surface *gfx) {
-	_gfx->free();
+	_gfx.free();
 
 	if (!gfx || !gfx->pixels)
 		return;
@@ -664,7 +659,7 @@ void GraphicsWidget::setGfx(const Graphics::Surface *gfx) {
 		return;
 	}
 
-	_gfx->copyFrom(*gfx);
+	_gfx.copyFrom(*gfx);
 }
 
 void GraphicsWidget::setGfx(int w, int h, int r, int g, int b) {
@@ -675,27 +670,24 @@ void GraphicsWidget::setGfx(int w, int h, int r, int g, int b) {
 
 	const Graphics::PixelFormat &requiredFormat = g_gui.theme()->getPixelFormat();
 
-	_gfx->free();
-	_gfx->create(w, h, requiredFormat);
-	_gfx->fillRect(Common::Rect(0, 0, w, h), _gfx->format.RGBToColor(r, g, b));
+	_gfx.free();
+	_gfx.create(w, h, requiredFormat);
+	_gfx.fillRect(Common::Rect(0, 0, w, h), _gfx.format.RGBToColor(r, g, b));
 }
 
 void GraphicsWidget::drawWidget() {
-	if (_gfx->pixels) {
+	if (_gfx.pixels) {
 		// Check whether the set up surface needs to be converted to the GUI
 		// color format.
 		const Graphics::PixelFormat &requiredFormat = g_gui.theme()->getPixelFormat();
-		if (_gfx->format != requiredFormat) {
-			Graphics::Surface *converted = _gfx->convertTo(requiredFormat);
-			_gfx->free();
-			delete _gfx;
-			_gfx = converted;
+		if (_gfx.format != requiredFormat) {
+			_gfx.convertToInPlace(requiredFormat);
 		}
 
-		const int x = _x + (_w - _gfx->w) / 2;
-		const int y = _y + (_h - _gfx->h) / 2;
+		const int x = _x + (_w - _gfx.w) / 2;
+		const int y = _y + (_h - _gfx.h) / 2;
 
-		g_gui.theme()->drawSurface(Common::Rect(x, y, x + _gfx->w,  y + _gfx->h), *_gfx, _state, _alpha, _transparency);
+		g_gui.theme()->drawSurface(Common::Rect(x, y, x + _gfx.w,  y + _gfx.h), _gfx, _state, _alpha, _transparency);
 	}
 }
 
diff --git a/gui/widget.h b/gui/widget.h
index 6f710f3..e3f7125 100644
--- a/gui/widget.h
+++ b/gui/widget.h
@@ -230,7 +230,7 @@ public:
 protected:
 	void drawWidget();
 
-	Graphics::Surface *_gfx;
+	Graphics::Surface _gfx;
 	int _alpha;
 	bool _transparency;
 };
@@ -358,7 +358,7 @@ public:
 protected:
 	void drawWidget();
 
-	Graphics::Surface *_gfx;
+	Graphics::Surface _gfx;
 	int _alpha;
 	bool _transparency;
 };


Commit: c2971374cdb189dbf9f72953a970d0769648e5ae
    https://github.com/scummvm/scummvm/commit/c2971374cdb189dbf9f72953a970d0769648e5ae
Author: Johannes Schickel (lordhoto at gmail.com)
Date: 2012-10-08T14:18:33-07:00

Commit Message:
Merge pull request #257 from lordhoto/graphics-conversion

Extend crossBlit for abitrary (in-place) conversions and add a in-place conversion to Surface

Changed paths:
    graphics/conversion.cpp
    graphics/conversion.h
    graphics/surface.cpp
    graphics/surface.h
    gui/widget.cpp
    gui/widget.h









More information about the Scummvm-git-logs mailing list