[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