[Scummvm-git-logs] scummvm master -> ad722f31cc0e6cd73e4333d6b29ac4896e62dcb2
sev-
sev at scummvm.org
Sat Jul 18 10:17:00 UTC 2020
This automated email contains information about 5 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
42019d4252 GRAPHICS: Move code for nearest neighbour scaling out of TransparentSurface
b2f2069fb0 GRAPHICS: Move code for bilinear scaling out of TransparentSurface
ff1474591f GRAPHICS: Allow using scaleBlitBilinear using different pixel formats and pitches
352653b8a2 GRAPHICS: Add a function for scaling a standard Graphics::Surface
ad722f31cc SCI32: Allow using HQ video with pixel formats other than RGBA8888
Commit: 42019d42527097a929ace8af1986b4b4124bad25
https://github.com/scummvm/scummvm/commit/42019d42527097a929ace8af1986b4b4124bad25
Author: Cameron Cawley (ccawley2011 at gmail.com)
Date: 2020-07-18T12:16:52+02:00
Commit Message:
GRAPHICS: Move code for nearest neighbour scaling out of TransparentSurface
Changed paths:
graphics/conversion.cpp
graphics/conversion.h
graphics/transparent_surface.cpp
graphics/transparent_surface.h
diff --git a/graphics/conversion.cpp b/graphics/conversion.cpp
index 27180b80ad..a9eaa7d80a 100644
--- a/graphics/conversion.cpp
+++ b/graphics/conversion.cpp
@@ -167,4 +167,59 @@ bool crossBlit(byte *dst, const byte *src,
return true;
}
+namespace {
+
+template <typename Size>
+void scaleNN(byte *dst, const byte *src,
+ const uint dstPitch, const uint srcPitch,
+ const uint dstW, const uint dstH,
+ const uint srcW, const uint srcH,
+ int *scaleCacheX) {
+
+ const uint dstDelta = (dstPitch - dstW * sizeof(Size));
+
+ for (uint y = 0; y < dstH; y++) {
+ const Size *srcP = (const Size *)(src + ((y * srcH) / dstH) * srcPitch);
+ for (uint x = 0; x < dstW; x++) {
+ int val = srcP[scaleCacheX[x]];
+ *(Size *)dst = val;
+ dst += sizeof(Size);
+ }
+ dst += dstDelta;
+ }
+}
+
+} // End of anonymous namespace
+
+bool scaleBlit(byte *dst, const byte *src,
+ const uint dstPitch, const uint srcPitch,
+ const uint dstW, const uint dstH,
+ const uint srcW, const uint srcH,
+ const Graphics::PixelFormat &fmt) {
+
+ int *scaleCacheX = new int[dstW];
+ for (uint x = 0; x < dstW; x++) {
+ scaleCacheX[x] = (x * srcW) / dstW;
+ }
+
+ switch (fmt.bytesPerPixel) {
+ case 1:
+ scaleNN<uint8>(dst, src, dstPitch, srcPitch, dstW, dstH, srcW, srcH, scaleCacheX);
+ break;
+ case 2:
+ scaleNN<uint16>(dst, src, dstPitch, srcPitch, dstW, dstH, srcW, srcH, scaleCacheX);
+ break;
+ case 4:
+ scaleNN<uint32>(dst, src, dstPitch, srcPitch, dstW, dstH, srcW, srcH, scaleCacheX);
+ break;
+ default:
+ delete[] scaleCacheX;
+ return false;
+ }
+
+ delete[] scaleCacheX;
+
+ return true;
+}
+
} // End of namespace Graphics
diff --git a/graphics/conversion.h b/graphics/conversion.h
index 8ca529acc0..04240c576d 100644
--- a/graphics/conversion.h
+++ b/graphics/conversion.h
@@ -72,6 +72,12 @@ bool crossBlit(byte *dst, const byte *src,
const uint w, const uint h,
const Graphics::PixelFormat &dstFmt, const Graphics::PixelFormat &srcFmt);
+bool scaleBlit(byte *dst, const byte *src,
+ const uint dstPitch, const uint srcPitch,
+ const uint dstW, const uint dstH,
+ const uint srcW, const uint srcH,
+ const Graphics::PixelFormat &fmt);
+
} // End of namespace Graphics
#endif // GRAPHICS_CONVERSION_H
diff --git a/graphics/transparent_surface.cpp b/graphics/transparent_surface.cpp
index eb8d3fe5ce..94d206ebb1 100644
--- a/graphics/transparent_surface.cpp
+++ b/graphics/transparent_surface.cpp
@@ -33,6 +33,7 @@
#include "common/rect.h"
#include "common/math.h"
#include "common/textconsole.h"
+#include "graphics/conversion.h"
#include "graphics/primitives.h"
#include "graphics/transparent_surface.h"
#include "graphics/transform_tools.h"
@@ -1068,26 +1069,7 @@ TransparentSurface *TransparentSurface::scaleT(uint16 newWidth, uint16 newHeight
delete[] say;
} else {
- int *scaleCacheX = new int[dstW];
- for (int x = 0; x < dstW; x++) {
- scaleCacheX[x] = (x * srcW) / dstW;
- }
-
- switch (format.bytesPerPixel) {
- case 1:
- scaleNN<uint8>(scaleCacheX, target);
- break;
- case 2:
- scaleNN<uint16>(scaleCacheX, target);
- break;
- case 4:
- scaleNN<uint32>(scaleCacheX, target);
- break;
- default:
- error("Can only scale 8bpp, 16bpp, and 32bpp");
- }
-
- delete[] scaleCacheX;
+ scaleBlit((byte *)target->getPixels(), (const byte *)getPixels(), target->pitch, pitch, dstW, dstH, srcW, srcH, format);
}
return target;
@@ -1171,26 +1153,11 @@ TransparentSurface *TransparentSurface::convertTo(const PixelFormat &dstFormat,
return surface;
}
-template <typename Size>
-void TransparentSurface::scaleNN(int *scaleCacheX, TransparentSurface *target) const {
- for (int y = 0; y < target->h; y++) {
- Size *destP = (Size *)target->getBasePtr(0, y);
- const Size *srcP = (const Size *)getBasePtr(0, (y * h) / target->h);
- for (int x = 0; x < target->w; x++) {
- *destP++ = srcP[scaleCacheX[x]];
- }
- }
-}
-
template TransparentSurface *TransparentSurface::rotoscaleT<FILTER_NEAREST>(const TransformStruct &transform) const;
template TransparentSurface *TransparentSurface::rotoscaleT<FILTER_BILINEAR>(const TransformStruct &transform) const;
template TransparentSurface *TransparentSurface::scaleT<FILTER_NEAREST>(uint16 newWidth, uint16 newHeight) const;
template TransparentSurface *TransparentSurface::scaleT<FILTER_BILINEAR>(uint16 newWidth, uint16 newHeight) const;
-template void TransparentSurface::scaleNN<uint8>(int *scaleCacheX, TransparentSurface *target) const;
-template void TransparentSurface::scaleNN<uint16>(int *scaleCacheX, TransparentSurface *target) const;
-template void TransparentSurface::scaleNN<uint32>(int *scaleCacheX, TransparentSurface *target) const;
-
TransparentSurface *TransparentSurface::rotoscale(const TransformStruct &transform) const {
return rotoscaleT<FILTER_BILINEAR>(transform);
}
diff --git a/graphics/transparent_surface.h b/graphics/transparent_surface.h
index 8bfddef8c1..3c2b29b7b3 100644
--- a/graphics/transparent_surface.h
+++ b/graphics/transparent_surface.h
@@ -177,9 +177,6 @@ struct TransparentSurface : public Graphics::Surface {
void setAlphaMode(AlphaType);
private:
AlphaType _alphaMode;
-
- template <typename Size>
- void scaleNN(int *scaleCacheX, TransparentSurface *target) const;
};
/**
Commit: b2f2069fb0472717ecfae33dbd1e4ac3e667f535
https://github.com/scummvm/scummvm/commit/b2f2069fb0472717ecfae33dbd1e4ac3e667f535
Author: Cameron Cawley (ccawley2011 at gmail.com)
Date: 2020-07-18T12:16:52+02:00
Commit Message:
GRAPHICS: Move code for bilinear scaling out of TransparentSurface
Changed paths:
graphics/conversion.cpp
graphics/conversion.h
graphics/transparent_surface.cpp
diff --git a/graphics/conversion.cpp b/graphics/conversion.cpp
index a9eaa7d80a..e86c8217b9 100644
--- a/graphics/conversion.cpp
+++ b/graphics/conversion.cpp
@@ -221,5 +221,201 @@ bool scaleBlit(byte *dst, const byte *src,
return true;
}
-
+
+/*
+
+The function below is adapted from SDL_rotozoom.c,
+taken from SDL_gfx-2.0.18.
+
+Its copyright notice:
+
+=============================================================================
+SDL_rotozoom.c: rotozoomer, zoomer and shrinker for 32bit or 8bit surfaces
+
+Copyright (C) 2001-2012 Andreas Schiffler
+
+This software is provided 'as-is', without any express or implied
+warranty. In no event will the authors be held liable for any damages
+arising from the use of this software.
+
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it
+freely, subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not
+claim that you wrote the original software. If you use this software
+in a product, an acknowledgment in the product documentation would be
+appreciated but is not required.
+
+2. Altered source versions must be plainly marked as such, and must not be
+misrepresented as being the original software.
+
+3. This notice may not be removed or altered from any source
+distribution.
+
+Andreas Schiffler -- aschiffler at ferzkopp dot net
+=============================================================================
+
+
+The functions have been adapted for different structures and coordinate
+systems.
+
+*/
+
+struct tColorRGBA { byte r; byte g; byte b; byte a; };
+
+bool scaleBlitBilinear(byte *dst, const byte *src,
+ const uint dstPitch, const uint srcPitch,
+ const uint dstW, const uint dstH,
+ const uint srcW, const uint srcH,
+ const Graphics::PixelFormat &fmt) {
+ assert(fmt.bytesPerPixel == 4);
+
+ bool flipx = false, flipy = false; // TODO: See mirroring comment in RenderTicket ctor
+
+
+ int *sax = new int[dstW + 1];
+ int *say = new int[dstH + 1];
+ assert(sax && say);
+
+ /*
+ * Precalculate row increments
+ */
+ int spixelw = (srcW - 1);
+ int spixelh = (srcH - 1);
+ int sx = (int)(65536.0f * (float) spixelw / (float) (dstW - 1));
+ int sy = (int)(65536.0f * (float) spixelh / (float) (dstH - 1));
+
+ /* Maximum scaled source size */
+ int ssx = (srcW << 16) - 1;
+ int ssy = (srcH << 16) - 1;
+
+ /* Precalculate horizontal row increments */
+ int csx = 0;
+ int *csax = sax;
+ for (uint x = 0; x <= dstW; x++) {
+ *csax = csx;
+ csax++;
+ csx += sx;
+
+ /* Guard from overflows */
+ if (csx > ssx) {
+ csx = ssx;
+ }
+ }
+
+ /* Precalculate vertical row increments */
+ int csy = 0;
+ int *csay = say;
+ for (uint y = 0; y <= dstH; y++) {
+ *csay = csy;
+ csay++;
+ csy += sy;
+
+ /* Guard from overflows */
+ if (csy > ssy) {
+ csy = ssy;
+ }
+ }
+
+ const tColorRGBA *sp = (const tColorRGBA *) src;
+ tColorRGBA *dp = (tColorRGBA *) dst;
+ int spixelgap = srcW;
+
+ if (flipx) {
+ sp += spixelw;
+ }
+ if (flipy) {
+ sp += spixelgap * spixelh;
+ }
+
+ csay = say;
+ for (uint y = 0; y < dstH; y++) {
+ const tColorRGBA *csp = sp;
+ csax = sax;
+ for (uint x = 0; x < dstW; x++) {
+ /*
+ * Setup color source pointers
+ */
+ int ex = (*csax & 0xffff);
+ int ey = (*csay & 0xffff);
+ int cx = (*csax >> 16);
+ int cy = (*csay >> 16);
+
+ const tColorRGBA *c00, *c01, *c10, *c11;
+ c00 = sp;
+ c01 = sp;
+ c10 = sp;
+ if (cy < spixelh) {
+ if (flipy) {
+ c10 -= spixelgap;
+ } else {
+ c10 += spixelgap;
+ }
+ }
+ c11 = c10;
+ if (cx < spixelw) {
+ if (flipx) {
+ c01--;
+ c11--;
+ } else {
+ c01++;
+ c11++;
+ }
+ }
+
+ /*
+ * Draw and interpolate colors
+ */
+ int t1, t2;
+ t1 = ((((c01->r - c00->r) * ex) >> 16) + c00->r) & 0xff;
+ t2 = ((((c11->r - c10->r) * ex) >> 16) + c10->r) & 0xff;
+ dp->r = (((t2 - t1) * ey) >> 16) + t1;
+ t1 = ((((c01->g - c00->g) * ex) >> 16) + c00->g) & 0xff;
+ t2 = ((((c11->g - c10->g) * ex) >> 16) + c10->g) & 0xff;
+ dp->g = (((t2 - t1) * ey) >> 16) + t1;
+ t1 = ((((c01->b - c00->b) * ex) >> 16) + c00->b) & 0xff;
+ t2 = ((((c11->b - c10->b) * ex) >> 16) + c10->b) & 0xff;
+ dp->b = (((t2 - t1) * ey) >> 16) + t1;
+ t1 = ((((c01->a - c00->a) * ex) >> 16) + c00->a) & 0xff;
+ t2 = ((((c11->a - c10->a) * ex) >> 16) + c10->a) & 0xff;
+ dp->a = (((t2 - t1) * ey) >> 16) + t1;
+
+ /*
+ * Advance source pointer x
+ */
+ int *salastx = csax;
+ csax++;
+ int sstepx = (*csax >> 16) - (*salastx >> 16);
+ if (flipx) {
+ sp -= sstepx;
+ } else {
+ sp += sstepx;
+ }
+
+ /*
+ * Advance destination pointer x
+ */
+ dp++;
+ }
+ /*
+ * Advance source pointer y
+ */
+ int *salasty = csay;
+ csay++;
+ int sstepy = (*csay >> 16) - (*salasty >> 16);
+ sstepy *= spixelgap;
+ if (flipy) {
+ sp = csp - sstepy;
+ } else {
+ sp = csp + sstepy;
+ }
+ }
+
+ delete[] sax;
+ delete[] say;
+
+ return true;
+}
+
} // End of namespace Graphics
diff --git a/graphics/conversion.h b/graphics/conversion.h
index 04240c576d..1e5486864a 100644
--- a/graphics/conversion.h
+++ b/graphics/conversion.h
@@ -78,6 +78,12 @@ bool scaleBlit(byte *dst, const byte *src,
const uint srcW, const uint srcH,
const Graphics::PixelFormat &fmt);
+bool scaleBlitBilinear(byte *dst, const byte *src,
+ const uint dstPitch, const uint srcPitch,
+ const uint dstW, const uint dstH,
+ const uint srcW, const uint srcH,
+ const Graphics::PixelFormat &fmt);
+
} // End of namespace Graphics
#endif // GRAPHICS_CONVERSION_H
diff --git a/graphics/transparent_surface.cpp b/graphics/transparent_surface.cpp
index 94d206ebb1..4d9000914f 100644
--- a/graphics/transparent_surface.cpp
+++ b/graphics/transparent_surface.cpp
@@ -751,7 +751,7 @@ void TransparentSurface::setAlphaMode(AlphaType mode) {
/*
-The below two functions are adapted from SDL_rotozoom.c,
+The function below is adapted from SDL_rotozoom.c,
taken from SDL_gfx-2.0.18.
Its copyright notice:
@@ -914,162 +914,12 @@ TransparentSurface *TransparentSurface::scaleT(uint16 newWidth, uint16 newHeight
TransparentSurface *target = new TransparentSurface();
- int srcW = w;
- int srcH = h;
- int dstW = newWidth;
- int dstH = newHeight;
-
- target->create((uint16)dstW, (uint16)dstH, format);
+ target->create(newWidth, newHeight, format);
if (filteringMode == FILTER_BILINEAR) {
- assert(format.bytesPerPixel == 4);
-
- bool flipx = false, flipy = false; // TODO: See mirroring comment in RenderTicket ctor
-
-
- int *sax = new int[dstW + 1];
- int *say = new int[dstH + 1];
- assert(sax && say);
-
- /*
- * Precalculate row increments
- */
- int spixelw = (srcW - 1);
- int spixelh = (srcH - 1);
- int sx = (int)(65536.0f * (float) spixelw / (float) (dstW - 1));
- int sy = (int)(65536.0f * (float) spixelh / (float) (dstH - 1));
-
- /* Maximum scaled source size */
- int ssx = (srcW << 16) - 1;
- int ssy = (srcH << 16) - 1;
-
- /* Precalculate horizontal row increments */
- int csx = 0;
- int *csax = sax;
- for (int x = 0; x <= dstW; x++) {
- *csax = csx;
- csax++;
- csx += sx;
-
- /* Guard from overflows */
- if (csx > ssx) {
- csx = ssx;
- }
- }
-
- /* Precalculate vertical row increments */
- int csy = 0;
- int *csay = say;
- for (int y = 0; y <= dstH; y++) {
- *csay = csy;
- csay++;
- csy += sy;
-
- /* Guard from overflows */
- if (csy > ssy) {
- csy = ssy;
- }
- }
-
- const tColorRGBA *sp = (const tColorRGBA *) getBasePtr(0, 0);
- tColorRGBA *dp = (tColorRGBA *) target->getBasePtr(0, 0);
- int spixelgap = srcW;
-
- if (flipx) {
- sp += spixelw;
- }
- if (flipy) {
- sp += spixelgap * spixelh;
- }
-
- csay = say;
- for (int y = 0; y < dstH; y++) {
- const tColorRGBA *csp = sp;
- csax = sax;
- for (int x = 0; x < dstW; x++) {
- /*
- * Setup color source pointers
- */
- int ex = (*csax & 0xffff);
- int ey = (*csay & 0xffff);
- int cx = (*csax >> 16);
- int cy = (*csay >> 16);
-
- const tColorRGBA *c00, *c01, *c10, *c11;
- c00 = sp;
- c01 = sp;
- c10 = sp;
- if (cy < spixelh) {
- if (flipy) {
- c10 -= spixelgap;
- } else {
- c10 += spixelgap;
- }
- }
- c11 = c10;
- if (cx < spixelw) {
- if (flipx) {
- c01--;
- c11--;
- } else {
- c01++;
- c11++;
- }
- }
-
- /*
- * Draw and interpolate colors
- */
- int t1, t2;
- t1 = ((((c01->r - c00->r) * ex) >> 16) + c00->r) & 0xff;
- t2 = ((((c11->r - c10->r) * ex) >> 16) + c10->r) & 0xff;
- dp->r = (((t2 - t1) * ey) >> 16) + t1;
- t1 = ((((c01->g - c00->g) * ex) >> 16) + c00->g) & 0xff;
- t2 = ((((c11->g - c10->g) * ex) >> 16) + c10->g) & 0xff;
- dp->g = (((t2 - t1) * ey) >> 16) + t1;
- t1 = ((((c01->b - c00->b) * ex) >> 16) + c00->b) & 0xff;
- t2 = ((((c11->b - c10->b) * ex) >> 16) + c10->b) & 0xff;
- dp->b = (((t2 - t1) * ey) >> 16) + t1;
- t1 = ((((c01->a - c00->a) * ex) >> 16) + c00->a) & 0xff;
- t2 = ((((c11->a - c10->a) * ex) >> 16) + c10->a) & 0xff;
- dp->a = (((t2 - t1) * ey) >> 16) + t1;
-
- /*
- * Advance source pointer x
- */
- int *salastx = csax;
- csax++;
- int sstepx = (*csax >> 16) - (*salastx >> 16);
- if (flipx) {
- sp -= sstepx;
- } else {
- sp += sstepx;
- }
-
- /*
- * Advance destination pointer x
- */
- dp++;
- }
- /*
- * Advance source pointer y
- */
- int *salasty = csay;
- csay++;
- int sstepy = (*csay >> 16) - (*salasty >> 16);
- sstepy *= spixelgap;
- if (flipy) {
- sp = csp - sstepy;
- } else {
- sp = csp + sstepy;
- }
- }
-
- delete[] sax;
- delete[] say;
-
+ scaleBlitBilinear((byte *)target->getPixels(), (const byte *)getPixels(), target->pitch, pitch, target->w, target->h, w, h, format);
} else {
- scaleBlit((byte *)target->getPixels(), (const byte *)getPixels(), target->pitch, pitch, dstW, dstH, srcW, srcH, format);
+ scaleBlit((byte *)target->getPixels(), (const byte *)getPixels(), target->pitch, pitch, target->w, target->h, w, h, format);
}
return target;
Commit: ff1474591ffe5d7155e8b3e2f987ef3511c0bb04
https://github.com/scummvm/scummvm/commit/ff1474591ffe5d7155e8b3e2f987ef3511c0bb04
Author: Cameron Cawley (ccawley2011 at gmail.com)
Date: 2020-07-18T12:16:52+02:00
Commit Message:
GRAPHICS: Allow using scaleBlitBilinear using different pixel formats and pitches
Changed paths:
graphics/conversion.cpp
diff --git a/graphics/conversion.cpp b/graphics/conversion.cpp
index e86c8217b9..8df8a53b9f 100644
--- a/graphics/conversion.cpp
+++ b/graphics/conversion.cpp
@@ -224,7 +224,7 @@ bool scaleBlit(byte *dst, const byte *src,
/*
-The function below is adapted from SDL_rotozoom.c,
+The functions below are adapted from SDL_rotozoom.c,
taken from SDL_gfx-2.0.18.
Its copyright notice:
@@ -257,82 +257,66 @@ Andreas Schiffler -- aschiffler at ferzkopp dot net
=============================================================================
-The functions have been adapted for different structures and coordinate
-systems.
+The functions have been adapted for different structures, coordinate
+systems and pixel formats.
*/
-struct tColorRGBA { byte r; byte g; byte b; byte a; };
-
-bool scaleBlitBilinear(byte *dst, const byte *src,
- const uint dstPitch, const uint srcPitch,
- const uint dstW, const uint dstH,
- const uint srcW, const uint srcH,
- const Graphics::PixelFormat &fmt) {
- assert(fmt.bytesPerPixel == 4);
-
- bool flipx = false, flipy = false; // TODO: See mirroring comment in RenderTicket ctor
+namespace {
+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;
+}
- int *sax = new int[dstW + 1];
- int *say = new int[dstH + 1];
- assert(sax && say);
+template <typename Size>
+Size scaleBlitBilinearInterpolate(Size c01, Size c00, Size c11, Size c10, int ex, int ey,
+ const Graphics::PixelFormat &fmt) {
+ byte c01_a, c01_r, c01_g, c01_b;
+ fmt.colorToARGB(c01, c01_a, c01_r, c01_g, c01_b);
- /*
- * Precalculate row increments
- */
- int spixelw = (srcW - 1);
- int spixelh = (srcH - 1);
- int sx = (int)(65536.0f * (float) spixelw / (float) (dstW - 1));
- int sy = (int)(65536.0f * (float) spixelh / (float) (dstH - 1));
+ byte c00_a, c00_r, c00_g, c00_b;
+ fmt.colorToARGB(c00, c00_a, c00_r, c00_g, c00_b);
- /* Maximum scaled source size */
- int ssx = (srcW << 16) - 1;
- int ssy = (srcH << 16) - 1;
+ byte c11_a, c11_r, c11_g, c11_b;
+ fmt.colorToARGB(c11, c11_a, c11_r, c11_g, c11_b);
- /* Precalculate horizontal row increments */
- int csx = 0;
- int *csax = sax;
- for (uint x = 0; x <= dstW; x++) {
- *csax = csx;
- csax++;
- csx += sx;
+ byte c10_a, c10_r, c10_g, c10_b;
+ fmt.colorToARGB(c10, c10_a, c10_r, c10_g, c10_b);
- /* Guard from overflows */
- if (csx > ssx) {
- csx = ssx;
- }
- }
+ 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.ARGBToColor(dp_a, dp_r, dp_g, dp_b);
+}
- /* Precalculate vertical row increments */
- int csy = 0;
- int *csay = say;
- for (uint y = 0; y <= dstH; y++) {
- *csay = csy;
- csay++;
- csy += sy;
+template <typename Size, bool flipx, bool flipy> // TODO: See mirroring comment in RenderTicket ctor
+void scaleBlitBilinearLogic(byte *dst, const byte *src,
+ const uint dstPitch, const uint srcPitch,
+ const uint dstW, const uint dstH,
+ const uint srcW, const uint srcH,
+ const Graphics::PixelFormat &fmt,
+ int *sax, int *say) {
- /* Guard from overflows */
- if (csy > ssy) {
- csy = ssy;
- }
- }
+ int spixelw = (srcW - 1);
+ int spixelh = (srcH - 1);
- const tColorRGBA *sp = (const tColorRGBA *) src;
- tColorRGBA *dp = (tColorRGBA *) dst;
- int spixelgap = srcW;
+ const byte *sp = src;
if (flipx) {
sp += spixelw;
}
if (flipy) {
- sp += spixelgap * spixelh;
+ sp += srcPitch * spixelh;
}
- csay = say;
+ int *csay = say;
for (uint y = 0; y < dstH; y++) {
- const tColorRGBA *csp = sp;
- csax = sax;
+ Size *dp = (Size *)(dst + (dstPitch * y));
+ const byte *csp = sp;
+ int *csax = sax;
for (uint x = 0; x < dstW; x++) {
/*
* Setup color source pointers
@@ -342,45 +326,30 @@ bool scaleBlitBilinear(byte *dst, const byte *src,
int cx = (*csax >> 16);
int cy = (*csay >> 16);
- const tColorRGBA *c00, *c01, *c10, *c11;
- c00 = sp;
- c01 = sp;
- c10 = sp;
+ const byte *c00, *c01, *c10, *c11;
+ c00 = c01 = c10 = sp;
if (cy < spixelh) {
if (flipy) {
- c10 -= spixelgap;
+ c10 -= srcPitch;
} else {
- c10 += spixelgap;
+ c10 += srcPitch;
}
}
c11 = c10;
if (cx < spixelw) {
if (flipx) {
- c01--;
- c11--;
+ c01 -= sizeof(Size);
+ c11 -= sizeof(Size);
} else {
- c01++;
- c11++;
+ c01 += sizeof(Size);
+ c11 += sizeof(Size);
}
}
/*
* Draw and interpolate colors
*/
- int t1, t2;
- t1 = ((((c01->r - c00->r) * ex) >> 16) + c00->r) & 0xff;
- t2 = ((((c11->r - c10->r) * ex) >> 16) + c10->r) & 0xff;
- dp->r = (((t2 - t1) * ey) >> 16) + t1;
- t1 = ((((c01->g - c00->g) * ex) >> 16) + c00->g) & 0xff;
- t2 = ((((c11->g - c10->g) * ex) >> 16) + c10->g) & 0xff;
- dp->g = (((t2 - t1) * ey) >> 16) + t1;
- t1 = ((((c01->b - c00->b) * ex) >> 16) + c00->b) & 0xff;
- t2 = ((((c11->b - c10->b) * ex) >> 16) + c10->b) & 0xff;
- dp->b = (((t2 - t1) * ey) >> 16) + t1;
- t1 = ((((c01->a - c00->a) * ex) >> 16) + c00->a) & 0xff;
- t2 = ((((c11->a - c10->a) * ex) >> 16) + c10->a) & 0xff;
- dp->a = (((t2 - t1) * ey) >> 16) + t1;
-
+ *dp = scaleBlitBilinearInterpolate(*(const Size *)c01, *(const Size *)c00, *(const Size *)c11, *(const Size *)c10, ex, ey, fmt);
/*
* Advance source pointer x
*/
@@ -388,9 +357,9 @@ bool scaleBlitBilinear(byte *dst, const byte *src,
csax++;
int sstepx = (*csax >> 16) - (*salastx >> 16);
if (flipx) {
- sp -= sstepx;
+ sp -= sstepx * sizeof(Size);
} else {
- sp += sstepx;
+ sp += sstepx * sizeof(Size);
}
/*
@@ -404,13 +373,79 @@ bool scaleBlitBilinear(byte *dst, const byte *src,
int *salasty = csay;
csay++;
int sstepy = (*csay >> 16) - (*salasty >> 16);
- sstepy *= spixelgap;
+ sstepy *= srcPitch;
if (flipy) {
sp = csp - sstepy;
} else {
sp = csp + sstepy;
}
}
+}
+
+} // End of anonymous namespace
+
+bool scaleBlitBilinear(byte *dst, const byte *src,
+ const uint dstPitch, const uint srcPitch,
+ const uint dstW, const uint dstH,
+ const uint srcW, const uint srcH,
+ const Graphics::PixelFormat &fmt) {
+ if (fmt.bytesPerPixel != 2 && fmt.bytesPerPixel != 4)
+ return false;
+
+ int *sax = new int[dstW + 1];
+ int *say = new int[dstH + 1];
+ assert(sax && say);
+
+ /*
+ * Precalculate row increments
+ */
+ int spixelw = (srcW - 1);
+ int spixelh = (srcH - 1);
+ int sx = (int)(65536.0f * (float) spixelw / (float) (dstW - 1));
+ int sy = (int)(65536.0f * (float) spixelh / (float) (dstH - 1));
+
+ /* Maximum scaled source size */
+ int ssx = (srcW << 16) - 1;
+ int ssy = (srcH << 16) - 1;
+
+ /* Precalculate horizontal row increments */
+ int csx = 0;
+ int *csax = sax;
+ for (uint x = 0; x <= dstW; x++) {
+ *csax = csx;
+ csax++;
+ csx += sx;
+
+ /* Guard from overflows */
+ if (csx > ssx) {
+ csx = ssx;
+ }
+ }
+
+ /* Precalculate vertical row increments */
+ int csy = 0;
+ int *csay = say;
+ for (uint y = 0; y <= dstH; y++) {
+ *csay = csy;
+ csay++;
+ csy += sy;
+
+ /* Guard from overflows */
+ if (csy > ssy) {
+ csy = ssy;
+ }
+ }
+
+ if (fmt.bytesPerPixel == 4) {
+ scaleBlitBilinearLogic<uint32, false, false>(dst, src, dstPitch, srcPitch, dstW, dstH, srcW, srcH, fmt, sax, say);
+ } else if (fmt.bytesPerPixel == 2) {
+ scaleBlitBilinearLogic<uint16, false, false>(dst, src, dstPitch, srcPitch, dstW, dstH, srcW, srcH, fmt, sax, say);
+ } else {
+ delete[] sax;
+ delete[] say;
+
+ return false;
+ }
delete[] sax;
delete[] say;
Commit: 352653b8a2d491f9c1bc514a17ec720a31f71e3d
https://github.com/scummvm/scummvm/commit/352653b8a2d491f9c1bc514a17ec720a31f71e3d
Author: Cameron Cawley (ccawley2011 at gmail.com)
Date: 2020-07-18T12:16:52+02:00
Commit Message:
GRAPHICS: Add a function for scaling a standard Graphics::Surface
This also makes use of it in the SCI and Wintermute engines
Changed paths:
engines/sci/graphics/video32.cpp
engines/wintermute/base/base_persistence_manager.cpp
engines/wintermute/base/gfx/base_image.cpp
engines/wintermute/base/gfx/osystem/render_ticket.cpp
graphics/surface.cpp
graphics/surface.h
graphics/transparent_surface.cpp
graphics/transparent_surface.h
diff --git a/engines/sci/graphics/video32.cpp b/engines/sci/graphics/video32.cpp
index 6b8f9e54b5..5b164bc9a0 100644
--- a/engines/sci/graphics/video32.cpp
+++ b/engines/sci/graphics/video32.cpp
@@ -30,7 +30,6 @@
#include "common/system.h" // for g_system
#include "engines/engine.h" // for Engine, g_engine
#include "graphics/palette.h" // for PaletteManager
-#include "graphics/transparent_surface.h" // for TransparentSurface
#include "sci/console.h" // for Console
#include "sci/engine/features.h" // for GameFeatures
#include "sci/engine/state.h" // for EngineState
@@ -242,20 +241,16 @@ void VideoPlayer::renderFrame(const Graphics::Surface &nextFrame) const {
if (_decoder->getWidth() != _drawRect.width() || _decoder->getHeight() != _drawRect.height()) {
Graphics::Surface *const unscaledFrame(convertedFrame);
- // TODO: The only reason TransparentSurface is used here because it is
- // where common scaler code is right now, which should just be part of
- // Graphics::Surface (or some free functions).
- const Graphics::TransparentSurface tsUnscaledFrame(*unscaledFrame);
#ifdef USE_RGB_COLOR
if (_hqVideoMode) {
- convertedFrame = tsUnscaledFrame.scaleT<Graphics::FILTER_BILINEAR>(_drawRect.width(), _drawRect.height());
+ convertedFrame = unscaledFrame->scale(_drawRect.width(), _drawRect.height(), true);
} else {
#elif 1
{
#else
}
#endif
- convertedFrame = tsUnscaledFrame.scaleT<Graphics::FILTER_NEAREST>(_drawRect.width(), _drawRect.height());
+ convertedFrame = unscaledFrame->scale(_drawRect.width(), _drawRect.height(), false);
}
assert(convertedFrame);
if (freeConvertedFrame) {
diff --git a/engines/wintermute/base/base_persistence_manager.cpp b/engines/wintermute/base/base_persistence_manager.cpp
index 5a694e7ce2..ad38f5d529 100644
--- a/engines/wintermute/base/base_persistence_manager.cpp
+++ b/engines/wintermute/base/base_persistence_manager.cpp
@@ -36,7 +36,6 @@
#include "engines/wintermute/base/gfx/base_image.h"
#include "engines/wintermute/base/save_thumb_helper.h"
#include "engines/wintermute/base/sound/base_sound.h"
-#include "graphics/transparent_surface.h"
#include "engines/wintermute/wintermute.h"
#include "graphics/scaler.h"
#include "image/bmp.h"
@@ -173,11 +172,9 @@ void BasePersistenceManager::getSaveStateDesc(int slot, SaveStateDescriptor &des
Image::BitmapDecoder bmpDecoder;
if (bmpDecoder.loadStream(thumbStream)) {
const Graphics::Surface *bmpSurface = bmpDecoder.getSurface();
- Graphics::TransparentSurface *scaleableSurface = new Graphics::TransparentSurface(*bmpSurface, false);
- Graphics::Surface *scaled = scaleableSurface->scale(kThumbnailWidth, kThumbnailHeight2);
+ Graphics::Surface *scaled = bmpSurface->scale(kThumbnailWidth, kThumbnailHeight2);
Graphics::Surface *thumb = scaled->convertTo(g_system->getOverlayFormat());
desc.setThumbnail(thumb);
- delete scaleableSurface;
scaled->free();
delete scaled;
}
diff --git a/engines/wintermute/base/gfx/base_image.cpp b/engines/wintermute/base/gfx/base_image.cpp
index a1548b83ea..963de43fc8 100644
--- a/engines/wintermute/base/gfx/base_image.cpp
+++ b/engines/wintermute/base/gfx/base_image.cpp
@@ -28,7 +28,6 @@
#include "engines/wintermute/base/gfx/base_image.h"
#include "engines/wintermute/base/base_file_manager.h"
-#include "graphics/transparent_surface.h"
#include "graphics/surface.h"
#include "image/png.h"
#include "image/jpeg.h"
@@ -112,14 +111,13 @@ bool BaseImage::saveBMPFile(const Common::String &filename) const {
//////////////////////////////////////////////////////////////////////////
bool BaseImage::resize(int newWidth, int newHeight) {
// WME Lite used FILTER_BILINEAR with FreeImage_Rescale here.
- Graphics::TransparentSurface temp(*_surface, true);
+ Graphics::Surface *temp = _surface->scale((uint16)newWidth, (uint16)newHeight);
if (_deletableSurface) {
_deletableSurface->free();
delete _deletableSurface;
_deletableSurface = nullptr;
}
- _surface = _deletableSurface = temp.scale((uint16)newWidth, (uint16)newHeight);
- temp.free();
+ _surface = _deletableSurface = temp;
return true;
}
@@ -216,13 +214,13 @@ bool BaseImage::writeBMPToStream(Common::WriteStream *stream) const {
bool BaseImage::copyFrom(BaseImage *origImage, int newWidth, int newHeight) {
// WME Lite used FILTER_BILINEAR with FreeImage_Rescale here.
- Graphics::TransparentSurface temp(*origImage->_surface, false);
+ Graphics::Surface *temp = origImage->_surface->scale((uint16)newWidth, (uint16)newHeight);
if (_deletableSurface) {
_deletableSurface->free();
delete _deletableSurface;
_deletableSurface = nullptr;
}
- _surface = _deletableSurface = temp.scale((uint16)newWidth, (uint16)newHeight);
+ _surface = _deletableSurface = temp;
return true;
}
diff --git a/engines/wintermute/base/gfx/osystem/render_ticket.cpp b/engines/wintermute/base/gfx/osystem/render_ticket.cpp
index e092e3cf17..d5297d6529 100644
--- a/engines/wintermute/base/gfx/osystem/render_ticket.cpp
+++ b/engines/wintermute/base/gfx/osystem/render_ticket.cpp
@@ -72,13 +72,7 @@ RenderTicket::RenderTicket(BaseSurfaceOSystem *owner, const Graphics::Surface *s
} else if ((dstRect->width() != srcRect->width() ||
dstRect->height() != srcRect->height()) &&
_transform._numTimesX * _transform._numTimesY == 1) {
- Graphics::TransparentSurface src(*_surface, false);
- Graphics::Surface *temp;
- if (owner->_gameRef->getBilinearFiltering()) {
- temp = src.scaleT<Graphics::FILTER_BILINEAR>(dstRect->width(), dstRect->height());
- } else {
- temp = src.scaleT<Graphics::FILTER_NEAREST>(dstRect->width(), dstRect->height());
- }
+ Graphics::Surface *temp = _surface->scale(dstRect->width(), dstRect->height(), owner->_gameRef->getBilinearFiltering());
_surface->free();
delete _surface;
_surface = temp;
diff --git a/graphics/surface.cpp b/graphics/surface.cpp
index e2e3401cc2..d389f139ef 100644
--- a/graphics/surface.cpp
+++ b/graphics/surface.cpp
@@ -368,6 +368,21 @@ void Surface::flipVertical(const Common::Rect &r) {
delete[] temp;
}
+Graphics::Surface *Surface::scale(uint16 newWidth, uint16 newHeight, bool filtering) const {
+
+ Graphics::Surface *target = new Graphics::Surface();
+
+ target->create(newWidth, newHeight, format);
+
+ if (filtering) {
+ scaleBlitBilinear((byte *)target->getPixels(), (const byte *)getPixels(), target->pitch, pitch, target->w, target->h, w, h, format);
+ } else {
+ scaleBlit((byte *)target->getPixels(), (const byte *)getPixels(), target->pitch, pitch, target->w, target->h, w, h, format);
+ }
+
+ return target;
+}
+
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) {
diff --git a/graphics/surface.h b/graphics/surface.h
index 8728106273..b7ada5ec28 100644
--- a/graphics/surface.h
+++ b/graphics/surface.h
@@ -334,6 +334,19 @@ public:
* @param r Rect to flip
*/
void flipVertical(const Common::Rect &r);
+
+ /**
+ * Scale the data to the given size.
+ *
+ * The calling code must call free on the returned surface and then delete
+ * it.
+ *
+ * @param newWidth the resulting width.
+ * @param newHeight the resulting height.
+ * @param filtering Whether or not to use bilinear filtering.
+ */
+ Graphics::Surface *scale(uint16 newWidth, uint16 newHeight, bool filtering = false) const;
+
};
/**
diff --git a/graphics/transparent_surface.cpp b/graphics/transparent_surface.cpp
index 4d9000914f..21dd893b47 100644
--- a/graphics/transparent_surface.cpp
+++ b/graphics/transparent_surface.cpp
@@ -909,14 +909,13 @@ TransparentSurface *TransparentSurface::rotoscaleT(const TransformStruct &transf
return target;
}
-template <TFilteringMode filteringMode>
-TransparentSurface *TransparentSurface::scaleT(uint16 newWidth, uint16 newHeight) const {
+TransparentSurface *TransparentSurface::scale(uint16 newWidth, uint16 newHeight, bool filtering) const {
TransparentSurface *target = new TransparentSurface();
target->create(newWidth, newHeight, format);
- if (filteringMode == FILTER_BILINEAR) {
+ if (filtering) {
scaleBlitBilinear((byte *)target->getPixels(), (const byte *)getPixels(), target->pitch, pitch, target->w, target->h, w, h, format);
} else {
scaleBlit((byte *)target->getPixels(), (const byte *)getPixels(), target->pitch, pitch, target->w, target->h, w, h, format);
@@ -1005,15 +1004,9 @@ TransparentSurface *TransparentSurface::convertTo(const PixelFormat &dstFormat,
template TransparentSurface *TransparentSurface::rotoscaleT<FILTER_NEAREST>(const TransformStruct &transform) const;
template TransparentSurface *TransparentSurface::rotoscaleT<FILTER_BILINEAR>(const TransformStruct &transform) const;
-template TransparentSurface *TransparentSurface::scaleT<FILTER_NEAREST>(uint16 newWidth, uint16 newHeight) const;
-template TransparentSurface *TransparentSurface::scaleT<FILTER_BILINEAR>(uint16 newWidth, uint16 newHeight) const;
TransparentSurface *TransparentSurface::rotoscale(const TransformStruct &transform) const {
return rotoscaleT<FILTER_BILINEAR>(transform);
}
-TransparentSurface *TransparentSurface::scale(uint16 newWidth, uint16 newHeight) const {
- return scaleT<FILTER_NEAREST>(newWidth, newHeight);
-}
-
} // End of namespace Graphics
diff --git a/graphics/transparent_surface.h b/graphics/transparent_surface.h
index 3c2b29b7b3..ae0de7d2e2 100644
--- a/graphics/transparent_surface.h
+++ b/graphics/transparent_surface.h
@@ -145,12 +145,10 @@ struct TransparentSurface : public Graphics::Surface {
*
* @param newWidth the resulting width.
* @param newHeight the resulting height.
+ * @param filtering Whether or not to use bilinear filtering.
* @see TransformStruct
*/
- template <TFilteringMode filteringMode>
- TransparentSurface *scaleT(uint16 newWidth, uint16 newHeight) const;
-
- TransparentSurface *scale(uint16 newWidth, uint16 newHeight) const;
+ TransparentSurface *scale(uint16 newWidth, uint16 newHeight, bool filtering = false) const;
/**
* @brief Rotoscale function; this returns a transformed version of this surface after rotation and
Commit: ad722f31cc0e6cd73e4333d6b29ac4896e62dcb2
https://github.com/scummvm/scummvm/commit/ad722f31cc0e6cd73e4333d6b29ac4896e62dcb2
Author: Cameron Cawley (ccawley2011 at gmail.com)
Date: 2020-07-18T12:16:52+02:00
Commit Message:
SCI32: Allow using HQ video with pixel formats other than RGBA8888
This should fix Trac #11332.
Changed paths:
engines/sci/graphics/video32.cpp
diff --git a/engines/sci/graphics/video32.cpp b/engines/sci/graphics/video32.cpp
index 5b164bc9a0..8c1741686e 100644
--- a/engines/sci/graphics/video32.cpp
+++ b/engines/sci/graphics/video32.cpp
@@ -80,19 +80,26 @@ bool VideoPlayer::startHQVideo() {
// Optimize rendering performance for unscaled videos, and allow
// better-than-NN interpolation for videos that are scaled
if (shouldStartHQVideo()) {
- // TODO: Search for and use the best supported format (which may be
- // lower than 32bpp) once the scaling code in Graphics supports
- // 16bpp/24bpp, and once the SDL backend can correctly communicate
- // supported pixel formats above whatever format is currently used by
- // _hwsurface. Right now, this will either show an error dialog (OpenGL)
- // or just crash entirely (SDL) if the backend does not support this
- // 32bpp pixel format, which sucks since this code really ought to be
- // able to fall back to NN scaling for games with 256-color videos
- // without any error.
- const Graphics::PixelFormat format(4, 8, 8, 8, 8, 24, 16, 8, 0);
- g_sci->_gfxFrameout->setPixelFormat(format);
- _hqVideoMode = (g_system->getScreenFormat() == format);
- return _hqVideoMode;
+ const Common::List<Graphics::PixelFormat> outFormats = g_system->getSupportedFormats();
+ Graphics::PixelFormat bestFormat = outFormats.front();
+ if (bestFormat.bytesPerPixel != 2 && bestFormat.bytesPerPixel != 4) {
+ Common::List<Graphics::PixelFormat>::const_iterator it;
+ for (it = outFormats.begin(); it != outFormats.end(); ++it) {
+ if (it->bytesPerPixel == 2 || it->bytesPerPixel == 4) {
+ bestFormat = *it;
+ break;
+ }
+ }
+ }
+
+ if (bestFormat.bytesPerPixel != 2 && bestFormat.bytesPerPixel != 4) {
+ warning("Failed to find any valid output pixel format");
+ _hqVideoMode = false;
+ } else {
+ g_sci->_gfxFrameout->setPixelFormat(bestFormat);
+ _hqVideoMode = (g_system->getScreenFormat() != Graphics::PixelFormat::createFormatCLUT8());
+ return _hqVideoMode;
+ }
} else {
_hqVideoMode = false;
}
More information about the Scummvm-git-logs
mailing list