diff options
author | Johannes Schickel | 2012-07-14 05:35:20 +0200 |
---|---|---|
committer | Johannes Schickel | 2012-08-28 02:27:48 +0200 |
commit | a92a509ac844fdad796748848d1143b27547173f (patch) | |
tree | 6f467d1cf704cc08f401414fce177addb30ec352 /graphics | |
parent | 0d78d46a0e82af81681727a94e01ff5f309887fa (diff) | |
download | scummvm-rg350-a92a509ac844fdad796748848d1143b27547173f.tar.gz scummvm-rg350-a92a509ac844fdad796748848d1143b27547173f.tar.bz2 scummvm-rg350-a92a509ac844fdad796748848d1143b27547173f.zip |
GRAPHICS: Allow in-place conversion with any color formats in crossBlit.
Diffstat (limited to 'graphics')
-rw-r--r-- | graphics/conversion.cpp | 70 | ||||
-rw-r--r-- | graphics/conversion.h | 9 |
2 files changed, 60 insertions, 19 deletions
diff --git a/graphics/conversion.cpp b/graphics/conversion.cpp index ece1f759d9..27a44f4ed5 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 0dce3cf279..28e64a94fb 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, |