aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README1
-rw-r--r--backends/graphics/openglsdl/openglsdl-graphics.cpp83
-rw-r--r--backends/graphics/openglsdl/openglsdl-graphics.h6
-rw-r--r--backends/graphics/surfacesdl/surfacesdl-graphics.cpp101
-rw-r--r--backends/graphics/surfacesdl/surfacesdl-graphics.h11
-rw-r--r--backends/graphics/windowed.h60
6 files changed, 246 insertions, 16 deletions
diff --git a/README b/README
index 700811828d..9c0b25bdb2 100644
--- a/README
+++ b/README
@@ -1718,6 +1718,7 @@ other games.
stretches the image to use 320x240 pixels
instead, or a multiple thereof
Ctrl-Alt f - Enable/disable graphics filtering
+ Ctrl-Alt s - Cycle through scaling modes
Alt-Enter - Toggles full screen/windowed
Alt-s - Make a screenshot (SDL backend only)
Ctrl-F7 - Open virtual keyboard (if enabled)
diff --git a/backends/graphics/openglsdl/openglsdl-graphics.cpp b/backends/graphics/openglsdl/openglsdl-graphics.cpp
index 3209905085..8dcc5582a9 100644
--- a/backends/graphics/openglsdl/openglsdl-graphics.cpp
+++ b/backends/graphics/openglsdl/openglsdl-graphics.cpp
@@ -39,7 +39,7 @@ OpenGLSdlGraphicsManager::OpenGLSdlGraphicsManager(uint desktopWidth, uint deskt
#else
_lastVideoModeLoad(0),
#endif
- _graphicsScale(2), _ignoreLoadVideoMode(false), _gotResize(false), _wantsFullScreen(false), _ignoreResizeEvents(0),
+ _graphicsScale(2), _stretchMode(STRETCH_FIT), _ignoreLoadVideoMode(false), _gotResize(false), _wantsFullScreen(false), _ignoreResizeEvents(0),
_desiredFullscreenWidth(0), _desiredFullscreenHeight(0) {
// Setup OpenGL attributes for SDL
SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
@@ -266,6 +266,54 @@ bool OpenGLSdlGraphicsManager::getFeatureState(OSystem::Feature f) const {
}
}
+namespace {
+const OSystem::GraphicsMode sdlGlStretchModes[] = {
+ {"center", _s("Center"), STRETCH_CENTER},
+ {"pixel-perfect", _s("Pixel-perfect scaling"), STRETCH_INTEGRAL},
+ {"fit", _s("Fit to window"), STRETCH_FIT},
+ {"stretch", _s("Stretch to window"), STRETCH_STRETCH},
+ {nullptr, nullptr, 0}
+};
+
+} // End of anonymous namespace
+
+const OSystem::GraphicsMode *OpenGLSdlGraphicsManager::getSupportedStretchModes() const {
+ return sdlGlStretchModes;
+}
+
+int OpenGLSdlGraphicsManager::getDefaultStretchMode() const {
+ return STRETCH_FIT;
+}
+
+bool OpenGLSdlGraphicsManager::setStretchMode(int mode) {
+ assert(getTransactionMode() != kTransactionNone);
+
+ if (mode == _stretchMode)
+ return true;
+
+ // Check this is a valid mode
+ const OSystem::GraphicsMode *sm = sdlGlStretchModes;
+ bool found = false;
+ while (sm->name) {
+ if (sm->id == mode) {
+ found = true;
+ break;
+ }
+ sm++;
+ }
+ if (!found) {
+ warning("unknown stretch mode %d", mode);
+ return false;
+ }
+
+ _stretchMode = mode;
+ return true;
+}
+
+int OpenGLSdlGraphicsManager::getStretchMode() const {
+ return _stretchMode;
+}
+
void OpenGLSdlGraphicsManager::initSize(uint w, uint h, const Graphics::PixelFormat *format) {
// HACK: This is stupid but the SurfaceSDL backend defaults to 2x. This
// assures that the launcher (which requests 320x200) has a reasonable
@@ -735,7 +783,7 @@ bool OpenGLSdlGraphicsManager::notifyEvent(const Common::Event &event) {
// Ctrl+Alt+f toggles filtering on/off
beginGFXTransaction();
- setFeatureState(OSystem::kFeatureFilteringMode, !getFeatureState(OSystem::kFeatureFilteringMode));
+ setFeatureState(OSystem::kFeatureFilteringMode, !getFeatureState(OSystem::kFeatureFilteringMode));
endGFXTransaction();
// Make sure we do not ignore the next resize. This
@@ -751,6 +799,34 @@ bool OpenGLSdlGraphicsManager::notifyEvent(const Common::Event &event) {
#endif
return true;
+ } else if (event.kbd.keycode == Common::KEYCODE_s) {
+ // Never try to resize the window when changing the scaling mode.
+ _ignoreLoadVideoMode = true;
+
+ // Ctrl+Alt+s cycles through stretch mode
+ int index = 0;
+ const OSystem::GraphicsMode *sm = sdlGlStretchModes;
+ while (sm->name) {
+ if (sm->id == _stretchMode)
+ break;
+ sm++;
+ index++;
+ }
+ index++;
+ if (!sdlGlStretchModes[index].name)
+ index = 0;
+ beginGFXTransaction();
+ setStretchMode(sdlGlStretchModes[index].id);
+ endGFXTransaction();
+
+#ifdef USE_OSD
+ Common::String message = Common::String::format("%s: %s",
+ _("Stretch mode"),
+ _(sdlGlStretchModes[index].description)
+ );
+ displayMessageOnOSD(message.c_str());
+#endif
+ return true;
}
}
// Fall through
@@ -769,7 +845,8 @@ bool OpenGLSdlGraphicsManager::isHotkey(const Common::Event &event) const {
return event.kbd.keycode == Common::KEYCODE_PLUS || event.kbd.keycode == Common::KEYCODE_MINUS
|| event.kbd.keycode == Common::KEYCODE_KP_PLUS || event.kbd.keycode == Common::KEYCODE_KP_MINUS
|| event.kbd.keycode == Common::KEYCODE_a
- || event.kbd.keycode == Common::KEYCODE_f;
+ || event.kbd.keycode == Common::KEYCODE_f
+ || event.kbd.keycode == Common::KEYCODE_s;
}
return false;
diff --git a/backends/graphics/openglsdl/openglsdl-graphics.h b/backends/graphics/openglsdl/openglsdl-graphics.h
index 954c7215a4..b6ea496575 100644
--- a/backends/graphics/openglsdl/openglsdl-graphics.h
+++ b/backends/graphics/openglsdl/openglsdl-graphics.h
@@ -43,6 +43,11 @@ public:
virtual void setFeatureState(OSystem::Feature f, bool enable) override;
virtual bool getFeatureState(OSystem::Feature f) const override;
+ virtual const OSystem::GraphicsMode *getSupportedStretchModes() const override;
+ virtual int getDefaultStretchMode() const override;
+ virtual bool setStretchMode(int mode) override;
+ virtual int getStretchMode() const override;
+
virtual void initSize(uint w, uint h, const Graphics::PixelFormat *format) override;
#ifdef USE_RGB_COLOR
@@ -82,6 +87,7 @@ private:
uint _lastRequestedWidth;
uint _lastRequestedHeight;
uint _graphicsScale;
+ int _stretchMode;
bool _ignoreLoadVideoMode;
bool _gotResize;
diff --git a/backends/graphics/surfacesdl/surfacesdl-graphics.cpp b/backends/graphics/surfacesdl/surfacesdl-graphics.cpp
index fd6e2bd400..654dbd7c97 100644
--- a/backends/graphics/surfacesdl/surfacesdl-graphics.cpp
+++ b/backends/graphics/surfacesdl/surfacesdl-graphics.cpp
@@ -71,6 +71,16 @@ static const OSystem::GraphicsMode s_supportedGraphicsModes[] = {
{0, 0, 0}
};
+#if SDL_VERSION_ATLEAST(2, 0, 0)
+const OSystem::GraphicsMode s_supportedStretchModes[] = {
+ {"center", _s("Center"), STRETCH_CENTER},
+ {"pixel-perfect", _s("Pixel-perfect scaling"), STRETCH_INTEGRAL},
+ {"fit", _s("Fit to window"), STRETCH_FIT},
+ {"stretch", _s("Stretch to window"), STRETCH_STRETCH},
+ {nullptr, nullptr, 0}
+};
+#endif
+
DECLARE_TRANSLATION_ADDITIONAL_CONTEXT("Normal (no scaling)", "lowres")
// Table of the cursor scalers [scaleFactor - 1]
@@ -196,6 +206,7 @@ SurfaceSdlGraphicsManager::SurfaceSdlGraphicsManager(SdlEventSource *sdlEventSou
#if SDL_VERSION_ATLEAST(2, 0, 0)
_videoMode.filtering = ConfMan.getBool("filtering");
+ _videoMode.stretchMode = STRETCH_FIT;
#endif
// the default backend has no shaders
@@ -323,6 +334,7 @@ void SurfaceSdlGraphicsManager::beginGFXTransaction() {
_transactionDetails.needHotswap = false;
_transactionDetails.needUpdatescreen = false;
+ _transactionDetails.needDisplayResize = false;
#if SDL_VERSION_ATLEAST(2, 0, 0)
_transactionDetails.needTextureUpdate = false;
@@ -354,6 +366,10 @@ OSystem::TransactionError SurfaceSdlGraphicsManager::endGFXTransaction() {
_videoMode.mode = _oldVideoMode.mode;
_videoMode.scaleFactor = _oldVideoMode.scaleFactor;
#if SDL_VERSION_ATLEAST(2, 0, 0)
+ } else if (_videoMode.stretchMode != _oldVideoMode.stretchMode) {
+ errors |= OSystem::kTransactionStretchModeSwitchFailed;
+
+ _videoMode.stretchMode = _oldVideoMode.stretchMode;
} else if (_videoMode.filtering != _oldVideoMode.filtering) {
errors |= OSystem::kTransactionFilteringFailed;
@@ -431,6 +447,8 @@ OSystem::TransactionError SurfaceSdlGraphicsManager::endGFXTransaction() {
// To fix this issue we update the screen change count right here.
_screenChangeCount++;
+ if (_transactionDetails.needDisplayResize)
+ recalculateDisplayAreas();
if (_transactionDetails.needUpdatescreen)
internUpdateScreen();
}
@@ -438,10 +456,14 @@ OSystem::TransactionError SurfaceSdlGraphicsManager::endGFXTransaction() {
} else if (_transactionDetails.needTextureUpdate) {
setGraphicsModeIntern();
recreateScreenTexture();
+ if (_transactionDetails.needDisplayResize)
+ recalculateDisplayAreas();
internUpdateScreen();
#endif
} else if (_transactionDetails.needUpdatescreen) {
setGraphicsModeIntern();
+ if (_transactionDetails.needDisplayResize)
+ recalculateDisplayAreas();
internUpdateScreen();
}
@@ -745,6 +767,51 @@ bool SurfaceSdlGraphicsManager::setShader(int id) {
return true;
}
+#if SDL_VERSION_ATLEAST(2, 0, 0)
+const OSystem::GraphicsMode *SurfaceSdlGraphicsManager::getSupportedStretchModes() const {
+ return s_supportedStretchModes;
+}
+
+int SurfaceSdlGraphicsManager::getDefaultStretchMode() const {
+ return STRETCH_FIT;
+}
+
+bool SurfaceSdlGraphicsManager::setStretchMode(int mode) {
+ Common::StackLock lock(_graphicsMutex);
+
+ assert(_transactionMode == kTransactionActive);
+
+ if (_oldVideoMode.setup && _oldVideoMode.stretchMode == mode)
+ return true;
+
+ // Check this is a valid mode
+ const OSystem::GraphicsMode *sm = s_supportedStretchModes;
+ bool found = false;
+ while (sm->name) {
+ if (sm->id == mode) {
+ found = true;
+ break;
+ }
+ sm++;
+ }
+ if (!found) {
+ warning("unknown stretch mode %d", mode);
+ return false;
+ }
+
+ _transactionDetails.needUpdatescreen = true;
+ _transactionDetails.needDisplayResize = true;
+
+ _videoMode.stretchMode = mode;
+
+ return true;
+}
+
+int SurfaceSdlGraphicsManager::getStretchMode() const {
+ return _videoMode.stretchMode;
+}
+#endif
+
void SurfaceSdlGraphicsManager::initSize(uint w, uint h, const Graphics::PixelFormat *format) {
assert(_transactionMode == kTransactionActive);
@@ -2485,6 +2552,38 @@ bool SurfaceSdlGraphicsManager::handleScalerHotkeys(Common::KeyCode key) {
}
#endif
+#if SDL_VERSION_ATLEAST(2, 0, 0)
+ // Ctrl+Alt+s cycles through scaling mode (0 to 3)
+ if (key == 's') {
+ int index = 0;
+ const OSystem::GraphicsMode *sm = s_supportedStretchModes;
+ while (sm->name) {
+ if (sm->id == _videoMode.stretchMode)
+ break;
+ sm++;
+ index++;
+ }
+ index++;
+ if (!s_supportedStretchModes[index].name)
+ index = 0;
+
+ beginGFXTransaction();
+ setStretchMode(s_supportedStretchModes[index].id);
+ endGFXTransaction();
+
+#ifdef USE_OSD
+ Common::String message = Common::String::format("%s: %s",
+ _("Stretch mode"),
+ _(s_supportedStretchModes[index].description)
+ );
+ displayMessageOnOSD(message.c_str());
+#endif
+ _forceRedraw = true;
+ internUpdateScreen();
+ return true;
+ }
+#endif
+
int newMode = -1;
int factor = _videoMode.scaleFactor - 1;
SDLKey sdlKey = (SDLKey)key;
@@ -2575,6 +2674,8 @@ bool SurfaceSdlGraphicsManager::isScalerHotkey(const Common::Event &event) {
#if SDL_VERSION_ATLEAST(2, 0, 0)
if (event.kbd.keycode == 'f')
return true;
+ if (event.kbd.keycode == 's')
+ return true;
#endif
return (isScaleKey || event.kbd.keycode == 'a');
}
diff --git a/backends/graphics/surfacesdl/surfacesdl-graphics.h b/backends/graphics/surfacesdl/surfacesdl-graphics.h
index 9e8e75772d..6e7fec4823 100644
--- a/backends/graphics/surfacesdl/surfacesdl-graphics.h
+++ b/backends/graphics/surfacesdl/surfacesdl-graphics.h
@@ -98,6 +98,12 @@ public:
virtual const OSystem::GraphicsMode *getSupportedShaders() const override;
virtual int getShader() const override;
virtual bool setShader(int id) override;
+#if SDL_VERSION_ATLEAST(2, 0, 0)
+ virtual const OSystem::GraphicsMode *getSupportedStretchModes() const override;
+ virtual int getDefaultStretchMode() const override;
+ virtual bool setStretchMode(int mode) override;
+ virtual int getStretchMode() const override;
+#endif
virtual void initSize(uint w, uint h, const Graphics::PixelFormat *format = NULL) override;
virtual int getScreenChangeID() const override { return _screenChangeCount; }
@@ -174,6 +180,9 @@ protected:
virtual bool gameNeedsAspectRatioCorrection() const override {
return _videoMode.aspectRatioCorrection;
}
+ virtual int getGameRenderScale() const override {
+ return _videoMode.scaleFactor;
+ }
virtual void handleResizeImpl(const int width, const int height) override;
@@ -225,6 +234,7 @@ protected:
bool needUpdatescreen;
#if SDL_VERSION_ATLEAST(2, 0, 0)
bool needTextureUpdate;
+ bool needDisplayResize;
#endif
#ifdef USE_RGB_COLOR
bool formatChanged;
@@ -241,6 +251,7 @@ protected:
#if SDL_VERSION_ATLEAST(2, 0, 0)
bool filtering;
+ int stretchMode;
#endif
int mode;
diff --git a/backends/graphics/windowed.h b/backends/graphics/windowed.h
index 8a0bddf5be..4732ea9708 100644
--- a/backends/graphics/windowed.h
+++ b/backends/graphics/windowed.h
@@ -26,9 +26,17 @@
#include "backends/graphics/graphics.h"
#include "common/frac.h"
#include "common/rect.h"
+#include "common/config-manager.h"
#include "common/textconsole.h"
#include "graphics/scaler/aspect.h"
+enum {
+ STRETCH_CENTER = 0,
+ STRETCH_INTEGRAL = 1,
+ STRETCH_FIT = 2,
+ STRETCH_STRETCH = 3
+};
+
class WindowedGraphicsManager : virtual public GraphicsManager {
public:
WindowedGraphicsManager() :
@@ -136,6 +144,13 @@ protected:
}
/**
+ * @returns the scale used between the game size and the surface on which it is rendered.
+ */
+ virtual int getGameRenderScale() const {
+ return 1;
+ }
+
+ /**
* Called after the window has been updated with new dimensions.
*
* @param width The new width of the window, excluding window decoration.
@@ -156,13 +171,11 @@ protected:
return;
}
- const frac_t outputAspect = intToFrac(_windowWidth) / _windowHeight;
-
- populateDisplayAreaDrawRect(getDesiredGameAspectRatio(), outputAspect, _gameDrawRect);
+ populateDisplayAreaDrawRect(getDesiredGameAspectRatio(), getWidth() * getGameRenderScale(), _gameDrawRect);
if (getOverlayHeight()) {
const frac_t overlayAspect = intToFrac(getOverlayWidth()) / getOverlayHeight();
- populateDisplayAreaDrawRect(overlayAspect, outputAspect, _overlayDrawRect);
+ populateDisplayAreaDrawRect(overlayAspect, getOverlayWidth(), _overlayDrawRect);
}
if (_overlayVisible) {
@@ -316,15 +329,36 @@ protected:
int _cursorX, _cursorY;
private:
- void populateDisplayAreaDrawRect(const frac_t inputAspect, const frac_t outputAspect, Common::Rect &drawRect) const {
- int width = _windowWidth;
- int height = _windowHeight;
-
- // Maintain aspect ratios
- if (outputAspect < inputAspect) {
- height = intToFrac(width) / inputAspect;
- } else if (outputAspect > inputAspect) {
- width = fracToInt(height * inputAspect);
+ void populateDisplayAreaDrawRect(const frac_t displayAspect, int originalWidth, Common::Rect &drawRect) const {
+ int mode = getStretchMode();
+ // Mode Center = use original size, or divide by an integral amount if window is smaller than game surface
+ // Mode Integral = scale by an integral amount.
+ // Mode Fit = scale to fit the window while respecting the aspect ratio
+ // Mode Stretch = scale and stretch to fit the window without respecting the aspect ratio
+
+ int width = 0, height = 0;
+ if (mode == STRETCH_CENTER || mode == STRETCH_INTEGRAL) {
+ width = originalWidth;
+ height = intToFrac(width) / displayAspect;
+ if (width > _windowWidth || height > _windowHeight) {
+ int fac = 1 + MAX((width - 1) / _windowWidth, (height - 1) / _windowHeight);
+ width /= fac;
+ height /= fac;
+ } else if (mode == STRETCH_INTEGRAL) {
+ int fac = MIN(_windowWidth / width, _windowHeight / height);
+ width *= fac;
+ height *= fac;
+ }
+ } else {
+ frac_t windowAspect = intToFrac(_windowWidth) / _windowHeight;
+ width = _windowWidth;
+ height = _windowHeight;
+ if (mode != STRETCH_STRETCH) {
+ if (windowAspect < displayAspect)
+ height = intToFrac(width) / displayAspect;
+ else if (windowAspect > displayAspect)
+ width = fracToInt(height * displayAspect);
+ }
}
drawRect.left = (_windowWidth - width) / 2;