aboutsummaryrefslogtreecommitdiff
path: root/backends/graphics/surfacesdl/surfacesdl-graphics.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'backends/graphics/surfacesdl/surfacesdl-graphics.cpp')
-rw-r--r--backends/graphics/surfacesdl/surfacesdl-graphics.cpp116
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)