aboutsummaryrefslogtreecommitdiff
path: root/backends/graphics/surfacesdl
diff options
context:
space:
mode:
Diffstat (limited to 'backends/graphics/surfacesdl')
-rw-r--r--backends/graphics/surfacesdl/surfacesdl-graphics.cpp938
-rw-r--r--backends/graphics/surfacesdl/surfacesdl-graphics.h179
2 files changed, 504 insertions, 613 deletions
diff --git a/backends/graphics/surfacesdl/surfacesdl-graphics.cpp b/backends/graphics/surfacesdl/surfacesdl-graphics.cpp
index 983b71ab28..90f9f7e1a1 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,24 +132,19 @@ 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),
#endif
_screen(0), _tmpscreen(0),
-#ifdef USE_RGB_COLOR
_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),
- _mouseOrigSurface(0), _cursorDontScale(false), _cursorPaletteDisabled(true),
+ _mouseData(nullptr), _mouseSurface(nullptr),
+ _mouseOrigSurface(nullptr), _cursorDontScale(false), _cursorPaletteDisabled(true),
_currentShakePos(0), _newShakePos(0),
_paletteDirtyStart(0), _paletteDirtyEnd(0),
_screenIsLocked(false),
@@ -214,21 +208,19 @@ SurfaceSdlGraphicsManager::SurfaceSdlGraphicsManager(SdlEventSource *sdlEventSou
SurfaceSdlGraphicsManager::~SurfaceSdlGraphicsManager() {
unloadGFXMode();
-#if SDL_VERSION_ATLEAST(2, 0, 0)
- if (_window)
- _window->destroyWindow();
-#endif
- if (_mouseSurface)
- SDL_FreeSurface(_mouseSurface);
- _mouseSurface = 0;
- if (_mouseOrigSurface)
+ if (_mouseOrigSurface) {
SDL_FreeSurface(_mouseOrigSurface);
- _mouseOrigSurface = 0;
+ if (_mouseOrigSurface == _mouseSurface) {
+ _mouseSurface = nullptr;
+ }
+ }
+ if (_mouseSurface) {
+ SDL_FreeSurface(_mouseSurface);
+ }
g_system->deleteMutex(_graphicsMutex);
-
free(_currentPalette);
free(_cursorPalette);
- free(_mouseData);
+ delete[] _mouseData;
}
void SurfaceSdlGraphicsManager::activateManager() {
@@ -247,7 +239,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 +276,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.
@@ -332,7 +324,6 @@ void SurfaceSdlGraphicsManager::beginGFXTransaction() {
_transactionDetails.needHotswap = false;
_transactionDetails.needUpdatescreen = false;
- _transactionDetails.normal1xScaler = false;
#if SDL_VERSION_ATLEAST(2, 0, 0)
_transactionDetails.needTextureUpdate = false;
#endif
@@ -556,16 +547,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);
@@ -580,7 +571,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]);
@@ -588,7 +579,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]);
@@ -599,65 +590,55 @@ void SurfaceSdlGraphicsManager::detectSupportedFormats() {
}
#endif
-bool SurfaceSdlGraphicsManager::setGraphicsMode(int mode) {
- Common::StackLock lock(_graphicsMutex);
-
- assert(_transactionMode == kTransactionActive);
-
- if (_oldVideoMode.setup && _oldVideoMode.mode == mode)
- return true;
-
- int newScaleFactor = 1;
-
+int SurfaceSdlGraphicsManager::getGraphicsModeScale(int mode) const {
+ int scale;
switch (mode) {
case GFX_NORMAL:
- newScaleFactor = 1;
+ scale = 1;
break;
#ifdef USE_SCALERS
case GFX_DOUBLESIZE:
- newScaleFactor = 2;
- break;
- case GFX_TRIPLESIZE:
- newScaleFactor = 3;
- break;
-
case GFX_2XSAI:
- newScaleFactor = 2;
- break;
case GFX_SUPER2XSAI:
- newScaleFactor = 2;
- break;
case GFX_SUPEREAGLE:
- newScaleFactor = 2;
- break;
case GFX_ADVMAME2X:
- newScaleFactor = 2;
- break;
- case GFX_ADVMAME3X:
- newScaleFactor = 3;
- break;
+ case GFX_TV2X:
+ case GFX_DOTMATRIX:
#ifdef USE_HQ_SCALERS
case GFX_HQ2X:
- newScaleFactor = 2;
+#endif
+ scale = 2;
break;
+ case GFX_TRIPLESIZE:
+ case GFX_ADVMAME3X:
+#ifdef USE_HQ_SCALERS
case GFX_HQ3X:
- newScaleFactor = 3;
- break;
#endif
- case GFX_TV2X:
- newScaleFactor = 2;
- break;
- case GFX_DOTMATRIX:
- newScaleFactor = 2;
+ scale = 3;
break;
-#endif // USE_SCALERS
-
+#endif
default:
+ scale = -1;
+ }
+
+ return scale;
+}
+
+bool SurfaceSdlGraphicsManager::setGraphicsMode(int mode) {
+ Common::StackLock lock(_graphicsMutex);
+
+ assert(_transactionMode == kTransactionActive);
+
+ if (_oldVideoMode.setup && _oldVideoMode.mode == mode)
+ return true;
+
+ int newScaleFactor = getGraphicsModeScale(mode);
+
+ if (newScaleFactor == -1) {
warning("unknown gfx mode %d", mode);
return false;
}
- _transactionDetails.normal1xScaler = (mode == GFX_NORMAL);
if (_oldVideoMode.setup && _oldVideoMode.scaleFactor != newScaleFactor)
_transactionDetails.needHotswap = true;
@@ -733,11 +714,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.
@@ -784,9 +765,23 @@ void SurfaceSdlGraphicsManager::initSize(uint w, uint h, const Graphics::PixelFo
}
#endif
- // Avoid redundant res changes
+#if !SDL_VERSION_ATLEAST(2, 0, 0)
+ // Avoid redundant res changes, only in SDL1. In SDL2, redundancies may not
+ // actually be redundant if ScummVM is switching between game engines and
+ // the screen dimensions are being reinitialized, since window resizing is
+ // supposed to reset when this happens
if ((int)w == _videoMode.screenWidth && (int)h == _videoMode.screenHeight)
return;
+#endif
+
+ if ((int)w != _videoMode.screenWidth || (int)h != _videoMode.screenHeight) {
+ const bool useDefault = defaultGraphicsModeConfig();
+ if (useDefault && w > 320) {
+ resetGraphicsScale();
+ } else {
+ setGraphicsMode(getGraphicsModeIdByName(ConfMan.get("gfx_mode")));
+ }
+ }
_videoMode.screenWidth = w;
_videoMode.screenHeight = h;
@@ -794,13 +789,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);
@@ -861,20 +849,23 @@ 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)
+#if !defined(__MAEMO__) && !defined(DINGUX) && !defined(GPH_DEVICE) && !defined(LINUXMOTO)
_videoMode.overlayWidth = _videoMode.screenWidth * _videoMode.scaleFactor;
_videoMode.overlayHeight = _videoMode.screenHeight * _videoMode.scaleFactor;
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;
@@ -884,22 +875,20 @@ bool SurfaceSdlGraphicsManager::loadGFXMode() {
//
// Create the surface that contains the 8 bit game data
//
-#ifdef USE_RGB_COLOR
+
+ const Graphics::PixelFormat &format = _screenFormat;
+ const Uint32 rMask = ((0xFF >> format.rLoss) << format.rShift);
+ const Uint32 gMask = ((0xFF >> format.gLoss) << format.gShift);
+ const Uint32 bMask = ((0xFF >> format.bLoss) << format.bShift);
+ const Uint32 aMask = ((0xFF >> format.aLoss) << format.aShift);
_screen = SDL_CreateRGBSurface(SDL_SWSURFACE, _videoMode.screenWidth, _videoMode.screenHeight,
- _screenFormat.bytesPerPixel << 3,
- ((1 << _screenFormat.rBits()) - 1) << _screenFormat.rShift ,
- ((1 << _screenFormat.gBits()) - 1) << _screenFormat.gShift ,
- ((1 << _screenFormat.bBits()) - 1) << _screenFormat.bShift ,
- ((1 << _screenFormat.aBits()) - 1) << _screenFormat.aShift );
+ _screenFormat.bytesPerPixel * 8, rMask, gMask, bMask, aMask);
if (_screen == NULL)
error("allocating _screen failed");
+#ifdef USE_RGB_COLOR
// Avoid having SDL_SRCALPHA set even if we supplied an alpha-channel in the format.
SDL_SetAlpha(_screen, 0, 255);
-#else
- _screen = SDL_CreateRGBSurface(SDL_SWSURFACE, _videoMode.screenWidth, _videoMode.screenHeight, 8, 0, 0, 0, 0);
- if (_screen == NULL)
- error("allocating _screen failed");
#endif
// SDL 1.2 palettes default to all black,
@@ -921,7 +910,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
{
@@ -934,7 +923,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
);
}
@@ -943,9 +932,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());
@@ -955,6 +944,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
//
@@ -962,20 +955,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");
@@ -994,25 +987,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);
@@ -1030,9 +1014,9 @@ void SurfaceSdlGraphicsManager::unloadGFXMode() {
deinitializeRenderer();
#endif
- if (_hwscreen) {
- SDL_FreeSurface(_hwscreen);
- _hwscreen = NULL;
+ if (_hwScreen) {
+ SDL_FreeSurface(_hwScreen);
+ _hwScreen = NULL;
}
if (_tmpscreen) {
@@ -1084,9 +1068,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);
@@ -1136,14 +1120,14 @@ void SurfaceSdlGraphicsManager::updateScreen() {
}
void SurfaceSdlGraphicsManager::updateShader() {
-// shader init code goes here
-// currently only used on Vita port
-// the user-selected shaderID should be obtained via ConfMan.getInt("shader")
-// and the corresponding shader should then be activated here
-// this way the user can combine any software scaling (scalers)
-// with any hardware shading (shaders). The shaders could provide
-// scanline masks, overlays, but could also serve for
-// hardware-based up-scaling (sharp-bilinear-simple, etc.)
+ // shader init code goes here
+ // currently only used on Vita port
+ // the user-selected shaderID should be obtained via ConfMan.getInt("shader")
+ // and the corresponding shader should then be activated here
+ // this way the user can combine any software scaling (scalers)
+ // with any hardware shading (shaders). The shaders could provide
+ // scanline masks, overlays, but could also serve for
+ // hardware-based up-scaling (sharp-bilinear-simple, etc.)
}
void SurfaceSdlGraphicsManager::internUpdateScreen() {
@@ -1152,25 +1136,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
@@ -1182,7 +1160,7 @@ void SurfaceSdlGraphicsManager::internUpdateScreen() {
_paletteDirtyEnd = 0;
- _forceFull = true;
+ _forceRedraw = true;
}
if (!_overlayVisible) {
@@ -1203,8 +1181,10 @@ 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)
+ // we have to redraw the mouse, or if the cursor is alpha-blended since
+ // alpha-blended cursors will happily blend into themselves if the surface
+ // under the cursor is not reset first
+ if (_cursorNeedsRedraw || _cursorFormat.bytesPerPixel == 4)
undrawMouse();
#ifdef USE_OSD
@@ -1212,7 +1192,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;
@@ -1221,7 +1201,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;
@@ -1237,10 +1217,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;
@@ -1265,7 +1245,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;
@@ -1275,17 +1255,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();
@@ -1315,18 +1295,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;
@@ -1337,14 +1317,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;
@@ -1355,12 +1335,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);
}
}
}
@@ -1368,17 +1348,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
@@ -1388,12 +1368,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,
@@ -1408,9 +1388,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;
}
@@ -1438,7 +1418,7 @@ bool SurfaceSdlGraphicsManager::saveScreenshot(const char *filename) {
return success;
#else
- return SDL_SaveBMP(_hwscreen, filename) == 0;
+ return SDL_SaveBMP(_hwScreen, filename) == 0;
#endif
}
@@ -1502,7 +1482,6 @@ void SurfaceSdlGraphicsManager::copyRectToScreen(const void *buf, int pitch, int
if (SDL_LockSurface(_screen) == -1)
error("SDL_LockSurface failed: %s", SDL_GetError());
-#ifdef USE_RGB_COLOR
byte *dst = (byte *)_screen->pixels + y * _screen->pitch + x * _screenFormat.bytesPerPixel;
if (_videoMode.screenWidth == w && pitch == _screen->pitch) {
memcpy(dst, buf, h*pitch);
@@ -1514,19 +1493,6 @@ void SurfaceSdlGraphicsManager::copyRectToScreen(const void *buf, int pitch, int
dst += _screen->pitch;
} while (--h);
}
-#else
- byte *dst = (byte *)_screen->pixels + y * _screen->pitch + x;
- if (_screen->pitch == pitch && pitch == w) {
- memcpy(dst, buf, h*w);
- } else {
- const byte *src = (const byte *)buf;
- do {
- memcpy(dst, src, w);
- src += pitch;
- dst += _screen->pitch;
- } while (--h);
- }
-#endif
// Unlock the screen surface
SDL_UnlockSurface(_screen);
@@ -1546,13 +1512,7 @@ Graphics::Surface *SurfaceSdlGraphicsManager::lockScreen() {
if (SDL_LockSurface(_screen) == -1)
error("SDL_LockSurface failed: %s", SDL_GetError());
- _framebuffer.init(_screen->w, _screen->h, _screen->pitch, _screen->pixels,
-#ifdef USE_RGB_COLOR
- _screenFormat
-#else
- Graphics::PixelFormat::createFormatCLUT8()
-#endif
- );
+ _framebuffer.init(_screen->w, _screen->h, _screen->pitch, _screen->pixels, _screenFormat);
return &_framebuffer;
}
@@ -1568,7 +1528,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);
@@ -1582,11 +1542,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;
}
@@ -1605,8 +1565,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
@@ -1617,7 +1577,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) {
@@ -1635,7 +1595,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;
}
@@ -1649,20 +1609,17 @@ 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;
}
void SurfaceSdlGraphicsManager::setPalette(const byte *colors, uint start, uint num) {
assert(colors);
-
-#ifdef USE_RGB_COLOR
assert(_screenFormat.bytesPerPixel == 1);
-#endif
// Setting the palette before _screen is created is allowed - for now -
// since we don't actually set the palette until the screen is updated.
@@ -1694,12 +1651,9 @@ 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
assert(_screenFormat.bytesPerPixel == 1);
-#endif
const SDL_Color *base = _currentPalette + start;
@@ -1774,56 +1728,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)
@@ -1851,10 +1756,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)
@@ -1928,143 +1833,201 @@ void SurfaceSdlGraphicsManager::copyRectToOverlay(const void *buf, int pitch, in
#pragma mark --- Mouse ---
#pragma mark -
-bool SurfaceSdlGraphicsManager::showMouse(bool visible) {
- if (_mouseVisible == visible)
- return visible;
+void SurfaceSdlGraphicsManager::setMouseCursor(const void *buf, uint w, uint h, int hotspotX, int hotspotY, uint32 keyColor, bool dontScale, const Graphics::PixelFormat *format) {
+ if (format) {
+#ifndef USE_RGB_COLOR
+ assert(format->bytesPerPixel == 1);
+#endif
+ _cursorFormat = *format;
+ } else {
+ _cursorFormat = Graphics::PixelFormat::createFormatCLUT8();
+ }
- bool last = _mouseVisible;
- _mouseVisible = visible;
- _mouseNeedsRedraw = true;
+ if (_cursorFormat.bytesPerPixel == 4) {
+ assert(keyColor == 0);
+ } else {
+ assert(keyColor < 1U << (_cursorFormat.bytesPerPixel * 8));
+ }
- return last;
-}
+ _mouseCurState.hotX = hotspotX;
+ _mouseCurState.hotY = hotspotY;
-void SurfaceSdlGraphicsManager::setMousePos(int x, int y) {
- if (x != _mouseCurState.x || y != _mouseCurState.y) {
- _mouseNeedsRedraw = true;
- _mouseCurState.x = x;
- _mouseCurState.y = y;
- }
-}
+ _mouseKeyColor = keyColor;
-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;
- }
+ _cursorDontScale = dontScale;
- int x1 = x, y1 = y;
- if (_videoMode.aspectRatioCorrection && !_overlayVisible)
- y1 = real2Aspect(y1);
+ if (_mouseCurState.w != (int)w || _mouseCurState.h != (int)h) {
+ _mouseCurState.w = w;
+ _mouseCurState.h = h;
- if (_mouseCurState.x != x || _mouseCurState.y != y) {
- if (!_overlayVisible) {
- x1 *= _videoMode.scaleFactor;
- y1 *= _videoMode.scaleFactor;
+ if (!w || !h) {
+ return;
}
-#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
+ if (_mouseOrigSurface) {
+ SDL_FreeSurface(_mouseOrigSurface);
+
+ if (_mouseSurface == _mouseOrigSurface) {
+ _mouseSurface = nullptr;
+ }
+ }
- _window->warpMouseInWindow(x1, y1);
+ if (_cursorFormat.bytesPerPixel == 4) {
+ if (_mouseSurface != _mouseOrigSurface) {
+ SDL_FreeSurface(_mouseSurface);
+ }
+
+ const Uint32 rMask = ((0xFF >> format->rLoss) << format->rShift);
+ const Uint32 gMask = ((0xFF >> format->gLoss) << format->gShift);
+ const Uint32 bMask = ((0xFF >> format->bLoss) << format->bShift);
+ const Uint32 aMask = ((0xFF >> format->aLoss) << format->aShift);
+ _mouseSurface = _mouseOrigSurface = SDL_CreateRGBSurfaceFrom(const_cast<void *>(buf), w, h, format->bytesPerPixel * 8, w * format->bytesPerPixel, rMask, gMask, bMask, aMask);
+ } else {
+ // Allocate bigger surface because AdvMame2x adds black pixel at [0,0]
+ _mouseOrigSurface = SDL_CreateRGBSurface(SDL_SWSURFACE | SDL_RLEACCEL | SDL_SRCCOLORKEY | SDL_SRCALPHA,
+ _mouseCurState.w + 2,
+ _mouseCurState.h + 2,
+ 16,
+ _hwScreen->format->Rmask,
+ _hwScreen->format->Gmask,
+ _hwScreen->format->Bmask,
+ _hwScreen->format->Amask);
+ }
+
+ if (_mouseOrigSurface == nullptr) {
+ error("Allocating _mouseOrigSurface failed");
+ }
- // 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.
+ if (_cursorFormat.bytesPerPixel < 4) {
+ SDL_SetColorKey(_mouseOrigSurface, SDL_RLEACCEL | SDL_SRCCOLORKEY | SDL_SRCALPHA, kMouseColorKey);
+ }
+ }
- setMousePos(x, y);
+ delete[] _mouseData;
+ if (_cursorFormat.bytesPerPixel == 4) {
+ _mouseData = nullptr;
+ } else {
+ _mouseData = new byte[w * h * _cursorFormat.bytesPerPixel];
+ assert(_mouseData);
+ memcpy(_mouseData, buf, w * h * _cursorFormat.bytesPerPixel);
}
+
+ blitCursor();
}
-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)
- _cursorFormat = Graphics::PixelFormat::createFormatCLUT8();
- else if (format->bytesPerPixel <= _screenFormat.bytesPerPixel)
- _cursorFormat = *format;
+void SurfaceSdlGraphicsManager::blitCursor() {
+ const int w = _mouseCurState.w;
+ const int h = _mouseCurState.h;
- if (_cursorFormat.bytesPerPixel < 4)
- assert(keycolor < (uint)(1 << (_cursorFormat.bytesPerPixel << 3)));
-#else
- assert(keycolor <= 0xFF);
-#endif
+ if (!w || !h || !_mouseOrigSurface) {
+ return;
+ }
- if (w == 0 || h == 0)
+ if (_cursorFormat.bytesPerPixel != 4 && !_mouseData) {
return;
+ }
- _mouseCurState.hotX = hotspot_x;
- _mouseCurState.hotY = hotspot_y;
+ _cursorNeedsRedraw = true;
- _mouseKeyColor = keycolor;
+ int cursorScale;
+ if (_cursorDontScale) {
+ // Don't scale the cursor at all if the user requests this behavior.
+ cursorScale = 1;
+ } else {
+ // Scale the cursor with the game screen scale factor.
+ cursorScale = _videoMode.scaleFactor;
+ }
- _cursorDontScale = dontScale;
+ // Adapt the real hotspot according to the scale factor.
+ int rW = w * cursorScale;
+ int rH = h * cursorScale;
+ _mouseCurState.rHotX = _mouseCurState.hotX * cursorScale;
+ _mouseCurState.rHotY = _mouseCurState.hotY * cursorScale;
- if (_mouseCurState.w != (int)w || _mouseCurState.h != (int)h) {
- _mouseCurState.w = w;
- _mouseCurState.h = h;
+ // The virtual dimensions will be the same as the original.
- if (_mouseOrigSurface)
- SDL_FreeSurface(_mouseOrigSurface);
+ _mouseCurState.vW = w;
+ _mouseCurState.vH = h;
+ _mouseCurState.vHotX = _mouseCurState.hotX;
+ _mouseCurState.vHotY = _mouseCurState.hotY;
- // Allocate bigger surface because AdvMame2x adds black pixel at [0,0]
- _mouseOrigSurface = SDL_CreateRGBSurface(SDL_SWSURFACE | SDL_RLEACCEL | SDL_SRCCOLORKEY | SDL_SRCALPHA,
- _mouseCurState.w + 2,
- _mouseCurState.h + 2,
- 16,
- _hwscreen->format->Rmask,
- _hwscreen->format->Gmask,
- _hwscreen->format->Bmask,
- _hwscreen->format->Amask);
+#ifdef USE_SCALERS
+ // store original to pass to aspect-correction function later
+ const int rH1 = rH;
+#endif
- if (_mouseOrigSurface == NULL)
- error("allocating _mouseOrigSurface failed");
- SDL_SetColorKey(_mouseOrigSurface, SDL_RLEACCEL | SDL_SRCCOLORKEY | SDL_SRCALPHA, kMouseColorKey);
+ if (!_cursorDontScale && _videoMode.aspectRatioCorrection) {
+ rH = real2Aspect(rH - 1) + 1;
+ _mouseCurState.rHotY = real2Aspect(_mouseCurState.rHotY);
}
- free(_mouseData);
-#ifdef USE_RGB_COLOR
- _mouseData = (byte *)malloc(w * h * _cursorFormat.bytesPerPixel);
- memcpy(_mouseData, buf, w * h * _cursorFormat.bytesPerPixel);
-#else
- _mouseData = (byte *)malloc(w * h);
- memcpy(_mouseData, buf, w * h);
-#endif
-
- blitCursor();
-}
+ bool sizeChanged = false;
+ if (_mouseCurState.rW != rW || _mouseCurState.rH != rH) {
+ _mouseCurState.rW = rW;
+ _mouseCurState.rH = rH;
+ sizeChanged = true;
+ }
-void SurfaceSdlGraphicsManager::blitCursor() {
- byte *dstPtr;
- const byte *srcPtr = _mouseData;
-#ifdef USE_RGB_COLOR
- uint32 color;
-#else
- byte color;
-#endif
- int w, h, i, j;
+ if (_cursorFormat.bytesPerPixel == 4) {
+ if (_mouseSurface != _mouseOrigSurface) {
+ SDL_FreeSurface(_mouseSurface);
+ }
- if (!_mouseOrigSurface || !_mouseData)
- return;
+ if (cursorScale == 1) {
+ _mouseSurface = _mouseOrigSurface;
+ return;
+ }
- _mouseNeedsRedraw = true;
+ SDL_PixelFormat *format = _mouseOrigSurface->format;
+ _mouseSurface = SDL_CreateRGBSurface(SDL_SWSURFACE | SDL_SRCALPHA,
+ rW, rH,
+ format->BitsPerPixel,
+ format->Rmask,
+ format->Gmask,
+ format->Bmask,
+ format->Amask);
+
+ // At least SDL 2.0.4 on Windows apparently has a broken SDL_BlitScaled
+ // implementation, and SDL 1 has no such API at all, and our other
+ // scalers operate exclusively at 16bpp, so here is a scrappy 32bpp
+ // point scaler
+ SDL_LockSurface(_mouseOrigSurface);
+ SDL_LockSurface(_mouseSurface);
+
+ const byte *src = (const byte *)_mouseOrigSurface->pixels;
+ byte *dst = (byte *)_mouseSurface->pixels;
+ for (int y = 0; y < _mouseOrigSurface->h; ++y) {
+ uint32 *rowDst = (uint32 *)dst;
+ const uint32 *rowSrc = (const uint32 *)src;
+ for (int x = 0; x < _mouseOrigSurface->w; ++x) {
+ for (int scaleX = 0; scaleX < cursorScale; ++scaleX) {
+ *rowDst++ = *rowSrc;
+ }
+ ++rowSrc;
+ }
+ for (int scaleY = 0; scaleY < cursorScale - 1; ++scaleY) {
+ memcpy(dst + _mouseSurface->pitch, dst, _mouseSurface->pitch);
+ dst += _mouseSurface->pitch;
+ }
+ dst += _mouseSurface->pitch;
+ src += _mouseOrigSurface->pitch;
+ }
- w = _mouseCurState.w;
- h = _mouseCurState.h;
+ SDL_UnlockSurface(_mouseSurface);
+ SDL_UnlockSurface(_mouseOrigSurface);
+ return;
+ }
SDL_LockSurface(_mouseOrigSurface);
+ byte *dstPtr;
+ const byte *srcPtr = _mouseData;
+ uint32 color;
+
// Make whole surface transparent
- for (i = 0; i < h + 2; i++) {
+ for (int i = 0; i < h + 2; i++) {
dstPtr = (byte *)_mouseOrigSurface->pixels + _mouseOrigSurface->pitch * i;
- for (j = 0; j < w + 2; j++) {
+ for (int j = 0; j < w + 2; j++) {
*(uint16 *)dstPtr = kMouseColorKey;
dstPtr += 2;
}
@@ -2080,75 +2043,31 @@ void SurfaceSdlGraphicsManager::blitCursor() {
else
palette = _cursorPalette;
- for (i = 0; i < h; i++) {
- for (j = 0; j < w; j++) {
-#ifdef USE_RGB_COLOR
- if (_cursorFormat.bytesPerPixel > 1) {
- if (_cursorFormat.bytesPerPixel == 2)
- color = *(const uint16 *)srcPtr;
- else
- color = *(const uint32 *)srcPtr;
- if (color != _mouseKeyColor) { // transparent, don't draw
+ for (int i = 0; i < h; i++) {
+ for (int j = 0; j < w; j++) {
+ if (_cursorFormat.bytesPerPixel == 2) {
+ color = *(const uint16 *)srcPtr;
+ if (color != _mouseKeyColor) {
uint8 r, g, b;
_cursorFormat.colorToRGB(color, r, g, b);
- *(uint16 *)dstPtr = SDL_MapRGB(_mouseOrigSurface->format,
- r, g, b);
+ *(uint16 *)dstPtr = SDL_MapRGB(_mouseOrigSurface->format, r, g, b);
}
dstPtr += 2;
srcPtr += _cursorFormat.bytesPerPixel;
} else {
-#endif
color = *srcPtr;
- if (color != _mouseKeyColor) { // transparent, don't draw
+ if (color != _mouseKeyColor) {
*(uint16 *)dstPtr = SDL_MapRGB(_mouseOrigSurface->format,
palette[color].r, palette[color].g, palette[color].b);
}
dstPtr += 2;
srcPtr++;
-#ifdef USE_RGB_COLOR
}
-#endif
}
dstPtr += _mouseOrigSurface->pitch - w * 2;
}
- int rW, rH;
- int cursorScale;
-
- if (_cursorDontScale) {
- // Don't scale the cursor at all if the user requests this behavior.
- cursorScale = 1;
- } else {
- // Scale the cursor with the game screen scale factor.
- cursorScale = _videoMode.scaleFactor;
- }
-
- // Adapt the real hotspot according to the scale factor.
- rW = w * cursorScale;
- rH = h * cursorScale;
- _mouseCurState.rHotX = _mouseCurState.hotX * cursorScale;
- _mouseCurState.rHotY = _mouseCurState.hotY * cursorScale;
-
- // The virtual dimensions will be the same as the original.
-
- _mouseCurState.vW = w;
- _mouseCurState.vH = h;
- _mouseCurState.vHotX = _mouseCurState.hotX;
- _mouseCurState.vHotY = _mouseCurState.hotY;
-
-#ifdef USE_SCALERS
- int rH1 = rH; // store original to pass to aspect-correction function later
-#endif
-
- if (!_cursorDontScale && _videoMode.aspectRatioCorrection) {
- rH = real2Aspect(rH - 1) + 1;
- _mouseCurState.rHotY = real2Aspect(_mouseCurState.rHotY);
- }
-
- if (_mouseCurState.rW != rW || _mouseCurState.rH != rH) {
- _mouseCurState.rW = rW;
- _mouseCurState.rH = rH;
-
+ if (sizeChanged) {
if (_mouseSurface)
SDL_FreeSurface(_mouseSurface);
@@ -2156,13 +2075,13 @@ 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");
+ if (_mouseSurface == nullptr)
+ error("Allocating _mouseSurface failed");
SDL_SetColorKey(_mouseSurface, SDL_RLEACCEL | SDL_SRCCOLORKEY | SDL_SRCALPHA, kMouseColorKey);
}
@@ -2233,7 +2152,7 @@ void SurfaceSdlGraphicsManager::undrawMouse() {
}
void SurfaceSdlGraphicsManager::drawMouse() {
- if (!_mouseVisible || !_mouseSurface) {
+ if (!_cursorVisible || !_mouseSurface || !_mouseCurState.w || !_mouseCurState.h) {
_mouseBackup.x = _mouseBackup.y = _mouseBackup.w = _mouseBackup.h = 0;
return;
}
@@ -2242,8 +2161,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;
@@ -2283,7 +2204,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, nullptr, _hwScreen, &dst) != 0)
error("SDL_BlitSurface failed: %s", SDL_GetError());
// The screen will be updated using real surface coordinates, i.e.
@@ -2332,14 +2253,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
@@ -2372,12 +2293,17 @@ void SurfaceSdlGraphicsManager::displayMessageOnOSD(const char *msg) {
// Init the OSD display parameters, and the fade out
_osdMessageAlpha = SDL_ALPHA_TRANSPARENT + kOSDInitialAlpha * (SDL_ALPHA_OPAQUE - SDL_ALPHA_TRANSPARENT) / 100;
_osdMessageFadeStartTime = SDL_GetTicks() + kOSDFadeOutDelay;
+ // Enable alpha blending
+ SDL_SetAlpha(_osdMessageSurface, SDL_RLEACCEL | SDL_SRCALPHA, _osdMessageAlpha);
+
+ // Ensure a full redraw takes place next time the screen is updated
+ _forceRedraw = true;
}
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;
@@ -2390,7 +2316,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) {
@@ -2429,7 +2355,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;
@@ -2460,8 +2386,8 @@ void SurfaceSdlGraphicsManager::updateOSD() {
const int startAlpha = SDL_ALPHA_TRANSPARENT + kOSDInitialAlpha * (SDL_ALPHA_OPAQUE - SDL_ALPHA_TRANSPARENT) / 100;
_osdMessageAlpha = startAlpha + diff * (SDL_ALPHA_TRANSPARENT - startAlpha) / kOSDFadeOutDuration;
}
- SDL_SetAlpha(_osdMessageSurface, SDL_RLEACCEL | SDL_SRCCOLORKEY | SDL_SRCALPHA, _osdMessageAlpha);
- _forceFull = true;
+ SDL_SetAlpha(_osdMessageSurface, SDL_RLEACCEL | SDL_SRCALPHA, _osdMessageAlpha);
+ _forceRedraw = true;
}
if (_osdMessageAlpha == SDL_ALPHA_TRANSPARENT) {
@@ -2471,26 +2397,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();
@@ -2502,13 +2432,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
@@ -2529,7 +2459,7 @@ bool SurfaceSdlGraphicsManager::handleScalerHotkeys(Common::KeyCode key) {
displayMessageOnOSD(_("Filtering disabled"));
}
#endif
- _forceFull = true;
+ _forceRedraw = true;
internUpdateScreen();
return true;
}
@@ -2539,12 +2469,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
}
}
@@ -2582,10 +2519,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;
@@ -2697,37 +2643,13 @@ 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
+ _forceRedraw = true;
}
-void SurfaceSdlGraphicsManager::transformMouseCoordinates(Common::Point &point) {
+void SurfaceSdlGraphicsManager::notifyResize(const int width, const int height) {
#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;
+ handleResize(width, height);
#endif
-
- if (!_overlayVisible) {
- point.x /= _videoMode.scaleFactor;
- point.y /= _videoMode.scaleFactor;
- if (_videoMode.aspectRatioCorrection)
- point.y = aspect2Real(point.y);
- }
-}
-
-void SurfaceSdlGraphicsManager::notifyMousePos(Common::Point mouse) {
- transformMouseCoordinates(mouse);
- setMousePos(mouse.x, mouse.y);
}
#if SDL_VERSION_ATLEAST(2, 0, 0)
@@ -2739,39 +2661,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;
@@ -2789,15 +2678,12 @@ void SurfaceSdlGraphicsManager::recreateScreenTexture() {
SDL_Surface *SurfaceSdlGraphicsManager::SDL_SetVideoMode(int width, int height, int bpp, Uint32 flags) {
deinitializeRenderer();
- uint32 createWindowFlags = 0;
-#ifdef USE_SDL_RESIZABLE_WINDOW
- createWindowFlags |= SDL_WINDOW_RESIZABLE;
-#endif
+ uint32 createWindowFlags = SDL_WINDOW_RESIZABLE;
if ((flags & SDL_FULLSCREEN) != 0) {
createWindowFlags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
}
- if (!_window->createOrUpdateWindow(width, height, createWindowFlags)) {
+ if (!createOrUpdateWindow(width, height, createWindowFlags)) {
return nullptr;
}
@@ -2807,8 +2693,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 +2716,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 532399ed66..60f5d29f55 100644
--- a/backends/graphics/surfacesdl/surfacesdl-graphics.h
+++ b/backends/graphics/surfacesdl/surfacesdl-graphics.h
@@ -39,17 +39,7 @@
#define USE_SDL_DEBUG_FOCUSRECT
#endif
-// We have (some) support for resizable windows when SDL2 is used. However
-// the overlay still uses the resolution setup with SDL_SetVideoMode. This
-// makes the GUI look subpar when the user resizes the window. In addition
-// we do not adapt the scale factor right now. Thus, we disable this code
-// path for now.
-#if SDL_VERSION_ATLEAST(2, 0, 0) && 0
-#define USE_SDL_RESIZABLE_WINDOW
-#endif
-
#if !defined(_WIN32_WCE) && !defined(__SYMBIAN32__)
-// Uncomment this to enable the 'on screen display' code.
#define USE_OSD 1
#endif
@@ -89,76 +79,70 @@ 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 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
@@ -187,18 +171,20 @@ 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;
#if SDL_VERSION_ATLEAST(2, 0, 0)
/* SDL2 features a different API for 2D graphics. We create a wrapper
* 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);
@@ -207,9 +193,9 @@ protected:
/** Unseen game screen */
SDL_Surface *_screen;
-#ifdef USE_RGB_COLOR
Graphics::PixelFormat _screenFormat;
Graphics::PixelFormat _cursorFormat;
+#ifdef USE_RGB_COLOR
Common::List<Graphics::PixelFormat> _supportedFormats;
/**
@@ -225,7 +211,6 @@ protected:
SDL_Surface *_tmpscreen2;
SDL_Surface *_overlayscreen;
- bool _overlayVisible;
Graphics::PixelFormat _overlayFormat;
enum {
@@ -238,7 +223,6 @@ protected:
bool sizeChanged;
bool needHotswap;
bool needUpdatescreen;
- bool normal1xScaler;
#if SDL_VERSION_ATLEAST(2, 0, 0)
bool needTextureUpdate;
#endif
@@ -288,14 +272,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;
@@ -316,10 +297,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;
@@ -334,14 +311,12 @@ 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;
@@ -394,21 +369,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