diff options
Diffstat (limited to 'backends/graphics/surfacesdl')
-rw-r--r-- | backends/graphics/surfacesdl/surfacesdl-graphics.cpp | 938 | ||||
-rw-r--r-- | backends/graphics/surfacesdl/surfacesdl-graphics.h | 179 |
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 |