diff --git a/graphics/blit/blit-scale.cpp b/graphics/blit/blit-scale.cpp index d5ee3f60deb..0b8aa799920 100644 --- a/graphics/blit/blit-scale.cpp +++ b/graphics/blit/blit-scale.cpp @@ -28,6 +28,7 @@ #include "graphics/pixelformat.h" #include "graphics/transform_struct.h" +#include "common/endian.h" #include "common/rect.h" #include "math/utils.h" @@ -57,7 +58,7 @@ static void scaleVertical(byte *dst, const byte *src, } } -template +template static void scaleNN(byte *dst, const byte *src, const uint dstPitch, const uint srcPitch, const uint dstW, const uint dstH, @@ -74,7 +75,7 @@ static void scaleNN(byte *dst, const byte *src, const int dstIncY = (flipy ? -static_cast(dstPitch) : static_cast(dstPitch)); if (flipx) { - dst += (dstW - 1) * sizeof(Size); + dst += (dstW - 1) * Size; } if (flipy) { @@ -82,12 +83,16 @@ static void scaleNN(byte *dst, const byte *src, } for (uint32 y = 0, yoff = 0; y < dstH; y++, yoff += srcIncY) { - const Size *srcP = (const Size *)(src + ((yoff >> 16) * srcPitch)); - Size *dst1 = (Size *)dst; + const byte *srcP = src + ((yoff >> 16) * srcPitch); + byte *dst1 = dst; for (uint32 x = 0, xoff = 0; x < dstW; x++, xoff += srcIncX) { - Size val = srcP[xoff >> 16]; - *dst1 = val; - dst1 += dstIncX; + const byte *src1 = srcP + ((xoff >> 16) * Size); + if (Size == sizeof(Color)) { + *(Color *)dst1 = *(const Color *)src1; + } else { + memcpy(dst1, src, Size); + } + dst1 += dstIncX * Size; } dst += dstIncY; } @@ -115,13 +120,16 @@ bool scaleBlit(byte *dst, const byte *src, switch (fmt.bytesPerPixel) { case 1: - scaleNN(dst, src, dstPitch, srcPitch, dstW, dstH, srcW, srcH, flip); + scaleNN(dst, src, dstPitch, srcPitch, dstW, dstH, srcW, srcH, flip); return true; case 2: - scaleNN(dst, src, dstPitch, srcPitch, dstW, dstH, srcW, srcH, flip); + scaleNN(dst, src, dstPitch, srcPitch, dstW, dstH, srcW, srcH, flip); + return true; + case 3: + scaleNN(dst, src, dstPitch, srcPitch, dstW, dstH, srcW, srcH, flip); return true; case 4: - scaleNN(dst, src, dstPitch, srcPitch, dstW, dstH, srcW, srcH, flip); + scaleNN(dst, src, dstPitch, srcPitch, dstW, dstH, srcW, srcH, flip); return true; default: break; @@ -172,35 +180,53 @@ systems and pixel formats. namespace { +template +inline uint32 getPixel(const byte *sp) { + if (Size == sizeof(Color)) { + return *(const Color *)sp; + } else { + return READ_UINT24(sp); + } +} + +template +inline void setPixel(byte *pc, const uint32 pix) { + if (Size == sizeof(Color)) { + *(Color *)pc = pix; + } else { + WRITE_UINT24(pc, pix); + } +} + inline byte scaleBlitBilinearInterpolate(byte c01, byte c00, byte c11, byte c10, int ex, int ey) { int t1 = ((((c01 - c00) * ex) >> 16) + c00) & 0xff; int t2 = ((((c11 - c10) * ex) >> 16) + c10) & 0xff; return (((t2 - t1) * ey) >> 16) + t1; } -template -Size scaleBlitBilinearInterpolate(Size c01, Size c00, Size c11, Size c10, int ex, int ey, +template +void scaleBlitBilinearInterpolate(byte *dp, const byte *c01, const byte *c00, const byte *c11, const byte *c10, int ex, int ey, const Graphics::PixelFormat &fmt) { byte c01_a, c01_r, c01_g, c01_b; - fmt.colorToARGBT(c01, c01_a, c01_r, c01_g, c01_b); + fmt.colorToARGBT(getPixel(c01), c01_a, c01_r, c01_g, c01_b); byte c00_a, c00_r, c00_g, c00_b; - fmt.colorToARGBT(c00, c00_a, c00_r, c00_g, c00_b); + fmt.colorToARGBT(getPixel(c00), c00_a, c00_r, c00_g, c00_b); byte c11_a, c11_r, c11_g, c11_b; - fmt.colorToARGBT(c11, c11_a, c11_r, c11_g, c11_b); + fmt.colorToARGBT(getPixel(c11), c11_a, c11_r, c11_g, c11_b); byte c10_a, c10_r, c10_g, c10_b; - fmt.colorToARGBT(c10, c10_a, c10_r, c10_g, c10_b); + fmt.colorToARGBT(getPixel(c10), c10_a, c10_r, c10_g, c10_b); byte dp_a = scaleBlitBilinearInterpolate(c01_a, c00_a, c11_a, c10_a, ex, ey); byte dp_r = scaleBlitBilinearInterpolate(c01_r, c00_r, c11_r, c10_r, ex, ey); byte dp_g = scaleBlitBilinearInterpolate(c01_g, c00_g, c11_g, c10_g, ex, ey); byte dp_b = scaleBlitBilinearInterpolate(c01_b, c00_b, c11_b, c10_b, ex, ey); - return fmt.ARGBToColorT(dp_a, dp_r, dp_g, dp_b); + setPixel(dp, fmt.ARGBToColorT(dp_a, dp_r, dp_g, dp_b)); } -template +template void scaleBlitBilinearLogic(byte *dst, const byte *src, const uint dstPitch, const uint srcPitch, const uint dstW, const uint dstH, @@ -216,7 +242,7 @@ void scaleBlitBilinearLogic(byte *dst, const byte *src, const byte *sp = src; if (flipx) { - sp += spixelw * sizeof(Size); + sp += spixelw * Size; } if (flipy) { sp += srcPitch * spixelh; @@ -224,7 +250,7 @@ void scaleBlitBilinearLogic(byte *dst, const byte *src, int *csay = say; for (uint y = 0; y < dstH; y++) { - Size *dp = (Size *)(dst + (dstPitch * y)); + byte *dp = dst + (dstPitch * y); const byte *csp = sp; int *csax = sax; for (uint x = 0; x < dstW; x++) { @@ -248,18 +274,19 @@ void scaleBlitBilinearLogic(byte *dst, const byte *src, c11 = c10; if (cx < spixelw) { if (flipx) { - c01 -= sizeof(Size); - c11 -= sizeof(Size); + c01 -= Size; + c11 -= Size; } else { - c01 += sizeof(Size); - c11 += sizeof(Size); + c01 += Size; + c11 += Size; } } /* * Draw and interpolate colors */ - *dp = scaleBlitBilinearInterpolate(*(const Size *)c01, *(const Size *)c00, *(const Size *)c11, *(const Size *)c10, ex, ey, fmt); + scaleBlitBilinearInterpolate(dp, c01, c00, c11, c10, ex, ey, fmt); + /* * Advance source pointer x */ @@ -267,15 +294,15 @@ void scaleBlitBilinearLogic(byte *dst, const byte *src, csax++; int sstepx = (*csax >> 16) - (*salastx >> 16); if (flipx) { - sp -= sstepx * sizeof(Size); + sp -= sstepx * Size; } else { - sp += sstepx * sizeof(Size); + sp += sstepx * Size; } /* * Advance destination pointer x */ - dp++; + dp += Size; } /* * Advance source pointer y @@ -292,7 +319,7 @@ void scaleBlitBilinearLogic(byte *dst, const byte *src, } } -template +template void rotoscaleBlitLogic(byte *dst, const byte *src, const uint dstPitch, const uint srcPitch, const uint dstW, const uint dstH, @@ -329,7 +356,7 @@ void rotoscaleBlitLogic(byte *dst, const byte *src, int sw = srcW - 1; int sh = srcH - 1; - Size *pc = (Size *)dst; + byte *pc = dst; for (uint y = 0; y < dstH; y++) { int t = cy - y; @@ -347,15 +374,15 @@ void rotoscaleBlitLogic(byte *dst, const byte *src, if (filtering) { if ((dx > -1) && (dy > -1) && (dx < sw) && (dy < sh)) { - const byte *sp = src + dy * srcPitch + dx * sizeof(Size); - Size c00, c01, c10, c11; - c00 = *(const Size *)sp; - sp += sizeof(Size); - c01 = *(const Size *)sp; + const byte *sp = src + dy * srcPitch + dx * Size; + const byte *c00, *c01, *c10, *c11; + c00 = sp; + sp += Size; + c01 = sp; sp += srcPitch; - c11 = *(const Size *)sp; - sp -= sizeof(Size); - c10 = *(const Size *)sp; + c11 = sp; + sp -= Size; + c10 = sp; if (flipx) { SWAP(c00, c01); SWAP(c10, c11); @@ -369,17 +396,21 @@ void rotoscaleBlitLogic(byte *dst, const byte *src, */ int ex = (sdx & 0xffff); int ey = (sdy & 0xffff); - *pc = scaleBlitBilinearInterpolate(c01, c00, c11, c10, ex, ey, fmt); + scaleBlitBilinearInterpolate(pc, c01, c00, c11, c10, ex, ey, fmt); } } else { if ((dx >= 0) && (dy >= 0) && (dx < (int)srcW) && (dy < (int)srcH)) { - const byte *sp = src + dy * srcPitch + dx * sizeof(Size); - *pc = *(const Size *)sp; + const byte *sp = src + dy * srcPitch + dx * Size; + if (Size == sizeof(Color)) { + *(Color *)pc = *(const Color *)sp; + } else { + memcpy(pc, sp, Size); + } } } sdx += icosx; sdy += isiny; - pc++; + pc += Size; } } } @@ -392,7 +423,7 @@ bool scaleBlitBilinear(byte *dst, const byte *src, const uint srcW, const uint srcH, const Graphics::PixelFormat &fmt, const byte flip) { - if (fmt.bytesPerPixel != 2 && fmt.bytesPerPixel != 4) + if (fmt.bytesPerPixel != 2 && fmt.bytesPerPixel != 3 && fmt.bytesPerPixel != 4) return false; int *sax = new int[dstW + 1]; @@ -440,18 +471,20 @@ bool scaleBlitBilinear(byte *dst, const byte *src, } if (fmt == createPixelFormat<8888>()) { - scaleBlitBilinearLogic, uint32>(dst, src, dstPitch, srcPitch, dstW, dstH, srcW, srcH, fmt, sax, say, flip); + scaleBlitBilinearLogic, uint32, 4>(dst, src, dstPitch, srcPitch, dstW, dstH, srcW, srcH, fmt, sax, say, flip); } else if (fmt == createPixelFormat<888>()) { - scaleBlitBilinearLogic, uint32>(dst, src, dstPitch, srcPitch, dstW, dstH, srcW, srcH, fmt, sax, say, flip); + scaleBlitBilinearLogic, uint32, 4>(dst, src, dstPitch, srcPitch, dstW, dstH, srcW, srcH, fmt, sax, say, flip); } else if (fmt == createPixelFormat<565>()) { - scaleBlitBilinearLogic, uint16>(dst, src, dstPitch, srcPitch, dstW, dstH, srcW, srcH, fmt, sax, say, flip); + scaleBlitBilinearLogic, uint16, 2>(dst, src, dstPitch, srcPitch, dstW, dstH, srcW, srcH, fmt, sax, say, flip); } else if (fmt == createPixelFormat<555>()) { - scaleBlitBilinearLogic, uint16>(dst, src, dstPitch, srcPitch, dstW, dstH, srcW, srcH, fmt, sax, say, flip); + scaleBlitBilinearLogic, uint16, 2>(dst, src, dstPitch, srcPitch, dstW, dstH, srcW, srcH, fmt, sax, say, flip); } else if (fmt.bytesPerPixel == 4) { - scaleBlitBilinearLogic, uint32>(dst, src, dstPitch, srcPitch, dstW, dstH, srcW, srcH, fmt, sax, say, flip); + scaleBlitBilinearLogic, uint32, 4>(dst, src, dstPitch, srcPitch, dstW, dstH, srcW, srcH, fmt, sax, say, flip); + } else if (fmt.bytesPerPixel == 3) { + scaleBlitBilinearLogic, uint8, 3>(dst, src, dstPitch, srcPitch, dstW, dstH, srcW, srcH, fmt, sax, say, flip); } else if (fmt.bytesPerPixel == 2) { - scaleBlitBilinearLogic, uint16>(dst, src, dstPitch, srcPitch, dstW, dstH, srcW, srcH, fmt, sax, say, flip); + scaleBlitBilinearLogic, uint16, 2>(dst, src, dstPitch, srcPitch, dstW, dstH, srcW, srcH, fmt, sax, say, flip); } else { delete[] sax; delete[] say; @@ -473,11 +506,13 @@ bool rotoscaleBlit(byte *dst, const byte *src, const TransformStruct &transform, const Common::Point &newHotspot) { if (fmt.bytesPerPixel == 4) { - rotoscaleBlitLogic, uint32, false>(dst, src, dstPitch, srcPitch, dstW, dstH, srcW, srcH, fmt, transform, newHotspot); + rotoscaleBlitLogic, uint32, 4, false>(dst, src, dstPitch, srcPitch, dstW, dstH, srcW, srcH, fmt, transform, newHotspot); + } else if (fmt.bytesPerPixel == 3) { + rotoscaleBlitLogic, uint8, 3, false>(dst, src, dstPitch, srcPitch, dstW, dstH, srcW, srcH, fmt, transform, newHotspot); } else if (fmt.bytesPerPixel == 2) { - rotoscaleBlitLogic, uint16, false>(dst, src, dstPitch, srcPitch, dstW, dstH, srcW, srcH, fmt, transform, newHotspot); + rotoscaleBlitLogic, uint16, 2, false>(dst, src, dstPitch, srcPitch, dstW, dstH, srcW, srcH, fmt, transform, newHotspot); } else if (fmt.bytesPerPixel == 1) { - rotoscaleBlitLogic, uint8, false>(dst, src, dstPitch, srcPitch, dstW, dstH, srcW, srcH, fmt, transform, newHotspot); + rotoscaleBlitLogic, uint8, 1, false>(dst, src, dstPitch, srcPitch, dstW, dstH, srcW, srcH, fmt, transform, newHotspot); } else { return false; } @@ -493,18 +528,20 @@ bool rotoscaleBlitBilinear(byte *dst, const byte *src, const TransformStruct &transform, const Common::Point &newHotspot) { if (fmt == createPixelFormat<8888>()) { - rotoscaleBlitLogic, uint32, true>(dst, src, dstPitch, srcPitch, dstW, dstH, srcW, srcH, fmt, transform, newHotspot); + rotoscaleBlitLogic, uint32, 4, true>(dst, src, dstPitch, srcPitch, dstW, dstH, srcW, srcH, fmt, transform, newHotspot); } else if (fmt == createPixelFormat<888>()) { - rotoscaleBlitLogic, uint32, true>(dst, src, dstPitch, srcPitch, dstW, dstH, srcW, srcH, fmt, transform, newHotspot); + rotoscaleBlitLogic, uint32, 4, true>(dst, src, dstPitch, srcPitch, dstW, dstH, srcW, srcH, fmt, transform, newHotspot); } else if (fmt == createPixelFormat<565>()) { - rotoscaleBlitLogic, uint16, true>(dst, src, dstPitch, srcPitch, dstW, dstH, srcW, srcH, fmt, transform, newHotspot); + rotoscaleBlitLogic, uint16, 2, true>(dst, src, dstPitch, srcPitch, dstW, dstH, srcW, srcH, fmt, transform, newHotspot); } else if (fmt == createPixelFormat<555>()) { - rotoscaleBlitLogic, uint16, true>(dst, src, dstPitch, srcPitch, dstW, dstH, srcW, srcH, fmt, transform, newHotspot); + rotoscaleBlitLogic, uint16, 2, true>(dst, src, dstPitch, srcPitch, dstW, dstH, srcW, srcH, fmt, transform, newHotspot); } else if (fmt.bytesPerPixel == 4) { - rotoscaleBlitLogic, uint32, true>(dst, src, dstPitch, srcPitch, dstW, dstH, srcW, srcH, fmt, transform, newHotspot); + rotoscaleBlitLogic, uint32, 4, true>(dst, src, dstPitch, srcPitch, dstW, dstH, srcW, srcH, fmt, transform, newHotspot); + } else if (fmt.bytesPerPixel == 3) { + rotoscaleBlitLogic, uint8, 3, true>(dst, src, dstPitch, srcPitch, dstW, dstH, srcW, srcH, fmt, transform, newHotspot); } else if (fmt.bytesPerPixel == 2) { - rotoscaleBlitLogic, uint16, true>(dst, src, dstPitch, srcPitch, dstW, dstH, srcW, srcH, fmt, transform, newHotspot); + rotoscaleBlitLogic, uint16, 2, true>(dst, src, dstPitch, srcPitch, dstW, dstH, srcW, srcH, fmt, transform, newHotspot); } else { return false; }