diff options
| author | Colin Snover | 2017-10-01 16:23:22 -0500 | 
|---|---|---|
| committer | Colin Snover | 2017-10-07 12:30:29 -0500 | 
| commit | 6e157429b7a5a64af6265d075c88595df2d6fd79 (patch) | |
| tree | 6e16e359d2f427ff0aa17ae229780509595ee1b1 /backends | |
| parent | 24f5d456195df3b65ed2876cbca2e2981f3d1a07 (diff) | |
| download | scummvm-rg350-6e157429b7a5a64af6265d075c88595df2d6fd79.tar.gz scummvm-rg350-6e157429b7a5a64af6265d075c88595df2d6fd79.tar.bz2 scummvm-rg350-6e157429b7a5a64af6265d075c88595df2d6fd79.zip  | |
BACKENDS: Fix window sizing of games that switch between multiple resolutions
Diffstat (limited to 'backends')
| -rw-r--r-- | backends/graphics/graphics.h | 2 | ||||
| -rw-r--r-- | backends/graphics/openglsdl/openglsdl-graphics.cpp | 17 | ||||
| -rw-r--r-- | backends/graphics/openglsdl/openglsdl-graphics.h | 5 | ||||
| -rw-r--r-- | backends/graphics/sdl/sdl-graphics.cpp | 89 | ||||
| -rw-r--r-- | backends/graphics/sdl/sdl-graphics.h | 14 | ||||
| -rw-r--r-- | backends/graphics/surfacesdl/surfacesdl-graphics.cpp | 45 | ||||
| -rw-r--r-- | backends/graphics/surfacesdl/surfacesdl-graphics.h | 2 | ||||
| -rw-r--r-- | backends/modular-backend.cpp | 4 | ||||
| -rw-r--r-- | backends/modular-backend.h | 1 | ||||
| -rw-r--r-- | backends/platform/sdl/sdl-window.cpp | 29 | 
10 files changed, 176 insertions, 32 deletions
diff --git a/backends/graphics/graphics.h b/backends/graphics/graphics.h index 35f2fa1cb6..9f07d36190 100644 --- a/backends/graphics/graphics.h +++ b/backends/graphics/graphics.h @@ -27,6 +27,7 @@  #include "common/noncopyable.h"  #include "common/keyboard.h" +#include "graphics/mode.h"  #include "graphics/palette.h"  /** @@ -58,6 +59,7 @@ public:  	virtual Common::List<Graphics::PixelFormat> getSupportedFormats() const = 0;  #endif  	virtual void initSize(uint width, uint height, const Graphics::PixelFormat *format = NULL) = 0; +	virtual void initSizeHint(const Graphics::ModeList &modes) = 0;  	virtual int getScreenChangeID() const = 0;  	virtual void beginGFXTransaction() = 0; diff --git a/backends/graphics/openglsdl/openglsdl-graphics.cpp b/backends/graphics/openglsdl/openglsdl-graphics.cpp index efc10a0d2c..73fc87a75f 100644 --- a/backends/graphics/openglsdl/openglsdl-graphics.cpp +++ b/backends/graphics/openglsdl/openglsdl-graphics.cpp @@ -268,22 +268,19 @@ bool OpenGLSdlGraphicsManager::getFeatureState(OSystem::Feature f) {  	}  } -bool OpenGLSdlGraphicsManager::setGraphicsMode(int mode) { +void OpenGLSdlGraphicsManager::initSize(uint w, uint h, const Graphics::PixelFormat *format) {  	// HACK: This is stupid but the SurfaceSDL backend defaults to 2x. This  	// assures that the launcher (which requests 320x200) has a reasonable  	// size. It also makes small games have a reasonable size (i.e. at least  	// 640x400). We follow the same logic here until we have a better way to  	// give hints to our backend for that. -	_graphicsScale = 2; - -	return OpenGLGraphicsManager::setGraphicsMode(mode); -} - -void OpenGLSdlGraphicsManager::resetGraphicsScale() { -	OpenGLGraphicsManager::resetGraphicsScale(); +	if (w > 320) { +		_graphicsScale = 1; +	} else { +		_graphicsScale = 2; +	} -	// HACK: See OpenGLSdlGraphicsManager::setGraphicsMode. -	_graphicsScale = 1; +	return OpenGLGraphicsManager::initSize(w, h, format);  }  #ifdef USE_RGB_COLOR diff --git a/backends/graphics/openglsdl/openglsdl-graphics.h b/backends/graphics/openglsdl/openglsdl-graphics.h index 51edcb4363..c5003d867b 100644 --- a/backends/graphics/openglsdl/openglsdl-graphics.h +++ b/backends/graphics/openglsdl/openglsdl-graphics.h @@ -43,8 +43,7 @@ public:  	virtual void setFeatureState(OSystem::Feature f, bool enable);  	virtual bool getFeatureState(OSystem::Feature f); -	virtual bool setGraphicsMode(int mode); -	virtual void resetGraphicsScale(); +	virtual void initSize(uint w, uint h, const Graphics::PixelFormat *format) override;  #ifdef USE_RGB_COLOR  	virtual Common::List<Graphics::PixelFormat> getSupportedFormats() const; @@ -69,6 +68,8 @@ protected:  	virtual void refreshScreen();  	virtual void *getProcAddress(const char *name) const; +	virtual int getGraphicsModeScale(int mode) const override { return 1; } +  private:  	bool setupMode(uint width, uint height); diff --git a/backends/graphics/sdl/sdl-graphics.cpp b/backends/graphics/sdl/sdl-graphics.cpp index aa6087beae..a181582235 100644 --- a/backends/graphics/sdl/sdl-graphics.cpp +++ b/backends/graphics/sdl/sdl-graphics.cpp @@ -23,12 +23,14 @@  #include "backends/graphics/sdl/sdl-graphics.h"  #include "backends/platform/sdl/sdl-sys.h"  #include "backends/events/sdl/sdl-events.h" +#include "common/config-manager.h"  #include "common/textconsole.h" +#include "graphics/scaler/aspect.h"  SdlGraphicsManager::SdlGraphicsManager(SdlEventSource *source, SdlWindow *window)  	: _eventSource(source), _window(window)  #if SDL_VERSION_ATLEAST(2, 0, 0) -	, _allowWindowSizeReset(false), _lastFlags(0) +	, _allowWindowSizeReset(false), _hintedWidth(0), _hintedHeight(0), _lastFlags(0)  #endif  	  {  } @@ -63,7 +65,7 @@ bool SdlGraphicsManager::setState(const State &state) {  #ifdef USE_RGB_COLOR  		initSize(state.screenWidth, state.screenHeight, &state.pixelFormat);  #else -		initSize(state.screenWidth, state.screenHeight, 0); +		initSize(state.screenWidth, state.screenHeight, nullptr);  #endif  		setFeatureState(OSystem::kFeatureAspectRatioCorrection, state.aspectRatio);  		setFeatureState(OSystem::kFeatureFullscreenMode, state.fullscreen); @@ -76,8 +78,82 @@ bool SdlGraphicsManager::setState(const State &state) {  	}  } +bool SdlGraphicsManager::defaultGraphicsModeConfig() const { +	const Common::ConfigManager::Domain *transientDomain = ConfMan.getDomain(Common::ConfigManager::kTransientDomain); +	if (transientDomain && transientDomain->contains("gfx_mode")) { +		const Common::String &mode = transientDomain->getVal("gfx_mode"); +		if (!mode.equalsIgnoreCase("normal") && !mode.equalsIgnoreCase("default")) { +			return false; +		} +	} + +	const Common::ConfigManager::Domain *gameDomain = ConfMan.getActiveDomain(); +	if (gameDomain && gameDomain->contains("gfx_mode")) { +		const Common::String &mode = gameDomain->getVal("gfx_mode"); +		if (!mode.equalsIgnoreCase("normal") && !mode.equalsIgnoreCase("default")) { +			return false; +		} +	} + +	return true; +} + +int SdlGraphicsManager::getGraphicsModeIdByName(const Common::String &name) const { +	const OSystem::GraphicsMode *mode = getSupportedGraphicsModes(); +	while (mode && mode->name != nullptr) { +		if (name.equalsIgnoreCase(mode->name)) { +			return mode->id; +		} +		++mode; +	} +	return -1; +} + +void SdlGraphicsManager::initSizeHint(const Graphics::ModeList &modes) {  #if SDL_VERSION_ATLEAST(2, 0, 0) -bool SdlGraphicsManager::createOrUpdateWindow(const int width, const int height, const Uint32 flags) { +	const bool useDefault = defaultGraphicsModeConfig(); + +	int scale = getGraphicsModeScale(getGraphicsModeIdByName(ConfMan.get("gfx_mode"))); +	if (scale == -1) { +		warning("Unknown scaler; defaulting to 1"); +		scale = 1; +	} + +	int16 bestWidth = 0, bestHeight = 0; +	const Graphics::ModeList::const_iterator end = modes.end(); +	for (Graphics::ModeList::const_iterator it = modes.begin(); it != end; ++it) { +		int16 width = it->width, height = it->height; + +		// TODO: Normalize AR correction by passing a PAR in the mode list +		// instead of checking the dimensions here like this, since not all +		// 320x200/640x400 uses are with non-square pixels (e.g. DreamWeb). +		if (ConfMan.getBool("aspect_ratio")) { +			if ((width == 320 && height == 200) || (width == 640 && height == 400)) { +				height = real2Aspect(height); +			} +		} + +		if (!useDefault || width <= 320) { +			width *= scale; +			height *= scale; +		} + +		if (bestWidth < width) { +			bestWidth = width; +		} + +		if (bestHeight < height) { +			bestHeight = height; +		} +	} + +	_hintedWidth = bestWidth; +	_hintedHeight = bestHeight; +#endif +} + +#if SDL_VERSION_ATLEAST(2, 0, 0) +bool SdlGraphicsManager::createOrUpdateWindow(int width, int height, const Uint32 flags) {  	if (!_window) {  		return false;  	} @@ -88,6 +164,13 @@ bool SdlGraphicsManager::createOrUpdateWindow(const int width, const int height,  	// size or pixel format of the internal game surface (since a user may have  	// resized the game window)  	if (!_window->getSDLWindow() || _lastFlags != flags || _allowWindowSizeReset) { +		if (_hintedWidth) { +			width = _hintedWidth; +		} +		if (_hintedHeight) { +			height = _hintedHeight; +		} +  		if (!_window->createOrUpdateWindow(width, height, flags)) {  			return false;  		} diff --git a/backends/graphics/sdl/sdl-graphics.h b/backends/graphics/sdl/sdl-graphics.h index 937beef9b4..74ee2838ea 100644 --- a/backends/graphics/sdl/sdl-graphics.h +++ b/backends/graphics/sdl/sdl-graphics.h @@ -122,14 +122,26 @@ public:  	 */  	SdlWindow *getWindow() const { return _window; } +	virtual void initSizeHint(const Graphics::ModeList &modes) override; +  protected: +	virtual int getGraphicsModeScale(int mode) const = 0; + +	bool defaultGraphicsModeConfig() const; +	int getGraphicsModeIdByName(const Common::String &name) const; +  #if SDL_VERSION_ATLEAST(2, 0, 0)  public: -	void unlockWindowSize() { _allowWindowSizeReset = true; } +	void unlockWindowSize() { +		_allowWindowSizeReset = true; +		_hintedWidth = 0; +		_hintedHeight = 0; +	}  protected:  	Uint32 _lastFlags;  	bool _allowWindowSizeReset; +	int _hintedWidth, _hintedHeight;  	bool createOrUpdateWindow(const int width, const int height, const Uint32 flags);  #endif diff --git a/backends/graphics/surfacesdl/surfacesdl-graphics.cpp b/backends/graphics/surfacesdl/surfacesdl-graphics.cpp index de54145d5f..897cdcb352 100644 --- a/backends/graphics/surfacesdl/surfacesdl-graphics.cpp +++ b/backends/graphics/surfacesdl/surfacesdl-graphics.cpp @@ -598,19 +598,11 @@ 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: @@ -623,18 +615,34 @@ bool SurfaceSdlGraphicsManager::setGraphicsMode(int mode) {  #ifdef USE_HQ_SCALERS  	case GFX_HQ2X:  #endif -		newScaleFactor = 2; +		scale = 2;  		break;  	case GFX_TRIPLESIZE:  	case GFX_ADVMAME3X:  #ifdef USE_HQ_SCALERS  	case GFX_HQ3X:  #endif -		newScaleFactor = 3; +		scale = 3;  		break;  #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;  	} @@ -774,6 +782,15 @@ void SurfaceSdlGraphicsManager::initSize(uint w, uint h, const Graphics::PixelFo  		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; diff --git a/backends/graphics/surfacesdl/surfacesdl-graphics.h b/backends/graphics/surfacesdl/surfacesdl-graphics.h index e93cf410ea..62a4a38d3e 100644 --- a/backends/graphics/surfacesdl/surfacesdl-graphics.h +++ b/backends/graphics/surfacesdl/surfacesdl-graphics.h @@ -190,6 +190,8 @@ protected:  	/** Hardware screen */  	SDL_Surface *_hwscreen; +	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. */ diff --git a/backends/modular-backend.cpp b/backends/modular-backend.cpp index 1dab18d54e..c9adbd3100 100644 --- a/backends/modular-backend.cpp +++ b/backends/modular-backend.cpp @@ -113,6 +113,10 @@ void ModularBackend::initSize(uint w, uint h, const Graphics::PixelFormat *forma  	_graphicsManager->initSize(w, h, format);  } +void ModularBackend::initSizeHint(const Graphics::ModeList &modes) { +	_graphicsManager->initSizeHint(modes); +} +  int ModularBackend::getScreenChangeID() const {  	return _graphicsManager->getScreenChangeID();  } diff --git a/backends/modular-backend.h b/backends/modular-backend.h index d828c2dde6..982dbbfb02 100644 --- a/backends/modular-backend.h +++ b/backends/modular-backend.h @@ -75,6 +75,7 @@ public:  	virtual Common::List<Graphics::PixelFormat> getSupportedFormats() const;  #endif  	virtual void initSize(uint width, uint height, const Graphics::PixelFormat *format = NULL); +	virtual void initSizeHint(const Graphics::ModeList &modes) override;  	virtual int getScreenChangeID() const;  	virtual void beginGFXTransaction(); diff --git a/backends/platform/sdl/sdl-window.cpp b/backends/platform/sdl/sdl-window.cpp index 07ddc998ba..75cf813638 100644 --- a/backends/platform/sdl/sdl-window.cpp +++ b/backends/platform/sdl/sdl-window.cpp @@ -223,6 +223,33 @@ bool SdlWindow::createOrUpdateWindow(int width, int height, uint32 flags) {  	const uint32 oldNonUpdateableFlags = _lastFlags & ~updateableFlagsMask;  	const uint32 newNonUpdateableFlags = flags & ~updateableFlagsMask; +	const uint32 fullscreenFlags = flags & fullscreenMask; + +	// This is terrible, but there is no way in SDL to get information on the +	// maximum bounds of a window with decoration, and SDL is too dumb to make +	// sure the window's surface doesn't grow beyond the display bounds, which +	// can easily happen with 3x scalers. There is a function in SDL to get the +	// window decoration size, but it only exists starting in SDL 2.0.5, which +	// is a buggy release on some platforms so we can't safely use 2.0.5+ +	// features since some users replace the SDL dynamic library with 2.0.4, and +	// the documentation says it only works on X11 anyway, which means it is +	// basically worthless. So we'll just try to keep things closeish to the +	// maximum for now. +	SDL_DisplayMode displayMode; +	SDL_GetDesktopDisplayMode(0, &displayMode); +	if (!fullscreenFlags) { +		displayMode.w -= 20; +		displayMode.h -= 30; +	} + +	if (width > displayMode.w) { +		width = displayMode.w; +	} + +	if (height > displayMode.h) { +		height = displayMode.h; +	} +  	if (!_window || oldNonUpdateableFlags != newNonUpdateableFlags) {  		destroyWindow();  		_window = SDL_CreateWindow(_windowCaption.c_str(), _lastX, @@ -231,8 +258,6 @@ bool SdlWindow::createOrUpdateWindow(int width, int height, uint32 flags) {  			setupIcon();  		}  	} else { -		const uint32 fullscreenFlags = flags & fullscreenMask; -  		if (fullscreenFlags) {  			SDL_DisplayMode fullscreenMode;  			fullscreenMode.w = width;  | 
