[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