diff options
Diffstat (limited to 'backends/graphics/surfacesdl/surfacesdl-graphics.cpp')
-rw-r--r-- | backends/graphics/surfacesdl/surfacesdl-graphics.cpp | 116 |
1 files changed, 97 insertions, 19 deletions
diff --git a/backends/graphics/surfacesdl/surfacesdl-graphics.cpp b/backends/graphics/surfacesdl/surfacesdl-graphics.cpp index 9cb14525ee..5b591e77ff 100644 --- a/backends/graphics/surfacesdl/surfacesdl-graphics.cpp +++ b/backends/graphics/surfacesdl/surfacesdl-graphics.cpp @@ -32,6 +32,7 @@ #include "common/textconsole.h" #include "common/translation.h" #include "common/util.h" +#include "common/frac.h" #ifdef USE_RGB_COLOR #include "common/list.h" #endif @@ -125,7 +126,9 @@ SurfaceSdlGraphicsManager::SurfaceSdlGraphicsManager(SdlEventSource *sdlEventSou _hwscreen(0), #if SDL_VERSION_ATLEAST(2, 0, 0) _renderer(nullptr), _screenTexture(nullptr), -#else + _viewport(), _windowWidth(1), _windowHeight(1), +#endif +#if defined(WIN32) && !SDL_VERSION_ATLEAST(2, 0, 0) _originalBitsPerPixel(0), #endif _screen(0), _tmpscreen(0), @@ -799,8 +802,9 @@ bool SurfaceSdlGraphicsManager::loadGFXMode() { } else #endif { - // Save the original bpp to be able to restore the video mode on unload -#if !SDL_VERSION_ATLEAST(2, 0, 0) +#if defined(WIN32) && !SDL_VERSION_ATLEAST(2, 0, 0) + // Save the original bpp to be able to restore the video mode on + // unload. See _originalBitsPerPixel documentation. if (_originalBitsPerPixel == 0) { const SDL_VideoInfo *videoInfo = SDL_GetVideoInfo(); _originalBitsPerPixel = videoInfo->vfmt->BitsPerPixel; @@ -889,9 +893,14 @@ bool SurfaceSdlGraphicsManager::loadGFXMode() { SDL_SetColorKey(_osdSurface, SDL_RLEACCEL | SDL_SRCCOLORKEY | SDL_SRCALPHA, kOSDColorKey); #endif +#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->resetKeyboadEmulation( _videoMode.screenWidth * _videoMode.scaleFactor - 1, effectiveScreenHeight() - 1); +#endif // Distinguish 555 and 565 mode if (_hwscreen->format->Rmask == 0x7C00) @@ -940,9 +949,10 @@ void SurfaceSdlGraphicsManager::unloadGFXMode() { #endif DestroyScalers(); -#if !SDL_VERSION_ATLEAST(2, 0, 0) - // Reset video mode to original - // This will ensure that any new graphic manager will use the initial BPP when listing available modes +#if defined(WIN32) && !SDL_VERSION_ATLEAST(2, 0, 0) + // Reset video mode to original. + // This will ensure that any new graphic manager will use the initial BPP + // when listing available modes. See _originalBitsPerPixel documentation. if (_originalBitsPerPixel != 0) SDL_SetVideoMode(_videoMode.screenWidth, _videoMode.screenHeight, _originalBitsPerPixel, _videoMode.fullscreen ? (SDL_FULLSCREEN | SDL_SWSURFACE) : SDL_SWSURFACE); #endif @@ -1756,22 +1766,30 @@ void SurfaceSdlGraphicsManager::setMousePos(int x, int y) { } void SurfaceSdlGraphicsManager::warpMouse(int x, int y) { - int y1 = y; - // Don't change actual mouse position, when mouse is outside of our window (in case of windowed mode) if (!_window->hasMouseFocus()) { setMousePos(x, y); // but change game cursor position return; } + int x1 = x, y1 = y; if (_videoMode.aspectRatioCorrection && !_overlayVisible) - y1 = real2Aspect(y); + y1 = real2Aspect(y1); if (_mouseCurState.x != x || _mouseCurState.y != y) { - if (!_overlayVisible) - _window->warpMouseInWindow(x * _videoMode.scaleFactor, y1 * _videoMode.scaleFactor); - else - _window->warpMouseInWindow(x, y1); + if (!_overlayVisible) { + x1 *= _videoMode.scaleFactor; + y1 *= _videoMode.scaleFactor; + } + +#if SDL_VERSION_ATLEAST(2, 0, 0) + // Transform our coordinates in "virtual" output coordinate space into + // actual output coordinate space. + x1 = x1 * _windowWidth / _videoMode.hardwareWidth; + y1 = y1 * _windowHeight / _videoMode.hardwareHeight; +#endif + + _window->warpMouseInWindow(x1, y1); // SDL_WarpMouse() generates a mouse movement event, so // setMousePos() would be called eventually. However, the @@ -2029,7 +2047,7 @@ void SurfaceSdlGraphicsManager::undrawMouse() { return; if (_mouseBackup.w != 0 && _mouseBackup.h != 0) - addDirtyRect(x, y - _currentShakePos, _mouseBackup.w, _mouseBackup.h); + addDirtyRect(x, y, _mouseBackup.w, _mouseBackup.h); } void SurfaceSdlGraphicsManager::drawMouse() { @@ -2070,9 +2088,7 @@ void SurfaceSdlGraphicsManager::drawMouse() { // We draw the pre-scaled cursor image, so now we need to adjust for // scaling, shake position and aspect ratio correction manually. - if (!_overlayVisible) { - dst.y += _currentShakePos; - } + dst.y += _currentShakePos; if (_videoMode.aspectRatioCorrection && !_overlayVisible) dst.y = real2Aspect(dst.y); @@ -2352,7 +2368,25 @@ void SurfaceSdlGraphicsManager::notifyVideoExpose() { _forceFull = true; } +#ifdef USE_SDL_RESIZABLE_WINDOW +void SurfaceSdlGraphicsManager::notifyResize(const uint width, const uint height) { +#if SDL_VERSION_ATLEAST(2, 0, 0) + setWindowResolution(width, height); +#endif +} +#endif + void SurfaceSdlGraphicsManager::transformMouseCoordinates(Common::Point &point) { +#if SDL_VERSION_ATLEAST(2, 0, 0) + // In SDL2 the actual output resolution might be different from what we + // requested. Thus, we transform the coordinates from actual output + // coordinate space into the "virtual" output coordinate space. + // Please note that we ignore the possible existence of black bars here, + // this avoids the feeling of stickyness to black bars. + point.x = point.x * _videoMode.hardwareWidth / _windowWidth; + point.y = point.y * _videoMode.hardwareHeight / _windowHeight; +#endif + if (!_overlayVisible) { point.x /= _videoMode.scaleFactor; point.y /= _videoMode.scaleFactor; @@ -2377,10 +2411,51 @@ void SurfaceSdlGraphicsManager::deinitializeRenderer() { _window->destroyWindow(); } +void SurfaceSdlGraphicsManager::setWindowResolution(int width, int height) { + _windowWidth = width; + _windowHeight = height; + + // We expect full screen resolution as inputs coming from the event system. + _eventSource->resetKeyboadEmulation(_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; +} + SDL_Surface *SurfaceSdlGraphicsManager::SDL_SetVideoMode(int width, int height, int bpp, Uint32 flags) { deinitializeRenderer(); - if (!_window->createWindow(width, height, (flags & SDL_FULLSCREEN) ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0)) { + uint32 createWindowFlags = 0; +#ifdef USE_SDL_RESIZABLE_WINDOW + createWindowFlags |= SDL_WINDOW_RESIZABLE; +#endif + if ((flags & SDL_FULLSCREEN) != 0) { + createWindowFlags |= SDL_WINDOW_FULLSCREEN_DESKTOP; + } + + if (!_window->createWindow(width, height, createWindowFlags)) { return nullptr; } @@ -2390,6 +2465,9 @@ SDL_Surface *SurfaceSdlGraphicsManager::SDL_SetVideoMode(int width, int height, return nullptr; } + SDL_GetWindowSize(_window->getSDLWindow(), &_windowWidth, &_windowHeight); + setWindowResolution(_windowWidth, _windowHeight); + _screenTexture = SDL_CreateTexture(_renderer, SDL_PIXELFORMAT_RGB565, SDL_TEXTUREACCESS_STREAMING, width, height); if (!_screenTexture) { deinitializeRenderer(); @@ -2409,7 +2487,7 @@ void SurfaceSdlGraphicsManager::SDL_UpdateRects(SDL_Surface *screen, int numrect SDL_UpdateTexture(_screenTexture, nullptr, screen->pixels, screen->pitch); SDL_RenderClear(_renderer); - SDL_RenderCopy(_renderer, _screenTexture, NULL, NULL); + SDL_RenderCopy(_renderer, _screenTexture, NULL, &_viewport); SDL_RenderPresent(_renderer); } #endif // SDL_VERSION_ATLEAST(2, 0, 0) |