[Scummvm-git-logs] scummvm master -> ba564bc66f053af96cbdd8810bb84484453342f1

sev- noreply at scummvm.org
Sat Nov 20 00:06:29 UTC 2021


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

Summary:
721c46ec84 GRAPHICS: Add generic functions for converting palettes
30c093bbd9 OPENGL: Combine TextureCLUT8 and FakeTexture
fe5b87d0f1 OPENGL: Implement scaler support
267f1f18fb ANDROID: Enable scalers by default
2db20b702e OPENGL: Implement cursor scaling
ba564bc66f NEWS: Mention scaler support in OpenGL mode


Commit: 721c46ec84bee78987bdf488b3dc0cf37972b988
    https://github.com/scummvm/scummvm/commit/721c46ec84bee78987bdf488b3dc0cf37972b988
Author: Cameron Cawley (ccawley2011 at gmail.com)
Date: 2021-11-20T01:06:23+01:00

Commit Message:
GRAPHICS: Add generic functions for converting palettes

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


diff --git a/graphics/conversion.cpp b/graphics/conversion.cpp
index f12db3dd67..cfef1a8454 100644
--- a/graphics/conversion.cpp
+++ b/graphics/conversion.cpp
@@ -135,6 +135,32 @@ inline void crossBlitLogic(byte *dst, const byte *src, const uint w, const uint
 	}
 }
 
+template<typename DstColor, bool backward>
+inline void crossBlitLogic1BppSource(byte *dst, const byte *src, const uint w, const uint h,
+									 const uint srcDelta, const uint dstDelta, const uint32 *map) {
+	for (uint y = 0; y < h; ++y) {
+		for (uint x = 0; x < w; ++x) {
+			*(DstColor *)dst = map[*src];
+
+			if (backward) {
+				src -= 1;
+				dst -= sizeof(DstColor);
+			} else {
+				src += 1;
+				dst += sizeof(DstColor);
+			}
+		}
+
+		if (backward) {
+			src -= srcDelta;
+			dst -= dstDelta;
+		} else {
+			src += srcDelta;
+			dst += dstDelta;
+		}
+	}
+}
+
 template<typename DstColor, bool backward>
 inline void crossBlitLogic3BppSource(byte *dst, const byte *src, const uint w, const uint h,
 									 const PixelFormat &srcFmt, const PixelFormat &dstFmt,
@@ -230,6 +256,45 @@ bool crossBlit(byte *dst, const byte *src,
 	return true;
 }
 
+// Function to blit a rect from one color format to another using a map
+bool crossBlitMap(byte *dst, const byte *src,
+			   const uint dstPitch, const uint srcPitch,
+			   const uint w, const uint h,
+			   const uint bytesPerPixel, const uint32 *map) {
+	// Error out if conversion is impossible
+	if ((bytesPerPixel == 3) || (!bytesPerPixel))
+		return false;
+
+	// Faster, but larger, to provide optimized handling for each case.
+	const uint srcDelta = (srcPitch - w);
+	const uint dstDelta = (dstPitch - w * bytesPerPixel);
+
+	if (bytesPerPixel == 1) {
+		crossBlitLogic1BppSource<uint8, false>(dst, src, w, h, srcDelta, dstDelta, map);
+	} else if (bytesPerPixel == 2) {
+		// 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 - bytesPerPixel;
+		src += h * srcPitch - srcDelta - 1;
+		crossBlitLogic1BppSource<uint16, true>(dst, src, w, h, srcDelta, dstDelta, map);
+	} else if (bytesPerPixel == 4) {
+		// 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 - bytesPerPixel;
+		src += h * srcPitch - srcDelta - 1;
+		crossBlitLogic1BppSource<uint32, true>(dst, src, w, h, srcDelta, dstDelta, map);
+	} else {
+		return false;
+	}
+	return true;
+}
+
 namespace {
 
 template <typename Size>
diff --git a/graphics/conversion.h b/graphics/conversion.h
index 75bc9aceb8..8d3a1312e2 100644
--- a/graphics/conversion.h
+++ b/graphics/conversion.h
@@ -25,6 +25,8 @@
 
 #include "common/util.h"
 
+#include "graphics/pixelformat.h"
+
 namespace Common {
 struct Point;
 }
@@ -40,7 +42,6 @@ namespace Graphics {
  * @{
  */
 
-struct PixelFormat;
 struct TransformStruct;
 
 /** Converting a color from YUV to RGB colorspace. */
@@ -57,6 +58,14 @@ inline static void RGB2YUV(byte r, byte g, byte b, byte &y, byte &u, byte &v) {
 	v = CLIP<int>( ((r * 512) >> 10) - ((g * 429) >> 10) - ((b *  83) >> 10) + 128, 0, 255);
 }
 
+/** Converting a palette for use with crossBlitMap(). */
+inline static void convertPaletteToMap(uint32 *dst, const byte *src, uint colors, const Graphics::PixelFormat &format) {
+	while (colors-- > 0) {
+		*dst++ = format.RGBToColor(src[0], src[1], src[2]);
+		src += 3;
+	}
+}
+
 // TODO: generic YUV to RGB blit
 
 /**
@@ -118,6 +127,11 @@ bool crossBlit(byte *dst, const byte *src,
 			   const uint w, const uint h,
 			   const Graphics::PixelFormat &dstFmt, const Graphics::PixelFormat &srcFmt);
 
+bool crossBlitMap(byte *dst, const byte *src,
+			   const uint dstPitch, const uint srcPitch,
+			   const uint w, const uint h,
+			   const uint bytesPerPixel, const uint32 *map);
+
 bool scaleBlit(byte *dst, const byte *src,
 			   const uint dstPitch, const uint srcPitch,
 			   const uint dstW, const uint dstH,


Commit: 30c093bbd9bc99831ddd92add0e31ea26029bbd4
    https://github.com/scummvm/scummvm/commit/30c093bbd9bc99831ddd92add0e31ea26029bbd4
Author: Cameron Cawley (ccawley2011 at gmail.com)
Date: 2021-11-20T01:06:23+01:00

Commit Message:
OPENGL: Combine TextureCLUT8 and FakeTexture

Changed paths:
    backends/graphics/opengl/opengl-graphics.cpp
    backends/graphics/opengl/texture.cpp
    backends/graphics/opengl/texture.h


diff --git a/backends/graphics/opengl/opengl-graphics.cpp b/backends/graphics/opengl/opengl-graphics.cpp
index eda1ad03fd..178c9281ed 100644
--- a/backends/graphics/opengl/opengl-graphics.cpp
+++ b/backends/graphics/opengl/opengl-graphics.cpp
@@ -1116,7 +1116,7 @@ Surface *OpenGLGraphicsManager::createSurface(const Graphics::PixelFormat &forma
 		if (!supported) {
 			return nullptr;
 		} else {
-			return new TextureCLUT8(glIntFormat, glFormat, glType, virtFormat);
+			return new FakeTexture(glIntFormat, glFormat, glType, virtFormat, format);
 		}
 	} else if (getGLPixelFormat(format, glIntFormat, glFormat, glType)) {
 		return new Texture(glIntFormat, glFormat, glType, format);
diff --git a/backends/graphics/opengl/texture.cpp b/backends/graphics/opengl/texture.cpp
index 1695517d79..745ff9f1b2 100644
--- a/backends/graphics/opengl/texture.cpp
+++ b/backends/graphics/opengl/texture.cpp
@@ -314,143 +314,60 @@ void Texture::updateGLTexture() {
 	clearDirty();
 }
 
-TextureCLUT8::TextureCLUT8(GLenum glIntFormat, GLenum glFormat, GLenum glType, const Graphics::PixelFormat &format)
-	: Texture(glIntFormat, glFormat, glType, format), _clut8Data(), _palette(new byte[256 * format.bytesPerPixel]) {
-	memset(_palette, 0, sizeof(byte) * format.bytesPerPixel);
+FakeTexture::FakeTexture(GLenum glIntFormat, GLenum glFormat, GLenum glType, const Graphics::PixelFormat &format, const Graphics::PixelFormat &fakeFormat)
+	: Texture(glIntFormat, glFormat, glType, format),
+	  _fakeFormat(fakeFormat),
+	  _rgbData(),
+	  _palette(nullptr) {
+	if (_fakeFormat == Graphics::PixelFormat::createFormatCLUT8()) {
+		_palette = new uint32[256];
+		memset(_palette, 0, sizeof(uint32));
+	}
 }
 
-TextureCLUT8::~TextureCLUT8() {
+FakeTexture::~FakeTexture() {
 	delete[] _palette;
 	_palette = nullptr;
-	_clut8Data.free();
+	_rgbData.free();
 }
 
-void TextureCLUT8::allocate(uint width, uint height) {
+void FakeTexture::allocate(uint width, uint height) {
 	Texture::allocate(width, height);
 
-	// We only need to reinitialize our CLUT8 surface when the output size
+	// We only need to reinitialize our surface when the output size
 	// changed.
-	if (width == (uint)_clut8Data.w && height == (uint)_clut8Data.h) {
+	if (width == (uint)_rgbData.w && height == (uint)_rgbData.h) {
 		return;
 	}
 
-	_clut8Data.create(width, height, Graphics::PixelFormat::createFormatCLUT8());
+	_rgbData.create(width, height, getFormat());
 }
 
-Graphics::PixelFormat TextureCLUT8::getFormat() const {
-	return Graphics::PixelFormat::createFormatCLUT8();
-}
+void FakeTexture::setColorKey(uint colorKey) {
+	if (!_palette)
+		return;
 
-void TextureCLUT8::setColorKey(uint colorKey) {
 	// The key color is set to black so the color value is pre-multiplied with the alpha value
 	// to avoid color fringes due to filtering.
 	// Erasing the color data is not a problem as the palette is always fully re-initialized
 	// before setting the key color.
-	if (_format.bytesPerPixel == 2) {
-		uint16 *palette = (uint16 *)_palette + colorKey;
-		*palette = 0;
-	} else if (_format.bytesPerPixel == 4) {
-		uint32 *palette = (uint32 *)_palette + colorKey;
-		*palette = 0;
-	} else {
-		warning("TextureCLUT8::setColorKey: Unsupported pixel depth %d", _format.bytesPerPixel);
-	}
+	uint32 *palette = _palette + colorKey;
+	*palette = 0;
 
 	// A palette changes means we need to refresh the whole surface.
 	flagDirty();
 }
 
-namespace {
-template<typename ColorType>
-inline void convertPalette(ColorType *dst, const byte *src, uint colors, const Graphics::PixelFormat &format) {
-	while (colors-- > 0) {
-		*dst++ = format.RGBToColor(src[0], src[1], src[2]);
-		src += 3;
-	}
-}
-} // End of anonymous namespace
+void FakeTexture::setPalette(uint start, uint colors, const byte *palData) {
+	if (!_palette)
+		return;
 
-void TextureCLUT8::setPalette(uint start, uint colors, const byte *palData) {
-	if (_format.bytesPerPixel == 2) {
-		convertPalette<uint16>((uint16 *)_palette + start, palData, colors, _format);
-	} else if (_format.bytesPerPixel == 4) {
-		convertPalette<uint32>((uint32 *)_palette + start, palData, colors, _format);
-	} else {
-		warning("TextureCLUT8::setPalette: Unsupported pixel depth: %d", _format.bytesPerPixel);
-	}
+	Graphics::convertPaletteToMap(_palette + start, palData, colors, _format);
 
 	// A palette changes means we need to refresh the whole surface.
 	flagDirty();
 }
 
-namespace {
-template<typename PixelType>
-inline void doPaletteLookUp(PixelType *dst, const byte *src, uint width, uint height, uint dstPitch, uint srcPitch, const PixelType *palette) {
-	uint srcAdd = srcPitch - width;
-	uint dstAdd = dstPitch - width * sizeof(PixelType);
-
-	while (height-- > 0) {
-		for (uint x = width; x > 0; --x) {
-			*dst++ = palette[*src++];
-		}
-
-		dst = (PixelType *)((byte *)dst + dstAdd);
-		src += srcAdd;
-	}
-}
-} // End of anonymous namespace
-
-void TextureCLUT8::updateGLTexture() {
-	if (!isDirty()) {
-		return;
-	}
-
-	// Do the palette look up
-	Graphics::Surface *outSurf = Texture::getSurface();
-
-	Common::Rect dirtyArea = getDirtyArea();
-
-	if (outSurf->format.bytesPerPixel == 2) {
-		doPaletteLookUp<uint16>((uint16 *)outSurf->getBasePtr(dirtyArea.left, dirtyArea.top),
-		                        (const byte *)_clut8Data.getBasePtr(dirtyArea.left, dirtyArea.top),
-		                        dirtyArea.width(), dirtyArea.height(),
-		                        outSurf->pitch, _clut8Data.pitch, (const uint16 *)_palette);
-	} else if (outSurf->format.bytesPerPixel == 4) {
-		doPaletteLookUp<uint32>((uint32 *)outSurf->getBasePtr(dirtyArea.left, dirtyArea.top),
-		                        (const byte *)_clut8Data.getBasePtr(dirtyArea.left, dirtyArea.top),
-		                        dirtyArea.width(), dirtyArea.height(),
-		                        outSurf->pitch, _clut8Data.pitch, (const uint32 *)_palette);
-	} else {
-		warning("TextureCLUT8::updateGLTexture: Unsupported pixel depth: %d", outSurf->format.bytesPerPixel);
-	}
-
-	// Do generic handling of updating the texture.
-	Texture::updateGLTexture();
-}
-
-FakeTexture::FakeTexture(GLenum glIntFormat, GLenum glFormat, GLenum glType, const Graphics::PixelFormat &format, const Graphics::PixelFormat &fakeFormat)
-	: Texture(glIntFormat, glFormat, glType, format),
-	  _fakeFormat(fakeFormat),
-	  _rgbData() {
-}
-
-FakeTexture::~FakeTexture() {
-	_rgbData.free();
-}
-
-void FakeTexture::allocate(uint width, uint height) {
-	Texture::allocate(width, height);
-
-	// We only need to reinitialize our surface when the output size
-	// changed.
-	if (width == (uint)_rgbData.w && height == (uint)_rgbData.h) {
-		return;
-	}
-
-	warning("%s pixel format not supported by OpenGL ES, using %s instead", getFormat().toString().c_str(), _format.toString().c_str());
-	_rgbData.create(width, height, getFormat());
-}
-
 void FakeTexture::updateGLTexture() {
 	if (!isDirty()) {
 		return;
@@ -463,7 +380,12 @@ void FakeTexture::updateGLTexture() {
 
 	byte *dst = (byte *)outSurf->getBasePtr(dirtyArea.left, dirtyArea.top);
 	const byte *src = (const byte *)_rgbData.getBasePtr(dirtyArea.left, dirtyArea.top);
-	Graphics::crossBlit(dst, src, outSurf->pitch, _rgbData.pitch, dirtyArea.width(), dirtyArea.height(), outSurf->format, _rgbData.format);
+
+	if (_palette) {
+		Graphics::crossBlitMap(dst, src, outSurf->pitch, _rgbData.pitch, dirtyArea.width(), dirtyArea.height(), outSurf->format.bytesPerPixel, _palette);
+	} else {
+		Graphics::crossBlit(dst, src, outSurf->pitch, _rgbData.pitch, dirtyArea.width(), dirtyArea.height(), outSurf->format, _rgbData.format);
+	}
 
 	// Do generic handling of updating the texture.
 	Texture::updateGLTexture();
diff --git a/backends/graphics/opengl/texture.h b/backends/graphics/opengl/texture.h
index aed42405f4..70c9feeb78 100644
--- a/backends/graphics/opengl/texture.h
+++ b/backends/graphics/opengl/texture.h
@@ -295,29 +295,6 @@ private:
 	Graphics::Surface _userPixelData;
 };
 
-class TextureCLUT8 : public Texture {
-public:
-	TextureCLUT8(GLenum glIntFormat, GLenum glFormat, GLenum glType, const Graphics::PixelFormat &format);
-	virtual ~TextureCLUT8();
-
-	virtual void allocate(uint width, uint height);
-
-	virtual Graphics::PixelFormat getFormat() const;
-
-	virtual bool hasPalette() const { return true; }
-
-	virtual void setColorKey(uint colorKey);
-	virtual void setPalette(uint start, uint colors, const byte *palData);
-
-	virtual Graphics::Surface *getSurface() { return &_clut8Data; }
-	virtual const Graphics::Surface *getSurface() const { return &_clut8Data; }
-
-	virtual void updateGLTexture();
-private:
-	Graphics::Surface _clut8Data;
-	byte *_palette;
-};
-
 class FakeTexture : public Texture {
 public:
 	FakeTexture(GLenum glIntFormat, GLenum glFormat, GLenum glType, const Graphics::PixelFormat &format, const Graphics::PixelFormat &fakeFormat);
@@ -327,6 +304,11 @@ public:
 
 	virtual Graphics::PixelFormat getFormat() const { return _fakeFormat; }
 
+	virtual bool hasPalette() const { return (_palette != nullptr); }
+
+	virtual void setColorKey(uint colorKey);
+	virtual void setPalette(uint start, uint colors, const byte *palData);
+
 	virtual Graphics::Surface *getSurface() { return &_rgbData; }
 	virtual const Graphics::Surface *getSurface() const { return &_rgbData; }
 
@@ -334,6 +316,7 @@ public:
 protected:
 	Graphics::Surface _rgbData;
 	Graphics::PixelFormat _fakeFormat;
+	uint32 *_palette;
 };
 
 class TextureRGB555 : public FakeTexture {


Commit: fe5b87d0f1f8574e321a93e4ee82d9eeb9d8a704
    https://github.com/scummvm/scummvm/commit/fe5b87d0f1f8574e321a93e4ee82d9eeb9d8a704
Author: Cameron Cawley (ccawley2011 at gmail.com)
Date: 2021-11-20T01:06:23+01:00

Commit Message:
OPENGL: Implement scaler support

Changed paths:
    backends/graphics/opengl/opengl-graphics.cpp
    backends/graphics/opengl/opengl-graphics.h
    backends/graphics/opengl/texture.cpp
    backends/graphics/opengl/texture.h


diff --git a/backends/graphics/opengl/opengl-graphics.cpp b/backends/graphics/opengl/opengl-graphics.cpp
index 178c9281ed..beb2163954 100644
--- a/backends/graphics/opengl/opengl-graphics.cpp
+++ b/backends/graphics/opengl/opengl-graphics.cpp
@@ -48,6 +48,9 @@
 #include "graphics/fontman.h"
 #include "graphics/font.h"
 #endif
+#ifdef USE_SCALERS
+#include "graphics/scalerplugin.h"
+#endif
 
 #ifdef USE_PNG
 #include "image/png.h"
@@ -71,6 +74,9 @@ OpenGLGraphicsManager::OpenGLGraphicsManager()
 #ifdef USE_OSD
 	  , _osdMessageChangeRequest(false), _osdMessageAlpha(0), _osdMessageFadeStartTime(0), _osdMessageSurface(nullptr),
 	  _osdIconSurface(nullptr)
+#endif
+#ifdef USE_SCALERS
+	  , _scalerPlugins(ScalerMan.getPlugins())
 #endif
 	{
 	memset(_gamePalette, 0, sizeof(_gamePalette));
@@ -96,6 +102,9 @@ bool OpenGLGraphicsManager::hasFeature(OSystem::Feature f) const {
 	case OSystem::kFeatureCursorPalette:
 	case OSystem::kFeatureFilteringMode:
 	case OSystem::kFeatureStretchMode:
+#ifdef USE_SCALERS
+	case OSystem::kFeatureScalers:
+#endif
 		return true;
 
 	case OSystem::kFeatureOverlaySupportsAlpha:
@@ -290,6 +299,39 @@ int OpenGLGraphicsManager::getStretchMode() const {
 	return _stretchMode;
 }
 
+#ifdef USE_SCALERS
+uint OpenGLGraphicsManager::getDefaultScaler() const {
+	return ScalerMan.findScalerPluginIndex("normal");
+}
+
+uint OpenGLGraphicsManager::getDefaultScaleFactor() const {
+	return 1;
+}
+
+bool OpenGLGraphicsManager::setScaler(uint mode, int factor) {
+	assert(_transactionMode != kTransactionNone);
+
+	int newFactor;
+	if (factor == -1)
+		newFactor = getDefaultScaleFactor();
+	else if (_scalerPlugins[mode]->get<ScalerPluginObject>().hasFactor(factor))
+		newFactor = factor;
+	else if (_scalerPlugins[mode]->get<ScalerPluginObject>().hasFactor(_oldState.scaleFactor))
+		newFactor = _oldState.scaleFactor;
+	else
+		newFactor = _scalerPlugins[mode]->get<ScalerPluginObject>().getFactor();
+
+	_currentState.scalerIndex = mode;
+	_currentState.scaleFactor = newFactor;
+
+	return true;
+}
+
+uint OpenGLGraphicsManager::getScaler() const {
+	return _currentState.scalerIndex;
+}
+#endif
+
 void OpenGLGraphicsManager::beginGFXTransaction() {
 	assert(_transactionMode == kTransactionNone);
 
@@ -323,6 +365,13 @@ OSystem::TransactionError OpenGLGraphicsManager::endGFXTransaction() {
 	}
 #endif
 
+#ifdef USE_SCALERS
+	if (_oldState.scaleFactor != _currentState.scaleFactor ||
+	    _oldState.scalerIndex != _currentState.scalerIndex) {
+		setupNewGameScreen = true;
+	}
+#endif
+
 	do {
 		const uint desiredAspect = getDesiredGameAspectRatio();
 		const uint requestedWidth  = _currentState.gameWidth;
@@ -368,6 +417,11 @@ OSystem::TransactionError OpenGLGraphicsManager::endGFXTransaction() {
 					if (_oldState.filtering != _currentState.filtering) {
 						transactionError |= OSystem::kTransactionFilteringFailed;
 					}
+#ifdef USE_SCALERS
+					if (_oldState.scalerIndex != _currentState.scalerIndex) {
+						transactionError |= OSystem::kTransactionModeSwitchFailed;
+					}
+#endif
 
 					// Roll back to the old state.
 					_currentState = _oldState;
@@ -391,19 +445,29 @@ OSystem::TransactionError OpenGLGraphicsManager::endGFXTransaction() {
 	} while (_transactionMode == kTransactionRollback);
 
 	if (setupNewGameScreen) {
+		if (_gameScreen)
+			_gameScreen->unloadScaler();
 		delete _gameScreen;
 		_gameScreen = nullptr;
 
+		bool wantScaler = _currentState.scaleFactor > 1;
+
 #ifdef USE_RGB_COLOR
-		_gameScreen = createSurface(_currentState.gameFormat);
+		_gameScreen = createSurface(_currentState.gameFormat, false, wantScaler);
 #else
-		_gameScreen = createSurface(Graphics::PixelFormat::createFormatCLUT8());
+		_gameScreen = createSurface(Graphics::PixelFormat::createFormatCLUT8(), false, wantScaler);
 #endif
 		assert(_gameScreen);
 		if (_gameScreen->hasPalette()) {
 			_gameScreen->setPalette(0, 256, _gamePalette);
 		}
 
+#ifdef USE_SCALERS
+		if (wantScaler) {
+			_gameScreen->setScaler(_currentState.scalerIndex, _currentState.scaleFactor);
+		}
+#endif
+
 		_gameScreen->allocate(_currentState.gameWidth, _currentState.gameHeight);
 		_gameScreen->enableLinearFiltering(_currentState.filtering);
 		// We fill the screen to all black or index 0 for CLUT8.
@@ -734,6 +798,7 @@ void OpenGLGraphicsManager::setMouseCursor(const void *buf, uint w, uint h, int
 		} else {
 			textureFormat = _defaultFormatAlpha;
 		}
+		// TODO: Enable SW scaling for cursors
 		_cursor = createSurface(textureFormat, true);
 		assert(_cursor);
 		_cursor->enableLinearFiltering(_currentState.filtering);
@@ -1102,8 +1167,24 @@ void OpenGLGraphicsManager::notifyContextDestroy() {
 	g_context.reset();
 }
 
-Surface *OpenGLGraphicsManager::createSurface(const Graphics::PixelFormat &format, bool wantAlpha) {
+Surface *OpenGLGraphicsManager::createSurface(const Graphics::PixelFormat &format, bool wantAlpha, bool wantScaler) {
 	GLenum glIntFormat, glFormat, glType;
+
+#ifdef USE_SCALERS
+	if (wantScaler) {
+		// TODO: Ensure that the requested pixel format is supported by the scaler
+		if (getGLPixelFormat(format, glIntFormat, glFormat, glType)) {
+			return new ScaledTexture(glIntFormat, glFormat, glType, format, format);
+		} else {
+#ifdef SCUMM_LITTLE_ENDIAN
+			return new ScaledTexture(GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, Graphics::PixelFormat(4, 8, 8, 8, 8, 0, 8, 16, 24), format);
+#else
+			return new ScaledTexture(GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0), format);
+#endif
+		}
+	}
+#endif
+
 	if (format.bytesPerPixel == 1) {
 #if !USE_FORCED_GLES
 		if (TextureCLUT8GPU::isSupportedByContext()) {
@@ -1242,6 +1323,10 @@ bool OpenGLGraphicsManager::gameNeedsAspectRatioCorrection() const {
 	return false;
 }
 
+int OpenGLGraphicsManager::getGameRenderScale() const {
+	return _currentState.scaleFactor;
+}
+
 void OpenGLGraphicsManager::recalculateDisplayAreas() {
 	if (!_gameScreen) {
 		return;
diff --git a/backends/graphics/opengl/opengl-graphics.h b/backends/graphics/opengl/opengl-graphics.h
index ecb00a2ead..3de23ff2d3 100644
--- a/backends/graphics/opengl/opengl-graphics.h
+++ b/backends/graphics/opengl/opengl-graphics.h
@@ -79,6 +79,13 @@ public:
 	bool setStretchMode(int mode) override;
 	int getStretchMode() const override;
 
+#ifdef USE_SCALERS
+	uint getDefaultScaler() const override;
+	uint getDefaultScaleFactor() const override;
+	bool setScaler(uint mode, int factor) override;
+	uint getScaler() const override;
+#endif
+
 	void beginGFXTransaction() override;
 	OSystem::TransactionError endGFXTransaction() override;
 
@@ -157,13 +164,14 @@ protected:
 	/**
 	 * Create a surface with the specified pixel format.
 	 *
-	 * @param format    The pixel format the Surface object should accept as
-	 *                  input.
-	 * @param wantAlpha For CLUT8 surfaces this marks whether an alpha
-	 *                  channel should be used.
+	 * @param format     The pixel format the Surface object should accept as
+	 *                   input.
+	 * @param wantAlpha  For CLUT8 surfaces this marks whether an alpha
+	 *                   channel should be used.
+	 * @param wantScaler Whether or not a software scaler should be used.
 	 * @return A pointer to the surface or nullptr on failure.
 	 */
-	Surface *createSurface(const Graphics::PixelFormat &format, bool wantAlpha = false);
+	Surface *createSurface(const Graphics::PixelFormat &format, bool wantAlpha = false, bool wantScaler = false);
 
 	//
 	// Transaction support
@@ -173,7 +181,8 @@ protected:
 #ifdef USE_RGB_COLOR
 		    gameFormat(),
 #endif
-		    aspectRatioCorrection(false), graphicsMode(GFX_OPENGL), filtering(true) {
+		    aspectRatioCorrection(false), graphicsMode(GFX_OPENGL), filtering(true),
+		    scalerIndex(0), scaleFactor(1) {
 		}
 
 		bool valid;
@@ -186,6 +195,9 @@ protected:
 		int graphicsMode;
 		bool filtering;
 
+		uint scalerIndex;
+		int scaleFactor;
+
 		bool operator==(const VideoState &right) {
 			return gameWidth == right.gameWidth && gameHeight == right.gameHeight
 #ifdef USE_RGB_COLOR
@@ -315,6 +327,7 @@ protected:
 	bool getGLPixelFormat(const Graphics::PixelFormat &pixelFormat, GLenum &glIntFormat, GLenum &glFormat, GLenum &glType) const;
 
 	bool gameNeedsAspectRatioCorrection() const override;
+	int getGameRenderScale() const override;
 	void recalculateDisplayAreas() override;
 	void handleResizeImpl(const int width, const int height) override;
 
@@ -419,6 +432,13 @@ protected:
 	 */
 	byte _cursorPalette[3 * 256];
 
+#ifdef USE_SCALERS
+	/**
+	 * The list of scaler plugins
+	 */
+	const PluginList &_scalerPlugins;
+#endif
+
 #ifdef USE_OSD
 	//
 	// OSD
diff --git a/backends/graphics/opengl/texture.cpp b/backends/graphics/opengl/texture.cpp
index 745ff9f1b2..1c6e1c6e37 100644
--- a/backends/graphics/opengl/texture.cpp
+++ b/backends/graphics/opengl/texture.cpp
@@ -33,6 +33,10 @@
 
 #include "graphics/conversion.h"
 
+#ifdef USE_SCALERS
+#include "graphics/scalerplugin.h"
+#endif
+
 namespace OpenGL {
 
 GLTexture::GLTexture(GLenum glIntFormat, GLenum glFormat, GLenum glType)
@@ -279,6 +283,10 @@ void Texture::updateGLTexture() {
 
 	Common::Rect dirtyArea = getDirtyArea();
 
+	updateGLTexture(dirtyArea);
+}
+
+void Texture::updateGLTexture(Common::Rect &dirtyArea) {
 	// In case we use linear filtering we might need to duplicate the last
 	// pixel row/column to avoid glitches with filtering.
 	if (_glTexture.isLinearFilteringEnabled()) {
@@ -468,6 +476,109 @@ void TextureRGBA8888Swap::updateGLTexture() {
 	Texture::updateGLTexture();
 }
 
+#ifdef USE_SCALERS
+
+ScaledTexture::ScaledTexture(GLenum glIntFormat, GLenum glFormat, GLenum glType, const Graphics::PixelFormat &format, const Graphics::PixelFormat &fakeFormat)
+	: FakeTexture(glIntFormat, glFormat, glType, format, fakeFormat), _convData(nullptr), _scalerPlugin(nullptr), _scaleFactor(1), _extraPixels(0) {
+}
+
+ScaledTexture::~ScaledTexture() {
+	if (_convData) {
+		_convData->free();
+		delete _convData;
+	}
+}
+
+void ScaledTexture::allocate(uint width, uint height) {
+	Texture::allocate(width * _scaleFactor, height * _scaleFactor);
+
+	// We only need to reinitialize our surface when the output size
+	// changed.
+	if (width != (uint)_rgbData.w || height != (uint)_rgbData.h) {
+		_rgbData.create(width, height, _fakeFormat);
+	}
+
+	if (_format != _fakeFormat || _extraPixels != 0) {
+		if (!_convData)
+			_convData = new Graphics::Surface();
+
+		_convData->create(width + (_extraPixels * 2), height + (_extraPixels * 2), _format);
+	} else if (_convData) {
+		_convData->free();
+		delete _convData;
+		_convData = nullptr;
+	}
+}
+
+void ScaledTexture::updateGLTexture() {
+	if (!isDirty()) {
+		return;
+	}
+
+	// Convert color space.
+	Graphics::Surface *outSurf = Texture::getSurface();
+
+	Common::Rect dirtyArea = getDirtyArea();
+
+	const byte *src = (const byte *)_rgbData.getBasePtr(dirtyArea.left, dirtyArea.top);
+	uint srcPitch = _rgbData.pitch;
+	byte *dst;
+	uint dstPitch;
+
+	if (_convData) {
+		dst = (byte *)_convData->getBasePtr(dirtyArea.left + _extraPixels, dirtyArea.top + _extraPixels);
+		dstPitch = _convData->pitch;
+
+		if (_palette) {
+			Graphics::crossBlitMap(dst, src, dstPitch, srcPitch, dirtyArea.width(), dirtyArea.height(), _convData->format.bytesPerPixel, _palette);
+		} else {
+			Graphics::crossBlit(dst, src, dstPitch, srcPitch, dirtyArea.width(), dirtyArea.height(), _convData->format, _rgbData.format);
+		}
+
+		src = dst;
+		srcPitch = dstPitch;
+	}
+
+	dst = (byte *)outSurf->getBasePtr(dirtyArea.left * _scaleFactor, dirtyArea.top * _scaleFactor);
+	dstPitch = outSurf->pitch;
+
+	assert(_scalerPlugin);
+	_scalerPlugin->scale(src, srcPitch, dst, dstPitch, dirtyArea.width(), dirtyArea.height(), dirtyArea.left, dirtyArea.top);
+
+	dirtyArea.left   *= _scaleFactor;
+	dirtyArea.right  *= _scaleFactor;
+	dirtyArea.top    *= _scaleFactor;
+	dirtyArea.bottom *= _scaleFactor;
+
+	// Do generic handling of updating the texture.
+	Texture::updateGLTexture(dirtyArea);
+}
+
+void ScaledTexture::setScaler(uint scalerIndex, int scaleFactor) {
+	const PluginList &scalerPlugins = ScalerMan.getPlugins();
+
+	// If the scalerIndex has changed, change scaler plugins
+	if (&scalerPlugins[scalerIndex]->get<ScalerPluginObject>() != _scalerPlugin) {
+		if (_scalerPlugin)
+			_scalerPlugin->deinitialize();
+
+		_scalerPlugin = &scalerPlugins[scalerIndex]->get<ScalerPluginObject>();
+		_scalerPlugin->initialize(_format);
+	}
+	_scalerPlugin->setFactor(scaleFactor);
+
+	_scaleFactor = _scalerPlugin->getFactor();
+	_extraPixels = _scalerPlugin->extraPixels();
+}
+
+void ScaledTexture::unloadScaler() {
+	if (_scalerPlugin) {
+		_scalerPlugin->deinitialize();
+		_scalerPlugin = nullptr;
+	}
+}
+#endif
+
 #if !USE_FORCED_GLES
 
 // _clut8Texture needs 8 bits internal precision, otherwise graphics glitches
diff --git a/backends/graphics/opengl/texture.h b/backends/graphics/opengl/texture.h
index 70c9feeb78..aaaa968adb 100644
--- a/backends/graphics/opengl/texture.h
+++ b/backends/graphics/opengl/texture.h
@@ -30,6 +30,8 @@
 
 #include "common/rect.h"
 
+class ScalerPluginObject;
+
 namespace OpenGL {
 
 class Shader;
@@ -229,6 +231,9 @@ public:
 	virtual void setColorKey(uint colorKey) {}
 	virtual void setPalette(uint start, uint colors, const byte *palData) {}
 
+	virtual void setScaler(uint scalerIndex, int scaleFactor) {}
+	virtual void unloadScaler() {}
+
 	/**
 	 * Update underlying OpenGL texture to reflect current state.
 	 */
@@ -288,6 +293,8 @@ public:
 protected:
 	const Graphics::PixelFormat _format;
 
+	void updateGLTexture(Common::Rect &dirtyArea);
+
 private:
 	GLTexture _glTexture;
 
@@ -335,6 +342,35 @@ public:
 	virtual void updateGLTexture();
 };
 
+#ifdef USE_SCALERS
+class ScaledTexture : public FakeTexture {
+public:
+	ScaledTexture(GLenum glIntFormat, GLenum glFormat, GLenum glType, const Graphics::PixelFormat &format, const Graphics::PixelFormat &fakeFormat);
+	virtual ~ScaledTexture();
+
+	virtual void allocate(uint width, uint height);
+
+	virtual uint getWidth() const { return _rgbData.w; }
+	virtual uint getHeight() const { return _rgbData.h; }
+	virtual Graphics::PixelFormat getFormat() const { return _fakeFormat; }
+
+	virtual bool hasPalette() const { return (_palette != nullptr); }
+
+	virtual Graphics::Surface *getSurface() { return &_rgbData; }
+	virtual const Graphics::Surface *getSurface() const { return &_rgbData; }
+
+	virtual void updateGLTexture();
+
+	virtual void setScaler(uint scalerIndex, int scaleFactor);
+	virtual void unloadScaler();
+protected:
+	Graphics::Surface *_convData;
+	ScalerPluginObject *_scalerPlugin;
+	uint _extraPixels;
+	uint _scaleFactor;
+};
+#endif
+
 #if !USE_FORCED_GLES
 class TextureTarget;
 class CLUT8LookUpPipeline;


Commit: 267f1f18fbfe2e802ecbc95c96283103d7c96942
    https://github.com/scummvm/scummvm/commit/267f1f18fbfe2e802ecbc95c96283103d7c96942
Author: Cameron Cawley (ccawley2011 at gmail.com)
Date: 2021-11-20T01:06:23+01:00

Commit Message:
ANDROID: Enable scalers by default

Changed paths:
    configure


diff --git a/configure b/configure
index 8f98e344d5..da7033f95e 100755
--- a/configure
+++ b/configure
@@ -3161,7 +3161,6 @@ if test -n "$_host"; then
 				_backend="android"
 			fi
 			_port_mk="backends/platform/$_backend/android.mk"
-			_build_scalers=no
 			_build_aspect=no
 			_seq_midi=no
 			_timidity=no


Commit: 2db20b702e05b16a9b8a6e0e0e0ea0799ea45459
    https://github.com/scummvm/scummvm/commit/2db20b702e05b16a9b8a6e0e0e0ea0799ea45459
Author: Cameron Cawley (ccawley2011 at gmail.com)
Date: 2021-11-20T01:06:23+01:00

Commit Message:
OPENGL: Implement cursor scaling

Changed paths:
    backends/graphics/opengl/opengl-graphics.cpp


diff --git a/backends/graphics/opengl/opengl-graphics.cpp b/backends/graphics/opengl/opengl-graphics.cpp
index beb2163954..e1489852ea 100644
--- a/backends/graphics/opengl/opengl-graphics.cpp
+++ b/backends/graphics/opengl/opengl-graphics.cpp
@@ -763,6 +763,8 @@ void OpenGLGraphicsManager::setMouseCursor(const void *buf, uint w, uint h, int
 	_cursorDontScale = dontScale;
 
 	if (!w || !h) {
+		if (_cursor)
+			_cursor->unloadScaler();
 		delete _cursor;
 		_cursor = nullptr;
 		return;
@@ -781,9 +783,17 @@ void OpenGLGraphicsManager::setMouseCursor(const void *buf, uint w, uint h, int
 
 	// In case the color format has changed we will need to create the texture.
 	if (!_cursor || _cursor->getFormat() != inputFormat) {
+		if (_cursor)
+			_cursor->unloadScaler();
 		delete _cursor;
 		_cursor = nullptr;
 
+#ifdef USE_SCALERS
+		bool wantScaler = (_currentState.scaleFactor > 1) && !dontScale
+		                && _scalerPlugins[_currentState.scalerIndex]->get<ScalerPluginObject>().canDrawCursor();
+#else
+		bool wantScaler = false;
+#endif
 		GLenum glIntFormat, glFormat, glType;
 
 		Graphics::PixelFormat textureFormat;
@@ -798,10 +808,14 @@ void OpenGLGraphicsManager::setMouseCursor(const void *buf, uint w, uint h, int
 		} else {
 			textureFormat = _defaultFormatAlpha;
 		}
-		// TODO: Enable SW scaling for cursors
-		_cursor = createSurface(textureFormat, true);
+		_cursor = createSurface(textureFormat, false, wantScaler);
 		assert(_cursor);
 		_cursor->enableLinearFiltering(_currentState.filtering);
+#ifdef USE_SCALERS
+		if (wantScaler) {
+			_cursor->setScaler(_currentState.scalerIndex, _currentState.scaleFactor);
+		}
+#endif
 	}
 
 	_cursor->allocate(w, h);


Commit: ba564bc66f053af96cbdd8810bb84484453342f1
    https://github.com/scummvm/scummvm/commit/ba564bc66f053af96cbdd8810bb84484453342f1
Author: Cameron Cawley (ccawley2011 at gmail.com)
Date: 2021-11-20T01:06:23+01:00

Commit Message:
NEWS: Mention scaler support in OpenGL mode

Changed paths:
    NEWS.md


diff --git a/NEWS.md b/NEWS.md
index a8f66e4004..2821e33870 100644
--- a/NEWS.md
+++ b/NEWS.md
@@ -11,6 +11,7 @@ For a more comprehensive changelog of the latest experimental code, see:
    - Implemented enhanced filtering in the Search box. See "Understanding
      the search box" in the documentation for details.
    - Implemented Icon view in GUI [GSoC task]
+   - Scalers are now supported with the OpenGL graphics mode.
 
  AGOS:
    - Fixed old Waxworks AdLib music regression.




More information about the Scummvm-git-logs mailing list