aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorColin Snover2017-07-19 19:15:12 -0500
committerColin Snover2017-10-15 13:24:20 -0500
commitde2bbe3b9738ef95b2529db989570770ef434f9d (patch)
treeb1a2994225ca92ec454bd4108673f27a6222145b
parent0ad03e492ac030193536e3167e8bf428e88cafb3 (diff)
downloadscummvm-rg350-de2bbe3b9738ef95b2529db989570770ef434f9d.tar.gz
scummvm-rg350-de2bbe3b9738ef95b2529db989570770ef434f9d.tar.bz2
scummvm-rg350-de2bbe3b9738ef95b2529db989570770ef434f9d.zip
BACKENDS: Refactor OpenGL & SDL graphics backends
This patch refactors the OpenGL and SDL graphics backends, primarily to unify window scaling and mouse handling, and to fix coordinate mapping between the ScummVM window and the virtual game screen when they have different aspect ratios. Unified code for these two backends has been moved to a new header-only WindowedGraphicsManager class, so named because it contains code for managing graphics managers that interact with a windowing system and render virtual screens within a larger physical content window. The biggest behavioral change here is with the coordinate system mapping: Previously, mouse offsets were converted by mapping the whole space within the window as input to the virtual game screen without maintaining aspect ratio. This was done to prevent 'stickiness' when the mouse cursor was within the window but outside of the virtual game screen, but it caused noticeable distortion of mouse movement speed on the axis with blank space. Instead of introducing mouse speed distortion to prevent stickiness, this patch changes coordinate transformation to show the system cursor when the mouse moves outside of the virtual game screen when mouse grab is off, or by holding the mouse inside the virtual game screen (instead of the entire window) when mouse grab is on. This patch also improves some other properties of the GraphicsManager/PaletteManager interfaces: * Nullipotent operations (getWidth, getHeight, etc.) of the PaletteManager/GraphicsManager interfaces are now const * Methods marked `virtual` but not inherited by any subclass have been de-virtualized * Extra unnecessary calculations of hardware height in SurfaceSdlGraphicsManager have been removed * Methods have been renamed where appropriate for clarity (setWindowSize -> handleResize, etc.) * C++11 support improved with `override` specifier added on overridden virtual methods in subclasses (primarily to avoid myself accidentally creating new methods in the subclasses by changing types/names during refactoring) Additional refactoring can and should be done at some point to continue to deduplicate code between the OpenGL and SDL backends. Since the primary goal here was to improve the coordinate mapping, full refactoring of these backends was not completed here.
-rw-r--r--backends/events/sdl/sdl-events.cpp3
-rw-r--r--backends/graphics/graphics.h18
-rw-r--r--backends/graphics/null/null-graphics.h4
-rw-r--r--backends/graphics/opengl/opengl-graphics.cpp221
-rw-r--r--backends/graphics/opengl/opengl-graphics.h228
-rw-r--r--backends/graphics/openglsdl/openglsdl-graphics.cpp82
-rw-r--r--backends/graphics/openglsdl/openglsdl-graphics.h36
-rw-r--r--backends/graphics/sdl/sdl-graphics.cpp36
-rw-r--r--backends/graphics/sdl/sdl-graphics.h66
-rw-r--r--backends/graphics/surfacesdl/surfacesdl-graphics.cpp478
-rw-r--r--backends/graphics/surfacesdl/surfacesdl-graphics.h165
-rw-r--r--backends/graphics/windowed.h313
-rw-r--r--backends/platform/sdl/sdl-window.cpp12
-rw-r--r--backends/platform/sdl/sdl-window.h9
-rw-r--r--graphics/palette.h2
15 files changed, 821 insertions, 852 deletions
diff --git a/backends/events/sdl/sdl-events.cpp b/backends/events/sdl/sdl-events.cpp
index 2c6fe85232..db4aa21ef1 100644
--- a/backends/events/sdl/sdl-events.cpp
+++ b/backends/events/sdl/sdl-events.cpp
@@ -174,8 +174,7 @@ void SdlEventSource::processMouseEvent(Common::Event &event, int x, int y) {
event.mouse.y = y;
if (_graphicsManager) {
- _graphicsManager->notifyMousePos(Common::Point(x, y));
- _graphicsManager->transformMouseCoordinates(event.mouse);
+ _graphicsManager->notifyMousePosition(event.mouse);
}
}
diff --git a/backends/graphics/graphics.h b/backends/graphics/graphics.h
index bcd659ac11..cf33803cf5 100644
--- a/backends/graphics/graphics.h
+++ b/backends/graphics/graphics.h
@@ -38,9 +38,9 @@ class GraphicsManager : public PaletteManager {
public:
virtual ~GraphicsManager() {}
- virtual bool hasFeature(OSystem::Feature f) = 0;
+ virtual bool hasFeature(OSystem::Feature f) const = 0;
virtual void setFeatureState(OSystem::Feature f, bool enable) = 0;
- virtual bool getFeatureState(OSystem::Feature f) = 0;
+ virtual bool getFeatureState(OSystem::Feature f) const = 0;
virtual const OSystem::GraphicsMode *getSupportedGraphicsModes() const = 0;
virtual int getDefaultGraphicsMode() const = 0;
@@ -65,10 +65,10 @@ public:
virtual void beginGFXTransaction() = 0;
virtual OSystem::TransactionError endGFXTransaction() = 0;
- virtual int16 getHeight() = 0;
- virtual int16 getWidth() = 0;
+ virtual int16 getHeight() const = 0;
+ virtual int16 getWidth() const = 0;
virtual void setPalette(const byte *colors, uint start, uint num) = 0;
- virtual void grabPalette(byte *colors, uint start, uint num) = 0;
+ virtual void grabPalette(byte *colors, uint start, uint num) const = 0;
virtual void copyRectToScreen(const void *buf, int pitch, int x, int y, int w, int h) = 0;
virtual Graphics::Surface *lockScreen() = 0;
virtual void unlockScreen() = 0;
@@ -82,10 +82,10 @@ public:
virtual void hideOverlay() = 0;
virtual Graphics::PixelFormat getOverlayFormat() const = 0;
virtual void clearOverlay() = 0;
- virtual void grabOverlay(void *buf, int pitch) = 0;
- virtual void copyRectToOverlay(const void *buf, int pitch, int x, int y, int w, int h)= 0;
- virtual int16 getOverlayHeight() = 0;
- virtual int16 getOverlayWidth() = 0;
+ virtual void grabOverlay(void *buf, int pitch) const = 0;
+ virtual void copyRectToOverlay(const void *buf, int pitch, int x, int y, int w, int h) = 0;
+ virtual int16 getOverlayHeight() const = 0;
+ virtual int16 getOverlayWidth() const = 0;
virtual bool showMouse(bool visible) = 0;
virtual void warpMouse(int x, int y) = 0;
diff --git a/backends/graphics/null/null-graphics.h b/backends/graphics/null/null-graphics.h
index 67306c29f3..a870a76b73 100644
--- a/backends/graphics/null/null-graphics.h
+++ b/backends/graphics/null/null-graphics.h
@@ -54,8 +54,8 @@ public:
void beginGFXTransaction() {}
OSystem::TransactionError endGFXTransaction() { return OSystem::kTransactionSuccess; }
- int16 getHeight() { return 0; }
- int16 getWidth() { return 0; }
+ int16 getHeight() const { return 0; }
+ int16 getWidth() const { return 0; }
void setPalette(const byte *colors, uint start, uint num) {}
void grabPalette(byte *colors, uint start, uint num) {}
void copyRectToScreen(const void *buf, int pitch, int x, int y, int w, int h) {}
diff --git a/backends/graphics/opengl/opengl-graphics.cpp b/backends/graphics/opengl/opengl-graphics.cpp
index 28ca110d91..d98dcda599 100644
--- a/backends/graphics/opengl/opengl-graphics.cpp
+++ b/backends/graphics/opengl/opengl-graphics.cpp
@@ -53,14 +53,12 @@ namespace OpenGL {
OpenGLGraphicsManager::OpenGLGraphicsManager()
: _currentState(), _oldState(), _transactionMode(kTransactionNone), _screenChangeID(1 << (sizeof(int) * 8 - 2)),
_pipeline(nullptr),
- _outputScreenWidth(0), _outputScreenHeight(0), _displayX(0), _displayY(0),
- _displayWidth(0), _displayHeight(0), _defaultFormat(), _defaultFormatAlpha(),
+ _defaultFormat(), _defaultFormatAlpha(),
_gameScreen(nullptr), _gameScreenShakeOffset(0), _overlay(nullptr),
- _overlayVisible(false), _cursor(nullptr),
- _cursorX(0), _cursorY(0), _cursorDisplayX(0),_cursorDisplayY(0), _cursorHotspotX(0), _cursorHotspotY(0),
+ _cursor(nullptr),
+ _cursorHotspotX(0), _cursorHotspotY(0),
_cursorHotspotXScaled(0), _cursorHotspotYScaled(0), _cursorWidthScaled(0), _cursorHeightScaled(0),
- _cursorKeyColor(0), _cursorVisible(false), _cursorDontScale(false), _cursorPaletteEnabled(false),
- _forceRedraw(false)
+ _cursorKeyColor(0), _cursorVisible(false), _cursorDontScale(false), _cursorPaletteEnabled(false)
#ifdef USE_OSD
, _osdMessageChangeRequest(false), _osdMessageAlpha(0), _osdMessageFadeStartTime(0), _osdMessageSurface(nullptr),
_osdIconSurface(nullptr)
@@ -83,7 +81,7 @@ OpenGLGraphicsManager::~OpenGLGraphicsManager() {
#endif
}
-bool OpenGLGraphicsManager::hasFeature(OSystem::Feature f) {
+bool OpenGLGraphicsManager::hasFeature(OSystem::Feature f) const {
switch (f) {
case OSystem::kFeatureAspectRatioCorrection:
case OSystem::kFeatureCursorPalette:
@@ -129,7 +127,7 @@ void OpenGLGraphicsManager::setFeatureState(OSystem::Feature f, bool enable) {
}
}
-bool OpenGLGraphicsManager::getFeatureState(OSystem::Feature f) {
+bool OpenGLGraphicsManager::getFeatureState(OSystem::Feature f) const {
switch (f) {
case OSystem::kFeatureAspectRatioCorrection:
return _currentState.aspectRatioCorrection;
@@ -220,10 +218,9 @@ OSystem::TransactionError OpenGLGraphicsManager::endGFXTransaction() {
#endif
do {
- uint requestedWidth = _currentState.gameWidth;
- uint requestedHeight = _currentState.gameHeight;
- const uint desiredAspect = getDesiredGameScreenAspect();
- requestedHeight = intToFrac(requestedWidth) / desiredAspect;
+ const uint desiredAspect = getDesiredGameAspectRatio();
+ const uint requestedWidth = _currentState.gameWidth;
+ const uint requestedHeight = intToFrac(requestedWidth) / desiredAspect;
if (!loadVideoMode(requestedWidth, requestedHeight,
#ifdef USE_RGB_COLOR
@@ -317,7 +314,7 @@ OSystem::TransactionError OpenGLGraphicsManager::endGFXTransaction() {
// Update our display area and cursor scaling. This makes sure we pick up
// aspect ratio correction and game screen changes correctly.
- recalculateDisplayArea();
+ recalculateDisplayAreas();
recalculateCursorScaling();
// Something changed, so update the screen change ID.
@@ -347,11 +344,11 @@ void OpenGLGraphicsManager::initSize(uint width, uint height, const Graphics::Pi
_currentState.gameHeight = height;
}
-int16 OpenGLGraphicsManager::getWidth() {
+int16 OpenGLGraphicsManager::getWidth() const {
return _currentState.gameWidth;
}
-int16 OpenGLGraphicsManager::getHeight() {
+int16 OpenGLGraphicsManager::getHeight() const {
return _currentState.gameHeight;
}
@@ -392,6 +389,7 @@ void OpenGLGraphicsManager::updateScreen() {
// We only update the screen when there actually have been any changes.
if ( !_forceRedraw
+ && !_cursorNeedsRedraw
&& !_gameScreen->isDirty()
&& !(_overlayVisible && _overlay->isDirty())
&& !(_cursorVisible && _cursor && _cursor->isDirty())
@@ -401,7 +399,6 @@ void OpenGLGraphicsManager::updateScreen() {
) {
return;
}
- _forceRedraw = false;
// Update changes to textures.
_gameScreen->updateGLTexture();
@@ -420,14 +417,14 @@ void OpenGLGraphicsManager::updateScreen() {
_backBuffer.enableScissorTest(true);
}
- const GLfloat shakeOffset = _gameScreenShakeOffset * (GLfloat)_displayHeight / _gameScreen->getHeight();
+ const GLfloat shakeOffset = _gameScreenShakeOffset * (GLfloat)_gameDrawRect.height() / _gameScreen->getHeight();
// First step: Draw the (virtual) game screen.
- g_context.getActivePipeline()->drawTexture(_gameScreen->getGLTexture(), _displayX, _displayY + shakeOffset, _displayWidth, _displayHeight);
+ g_context.getActivePipeline()->drawTexture(_gameScreen->getGLTexture(), _gameDrawRect.left, _gameDrawRect.top + shakeOffset, _gameDrawRect.width(), _gameDrawRect.height());
// Second step: Draw the overlay if visible.
if (_overlayVisible) {
- g_context.getActivePipeline()->drawTexture(_overlay->getGLTexture(), 0, 0, _outputScreenWidth, _outputScreenHeight);
+ g_context.getActivePipeline()->drawTexture(_overlay->getGLTexture(), 0, 0, _overlayDrawRect.width(), _overlayDrawRect.height());
}
// Third step: Draw the cursor if visible.
@@ -437,8 +434,8 @@ void OpenGLGraphicsManager::updateScreen() {
const GLfloat cursorOffset = _overlayVisible ? 0 : shakeOffset;
g_context.getActivePipeline()->drawTexture(_cursor->getGLTexture(),
- _cursorDisplayX - _cursorHotspotXScaled,
- _cursorDisplayY - _cursorHotspotYScaled + cursorOffset,
+ _cursorX - _cursorHotspotXScaled,
+ _cursorY - _cursorHotspotYScaled + cursorOffset,
_cursorWidthScaled, _cursorHeightScaled);
}
@@ -464,8 +461,8 @@ void OpenGLGraphicsManager::updateScreen() {
// Set the OSD transparency.
g_context.getActivePipeline()->setColor(1.0f, 1.0f, 1.0f, _osdMessageAlpha / 100.0f);
- int dstX = (_outputScreenWidth - _osdMessageSurface->getWidth()) / 2;
- int dstY = (_outputScreenHeight - _osdMessageSurface->getHeight()) / 2;
+ int dstX = (_windowWidth - _osdMessageSurface->getWidth()) / 2;
+ int dstY = (_windowHeight - _osdMessageSurface->getHeight()) / 2;
// Draw the OSD texture.
g_context.getActivePipeline()->drawTexture(_osdMessageSurface->getGLTexture(),
@@ -481,7 +478,7 @@ void OpenGLGraphicsManager::updateScreen() {
}
if (_osdIconSurface) {
- int dstX = _outputScreenWidth - _osdIconSurface->getWidth() - kOSDIconRightMargin;
+ int dstX = _windowWidth - _osdIconSurface->getWidth() - kOSDIconRightMargin;
int dstY = kOSDIconTopMargin;
// Draw the OSD icon texture.
@@ -490,6 +487,8 @@ void OpenGLGraphicsManager::updateScreen() {
}
#endif
+ _cursorNeedsRedraw = false;
+ _forceRedraw = false;
refreshScreen();
}
@@ -507,7 +506,7 @@ void OpenGLGraphicsManager::setFocusRectangle(const Common::Rect& rect) {
void OpenGLGraphicsManager::clearFocusRectangle() {
}
-int16 OpenGLGraphicsManager::getOverlayWidth() {
+int16 OpenGLGraphicsManager::getOverlayWidth() const {
if (_overlay) {
return _overlay->getWidth();
} else {
@@ -515,7 +514,7 @@ int16 OpenGLGraphicsManager::getOverlayWidth() {
}
}
-int16 OpenGLGraphicsManager::getOverlayHeight() {
+int16 OpenGLGraphicsManager::getOverlayHeight() const {
if (_overlay) {
return _overlay->getHeight();
} else {
@@ -523,22 +522,6 @@ int16 OpenGLGraphicsManager::getOverlayHeight() {
}
}
-void OpenGLGraphicsManager::showOverlay() {
- _overlayVisible = true;
- _forceRedraw = true;
-
- // Update cursor position.
- setMousePosition(_cursorX, _cursorY);
-}
-
-void OpenGLGraphicsManager::hideOverlay() {
- _overlayVisible = false;
- _forceRedraw = true;
-
- // Update cursor position.
- setMousePosition(_cursorX, _cursorY);
-}
-
Graphics::PixelFormat OpenGLGraphicsManager::getOverlayFormat() const {
return _overlay->getFormat();
}
@@ -551,7 +534,7 @@ void OpenGLGraphicsManager::clearOverlay() {
_overlay->fill(0);
}
-void OpenGLGraphicsManager::grabOverlay(void *buf, int pitch) {
+void OpenGLGraphicsManager::grabOverlay(void *buf, int pitch) const {
const Graphics::Surface *overlayData = _overlay->getSurface();
const byte *src = (const byte *)overlayData->getPixels();
@@ -568,7 +551,7 @@ bool OpenGLGraphicsManager::showMouse(bool visible) {
// In case the mouse cursor visibility changed we need to redraw the whole
// screen even when nothing else changed.
if (_cursorVisible != visible) {
- _forceRedraw = true;
+ _cursorNeedsRedraw = true;
}
bool last = _cursorVisible;
@@ -576,43 +559,6 @@ bool OpenGLGraphicsManager::showMouse(bool visible) {
return last;
}
-void OpenGLGraphicsManager::warpMouse(int x, int y) {
- int16 currentX = _cursorX;
- int16 currentY = _cursorY;
- adjustMousePosition(currentX, currentY);
-
- // Check whether the (virtual) coordinate actually changed. If not, then
- // simply do nothing. This avoids ugly "jittering" due to the actual
- // output screen having a bigger resolution than the virtual coordinates.
- if (currentX == x && currentY == y) {
- return;
- }
-
- // Scale the virtual coordinates into actual physical coordinates.
- if (_overlayVisible) {
- if (!_overlay) {
- return;
- }
-
- // It might be confusing that we actually have to handle something
- // here when the overlay is visible. This is because for very small
- // resolutions we have a minimal overlay size and have to adjust
- // for that.
- x = (x * _outputScreenWidth) / _overlay->getWidth();
- y = (y * _outputScreenHeight) / _overlay->getHeight();
- } else {
- if (!_gameScreen) {
- return;
- }
-
- x = (x * _outputScreenWidth) / _gameScreen->getWidth();
- y = (y * _outputScreenHeight) / _gameScreen->getHeight();
- }
-
- setMousePosition(x, y);
- setInternalMousePosition(x, y);
-}
-
namespace {
template<typename DstPixel, typename SrcPixel>
void applyColorKey(DstPixel *dst, const SrcPixel *src, uint w, uint h, uint dstPitch, uint srcPitch, SrcPixel keyColor, DstPixel alphaMask) {
@@ -720,7 +666,6 @@ void OpenGLGraphicsManager::setMouseCursor(const void *buf, uint w, uint h, int
updateCursorPalette();
}
- // Update the scaling.
recalculateCursorScaling();
}
@@ -765,8 +710,8 @@ void OpenGLGraphicsManager::osdMessageUpdateSurface() {
}
// Clip the rect
- width = MIN<uint>(width, _displayWidth);
- height = MIN<uint>(height, _displayHeight);
+ width = MIN<uint>(width, _gameDrawRect.width());
+ height = MIN<uint>(height, _gameDrawRect.height());
delete _osdMessageSurface;
_osdMessageSurface = nullptr;
@@ -849,16 +794,13 @@ void OpenGLGraphicsManager::setPalette(const byte *colors, uint start, uint num)
updateCursorPalette();
}
-void OpenGLGraphicsManager::grabPalette(byte *colors, uint start, uint num) {
+void OpenGLGraphicsManager::grabPalette(byte *colors, uint start, uint num) const {
assert(_gameScreen->hasPalette());
memcpy(colors, _gamePalette + start * 3, num * 3);
}
-void OpenGLGraphicsManager::setActualScreenSize(uint width, uint height) {
- _outputScreenWidth = width;
- _outputScreenHeight = height;
-
+void OpenGLGraphicsManager::handleResizeImpl(const int width, const int height) {
// Setup backbuffer size.
_backBuffer.setDimensions(width, height);
@@ -873,7 +815,7 @@ void OpenGLGraphicsManager::setActualScreenSize(uint width, uint height) {
// anyway. Thus, it should not be a real issue for modern hardware.
if ( overlayWidth > (uint)g_context.maxTextureSize
|| overlayHeight > (uint)g_context.maxTextureSize) {
- const frac_t outputAspect = intToFrac(_outputScreenWidth) / _outputScreenHeight;
+ const frac_t outputAspect = intToFrac(_windowWidth) / _windowHeight;
if (outputAspect > (frac_t)FRAC_ONE) {
overlayWidth = g_context.maxTextureSize;
@@ -906,7 +848,7 @@ void OpenGLGraphicsManager::setActualScreenSize(uint width, uint height) {
_overlay->fill(0);
// Re-setup the scaling for the screen and cursor
- recalculateDisplayArea();
+ recalculateDisplayAreas();
recalculateCursorScaling();
// Something changed, so update the screen change ID.
@@ -960,8 +902,8 @@ void OpenGLGraphicsManager::notifyContextCreate(const Graphics::PixelFormat &def
GL_CALL(glPixelStorei(GL_PACK_ALIGNMENT, 4));
// Refresh the output screen dimensions if some are set up.
- if (_outputScreenWidth != 0 && _outputScreenHeight != 0) {
- setActualScreenSize(_outputScreenWidth, _outputScreenHeight);
+ if (_windowWidth != 0 && _windowHeight != 0) {
+ handleResize(_windowWidth, _windowHeight);
}
// TODO: Should we try to convert textures into one of those formats if
@@ -1031,46 +973,6 @@ void OpenGLGraphicsManager::notifyContextDestroy() {
g_context.reset();
}
-void OpenGLGraphicsManager::adjustMousePosition(int16 &x, int16 &y) {
- if (_overlayVisible) {
- // It might be confusing that we actually have to handle something
- // here when the overlay is visible. This is because for very small
- // resolutions we have a minimal overlay size and have to adjust
- // for that.
- // This can also happen when the overlay is smaller than the actual
- // display size because of texture size limitations.
- if (_overlay) {
- x = (x * _overlay->getWidth()) / _outputScreenWidth;
- y = (y * _overlay->getHeight()) / _outputScreenHeight;
- }
- } else if (_gameScreen) {
- const int16 width = _gameScreen->getWidth();
- const int16 height = _gameScreen->getHeight();
-
- x = (x * width) / (int)_outputScreenWidth;
- y = (y * height) / (int)_outputScreenHeight;
- }
-}
-
-void OpenGLGraphicsManager::setMousePosition(int x, int y) {
- // Whenever the mouse position changed we force a screen redraw to reflect
- // changes properly.
- if (_cursorX != x || _cursorY != y) {
- _forceRedraw = true;
- }
-
- _cursorX = x;
- _cursorY = y;
-
- if (_overlayVisible) {
- _cursorDisplayX = x;
- _cursorDisplayY = y;
- } else {
- _cursorDisplayX = _displayX + (x * _displayWidth) / _outputScreenWidth;
- _cursorDisplayY = _displayY + (y * _displayHeight) / _outputScreenHeight;
- }
-}
-
Surface *OpenGLGraphicsManager::createSurface(const Graphics::PixelFormat &format, bool wantAlpha) {
GLenum glIntFormat, glFormat, glType;
if (format.bytesPerPixel == 1) {
@@ -1191,51 +1093,34 @@ bool OpenGLGraphicsManager::getGLPixelFormat(const Graphics::PixelFormat &pixelF
}
}
-frac_t OpenGLGraphicsManager::getDesiredGameScreenAspect() const {
- const uint width = _currentState.gameWidth;
- const uint height = _currentState.gameHeight;
-
+bool OpenGLGraphicsManager::gameNeedsAspectRatioCorrection() const {
if (_currentState.aspectRatioCorrection) {
+ const uint width = getWidth();
+ const uint height = getHeight();
+
// In case we enable aspect ratio correction we force a 4/3 ratio.
// But just for 320x200 and 640x400 games, since other games do not need
// this.
- if ((width == 320 && height == 200) || (width == 640 && height == 400)) {
- return intToFrac(4) / 3;
- }
+ return (width == 320 && height == 200) || (width == 640 && height == 400);
}
- return intToFrac(width) / height;
+ return false;
}
-void OpenGLGraphicsManager::recalculateDisplayArea() {
- if (!_gameScreen || _outputScreenHeight == 0) {
+void OpenGLGraphicsManager::recalculateDisplayAreas() {
+ if (!_gameScreen) {
return;
}
- const frac_t outputAspect = intToFrac(_outputScreenWidth) / _outputScreenHeight;
- const frac_t desiredAspect = getDesiredGameScreenAspect();
-
- _displayWidth = _outputScreenWidth;
- _displayHeight = _outputScreenHeight;
-
- // Adjust one dimension for mantaining the aspect ratio.
- if (outputAspect < desiredAspect) {
- _displayHeight = intToFrac(_displayWidth) / desiredAspect;
- } else if (outputAspect > desiredAspect) {
- _displayWidth = fracToInt(_displayHeight * desiredAspect);
- }
-
- // We center the screen in the middle for now.
- _displayX = (_outputScreenWidth - _displayWidth ) / 2;
- _displayY = (_outputScreenHeight - _displayHeight) / 2;
+ WindowedGraphicsManager::recalculateDisplayAreas();
// Setup drawing limitation for game graphics.
// This involves some trickery because OpenGL's viewport coordinate system
// is upside down compared to ours.
- _backBuffer.setScissorBox(_displayX,
- _outputScreenHeight - _displayHeight - _displayY,
- _displayWidth,
- _displayHeight);
+ _backBuffer.setScissorBox(_gameDrawRect.left,
+ _windowHeight - _gameDrawRect.height() - _gameDrawRect.top,
+ _gameDrawRect.width(),
+ _gameDrawRect.height());
// Update the cursor position to adjust for new display area.
setMousePosition(_cursorX, _cursorY);
@@ -1272,8 +1157,8 @@ void OpenGLGraphicsManager::recalculateCursorScaling() {
// In case scaling is actually enabled we will scale the cursor according
// to the game screen.
if (!_cursorDontScale) {
- const frac_t screenScaleFactorX = intToFrac(_displayWidth) / _gameScreen->getWidth();
- const frac_t screenScaleFactorY = intToFrac(_displayHeight) / _gameScreen->getHeight();
+ const frac_t screenScaleFactorX = intToFrac(_gameDrawRect.width()) / _gameScreen->getWidth();
+ const frac_t screenScaleFactorY = intToFrac(_gameDrawRect.height()) / _gameScreen->getHeight();
_cursorHotspotXScaled = fracToInt(_cursorHotspotXScaled * screenScaleFactorX);
_cursorWidthScaled = fracToInt(_cursorWidthScaled * screenScaleFactorX);
@@ -1284,14 +1169,14 @@ void OpenGLGraphicsManager::recalculateCursorScaling() {
}
#ifdef USE_OSD
-const Graphics::Font *OpenGLGraphicsManager::getFontOSD() {
+const Graphics::Font *OpenGLGraphicsManager::getFontOSD() const {
return FontMan.getFontByUsage(Graphics::FontManager::kLocalizedFont);
}
#endif
bool OpenGLGraphicsManager::saveScreenshot(const Common::String &filename) const {
- const uint width = _outputScreenWidth;
- const uint height = _outputScreenHeight;
+ const uint width = _windowWidth;
+ const uint height = _windowHeight;
// A line of a BMP image must have a size divisible by 4.
// We calculate the padding bytes needed here.
diff --git a/backends/graphics/opengl/opengl-graphics.h b/backends/graphics/opengl/opengl-graphics.h
index cbf68d9cf1..92bb988a5e 100644
--- a/backends/graphics/opengl/opengl-graphics.h
+++ b/backends/graphics/opengl/opengl-graphics.h
@@ -25,7 +25,7 @@
#include "backends/graphics/opengl/opengl-sys.h"
#include "backends/graphics/opengl/framebuffer.h"
-#include "backends/graphics/graphics.h"
+#include "backends/graphics/windowed.h"
#include "common/frac.h"
#include "common/mutex.h"
@@ -53,74 +53,70 @@ enum {
GFX_OPENGL = 0
};
-class OpenGLGraphicsManager : virtual public GraphicsManager {
+class OpenGLGraphicsManager : virtual public WindowedGraphicsManager {
public:
OpenGLGraphicsManager();
virtual ~OpenGLGraphicsManager();
// GraphicsManager API
- virtual bool hasFeature(OSystem::Feature f);
- virtual void setFeatureState(OSystem::Feature f, bool enable);
- virtual bool getFeatureState(OSystem::Feature f);
+ virtual bool hasFeature(OSystem::Feature f) const override;
+ virtual void setFeatureState(OSystem::Feature f, bool enable) override;
+ virtual bool getFeatureState(OSystem::Feature f) const override;
- virtual const OSystem::GraphicsMode *getSupportedGraphicsModes() const;
- virtual int getDefaultGraphicsMode() const;
- virtual bool setGraphicsMode(int mode);
- virtual int getGraphicsMode() const;
+ virtual const OSystem::GraphicsMode *getSupportedGraphicsModes() const override;
+ virtual int getDefaultGraphicsMode() const override;
+ virtual bool setGraphicsMode(int mode) override;
+ virtual int getGraphicsMode() const override;
- virtual void resetGraphicsScale() {}
+ virtual void resetGraphicsScale() override {}
#ifdef USE_RGB_COLOR
- virtual Graphics::PixelFormat getScreenFormat() const;
- virtual Common::List<Graphics::PixelFormat> getSupportedFormats() const = 0;
+ virtual Graphics::PixelFormat getScreenFormat() const override;
+ virtual Common::List<Graphics::PixelFormat> getSupportedFormats() const override = 0;
#endif
- virtual void beginGFXTransaction();
- virtual OSystem::TransactionError endGFXTransaction();
+ virtual void beginGFXTransaction() override;
+ virtual OSystem::TransactionError endGFXTransaction() override;
- virtual int getScreenChangeID() const;
+ virtual int getScreenChangeID() const override;
- virtual void initSize(uint width, uint height, const Graphics::PixelFormat *format);
+ virtual void initSize(uint width, uint height, const Graphics::PixelFormat *format) override;
- virtual int16 getWidth();
- virtual int16 getHeight();
+ virtual int16 getWidth() const override;
+ virtual int16 getHeight() const override;
- virtual void copyRectToScreen(const void *buf, int pitch, int x, int y, int w, int h);
- virtual void fillScreen(uint32 col);
+ virtual void copyRectToScreen(const void *buf, int pitch, int x, int y, int w, int h) override;
+ virtual void fillScreen(uint32 col) override;
- virtual void setShakePos(int shakeOffset);
+ virtual void setShakePos(int shakeOffset) override;
- virtual void updateScreen();
+ virtual void updateScreen() override;
- virtual Graphics::Surface *lockScreen();
- virtual void unlockScreen();
+ virtual Graphics::Surface *lockScreen() override;
+ virtual void unlockScreen() override;
- virtual void setFocusRectangle(const Common::Rect& rect);
- virtual void clearFocusRectangle();
+ virtual void setFocusRectangle(const Common::Rect& rect) override;
+ virtual void clearFocusRectangle() override;
- virtual int16 getOverlayWidth();
- virtual int16 getOverlayHeight();
+ virtual int16 getOverlayWidth() const override;
+ virtual int16 getOverlayHeight() const override;
- virtual void showOverlay();
- virtual void hideOverlay();
+ virtual Graphics::PixelFormat getOverlayFormat() const override;
- virtual Graphics::PixelFormat getOverlayFormat() const;
+ virtual void copyRectToOverlay(const void *buf, int pitch, int x, int y, int w, int h) override;
+ virtual void clearOverlay() override;
+ virtual void grabOverlay(void *buf, int pitch) const override;
- virtual void copyRectToOverlay(const void *buf, int pitch, int x, int y, int w, int h);
- virtual void clearOverlay();
- virtual void grabOverlay(void *buf, int pitch);
+ virtual bool showMouse(bool visible) override;
+ virtual void setMouseCursor(const void *buf, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor, bool dontScale, const Graphics::PixelFormat *format) override;
+ virtual void setCursorPalette(const byte *colors, uint start, uint num) override;
- virtual bool showMouse(bool visible);
- virtual void warpMouse(int x, int y);
- virtual void setMouseCursor(const void *buf, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor, bool dontScale, const Graphics::PixelFormat *format);
- virtual void setCursorPalette(const byte *colors, uint start, uint num);
-
- virtual void displayMessageOnOSD(const char *msg);
- virtual void displayActivityIconOnOSD(const Graphics::Surface *icon);
+ virtual void displayMessageOnOSD(const char *msg) override;
+ virtual void displayActivityIconOnOSD(const Graphics::Surface *icon) override;
// PaletteManager interface
- virtual void setPalette(const byte *colors, uint start, uint num);
- virtual void grabPalette(byte *colors, uint start, uint num);
+ virtual void setPalette(const byte *colors, uint start, uint num) override;
+ virtual void grabPalette(byte *colors, uint start, uint num) const override;
protected:
/**
@@ -129,15 +125,6 @@ protected:
bool isGLESContext() const { return g_context.type == kContextGLES || g_context.type == kContextGLES2; }
/**
- * Set up the actual screen size available for the OpenGL code to do any
- * drawing.
- *
- * @param width The width of the screen.
- * @param height The height of the screen.
- */
- void setActualScreenSize(uint width, uint height);
-
- /**
* Sets the OpenGL (ES) type the graphics manager shall work with.
*
* This needs to be called at least once (and before ever calling
@@ -167,33 +154,6 @@ protected:
void notifyContextDestroy();
/**
- * Adjust the physical mouse coordinates according to the currently visible screen.
- */
- void adjustMousePosition(int16 &x, int16 &y);
-
- /**
- * Set up the mouse position for graphics output.
- *
- * @param x X coordinate in physical coordinates.
- * @param y Y coordinate in physical coordinates.
- */
- void setMousePosition(int x, int y);
-
- /**
- * Query the mouse position in physical coordinates.
- */
- void getMousePosition(int16 &x, int16 &y) const { x = _cursorX; y = _cursorY; }
-
- /**
- * Set up the mouse position for the (event) system.
- *
- * @param x X coordinate in physical coordinates.
- * @param y Y coordinate in physical coordinates.
- */
- virtual void setInternalMousePosition(int x, int y) = 0;
-
-private:
- /**
* Create a surface with the specified pixel format.
*
* @param format The pixel format the Surface object should accept as
@@ -292,8 +252,7 @@ protected:
virtual void refreshScreen() = 0;
/**
- * Save a screenshot of the full display as BMP to the given file. This
- * uses Common::DumpFile for writing the screenshot.
+ * Saves a screenshot of the entire window, excluding window decorations.
*
* @param filename The output filename.
* @return true on success, false otherwise
@@ -334,7 +293,6 @@ protected:
*/
virtual void *getProcAddress(const char *name) const = 0;
-private:
/**
* Try to determine the internal parameters for a given pixel format.
*
@@ -342,49 +300,9 @@ private:
*/
bool getGLPixelFormat(const Graphics::PixelFormat &pixelFormat, GLenum &glIntFormat, GLenum &glFormat, GLenum &glType) const;
- //
- // Actual hardware screen
- //
-
- /**
- * The width of the physical output.
- */
- uint _outputScreenWidth;
-
- /**
- * The height of the physical output.
- */
- uint _outputScreenHeight;
-
- /**
- * @return The desired aspect of the game screen.
- */
- frac_t getDesiredGameScreenAspect() const;
-
- /**
- * Recalculates the area used to display the game screen.
- */
- void recalculateDisplayArea();
-
- /**
- * The X coordinate of the game screen.
- */
- uint _displayX;
-
- /**
- * The Y coordinate of the game screen.
- */
- uint _displayY;
-
- /**
- * The width of the game screen in physical coordinates.
- */
- uint _displayWidth;
-
- /**
- * The height of the game screen in physical coordinates.
- */
- uint _displayHeight;
+ virtual bool gameNeedsAspectRatioCorrection() const override;
+ virtual void recalculateDisplayAreas() override;
+ virtual void handleResizeImpl(const int width, const int height) override;
/**
* The default pixel format of the backend.
@@ -396,12 +314,8 @@ private:
*/
Graphics::PixelFormat _defaultFormatAlpha;
- //
- // Game screen
- //
-
/**
- * The virtual game screen.
+ * The rendering surface for the virtual game screen.
*/
Surface *_gameScreen;
@@ -420,15 +334,10 @@ private:
//
/**
- * The overlay screen.
+ * The rendering surface for the overlay.
*/
Surface *_overlay;
- /**
- * Whether the overlay is visible or not.
- */
- bool _overlayVisible;
-
//
// Cursor
//
@@ -439,37 +348,17 @@ private:
void updateCursorPalette();
/**
- * The cursor image.
+ * The rendering surface for the mouse cursor.
*/
Surface *_cursor;
/**
- * X coordinate of the cursor in physical coordinates.
- */
- int _cursorX;
-
- /**
- * Y coordinate of the cursor in physical coordinates.
- */
- int _cursorY;
-
- /**
- * X coordinate used for drawing the cursor.
- */
- int _cursorDisplayX;
-
- /**
- * Y coordinate used for drawing the cursor.
- */
- int _cursorDisplayY;
-
- /**
- * The X offset for the cursor hotspot in unscaled coordinates.
+ * The X offset for the cursor hotspot in unscaled game coordinates.
*/
int _cursorHotspotX;
/**
- * The Y offset for the cursor hotspot in unscaled coordinates.
+ * The Y offset for the cursor hotspot in unscaled game coordinates.
*/
int _cursorHotspotY;
@@ -480,22 +369,24 @@ private:
void recalculateCursorScaling();
/**
- * The X offset for the cursor hotspot in scaled coordinates.
+ * The X offset for the cursor hotspot in scaled game display area
+ * coordinates.
*/
int _cursorHotspotXScaled;
/**
- * The Y offset for the cursor hotspot in scaled coordinates.
+ * The Y offset for the cursor hotspot in scaled game display area
+ * coordinates.
*/
int _cursorHotspotYScaled;
/**
- * The width of the cursor scaled coordinates.
+ * The width of the cursor in scaled game display area coordinates.
*/
uint _cursorWidthScaled;
/**
- * The height of the cursor scaled coordinates.
+ * The height of the cursor in scaled game display area coordinates.
*/
uint _cursorHeightScaled;
@@ -524,15 +415,6 @@ private:
*/
byte _cursorPalette[3 * 256];
- //
- // Misc
- //
-
- /**
- * Whether the screen contents shall be forced to redrawn.
- */
- bool _forceRedraw;
-
#ifdef USE_OSD
//
// OSD
@@ -541,7 +423,7 @@ protected:
/**
* Returns the font used for on screen display
*/
- virtual const Graphics::Font *getFontOSD();
+ virtual const Graphics::Font *getFontOSD() const;
private:
/**
diff --git a/backends/graphics/openglsdl/openglsdl-graphics.cpp b/backends/graphics/openglsdl/openglsdl-graphics.cpp
index 46940d74f2..c77e9dafc5 100644
--- a/backends/graphics/openglsdl/openglsdl-graphics.cpp
+++ b/backends/graphics/openglsdl/openglsdl-graphics.cpp
@@ -21,8 +21,10 @@
*/
#include "backends/graphics/openglsdl/openglsdl-graphics.h"
+#include "backends/graphics/opengl/texture.h"
#include "backends/events/sdl/sdl-events.h"
#include "backends/platform/sdl/sdl.h"
+#include "graphics/scaler/aspect.h"
#include "common/textconsole.h"
#include "common/config-manager.h"
@@ -35,7 +37,7 @@ OpenGLSdlGraphicsManager::OpenGLSdlGraphicsManager(uint desktopWidth, uint deskt
#if SDL_VERSION_ATLEAST(2, 0, 0)
_glContext(),
#else
- _lastVideoModeLoad(0), _hwScreen(nullptr),
+ _lastVideoModeLoad(0),
#endif
_graphicsScale(2), _ignoreLoadVideoMode(false), _gotResize(false), _wantsFullScreen(false), _ignoreResizeEvents(0),
_desiredFullscreenWidth(0), _desiredFullscreenHeight(0) {
@@ -52,14 +54,16 @@ OpenGLSdlGraphicsManager::OpenGLSdlGraphicsManager(uint desktopWidth, uint deskt
// Context version 1.4 is choosen arbitrarily based on what most shader
// extensions were written against.
-#define DEFAULT_GL_MAJOR 1
-#define DEFAULT_GL_MINOR 4
+ enum {
+ DEFAULT_GL_MAJOR = 1,
+ DEFAULT_GL_MINOR = 4,
-#define DEFAULT_GLES_MAJOR 1
-#define DEFAULT_GLES_MINOR 1
+ DEFAULT_GLES_MAJOR = 1,
+ DEFAULT_GLES_MINOR = 1,
-#define DEFAULT_GLES2_MAJOR 2
-#define DEFAULT_GLES2_MINOR 0
+ DEFAULT_GLES2_MAJOR = 2,
+ DEFAULT_GLES2_MINOR = 0
+ };
#if USE_FORCED_GL
glContextType = OpenGL::kContextGL;
@@ -127,12 +131,6 @@ OpenGLSdlGraphicsManager::OpenGLSdlGraphicsManager(uint desktopWidth, uint deskt
} else {
glContextType = OpenGL::kContextGL;
}
-#undef DEFAULT_GL_MAJOR
-#undef DEFAULT_GL_MINOR
-#undef DEFAULT_GLES_MAJOR
-#undef DEFAULT_GLES_MINOR
-#undef DEFAULT_GLES2_MAJOR
-#undef DEFAULT_GLES2_MINOR
#endif
setContextType(glContextType);
@@ -217,7 +215,7 @@ void OpenGLSdlGraphicsManager::deactivateManager() {
SdlGraphicsManager::deactivateManager();
}
-bool OpenGLSdlGraphicsManager::hasFeature(OSystem::Feature f) {
+bool OpenGLSdlGraphicsManager::hasFeature(OSystem::Feature f) const {
switch (f) {
case OSystem::kFeatureFullscreenMode:
case OSystem::kFeatureIconifyWindow:
@@ -246,7 +244,7 @@ void OpenGLSdlGraphicsManager::setFeatureState(OSystem::Feature f, bool enable)
}
}
-bool OpenGLSdlGraphicsManager::getFeatureState(OSystem::Feature f) {
+bool OpenGLSdlGraphicsManager::getFeatureState(OSystem::Feature f) const {
switch (f) {
case OSystem::kFeatureFullscreenMode:
#if SDL_VERSION_ATLEAST(2, 0, 0)
@@ -344,7 +342,7 @@ void OpenGLSdlGraphicsManager::updateScreen() {
void OpenGLSdlGraphicsManager::notifyVideoExpose() {
}
-void OpenGLSdlGraphicsManager::notifyResize(const uint width, const uint height) {
+void OpenGLSdlGraphicsManager::notifyResize(const int width, const int height) {
#if SDL_VERSION_ATLEAST(2, 0, 0)
// We sometime get outdated resize events from SDL2. So check that the size we get
// is the actual current window size. If not ignore the resize.
@@ -354,11 +352,10 @@ void OpenGLSdlGraphicsManager::notifyResize(const uint width, const uint height)
// causes a SDL_WINDOWEVENT_RESIZED event with the old resolution to be sent, and this
// event is processed after recreating the window at the new resolution.
int currentWidth, currentHeight;
- getWindowDimensions(&currentWidth, &currentHeight);
- if (width != (uint)currentWidth || height != (uint)currentHeight)
+ getWindowSizeFromSdl(&currentWidth, &currentHeight);
+ if (width != currentWidth || height != currentHeight)
return;
- setActualScreenSize(width, height);
- _eventSource->resetKeyboardEmulation(width - 1, height - 1);
+ handleResize(width, height);
#else
if (!_ignoreResizeEvents && _hwScreen && !(_hwScreen->flags & SDL_FULLSCREEN)) {
// We save that we handled a resize event here. We need to know this
@@ -373,18 +370,6 @@ void OpenGLSdlGraphicsManager::notifyResize(const uint width, const uint height)
#endif
}
-void OpenGLSdlGraphicsManager::transformMouseCoordinates(Common::Point &point) {
- adjustMousePosition(point.x, point.y);
-}
-
-void OpenGLSdlGraphicsManager::notifyMousePos(Common::Point mouse) {
- setMousePosition(mouse.x, mouse.y);
-}
-
-void OpenGLSdlGraphicsManager::setInternalMousePosition(int x, int y) {
- _window->warpMouseInWindow(x, y);
-}
-
bool OpenGLSdlGraphicsManager::loadVideoMode(uint requestedWidth, uint requestedHeight, const Graphics::PixelFormat &format) {
// In some cases we might not want to load the requested video mode. This
// will assure that the window size is not altered.
@@ -422,6 +407,11 @@ void *OpenGLSdlGraphicsManager::getProcAddress(const char *name) const {
return SDL_GL_GetProcAddress(name);
}
+void OpenGLSdlGraphicsManager::handleResizeImpl(const int width, const int height) {
+ OpenGLGraphicsManager::handleResizeImpl(width, height);
+ SdlGraphicsManager::handleResizeImpl(width, height);
+}
+
bool OpenGLSdlGraphicsManager::setupMode(uint width, uint height) {
// In case we request a fullscreen mode we will use the mode the user
// has chosen last time or the biggest mode available.
@@ -517,9 +507,8 @@ bool OpenGLSdlGraphicsManager::setupMode(uint width, uint height) {
notifyContextCreate(rgba8888, rgba8888);
int actualWidth, actualHeight;
- getWindowDimensions(&actualWidth, &actualHeight);
- setActualScreenSize(actualWidth, actualHeight);
- _eventSource->resetKeyboardEmulation(actualWidth - 1, actualHeight - 1);
+ getWindowSizeFromSdl(&actualWidth, &actualHeight);
+ handleResize(actualWidth, actualHeight);
return true;
#else
// WORKAROUND: Working around infamous SDL bugs when switching
@@ -566,8 +555,7 @@ bool OpenGLSdlGraphicsManager::setupMode(uint width, uint height) {
if (_hwScreen) {
notifyContextCreate(rgba8888, rgba8888);
- setActualScreenSize(_hwScreen->w, _hwScreen->h);
- _eventSource->resetKeyboardEmulation(_hwScreen->w - 1, _hwScreen->h - 1);
+ handleResize(_hwScreen->w, _hwScreen->h);
}
// Ignore resize events (from SDL) for a few frames, if this isn't
@@ -580,20 +568,6 @@ bool OpenGLSdlGraphicsManager::setupMode(uint width, uint height) {
#endif
}
-void OpenGLSdlGraphicsManager::getWindowDimensions(int *width, int *height) {
-#if SDL_VERSION_ATLEAST(2, 0, 0)
- SDL_GetWindowSize(_window->getSDLWindow(), width, height);
-#else
- if (width) {
- *width = _hwScreen->w;
- }
-
- if (height) {
- *height = _hwScreen->h;
- }
-#endif
-}
-
bool OpenGLSdlGraphicsManager::notifyEvent(const Common::Event &event) {
switch (event.type) {
case Common::EVENT_KEYUP:
@@ -707,7 +681,7 @@ bool OpenGLSdlGraphicsManager::notifyEvent(const Common::Event &event) {
// current scale setting in case the user resized the
// window. Then we apply the direction change.
int windowWidth = 0, windowHeight = 0;
- getWindowDimensions(&windowWidth, &windowHeight);
+ getWindowSizeFromSdl(&windowWidth, &windowHeight);
_graphicsScale = MAX<int>(windowWidth / _lastRequestedWidth, windowHeight / _lastRequestedHeight);
_graphicsScale = MAX<int>(_graphicsScale + direction, 1);
@@ -725,7 +699,7 @@ bool OpenGLSdlGraphicsManager::notifyEvent(const Common::Event &event) {
#ifdef USE_OSD
int windowWidth = 0, windowHeight = 0;
- getWindowDimensions(&windowWidth, &windowHeight);
+ getWindowSizeFromSdl(&windowWidth, &windowHeight);
const Common::String osdMsg = Common::String::format(_("Resolution: %dx%d"), windowWidth, windowHeight);
displayMessageOnOSD(osdMsg.c_str());
#endif
@@ -785,7 +759,7 @@ bool OpenGLSdlGraphicsManager::notifyEvent(const Common::Event &event) {
}
}
-bool OpenGLSdlGraphicsManager::isHotkey(const Common::Event &event) {
+bool OpenGLSdlGraphicsManager::isHotkey(const Common::Event &event) const {
if (event.kbd.hasFlags(Common::KBD_ALT)) {
return event.kbd.keycode == Common::KEYCODE_RETURN
|| event.kbd.keycode == (Common::KeyCode)SDLK_KP_ENTER
diff --git a/backends/graphics/openglsdl/openglsdl-graphics.h b/backends/graphics/openglsdl/openglsdl-graphics.h
index c5003d867b..954c7215a4 100644
--- a/backends/graphics/openglsdl/openglsdl-graphics.h
+++ b/backends/graphics/openglsdl/openglsdl-graphics.h
@@ -36,38 +36,37 @@ public:
virtual ~OpenGLSdlGraphicsManager();
// GraphicsManager API
- virtual void activateManager();
- virtual void deactivateManager();
+ virtual void activateManager() override;
+ virtual void deactivateManager() override;
- virtual bool hasFeature(OSystem::Feature f);
- virtual void setFeatureState(OSystem::Feature f, bool enable);
- virtual bool getFeatureState(OSystem::Feature f);
+ virtual bool hasFeature(OSystem::Feature f) const override;
+ virtual void setFeatureState(OSystem::Feature f, bool enable) override;
+ virtual bool getFeatureState(OSystem::Feature f) const override;
virtual void initSize(uint w, uint h, const Graphics::PixelFormat *format) override;
#ifdef USE_RGB_COLOR
- virtual Common::List<Graphics::PixelFormat> getSupportedFormats() const;
+ virtual Common::List<Graphics::PixelFormat> getSupportedFormats() const override;
#endif
- virtual void updateScreen();
+ virtual void updateScreen() override;
// EventObserver API
- virtual bool notifyEvent(const Common::Event &event);
+ virtual bool notifyEvent(const Common::Event &event) override;
// SdlGraphicsManager API
- virtual void notifyVideoExpose();
- virtual void notifyResize(const uint width, const uint height);
- virtual void transformMouseCoordinates(Common::Point &point);
- virtual void notifyMousePos(Common::Point mouse);
+ virtual void notifyVideoExpose() override;
+ virtual void notifyResize(const int width, const int height) override;
protected:
- virtual void setInternalMousePosition(int x, int y);
+ virtual bool loadVideoMode(uint requestedWidth, uint requestedHeight, const Graphics::PixelFormat &format) override;
- virtual bool loadVideoMode(uint requestedWidth, uint requestedHeight, const Graphics::PixelFormat &format);
+ virtual void refreshScreen() override;
- virtual void refreshScreen();
+ virtual void *getProcAddress(const char *name) const override;
+
+ virtual void handleResizeImpl(const int width, const int height) override;
- virtual void *getProcAddress(const char *name) const;
virtual int getGraphicsModeScale(int mode) const override { return 1; }
private:
@@ -78,11 +77,8 @@ private:
SDL_GLContext _glContext;
#else
uint32 _lastVideoModeLoad;
- SDL_Surface *_hwScreen;
#endif
- void getWindowDimensions(int *width, int *height);
-
uint _lastRequestedWidth;
uint _lastRequestedHeight;
uint _graphicsScale;
@@ -122,7 +118,7 @@ private:
uint _desiredFullscreenWidth;
uint _desiredFullscreenHeight;
- virtual bool isHotkey(const Common::Event &event);
+ bool isHotkey(const Common::Event &event) const;
};
#endif
diff --git a/backends/graphics/sdl/sdl-graphics.cpp b/backends/graphics/sdl/sdl-graphics.cpp
index a181582235..ea947c1073 100644
--- a/backends/graphics/sdl/sdl-graphics.cpp
+++ b/backends/graphics/sdl/sdl-graphics.cpp
@@ -28,15 +28,11 @@
#include "graphics/scaler/aspect.h"
SdlGraphicsManager::SdlGraphicsManager(SdlEventSource *source, SdlWindow *window)
- : _eventSource(source), _window(window)
+ : _eventSource(source), _window(window), _hwScreen(nullptr)
#if SDL_VERSION_ATLEAST(2, 0, 0)
, _allowWindowSizeReset(false), _hintedWidth(0), _hintedHeight(0), _lastFlags(0)
#endif
- {
-}
-
-SdlGraphicsManager::~SdlGraphicsManager() {
-}
+{}
void SdlGraphicsManager::activateManager() {
_eventSource->setGraphicsManager(this);
@@ -46,7 +42,7 @@ void SdlGraphicsManager::deactivateManager() {
_eventSource->setGraphicsManager(0);
}
-SdlGraphicsManager::State SdlGraphicsManager::getState() {
+SdlGraphicsManager::State SdlGraphicsManager::getState() const {
State state;
state.screenWidth = getWidth();
@@ -152,6 +148,32 @@ void SdlGraphicsManager::initSizeHint(const Graphics::ModeList &modes) {
#endif
}
+void SdlGraphicsManager::notifyMousePosition(Common::Point &mouse) {
+ int showCursor;
+ if (_activeArea.drawRect.contains(mouse)) {
+ showCursor = SDL_DISABLE;
+ } else {
+ mouse.x = CLIP<int>(mouse.x, _activeArea.drawRect.left, _activeArea.drawRect.right - 1);
+ mouse.y = CLIP<int>(mouse.y, _activeArea.drawRect.top, _activeArea.drawRect.bottom - 1);
+
+ if (_window->mouseIsGrabbed()) {
+ setSystemMousePosition(mouse.x, mouse.y);
+ showCursor = SDL_DISABLE;
+ } else {
+ showCursor = SDL_ENABLE;
+ }
+ }
+
+ SDL_ShowCursor(showCursor);
+ setMousePosition(mouse.x, mouse.y);
+ mouse = convertWindowToVirtual(mouse.x, mouse.y);
+}
+
+void SdlGraphicsManager::handleResizeImpl(const int width, const int height) {
+ _eventSource->resetKeyboardEmulation(width - 1, height - 1);
+ _forceRedraw = true;
+}
+
#if SDL_VERSION_ATLEAST(2, 0, 0)
bool SdlGraphicsManager::createOrUpdateWindow(int width, int height, const Uint32 flags) {
if (!_window) {
diff --git a/backends/graphics/sdl/sdl-graphics.h b/backends/graphics/sdl/sdl-graphics.h
index ce282d842d..886070aedb 100644
--- a/backends/graphics/sdl/sdl-graphics.h
+++ b/backends/graphics/sdl/sdl-graphics.h
@@ -23,7 +23,7 @@
#ifndef BACKENDS_GRAPHICS_SDL_SDLGRAPHICS_H
#define BACKENDS_GRAPHICS_SDL_SDLGRAPHICS_H
-#include "backends/graphics/graphics.h"
+#include "backends/graphics/windowed.h"
#include "backends/platform/sdl/sdl-window.h"
#include "common/rect.h"
@@ -32,13 +32,11 @@ class SdlEventSource;
/**
* Base class for a SDL based graphics manager.
- *
- * It features a few extra a few extra features required by SdlEventSource.
*/
-class SdlGraphicsManager : virtual public GraphicsManager {
+class SdlGraphicsManager : virtual public WindowedGraphicsManager {
public:
SdlGraphicsManager(SdlEventSource *source, SdlWindow *window);
- virtual ~SdlGraphicsManager();
+ virtual ~SdlGraphicsManager() {}
/**
* Makes this graphics manager active. That means it should be ready to
@@ -74,23 +72,20 @@ public:
* @param width Requested window width.
* @param height Requested window height.
*/
- virtual void notifyResize(const uint width, const uint height) {}
+ virtual void notifyResize(const int width, const int height) {}
/**
- * Transforms real screen coordinates into the current active screen
- * coordinates (may be either game screen or overlay).
+ * Notifies the graphics manager about a mouse position change.
*
- * @param point Mouse coordinates to transform.
- */
- virtual void transformMouseCoordinates(Common::Point &point) = 0;
-
- /**
- * Notifies the graphics manager about a position change according to the
- * real screen coordinates.
+ * The passed point *must* be converted from window coordinates to virtual
+ * coordinates in order for the event to be processed correctly by the game
+ * engine. Just use `convertWindowToVirtual` for this unless you need to do
+ * something special.
*
- * @param mouse Mouse position.
+ * @param mouse The mouse position in window coordinates, which must be
+ * converted synchronously to virtual coordinates.
*/
- virtual void notifyMousePos(Common::Point mouse) = 0;
+ virtual void notifyMousePosition(Common::Point &mouse);
/**
* A (subset) of the graphic manager's state. This is used when switching
@@ -108,17 +103,17 @@ public:
};
/**
- * Queries the current state of the graphic manager.
+ * Gets the current state of the graphics manager.
*/
- State getState();
+ State getState() const;
/**
- * Setup a basic state of the graphic manager.
+ * Sets up a basic state of the graphics manager.
*/
bool setState(const State &state);
/**
- * Queries the SDL window.
+ * @returns the SDL window.
*/
SdlWindow *getWindow() const { return _window; }
@@ -130,6 +125,34 @@ protected:
bool defaultGraphicsModeConfig() const;
int getGraphicsModeIdByName(const Common::String &name) const;
+ /**
+ * Gets the dimensions of the window directly from SDL instead of from the
+ * values stored by the graphics manager.
+ */
+ void getWindowSizeFromSdl(int *width, int *height) const {
+#if SDL_VERSION_ATLEAST(2, 0, 0)
+ assert(_window);
+ SDL_GetWindowSize(_window->getSDLWindow(), width, height);
+#else
+ assert(_hwScreen);
+
+ if (width) {
+ *width = _hwScreen->w;
+ }
+
+ if (height) {
+ *height = _hwScreen->h;
+ }
+#endif
+ }
+
+ virtual void setSystemMousePosition(const int x, const int y) override {
+ assert(_window);
+ _window->warpMouseInWindow(x, y);
+ }
+
+ virtual void handleResizeImpl(const int width, const int height) override;
+
#if SDL_VERSION_ATLEAST(2, 0, 0)
public:
void unlockWindowSize() {
@@ -146,6 +169,7 @@ protected:
bool createOrUpdateWindow(const int width, const int height, const Uint32 flags);
#endif
+ SDL_Surface *_hwScreen;
SdlEventSource *_eventSource;
SdlWindow *_window;
};
diff --git a/backends/graphics/surfacesdl/surfacesdl-graphics.cpp b/backends/graphics/surfacesdl/surfacesdl-graphics.cpp
index fb9870910b..52104ffb7a 100644
--- a/backends/graphics/surfacesdl/surfacesdl-graphics.cpp
+++ b/backends/graphics/surfacesdl/surfacesdl-graphics.cpp
@@ -23,7 +23,6 @@
#include "common/scummsys.h"
#if defined(SDL_BACKEND)
-
#include "backends/graphics/surfacesdl/surfacesdl-graphics.h"
#include "backends/events/sdl/sdl-events.h"
#include "backends/platform/sdl/sdl.h"
@@ -133,10 +132,8 @@ SurfaceSdlGraphicsManager::SurfaceSdlGraphicsManager(SdlEventSource *sdlEventSou
_osdMessageSurface(nullptr), _osdMessageAlpha(SDL_ALPHA_TRANSPARENT), _osdMessageFadeStartTime(0),
_osdIconSurface(nullptr),
#endif
- _hwscreen(0),
#if SDL_VERSION_ATLEAST(2, 0, 0)
_renderer(nullptr), _screenTexture(nullptr),
- _viewport(), _windowWidth(1), _windowHeight(1),
#endif
#if defined(WIN32) && !SDL_VERSION_ATLEAST(2, 0, 0)
_originalBitsPerPixel(0),
@@ -146,10 +143,9 @@ SurfaceSdlGraphicsManager::SurfaceSdlGraphicsManager(SdlEventSource *sdlEventSou
_screenFormat(Graphics::PixelFormat::createFormatCLUT8()),
_cursorFormat(Graphics::PixelFormat::createFormatCLUT8()),
#endif
- _overlayVisible(false),
_overlayscreen(0), _tmpscreen2(0),
_scalerProc(0), _screenChangeCount(0),
- _mouseVisible(false), _mouseNeedsRedraw(false), _mouseData(0), _mouseSurface(0),
+ _mouseVisible(false), _mouseData(0), _mouseSurface(0),
_mouseOrigSurface(0), _cursorDontScale(false), _cursorPaletteDisabled(true),
_currentShakePos(0), _newShakePos(0),
_paletteDirtyStart(0), _paletteDirtyEnd(0),
@@ -247,7 +243,7 @@ void SurfaceSdlGraphicsManager::deactivateManager() {
SdlGraphicsManager::deactivateManager();
}
-bool SurfaceSdlGraphicsManager::hasFeature(OSystem::Feature f) {
+bool SurfaceSdlGraphicsManager::hasFeature(OSystem::Feature f) const {
return
(f == OSystem::kFeatureFullscreenMode) ||
(f == OSystem::kFeatureAspectRatioCorrection) ||
@@ -284,7 +280,7 @@ void SurfaceSdlGraphicsManager::setFeatureState(OSystem::Feature f, bool enable)
}
}
-bool SurfaceSdlGraphicsManager::getFeatureState(OSystem::Feature f) {
+bool SurfaceSdlGraphicsManager::getFeatureState(OSystem::Feature f) const {
// We need to allow this to be called from within a transaction, since we
// currently use it to retreive the graphics state, when switching from
// SDL->OpenGL mode for example.
@@ -555,16 +551,16 @@ void SurfaceSdlGraphicsManager::detectSupportedFormats() {
Graphics::PixelFormat(2, 4, 4, 4, 4, 4, 8, 12, 0)
};
- if (_hwscreen) {
+ if (_hwScreen) {
// Get our currently set hardware format
- Graphics::PixelFormat hwFormat(_hwscreen->format->BytesPerPixel,
- 8 - _hwscreen->format->Rloss, 8 - _hwscreen->format->Gloss,
- 8 - _hwscreen->format->Bloss, 8 - _hwscreen->format->Aloss,
- _hwscreen->format->Rshift, _hwscreen->format->Gshift,
- _hwscreen->format->Bshift, _hwscreen->format->Ashift);
+ Graphics::PixelFormat hwFormat(_hwScreen->format->BytesPerPixel,
+ 8 - _hwScreen->format->Rloss, 8 - _hwScreen->format->Gloss,
+ 8 - _hwScreen->format->Bloss, 8 - _hwScreen->format->Aloss,
+ _hwScreen->format->Rshift, _hwScreen->format->Gshift,
+ _hwScreen->format->Bshift, _hwScreen->format->Ashift);
// Workaround to SDL not providing an accurate Aloss value on Mac OS X.
- if (_hwscreen->format->Amask == 0)
+ if (_hwScreen->format->Amask == 0)
hwFormat.aLoss = 8;
_supportedFormats.push_back(hwFormat);
@@ -579,7 +575,7 @@ void SurfaceSdlGraphicsManager::detectSupportedFormats() {
// Push some RGB formats
for (i = 0; i < ARRAYSIZE(RGBList); i++) {
- if (_hwscreen && (RGBList[i].bytesPerPixel > format.bytesPerPixel))
+ if (_hwScreen && (RGBList[i].bytesPerPixel > format.bytesPerPixel))
continue;
if (RGBList[i] != format)
_supportedFormats.push_back(RGBList[i]);
@@ -587,7 +583,7 @@ void SurfaceSdlGraphicsManager::detectSupportedFormats() {
// Push some BGR formats
for (i = 0; i < ARRAYSIZE(BGRList); i++) {
- if (_hwscreen && (BGRList[i].bytesPerPixel > format.bytesPerPixel))
+ if (_hwScreen && (BGRList[i].bytesPerPixel > format.bytesPerPixel))
continue;
if (BGRList[i] != format)
_supportedFormats.push_back(BGRList[i]);
@@ -722,11 +718,11 @@ void SurfaceSdlGraphicsManager::setGraphicsModeIntern() {
}
}
- if (!_screen || !_hwscreen)
+ if (!_screen || !_hwScreen)
return;
// Blit everything to the screen
- _forceFull = true;
+ _forceRedraw = true;
// Even if the old and new scale factors are the same, we may have a
// different scaler for the cursor now.
@@ -797,13 +793,6 @@ void SurfaceSdlGraphicsManager::initSize(uint w, uint h, const Graphics::PixelFo
_transactionDetails.sizeChanged = true;
}
-int SurfaceSdlGraphicsManager::effectiveScreenHeight() const {
- return _videoMode.scaleFactor *
- (_videoMode.aspectRatioCorrection
- ? real2Aspect(_videoMode.screenHeight)
- : _videoMode.screenHeight);
-}
-
static void fixupResolutionForAspectRatio(AspectRatio desiredAspectRatio, int &width, int &height) {
assert(&width != &height);
@@ -864,7 +853,7 @@ static void fixupResolutionForAspectRatio(AspectRatio desiredAspectRatio, int &w
}
bool SurfaceSdlGraphicsManager::loadGFXMode() {
- _forceFull = true;
+ _forceRedraw = true;
#if !defined(__MAEMO__) && !defined(DINGUX) && !defined(GPH_DEVICE) && !defined(LINUXMOTO) && !defined(OPENPANDORA)
_videoMode.overlayWidth = _videoMode.screenWidth * _videoMode.scaleFactor;
@@ -873,11 +862,14 @@ bool SurfaceSdlGraphicsManager::loadGFXMode() {
if (_videoMode.screenHeight != 200 && _videoMode.screenHeight != 400)
_videoMode.aspectRatioCorrection = false;
- if (_videoMode.aspectRatioCorrection)
+ _videoMode.hardwareWidth = _videoMode.screenWidth * _videoMode.scaleFactor;
+ _videoMode.hardwareHeight = _videoMode.screenHeight * _videoMode.scaleFactor;
+
+ if (_videoMode.aspectRatioCorrection) {
_videoMode.overlayHeight = real2Aspect(_videoMode.overlayHeight);
+ _videoMode.hardwareHeight = real2Aspect(_videoMode.hardwareHeight);
+ }
- _videoMode.hardwareWidth = _videoMode.screenWidth * _videoMode.scaleFactor;
- _videoMode.hardwareHeight = effectiveScreenHeight();
// On GPH devices ALL the _videoMode.hardware... are setup in GPHGraphicsManager::loadGFXMode()
#elif !defined(GPH_DEVICE)
_videoMode.hardwareWidth = _videoMode.overlayWidth;
@@ -924,7 +916,7 @@ bool SurfaceSdlGraphicsManager::loadGFXMode() {
_displayDisabled = ConfMan.getBool("disable_display");
if (_displayDisabled) {
- _hwscreen = g_eventRec.getSurface(_videoMode.hardwareWidth, _videoMode.hardwareHeight);
+ _hwScreen = g_eventRec.getSurface(_videoMode.hardwareWidth, _videoMode.hardwareHeight);
} else
#endif
{
@@ -937,7 +929,7 @@ bool SurfaceSdlGraphicsManager::loadGFXMode() {
}
#endif
- _hwscreen = SDL_SetVideoMode(_videoMode.hardwareWidth, _videoMode.hardwareHeight, 16,
+ _hwScreen = SDL_SetVideoMode(_videoMode.hardwareWidth, _videoMode.hardwareHeight, 16,
_videoMode.fullscreen ? (SDL_FULLSCREEN|SDL_SWSURFACE) : SDL_SWSURFACE
);
}
@@ -946,9 +938,9 @@ bool SurfaceSdlGraphicsManager::loadGFXMode() {
detectSupportedFormats();
#endif
- if (_hwscreen == NULL) {
+ if (_hwScreen == NULL) {
// DON'T use error(), as this tries to bring up the debug
- // console, which WON'T WORK now that _hwscreen is hosed.
+ // console, which WON'T WORK now that _hwScreen is hosed.
if (!_oldVideoMode.setup) {
warning("SDL_SetVideoMode says we can't switch to that mode (%s)", SDL_GetError());
@@ -958,6 +950,10 @@ bool SurfaceSdlGraphicsManager::loadGFXMode() {
}
}
+#if !SDL_VERSION_ATLEAST(2, 0, 0)
+ handleResize(_videoMode.hardwareWidth, _videoMode.hardwareHeight);
+#endif
+
//
// Create the surface used for the graphics in 16 bit before scaling, and also the overlay
//
@@ -965,20 +961,20 @@ bool SurfaceSdlGraphicsManager::loadGFXMode() {
// Need some extra bytes around when using 2xSaI
_tmpscreen = SDL_CreateRGBSurface(SDL_SWSURFACE, _videoMode.screenWidth + 3, _videoMode.screenHeight + 3,
16,
- _hwscreen->format->Rmask,
- _hwscreen->format->Gmask,
- _hwscreen->format->Bmask,
- _hwscreen->format->Amask);
+ _hwScreen->format->Rmask,
+ _hwScreen->format->Gmask,
+ _hwScreen->format->Bmask,
+ _hwScreen->format->Amask);
if (_tmpscreen == NULL)
error("allocating _tmpscreen failed");
_overlayscreen = SDL_CreateRGBSurface(SDL_SWSURFACE, _videoMode.overlayWidth, _videoMode.overlayHeight,
16,
- _hwscreen->format->Rmask,
- _hwscreen->format->Gmask,
- _hwscreen->format->Bmask,
- _hwscreen->format->Amask);
+ _hwScreen->format->Rmask,
+ _hwScreen->format->Gmask,
+ _hwScreen->format->Bmask,
+ _hwScreen->format->Amask);
if (_overlayscreen == NULL)
error("allocating _overlayscreen failed");
@@ -997,25 +993,16 @@ bool SurfaceSdlGraphicsManager::loadGFXMode() {
_tmpscreen2 = SDL_CreateRGBSurface(SDL_SWSURFACE, _videoMode.overlayWidth + 3, _videoMode.overlayHeight + 3,
16,
- _hwscreen->format->Rmask,
- _hwscreen->format->Gmask,
- _hwscreen->format->Bmask,
- _hwscreen->format->Amask);
+ _hwScreen->format->Rmask,
+ _hwScreen->format->Gmask,
+ _hwScreen->format->Bmask,
+ _hwScreen->format->Amask);
if (_tmpscreen2 == NULL)
error("allocating _tmpscreen2 failed");
-#if !SDL_VERSION_ATLEAST(2, 0, 0)
- // For SDL2 the output resolution might differ from the requested
- // resolution. We handle resetting the keyboard emulation properly inside
- // our SDL_SetVideoMode wrapper for SDL2.
- _eventSource->resetKeyboardEmulation(
- _videoMode.screenWidth * _videoMode.scaleFactor - 1,
- effectiveScreenHeight() - 1);
-#endif
-
// Distinguish 555 and 565 mode
- if (_hwscreen->format->Rmask == 0x7C00)
+ if (_hwScreen->format->Rmask == 0x7C00)
InitScalers(555);
else
InitScalers(565);
@@ -1033,9 +1020,9 @@ void SurfaceSdlGraphicsManager::unloadGFXMode() {
deinitializeRenderer();
#endif
- if (_hwscreen) {
- SDL_FreeSurface(_hwscreen);
- _hwscreen = NULL;
+ if (_hwScreen) {
+ SDL_FreeSurface(_hwScreen);
+ _hwScreen = NULL;
}
if (_tmpscreen) {
@@ -1087,9 +1074,9 @@ bool SurfaceSdlGraphicsManager::hotswapGFXMode() {
_overlayscreen = NULL;
// Release the HW screen surface
- if (_hwscreen) {
- SDL_FreeSurface(_hwscreen);
- _hwscreen = NULL;
+ if (_hwScreen) {
+ SDL_FreeSurface(_hwScreen);
+ _hwScreen = NULL;
}
if (_tmpscreen) {
SDL_FreeSurface(_tmpscreen);
@@ -1155,25 +1142,19 @@ void SurfaceSdlGraphicsManager::internUpdateScreen() {
ScalerProc *scalerProc;
int scale1;
- // definitions not available for non-DEBUG here. (needed this to compile in SYMBIAN32 & linux?)
-#if defined(DEBUG) && !defined(WIN32) && !defined(_WIN32_WCE)
- assert(_hwscreen != NULL);
- assert(_hwscreen->map->sw_data != NULL);
-#endif
-
// If the shake position changed, fill the dirty area with blackness
if (_currentShakePos != _newShakePos ||
- (_mouseNeedsRedraw && _mouseBackup.y <= _currentShakePos)) {
+ (_cursorNeedsRedraw && _mouseBackup.y <= _currentShakePos)) {
SDL_Rect blackrect = {0, 0, (Uint16)(_videoMode.screenWidth * _videoMode.scaleFactor), (Uint16)(_newShakePos * _videoMode.scaleFactor)};
if (_videoMode.aspectRatioCorrection && !_overlayVisible)
blackrect.h = real2Aspect(blackrect.h - 1) + 1;
- SDL_FillRect(_hwscreen, &blackrect, 0);
+ SDL_FillRect(_hwScreen, &blackrect, 0);
_currentShakePos = _newShakePos;
- _forceFull = true;
+ _forceRedraw = true;
}
// Check whether the palette was changed in the meantime and update the
@@ -1185,7 +1166,7 @@ void SurfaceSdlGraphicsManager::internUpdateScreen() {
_paletteDirtyEnd = 0;
- _forceFull = true;
+ _forceRedraw = true;
}
if (!_overlayVisible) {
@@ -1207,7 +1188,7 @@ void SurfaceSdlGraphicsManager::internUpdateScreen() {
// Add the area covered by the mouse cursor to the list of dirty rects if
// we have to redraw the mouse.
- if (_mouseNeedsRedraw)
+ if (_cursorNeedsRedraw)
undrawMouse();
#ifdef USE_OSD
@@ -1215,7 +1196,7 @@ void SurfaceSdlGraphicsManager::internUpdateScreen() {
#endif
// Force a full redraw if requested
- if (_forceFull) {
+ if (_forceRedraw) {
_numDirtyRects = 1;
_dirtyRectList[0].x = 0;
_dirtyRectList[0].y = 0;
@@ -1224,7 +1205,7 @@ void SurfaceSdlGraphicsManager::internUpdateScreen() {
}
// Only draw anything if necessary
- if (_numDirtyRects > 0 || _mouseNeedsRedraw) {
+ if (_numDirtyRects > 0 || _cursorNeedsRedraw) {
SDL_Rect *r;
SDL_Rect dst;
uint32 srcPitch, dstPitch;
@@ -1240,10 +1221,10 @@ void SurfaceSdlGraphicsManager::internUpdateScreen() {
}
SDL_LockSurface(srcSurf);
- SDL_LockSurface(_hwscreen);
+ SDL_LockSurface(_hwScreen);
srcPitch = srcSurf->pitch;
- dstPitch = _hwscreen->pitch;
+ dstPitch = _hwScreen->pitch;
for (r = _dirtyRectList; r != lastRect; ++r) {
register int dst_y = r->y + _currentShakePos;
@@ -1268,7 +1249,7 @@ void SurfaceSdlGraphicsManager::internUpdateScreen() {
assert(scalerProc != NULL);
scalerProc((byte *)srcSurf->pixels + (r->x * 2 + 2) + (r->y + 1) * srcPitch, srcPitch,
- (byte *)_hwscreen->pixels + rx1 * 2 + dst_y * dstPitch, dstPitch, r->w, dst_h);
+ (byte *)_hwScreen->pixels + rx1 * 2 + dst_y * dstPitch, dstPitch, r->w, dst_h);
}
r->x = rx1;
@@ -1278,17 +1259,17 @@ void SurfaceSdlGraphicsManager::internUpdateScreen() {
#ifdef USE_SCALERS
if (_videoMode.aspectRatioCorrection && orig_dst_y < height && !_overlayVisible)
- r->h = stretch200To240((uint8 *) _hwscreen->pixels, dstPitch, r->w, r->h, r->x, r->y, orig_dst_y * scale1);
+ r->h = stretch200To240((uint8 *) _hwScreen->pixels, dstPitch, r->w, r->h, r->x, r->y, orig_dst_y * scale1);
#endif
}
SDL_UnlockSurface(srcSurf);
- SDL_UnlockSurface(_hwscreen);
+ SDL_UnlockSurface(_hwScreen);
// Readjust the dirty rect list in case we are doing a full update.
// This is necessary if shaking is active.
- if (_forceFull) {
+ if (_forceRedraw) {
_dirtyRectList[0].y = 0;
- _dirtyRectList[0].h = effectiveScreenHeight();
+ _dirtyRectList[0].h = _videoMode.hardwareHeight;
}
drawMouse();
@@ -1318,18 +1299,18 @@ void SurfaceSdlGraphicsManager::internUpdateScreen() {
y = real2Aspect(y);
if (h > 0 && w > 0) {
- SDL_LockSurface(_hwscreen);
+ SDL_LockSurface(_hwScreen);
// Use white as color for now.
- Uint32 rectColor = SDL_MapRGB(_hwscreen->format, 0xFF, 0xFF, 0xFF);
+ Uint32 rectColor = SDL_MapRGB(_hwScreen->format, 0xFF, 0xFF, 0xFF);
// First draw the top and bottom lines
// then draw the left and right lines
- if (_hwscreen->format->BytesPerPixel == 2) {
- uint16 *top = (uint16 *)((byte *)_hwscreen->pixels + y * _hwscreen->pitch + x * 2);
- uint16 *bottom = (uint16 *)((byte *)_hwscreen->pixels + (y + h) * _hwscreen->pitch + x * 2);
- byte *left = ((byte *)_hwscreen->pixels + y * _hwscreen->pitch + x * 2);
- byte *right = ((byte *)_hwscreen->pixels + y * _hwscreen->pitch + (x + w - 1) * 2);
+ if (_hwScreen->format->BytesPerPixel == 2) {
+ uint16 *top = (uint16 *)((byte *)_hwScreen->pixels + y * _hwScreen->pitch + x * 2);
+ uint16 *bottom = (uint16 *)((byte *)_hwScreen->pixels + (y + h) * _hwScreen->pitch + x * 2);
+ byte *left = ((byte *)_hwScreen->pixels + y * _hwScreen->pitch + x * 2);
+ byte *right = ((byte *)_hwScreen->pixels + y * _hwScreen->pitch + (x + w - 1) * 2);
while (w--) {
*top++ = rectColor;
@@ -1340,14 +1321,14 @@ void SurfaceSdlGraphicsManager::internUpdateScreen() {
*(uint16 *)left = rectColor;
*(uint16 *)right = rectColor;
- left += _hwscreen->pitch;
- right += _hwscreen->pitch;
+ left += _hwScreen->pitch;
+ right += _hwScreen->pitch;
}
- } else if (_hwscreen->format->BytesPerPixel == 4) {
- uint32 *top = (uint32 *)((byte *)_hwscreen->pixels + y * _hwscreen->pitch + x * 4);
- uint32 *bottom = (uint32 *)((byte *)_hwscreen->pixels + (y + h) * _hwscreen->pitch + x * 4);
- byte *left = ((byte *)_hwscreen->pixels + y * _hwscreen->pitch + x * 4);
- byte *right = ((byte *)_hwscreen->pixels + y * _hwscreen->pitch + (x + w - 1) * 4);
+ } else if (_hwScreen->format->BytesPerPixel == 4) {
+ uint32 *top = (uint32 *)((byte *)_hwScreen->pixels + y * _hwScreen->pitch + x * 4);
+ uint32 *bottom = (uint32 *)((byte *)_hwScreen->pixels + (y + h) * _hwScreen->pitch + x * 4);
+ byte *left = ((byte *)_hwScreen->pixels + y * _hwScreen->pitch + x * 4);
+ byte *right = ((byte *)_hwScreen->pixels + y * _hwScreen->pitch + (x + w - 1) * 4);
while (w--) {
*top++ = rectColor;
@@ -1358,12 +1339,12 @@ void SurfaceSdlGraphicsManager::internUpdateScreen() {
*(uint32 *)left = rectColor;
*(uint32 *)right = rectColor;
- left += _hwscreen->pitch;
- right += _hwscreen->pitch;
+ left += _hwScreen->pitch;
+ right += _hwScreen->pitch;
}
}
- SDL_UnlockSurface(_hwscreen);
+ SDL_UnlockSurface(_hwScreen);
}
}
}
@@ -1371,17 +1352,17 @@ void SurfaceSdlGraphicsManager::internUpdateScreen() {
// Finally, blit all our changes to the screen
if (!_displayDisabled) {
- SDL_UpdateRects(_hwscreen, _numDirtyRects, _dirtyRectList);
+ SDL_UpdateRects(_hwScreen, _numDirtyRects, _dirtyRectList);
}
}
_numDirtyRects = 0;
- _forceFull = false;
- _mouseNeedsRedraw = false;
+ _forceRedraw = false;
+ _cursorNeedsRedraw = false;
}
bool SurfaceSdlGraphicsManager::saveScreenshot(const char *filename) {
- assert(_hwscreen != NULL);
+ assert(_hwScreen != NULL);
Common::StackLock lock(_graphicsMutex);
#ifdef USE_PNG
@@ -1391,12 +1372,12 @@ bool SurfaceSdlGraphicsManager::saveScreenshot(const char *filename) {
}
#if SDL_VERSION_ATLEAST(2, 0, 0)
- SDL_Surface *rgbScreen = SDL_ConvertSurfaceFormat(_hwscreen, SDL_PIXELFORMAT_RGB24, 0);
+ SDL_Surface *rgbScreen = SDL_ConvertSurfaceFormat(_hwScreen, SDL_PIXELFORMAT_RGB24, 0);
#else
// This block of code was taken mostly as-is from SDL 1.2's SDL_SaveBMP_RW
SDL_Surface *rgbScreen = SDL_CreateRGBSurface(SDL_SWSURFACE,
- _hwscreen->w,
- _hwscreen->h,
+ _hwScreen->w,
+ _hwScreen->h,
24,
#ifdef SCUMM_LITTLE_ENDIAN
0x0000FF, 0x00FF00, 0xFF0000,
@@ -1411,9 +1392,9 @@ bool SurfaceSdlGraphicsManager::saveScreenshot(const char *filename) {
SDL_Rect bounds;
bounds.x = bounds.y = 0;
- bounds.w = _hwscreen->w;
- bounds.h = _hwscreen->h;
- if (SDL_LowerBlit(_hwscreen, &bounds, rgbScreen, &bounds) < 0) {
+ bounds.w = _hwScreen->w;
+ bounds.h = _hwScreen->h;
+ if (SDL_LowerBlit(_hwScreen, &bounds, rgbScreen, &bounds) < 0) {
SDL_FreeSurface(rgbScreen);
rgbScreen = nullptr;
}
@@ -1441,7 +1422,7 @@ bool SurfaceSdlGraphicsManager::saveScreenshot(const char *filename) {
return success;
#else
- return SDL_SaveBMP(_hwscreen, filename) == 0;
+ return SDL_SaveBMP(_hwScreen, filename) == 0;
#endif
}
@@ -1571,7 +1552,7 @@ void SurfaceSdlGraphicsManager::unlockScreen() {
SDL_UnlockSurface(_screen);
// Trigger a full screen update
- _forceFull = true;
+ _forceRedraw = true;
// Finally unlock the graphics mutex
g_system->unlockMutex(_graphicsMutex);
@@ -1585,11 +1566,11 @@ void SurfaceSdlGraphicsManager::fillScreen(uint32 col) {
}
void SurfaceSdlGraphicsManager::addDirtyRect(int x, int y, int w, int h, bool realCoordinates) {
- if (_forceFull)
+ if (_forceRedraw)
return;
if (_numDirtyRects == NUM_DIRTY_RECT) {
- _forceFull = true;
+ _forceRedraw = true;
return;
}
@@ -1608,8 +1589,8 @@ void SurfaceSdlGraphicsManager::addDirtyRect(int x, int y, int w, int h, bool re
if (!realCoordinates) {
x--;
y--;
- w+=2;
- h+=2;
+ w += 2;
+ h += 2;
}
// clip
@@ -1620,7 +1601,7 @@ void SurfaceSdlGraphicsManager::addDirtyRect(int x, int y, int w, int h, bool re
if (y < 0) {
h += y;
- y=0;
+ y = 0;
}
if (w > width - x) {
@@ -1638,7 +1619,7 @@ void SurfaceSdlGraphicsManager::addDirtyRect(int x, int y, int w, int h, bool re
#endif
if (w == width && h == height) {
- _forceFull = true;
+ _forceRedraw = true;
return;
}
@@ -1652,11 +1633,11 @@ void SurfaceSdlGraphicsManager::addDirtyRect(int x, int y, int w, int h, bool re
}
}
-int16 SurfaceSdlGraphicsManager::getHeight() {
+int16 SurfaceSdlGraphicsManager::getHeight() const {
return _videoMode.screenHeight;
}
-int16 SurfaceSdlGraphicsManager::getWidth() {
+int16 SurfaceSdlGraphicsManager::getWidth() const {
return _videoMode.screenWidth;
}
@@ -1697,7 +1678,7 @@ void SurfaceSdlGraphicsManager::setPalette(const byte *colors, uint start, uint
blitCursor();
}
-void SurfaceSdlGraphicsManager::grabPalette(byte *colors, uint start, uint num) {
+void SurfaceSdlGraphicsManager::grabPalette(byte *colors, uint start, uint num) const {
assert(colors);
#ifdef USE_RGB_COLOR
@@ -1777,56 +1758,7 @@ void SurfaceSdlGraphicsManager::clearFocusRectangle() {
#pragma mark --- Overlays ---
#pragma mark -
-void SurfaceSdlGraphicsManager::showOverlay() {
- assert(_transactionMode == kTransactionNone);
-
- int x, y;
-
- if (_overlayVisible)
- return;
-
- _overlayVisible = true;
-
- // Since resolution could change, put mouse to adjusted position
- // Fixes bug #1349059
- x = _mouseCurState.x * _videoMode.scaleFactor;
- if (_videoMode.aspectRatioCorrection)
- y = real2Aspect(_mouseCurState.y) * _videoMode.scaleFactor;
- else
- y = _mouseCurState.y * _videoMode.scaleFactor;
-
- warpMouse(x, y);
-
- clearOverlay();
-}
-
-void SurfaceSdlGraphicsManager::hideOverlay() {
- assert(_transactionMode == kTransactionNone);
-
- if (!_overlayVisible)
- return;
-
- int x, y;
-
- _overlayVisible = false;
-
- // Since resolution could change, put mouse to adjusted position
- // Fixes bug #1349059
- x = _mouseCurState.x / _videoMode.scaleFactor;
- y = _mouseCurState.y / _videoMode.scaleFactor;
- if (_videoMode.aspectRatioCorrection)
- y = aspect2Real(y);
-
- warpMouse(x, y);
-
- clearOverlay();
-
- _forceFull = true;
-}
-
void SurfaceSdlGraphicsManager::clearOverlay() {
- //assert(_transactionMode == kTransactionNone);
-
Common::StackLock lock(_graphicsMutex); // Lock the mutex until this function ends
if (!_overlayVisible)
@@ -1854,10 +1786,10 @@ void SurfaceSdlGraphicsManager::clearOverlay() {
SDL_UnlockSurface(_tmpscreen);
SDL_UnlockSurface(_overlayscreen);
- _forceFull = true;
+ _forceRedraw = true;
}
-void SurfaceSdlGraphicsManager::grabOverlay(void *buf, int pitch) {
+void SurfaceSdlGraphicsManager::grabOverlay(void *buf, int pitch) const {
assert(_transactionMode == kTransactionNone);
if (_overlayscreen == NULL)
@@ -1937,56 +1869,11 @@ bool SurfaceSdlGraphicsManager::showMouse(bool visible) {
bool last = _mouseVisible;
_mouseVisible = visible;
- _mouseNeedsRedraw = true;
+ _cursorNeedsRedraw = true;
return last;
}
-void SurfaceSdlGraphicsManager::setMousePos(int x, int y) {
- if (x != _mouseCurState.x || y != _mouseCurState.y) {
- _mouseNeedsRedraw = true;
- _mouseCurState.x = x;
- _mouseCurState.y = y;
- }
-}
-
-void SurfaceSdlGraphicsManager::warpMouse(int x, int y) {
- // Don't change actual mouse position, when mouse is outside of our window (in case of windowed mode)
- if (!_window->hasMouseFocus()) {
- setMousePos(x, y); // but change game cursor position
- return;
- }
-
- int x1 = x, y1 = y;
- if (_videoMode.aspectRatioCorrection && !_overlayVisible)
- y1 = real2Aspect(y1);
-
- if (_mouseCurState.x != x || _mouseCurState.y != y) {
- if (!_overlayVisible) {
- x1 *= _videoMode.scaleFactor;
- y1 *= _videoMode.scaleFactor;
- }
-
-#if SDL_VERSION_ATLEAST(2, 0, 0)
- // Transform our coordinates in "virtual" output coordinate space into
- // actual output coordinate space.
- x1 = x1 * _windowWidth / _videoMode.hardwareWidth;
- y1 = y1 * _windowHeight / _videoMode.hardwareHeight;
-#endif
-
- _window->warpMouseInWindow(x1, y1);
-
- // SDL_WarpMouse() generates a mouse movement event, so
- // setMousePos() would be called eventually. However, the
- // cannon script in CoMI calls this function twice each time
- // the cannon is reloaded. Unless we update the mouse position
- // immediately the second call is ignored, causing the cannon
- // to change its aim.
-
- setMousePos(x, y);
- }
-}
-
void SurfaceSdlGraphicsManager::setMouseCursor(const void *buf, uint w, uint h, int hotspot_x, int hotspot_y, uint32 keycolor, bool dontScale, const Graphics::PixelFormat *format) {
#ifdef USE_RGB_COLOR
if (!format)
@@ -2022,10 +1909,10 @@ void SurfaceSdlGraphicsManager::setMouseCursor(const void *buf, uint w, uint h,
_mouseCurState.w + 2,
_mouseCurState.h + 2,
16,
- _hwscreen->format->Rmask,
- _hwscreen->format->Gmask,
- _hwscreen->format->Bmask,
- _hwscreen->format->Amask);
+ _hwScreen->format->Rmask,
+ _hwScreen->format->Gmask,
+ _hwScreen->format->Bmask,
+ _hwScreen->format->Amask);
if (_mouseOrigSurface == NULL)
error("allocating _mouseOrigSurface failed");
@@ -2057,7 +1944,7 @@ void SurfaceSdlGraphicsManager::blitCursor() {
if (!_mouseOrigSurface || !_mouseData)
return;
- _mouseNeedsRedraw = true;
+ _cursorNeedsRedraw = true;
w = _mouseCurState.w;
h = _mouseCurState.h;
@@ -2159,10 +2046,10 @@ void SurfaceSdlGraphicsManager::blitCursor() {
_mouseCurState.rW,
_mouseCurState.rH,
16,
- _hwscreen->format->Rmask,
- _hwscreen->format->Gmask,
- _hwscreen->format->Bmask,
- _hwscreen->format->Amask);
+ _hwScreen->format->Rmask,
+ _hwScreen->format->Gmask,
+ _hwScreen->format->Bmask,
+ _hwScreen->format->Amask);
if (_mouseSurface == NULL)
error("allocating _mouseSurface failed");
@@ -2245,8 +2132,10 @@ void SurfaceSdlGraphicsManager::drawMouse() {
int scale;
int hotX, hotY;
- dst.x = _mouseCurState.x;
- dst.y = _mouseCurState.y;
+ const Common::Point virtualCursor = convertWindowToVirtual(_cursorX, _cursorY);
+
+ dst.x = virtualCursor.x;
+ dst.y = virtualCursor.y;
if (!_overlayVisible) {
scale = _videoMode.scaleFactor;
@@ -2286,7 +2175,7 @@ void SurfaceSdlGraphicsManager::drawMouse() {
// Note that SDL_BlitSurface() and addDirtyRect() will both perform any
// clipping necessary
- if (SDL_BlitSurface(_mouseSurface, NULL, _hwscreen, &dst) != 0)
+ if (SDL_BlitSurface(_mouseSurface, NULL, _hwScreen, &dst) != 0)
error("SDL_BlitSurface failed: %s", SDL_GetError());
// The screen will be updated using real surface coordinates, i.e.
@@ -2335,14 +2224,14 @@ void SurfaceSdlGraphicsManager::displayMessageOnOSD(const char *msg) {
}
// Clip the rect
- if (width > _hwscreen->w)
- width = _hwscreen->w;
- if (height > _hwscreen->h)
- height = _hwscreen->h;
+ if (width > _hwScreen->w)
+ width = _hwScreen->w;
+ if (height > _hwScreen->h)
+ height = _hwScreen->h;
_osdMessageSurface = SDL_CreateRGBSurface(
SDL_SWSURFACE | SDL_RLEACCEL | SDL_SRCALPHA,
- width, height, 16, _hwscreen->format->Rmask, _hwscreen->format->Gmask, _hwscreen->format->Bmask, _hwscreen->format->Amask
+ width, height, 16, _hwScreen->format->Rmask, _hwScreen->format->Gmask, _hwScreen->format->Bmask, _hwScreen->format->Amask
);
// Lock the surface
@@ -2379,8 +2268,8 @@ void SurfaceSdlGraphicsManager::displayMessageOnOSD(const char *msg) {
SDL_Rect SurfaceSdlGraphicsManager::getOSDMessageRect() const {
SDL_Rect rect;
- rect.x = (_hwscreen->w - _osdMessageSurface->w) / 2;
- rect.y = (_hwscreen->h - _osdMessageSurface->h) / 2;
+ rect.x = (_hwScreen->w - _osdMessageSurface->w) / 2;
+ rect.y = (_hwScreen->h - _osdMessageSurface->h) / 2;
rect.w = _osdMessageSurface->w;
rect.h = _osdMessageSurface->h;
return rect;
@@ -2393,7 +2282,7 @@ void SurfaceSdlGraphicsManager::displayActivityIconOnOSD(const Graphics::Surface
if (_osdIconSurface && !icon) {
// Force a redraw to clear the icon on the next update
- _forceFull = true;
+ _forceRedraw = true;
}
if (_osdIconSurface) {
@@ -2432,7 +2321,7 @@ void SurfaceSdlGraphicsManager::displayActivityIconOnOSD(const Graphics::Surface
SDL_Rect SurfaceSdlGraphicsManager::getOSDIconRect() const {
SDL_Rect dstRect;
- dstRect.x = _hwscreen->w - _osdIconSurface->w - 10;
+ dstRect.x = _hwScreen->w - _osdIconSurface->w - 10;
dstRect.y = 10;
dstRect.w = _osdIconSurface->w;
dstRect.h = _osdIconSurface->h;
@@ -2464,7 +2353,7 @@ void SurfaceSdlGraphicsManager::updateOSD() {
_osdMessageAlpha = startAlpha + diff * (SDL_ALPHA_TRANSPARENT - startAlpha) / kOSDFadeOutDuration;
}
SDL_SetAlpha(_osdMessageSurface, SDL_RLEACCEL | SDL_SRCCOLORKEY | SDL_SRCALPHA, _osdMessageAlpha);
- _forceFull = true;
+ _forceRedraw = true;
}
if (_osdMessageAlpha == SDL_ALPHA_TRANSPARENT) {
@@ -2474,26 +2363,30 @@ void SurfaceSdlGraphicsManager::updateOSD() {
if (_osdIconSurface) {
// Redraw the area below the icon for the transparent blit to give correct results.
- _forceFull = true;
+ _forceRedraw = true;
}
}
void SurfaceSdlGraphicsManager::drawOSD() {
if (_osdMessageSurface) {
SDL_Rect dstRect = getOSDMessageRect();
- SDL_BlitSurface(_osdMessageSurface, 0, _hwscreen, &dstRect);
+ SDL_BlitSurface(_osdMessageSurface, 0, _hwScreen, &dstRect);
}
if (_osdIconSurface) {
SDL_Rect dstRect = getOSDIconRect();
- SDL_BlitSurface(_osdIconSurface, 0, _hwscreen, &dstRect);
+ SDL_BlitSurface(_osdIconSurface, 0, _hwScreen, &dstRect);
}
}
#endif
-bool SurfaceSdlGraphicsManager::handleScalerHotkeys(Common::KeyCode key) {
+void SurfaceSdlGraphicsManager::handleResizeImpl(const int width, const int height) {
+ SdlGraphicsManager::handleResizeImpl(width, height);
+ recalculateDisplayAreas();
+}
+bool SurfaceSdlGraphicsManager::handleScalerHotkeys(Common::KeyCode key) {
// Ctrl-Alt-a toggles aspect ratio correction
if (key == 'a') {
beginGFXTransaction();
@@ -2505,13 +2398,13 @@ bool SurfaceSdlGraphicsManager::handleScalerHotkeys(Common::KeyCode key) {
message = Common::String::format("%s\n%d x %d -> %d x %d",
_("Enabled aspect ratio correction"),
_videoMode.screenWidth, _videoMode.screenHeight,
- _hwscreen->w, _hwscreen->h
+ _hwScreen->w, _hwScreen->h
);
else
message = Common::String::format("%s\n%d x %d -> %d x %d",
_("Disabled aspect ratio correction"),
_videoMode.screenWidth, _videoMode.screenHeight,
- _hwscreen->w, _hwscreen->h
+ _hwScreen->w, _hwScreen->h
);
displayMessageOnOSD(message.c_str());
#endif
@@ -2532,7 +2425,7 @@ bool SurfaceSdlGraphicsManager::handleScalerHotkeys(Common::KeyCode key) {
displayMessageOnOSD(_("Filtering disabled"));
}
#endif
- _forceFull = true;
+ _forceRedraw = true;
internUpdateScreen();
return true;
}
@@ -2542,12 +2435,19 @@ bool SurfaceSdlGraphicsManager::handleScalerHotkeys(Common::KeyCode key) {
int factor = _videoMode.scaleFactor - 1;
SDLKey sdlKey = (SDLKey)key;
+#if SDL_VERSION_ATLEAST(2, 0, 0)
+ bool sizeChanged = false;
+#endif
+
// Increase/decrease the scale factor
if (sdlKey == SDLK_EQUALS || sdlKey == SDLK_PLUS || sdlKey == SDLK_MINUS ||
sdlKey == SDLK_KP_PLUS || sdlKey == SDLK_KP_MINUS) {
factor += (sdlKey == SDLK_MINUS || sdlKey == SDLK_KP_MINUS) ? -1 : +1;
if (0 <= factor && factor <= 3) {
newMode = s_gfxModeSwitchTable[_scalerType][factor];
+#if SDL_VERSION_ATLEAST(2, 0, 0)
+ sizeChanged = true;
+#endif
}
}
@@ -2585,10 +2485,19 @@ bool SurfaceSdlGraphicsManager::handleScalerHotkeys(Common::KeyCode key) {
_("Active graphics filter:"),
newScalerName,
_videoMode.screenWidth, _videoMode.screenHeight,
- _hwscreen->w, _hwscreen->h);
+ _hwScreen->w, _hwScreen->h);
displayMessageOnOSD(message.c_str());
}
#endif
+
+#if SDL_VERSION_ATLEAST(2, 0, 0)
+ if (sizeChanged) {
+ // Forcibly resizing the window here since a user switching scaler
+ // size will not normally cause the window to update
+ _window->createOrUpdateWindow(_hwScreen->w, _hwScreen->h, _lastFlags);
+ }
+#endif
+
internUpdateScreen();
return true;
@@ -2700,37 +2609,11 @@ bool SurfaceSdlGraphicsManager::notifyEvent(const Common::Event &event) {
}
void SurfaceSdlGraphicsManager::notifyVideoExpose() {
- _forceFull = true;
-}
-
-void SurfaceSdlGraphicsManager::notifyResize(const uint width, const uint height) {
-#if SDL_VERSION_ATLEAST(2, 0, 0)
- setWindowResolution(width, height);
-#endif
-}
-
-void SurfaceSdlGraphicsManager::transformMouseCoordinates(Common::Point &point) {
-#if SDL_VERSION_ATLEAST(2, 0, 0)
- // In SDL2 the actual output resolution might be different from what we
- // requested. Thus, we transform the coordinates from actual output
- // coordinate space into the "virtual" output coordinate space.
- // Please note that we ignore the possible existence of black bars here,
- // this avoids the feeling of stickyness to black bars.
- point.x = point.x * _videoMode.hardwareWidth / _windowWidth;
- point.y = point.y * _videoMode.hardwareHeight / _windowHeight;
-#endif
-
- if (!_overlayVisible) {
- point.x /= _videoMode.scaleFactor;
- point.y /= _videoMode.scaleFactor;
- if (_videoMode.aspectRatioCorrection)
- point.y = aspect2Real(point.y);
- }
+ _forceRedraw = true;
}
-void SurfaceSdlGraphicsManager::notifyMousePos(Common::Point mouse) {
- transformMouseCoordinates(mouse);
- setMousePos(mouse.x, mouse.y);
+void SurfaceSdlGraphicsManager::notifyResize(const int width, const int height) {
+ handleResize(width, height);
}
#if SDL_VERSION_ATLEAST(2, 0, 0)
@@ -2742,39 +2625,6 @@ void SurfaceSdlGraphicsManager::deinitializeRenderer() {
_renderer = nullptr;
}
-void SurfaceSdlGraphicsManager::setWindowResolution(int width, int height) {
- _windowWidth = width;
- _windowHeight = height;
-
- // We expect full screen resolution as inputs coming from the event system.
- _eventSource->resetKeyboardEmulation(_windowWidth - 1, _windowHeight - 1);
-
- // Calculate the "viewport" for the actual area we draw in. In fullscreen
- // we can easily get a different resolution than what we requested. In
- // this case, we add black bars if necessary to assure the aspect ratio
- // is preserved.
- const frac_t outputAspect = intToFrac(_windowWidth) / _windowHeight;
- const frac_t desiredAspect = intToFrac(_videoMode.hardwareWidth) / _videoMode.hardwareHeight;
-
- _viewport.w = _windowWidth;
- _viewport.h = _windowHeight;
-
- // Adjust one dimension for mantaining the aspect ratio.
- if (abs(outputAspect - desiredAspect) >= (int)(FRAC_ONE / 1000)) {
- if (outputAspect < desiredAspect) {
- _viewport.h = _videoMode.hardwareHeight * _windowWidth / _videoMode.hardwareWidth;
- } else if (outputAspect > desiredAspect) {
- _viewport.w = _videoMode.hardwareWidth * _windowHeight / _videoMode.hardwareHeight;
- }
- }
-
- _viewport.x = (_windowWidth - _viewport.w) / 2;
- _viewport.y = (_windowHeight - _viewport.h) / 2;
-
- // Force a full redraw because we changed the viewport.
- _forceFull = true;
-}
-
void SurfaceSdlGraphicsManager::recreateScreenTexture() {
if (!_renderer)
return;
@@ -2807,8 +2657,8 @@ SDL_Surface *SurfaceSdlGraphicsManager::SDL_SetVideoMode(int width, int height,
return nullptr;
}
- SDL_GetWindowSize(_window->getSDLWindow(), &_windowWidth, &_windowHeight);
- setWindowResolution(_windowWidth, _windowHeight);
+ getWindowSizeFromSdl(&_windowWidth, &_windowHeight);
+ handleResize(_windowWidth, _windowHeight);
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, _videoMode.filtering ? "linear" : "nearest");
@@ -2830,8 +2680,14 @@ SDL_Surface *SurfaceSdlGraphicsManager::SDL_SetVideoMode(int width, int height,
void SurfaceSdlGraphicsManager::SDL_UpdateRects(SDL_Surface *screen, int numrects, SDL_Rect *rects) {
SDL_UpdateTexture(_screenTexture, nullptr, screen->pixels, screen->pitch);
+ SDL_Rect viewport;
+ viewport.x = _activeArea.drawRect.left;
+ viewport.y = _activeArea.drawRect.top;
+ viewport.w = _activeArea.drawRect.width();
+ viewport.h = _activeArea.drawRect.height();
+
SDL_RenderClear(_renderer);
- SDL_RenderCopy(_renderer, _screenTexture, NULL, &_viewport);
+ SDL_RenderCopy(_renderer, _screenTexture, NULL, &viewport);
SDL_RenderPresent(_renderer);
}
#endif // SDL_VERSION_ATLEAST(2, 0, 0)
diff --git a/backends/graphics/surfacesdl/surfacesdl-graphics.h b/backends/graphics/surfacesdl/surfacesdl-graphics.h
index 85f63cb61a..c1e49b953a 100644
--- a/backends/graphics/surfacesdl/surfacesdl-graphics.h
+++ b/backends/graphics/surfacesdl/surfacesdl-graphics.h
@@ -40,7 +40,6 @@
#endif
#if !defined(_WIN32_WCE) && !defined(__SYMBIAN32__)
-// Uncomment this to enable the 'on screen display' code.
#define USE_OSD 1
#endif
@@ -80,76 +79,71 @@ public:
SurfaceSdlGraphicsManager(SdlEventSource *sdlEventSource, SdlWindow *window);
virtual ~SurfaceSdlGraphicsManager();
- virtual void activateManager();
- virtual void deactivateManager();
+ virtual void activateManager() override;
+ virtual void deactivateManager() override;
- virtual bool hasFeature(OSystem::Feature f);
- virtual void setFeatureState(OSystem::Feature f, bool enable);
- virtual bool getFeatureState(OSystem::Feature f);
+ virtual bool hasFeature(OSystem::Feature f) const override;
+ virtual void setFeatureState(OSystem::Feature f, bool enable) override;
+ virtual bool getFeatureState(OSystem::Feature f) const override;
- virtual const OSystem::GraphicsMode *getSupportedGraphicsModes() const;
- virtual int getDefaultGraphicsMode() const;
- virtual bool setGraphicsMode(int mode);
- virtual int getGraphicsMode() const;
- virtual void resetGraphicsScale();
+ virtual const OSystem::GraphicsMode *getSupportedGraphicsModes() const override;
+ virtual int getDefaultGraphicsMode() const override;
+ virtual bool setGraphicsMode(int mode) override;
+ virtual int getGraphicsMode() const override;
+ virtual void resetGraphicsScale() override;
#ifdef USE_RGB_COLOR
- virtual Graphics::PixelFormat getScreenFormat() const { return _screenFormat; }
- virtual Common::List<Graphics::PixelFormat> getSupportedFormats() const;
+ virtual Graphics::PixelFormat getScreenFormat() const override { return _screenFormat; }
+ virtual Common::List<Graphics::PixelFormat> getSupportedFormats() const override;
#endif
- virtual const OSystem::GraphicsMode *getSupportedShaders() const;
- virtual int getShader() const;
- virtual bool setShader(int id);
- virtual void initSize(uint w, uint h, const Graphics::PixelFormat *format = NULL);
- virtual int getScreenChangeID() const { return _screenChangeCount; }
+ virtual const OSystem::GraphicsMode *getSupportedShaders() const override;
+ virtual int getShader() const override;
+ virtual bool setShader(int id) override;
+ virtual void initSize(uint w, uint h, const Graphics::PixelFormat *format = NULL) override;
+ virtual int getScreenChangeID() const override { return _screenChangeCount; }
- virtual void beginGFXTransaction();
- virtual OSystem::TransactionError endGFXTransaction();
+ virtual void beginGFXTransaction() override;
+ virtual OSystem::TransactionError endGFXTransaction() override;
- virtual int16 getHeight();
- virtual int16 getWidth();
+ virtual int16 getHeight() const override;
+ virtual int16 getWidth() const override;
protected:
// PaletteManager API
- virtual void setPalette(const byte *colors, uint start, uint num);
- virtual void grabPalette(byte *colors, uint start, uint num);
+ virtual void setPalette(const byte *colors, uint start, uint num) override;
+ virtual void grabPalette(byte *colors, uint start, uint num) const override;
public:
- virtual void copyRectToScreen(const void *buf, int pitch, int x, int y, int w, int h);
- virtual Graphics::Surface *lockScreen();
- virtual void unlockScreen();
- virtual void fillScreen(uint32 col);
- virtual void updateScreen();
- virtual void setShakePos(int shakeOffset);
- virtual void setFocusRectangle(const Common::Rect& rect);
- virtual void clearFocusRectangle();
-
- virtual void showOverlay();
- virtual void hideOverlay();
- virtual Graphics::PixelFormat getOverlayFormat() const { return _overlayFormat; }
- virtual void clearOverlay();
- virtual void grabOverlay(void *buf, int pitch);
- virtual void copyRectToOverlay(const void *buf, int pitch, int x, int y, int w, int h);
- virtual int16 getOverlayHeight() { return _videoMode.overlayHeight; }
- virtual int16 getOverlayWidth() { return _videoMode.overlayWidth; }
-
- virtual bool showMouse(bool visible);
- virtual void warpMouse(int x, int y);
- virtual void setMouseCursor(const void *buf, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor, bool dontScale = false, const Graphics::PixelFormat *format = NULL);
- virtual void setCursorPalette(const byte *colors, uint start, uint num);
+ virtual void copyRectToScreen(const void *buf, int pitch, int x, int y, int w, int h) override;
+ virtual Graphics::Surface *lockScreen() override;
+ virtual void unlockScreen() override;
+ virtual void fillScreen(uint32 col) override;
+ virtual void updateScreen() override;
+ virtual void setShakePos(int shakeOffset) override;
+ virtual void setFocusRectangle(const Common::Rect& rect) override;
+ virtual void clearFocusRectangle() override;
+
+ virtual Graphics::PixelFormat getOverlayFormat() const override { return _overlayFormat; }
+ virtual void clearOverlay() override;
+ virtual void grabOverlay(void *buf, int pitch) const override;
+ virtual void copyRectToOverlay(const void *buf, int pitch, int x, int y, int w, int h) override;
+ virtual int16 getOverlayHeight() const override { return _videoMode.overlayHeight; }
+ virtual int16 getOverlayWidth() const override { return _videoMode.overlayWidth; }
+
+ virtual bool showMouse(bool visible) override;
+ virtual void setMouseCursor(const void *buf, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor, bool dontScale = false, const Graphics::PixelFormat *format = NULL) override;
+ virtual void setCursorPalette(const byte *colors, uint start, uint num) override;
#ifdef USE_OSD
- virtual void displayMessageOnOSD(const char *msg);
- virtual void displayActivityIconOnOSD(const Graphics::Surface *icon);
+ virtual void displayMessageOnOSD(const char *msg) override;
+ virtual void displayActivityIconOnOSD(const Graphics::Surface *icon) override;
#endif
// Override from Common::EventObserver
- bool notifyEvent(const Common::Event &event);
+ virtual bool notifyEvent(const Common::Event &event) override;
// SdlGraphicsManager interface
- virtual void notifyVideoExpose();
- virtual void notifyResize(const uint width, const uint height);
- virtual void transformMouseCoordinates(Common::Point &point);
- virtual void notifyMousePos(Common::Point mouse);
+ virtual void notifyVideoExpose() override;
+ virtual void notifyResize(const int width, const int height) override;
protected:
#ifdef USE_OSD
@@ -178,8 +172,11 @@ protected:
void drawOSD();
#endif
- /** Hardware screen */
- SDL_Surface *_hwscreen;
+ virtual bool gameNeedsAspectRatioCorrection() const override {
+ return _videoMode.aspectRatioCorrection;
+ }
+
+ virtual void handleResizeImpl(const int width, const int height) override;
virtual int getGraphicsModeScale(int mode) const override;
@@ -188,10 +185,7 @@ protected:
* around this API to keep the code paths as close as possible. */
SDL_Renderer *_renderer;
SDL_Texture *_screenTexture;
- SDL_Rect _viewport;
- int _windowWidth, _windowHeight;
void deinitializeRenderer();
- void setWindowResolution(int width, int height);
void recreateScreenTexture();
virtual SDL_Surface *SDL_SetVideoMode(int width, int height, int bpp, Uint32 flags);
@@ -218,7 +212,6 @@ protected:
SDL_Surface *_tmpscreen2;
SDL_Surface *_overlayscreen;
- bool _overlayVisible;
Graphics::PixelFormat _overlayFormat;
enum {
@@ -280,14 +273,11 @@ protected:
uint8 _originalBitsPerPixel;
#endif
- /** Force full redraw on next updateScreen */
- bool _forceFull;
-
ScalerProc *_scalerProc;
int _scalerType;
int _transactionMode;
- // Indicates whether it is needed to free _hwsurface in destructor
+ // Indicates whether it is needed to free _hwSurface in destructor
bool _displayDisabled;
bool _screenIsLocked;
@@ -308,10 +298,6 @@ protected:
int _numDirtyRects;
struct MousePos {
- // The mouse position, using either virtual (game) or real
- // (overlay) coordinates.
- int16 x, y;
-
// The size and hotspot of the original cursor image.
int16 w, h;
int16 hotX, hotY;
@@ -326,14 +312,13 @@ protected:
int16 vW, vH;
int16 vHotX, vHotY;
- MousePos() : x(0), y(0), w(0), h(0), hotX(0), hotY(0),
+ MousePos() : w(0), h(0), hotX(0), hotY(0),
rW(0), rH(0), rHotX(0), rHotY(0), vW(0), vH(0),
vHotX(0), vHotY(0)
{ }
};
bool _mouseVisible;
- bool _mouseNeedsRedraw;
byte *_mouseData;
SDL_Rect _mouseBackup;
MousePos _mouseCurState;
@@ -386,21 +371,45 @@ protected:
virtual void unloadGFXMode();
virtual bool hotswapGFXMode();
- virtual void setFullscreenMode(bool enable);
virtual void setAspectRatioCorrection(bool enable);
#if SDL_VERSION_ATLEAST(2, 0, 0)
- virtual void setFilteringMode(bool enable);
+ void setFilteringMode(bool enable);
#endif
- virtual int effectiveScreenHeight() const;
-
+ virtual bool saveScreenshot(const char *filename);
virtual void setGraphicsModeIntern();
- virtual bool handleScalerHotkeys(Common::KeyCode key);
- virtual bool isScalerHotkey(const Common::Event &event);
- virtual void setMousePos(int x, int y);
- virtual void toggleFullScreen();
- virtual bool saveScreenshot(const char *filename);
+private:
+ void setFullscreenMode(bool enable);
+ bool handleScalerHotkeys(Common::KeyCode key);
+ bool isScalerHotkey(const Common::Event &event);
+ void toggleFullScreen();
+
+ /**
+ * Converts the given point from the overlay's coordinate space to the
+ * game's coordinate space.
+ */
+ Common::Point convertOverlayToGame(const int x, const int y) const {
+ if (getOverlayWidth() == 0 || getOverlayHeight() == 0) {
+ error("convertOverlayToGame called without a valid overlay");
+ }
+
+ return Common::Point(x * getWidth() / getOverlayWidth(),
+ y * getHeight() / getOverlayHeight());
+ }
+
+ /**
+ * Converts the given point from the game's coordinate space to the
+ * overlay's coordinate space.
+ */
+ Common::Point convertGameToOverlay(const int x, const int y) const {
+ if (getWidth() == 0 || getHeight() == 0) {
+ error("convertGameToOverlay called without a valid overlay");
+ }
+
+ return Common::Point(x * getOverlayWidth() / getWidth(),
+ y * getOverlayHeight() / getHeight());
+ }
};
#endif
diff --git a/backends/graphics/windowed.h b/backends/graphics/windowed.h
new file mode 100644
index 0000000000..b3e5b832b3
--- /dev/null
+++ b/backends/graphics/windowed.h
@@ -0,0 +1,313 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef BACKENDS_GRAPHICS_WINDOWED_H
+#define BACKENDS_GRAPHICS_WINDOWED_H
+
+#include "backends/graphics/graphics.h"
+#include "common/frac.h"
+#include "common/rect.h"
+#include "common/textconsole.h"
+#include "graphics/scaler/aspect.h"
+
+class WindowedGraphicsManager : virtual public GraphicsManager {
+public:
+ WindowedGraphicsManager() :
+ _windowWidth(0),
+ _windowHeight(0),
+ _overlayVisible(false),
+ _forceRedraw(false),
+ _cursorX(0),
+ _cursorY(0),
+ _cursorNeedsRedraw(false) {}
+
+ virtual void showOverlay() override {
+ if (_overlayVisible)
+ return;
+
+ _activeArea.drawRect = _overlayDrawRect;
+ _activeArea.width = getOverlayWidth();
+ _activeArea.height = getOverlayHeight();
+ _overlayVisible = true;
+ _forceRedraw = true;
+ }
+
+ virtual void hideOverlay() override {
+ if (!_overlayVisible)
+ return;
+
+ _activeArea.drawRect = _gameDrawRect;
+ _activeArea.width = getWidth();
+ _activeArea.height = getHeight();
+ _overlayVisible = false;
+ _forceRedraw = true;
+ }
+
+protected:
+ /**
+ * @returns whether or not the game screen must have aspect ratio correction
+ * applied for correct rendering.
+ */
+ virtual bool gameNeedsAspectRatioCorrection() const = 0;
+
+ /**
+ * Backend-specific implementation for updating internal surfaces that need
+ * to reflect the new window size.
+ */
+ virtual void handleResizeImpl(const int width, const int height) = 0;
+
+ /**
+ * Converts the given point from the active virtual screen's coordinate
+ * space to the window's coordinate space (i.e. game-to-window or
+ * overlay-to-window).
+ */
+ Common::Point convertVirtualToWindow(const int x, const int y) const {
+ const int targetX = _activeArea.drawRect.left;
+ const int targetY = _activeArea.drawRect.top;
+ const int targetWidth = _activeArea.drawRect.width();
+ const int targetHeight = _activeArea.drawRect.height();
+ const int sourceWidth = _activeArea.width;
+ const int sourceHeight = _activeArea.height;
+
+ if (sourceWidth == 0 || sourceHeight == 0) {
+ error("convertVirtualToWindow called without a valid draw rect");
+ }
+
+ return Common::Point(targetX + x * targetWidth / sourceWidth,
+ targetY + y * targetHeight / sourceHeight);
+ }
+
+ /**
+ * Converts the given point from the window's coordinate space to the
+ * active virtual screen's coordinate space (i.e. window-to-game or
+ * window-to-overlay).
+ */
+ Common::Point convertWindowToVirtual(int x, int y) const {
+ const int sourceX = _activeArea.drawRect.left;
+ const int sourceY = _activeArea.drawRect.top;
+ const int sourceMaxX = _activeArea.drawRect.right - 1;
+ const int sourceMaxY = _activeArea.drawRect.bottom - 1;
+ const int sourceWidth = _activeArea.drawRect.width();
+ const int sourceHeight = _activeArea.drawRect.height();
+ const int targetWidth = _activeArea.width;
+ const int targetHeight = _activeArea.height;
+
+ if (sourceWidth == 0 || sourceHeight == 0) {
+ error("convertWindowToVirtual called without a valid draw rect");
+ }
+
+ x = CLIP<int>(x, sourceX, sourceMaxX);
+ y = CLIP<int>(y, sourceY, sourceMaxY);
+
+ return Common::Point(((x - sourceX) * targetWidth) / sourceWidth,
+ ((y - sourceY) * targetHeight) / sourceHeight);
+ }
+
+ /**
+ * @returns the desired aspect ratio of the game surface.
+ */
+ frac_t getDesiredGameAspectRatio() const {
+ if (getHeight() == 0 || gameNeedsAspectRatioCorrection()) {
+ return intToFrac(4) / 3;
+ }
+
+ return intToFrac(getWidth()) / getHeight();
+ }
+
+ /**
+ * Called after the window has been updated with new dimensions.
+ *
+ * @param width The new width of the window, excluding window decoration.
+ * @param height The new height of the window, excluding window decoration.
+ */
+ void handleResize(const int width, const int height) {
+ _windowWidth = width;
+ _windowHeight = height;
+ handleResizeImpl(width, height);
+ }
+
+ /**
+ * Recalculates the display areas for the game and overlay surfaces within
+ * the window.
+ */
+ virtual void recalculateDisplayAreas() {
+ if (_windowHeight == 0) {
+ return;
+ }
+
+ const frac_t outputAspect = intToFrac(_windowWidth) / _windowHeight;
+
+ populateDisplayAreaDrawRect(getDesiredGameAspectRatio(), outputAspect, _gameDrawRect);
+
+ if (getOverlayHeight()) {
+ const frac_t overlayAspect = intToFrac(getOverlayWidth()) / getOverlayHeight();
+ populateDisplayAreaDrawRect(overlayAspect, outputAspect, _overlayDrawRect);
+ }
+
+ if (_overlayVisible) {
+ _activeArea.drawRect = _overlayDrawRect;
+ _activeArea.width = getOverlayWidth();
+ _activeArea.height = getOverlayHeight();
+ } else {
+ _activeArea.drawRect = _gameDrawRect;
+ _activeArea.width = getWidth();
+ _activeArea.height = getHeight();
+ }
+ }
+ /**
+ * Sets the position of the hardware mouse cursor in the host system,
+ * relative to the window.
+ *
+ * @param x X coordinate in window coordinates.
+ * @param y Y coordinate in window coordinates.
+ */
+ virtual void setSystemMousePosition(const int x, const int y) = 0;
+
+ /**
+ * Move ("warp") the mouse cursor to the specified position.
+ *
+ * @param x The new X position of the mouse in virtual screen coordinates.
+ * @param y The new Y position of the mouse in virtual screen coordinates.
+ */
+ void warpMouse(const int x, const int y) {
+ // Check active coordinate instead of window coordinate to avoid warping
+ // the mouse if it is still within the same virtual pixel
+ const Common::Point virtualCursor = convertWindowToVirtual(_cursorX, _cursorY);
+ if (virtualCursor.x != x || virtualCursor.y != y) {
+ // Warping the mouse in SDL generates a mouse movement event, so
+ // `setMousePosition` would be called eventually through the
+ // `notifyMousePosition` callback if we *only* set the system mouse
+ // position here. However, this can cause problems with some games.
+ // For example, the cannon script in CoMI calls to warp the mouse
+ // twice each time the cannon is reloaded, and unless we update the
+ // mouse position immediately, the second call is ignored, which
+ // causes the cannon to change its aim.
+ const Common::Point windowCursor = convertVirtualToWindow(x, y);
+ setMousePosition(windowCursor.x, windowCursor.y);
+ setSystemMousePosition(windowCursor.x, windowCursor.y);
+ }
+ }
+
+ /**
+ * Sets the position of the rendered mouse cursor in the window.
+ *
+ * @param x X coordinate in window coordinates.
+ * @param y Y coordinate in window coordinates.
+ */
+ void setMousePosition(int x, int y) {
+ if (_cursorX != x || _cursorY != y) {
+ _cursorNeedsRedraw = true;
+ }
+
+ _cursorX = x;
+ _cursorY = y;
+ }
+
+ /**
+ * The width of the window, excluding window decoration.
+ */
+ int _windowWidth;
+
+ /**
+ * The height of the window, excluding window decoration.
+ */
+ int _windowHeight;
+
+ /**
+ * Whether the overlay (i.e. launcher, including the out-of-game launcher)
+ * is visible or not.
+ */
+ bool _overlayVisible;
+
+ /**
+ * The scaled draw rectangle for the game surface within the window.
+ */
+ Common::Rect _gameDrawRect;
+
+ /**
+ * The scaled draw rectangle for the overlay (launcher) surface within the
+ * window.
+ */
+ Common::Rect _overlayDrawRect;
+
+ /**
+ * Data about the display area of a virtual screen.
+ */
+ struct DisplayArea {
+ /**
+ * The scaled area where the virtual screen is drawn within the window.
+ */
+ Common::Rect drawRect;
+
+ /**
+ * The width of the virtual screen's unscaled coordinate space.
+ */
+ int width;
+
+ /**
+ * The height of the virtual screen's unscaled coordinate space.
+ */
+ int height;
+ };
+
+ /**
+ * Display area information about the currently active virtual screen. This
+ * will be the overlay screen when the overlay is active, and the game
+ * screen otherwise.
+ */
+ DisplayArea _activeArea;
+
+ /**
+ * Whether the screen must be redrawn on the next frame.
+ */
+ bool _forceRedraw;
+
+ /**
+ * Whether the mouse cursor needs to be redrawn on the next frame.
+ */
+ bool _cursorNeedsRedraw;
+
+ /**
+ * The position of the mouse cursor, in window coordinates.
+ */
+ 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);
+ }
+
+ drawRect.left = (_windowWidth - width) / 2;
+ drawRect.top = (_windowHeight - height) / 2;
+ drawRect.setWidth(width);
+ drawRect.setHeight(height);
+ }
+};
+
+#endif
diff --git a/backends/platform/sdl/sdl-window.cpp b/backends/platform/sdl/sdl-window.cpp
index 16b978dca4..a550fbbd40 100644
--- a/backends/platform/sdl/sdl-window.cpp
+++ b/backends/platform/sdl/sdl-window.cpp
@@ -135,8 +135,10 @@ void SdlWindow::toggleMouseGrab() {
#else
if (SDL_WM_GrabInput(SDL_GRAB_QUERY) == SDL_GRAB_OFF) {
SDL_WM_GrabInput(SDL_GRAB_ON);
+ _inputGrabState = true;
} else {
SDL_WM_GrabInput(SDL_GRAB_OFF);
+ _inputGrabState = false;
}
#endif
}
@@ -154,13 +156,15 @@ bool SdlWindow::hasMouseFocus() const {
}
void SdlWindow::warpMouseInWindow(int x, int y) {
+ if (hasMouseFocus()) {
#if SDL_VERSION_ATLEAST(2, 0, 0)
- if (_window && hasMouseFocus()) {
- SDL_WarpMouseInWindow(_window, x, y);
- }
+ if (_window) {
+ SDL_WarpMouseInWindow(_window, x, y);
+ }
#else
- SDL_WarpMouse(x, y);
+ SDL_WarpMouse(x, y);
#endif
+ }
}
void SdlWindow::iconifyWindow() {
diff --git a/backends/platform/sdl/sdl-window.h b/backends/platform/sdl/sdl-window.h
index fb7607be55..4f6d924411 100644
--- a/backends/platform/sdl/sdl-window.h
+++ b/backends/platform/sdl/sdl-window.h
@@ -56,7 +56,8 @@ public:
bool hasMouseFocus() const;
/**
- * Warp the mouse to the specified position in window coordinates.
+ * Warp the mouse to the specified position in window coordinates. The mouse
+ * will only be warped if the window is focused in the window manager.
*/
void warpMouseInWindow(int x, int y);
@@ -73,6 +74,11 @@ public:
*/
bool getSDLWMInformation(SDL_SysWMinfo *info) const;
+ bool mouseIsGrabbed() const { return _inputGrabState; }
+
+private:
+ bool _inputGrabState;
+
#if SDL_VERSION_ATLEAST(2, 0, 0)
public:
/**
@@ -108,7 +114,6 @@ private:
*/
int _lastX, _lastY;
- bool _inputGrabState;
Common::String _windowCaption;
#endif
};
diff --git a/graphics/palette.h b/graphics/palette.h
index 2884bef7f4..0b9b861aa9 100644
--- a/graphics/palette.h
+++ b/graphics/palette.h
@@ -96,7 +96,7 @@ public:
*
* @see getScreenFormat
*/
- virtual void grabPalette(byte *colors, uint start, uint num) = 0;
+ virtual void grabPalette(byte *colors, uint start, uint num) const = 0;
};
#endif