diff options
| author | Colin Snover | 2017-10-15 13:26:39 -0500 | 
|---|---|---|
| committer | Colin Snover | 2017-10-15 13:26:39 -0500 | 
| commit | 7d8d2f80fbc9cf96b3bd03b85a9722b576d23adc (patch) | |
| tree | a35cf3cd386219e8c945ba8aacc3e20c442fbf69 | |
| parent | 7fc86195343adf962054fd52605c3a3cc8b501e9 (diff) | |
| parent | 4757c24c683c2f2b8e3b55aa8d7a767aad9e947e (diff) | |
| download | scummvm-rg350-7d8d2f80fbc9cf96b3bd03b85a9722b576d23adc.tar.gz scummvm-rg350-7d8d2f80fbc9cf96b3bd03b85a9722b576d23adc.tar.bz2 scummvm-rg350-7d8d2f80fbc9cf96b3bd03b85a9722b576d23adc.zip | |
Merge branch 'graphics-backends-improvements'
35 files changed, 1284 insertions, 1223 deletions
| diff --git a/backends/events/default/default-events.cpp b/backends/events/default/default-events.cpp index c7c39da069..667914b023 100644 --- a/backends/events/default/default-events.cpp +++ b/backends/events/default/default-events.cpp @@ -254,4 +254,30 @@ void DefaultEventManager::pushEvent(const Common::Event &event) {  		_artificialEventSource.addEvent(event);  } +void DefaultEventManager::purgeMouseEvents() { +	_dispatcher.dispatch(); + +	Common::Queue<Common::Event> filteredQueue; +	while (!_eventQueue.empty()) { +		Common::Event event = _eventQueue.pop(); +		switch (event.type) { +		case Common::EVENT_MOUSEMOVE: +		case Common::EVENT_LBUTTONDOWN: +		case Common::EVENT_LBUTTONUP: +		case Common::EVENT_RBUTTONDOWN: +		case Common::EVENT_RBUTTONUP: +		case Common::EVENT_WHEELUP: +		case Common::EVENT_WHEELDOWN: +		case Common::EVENT_MBUTTONDOWN: +		case Common::EVENT_MBUTTONUP: +			// do nothing +			break; +		default: +			filteredQueue.push(event); +			break; +		} +	} +	_eventQueue = filteredQueue; +} +  #endif // !defined(DISABLE_DEFAULT_EVENTMANAGER) diff --git a/backends/events/default/default-events.h b/backends/events/default/default-events.h index f378fb9ff0..38406c25aa 100644 --- a/backends/events/default/default-events.h +++ b/backends/events/default/default-events.h @@ -80,6 +80,7 @@ public:  	virtual void init();  	virtual bool pollEvent(Common::Event &event);  	virtual void pushEvent(const Common::Event &event); +	virtual void purgeMouseEvents() override;  	virtual Common::Point getMousePos() const { return _mousePos; }  	virtual int getButtonState() const { return _buttonState; } diff --git a/backends/events/sdl/sdl-events.cpp b/backends/events/sdl/sdl-events.cpp index fb5a4c9b09..91ca0f5df6 100644 --- a/backends/events/sdl/sdl-events.cpp +++ b/backends/events/sdl/sdl-events.cpp @@ -75,7 +75,7 @@ static uint32 convUTF8ToUTF32(const char *src) {  #endif  SdlEventSource::SdlEventSource() -    : EventSource(), _scrollLock(false), _joystick(0), _lastScreenID(0), _graphicsManager(0) +    : EventSource(), _scrollLock(false), _joystick(0), _lastScreenID(0), _graphicsManager(0), _queuedFakeMouseMove(false)  #if SDL_VERSION_ATLEAST(2, 0, 0)        , _queuedFakeKeyUp(false), _fakeKeyUp()  #endif @@ -158,7 +158,7 @@ int SdlEventSource::mapKey(SDLKey sdlKey, SDLMod mod, Uint16 unicode) {  	} else if (key >= Common::KEYCODE_UP && key <= Common::KEYCODE_PAGEDOWN) {  		return key;  	} else if (unicode) { -		// Return unicode in case it's stil set and wasn't filtered. +		// Return unicode in case it's still set and wasn't filtered.  		return unicode;  	} else if (key >= 'a' && key <= 'z' && (mod & KMOD_SHIFT)) {  		return key & ~0x20; @@ -169,14 +169,15 @@ int SdlEventSource::mapKey(SDLKey sdlKey, SDLMod mod, Uint16 unicode) {  	}  } -void SdlEventSource::processMouseEvent(Common::Event &event, int x, int y) { +bool SdlEventSource::processMouseEvent(Common::Event &event, int x, int y) {  	event.mouse.x = x;  	event.mouse.y = y;  	if (_graphicsManager) { -		_graphicsManager->notifyMousePos(Common::Point(x, y)); -		_graphicsManager->transformMouseCoordinates(event.mouse); +		return _graphicsManager->notifyMousePosition(event.mouse);  	} + +	return true;  }  bool SdlEventSource::handleKbdMouse(Common::Event &event) { @@ -308,8 +309,7 @@ bool SdlEventSource::handleKbdMouse(Common::Event &event) {  			if (_km.x != oldKmX || _km.y != oldKmY) {  				event.type = Common::EVENT_MOUSEMOVE; -				processMouseEvent(event, _km.x / MULTIPLIER, _km.y / MULTIPLIER); -				return true; +				return processMouseEvent(event, _km.x / MULTIPLIER, _km.y / MULTIPLIER);  			}  		}  	} @@ -508,6 +508,12 @@ bool SdlEventSource::pollEvent(Common::Event &event) {  		return true;  	} +	if (_queuedFakeMouseMove) { +		event = _fakeMouseMove; +		_queuedFakeMouseMove = false; +		return true; +	} +  	SDL_Event ev;  	while (SDL_PollEvent(&ev)) {  		preprocessEvents(&ev); @@ -549,7 +555,9 @@ bool SdlEventSource::dispatchSDLEvent(SDL_Event &ev, Common::Event &event) {  		// with a mouse wheel event. However, SDL2 does not supply  		// these, thus we use whatever we got last time. It seems  		// these are always stored in _km.x, _km.y. -		processMouseEvent(event, _km.x / MULTIPLIER, _km.y / MULTIPLIER); +		if (!processMouseEvent(event, _km.x / MULTIPLIER, _km.y / MULTIPLIER)) { +			return false; +		}  		if (yDir < 0) {  			event.type = Common::EVENT_WHEELDOWN;  			return true; @@ -740,12 +748,12 @@ bool SdlEventSource::handleKeyUp(SDL_Event &ev, Common::Event &event) {  bool SdlEventSource::handleMouseMotion(SDL_Event &ev, Common::Event &event) {  	event.type = Common::EVENT_MOUSEMOVE; -	processMouseEvent(event, ev.motion.x, ev.motion.y); +  	// update KbdMouse  	_km.x = ev.motion.x * MULTIPLIER;  	_km.y = ev.motion.y * MULTIPLIER; -	return true; +	return processMouseEvent(event, ev.motion.x, ev.motion.y);  }  bool SdlEventSource::handleMouseButtonDown(SDL_Event &ev, Common::Event &event) { @@ -766,12 +774,11 @@ bool SdlEventSource::handleMouseButtonDown(SDL_Event &ev, Common::Event &event)  	else  		return false; -	processMouseEvent(event, ev.button.x, ev.button.y);  	// update KbdMouse  	_km.x = ev.button.x * MULTIPLIER;  	_km.y = ev.button.y * MULTIPLIER; -	return true; +	return processMouseEvent(event, ev.button.x, ev.button.y);  }  bool SdlEventSource::handleMouseButtonUp(SDL_Event &ev, Common::Event &event) { @@ -785,21 +792,21 @@ bool SdlEventSource::handleMouseButtonUp(SDL_Event &ev, Common::Event &event) {  #endif  	else  		return false; -	processMouseEvent(event, ev.button.x, ev.button.y); +  	// update KbdMouse  	_km.x = ev.button.x * MULTIPLIER;  	_km.y = ev.button.y * MULTIPLIER; -	return true; +	return processMouseEvent(event, ev.button.x, ev.button.y);  }  bool SdlEventSource::handleJoyButtonDown(SDL_Event &ev, Common::Event &event) {  	if (ev.jbutton.button == JOY_BUT_LMOUSE) {  		event.type = Common::EVENT_LBUTTONDOWN; -		processMouseEvent(event, _km.x / MULTIPLIER, _km.y / MULTIPLIER); +		return processMouseEvent(event, _km.x / MULTIPLIER, _km.y / MULTIPLIER);  	} else if (ev.jbutton.button == JOY_BUT_RMOUSE) {  		event.type = Common::EVENT_RBUTTONDOWN; -		processMouseEvent(event, _km.x / MULTIPLIER, _km.y / MULTIPLIER); +		return processMouseEvent(event, _km.x / MULTIPLIER, _km.y / MULTIPLIER);  	} else {  		event.type = Common::EVENT_KEYDOWN;  		switch (ev.jbutton.button) { @@ -820,17 +827,17 @@ bool SdlEventSource::handleJoyButtonDown(SDL_Event &ev, Common::Event &event) {  			event.kbd.ascii = mapKey(SDLK_F5, (SDLMod)ev.key.keysym.mod, 0);  			break;  		} +		return true;  	} -	return true;  }  bool SdlEventSource::handleJoyButtonUp(SDL_Event &ev, Common::Event &event) {  	if (ev.jbutton.button == JOY_BUT_LMOUSE) {  		event.type = Common::EVENT_LBUTTONUP; -		processMouseEvent(event, _km.x / MULTIPLIER, _km.y / MULTIPLIER); +		return processMouseEvent(event, _km.x / MULTIPLIER, _km.y / MULTIPLIER);  	} else if (ev.jbutton.button == JOY_BUT_RMOUSE) {  		event.type = Common::EVENT_RBUTTONUP; -		processMouseEvent(event, _km.x / MULTIPLIER, _km.y / MULTIPLIER); +		return processMouseEvent(event, _km.x / MULTIPLIER, _km.y / MULTIPLIER);  	} else {  		event.type = Common::EVENT_KEYUP;  		switch (ev.jbutton.button) { @@ -851,8 +858,8 @@ bool SdlEventSource::handleJoyButtonUp(SDL_Event &ev, Common::Event &event) {  			event.kbd.ascii = mapKey(SDLK_F5, (SDLMod)ev.key.keysym.mod, 0);  			break;  		} +		return true;  	} -	return true;  }  bool SdlEventSource::handleJoyAxisMotion(SDL_Event &ev, Common::Event &event) { @@ -968,9 +975,8 @@ bool SdlEventSource::remapKey(SDL_Event &ev, Common::Event &event) {  		event.kbd.keycode = Common::KEYCODE_F5;  		event.kbd.ascii = mapKey(SDLK_F5, ev.key.keysym.mod, 0);  	} -	// Nap center (space) to tab (default action ) +	// Map center (space) to tab (default action)  	// I wanted to map the calendar button but the calendar comes up -	//  	else if (ev.key.keysym.sym == SDLK_SPACE) {  		event.type = Common::EVENT_KEYDOWN;  		event.kbd.keycode = Common::KEYCODE_TAB; @@ -1003,6 +1009,12 @@ void SdlEventSource::resetKeyboardEmulation(int16 x_max, int16 y_max) {  	_km.joy_y = 0;  } +void SdlEventSource::fakeWarpMouse(const int x, const int y) { +	_queuedFakeMouseMove = true; +	_fakeMouseMove.type = Common::EVENT_MOUSEMOVE; +	_fakeMouseMove.mouse = Common::Point(x, y); +} +  bool SdlEventSource::handleResizeEvent(Common::Event &event, int w, int h) {  	if (_graphicsManager) {  		_graphicsManager->notifyResize(w, h); diff --git a/backends/events/sdl/sdl-events.h b/backends/events/sdl/sdl-events.h index cf445e9e2c..5fd3cb7ea5 100644 --- a/backends/events/sdl/sdl-events.h +++ b/backends/events/sdl/sdl-events.h @@ -51,6 +51,12 @@ public:  	 */  	virtual void resetKeyboardEmulation(int16 x_max, int16 y_max); +	/** +	 * Emulates a mouse movement that would normally be caused by a mouse warp +	 * of the system mouse. +	 */ +	void fakeWarpMouse(const int x, const int y); +  protected:  	/** @name Keyboard mouse emulation  	 * Disabled by fingolfin 2004-12-18. @@ -117,7 +123,7 @@ protected:  	 * Assigns the mouse coords to the mouse event. Furthermore notify the  	 * graphics manager about the position change.  	 */ -	virtual void processMouseEvent(Common::Event &event, int x, int y); +	virtual bool processMouseEvent(Common::Event &event, int x, int y);  	/**  	 * Remaps key events. This allows platforms to configure @@ -156,6 +162,18 @@ protected:  	 */  	SDLKey obtainKeycode(const SDL_keysym keySym); +	/** +	 * Whether _fakeMouseMove contains an event we need to send. +	 */ +	bool _queuedFakeMouseMove; + +	/** +	 * A fake mouse motion event sent when the graphics manager is told to warp +	 * the mouse but the system mouse is unable to be warped (e.g. because the +	 * window is not focused). +	 */ +	Common::Event _fakeMouseMove; +  #if SDL_VERSION_ATLEAST(2, 0, 0)  	/**  	 * Whether _fakeKeyUp contains an event we need to send. diff --git a/backends/graphics/dinguxsdl/dinguxsdl-graphics.cpp b/backends/graphics/dinguxsdl/dinguxsdl-graphics.cpp index 10605f45a7..3de6439d1a 100644 --- a/backends/graphics/dinguxsdl/dinguxsdl-graphics.cpp +++ b/backends/graphics/dinguxsdl/dinguxsdl-graphics.cpp @@ -487,14 +487,6 @@ bool DINGUXSdlGraphicsManager::getFeatureState(OSystem::Feature f) {  	}  } -SurfaceSdlGraphicsManager::MousePos *DINGUXSdlGraphicsManager::getMouseCurState() { -	return &_mouseCurState; -} - -SurfaceSdlGraphicsManager::VideoState *DINGUXSdlGraphicsManager::getVideoMode() { -	return &_videoMode; -} -  void DINGUXSdlGraphicsManager::warpMouse(int x, int y) {  	if (_mouseCurState.x != x || _mouseCurState.y != y) {  		if (_videoMode.mode == GFX_HALF && !_overlayVisible) { diff --git a/backends/graphics/dinguxsdl/dinguxsdl-graphics.h b/backends/graphics/dinguxsdl/dinguxsdl-graphics.h index 8a356106ad..89ee1411f1 100644 --- a/backends/graphics/dinguxsdl/dinguxsdl-graphics.h +++ b/backends/graphics/dinguxsdl/dinguxsdl-graphics.h @@ -36,26 +36,23 @@ class DINGUXSdlGraphicsManager : public SurfaceSdlGraphicsManager {  public:  	DINGUXSdlGraphicsManager(SdlEventSource *boss, SdlWindow *window); -	bool hasFeature(OSystem::Feature f); -	void setFeatureState(OSystem::Feature f, bool enable); -	bool getFeatureState(OSystem::Feature f); -	int getDefaultGraphicsMode() const; - -	void initSize(uint w, uint h); -	const OSystem::GraphicsMode *getSupportedGraphicsModes() const; -	bool setGraphicsMode(const char *name); -	bool setGraphicsMode(int mode); -	void setGraphicsModeIntern(); -	void internUpdateScreen(); -	void showOverlay(); -	void hideOverlay(); -	bool loadGFXMode(); -	void drawMouse(); -	void undrawMouse(); -	virtual void warpMouse(int x, int y); - -	SurfaceSdlGraphicsManager::MousePos *getMouseCurState(); -	SurfaceSdlGraphicsManager::VideoState *getVideoMode(); +	bool hasFeature(OSystem::Feature f) const override; +	void setFeatureState(OSystem::Feature f, bool enable) override; +	bool getFeatureState(OSystem::Feature f) override; +	int getDefaultGraphicsMode() const override; + +	void initSize(uint w, uint h) override; +	const OSystem::GraphicsMode *getSupportedGraphicsModes() const override; +	bool setGraphicsMode(const char *name) override; +	bool setGraphicsMode(int mode) override; +	void setGraphicsModeIntern() override; +	void internUpdateScreen() override; +	void showOverlay() override; +	void hideOverlay() override; +	bool loadGFXMode() override; +	void drawMouse() override; +	void undrawMouse() override; +	void warpMouse(int x, int y) override;  	virtual void transformMouseCoordinates(Common::Point &point);  }; diff --git a/backends/graphics/gph/gph-graphics.cpp b/backends/graphics/gph/gph-graphics.cpp index 767fb57e11..e2c84114c4 100644 --- a/backends/graphics/gph/gph-graphics.cpp +++ b/backends/graphics/gph/gph-graphics.cpp @@ -477,7 +477,7 @@ bool GPHGraphicsManager::loadGFXMode() {  	return true;  } -bool GPHGraphicsManager::hasFeature(OSystem::Feature f) { +bool GPHGraphicsManager::hasFeature(OSystem::Feature f) const {  	return  	    (f == OSystem::kFeatureAspectRatioCorrection) ||  	    (f == OSystem::kFeatureCursorPalette); @@ -497,7 +497,7 @@ void GPHGraphicsManager::setFeatureState(OSystem::Feature f, bool enable) {  	}  } -bool GPHGraphicsManager::getFeatureState(OSystem::Feature f) { +bool GPHGraphicsManager::getFeatureState(OSystem::Feature f) const {  	assert(_transactionMode == kTransactionNone);  	switch (f) { @@ -510,14 +510,6 @@ bool GPHGraphicsManager::getFeatureState(OSystem::Feature f) {  	}  } -SurfaceSdlGraphicsManager::MousePos *GPHGraphicsManager::getMouseCurState() { -	return &_mouseCurState; -} - -SurfaceSdlGraphicsManager::VideoState *GPHGraphicsManager::getVideoMode() { -	return &_videoMode; -} -  void GPHGraphicsManager::warpMouse(int x, int y) {  	if (_mouseCurState.x != x || _mouseCurState.y != y) {  		if (_videoMode.mode == GFX_HALF && !_overlayVisible) { diff --git a/backends/graphics/gph/gph-graphics.h b/backends/graphics/gph/gph-graphics.h index 152d29ddf4..69e3b8947f 100644 --- a/backends/graphics/gph/gph-graphics.h +++ b/backends/graphics/gph/gph-graphics.h @@ -35,26 +35,23 @@ class GPHGraphicsManager : public SurfaceSdlGraphicsManager {  public:  	GPHGraphicsManager(SdlEventSource *boss, SdlWindow *window); -	bool hasFeature(OSystem::Feature f); -	void setFeatureState(OSystem::Feature f, bool enable); -	bool getFeatureState(OSystem::Feature f); -	int getDefaultGraphicsMode() const; - -	void initSize(uint w, uint h, const Graphics::PixelFormat *format = NULL); -	const OSystem::GraphicsMode *getSupportedGraphicsModes() const; -	bool setGraphicsMode(const char *name); -	bool setGraphicsMode(int mode); -	void setGraphicsModeIntern(); -	void internUpdateScreen(); -	void showOverlay(); -	void hideOverlay(); -	bool loadGFXMode(); -	void drawMouse(); -	void undrawMouse(); -	virtual void warpMouse(int x, int y); - -	SurfaceSdlGraphicsManager::MousePos *getMouseCurState(); -	SurfaceSdlGraphicsManager::VideoState *getVideoMode(); +	bool hasFeature(OSystem::Feature f) const override; +	void setFeatureState(OSystem::Feature f, bool enable) override; +	bool getFeatureState(OSystem::Feature f) const; +	int getDefaultGraphicsMode() const override; + +	void initSize(uint w, uint h, const Graphics::PixelFormat *format = NULL) override; +	const OSystem::GraphicsMode *getSupportedGraphicsModes() const override; +	bool setGraphicsMode(const char *name) override; +	bool setGraphicsMode(int mode) override; +	void setGraphicsModeIntern() override; +	void internUpdateScreen() override; +	void showOverlay() override; +	void hideOverlay() override; +	bool loadGFXMode() override; +	void drawMouse() override; +	void undrawMouse() override; +	void warpMouse(int x, int y) override;  	virtual void transformMouseCoordinates(Common::Point &point);  }; diff --git a/backends/graphics/graphics.h b/backends/graphics/graphics.h index bcd659ac11..cf33803cf5 100644 --- a/backends/graphics/graphics.h +++ b/backends/graphics/graphics.h @@ -38,9 +38,9 @@ class GraphicsManager : public PaletteManager {  public:  	virtual ~GraphicsManager() {} -	virtual bool hasFeature(OSystem::Feature f) = 0; +	virtual bool hasFeature(OSystem::Feature f) const = 0;  	virtual void setFeatureState(OSystem::Feature f, bool enable) = 0; -	virtual bool getFeatureState(OSystem::Feature f) = 0; +	virtual bool getFeatureState(OSystem::Feature f) const = 0;  	virtual const OSystem::GraphicsMode *getSupportedGraphicsModes() const = 0;  	virtual int getDefaultGraphicsMode() const = 0; @@ -65,10 +65,10 @@ public:  	virtual void beginGFXTransaction() = 0;  	virtual OSystem::TransactionError endGFXTransaction() = 0; -	virtual int16 getHeight() = 0; -	virtual int16 getWidth() = 0; +	virtual int16 getHeight() const = 0; +	virtual int16 getWidth() const = 0;  	virtual void setPalette(const byte *colors, uint start, uint num) = 0; -	virtual void grabPalette(byte *colors, uint start, uint num) = 0; +	virtual void grabPalette(byte *colors, uint start, uint num) const = 0;  	virtual void copyRectToScreen(const void *buf, int pitch, int x, int y, int w, int h) = 0;  	virtual Graphics::Surface *lockScreen() = 0;  	virtual void unlockScreen() = 0; @@ -82,10 +82,10 @@ public:  	virtual void hideOverlay() = 0;  	virtual Graphics::PixelFormat getOverlayFormat() const = 0;  	virtual void clearOverlay() = 0; -	virtual void grabOverlay(void *buf, int pitch) = 0; -	virtual void copyRectToOverlay(const void *buf, int pitch, int x, int y, int w, int h)= 0; -	virtual int16 getOverlayHeight() = 0; -	virtual int16 getOverlayWidth() = 0; +	virtual void grabOverlay(void *buf, int pitch) const = 0; +	virtual void copyRectToOverlay(const void *buf, int pitch, int x, int y, int w, int h) = 0; +	virtual int16 getOverlayHeight() const = 0; +	virtual int16 getOverlayWidth() const = 0;  	virtual bool showMouse(bool visible) = 0;  	virtual void warpMouse(int x, int y) = 0; diff --git a/backends/graphics/linuxmotosdl/linuxmotosdl-graphics.h b/backends/graphics/linuxmotosdl/linuxmotosdl-graphics.h index d7a13b1cb4..e7f96e877c 100644 --- a/backends/graphics/linuxmotosdl/linuxmotosdl-graphics.h +++ b/backends/graphics/linuxmotosdl/linuxmotosdl-graphics.h @@ -29,18 +29,18 @@ class LinuxmotoSdlGraphicsManager : public SurfaceSdlGraphicsManager {  public:  	LinuxmotoSdlGraphicsManager(SdlEventSource *sdlEventSource, SdlWindow *window); -	virtual void initSize(uint w, uint h); -	virtual void setGraphicsModeIntern(); -	virtual bool setGraphicsMode(int mode); -	virtual void internUpdateScreen(); -	virtual const OSystem::GraphicsMode *getSupportedGraphicsModes() const; -	virtual int getDefaultGraphicsMode() const; -	virtual bool loadGFXMode(); -	virtual void drawMouse(); -	virtual void undrawMouse(); -	virtual void showOverlay(); -	virtual void hideOverlay(); -	virtual void warpMouse(int x, int y); +	virtual void initSize(uint w, uint h) override; +	virtual void setGraphicsModeIntern() override; +	virtual bool setGraphicsMode(int mode) override; +	virtual void internUpdateScreen() override; +	virtual const OSystem::GraphicsMode *getSupportedGraphicsModes() const override; +	virtual int getDefaultGraphicsMode() const override; +	virtual bool loadGFXMode() override; +	virtual void drawMouse() override; +	virtual void undrawMouse() override; +	virtual void showOverlay() override; +	virtual void hideOverlay() override; +	virtual void warpMouse(int x, int y) override;  	virtual void transformMouseCoordinates(Common::Point &point);  }; diff --git a/backends/graphics/maemosdl/maemosdl-graphics.h b/backends/graphics/maemosdl/maemosdl-graphics.h index 4cb84c81ee..ff4278b48c 100644 --- a/backends/graphics/maemosdl/maemosdl-graphics.h +++ b/backends/graphics/maemosdl/maemosdl-graphics.h @@ -32,7 +32,7 @@ public:  	MaemoSdlGraphicsManager(SdlEventSource *sdlEventSource, SdlWindow *window);  protected: -	virtual bool loadGFXMode(); +	virtual bool loadGFXMode() override;  };  #endif diff --git a/backends/graphics/null/null-graphics.h b/backends/graphics/null/null-graphics.h index 67306c29f3..4c628568ff 100644 --- a/backends/graphics/null/null-graphics.h +++ b/backends/graphics/null/null-graphics.h @@ -31,55 +31,55 @@ class NullGraphicsManager : public GraphicsManager {  public:  	virtual ~NullGraphicsManager() {} -	bool hasFeature(OSystem::Feature f) { return false; } -	void setFeatureState(OSystem::Feature f, bool enable) {} -	bool getFeatureState(OSystem::Feature f) { return false; } +	bool hasFeature(OSystem::Feature f) const override { return false; } +	void setFeatureState(OSystem::Feature f, bool enable) override {} +	bool getFeatureState(OSystem::Feature f) const override { return false; } -	const OSystem::GraphicsMode *getSupportedGraphicsModes() const { return s_noGraphicsModes; } -	int getDefaultGraphicsMode() const { return 0; } -	bool setGraphicsMode(int mode) { return true; } -	void resetGraphicsScale(){} -	int getGraphicsMode() const { return 0; } -	inline Graphics::PixelFormat getScreenFormat() const { +	const OSystem::GraphicsMode *getSupportedGraphicsModes() const override { return s_noGraphicsModes; } +	int getDefaultGraphicsMode() const override { return 0; } +	bool setGraphicsMode(int mode) override { return true; } +	void resetGraphicsScale() override {} +	int getGraphicsMode() const override { return 0; } +	inline Graphics::PixelFormat getScreenFormat() const override {  		return Graphics::PixelFormat::createFormatCLUT8();  	} -	inline Common::List<Graphics::PixelFormat> getSupportedFormats() const { +	inline Common::List<Graphics::PixelFormat> getSupportedFormats() const override {  		Common::List<Graphics::PixelFormat> list;  		list.push_back(Graphics::PixelFormat::createFormatCLUT8());  		return list;  	} -	void initSize(uint width, uint height, const Graphics::PixelFormat *format = NULL) {} -	virtual int getScreenChangeID() const { return 0; } +	void initSize(uint width, uint height, const Graphics::PixelFormat *format = NULL) override {} +	virtual int getScreenChangeID() const override { return 0; } -	void beginGFXTransaction() {} -	OSystem::TransactionError endGFXTransaction() { return OSystem::kTransactionSuccess; } +	void beginGFXTransaction() override {} +	OSystem::TransactionError endGFXTransaction() override { return OSystem::kTransactionSuccess; } -	int16 getHeight() { return 0; } -	int16 getWidth() { return 0; } -	void setPalette(const byte *colors, uint start, uint num) {} -	void grabPalette(byte *colors, uint start, uint num) {} -	void copyRectToScreen(const void *buf, int pitch, int x, int y, int w, int h) {} -	Graphics::Surface *lockScreen() { return NULL; } -	void unlockScreen() {} -	void fillScreen(uint32 col) {} -	void updateScreen() {} -	void setShakePos(int shakeOffset) {} -	void setFocusRectangle(const Common::Rect& rect) {} -	void clearFocusRectangle() {} +	int16 getHeight() const override { return 0; } +	int16 getWidth() const override { return 0; } +	void setPalette(const byte *colors, uint start, uint num) override {} +	void grabPalette(byte *colors, uint start, uint num) const override {} +	void copyRectToScreen(const void *buf, int pitch, int x, int y, int w, int h) override {} +	Graphics::Surface *lockScreen() override { return NULL; } +	void unlockScreen() override {} +	void fillScreen(uint32 col) override {} +	void updateScreen() override {} +	void setShakePos(int shakeOffset) override {} +	void setFocusRectangle(const Common::Rect& rect) override {} +	void clearFocusRectangle() override {} -	void showOverlay() {} -	void hideOverlay() {} -	Graphics::PixelFormat getOverlayFormat() const { return Graphics::PixelFormat(); } -	void clearOverlay() {} -	void grabOverlay(void *buf, int pitch) {} -	void copyRectToOverlay(const void *buf, int pitch, int x, int y, int w, int h) {} -	int16 getOverlayHeight() { return 0; } -	int16 getOverlayWidth() { return 0; } +	void showOverlay() override {} +	void hideOverlay() override {} +	Graphics::PixelFormat getOverlayFormat() const override { return Graphics::PixelFormat(); } +	void clearOverlay() override {} +	void grabOverlay(void *buf, int pitch) const override {} +	void copyRectToOverlay(const void *buf, int pitch, int x, int y, int w, int h) override {} +	int16 getOverlayHeight() const override { return 0; } +	int16 getOverlayWidth() const override { return 0; } -	bool showMouse(bool visible) { return !visible; } -	void warpMouse(int x, int y) {} -	void setMouseCursor(const void *buf, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor, bool dontScale = false, const Graphics::PixelFormat *format = NULL) {} -	void setCursorPalette(const byte *colors, uint start, uint num) {} +	bool showMouse(bool visible) override { return !visible; } +	void warpMouse(int x, int y) override {} +	void setMouseCursor(const void *buf, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor, bool dontScale = false, const Graphics::PixelFormat *format = NULL) override {} +	void setCursorPalette(const byte *colors, uint start, uint num) override {}  };  #endif diff --git a/backends/graphics/opengl/opengl-graphics.cpp b/backends/graphics/opengl/opengl-graphics.cpp index 28ca110d91..7bac4c85cb 100644 --- a/backends/graphics/opengl/opengl-graphics.cpp +++ b/backends/graphics/opengl/opengl-graphics.cpp @@ -53,14 +53,12 @@ namespace OpenGL {  OpenGLGraphicsManager::OpenGLGraphicsManager()      : _currentState(), _oldState(), _transactionMode(kTransactionNone), _screenChangeID(1 << (sizeof(int) * 8 - 2)),        _pipeline(nullptr), -      _outputScreenWidth(0), _outputScreenHeight(0), _displayX(0), _displayY(0), -      _displayWidth(0), _displayHeight(0), _defaultFormat(), _defaultFormatAlpha(), +      _defaultFormat(), _defaultFormatAlpha(),        _gameScreen(nullptr), _gameScreenShakeOffset(0), _overlay(nullptr), -      _overlayVisible(false), _cursor(nullptr), -      _cursorX(0), _cursorY(0), _cursorDisplayX(0),_cursorDisplayY(0), _cursorHotspotX(0), _cursorHotspotY(0), +      _cursor(nullptr), +      _cursorHotspotX(0), _cursorHotspotY(0),        _cursorHotspotXScaled(0), _cursorHotspotYScaled(0), _cursorWidthScaled(0), _cursorHeightScaled(0), -      _cursorKeyColor(0), _cursorVisible(false), _cursorDontScale(false), _cursorPaletteEnabled(false), -      _forceRedraw(false) +      _cursorKeyColor(0), _cursorDontScale(false), _cursorPaletteEnabled(false)  #ifdef USE_OSD        , _osdMessageChangeRequest(false), _osdMessageAlpha(0), _osdMessageFadeStartTime(0), _osdMessageSurface(nullptr),        _osdIconSurface(nullptr) @@ -83,7 +81,7 @@ OpenGLGraphicsManager::~OpenGLGraphicsManager() {  #endif  } -bool OpenGLGraphicsManager::hasFeature(OSystem::Feature f) { +bool OpenGLGraphicsManager::hasFeature(OSystem::Feature f) const {  	switch (f) {  	case OSystem::kFeatureAspectRatioCorrection:  	case OSystem::kFeatureCursorPalette: @@ -129,7 +127,7 @@ void OpenGLGraphicsManager::setFeatureState(OSystem::Feature f, bool enable) {  	}  } -bool OpenGLGraphicsManager::getFeatureState(OSystem::Feature f) { +bool OpenGLGraphicsManager::getFeatureState(OSystem::Feature f) const {  	switch (f) {  	case OSystem::kFeatureAspectRatioCorrection:  		return _currentState.aspectRatioCorrection; @@ -220,10 +218,9 @@ OSystem::TransactionError OpenGLGraphicsManager::endGFXTransaction() {  #endif  	do { -		uint requestedWidth  = _currentState.gameWidth; -		uint requestedHeight = _currentState.gameHeight; -		const uint desiredAspect = getDesiredGameScreenAspect(); -		requestedHeight = intToFrac(requestedWidth) / desiredAspect; +		const uint desiredAspect = getDesiredGameAspectRatio(); +		const uint requestedWidth  = _currentState.gameWidth; +		const uint requestedHeight = intToFrac(requestedWidth) / desiredAspect;  		if (!loadVideoMode(requestedWidth, requestedHeight,  #ifdef USE_RGB_COLOR @@ -317,7 +314,7 @@ OSystem::TransactionError OpenGLGraphicsManager::endGFXTransaction() {  	// Update our display area and cursor scaling. This makes sure we pick up  	// aspect ratio correction and game screen changes correctly. -	recalculateDisplayArea(); +	recalculateDisplayAreas();  	recalculateCursorScaling();  	// Something changed, so update the screen change ID. @@ -347,11 +344,11 @@ void OpenGLGraphicsManager::initSize(uint width, uint height, const Graphics::Pi  	_currentState.gameHeight = height;  } -int16 OpenGLGraphicsManager::getWidth() { +int16 OpenGLGraphicsManager::getWidth() const {  	return _currentState.gameWidth;  } -int16 OpenGLGraphicsManager::getHeight() { +int16 OpenGLGraphicsManager::getHeight() const {  	return _currentState.gameHeight;  } @@ -392,6 +389,7 @@ void OpenGLGraphicsManager::updateScreen() {  	// We only update the screen when there actually have been any changes.  	if (   !_forceRedraw +		&& !_cursorNeedsRedraw  	    && !_gameScreen->isDirty()  	    && !(_overlayVisible && _overlay->isDirty())  	    && !(_cursorVisible && _cursor && _cursor->isDirty()) @@ -401,7 +399,6 @@ void OpenGLGraphicsManager::updateScreen() {  	    ) {  		return;  	} -	_forceRedraw = false;  	// Update changes to textures.  	_gameScreen->updateGLTexture(); @@ -420,14 +417,14 @@ void OpenGLGraphicsManager::updateScreen() {  		_backBuffer.enableScissorTest(true);  	} -	const GLfloat shakeOffset = _gameScreenShakeOffset * (GLfloat)_displayHeight / _gameScreen->getHeight(); +	const GLfloat shakeOffset = _gameScreenShakeOffset * (GLfloat)_gameDrawRect.height() / _gameScreen->getHeight();  	// First step: Draw the (virtual) game screen. -	g_context.getActivePipeline()->drawTexture(_gameScreen->getGLTexture(), _displayX, _displayY + shakeOffset, _displayWidth, _displayHeight); +	g_context.getActivePipeline()->drawTexture(_gameScreen->getGLTexture(), _gameDrawRect.left, _gameDrawRect.top + shakeOffset, _gameDrawRect.width(), _gameDrawRect.height());  	// Second step: Draw the overlay if visible.  	if (_overlayVisible) { -		g_context.getActivePipeline()->drawTexture(_overlay->getGLTexture(), 0, 0, _outputScreenWidth, _outputScreenHeight); +		g_context.getActivePipeline()->drawTexture(_overlay->getGLTexture(), 0, 0, _overlayDrawRect.width(), _overlayDrawRect.height());  	}  	// Third step: Draw the cursor if visible. @@ -437,8 +434,8 @@ void OpenGLGraphicsManager::updateScreen() {  		const GLfloat cursorOffset = _overlayVisible ? 0 : shakeOffset;  		g_context.getActivePipeline()->drawTexture(_cursor->getGLTexture(), -		                         _cursorDisplayX - _cursorHotspotXScaled, -		                         _cursorDisplayY - _cursorHotspotYScaled + cursorOffset, +		                         _cursorX - _cursorHotspotXScaled, +		                         _cursorY - _cursorHotspotYScaled + cursorOffset,  		                         _cursorWidthScaled, _cursorHeightScaled);  	} @@ -464,8 +461,8 @@ void OpenGLGraphicsManager::updateScreen() {  		// Set the OSD transparency.  		g_context.getActivePipeline()->setColor(1.0f, 1.0f, 1.0f, _osdMessageAlpha / 100.0f); -		int dstX = (_outputScreenWidth - _osdMessageSurface->getWidth()) / 2; -		int dstY = (_outputScreenHeight - _osdMessageSurface->getHeight()) / 2; +		int dstX = (_windowWidth - _osdMessageSurface->getWidth()) / 2; +		int dstY = (_windowHeight - _osdMessageSurface->getHeight()) / 2;  		// Draw the OSD texture.  		g_context.getActivePipeline()->drawTexture(_osdMessageSurface->getGLTexture(), @@ -481,7 +478,7 @@ void OpenGLGraphicsManager::updateScreen() {  	}  	if (_osdIconSurface) { -		int dstX = _outputScreenWidth - _osdIconSurface->getWidth() - kOSDIconRightMargin; +		int dstX = _windowWidth - _osdIconSurface->getWidth() - kOSDIconRightMargin;  		int dstY = kOSDIconTopMargin;  		// Draw the OSD icon texture. @@ -490,6 +487,8 @@ void OpenGLGraphicsManager::updateScreen() {  	}  #endif +	_cursorNeedsRedraw = false; +	_forceRedraw = false;  	refreshScreen();  } @@ -507,7 +506,7 @@ void OpenGLGraphicsManager::setFocusRectangle(const Common::Rect& rect) {  void OpenGLGraphicsManager::clearFocusRectangle() {  } -int16 OpenGLGraphicsManager::getOverlayWidth() { +int16 OpenGLGraphicsManager::getOverlayWidth() const {  	if (_overlay) {  		return _overlay->getWidth();  	} else { @@ -515,7 +514,7 @@ int16 OpenGLGraphicsManager::getOverlayWidth() {  	}  } -int16 OpenGLGraphicsManager::getOverlayHeight() { +int16 OpenGLGraphicsManager::getOverlayHeight() const {  	if (_overlay) {  		return _overlay->getHeight();  	} else { @@ -523,22 +522,6 @@ int16 OpenGLGraphicsManager::getOverlayHeight() {  	}  } -void OpenGLGraphicsManager::showOverlay() { -	_overlayVisible = true; -	_forceRedraw = true; - -	// Update cursor position. -	setMousePosition(_cursorX, _cursorY); -} - -void OpenGLGraphicsManager::hideOverlay() { -	_overlayVisible = false; -	_forceRedraw = true; - -	// Update cursor position. -	setMousePosition(_cursorX, _cursorY); -} -  Graphics::PixelFormat OpenGLGraphicsManager::getOverlayFormat() const {  	return _overlay->getFormat();  } @@ -551,7 +534,7 @@ void OpenGLGraphicsManager::clearOverlay() {  	_overlay->fill(0);  } -void OpenGLGraphicsManager::grabOverlay(void *buf, int pitch) { +void OpenGLGraphicsManager::grabOverlay(void *buf, int pitch) const {  	const Graphics::Surface *overlayData = _overlay->getSurface();  	const byte *src = (const byte *)overlayData->getPixels(); @@ -564,55 +547,6 @@ void OpenGLGraphicsManager::grabOverlay(void *buf, int pitch) {  	}  } -bool OpenGLGraphicsManager::showMouse(bool visible) { -	// In case the mouse cursor visibility changed we need to redraw the whole -	// screen even when nothing else changed. -	if (_cursorVisible != visible) { -		_forceRedraw = true; -	} - -	bool last = _cursorVisible; -	_cursorVisible = visible; -	return last; -} - -void OpenGLGraphicsManager::warpMouse(int x, int y) { -	int16 currentX = _cursorX; -	int16 currentY = _cursorY; -	adjustMousePosition(currentX, currentY); - -	// Check whether the (virtual) coordinate actually changed. If not, then -	// simply do nothing. This avoids ugly "jittering" due to the actual -	// output screen having a bigger resolution than the virtual coordinates. -	if (currentX == x && currentY == y) { -		return; -	} - -	// Scale the virtual coordinates into actual physical coordinates. -	if (_overlayVisible) { -		if (!_overlay) { -			return; -		} - -		// It might be confusing that we actually have to handle something -		// here when the overlay is visible. This is because for very small -		// resolutions we have a minimal overlay size and have to adjust -		// for that. -		x = (x * _outputScreenWidth)  / _overlay->getWidth(); -		y = (y * _outputScreenHeight) / _overlay->getHeight(); -	} else { -		if (!_gameScreen) { -			return; -		} - -		x = (x * _outputScreenWidth)  / _gameScreen->getWidth(); -		y = (y * _outputScreenHeight) / _gameScreen->getHeight(); -	} - -	setMousePosition(x, y); -	setInternalMousePosition(x, y); -} -  namespace {  template<typename DstPixel, typename SrcPixel>  void applyColorKey(DstPixel *dst, const SrcPixel *src, uint w, uint h, uint dstPitch, uint srcPitch, SrcPixel keyColor, DstPixel alphaMask) { @@ -633,6 +567,18 @@ void applyColorKey(DstPixel *dst, const SrcPixel *src, uint w, uint h, uint dstP  } // End of anonymous namespace  void OpenGLGraphicsManager::setMouseCursor(const void *buf, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor, bool dontScale, const Graphics::PixelFormat *format) { + +	_cursorKeyColor = keycolor; +	_cursorHotspotX = hotspotX; +	_cursorHotspotY = hotspotY; +	_cursorDontScale = dontScale; + +	if (!w || !h) { +		delete _cursor; +		_cursor = nullptr; +		return; +	} +  	Graphics::PixelFormat inputFormat;  #ifdef USE_RGB_COLOR  	if (format) { @@ -668,11 +614,6 @@ void OpenGLGraphicsManager::setMouseCursor(const void *buf, uint w, uint h, int  		_cursor->enableLinearFiltering(_currentState.filtering);  	} -	_cursorKeyColor = keycolor; -	_cursorHotspotX = hotspotX; -	_cursorHotspotY = hotspotY; -	_cursorDontScale = dontScale; -  	_cursor->allocate(w, h);  	if (inputFormat.bytesPerPixel == 1) {  		// For CLUT8 cursors we can simply copy the input data into the @@ -720,7 +661,6 @@ void OpenGLGraphicsManager::setMouseCursor(const void *buf, uint w, uint h, int  		updateCursorPalette();  	} -	// Update the scaling.  	recalculateCursorScaling();  } @@ -765,8 +705,8 @@ void OpenGLGraphicsManager::osdMessageUpdateSurface() {  	}  	// Clip the rect -	width  = MIN<uint>(width,  _displayWidth); -	height = MIN<uint>(height, _displayHeight); +	width  = MIN<uint>(width,  _gameDrawRect.width()); +	height = MIN<uint>(height, _gameDrawRect.height());  	delete _osdMessageSurface;  	_osdMessageSurface = nullptr; @@ -849,16 +789,13 @@ void OpenGLGraphicsManager::setPalette(const byte *colors, uint start, uint num)  	updateCursorPalette();  } -void OpenGLGraphicsManager::grabPalette(byte *colors, uint start, uint num) { +void OpenGLGraphicsManager::grabPalette(byte *colors, uint start, uint num) const {  	assert(_gameScreen->hasPalette());  	memcpy(colors, _gamePalette + start * 3, num * 3);  } -void OpenGLGraphicsManager::setActualScreenSize(uint width, uint height) { -	_outputScreenWidth = width; -	_outputScreenHeight = height; - +void OpenGLGraphicsManager::handleResizeImpl(const int width, const int height) {  	// Setup backbuffer size.  	_backBuffer.setDimensions(width, height); @@ -873,7 +810,7 @@ void OpenGLGraphicsManager::setActualScreenSize(uint width, uint height) {  	// anyway. Thus, it should not be a real issue for modern hardware.  	if (   overlayWidth  > (uint)g_context.maxTextureSize  	    || overlayHeight > (uint)g_context.maxTextureSize) { -		const frac_t outputAspect = intToFrac(_outputScreenWidth) / _outputScreenHeight; +		const frac_t outputAspect = intToFrac(_windowWidth) / _windowHeight;  		if (outputAspect > (frac_t)FRAC_ONE) {  			overlayWidth  = g_context.maxTextureSize; @@ -906,7 +843,7 @@ void OpenGLGraphicsManager::setActualScreenSize(uint width, uint height) {  	_overlay->fill(0);  	// Re-setup the scaling for the screen and cursor -	recalculateDisplayArea(); +	recalculateDisplayAreas();  	recalculateCursorScaling();  	// Something changed, so update the screen change ID. @@ -960,8 +897,8 @@ void OpenGLGraphicsManager::notifyContextCreate(const Graphics::PixelFormat &def  	GL_CALL(glPixelStorei(GL_PACK_ALIGNMENT, 4));  	// Refresh the output screen dimensions if some are set up. -	if (_outputScreenWidth != 0 && _outputScreenHeight != 0) { -		setActualScreenSize(_outputScreenWidth, _outputScreenHeight); +	if (_windowWidth != 0 && _windowHeight != 0) { +		handleResize(_windowWidth, _windowHeight);  	}  	// TODO: Should we try to convert textures into one of those formats if @@ -1031,46 +968,6 @@ void OpenGLGraphicsManager::notifyContextDestroy() {  	g_context.reset();  } -void OpenGLGraphicsManager::adjustMousePosition(int16 &x, int16 &y) { -	if (_overlayVisible) { -		// It might be confusing that we actually have to handle something -		// here when the overlay is visible. This is because for very small -		// resolutions we have a minimal overlay size and have to adjust -		// for that. -		// This can also happen when the overlay is smaller than the actual -		// display size because of texture size limitations. -		if (_overlay) { -			x = (x * _overlay->getWidth())  / _outputScreenWidth; -			y = (y * _overlay->getHeight()) / _outputScreenHeight; -		} -	} else if (_gameScreen) { -		const int16 width  = _gameScreen->getWidth(); -		const int16 height = _gameScreen->getHeight(); - -		x = (x * width)  / (int)_outputScreenWidth; -		y = (y * height) / (int)_outputScreenHeight; -	} -} - -void OpenGLGraphicsManager::setMousePosition(int x, int y) { -	// Whenever the mouse position changed we force a screen redraw to reflect -	// changes properly. -	if (_cursorX != x || _cursorY != y) { -		_forceRedraw = true; -	} - -	_cursorX = x; -	_cursorY = y; - -	if (_overlayVisible) { -		_cursorDisplayX = x; -		_cursorDisplayY = y; -	} else { -		_cursorDisplayX = _displayX + (x * _displayWidth)  / _outputScreenWidth; -		_cursorDisplayY = _displayY + (y * _displayHeight) / _outputScreenHeight; -	} -} -  Surface *OpenGLGraphicsManager::createSurface(const Graphics::PixelFormat &format, bool wantAlpha) {  	GLenum glIntFormat, glFormat, glType;  	if (format.bytesPerPixel == 1) { @@ -1191,51 +1088,34 @@ bool OpenGLGraphicsManager::getGLPixelFormat(const Graphics::PixelFormat &pixelF  	}  } -frac_t OpenGLGraphicsManager::getDesiredGameScreenAspect() const { -	const uint width  = _currentState.gameWidth; -	const uint height = _currentState.gameHeight; - +bool OpenGLGraphicsManager::gameNeedsAspectRatioCorrection() const {  	if (_currentState.aspectRatioCorrection) { +		const uint width = getWidth(); +		const uint height = getHeight(); +  		// In case we enable aspect ratio correction we force a 4/3 ratio.  		// But just for 320x200 and 640x400 games, since other games do not need  		// this. -		if ((width == 320 && height == 200) || (width == 640 && height == 400)) { -			return intToFrac(4) / 3; -		} +		return (width == 320 && height == 200) || (width == 640 && height == 400);  	} -	return intToFrac(width) / height; +	return false;  } -void OpenGLGraphicsManager::recalculateDisplayArea() { -	if (!_gameScreen || _outputScreenHeight == 0) { +void OpenGLGraphicsManager::recalculateDisplayAreas() { +	if (!_gameScreen) {  		return;  	} -	const frac_t outputAspect = intToFrac(_outputScreenWidth) / _outputScreenHeight; -	const frac_t desiredAspect = getDesiredGameScreenAspect(); - -	_displayWidth = _outputScreenWidth; -	_displayHeight = _outputScreenHeight; - -	// Adjust one dimension for mantaining the aspect ratio. -	if (outputAspect < desiredAspect) { -		_displayHeight = intToFrac(_displayWidth) / desiredAspect; -	} else if (outputAspect > desiredAspect) { -		_displayWidth = fracToInt(_displayHeight * desiredAspect); -	} - -	// We center the screen in the middle for now. -	_displayX = (_outputScreenWidth  - _displayWidth ) / 2; -	_displayY = (_outputScreenHeight - _displayHeight) / 2; +	WindowedGraphicsManager::recalculateDisplayAreas();  	// Setup drawing limitation for game graphics.  	// This involves some trickery because OpenGL's viewport coordinate system  	// is upside down compared to ours. -	_backBuffer.setScissorBox(_displayX, -	                          _outputScreenHeight - _displayHeight - _displayY, -	                          _displayWidth, -	                          _displayHeight); +	_backBuffer.setScissorBox(_gameDrawRect.left, +	                          _windowHeight - _gameDrawRect.height() - _gameDrawRect.top, +	                          _gameDrawRect.width(), +	                          _gameDrawRect.height());  	// Update the cursor position to adjust for new display area.  	setMousePosition(_cursorX, _cursorY); @@ -1272,8 +1152,8 @@ void OpenGLGraphicsManager::recalculateCursorScaling() {  	// In case scaling is actually enabled we will scale the cursor according  	// to the game screen.  	if (!_cursorDontScale) { -		const frac_t screenScaleFactorX = intToFrac(_displayWidth)  / _gameScreen->getWidth(); -		const frac_t screenScaleFactorY = intToFrac(_displayHeight) / _gameScreen->getHeight(); +		const frac_t screenScaleFactorX = intToFrac(_gameDrawRect.width()) / _gameScreen->getWidth(); +		const frac_t screenScaleFactorY = intToFrac(_gameDrawRect.height()) / _gameScreen->getHeight();  		_cursorHotspotXScaled = fracToInt(_cursorHotspotXScaled * screenScaleFactorX);  		_cursorWidthScaled    = fracToInt(_cursorWidthScaled    * screenScaleFactorX); @@ -1284,14 +1164,14 @@ void OpenGLGraphicsManager::recalculateCursorScaling() {  }  #ifdef USE_OSD -const Graphics::Font *OpenGLGraphicsManager::getFontOSD() { +const Graphics::Font *OpenGLGraphicsManager::getFontOSD() const {  	return FontMan.getFontByUsage(Graphics::FontManager::kLocalizedFont);  }  #endif  bool OpenGLGraphicsManager::saveScreenshot(const Common::String &filename) const { -	const uint width  = _outputScreenWidth; -	const uint height = _outputScreenHeight; +	const uint width  = _windowWidth; +	const uint height = _windowHeight;  	// A line of a BMP image must have a size divisible by 4.  	// We calculate the padding bytes needed here. diff --git a/backends/graphics/opengl/opengl-graphics.h b/backends/graphics/opengl/opengl-graphics.h index e02137bba7..df968aa67e 100644 --- a/backends/graphics/opengl/opengl-graphics.h +++ b/backends/graphics/opengl/opengl-graphics.h @@ -25,7 +25,7 @@  #include "backends/graphics/opengl/opengl-sys.h"  #include "backends/graphics/opengl/framebuffer.h" -#include "backends/graphics/graphics.h" +#include "backends/graphics/windowed.h"  #include "common/frac.h"  #include "common/mutex.h" @@ -53,74 +53,69 @@ enum {  	GFX_OPENGL = 0  }; -class OpenGLGraphicsManager : virtual public GraphicsManager { +class OpenGLGraphicsManager : virtual public WindowedGraphicsManager {  public:  	OpenGLGraphicsManager();  	virtual ~OpenGLGraphicsManager();  	// GraphicsManager API -	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 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() {} +	virtual void resetGraphicsScale() override {}  #ifdef USE_RGB_COLOR -	virtual Graphics::PixelFormat getScreenFormat() const; -	virtual Common::List<Graphics::PixelFormat> getSupportedFormats() const = 0; +	virtual Graphics::PixelFormat getScreenFormat() const override; +	virtual Common::List<Graphics::PixelFormat> getSupportedFormats() const override = 0;  #endif -	virtual void beginGFXTransaction(); -	virtual OSystem::TransactionError endGFXTransaction(); +	virtual void beginGFXTransaction() override; +	virtual OSystem::TransactionError endGFXTransaction() override; -	virtual int getScreenChangeID() const; +	virtual int getScreenChangeID() const override; -	virtual void initSize(uint width, uint height, const Graphics::PixelFormat *format); +	virtual void initSize(uint width, uint height, const Graphics::PixelFormat *format) override; -	virtual int16 getWidth(); -	virtual int16 getHeight(); +	virtual int16 getWidth() const override; +	virtual int16 getHeight() const override; -	virtual void copyRectToScreen(const void *buf, int pitch, int x, int y, int w, int h); -	virtual void fillScreen(uint32 col); +	virtual void copyRectToScreen(const void *buf, int pitch, int x, int y, int w, int h) override; +	virtual void fillScreen(uint32 col) override; -	virtual void setShakePos(int shakeOffset); +	virtual void setShakePos(int shakeOffset) override; -	virtual void updateScreen(); +	virtual void updateScreen() override; -	virtual Graphics::Surface *lockScreen(); -	virtual void unlockScreen(); +	virtual Graphics::Surface *lockScreen() override; +	virtual void unlockScreen() override; -	virtual void setFocusRectangle(const Common::Rect& rect); -	virtual void clearFocusRectangle(); +	virtual void setFocusRectangle(const Common::Rect& rect) override; +	virtual void clearFocusRectangle() override; -	virtual int16 getOverlayWidth(); -	virtual int16 getOverlayHeight(); +	virtual int16 getOverlayWidth() const override; +	virtual int16 getOverlayHeight() const override; -	virtual void showOverlay(); -	virtual void hideOverlay(); +	virtual Graphics::PixelFormat getOverlayFormat() const override; -	virtual Graphics::PixelFormat getOverlayFormat() const; +	virtual void copyRectToOverlay(const void *buf, int pitch, int x, int y, int w, int h) override; +	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); -	virtual void clearOverlay(); -	virtual void grabOverlay(void *buf, int pitch); +	virtual void setMouseCursor(const void *buf, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor, bool dontScale, const Graphics::PixelFormat *format) override; +	virtual void setCursorPalette(const byte *colors, uint start, uint num) override; -	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, const Graphics::PixelFormat *format); -	virtual void setCursorPalette(const byte *colors, uint start, uint num); - -	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;  	// PaletteManager interface -	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;  protected:  	/** @@ -129,15 +124,6 @@ protected:  	bool isGLESContext() const { return g_context.type == kContextGLES || g_context.type == kContextGLES2; }  	/** -	 * Set up the actual screen size available for the OpenGL code to do any -	 * drawing. -	 * -	 * @param width  The width of the screen. -	 * @param height The height of the screen. -	 */ -	void setActualScreenSize(uint width, uint height); - -	/**  	 * Sets the OpenGL (ES) type the graphics manager shall work with.  	 *  	 * This needs to be called at least once (and before ever calling @@ -167,33 +153,6 @@ protected:  	void notifyContextDestroy();  	/** -	 * Adjust the physical mouse coordinates according to the currently visible screen. -	 */ -	void adjustMousePosition(int16 &x, int16 &y); - -	/** -	 * Set up the mouse position for graphics output. -	 * -	 * @param x X coordinate in physical coordinates. -	 * @param y Y coordinate in physical coordinates. -	 */ -	void setMousePosition(int x, int y); - -	/** -	 * Query the mouse position in physical coordinates. -	 */ -	void getMousePosition(int16 &x, int16 &y) const { x = _cursorX; y = _cursorY; } - -	/** -	 * Set up the mouse position for the (event) system. -	 * -	 * @param x X coordinate in physical coordinates. -	 * @param y Y coordinate in physical coordinates. -	 */ -	virtual void setInternalMousePosition(int x, int y) = 0; - -private: -	/**  	 * Create a surface with the specified pixel format.  	 *  	 * @param format    The pixel format the Surface object should accept as @@ -241,7 +200,7 @@ private:  	};  	/** -	 * The currently setup video state. +	 * The currently set up video state.  	 */  	VideoState _currentState; @@ -292,8 +251,7 @@ protected:  	virtual void refreshScreen() = 0;  	/** -	 * Save a screenshot of the full display as BMP to the given file. This -	 * uses Common::DumpFile for writing the screenshot. +	 * Saves a screenshot of the entire window, excluding window decorations.  	 *  	 * @param filename The output filename.  	 * @return true on success, false otherwise @@ -334,7 +292,6 @@ protected:  	 */  	virtual void *getProcAddress(const char *name) const = 0; -private:  	/**  	 * Try to determine the internal parameters for a given pixel format.  	 * @@ -342,49 +299,9 @@ private:  	 */  	bool getGLPixelFormat(const Graphics::PixelFormat &pixelFormat, GLenum &glIntFormat, GLenum &glFormat, GLenum &glType) const; -	// -	// Actual hardware screen -	// - -	/** -	 * The width of the physical output. -	 */ -	uint _outputScreenWidth; - -	/** -	 * The height of the physical output. -	 */ -	uint _outputScreenHeight; - -	/** -	 * @return The desired aspect of the game screen. -	 */ -	frac_t getDesiredGameScreenAspect() const; - -	/** -	 * Recalculates the area used to display the game screen. -	 */ -	void recalculateDisplayArea(); - -	/** -	 * The X coordinate of the game screen. -	 */ -	uint _displayX; - -	/** -	 * The Y coordinate of the game screen. -	 */ -	uint _displayY; - -	/** -	 * The width of the game screen in physical coordinates. -	 */ -	uint _displayWidth; - -	/** -	 * The height of the game screen in physical coordinates. -	 */ -	uint _displayHeight; +	virtual bool gameNeedsAspectRatioCorrection() const override; +	virtual void recalculateDisplayAreas() override; +	virtual void handleResizeImpl(const int width, const int height) override;  	/**  	 * The default pixel format of the backend. @@ -396,12 +313,8 @@ private:  	 */  	Graphics::PixelFormat _defaultFormatAlpha; -	// -	// Game screen -	// -  	/** -	 * The virtual game screen. +	 * The rendering surface for the virtual game screen.  	 */  	Surface *_gameScreen; @@ -420,15 +333,10 @@ private:  	//  	/** -	 * The overlay screen. +	 * The rendering surface for the overlay.  	 */  	Surface *_overlay; -	/** -	 * Whether the overlay is visible or not. -	 */ -	bool _overlayVisible; -  	//  	// Cursor  	// @@ -439,37 +347,17 @@ private:  	void updateCursorPalette();  	/** -	 * The cursor image. +	 * The rendering surface for the mouse cursor.  	 */  	Surface *_cursor;  	/** -	 * X coordinate of the cursor in phyiscal coordinates. -	 */ -	int _cursorX; - -	/** -	 * Y coordinate of the cursor in physical coordinates. -	 */ -	int _cursorY; - -	/** -	 * X coordinate used for drawing the cursor. -	 */ -	int _cursorDisplayX; - -	/** -	 * Y coordinate used for drawing the cursor. -	 */ -	int _cursorDisplayY; - -	/** -	 * The X offset for the cursor hotspot in unscaled coordinates. +	 * The X offset for the cursor hotspot in unscaled game coordinates.  	 */  	int _cursorHotspotX;  	/** -	 * The Y offset for the cursor hotspot in unscaled coordinates. +	 * The Y offset for the cursor hotspot in unscaled game coordinates.  	 */  	int _cursorHotspotY; @@ -480,22 +368,24 @@ private:  	void recalculateCursorScaling();  	/** -	 * The X offset for the cursor hotspot in scaled coordinates. +	 * The X offset for the cursor hotspot in scaled game display area +	 * coordinates.  	 */  	int _cursorHotspotXScaled;  	/** -	 * The Y offset for the cursor hotspot in scaled coordinates. +	 * The Y offset for the cursor hotspot in scaled game display area +	 * coordinates.  	 */  	int _cursorHotspotYScaled;  	/** -	 * The width of the cursor scaled coordinates. +	 * The width of the cursor in scaled game display area coordinates.  	 */  	uint _cursorWidthScaled;  	/** -	 * The height of the cursor scaled coordinates. +	 * The height of the cursor in scaled game display area coordinates.  	 */  	uint _cursorHeightScaled; @@ -505,11 +395,6 @@ private:  	uint32 _cursorKeyColor;  	/** -	 * Whether the cursor is actually visible. -	 */ -	bool _cursorVisible; - -	/**  	 * Whether no cursor scaling should be applied.  	 */  	bool _cursorDontScale; @@ -524,15 +409,6 @@ private:  	 */  	byte _cursorPalette[3 * 256]; -	// -	// Misc -	// - -	/** -	 * Whether the screen contents shall be forced to redrawn. -	 */ -	bool _forceRedraw; -  #ifdef USE_OSD  	//  	// OSD @@ -541,7 +417,7 @@ protected:  	/**  	 * Returns the font used for on screen display  	 */ -	virtual const Graphics::Font *getFontOSD(); +	virtual const Graphics::Font *getFontOSD() const;  private:  	/** diff --git a/backends/graphics/openglsdl/openglsdl-graphics.cpp b/backends/graphics/openglsdl/openglsdl-graphics.cpp index 73fc87a75f..c77e9dafc5 100644 --- a/backends/graphics/openglsdl/openglsdl-graphics.cpp +++ b/backends/graphics/openglsdl/openglsdl-graphics.cpp @@ -21,8 +21,10 @@   */  #include "backends/graphics/openglsdl/openglsdl-graphics.h" +#include "backends/graphics/opengl/texture.h"  #include "backends/events/sdl/sdl-events.h"  #include "backends/platform/sdl/sdl.h" +#include "graphics/scaler/aspect.h"  #include "common/textconsole.h"  #include "common/config-manager.h" @@ -35,7 +37,7 @@ OpenGLSdlGraphicsManager::OpenGLSdlGraphicsManager(uint desktopWidth, uint deskt  #if SDL_VERSION_ATLEAST(2, 0, 0)        _glContext(),  #else -      _lastVideoModeLoad(0), _hwScreen(nullptr), +      _lastVideoModeLoad(0),  #endif        _graphicsScale(2), _ignoreLoadVideoMode(false), _gotResize(false), _wantsFullScreen(false), _ignoreResizeEvents(0),        _desiredFullscreenWidth(0), _desiredFullscreenHeight(0) { @@ -46,20 +48,22 @@ OpenGLSdlGraphicsManager::OpenGLSdlGraphicsManager(uint desktopWidth, uint deskt  	SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);  	SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); -	// Setup proper SDL OpenGL context creation. +	// Set up proper SDL OpenGL context creation.  #if SDL_VERSION_ATLEAST(2, 0, 0)  	OpenGL::ContextType glContextType;  	// Context version 1.4 is choosen arbitrarily based on what most shader  	// extensions were written against. -#define DEFAULT_GL_MAJOR 1 -#define DEFAULT_GL_MINOR 4 +	enum { +		DEFAULT_GL_MAJOR = 1, +		DEFAULT_GL_MINOR = 4, -#define DEFAULT_GLES_MAJOR 1 -#define DEFAULT_GLES_MINOR 1 +		DEFAULT_GLES_MAJOR = 1, +		DEFAULT_GLES_MINOR = 1, -#define DEFAULT_GLES2_MAJOR 2 -#define DEFAULT_GLES2_MINOR 0 +		DEFAULT_GLES2_MAJOR = 2, +		DEFAULT_GLES2_MINOR = 0 +	};  #if USE_FORCED_GL  	glContextType = OpenGL::kContextGL; @@ -127,12 +131,6 @@ OpenGLSdlGraphicsManager::OpenGLSdlGraphicsManager(uint desktopWidth, uint deskt  	} else {  		glContextType = OpenGL::kContextGL;  	} -#undef DEFAULT_GL_MAJOR -#undef DEFAULT_GL_MINOR -#undef DEFAULT_GLES_MAJOR -#undef DEFAULT_GLES_MINOR -#undef DEFAULT_GLES2_MAJOR -#undef DEFAULT_GLES2_MINOR  #endif  	setContextType(glContextType); @@ -217,7 +215,7 @@ void OpenGLSdlGraphicsManager::deactivateManager() {  	SdlGraphicsManager::deactivateManager();  } -bool OpenGLSdlGraphicsManager::hasFeature(OSystem::Feature f) { +bool OpenGLSdlGraphicsManager::hasFeature(OSystem::Feature f) const {  	switch (f) {  	case OSystem::kFeatureFullscreenMode:  	case OSystem::kFeatureIconifyWindow: @@ -246,7 +244,7 @@ void OpenGLSdlGraphicsManager::setFeatureState(OSystem::Feature f, bool enable)  	}  } -bool OpenGLSdlGraphicsManager::getFeatureState(OSystem::Feature f) { +bool OpenGLSdlGraphicsManager::getFeatureState(OSystem::Feature f) const {  	switch (f) {  	case OSystem::kFeatureFullscreenMode:  #if SDL_VERSION_ATLEAST(2, 0, 0) @@ -344,7 +342,7 @@ void OpenGLSdlGraphicsManager::updateScreen() {  void OpenGLSdlGraphicsManager::notifyVideoExpose() {  } -void OpenGLSdlGraphicsManager::notifyResize(const uint width, const uint height) { +void OpenGLSdlGraphicsManager::notifyResize(const int width, const int height) {  #if SDL_VERSION_ATLEAST(2, 0, 0)  	// We sometime get outdated resize events from SDL2. So check that the size we get  	// is the actual current window size. If not ignore the resize. @@ -354,11 +352,10 @@ void OpenGLSdlGraphicsManager::notifyResize(const uint width, const uint height)  	// causes a SDL_WINDOWEVENT_RESIZED event with the old resolution to be sent, and this  	// event is processed after recreating the window at the new resolution.  	int currentWidth, currentHeight; -	getWindowDimensions(¤tWidth, ¤tHeight); -	if (width != (uint)currentWidth || height != (uint)currentHeight) +	getWindowSizeFromSdl(¤tWidth, ¤tHeight); +	if (width != currentWidth || height != currentHeight)  		return; -	setActualScreenSize(width, height); -	_eventSource->resetKeyboardEmulation(width - 1, height - 1); +	handleResize(width, height);  #else  	if (!_ignoreResizeEvents && _hwScreen && !(_hwScreen->flags & SDL_FULLSCREEN)) {  		// We save that we handled a resize event here. We need to know this @@ -373,18 +370,6 @@ void OpenGLSdlGraphicsManager::notifyResize(const uint width, const uint height)  #endif  } -void OpenGLSdlGraphicsManager::transformMouseCoordinates(Common::Point &point) { -	adjustMousePosition(point.x, point.y); -} - -void OpenGLSdlGraphicsManager::notifyMousePos(Common::Point mouse) { -	setMousePosition(mouse.x, mouse.y); -} - -void OpenGLSdlGraphicsManager::setInternalMousePosition(int x, int y) { -	_window->warpMouseInWindow(x, y); -} -  bool OpenGLSdlGraphicsManager::loadVideoMode(uint requestedWidth, uint requestedHeight, const Graphics::PixelFormat &format) {  	// In some cases we might not want to load the requested video mode. This  	// will assure that the window size is not altered. @@ -422,6 +407,11 @@ void *OpenGLSdlGraphicsManager::getProcAddress(const char *name) const {  	return SDL_GL_GetProcAddress(name);  } +void OpenGLSdlGraphicsManager::handleResizeImpl(const int width, const int height) { +	OpenGLGraphicsManager::handleResizeImpl(width, height); +	SdlGraphicsManager::handleResizeImpl(width, height); +} +  bool OpenGLSdlGraphicsManager::setupMode(uint width, uint height) {  	// In case we request a fullscreen mode we will use the mode the user  	// has chosen last time or the biggest mode available. @@ -517,9 +507,8 @@ bool OpenGLSdlGraphicsManager::setupMode(uint width, uint height) {  	notifyContextCreate(rgba8888, rgba8888);  	int actualWidth, actualHeight; -	getWindowDimensions(&actualWidth, &actualHeight); -	setActualScreenSize(actualWidth, actualHeight); -	_eventSource->resetKeyboardEmulation(actualWidth - 1, actualHeight - 1); +	getWindowSizeFromSdl(&actualWidth, &actualHeight); +	handleResize(actualWidth, actualHeight);  	return true;  #else  	// WORKAROUND: Working around infamous SDL bugs when switching @@ -566,8 +555,7 @@ bool OpenGLSdlGraphicsManager::setupMode(uint width, uint height) {  	if (_hwScreen) {  		notifyContextCreate(rgba8888, rgba8888); -		setActualScreenSize(_hwScreen->w, _hwScreen->h); -		_eventSource->resetKeyboardEmulation(_hwScreen->w - 1, _hwScreen->h - 1); +		handleResize(_hwScreen->w, _hwScreen->h);  	}  	// Ignore resize events (from SDL) for a few frames, if this isn't @@ -580,20 +568,6 @@ bool OpenGLSdlGraphicsManager::setupMode(uint width, uint height) {  #endif  } -void OpenGLSdlGraphicsManager::getWindowDimensions(int *width, int *height) { -#if SDL_VERSION_ATLEAST(2, 0, 0) -	SDL_GetWindowSize(_window->getSDLWindow(), width, height); -#else -	if (width) { -		*width = _hwScreen->w; -	} - -	if (height) { -		*height = _hwScreen->h; -	} -#endif -} -  bool OpenGLSdlGraphicsManager::notifyEvent(const Common::Event &event) {  	switch (event.type) {  	case Common::EVENT_KEYUP: @@ -707,7 +681,7 @@ bool OpenGLSdlGraphicsManager::notifyEvent(const Common::Event &event) {  					// current scale setting in case the user resized the  					// window. Then we apply the direction change.  					int windowWidth = 0, windowHeight = 0; -					getWindowDimensions(&windowWidth, &windowHeight); +					getWindowSizeFromSdl(&windowWidth, &windowHeight);  					_graphicsScale = MAX<int>(windowWidth / _lastRequestedWidth, windowHeight / _lastRequestedHeight);  					_graphicsScale = MAX<int>(_graphicsScale + direction, 1); @@ -725,7 +699,7 @@ bool OpenGLSdlGraphicsManager::notifyEvent(const Common::Event &event) {  #ifdef USE_OSD  				int windowWidth = 0, windowHeight = 0; -				getWindowDimensions(&windowWidth, &windowHeight); +				getWindowSizeFromSdl(&windowWidth, &windowHeight);  				const Common::String osdMsg = Common::String::format(_("Resolution: %dx%d"), windowWidth, windowHeight);  				displayMessageOnOSD(osdMsg.c_str());  #endif @@ -785,7 +759,7 @@ bool OpenGLSdlGraphicsManager::notifyEvent(const Common::Event &event) {  	}  } -bool OpenGLSdlGraphicsManager::isHotkey(const Common::Event &event) { +bool OpenGLSdlGraphicsManager::isHotkey(const Common::Event &event) const {  	if (event.kbd.hasFlags(Common::KBD_ALT)) {  		return    event.kbd.keycode == Common::KEYCODE_RETURN  		       || event.kbd.keycode == (Common::KeyCode)SDLK_KP_ENTER diff --git a/backends/graphics/openglsdl/openglsdl-graphics.h b/backends/graphics/openglsdl/openglsdl-graphics.h index c5003d867b..954c7215a4 100644 --- a/backends/graphics/openglsdl/openglsdl-graphics.h +++ b/backends/graphics/openglsdl/openglsdl-graphics.h @@ -36,38 +36,37 @@ public:  	virtual ~OpenGLSdlGraphicsManager();  	// GraphicsManager API -	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 void initSize(uint w, uint h, const Graphics::PixelFormat *format) override;  #ifdef USE_RGB_COLOR -	virtual Common::List<Graphics::PixelFormat> getSupportedFormats() const; +	virtual Common::List<Graphics::PixelFormat> getSupportedFormats() const override;  #endif -	virtual void updateScreen(); +	virtual void updateScreen() override;  	// EventObserver API -	virtual bool notifyEvent(const Common::Event &event); +	virtual bool notifyEvent(const Common::Event &event) override;  	// SdlGraphicsManager API -	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: -	virtual void setInternalMousePosition(int x, int y); +	virtual bool loadVideoMode(uint requestedWidth, uint requestedHeight, const Graphics::PixelFormat &format) override; -	virtual bool loadVideoMode(uint requestedWidth, uint requestedHeight, const Graphics::PixelFormat &format); +	virtual void refreshScreen() override; -	virtual void refreshScreen(); +	virtual void *getProcAddress(const char *name) const override; + +	virtual void handleResizeImpl(const int width, const int height) override; -	virtual void *getProcAddress(const char *name) const;  	virtual int getGraphicsModeScale(int mode) const override { return 1; }  private: @@ -78,11 +77,8 @@ private:  	SDL_GLContext _glContext;  #else  	uint32 _lastVideoModeLoad; -	SDL_Surface *_hwScreen;  #endif -	void getWindowDimensions(int *width, int *height); -  	uint _lastRequestedWidth;  	uint _lastRequestedHeight;  	uint _graphicsScale; @@ -122,7 +118,7 @@ private:  	uint _desiredFullscreenWidth;  	uint _desiredFullscreenHeight; -	virtual bool isHotkey(const Common::Event &event); +	bool isHotkey(const Common::Event &event) const;  };  #endif diff --git a/backends/graphics/openpandora/op-graphics.h b/backends/graphics/openpandora/op-graphics.h index 50994072bb..56777dc892 100644 --- a/backends/graphics/openpandora/op-graphics.h +++ b/backends/graphics/openpandora/op-graphics.h @@ -34,8 +34,8 @@ class OPGraphicsManager : public SurfaceSdlGraphicsManager {  public:  	OPGraphicsManager(SdlEventSource *sdlEventSource, SdlWindow *window); -	bool loadGFXMode(); -	void unloadGFXMode(); +	bool loadGFXMode() override; +	void unloadGFXMode() override;  };  #endif /* BACKENDS_GRAPHICS_OP_H */ diff --git a/backends/graphics/psp2sdl/psp2sdl-graphics.h b/backends/graphics/psp2sdl/psp2sdl-graphics.h index 638437c9a6..0cabeb094d 100644 --- a/backends/graphics/psp2sdl/psp2sdl-graphics.h +++ b/backends/graphics/psp2sdl/psp2sdl-graphics.h @@ -30,19 +30,19 @@ class PSP2SdlGraphicsManager : public SurfaceSdlGraphicsManager {  public:  	PSP2SdlGraphicsManager(SdlEventSource *sdlEventSource, SdlWindow *window);  	virtual ~PSP2SdlGraphicsManager(); -	 -	virtual OSystem::TransactionError endGFXTransaction(); -	virtual const OSystem::GraphicsMode *getSupportedShaders() const; + +	virtual OSystem::TransactionError endGFXTransaction() override; +	virtual const OSystem::GraphicsMode *getSupportedShaders() const override;  protected: -	virtual void setGraphicsModeIntern(); -	virtual void unloadGFXMode(); -	virtual bool hotswapGFXMode(); - -	virtual void internUpdateScreen(); -	virtual void updateShader(); -	virtual void setAspectRatioCorrection(bool enable); -	virtual SDL_Surface *SDL_SetVideoMode(int width, int height, int bpp, Uint32 flags); +	virtual void setGraphicsModeIntern() override; +	virtual void unloadGFXMode() override; +	virtual bool hotswapGFXMode() override; + +	virtual void internUpdateScreen() override; +	virtual void updateShader() override; +	virtual void setAspectRatioCorrection(bool enable) override; +	virtual SDL_Surface *SDL_SetVideoMode(int width, int height, int bpp, Uint32 flags) override;  	void PSP2_UpdateRects(SDL_Surface *screen, int numrects, SDL_Rect *rects);  	void PSP2_UpdateFiltering(); diff --git a/backends/graphics/samsungtvsdl/samsungtvsdl-graphics.cpp b/backends/graphics/samsungtvsdl/samsungtvsdl-graphics.cpp index 0c98462891..befa793263 100644 --- a/backends/graphics/samsungtvsdl/samsungtvsdl-graphics.cpp +++ b/backends/graphics/samsungtvsdl/samsungtvsdl-graphics.cpp @@ -32,7 +32,7 @@ SamsungTVSdlGraphicsManager::SamsungTVSdlGraphicsManager(SdlEventSource *sdlEven  	: SurfaceSdlGraphicsManager(sdlEventSource, window) {  } -bool SamsungTVSdlGraphicsManager::hasFeature(OSystem::Feature f) { +bool SamsungTVSdlGraphicsManager::hasFeature(OSystem::Feature f) const {  	return  		(f == OSystem::kFeatureAspectRatioCorrection) ||  		(f == OSystem::kFeatureCursorPalette); @@ -48,7 +48,7 @@ void SamsungTVSdlGraphicsManager::setFeatureState(OSystem::Feature f, bool enabl  	}  } -bool SamsungTVSdlGraphicsManager::getFeatureState(OSystem::Feature f) { +bool SamsungTVSdlGraphicsManager::getFeatureState(OSystem::Feature f) const {  	switch (f) {  	case OSystem::kFeatureAspectRatioCorrection:  		return SurfaceSdlGraphicsManager::getFeatureState(f); diff --git a/backends/graphics/samsungtvsdl/samsungtvsdl-graphics.h b/backends/graphics/samsungtvsdl/samsungtvsdl-graphics.h index 8699d77bc8..b86ebe2c45 100644 --- a/backends/graphics/samsungtvsdl/samsungtvsdl-graphics.h +++ b/backends/graphics/samsungtvsdl/samsungtvsdl-graphics.h @@ -31,9 +31,9 @@ class SamsungTVSdlGraphicsManager : public SurfaceSdlGraphicsManager {  public:  	SamsungTVSdlGraphicsManager(SdlEventSource *sdlEventSource, SdlWindow *window); -	bool hasFeature(OSystem::Feature f); -	void setFeatureState(OSystem::Feature f, bool enable); -	bool getFeatureState(OSystem::Feature f); +	bool hasFeature(OSystem::Feature f) const override; +	void setFeatureState(OSystem::Feature f, bool enable) override; +	bool getFeatureState(OSystem::Feature f) const override;  };  #endif diff --git a/backends/graphics/sdl/sdl-graphics.cpp b/backends/graphics/sdl/sdl-graphics.cpp index a181582235..0e0a45a38f 100644 --- a/backends/graphics/sdl/sdl-graphics.cpp +++ b/backends/graphics/sdl/sdl-graphics.cpp @@ -28,15 +28,11 @@  #include "graphics/scaler/aspect.h"  SdlGraphicsManager::SdlGraphicsManager(SdlEventSource *source, SdlWindow *window) -	: _eventSource(source), _window(window) +	: _eventSource(source), _window(window), _hwScreen(nullptr)  #if SDL_VERSION_ATLEAST(2, 0, 0)  	, _allowWindowSizeReset(false), _hintedWidth(0), _hintedHeight(0), _lastFlags(0)  #endif -	  { -} - -SdlGraphicsManager::~SdlGraphicsManager() { -} +{}  void SdlGraphicsManager::activateManager() {  	_eventSource->setGraphicsManager(this); @@ -46,7 +42,7 @@ void SdlGraphicsManager::deactivateManager() {  	_eventSource->setGraphicsManager(0);  } -SdlGraphicsManager::State SdlGraphicsManager::getState() { +SdlGraphicsManager::State SdlGraphicsManager::getState() const {  	State state;  	state.screenWidth   = getWidth(); @@ -152,6 +148,82 @@ void SdlGraphicsManager::initSizeHint(const Graphics::ModeList &modes) {  #endif  } +bool SdlGraphicsManager::showMouse(const bool visible) { +	if (visible == _cursorVisible) { +		return visible; +	} + +	int showCursor = SDL_DISABLE; +	if (visible) { +		// _cursorX and _cursorY are currently always clipped to the active +		// area, so we need to ask SDL where the system's mouse cursor is +		// instead +		int x, y; +		SDL_GetMouseState(&x, &y); +		if (!_activeArea.drawRect.contains(Common::Point(x, y))) { +			showCursor = SDL_ENABLE; +		} +	} +	SDL_ShowCursor(showCursor); + +	return WindowedGraphicsManager::showMouse(visible); +} + +bool SdlGraphicsManager::notifyMousePosition(Common::Point &mouse) { +	int showCursor = SDL_DISABLE; +	bool valid = true; +	if (_activeArea.drawRect.contains(mouse)) { +		_cursorLastInActiveArea = true; +	} else { +		mouse.x = CLIP<int>(mouse.x, _activeArea.drawRect.left, _activeArea.drawRect.right - 1); +		mouse.y = CLIP<int>(mouse.y, _activeArea.drawRect.top, _activeArea.drawRect.bottom - 1); + +		if (_window->mouseIsGrabbed() || +			// Keep the mouse inside the game area during dragging to prevent an +			// event mismatch where the mouseup event gets lost because it is +			// performed outside of the game area +			(_cursorLastInActiveArea && SDL_GetMouseState(nullptr, nullptr) != 0)) { +			setSystemMousePosition(mouse.x, mouse.y); +		} else { +			// Allow the in-game mouse to get a final movement event to the edge +			// of the window if the mouse was moved out of the game area +			if (_cursorLastInActiveArea) { +				_cursorLastInActiveArea = false; +			} else if (_cursorVisible) { +				// Keep sending events to the game if the cursor is invisible, +				// since otherwise if a game lets you skip a cutscene by +				// clicking and the user moved the mouse outside the active +				// area, the clicks wouldn't do anything, which would be +				// confusing +				valid = false; +			} + +			if (_cursorVisible) { +				showCursor = SDL_ENABLE; +			} +		} +	} + +	SDL_ShowCursor(showCursor); +	if (valid) { +		setMousePosition(mouse.x, mouse.y); +		mouse = convertWindowToVirtual(mouse.x, mouse.y); +	} +	return valid; +} + +void SdlGraphicsManager::setSystemMousePosition(const int x, const int y) { +	assert(_window); +	if (!_window->warpMouseInWindow(x, y)) { +		_eventSource->fakeWarpMouse(x, y); +	} +} + +void SdlGraphicsManager::handleResizeImpl(const int width, const int height) { +	_eventSource->resetKeyboardEmulation(width - 1, height - 1); +	_forceRedraw = true; +} +  #if SDL_VERSION_ATLEAST(2, 0, 0)  bool SdlGraphicsManager::createOrUpdateWindow(int width, int height, const Uint32 flags) {  	if (!_window) { @@ -159,11 +231,12 @@ bool SdlGraphicsManager::createOrUpdateWindow(int width, int height, const Uint3  	}  	// We only update the actual window when flags change (which usually means -	// fullscreen mode is entered/exited) or when updates are forced so that we +	// fullscreen mode is entered/exited), when updates are forced so that we  	// do not reset the window size whenever 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->getSDLWindow() || _lastFlags != flags || _allowWindowSizeReset) { +	// resized the game window), or when the launcher is visible (since a user +	// may change the scaler, which should reset the window size) +	if (!_window->getSDLWindow() || _lastFlags != flags || _overlayVisible || _allowWindowSizeReset) {  		if (_hintedWidth) {  			width = _hintedWidth;  		} diff --git a/backends/graphics/sdl/sdl-graphics.h b/backends/graphics/sdl/sdl-graphics.h index 74ee2838ea..526306270b 100644 --- a/backends/graphics/sdl/sdl-graphics.h +++ b/backends/graphics/sdl/sdl-graphics.h @@ -23,7 +23,7 @@  #ifndef BACKENDS_GRAPHICS_SDL_SDLGRAPHICS_H  #define BACKENDS_GRAPHICS_SDL_SDLGRAPHICS_H -#include "backends/graphics/graphics.h" +#include "backends/graphics/windowed.h"  #include "backends/platform/sdl/sdl-window.h"  #include "common/rect.h" @@ -32,13 +32,11 @@ class SdlEventSource;  /**   * Base class for a SDL based graphics manager. - * - * It features a few extra a few extra features required by SdlEventSource.   */ -class SdlGraphicsManager : virtual public GraphicsManager { +class SdlGraphicsManager : virtual public WindowedGraphicsManager {  public:  	SdlGraphicsManager(SdlEventSource *source, SdlWindow *window); -	virtual ~SdlGraphicsManager(); +	virtual ~SdlGraphicsManager() {}  	/**  	 * Makes this graphics manager active. That means it should be ready to @@ -62,10 +60,10 @@ public:  	virtual void notifyVideoExpose() = 0;  	/** -	 * Notify the graphics manager about an resize event. +	 * Notify the graphics manager about a resize event.  	 *  	 * It is noteworthy that the requested width/height should actually be set -	 * up as is and not changed by the graphics manager, since else it might +	 * up as is and not changed by the graphics manager, since otherwise it may  	 * lead to odd behavior for certain window managers.  	 *  	 * It is only required to overwrite this method in case you want a @@ -74,27 +72,28 @@ public:  	 * @param width Requested window width.  	 * @param height Requested window height.  	 */ -	virtual void notifyResize(const uint width, const uint height) {} +	virtual void notifyResize(const int width, const int height) {}  	/** -	 * Transforms real screen coordinates into the current active screen -	 * coordinates (may be either game screen or overlay). +	 * Notifies the graphics manager about a mouse position change.  	 * -	 * @param point Mouse coordinates to transform. -	 */ -	virtual void transformMouseCoordinates(Common::Point &point) = 0; - -	/** -	 * Notifies the graphics manager about a position change according to the -	 * real screen coordinates. +	 * The passed point *must* be converted from window coordinates to virtual +	 * coordinates in order for the event to be processed correctly by the game +	 * engine. Just use `convertWindowToVirtual` for this unless you need to do +	 * something special.  	 * -	 * @param mouse Mouse position. +	 * @param mouse The mouse position in window coordinates, which must be +	 * converted synchronously to virtual coordinates. +	 * @returns true if the mouse was in a valid position for the game and +	 * should cause the event to be sent to the game.  	 */ -	virtual void notifyMousePos(Common::Point mouse) = 0; +	virtual bool notifyMousePosition(Common::Point &mouse); + +	virtual bool showMouse(const bool visible) override;  	/**  	 * A (subset) of the graphic manager's state. This is used when switching -	 * between different SDL graphic managers on runtime. +	 * between different SDL graphic managers at runtime.  	 */  	struct State {  		int screenWidth, screenHeight; @@ -108,17 +107,17 @@ public:  	};  	/** -	 * Queries the current state of the graphic manager. +	 * Gets the current state of the graphics manager.  	 */ -	State getState(); +	State getState() const;  	/** -	 * Setup a basic state of the graphic manager. +	 * Sets up a basic state of the graphics manager.  	 */  	bool setState(const State &state);  	/** -	 * Queries the SDL window. +	 * @returns the SDL window.  	 */  	SdlWindow *getWindow() const { return _window; } @@ -130,6 +129,31 @@ protected:  	bool defaultGraphicsModeConfig() const;  	int getGraphicsModeIdByName(const Common::String &name) const; +	/** +	 * Gets the dimensions of the window directly from SDL instead of from the +	 * values stored by the graphics manager. +	 */ +	void getWindowSizeFromSdl(int *width, int *height) const { +#if SDL_VERSION_ATLEAST(2, 0, 0) +		assert(_window); +		SDL_GetWindowSize(_window->getSDLWindow(), width, height); +#else +		assert(_hwScreen); + +		if (width) { +			*width = _hwScreen->w; +		} + +		if (height) { +			*height = _hwScreen->h; +		} +#endif +	} + +	virtual void setSystemMousePosition(const int x, const int y) override; + +	virtual void handleResizeImpl(const int width, const int height) override; +  #if SDL_VERSION_ATLEAST(2, 0, 0)  public:  	void unlockWindowSize() { @@ -146,6 +170,7 @@ protected:  	bool createOrUpdateWindow(const int width, const int height, const Uint32 flags);  #endif +	SDL_Surface *_hwScreen;  	SdlEventSource *_eventSource;  	SdlWindow *_window;  }; diff --git a/backends/graphics/surfacesdl/surfacesdl-graphics.cpp b/backends/graphics/surfacesdl/surfacesdl-graphics.cpp index 897cdcb352..f025cfa7e5 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. @@ -555,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); @@ -579,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]); @@ -587,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]); @@ -722,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. @@ -797,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); @@ -864,7 +849,7 @@ 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)  	_videoMode.overlayWidth = _videoMode.screenWidth * _videoMode.scaleFactor; @@ -873,11 +858,14 @@ bool SurfaceSdlGraphicsManager::loadGFXMode() {  	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; @@ -887,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, @@ -924,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  	{ @@ -937,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  			);  	} @@ -946,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()); @@ -958,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  	// @@ -965,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"); @@ -997,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); @@ -1033,9 +1014,9 @@ void SurfaceSdlGraphicsManager::unloadGFXMode() {  	deinitializeRenderer();  #endif -	if (_hwscreen) { -		SDL_FreeSurface(_hwscreen); -		_hwscreen = NULL; +	if (_hwScreen) { +		SDL_FreeSurface(_hwScreen); +		_hwScreen = NULL;  	}  	if (_tmpscreen) { @@ -1087,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); @@ -1139,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() { @@ -1155,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 @@ -1185,7 +1160,7 @@ void SurfaceSdlGraphicsManager::internUpdateScreen() {  		_paletteDirtyEnd = 0; -		_forceFull = true; +		_forceRedraw = true;  	}  	if (!_overlayVisible) { @@ -1207,7 +1182,7 @@ 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) +	if (_cursorNeedsRedraw)  		undrawMouse();  #ifdef USE_OSD @@ -1215,7 +1190,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; @@ -1224,7 +1199,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; @@ -1240,10 +1215,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; @@ -1268,7 +1243,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; @@ -1278,17 +1253,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(); @@ -1318,18 +1293,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; @@ -1340,14 +1315,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; @@ -1358,12 +1333,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);  				}  			}  		} @@ -1371,17 +1346,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 @@ -1391,12 +1366,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, @@ -1411,9 +1386,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;  	} @@ -1441,7 +1416,7 @@ bool SurfaceSdlGraphicsManager::saveScreenshot(const char *filename) {  	return success;  #else -	return SDL_SaveBMP(_hwscreen, filename) == 0; +	return SDL_SaveBMP(_hwScreen, filename) == 0;  #endif  } @@ -1505,7 +1480,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); @@ -1517,19 +1491,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); @@ -1549,13 +1510,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;  } @@ -1571,7 +1526,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); @@ -1585,11 +1540,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;  	} @@ -1608,8 +1563,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 @@ -1620,7 +1575,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) { @@ -1638,7 +1593,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;  	} @@ -1652,20 +1607,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. @@ -1697,12 +1649,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; @@ -1777,56 +1726,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) @@ -1854,10 +1754,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) @@ -1931,143 +1831,159 @@ 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); +		dontScale = true; +	} 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; +			} +		} + +		if (_cursorFormat.bytesPerPixel == 4) { +			if (_mouseSurface != _mouseOrigSurface) { +				SDL_FreeSurface(_mouseSurface); +			} -		_window->warpMouseInWindow(x1, y1); +			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); +		} -		// 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 (_mouseOrigSurface == nullptr) { +			error("Allocating _mouseOrigSurface failed"); +		} -		setMousePos(x, y); +		if (_cursorFormat.bytesPerPixel < 4) { +			SDL_SetColorKey(_mouseOrigSurface, SDL_RLEACCEL | SDL_SRCCOLORKEY | SDL_SRCALPHA, kMouseColorKey); +		}  	} -} -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; +	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); +	} -	if (_cursorFormat.bytesPerPixel < 4) -		assert(keycolor < (uint)(1 << (_cursorFormat.bytesPerPixel << 3))); -#else -	assert(keycolor <= 0xFF); -#endif +	blitCursor(); +} -	if (w == 0 || h == 0) +void SurfaceSdlGraphicsManager::blitCursor() { +	const int w = _mouseCurState.w; +	const int h = _mouseCurState.h; + +	if (!w || !h || !_mouseOrigSurface) {  		return; +	} -	_mouseCurState.hotX = hotspot_x; -	_mouseCurState.hotY = hotspot_y; +	if (_cursorFormat.bytesPerPixel != 4 && !_mouseData) { +		return; +	} -	_mouseKeyColor = keycolor; +	_cursorNeedsRedraw = true; -	_cursorDontScale = dontScale; +	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; +	} -	if (_mouseCurState.w != (int)w || _mouseCurState.h != (int)h) { -		_mouseCurState.w = w; -		_mouseCurState.h = h; +	assert(_cursorFormat.bytesPerPixel != 4 || cursorScale == 1); -		if (_mouseOrigSurface) -			SDL_FreeSurface(_mouseOrigSurface); +	// 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; -		// 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); +	// The virtual dimensions will be the same as the original. -		if (_mouseOrigSurface == NULL) -			error("allocating _mouseOrigSurface failed"); -		SDL_SetColorKey(_mouseOrigSurface, SDL_RLEACCEL | SDL_SRCCOLORKEY | SDL_SRCALPHA, kMouseColorKey); -	} +	_mouseCurState.vW = w; +	_mouseCurState.vH = h; +	_mouseCurState.vHotX = _mouseCurState.hotX; +	_mouseCurState.vHotY = _mouseCurState.hotY; -	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); +#ifdef USE_SCALERS +	// store original to pass to aspect-correction function later +	const int rH1 = rH;  #endif -	blitCursor(); -} +	if (!_cursorDontScale && _videoMode.aspectRatioCorrection) { +		rH = real2Aspect(rH - 1) + 1; +		_mouseCurState.rHotY = real2Aspect(_mouseCurState.rHotY); +	} -void SurfaceSdlGraphicsManager::blitCursor() { -	byte *dstPtr; -	const byte *srcPtr = _mouseData; -#ifdef USE_RGB_COLOR -	uint32 color; -#else -	byte color; -#endif -	int w, h, i, j; +	bool sizeChanged = false; +	if (_mouseCurState.rW != rW || _mouseCurState.rH != rH) { +		_mouseCurState.rW = rW; +		_mouseCurState.rH = rH; +		sizeChanged = true; +	} -	if (!_mouseOrigSurface || !_mouseData) +	// 32bpp always blits directly, so no need to do any more work here +	if (_cursorFormat.bytesPerPixel == 4) {  		return; - -	_mouseNeedsRedraw = true; - -	w = _mouseCurState.w; -	h = _mouseCurState.h; +	}  	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;  		} @@ -2083,75 +1999,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); @@ -2159,13 +2031,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);  	} @@ -2236,7 +2108,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;  	} @@ -2245,8 +2117,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,10 +2157,17 @@ void SurfaceSdlGraphicsManager::drawMouse() {  	dst.w = _mouseCurState.rW;  	dst.h = _mouseCurState.rH; +	// Alpha-blended cursors will happily blend into themselves if the hardware +	// surface under the cursor is not reset first +	if (!_forceRedraw && _cursorFormat.bytesPerPixel == 4) { +		if (SDL_BlitSurface(_screen, &dst, _hwScreen, &dst) != 0) +			error("SD_BlitSurface failed: %s", SDL_GetError()); +	} +  	// 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. @@ -2335,14 +2216,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 @@ -2379,8 +2260,8 @@ void SurfaceSdlGraphicsManager::displayMessageOnOSD(const char *msg) {  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; @@ -2393,7 +2274,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) { @@ -2432,7 +2313,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; @@ -2464,7 +2345,7 @@ void SurfaceSdlGraphicsManager::updateOSD() {  				_osdMessageAlpha = startAlpha + diff * (SDL_ALPHA_TRANSPARENT - startAlpha) / kOSDFadeOutDuration;  			}  			SDL_SetAlpha(_osdMessageSurface, SDL_RLEACCEL | SDL_SRCCOLORKEY | SDL_SRCALPHA, _osdMessageAlpha); -			_forceFull = true; +			_forceRedraw = true;  		}  		if (_osdMessageAlpha == SDL_ALPHA_TRANSPARENT) { @@ -2474,26 +2355,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(); @@ -2505,13 +2390,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 @@ -2532,7 +2417,7 @@ bool SurfaceSdlGraphicsManager::handleScalerHotkeys(Common::KeyCode key) {  			displayMessageOnOSD(_("Filtering disabled"));  		}  #endif -		_forceFull = true; +		_forceRedraw = true;  		internUpdateScreen();  		return true;  	} @@ -2542,12 +2427,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  		}  	} @@ -2585,10 +2477,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; @@ -2700,37 +2601,11 @@ bool SurfaceSdlGraphicsManager::notifyEvent(const Common::Event &event) {  }  void SurfaceSdlGraphicsManager::notifyVideoExpose() { -	_forceFull = true; +	_forceRedraw = true;  } -void SurfaceSdlGraphicsManager::notifyResize(const uint width, const uint height) { -#if SDL_VERSION_ATLEAST(2, 0, 0) -	setWindowResolution(width, height); -#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; -		if (_videoMode.aspectRatioCorrection) -			point.y = aspect2Real(point.y); -	} -} - -void SurfaceSdlGraphicsManager::notifyMousePos(Common::Point mouse) { -	transformMouseCoordinates(mouse); -	setMousePos(mouse.x, mouse.y); +void SurfaceSdlGraphicsManager::notifyResize(const int width, const int height) { +	handleResize(width, height);  }  #if SDL_VERSION_ATLEAST(2, 0, 0) @@ -2742,39 +2617,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; @@ -2792,10 +2634,7 @@ 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;  	} @@ -2810,8 +2649,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"); @@ -2833,8 +2672,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 62a4a38d3e..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,8 +171,11 @@ 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; @@ -197,10 +184,7 @@ protected:  	 * 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); @@ -209,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;  	/** @@ -227,7 +211,6 @@ protected:  	SDL_Surface *_tmpscreen2;  	SDL_Surface *_overlayscreen; -	bool _overlayVisible;  	Graphics::PixelFormat _overlayFormat;  	enum { @@ -289,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; @@ -317,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; @@ -335,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; @@ -395,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 diff --git a/backends/graphics/symbiansdl/symbiansdl-graphics.cpp b/backends/graphics/symbiansdl/symbiansdl-graphics.cpp index c17cfd5efa..227674f811 100644 --- a/backends/graphics/symbiansdl/symbiansdl-graphics.cpp +++ b/backends/graphics/symbiansdl/symbiansdl-graphics.cpp @@ -50,7 +50,7 @@ bool SymbianSdlGraphicsManager::setGraphicsMode(int /*name*/) {  	return SurfaceSdlGraphicsManager::setGraphicsMode(getDefaultGraphicsMode());  } -bool SymbianSdlGraphicsManager::hasFeature(OSystem::Feature f) { +bool SymbianSdlGraphicsManager::hasFeature(OSystem::Feature f) const {  	switch (f) {  	case OSystem::kFeatureFullscreenMode:  	case OSystem::kFeatureAspectRatioCorrection: diff --git a/backends/graphics/symbiansdl/symbiansdl-graphics.h b/backends/graphics/symbiansdl/symbiansdl-graphics.h index fb9a49a834..0fcfb70f24 100644 --- a/backends/graphics/symbiansdl/symbiansdl-graphics.h +++ b/backends/graphics/symbiansdl/symbiansdl-graphics.h @@ -30,12 +30,12 @@ public:  	SymbianSdlGraphicsManager(SdlEventSource *sdlEventSource, SdlWindow *window);  public: -	virtual bool hasFeature(OSystem::Feature f); -	virtual void setFeatureState(OSystem::Feature f, bool enable); +	virtual bool hasFeature(OSystem::Feature f) const override; +	virtual void setFeatureState(OSystem::Feature f, bool enable) override; -	virtual const OSystem::GraphicsMode *getSupportedGraphicsModes() const; -	virtual int getDefaultGraphicsMode() const; -	virtual bool setGraphicsMode(int mode); +	virtual const OSystem::GraphicsMode *getSupportedGraphicsModes() const override; +	virtual int getDefaultGraphicsMode() const override; +	virtual bool setGraphicsMode(int mode) override;  };  #endif diff --git a/backends/graphics/wincesdl/wincesdl-graphics.cpp b/backends/graphics/wincesdl/wincesdl-graphics.cpp index 44a1214a44..1677ecac06 100644 --- a/backends/graphics/wincesdl/wincesdl-graphics.cpp +++ b/backends/graphics/wincesdl/wincesdl-graphics.cpp @@ -115,7 +115,7 @@ const OSystem::GraphicsMode *WINCESdlGraphicsManager::getSupportedGraphicsModes(  		return s_supportedGraphicsModesLow;  } -bool WINCESdlGraphicsManager::hasFeature(OSystem::Feature f) { +bool WINCESdlGraphicsManager::hasFeature(OSystem::Feature f) const {  	return (f == OSystem::kFeatureVirtualKeyboard);  } @@ -153,7 +153,7 @@ void WINCESdlGraphicsManager::setFeatureState(OSystem::Feature f, bool enable) {  	}  } -bool WINCESdlGraphicsManager::getFeatureState(OSystem::Feature f) { +bool WINCESdlGraphicsManager::getFeatureState(OSystem::Feature f) const {  	switch (f) {  	case OSystem::kFeatureFullscreenMode:  		return false; diff --git a/backends/graphics/wincesdl/wincesdl-graphics.h b/backends/graphics/wincesdl/wincesdl-graphics.h index 9316c69e44..4842d49023 100644 --- a/backends/graphics/wincesdl/wincesdl-graphics.h +++ b/backends/graphics/wincesdl/wincesdl-graphics.h @@ -46,9 +46,9 @@ public:  	const OSystem::GraphicsMode *getSupportedGraphicsModes() const;  	void initSize(uint w, uint h, const Graphics::PixelFormat *format = NULL); -	bool hasFeature(OSystem::Feature f); +	bool hasFeature(OSystem::Feature f) const;  	void setFeatureState(OSystem::Feature f, bool enable); -	bool getFeatureState(OSystem::Feature f); +	bool getFeatureState(OSystem::Feature f) const;  	int getDefaultGraphicsMode() const;  	bool setGraphicsMode(int mode); diff --git a/backends/graphics/windowed.h b/backends/graphics/windowed.h new file mode 100644 index 0000000000..1d4958c9d6 --- /dev/null +++ b/backends/graphics/windowed.h @@ -0,0 +1,337 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef BACKENDS_GRAPHICS_WINDOWED_H +#define BACKENDS_GRAPHICS_WINDOWED_H + +#include "backends/graphics/graphics.h" +#include "common/frac.h" +#include "common/rect.h" +#include "common/textconsole.h" +#include "graphics/scaler/aspect.h" + +class WindowedGraphicsManager : virtual public GraphicsManager { +public: +	WindowedGraphicsManager() : +		_windowWidth(0), +		_windowHeight(0), +		_overlayVisible(false), +		_forceRedraw(false), +		_cursorVisible(false), +		_cursorX(0), +		_cursorY(0), +		_cursorNeedsRedraw(false), +		_cursorLastInActiveArea(true) {} + +	virtual void showOverlay() override { +		if (_overlayVisible) +			return; + +		_activeArea.drawRect = _overlayDrawRect; +		_activeArea.width = getOverlayWidth(); +		_activeArea.height = getOverlayHeight(); +		_overlayVisible = true; +		_forceRedraw = true; +	} + +	virtual void hideOverlay() override { +		if (!_overlayVisible) +			return; + +		_activeArea.drawRect = _gameDrawRect; +		_activeArea.width = getWidth(); +		_activeArea.height = getHeight(); +		_overlayVisible = false; +		_forceRedraw = true; +	} + +protected: +	/** +	 * @returns whether or not the game screen must have aspect ratio correction +	 * applied for correct rendering. +	 */ +	virtual bool gameNeedsAspectRatioCorrection() const = 0; + +	/** +	 * Backend-specific implementation for updating internal surfaces that need +	 * to reflect the new window size. +	 */ +	virtual void handleResizeImpl(const int width, const int height) = 0; + +	/** +	 * Converts the given point from the active virtual screen's coordinate +	 * space to the window's coordinate space (i.e. game-to-window or +	 * overlay-to-window). +	 */ +	Common::Point convertVirtualToWindow(const int x, const int y) const { +		const int targetX = _activeArea.drawRect.left; +		const int targetY = _activeArea.drawRect.top; +		const int targetWidth = _activeArea.drawRect.width(); +		const int targetHeight = _activeArea.drawRect.height(); +		const int sourceWidth = _activeArea.width; +		const int sourceHeight = _activeArea.height; + +		if (sourceWidth == 0 || sourceHeight == 0) { +			error("convertVirtualToWindow called without a valid draw rect"); +		} + +		return Common::Point(targetX + x * targetWidth / sourceWidth, +							 targetY + y * targetHeight / sourceHeight); +	} + +	/** +	 * Converts the given point from the window's coordinate space to the +	 * active virtual screen's coordinate space (i.e. window-to-game or +	 * window-to-overlay). +	 */ +	Common::Point convertWindowToVirtual(int x, int y) const { +		const int sourceX = _activeArea.drawRect.left; +		const int sourceY = _activeArea.drawRect.top; +		const int sourceMaxX = _activeArea.drawRect.right - 1; +		const int sourceMaxY = _activeArea.drawRect.bottom - 1; +		const int sourceWidth = _activeArea.drawRect.width(); +		const int sourceHeight = _activeArea.drawRect.height(); +		const int targetWidth = _activeArea.width; +		const int targetHeight = _activeArea.height; + +		if (sourceWidth == 0 || sourceHeight == 0) { +			error("convertWindowToVirtual called without a valid draw rect"); +		} + +		x = CLIP<int>(x, sourceX, sourceMaxX); +		y = CLIP<int>(y, sourceY, sourceMaxY); + +		return Common::Point(((x - sourceX) * targetWidth) / sourceWidth, +							 ((y - sourceY) * targetHeight) / sourceHeight); +	} + +	/** +	 * @returns the desired aspect ratio of the game surface. +	 */ +	frac_t getDesiredGameAspectRatio() const { +		if (getHeight() == 0 || gameNeedsAspectRatioCorrection()) { +			return intToFrac(4) / 3; +		} + +		return intToFrac(getWidth()) / getHeight(); +	} + +	/** +	 * Called after the window has been updated with new dimensions. +	 * +	 * @param width The new width of the window, excluding window decoration. +	 * @param height The new height of the window, excluding window decoration. +	 */ +	void handleResize(const int width, const int height) { +		_windowWidth = width; +		_windowHeight = height; +		handleResizeImpl(width, height); +	} + +	/** +	 * Recalculates the display areas for the game and overlay surfaces within +	 * the window. +	 */ +	virtual void recalculateDisplayAreas() { +		if (_windowHeight == 0) { +			return; +		} + +		const frac_t outputAspect = intToFrac(_windowWidth) / _windowHeight; + +		populateDisplayAreaDrawRect(getDesiredGameAspectRatio(), outputAspect, _gameDrawRect); + +		if (getOverlayHeight()) { +			const frac_t overlayAspect = intToFrac(getOverlayWidth()) / getOverlayHeight(); +			populateDisplayAreaDrawRect(overlayAspect, outputAspect, _overlayDrawRect); +		} + +		if (_overlayVisible) { +			_activeArea.drawRect = _overlayDrawRect; +			_activeArea.width = getOverlayWidth(); +			_activeArea.height = getOverlayHeight(); +		} else { +			_activeArea.drawRect = _gameDrawRect; +			_activeArea.width = getWidth(); +			_activeArea.height = getHeight(); +		} +	} +	/** +	 * Sets the position of the hardware mouse cursor in the host system, +	 * relative to the window. +	 * +	 * @param x X coordinate in window coordinates. +	 * @param y Y coordinate in window coordinates. +	 */ +	virtual void setSystemMousePosition(const int x, const int y) = 0; + +	virtual bool showMouse(const bool visible) override { +		if (_cursorVisible == visible) { +			return visible; +		} + +		const bool last = _cursorVisible; +		_cursorVisible = visible; +		_cursorNeedsRedraw = true; +		return last; +	} + +	/** +	 * Move ("warp") the mouse cursor to the specified position. +	 * +	 * @param x	The new X position of the mouse in virtual screen coordinates. +	 * @param y	The new Y position of the mouse in virtual screen coordinates. +	 */ +	void warpMouse(const int x, const int y) { +		// Check active coordinate instead of window coordinate to avoid warping +		// the mouse if it is still within the same virtual pixel +		const Common::Point virtualCursor = convertWindowToVirtual(_cursorX, _cursorY); +		if (virtualCursor.x != x || virtualCursor.y != y) { +			// Warping the mouse in SDL generates a mouse movement event, so +			// `setMousePosition` would be called eventually through the +			// `notifyMousePosition` callback if we *only* set the system mouse +			// position here. However, this can cause problems with some games. +			// For example, the cannon script in CoMI calls to warp the mouse +			// twice each time the cannon is reloaded, and unless we update the +			// mouse position immediately, the second call is ignored, which +			// causes the cannon to change its aim. +			const Common::Point windowCursor = convertVirtualToWindow(x, y); +			setMousePosition(windowCursor.x, windowCursor.y); +			setSystemMousePosition(windowCursor.x, windowCursor.y); +		} +	} + +	/** +	 * Sets the position of the rendered mouse cursor in the window. +	 * +	 * @param x X coordinate in window coordinates. +	 * @param y Y coordinate in window coordinates. +	 */ +	void setMousePosition(int x, int y) { +		if (_cursorX != x || _cursorY != y) { +			_cursorNeedsRedraw = true; +		} + +		_cursorX = x; +		_cursorY = y; +	} + +	/** +	 * The width of the window, excluding window decoration. +	 */ +	int _windowWidth; + +	/** +	 * The height of the window, excluding window decoration. +	 */ +	int _windowHeight; + +	/** +	 * Whether the overlay (i.e. launcher, including the out-of-game launcher) +	 * is visible or not. +	 */ +	bool _overlayVisible; + +	/** +	 * The scaled draw rectangle for the game surface within the window. +	 */ +	Common::Rect _gameDrawRect; + +	/** +	 * The scaled draw rectangle for the overlay (launcher) surface within the +	 * window. +	 */ +	Common::Rect _overlayDrawRect; + +	/** +	 * Data about the display area of a virtual screen. +	 */ +	struct DisplayArea { +		/** +		 * The scaled area where the virtual screen is drawn within the window. +		 */ +		Common::Rect drawRect; + +		/** +		 * The width of the virtual screen's unscaled coordinate space. +		 */ +		int width; + +		/** +		 * The height of the virtual screen's unscaled coordinate space. +		 */ +		int height; +	}; + +	/** +	 * Display area information about the currently active virtual screen. This +	 * will be the overlay screen when the overlay is active, and the game +	 * screen otherwise. +	 */ +	DisplayArea _activeArea; + +	/** +	 * Whether the screen must be redrawn on the next frame. +	 */ +	bool _forceRedraw; + +	/** +	 * Whether the cursor is actually visible. +	 */ +	bool _cursorVisible; + +	/** +	 * Whether the mouse cursor needs to be redrawn on the next frame. +	 */ +	bool _cursorNeedsRedraw; + +	/** +	 * Whether the last position of the system cursor was within the active area +	 * of the window. +	 */ +	bool _cursorLastInActiveArea; + +	/** +	 * The position of the mouse cursor, in window coordinates. +	 */ +	int _cursorX, _cursorY; + +private: +	void populateDisplayAreaDrawRect(const frac_t inputAspect, const frac_t outputAspect, Common::Rect &drawRect) const { +		int width = _windowWidth; +		int height = _windowHeight; + +		// Maintain aspect ratios +		if (outputAspect < inputAspect) { +			height = intToFrac(width) / inputAspect; +		} else if (outputAspect > inputAspect) { +			width = fracToInt(height * inputAspect); +		} + +		drawRect.left = (_windowWidth - width) / 2; +		drawRect.top = (_windowHeight - height) / 2; +		drawRect.setWidth(width); +		drawRect.setHeight(height); +	} +}; + +#endif diff --git a/backends/modular-backend.cpp b/backends/modular-backend.cpp index c9adbd3100..944ddd5a47 100644 --- a/backends/modular-backend.cpp +++ b/backends/modular-backend.cpp @@ -217,6 +217,7 @@ bool ModularBackend::showMouse(bool visible) {  }  void ModularBackend::warpMouse(int x, int y) { +	_eventManager->purgeMouseEvents();  	_graphicsManager->warpMouse(x, y);  } diff --git a/backends/platform/sdl/sdl-window.cpp b/backends/platform/sdl/sdl-window.cpp index 75cf813638..fe27d84de2 100644 --- a/backends/platform/sdl/sdl-window.cpp +++ b/backends/platform/sdl/sdl-window.cpp @@ -135,8 +135,10 @@ void SdlWindow::toggleMouseGrab() {  #else  	if (SDL_WM_GrabInput(SDL_GRAB_QUERY) == SDL_GRAB_OFF) {  		SDL_WM_GrabInput(SDL_GRAB_ON); +		_inputGrabState = true;  	} else {  		SDL_WM_GrabInput(SDL_GRAB_OFF); +		_inputGrabState = false;  	}  #endif  } @@ -153,14 +155,20 @@ bool SdlWindow::hasMouseFocus() const {  #endif  } -void SdlWindow::warpMouseInWindow(uint x, uint y) { +bool SdlWindow::warpMouseInWindow(int x, int y) { +	if (hasMouseFocus()) {  #if SDL_VERSION_ATLEAST(2, 0, 0) -	if (_window && hasMouseFocus()) { -		SDL_WarpMouseInWindow(_window, x, y); -	} +		if (_window) { +			SDL_WarpMouseInWindow(_window, x, y); +			return true; +		}  #else -	SDL_WarpMouse(x, y); +		SDL_WarpMouse(x, y); +		return true;  #endif +	} + +	return false;  }  void SdlWindow::iconifyWindow() { diff --git a/backends/platform/sdl/sdl-window.h b/backends/platform/sdl/sdl-window.h index d75e811f56..e1a3499d19 100644 --- a/backends/platform/sdl/sdl-window.h +++ b/backends/platform/sdl/sdl-window.h @@ -56,9 +56,12 @@ public:  	bool hasMouseFocus() const;  	/** -	 * Warp the mouse to the specified position in window coordinates. +	 * Warp the mouse to the specified position in window coordinates. The mouse +	 * will only be warped if the window is focused in the window manager. +	 * +	 * @returns true if the system cursor was warped.  	 */ -	void warpMouseInWindow(uint x, uint y); +	bool warpMouseInWindow(int x, int y);  	/**  	 * Iconifies the window. @@ -73,6 +76,11 @@ public:  	 */  	bool getSDLWMInformation(SDL_SysWMinfo *info) const; +	bool mouseIsGrabbed() const { return _inputGrabState; } + +private: +	bool _inputGrabState; +  #if SDL_VERSION_ATLEAST(2, 0, 0)  public:  	/** @@ -108,7 +116,6 @@ private:  	 */  	int _lastX, _lastY; -	bool _inputGrabState;  	Common::String _windowCaption;  #endif  }; diff --git a/common/events.h b/common/events.h index 21a65a642b..e5bb8cab50 100644 --- a/common/events.h +++ b/common/events.h @@ -395,6 +395,11 @@ public:  	 */  	virtual void pushEvent(const Event &event) = 0; +	/** +	 * Purges all unprocessed mouse events already in the event queue. +	 */ +	virtual void purgeMouseEvents() = 0; +  	/** Return the current mouse position */  	virtual Point getMousePos() const = 0; diff --git a/graphics/cursorman.cpp b/graphics/cursorman.cpp index 5fcd2a3602..678b074360 100644 --- a/graphics/cursorman.cpp +++ b/graphics/cursorman.cpp @@ -65,9 +65,7 @@ void CursorManager::pushCursor(const void *buf, uint w, uint h, int hotspotX, in  	cur->_visible = isVisible();  	_cursorStack.push(cur); -	if (buf) { -		g_system->setMouseCursor(cur->_data, w, h, hotspotX, hotspotY, keycolor, dontScale, format); -	} +	g_system->setMouseCursor(cur->_data, w, h, hotspotX, hotspotY, keycolor, dontScale, format);  }  void CursorManager::popCursor() { @@ -80,6 +78,8 @@ void CursorManager::popCursor() {  	if (!_cursorStack.empty()) {  		cur = _cursorStack.top();  		g_system->setMouseCursor(cur->_data, cur->_width, cur->_height, cur->_hotspotX, cur->_hotspotY, cur->_keycolor, cur->_dontScale, &cur->_format); +	} else { +		g_system->setMouseCursor(nullptr, 0, 0, 0, 0, 0);  	}  	g_system->showMouse(isVisible()); @@ -99,6 +99,7 @@ void CursorManager::popAllCursors() {  		}  	} +	g_system->setMouseCursor(nullptr, 0, 0, 0, 0, 0);  	g_system->showMouse(isVisible());  } diff --git a/graphics/palette.h b/graphics/palette.h index 2884bef7f4..0b9b861aa9 100644 --- a/graphics/palette.h +++ b/graphics/palette.h @@ -96,7 +96,7 @@ public:  	 *  	 * @see getScreenFormat  	 */ -	virtual void grabPalette(byte *colors, uint start, uint num) = 0; +	virtual void grabPalette(byte *colors, uint start, uint num) const = 0;  };  #endif | 
