Skip to content

Commit

Permalink
SDL: Do not reset window size when engines update rendering surface
Browse files Browse the repository at this point in the history
This change allows:

* Engines to update their target rendering surface/size and pixel
  format with the backend multiple times during gameplay;
* Users to resize the ScummVM window without having it reset
  size/position every time an engine updates its target surface
  format;
* Conversions/scaling to continue to run efficiently in hardware,
  instead of requiring engines to pick their maximum possible
  output format once and upscale inefficiently in software;
* The window to reset size once when an engine calls to set its
  initial output size, and to reset again once ScummVM returns to
  the launcher.

This is relevant for at least SCI32 and DreamWeb engines, which
perform graphics mode switches during games.

This is a not-awesome hack, but it seems to be the least terrible
way I could find to enable a satisfactory user experience for
resizing without making more extensive changes to the graphics
manager API, and without forcing engines to opt-in to not breaking
the user experience with their calls to change screen modes (which
should not be the responsibility of game engines).

One potential alternative to having the graphics manager track the
global engine pointer would be to instead use a flag that gets set
and cleared by the main ScummVM loop before it calls to run an
engine, and after the engine run call returns.
  • Loading branch information
csnover committed Sep 3, 2017
1 parent 22e24d7 commit f8532bd
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 14 deletions.
12 changes: 2 additions & 10 deletions backends/graphics/openglsdl/openglsdl-graphics.cpp
Expand Up @@ -509,16 +509,8 @@ bool OpenGLSdlGraphicsManager::setupMode(uint width, uint height) {
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, _glContextMajor);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, _glContextMinor);

if (!_window->createOrUpdateWindow(width, height, flags)) {
// We treat fullscreen requests as a "hint" for now. This means in
// case it is not available we simply ignore it.
if (_wantsFullScreen) {
_window->createOrUpdateWindow(width, height, SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE);
}

if (!_window->getSDLWindow()) {
return false;
}
if (!createOrUpdateWindow(width, height, flags)) {
return false;
}

_glContext = SDL_GL_CreateContext(_window->getSDLWindow());
Expand Down
27 changes: 25 additions & 2 deletions backends/graphics/sdl/sdl-graphics.cpp
Expand Up @@ -21,13 +21,17 @@
*/

#include "backends/graphics/sdl/sdl-graphics.h"

#include "backends/platform/sdl/sdl-sys.h"
#include "backends/events/sdl/sdl-events.h"
#include "common/textconsole.h"
#include "engines/engine.h"

SdlGraphicsManager::SdlGraphicsManager(SdlEventSource *source, SdlWindow *window)
: _eventSource(source), _window(window) {
: _eventSource(source), _window(window)
#if SDL_VERSION_ATLEAST(2, 0, 0)
, _lastEngine(nullptr), _lastFlags(0)
#endif
{
}

SdlGraphicsManager::~SdlGraphicsManager() {
Expand Down Expand Up @@ -73,3 +77,22 @@ bool SdlGraphicsManager::setState(const State &state) {
}
}

#if SDL_VERSION_ATLEAST(2, 0, 0)
bool SdlGraphicsManager::createOrUpdateWindow(const int width, const int height, const Uint32 flags) {
// We store and check what the last engine was at the time that this method
// was called so that the ScummVM window size gets reset whenever the engine
// changes, but does not get reset when a game makes a call to change the
// size or pixel format of the internal game surface (since a user may have
// resized the game window)
if (!_window || _lastFlags != flags || g_engine != _lastEngine) {
if (!_window->createOrUpdateWindow(width, height, flags)) {
return false;
}

_lastFlags = flags;
_lastEngine = g_engine;
}

return true;
}
#endif
7 changes: 7 additions & 0 deletions backends/graphics/sdl/sdl-graphics.h
Expand Up @@ -123,6 +123,13 @@ class SdlGraphicsManager : virtual public GraphicsManager {
SdlWindow *getWindow() const { return _window; }

protected:
#if SDL_VERSION_ATLEAST(2, 0, 0)
void *_lastEngine;
Uint32 _lastFlags;

bool createOrUpdateWindow(const int width, const int height, const Uint32 flags);
#endif

SdlEventSource *_eventSource;
SdlWindow *_window;
};
Expand Down
9 changes: 7 additions & 2 deletions backends/graphics/surfacesdl/surfacesdl-graphics.cpp
Expand Up @@ -733,9 +733,14 @@ 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

_videoMode.screenWidth = w;
_videoMode.screenHeight = h;
Expand Down Expand Up @@ -2747,7 +2752,7 @@ SDL_Surface *SurfaceSdlGraphicsManager::SDL_SetVideoMode(int width, int height,
createWindowFlags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
}

if (!_window->createOrUpdateWindow(width, height, createWindowFlags)) {
if (!createOrUpdateWindow(width, height, createWindowFlags)) {
return nullptr;
}

Expand Down

0 comments on commit f8532bd

Please sign in to comment.