[Scummvm-git-logs] scummvm master -> ce68acff93c156deeea0b4c635db17500b7098b5

lephilousophe noreply at scummvm.org
Sun Jun 15 11:22:35 UTC 2025


This automated email contains information about 5 new commits which have been
pushed to the 'scummvm' repo located at https://api.github.com/repos/scummvm/scummvm .

Summary:
1d89f4fcdd GRAPHICS: Add texture rotation support
9cba65100a BACKENDS: GRAPHICS: Fix rotation mouse mapping
fcd7c66497 BACKENDS: OPENGL: Fix screen rotation
3f7d37b03f COMMON: Make rotation mode fit other settings semantics
ce68acff93 BACKENDS: Avoid double call of getOverlayWidth/Height


Commit: 1d89f4fcdd235276efd8195410a4f95573da2163
    https://github.com/scummvm/scummvm/commit/1d89f4fcdd235276efd8195410a4f95573da2163
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2025-06-15T13:22:31+02:00

Commit Message:
GRAPHICS: Add texture rotation support

Also make flip parameter separate from size.

Changed paths:
    backends/graphics/opengl/renderer3d.cpp
    graphics/opengl/texture.cpp
    graphics/opengl/texture.h


diff --git a/backends/graphics/opengl/renderer3d.cpp b/backends/graphics/opengl/renderer3d.cpp
index 64590899d77..cfdad82519d 100644
--- a/backends/graphics/opengl/renderer3d.cpp
+++ b/backends/graphics/opengl/renderer3d.cpp
@@ -48,6 +48,7 @@ Renderer3D::Renderer3D() :
 	_samples(0), _stackLevel(0), _inOverlay(false),
 	_pendingScreenChangeWidth(-1), _pendingScreenChangeHeight(-1) {
 	_texture.enableLinearFiltering(true);
+	_texture.setFlip(true);
 }
 
 void Renderer3D::destroy() {
@@ -78,7 +79,7 @@ void Renderer3D::initSize(uint w, uint h, int samples, bool renderToFrameBuffer)
 		return;
 	}
 
-	_texture.setSize(w, h, true);
+	_texture.setSize(w, h);
 	recreate();
 }
 
@@ -98,7 +99,7 @@ void Renderer3D::resize(uint w, uint h) {
 		return;
 	}
 
-	_texture.setSize(w, h, true);
+	_texture.setSize(w, h);
 	setup();
 
 	// Rebind the framebuffer
@@ -428,7 +429,7 @@ void Renderer3D::showOverlay(uint w, uint h) {
 	}
 
 	_texture.create();
-	_texture.setSize(w, h, true);
+	_texture.setSize(w, h);
 	Graphics::Surface background;
 	background.create(w, h, Texture::getRGBAPixelFormat());
 	glReadPixels(0, 0, background.w, background.h, GL_RGBA, GL_UNSIGNED_BYTE, background.getPixels());
diff --git a/graphics/opengl/texture.cpp b/graphics/opengl/texture.cpp
index 6cc30733eec..150e6126a3f 100644
--- a/graphics/opengl/texture.cpp
+++ b/graphics/opengl/texture.cpp
@@ -36,8 +36,8 @@ namespace OpenGL {
 Texture::Texture(GLenum glIntFormat, GLenum glFormat, GLenum glType, bool autoCreate)
 	: _glIntFormat(glIntFormat), _glFormat(glFormat), _glType(glType),
 	  _width(0), _height(0), _logicalWidth(0), _logicalHeight(0),
-	  _texCoords(), _glFilter(GL_NEAREST),
-	  _glTexture(0) {
+	  _flip(false), _rotation(Common::kRotationNormal),
+	  _texCoords(), _glFilter(GL_NEAREST), _glTexture(0) {
 	if (autoCreate)
 		create();
 }
@@ -150,7 +150,7 @@ bool Texture::bind() const {
 	return true;
 }
 
-bool Texture::setSize(uint width, uint height, bool flip) {
+bool Texture::setSize(uint width, uint height) {
 	const uint oldWidth  = _width;
 	const uint oldHeight = _height;
 
@@ -167,34 +167,7 @@ bool Texture::setSize(uint width, uint height, bool flip) {
 
 	// If a size is specified, allocate memory for it.
 	if (width != 0 && height != 0) {
-		const GLfloat texWidth = (GLfloat)width / _width;
-		const GLfloat texHeight = (GLfloat)height / _height;
-
-		if (flip) {
-			_texCoords[0] = 0;
-			_texCoords[1] = texHeight;
-
-			_texCoords[2] = texWidth;
-			_texCoords[3] = texHeight;
-
-			_texCoords[4] = 0;
-			_texCoords[5] = 0;
-
-			_texCoords[6] = texWidth;
-			_texCoords[7] = 0;
-		} else {
-			_texCoords[0] = 0;
-			_texCoords[1] = 0;
-
-			_texCoords[2] = texWidth;
-			_texCoords[3] = 0;
-
-			_texCoords[4] = 0;
-			_texCoords[5] = texHeight;
-
-			_texCoords[6] = texWidth;
-			_texCoords[7] = texHeight;
-		}
+		computeTexCoords();
 
 		// Allocate storage for OpenGL texture if necessary.
 		if (oldWidth != _width || oldHeight != _height) {
@@ -213,6 +186,66 @@ bool Texture::setSize(uint width, uint height, bool flip) {
 	return true;
 }
 
+void Texture::computeTexCoords() {
+	const GLfloat texWidth = (GLfloat)_logicalWidth / _width;
+	const GLfloat texHeight = (GLfloat)_logicalHeight / _height;
+
+	if (_flip) {
+		_texCoords[0] = 0;
+		_texCoords[1] = texHeight;
+
+		_texCoords[2] = texWidth;
+		_texCoords[3] = texHeight;
+
+		_texCoords[4] = 0;
+		_texCoords[5] = 0;
+
+		_texCoords[6] = texWidth;
+		_texCoords[7] = 0;
+	} else {
+		_texCoords[0] = 0;
+		_texCoords[1] = 0;
+
+		_texCoords[2] = texWidth;
+		_texCoords[3] = 0;
+
+		_texCoords[4] = 0;
+		_texCoords[5] = texHeight;
+
+		_texCoords[6] = texWidth;
+		_texCoords[7] = texHeight;
+	}
+
+	switch(_rotation) {
+	default:
+	case Common::kRotationNormal:
+		// Nothing to do
+		break;
+	case Common::kRotation90:
+		// LT -> LB and RB -> RT
+		SWAP(_texCoords[1], _texCoords[7]);
+		// RT -> LT and LB -> RB
+		SWAP(_texCoords[2], _texCoords[4]);
+		break;
+	case Common::kRotation180:
+		// LT -> RT and RT -> LT
+		SWAP(_texCoords[0], _texCoords[2]);
+		// RT -> RB and LB -> LT
+		SWAP(_texCoords[1], _texCoords[5]);
+		// LT -> LB and RB -> RT
+		SWAP(_texCoords[3], _texCoords[7]);
+		// LT -> RT and RT -> LT
+		SWAP(_texCoords[4], _texCoords[6]);
+		break;
+	case Common::kRotation270:
+		// LT -> RT and RB -> LB
+		SWAP(_texCoords[0], _texCoords[6]);
+		// RT -> RB and LB -> LT
+		SWAP(_texCoords[3], _texCoords[5]);
+		break;
+	}
+}
+
 void Texture::updateArea(const Common::Rect &area, const Graphics::Surface &src) {
 	// Set the texture on the active texture unit.
 	if (!bind()) {
diff --git a/graphics/opengl/texture.h b/graphics/opengl/texture.h
index 93c7193948b..866b3b00909 100644
--- a/graphics/opengl/texture.h
+++ b/graphics/opengl/texture.h
@@ -29,6 +29,7 @@
 #include "graphics/surface.h"
 
 #include "common/rect.h"
+#include "common/rotationmode.h"
 
 namespace OpenGL {
 
@@ -100,10 +101,23 @@ public:
 	 *
 	 * @param width  The desired logical width.
 	 * @param height The desired logical height.
-	 * @param flip   Whether to flip vertically the texture when displaying it.
 	 * @return Whether the call was successful
 	 */
-	bool setSize(uint width, uint height, bool flip = false);
+	bool setSize(uint width, uint height);
+
+	/**
+	 * Sets the flip and rotate parameters of the texture
+	 *
+	 * @param flip     Whether to flip vertically the texture when displaying it.
+	 */
+	void setFlip(bool flip) { if (_flip != flip) { _flip = flip; computeTexCoords(); } }
+
+	/**
+	 * Sets the rotate parameter of the texture
+	 *
+	 * @param rotation How to rotate the texture
+	 */
+	void setRotation(Common::RotationMode rotation) { if (_rotation != rotation) { _rotation = rotation; computeTexCoords(); } }
 
 	/**
 	 * Copy image data to the texture.
@@ -173,12 +187,17 @@ public:
 	}
 
 protected:
+	void computeTexCoords();
+
 	const GLenum _glIntFormat;
 	const GLenum _glFormat;
 	const GLenum _glType;
 
 	uint _width, _height;
 	uint _logicalWidth, _logicalHeight;
+	bool _flip;
+	Common::RotationMode _rotation;
+
 	GLfloat _texCoords[4*2];
 
 	GLint _glFilter;


Commit: 9cba65100ac7c8d7819f77b477a53baa0a4f5ca4
    https://github.com/scummvm/scummvm/commit/9cba65100ac7c8d7819f77b477a53baa0a4f5ca4
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2025-06-15T13:22:31+02:00

Commit Message:
BACKENDS: GRAPHICS: Fix rotation mouse mapping

The rotation is fully handled by the WindowedGraphicsManager including
for the mouse mapping.
The draw rect is always in window coordinates.

Changed paths:
    backends/graphics/sdl/sdl-graphics.cpp
    backends/graphics/surfacesdl/surfacesdl-graphics.cpp
    backends/graphics/windowed.h


diff --git a/backends/graphics/sdl/sdl-graphics.cpp b/backends/graphics/sdl/sdl-graphics.cpp
index 4a955fc0a45..0b1e41bc51d 100644
--- a/backends/graphics/sdl/sdl-graphics.cpp
+++ b/backends/graphics/sdl/sdl-graphics.cpp
@@ -255,28 +255,6 @@ bool SdlGraphicsManager::lockMouse(bool lock) {
 }
 
 bool SdlGraphicsManager::notifyMousePosition(Common::Point &mouse) {
-	switch (getRotationMode()) {
-	case Common::kRotationNormal:
-		break;
-	case Common::kRotation90: {
-		int x0 = mouse.x, y0 = mouse.y;
-		mouse.x = CLIP<int16>(y0, 0, _windowHeight - 1);
-		mouse.y = CLIP<int16>(_windowWidth - 1 - x0, 0, _windowWidth - 1);
-		break;
-	}
-	case Common::kRotation180: {
-		mouse.x = CLIP<int16>(_windowWidth - 1 - mouse.x, 0, _windowWidth - 1);
-		mouse.y = CLIP<int16>(_windowHeight - 1 - mouse.y, 0, _windowHeight - 1);
-		break;
-	}
-	case Common::kRotation270: {
-		int x0 = mouse.x, y0 = mouse.y;
-		mouse.x = CLIP<int16>(_windowHeight - 1 - y0, 0, _windowHeight - 1);
-		mouse.y = CLIP<int16>(x0, 0, _windowWidth - 1);
-		break;
-	}
-	}
-
 	bool showCursor = false;
 	// Currently on macOS we need to scale the events for HiDPI screen, but on
 	// Windows we do not. We can find out if we need to do it by querying the
diff --git a/backends/graphics/surfacesdl/surfacesdl-graphics.cpp b/backends/graphics/surfacesdl/surfacesdl-graphics.cpp
index 1c33ddf034a..7cd524df1ec 100644
--- a/backends/graphics/surfacesdl/surfacesdl-graphics.cpp
+++ b/backends/graphics/surfacesdl/surfacesdl-graphics.cpp
@@ -3230,20 +3230,23 @@ void SurfaceSdlGraphicsManager::SDL_UpdateRects(SDL_Surface *screen, int numrect
 	SDL_Rect viewport;
 
 	Common::Rect &drawRect = (_overlayVisible) ? _overlayDrawRect : _gameDrawRect;
-	viewport.x = drawRect.left;
-	viewport.y = drawRect.top;
+	Common::RotationMode rotation = getRotationMode();
 
-	int rotation = getRotationMode();
-	int rotangle = 0;
+	/* Destination rectangle represents the texture before rotation */
 	if (rotation == Common::kRotation90 || rotation == Common::kRotation270) {
-		int delta = (drawRect.width() - drawRect.height()) / 2;
-		viewport.x = drawRect.top - delta;
-		viewport.y = drawRect.left + delta;
+		viewport.w = drawRect.height();
+		viewport.h = drawRect.width();
+		int delta = (viewport.w - viewport.h) / 2;
+		viewport.x = drawRect.left - delta;
+		viewport.y = drawRect.top + delta;
+	} else {
+		viewport.w = drawRect.width();
+		viewport.h = drawRect.height();
+		viewport.x = drawRect.left;
+		viewport.y = drawRect.top;
 	}
-	rotangle = rotation;
 
-	viewport.w = drawRect.width();
-	viewport.h = drawRect.height();
+	int rotangle = (int)rotation;
 
 	SDL_RenderClear(_renderer);
 
diff --git a/backends/graphics/windowed.h b/backends/graphics/windowed.h
index e39177c8bdf..42821952206 100644
--- a/backends/graphics/windowed.h
+++ b/backends/graphics/windowed.h
@@ -145,8 +145,26 @@ protected:
 			error("convertVirtualToWindow called without a valid draw rect");
 		}
 
-		int windowX = targetX + (x * targetWidth + sourceWidth / 2) / sourceWidth;
-		int windowY = targetY + (y * targetHeight + sourceHeight / 2) / sourceHeight;
+		int windowX, windowY;
+		switch (getRotationMode()) {
+		default:
+		case Common::kRotationNormal:
+			windowX = targetX + (x * targetWidth + sourceWidth / 2) / sourceWidth;
+			windowY = targetY + (y * targetHeight + sourceHeight / 2) / sourceHeight;
+			break;
+		case Common::kRotation90:
+			windowX = targetX + ((y - (sourceHeight - 1)) * targetWidth + sourceHeight / 2) / sourceHeight;
+			windowY = targetY + (x * targetHeight + sourceWidth / 2) / sourceWidth;
+			break;
+		case Common::kRotation180:
+			windowX = targetX + ((x - (sourceWidth - 1)) * targetWidth + sourceWidth / 2) / sourceWidth;
+			windowY = targetY + ((y - (sourceHeight - 1)) * targetHeight + sourceHeight / 2) / sourceHeight;
+			break;
+		case Common::kRotation270:
+			windowX = targetX + (y * targetWidth + sourceHeight / 2) / sourceHeight;
+			windowY = targetY + ((x - (sourceWidth - 1)) * targetHeight + sourceWidth / 2) / sourceWidth;
+			break;
+		}
 
 		return Common::Point(CLIP<int>(windowX, targetX, targetX + targetWidth - 1),
 		                     CLIP<int>(windowY, targetY, targetY + targetHeight - 1));
@@ -174,8 +192,26 @@ protected:
 		x = CLIP<int>(x, sourceX, sourceMaxX);
 		y = CLIP<int>(y, sourceY, sourceMaxY);
 
-		int virtualX = ((x - sourceX) * targetWidth + sourceWidth / 2) / sourceWidth;
-		int virtualY = ((y - sourceY) * targetHeight + sourceHeight / 2) / sourceHeight;
+		int virtualX, virtualY;
+		switch (getRotationMode()) {
+		default:
+		case Common::kRotationNormal:
+			virtualX = ((x - sourceX) * targetWidth + sourceWidth / 2) / sourceWidth;
+			virtualY = ((y - sourceY) * targetHeight + sourceHeight / 2) / sourceHeight;
+			break;
+		case Common::kRotation90:
+			virtualY = targetHeight - 1 - ((x - sourceX) * targetHeight + sourceWidth / 2) / sourceWidth;
+			virtualX = ((y - sourceY) * targetWidth + sourceHeight / 2) / sourceHeight;
+			break;
+		case Common::kRotation180:
+			virtualX = targetWidth - 1 - ((x - sourceX) * targetWidth + sourceWidth / 2) / sourceWidth;
+			virtualY = targetHeight - 1 - ((y - sourceY) * targetHeight + sourceHeight / 2) / sourceHeight;
+			break;
+		case Common::kRotation270:
+			virtualY = ((x - sourceX) * targetHeight + sourceWidth / 2) / sourceWidth;
+			virtualX = targetWidth - 1 - ((y - sourceY) * targetWidth + sourceHeight / 2) / sourceHeight;
+			break;
+		}
 
 		return Common::Point(CLIP<int>(virtualX, 0, targetWidth - 1),
 		                     CLIP<int>(virtualY, 0, targetHeight - 1));
@@ -494,10 +530,20 @@ private:
 				break;
 		}
 
-		drawRect.left = alignX + _gameScreenShakeXOffset * width / getWidth();
-		drawRect.top = alignY + _gameScreenShakeYOffset * height / getHeight();
-		drawRect.setWidth(width);
-		drawRect.setHeight(height);
+		alignX += _gameScreenShakeXOffset * width / getWidth();
+		alignY += _gameScreenShakeYOffset * height / getHeight();
+
+		if (rotation == Common::kRotation90 || rotation == Common::kRotation270) {
+			drawRect.top = alignX;
+			drawRect.left = alignY;
+			drawRect.setWidth(height);
+			drawRect.setHeight(width);
+		} else {
+			drawRect.left = alignX;
+			drawRect.top = alignY;
+			drawRect.setWidth(width);
+			drawRect.setHeight(height);
+		}
 	}
 };
 


Commit: fcd7c6649797773bc93ecc6f7ad9f741603f50eb
    https://github.com/scummvm/scummvm/commit/fcd7c6649797773bc93ecc6f7ad9f741603f50eb
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2025-06-15T13:22:31+02:00

Commit Message:
BACKENDS: OPENGL: Fix screen rotation

This has only worked correctly in some specific cases (screen centered,
no shaders, ...).

Changed paths:
    backends/graphics/ios/renderbuffer.cpp
    backends/graphics/ios/renderbuffer.h
    backends/graphics/opengl/framebuffer.cpp
    backends/graphics/opengl/framebuffer.h
    backends/graphics/opengl/opengl-graphics.cpp
    backends/graphics/opengl/opengl-graphics.h
    backends/graphics/opengl/pipelines/libretro.cpp
    backends/graphics/opengl/pipelines/libretro.h
    backends/graphics/opengl/renderer3d.h
    backends/graphics/opengl/texture.cpp
    backends/graphics/opengl/texture.h


diff --git a/backends/graphics/ios/renderbuffer.cpp b/backends/graphics/ios/renderbuffer.cpp
index b4d2e08cc6a..9e568ad358f 100644
--- a/backends/graphics/ios/renderbuffer.cpp
+++ b/backends/graphics/ios/renderbuffer.cpp
@@ -53,7 +53,7 @@ void RenderbufferTarget::activateInternal() {
 	}
 }
 
-bool RenderbufferTarget::setSize(uint width, uint height, Common::RotationMode rotation) {
+bool RenderbufferTarget::setSize(uint width, uint height) {
 	// Set viewport dimensions.
 	_viewport[0] = 0;
 	_viewport[1] = 0;
diff --git a/backends/graphics/ios/renderbuffer.h b/backends/graphics/ios/renderbuffer.h
index 758672d7757..0047f9c2f1c 100644
--- a/backends/graphics/ios/renderbuffer.h
+++ b/backends/graphics/ios/renderbuffer.h
@@ -40,7 +40,7 @@ public:
 	/**
 	 * Set size of the render target.
 	 */
-	bool setSize(uint width, uint height, Common::RotationMode rotation) override;
+	bool setSize(uint width, uint height) override;
 
 protected:
 	void activateInternal() override;
diff --git a/backends/graphics/opengl/framebuffer.cpp b/backends/graphics/opengl/framebuffer.cpp
index f0d08630aa9..c3b373da163 100644
--- a/backends/graphics/opengl/framebuffer.cpp
+++ b/backends/graphics/opengl/framebuffer.cpp
@@ -189,7 +189,7 @@ void Backbuffer::activateInternal() {
 #endif
 }
 
-bool Backbuffer::setSize(uint width, uint height, Common::RotationMode rotation) {
+bool Backbuffer::setSize(uint width, uint height) {
 	// Set viewport dimensions.
 	_viewport[0] = 0;
 	_viewport[1] = 0;
@@ -217,41 +217,6 @@ bool Backbuffer::setSize(uint width, uint height, Common::RotationMode rotation)
 	_projectionMatrix(3, 2) =  0.0f;
 	_projectionMatrix(3, 3) =  1.0f;
 
-	switch (rotation) {
-	default:
-		_projectionMatrix(0, 0) =  2.0f / width;
-		_projectionMatrix(0, 1) =  0.0f;
-		_projectionMatrix(1, 0) =  0.0f;
-		_projectionMatrix(1, 1) = -2.0f / height;
-		_projectionMatrix(3, 0) = -1.0f;
-		_projectionMatrix(3, 1) =  1.0f;
-		break;
-	case Common::kRotation90:
-		_projectionMatrix(0, 0) =  0.0f;
-		_projectionMatrix(0, 1) =  -2.0f / height;
-		_projectionMatrix(1, 0) =  -2.0f / width;
-		_projectionMatrix(1, 1) =  0.0f;
-		_projectionMatrix(3, 0) =  1.0f;
-		_projectionMatrix(3, 1) =  1.0f;
-		break;
-	case Common::kRotation180:
-		_projectionMatrix(0, 0) =  -2.0f / width;
-		_projectionMatrix(0, 1) =  0.0f;
-		_projectionMatrix(1, 0) =  0.0f;
-		_projectionMatrix(1, 1) =  2.0f / height;
-		_projectionMatrix(3, 0) =  1.0f;
-		_projectionMatrix(3, 1) = -1.0f;
-		break;
-	case Common::kRotation270:
-		_projectionMatrix(0, 0) =  0.0f;
-		_projectionMatrix(0, 1) =  2.0f / height;
-		_projectionMatrix(1, 0) =  2.0f / width;
-		_projectionMatrix(1, 1) =  0.0f;
-		_projectionMatrix(3, 0) = -1.0f;
-		_projectionMatrix(3, 1) = -1.0f;
-		break;
-	}
-
 	// Directly apply changes when we are active.
 	if (isActive()) {
 		applyViewport();
@@ -304,7 +269,7 @@ void TextureTarget::create() {
 	_needUpdate = true;
 }
 
-bool TextureTarget::setSize(uint width, uint height, Common::RotationMode rotation) {
+bool TextureTarget::setSize(uint width, uint height) {
 	if (!_texture->setSize(width, height)) {
 		return false;
 	}
diff --git a/backends/graphics/opengl/framebuffer.h b/backends/graphics/opengl/framebuffer.h
index 445984034a4..c8029c7b1c2 100644
--- a/backends/graphics/opengl/framebuffer.h
+++ b/backends/graphics/opengl/framebuffer.h
@@ -149,7 +149,7 @@ public:
 	/**
 	 * Set the size of the target buffer.
 	 */
-	virtual bool setSize(uint width, uint height, Common::RotationMode rotation) = 0;
+	virtual bool setSize(uint width, uint height) = 0;
 
 	/**
 	 * Accessor to activate framebuffer for pipeline.
@@ -185,7 +185,7 @@ public:
 	/**
 	 * Set the size of the back buffer.
 	 */
-	bool setSize(uint width, uint height, Common::RotationMode rotation) override;
+	bool setSize(uint width, uint height) override;
 
 protected:
 	void activateInternal() override;
@@ -218,7 +218,7 @@ public:
 	/**
 	 * Set size of the texture target.
 	 */
-	bool setSize(uint width, uint height, Common::RotationMode rotation) override;
+	bool setSize(uint width, uint height) override;
 
 	/**
 	 * Query pointer to underlying GL texture.
diff --git a/backends/graphics/opengl/opengl-graphics.cpp b/backends/graphics/opengl/opengl-graphics.cpp
index d7fc3e1ec5b..349f63a3c31 100644
--- a/backends/graphics/opengl/opengl-graphics.cpp
+++ b/backends/graphics/opengl/opengl-graphics.cpp
@@ -632,7 +632,7 @@ OSystem::TransactionError OpenGLGraphicsManager::endGFXTransaction() {
 	// aspect ratio correction and game screen changes correctly.
 	recalculateDisplayAreas();
 	recalculateCursorScaling();
-	updateLinearFiltering();
+	updateTextureSettings();
 
 	// Something changed, so update the screen change ID.
 	++_screenChangeID;
@@ -722,15 +722,6 @@ void OpenGLGraphicsManager::renderCursor() {
 }
 
 void OpenGLGraphicsManager::updateScreen() {
-	int rotation = getRotationMode();
-	int rotatedWidth = _windowWidth;
-	int rotatedHeight = _windowHeight;
-
-	if (rotation == Common::kRotation90 || rotation == Common::kRotation270) {
-		rotatedWidth = _windowHeight;
-		rotatedHeight = _windowWidth;
-	}
-
 	if ((!_gameScreen
 #if defined(USE_OPENGL_GAME) || defined(USE_OPENGL_SHADERS)
 		&& !_renderer3d
@@ -852,8 +843,8 @@ void OpenGLGraphicsManager::updateScreen() {
 
 	// Third step: Draw the overlay if visible.
 	if (_overlayVisible) {
-		int dstX = (rotatedWidth - _overlayDrawRect.width()) / 2;
-		int dstY = (rotatedHeight - _overlayDrawRect.height()) / 2;
+		int dstX = (_windowWidth - _overlayDrawRect.width()) / 2;
+		int dstY = (_windowHeight - _overlayDrawRect.height()) / 2;
 		_targetBuffer->enableBlend(Framebuffer::kBlendModeTraditionalTransparency);
 		_pipeline->drawTexture(_overlay->getGLTexture(), dstX, dstY, _overlayDrawRect.width(), _overlayDrawRect.height());
 	}
@@ -873,6 +864,7 @@ void OpenGLGraphicsManager::updateScreen() {
 	}
 
 	if (_osdMessageSurface) {
+		Common::RotationMode rotationMode = getRotationMode();
 		// Update alpha value.
 		const int diff = g_system->getMillis(false) - _osdMessageFadeStartTime;
 		if (diff > 0) {
@@ -888,12 +880,18 @@ void OpenGLGraphicsManager::updateScreen() {
 		// Set the OSD transparency.
 		_pipeline->setColor(1.0f, 1.0f, 1.0f, _osdMessageAlpha / 100.0f);
 
-		int dstX = (rotatedWidth - _osdMessageSurface->getWidth()) / 2;
-		int dstY = (rotatedHeight - _osdMessageSurface->getHeight()) / 2;
+		int osdWidth = _osdMessageSurface->getWidth(),
+		    osdHeight = _osdMessageSurface->getHeight();
+		if (rotationMode == Common::kRotation90 || rotationMode == Common::kRotation270) {
+			SWAP(osdWidth, osdHeight);
+		}
+
+		int dstX = (_windowWidth - osdWidth) / 2;
+		int dstY = (_windowHeight - osdHeight) / 2;
 
 		// Draw the OSD texture.
 		_pipeline->drawTexture(_osdMessageSurface->getGLTexture(),
-		                                           dstX, dstY, _osdMessageSurface->getWidth(), _osdMessageSurface->getHeight());
+		                                           dstX, dstY, osdWidth, osdHeight);
 
 		// Reset color.
 		_pipeline->setColor(1.0f, 1.0f, 1.0f, 1.0f);
@@ -909,12 +907,35 @@ void OpenGLGraphicsManager::updateScreen() {
 	}
 
 	if (_osdIconSurface) {
-		int dstX = rotatedWidth - _osdIconSurface->getWidth() - kOSDIconRightMargin;
-		int dstY = kOSDIconTopMargin;
+		Common::RotationMode rotationMode = getRotationMode();
+		int osdWidth = _osdIconSurface->getWidth(),
+		    osdHeight = _osdIconSurface->getHeight();
+		int dstX, dstY;
+		switch (rotationMode) {
+		default:
+		case Common::kRotationNormal:
+			dstX = _windowWidth - osdWidth - kOSDIconRightMargin;
+			dstY = kOSDIconTopMargin;
+			break;
+		case Common::kRotation90:
+			SWAP(osdWidth, osdHeight);
+			dstX = _windowWidth - osdWidth - kOSDIconTopMargin;
+			dstY = _windowHeight - osdHeight - kOSDIconRightMargin;
+			break;
+		case Common::kRotation180:
+			dstX = kOSDIconRightMargin;
+			dstY = _windowHeight - osdHeight - kOSDIconTopMargin;
+			break;
+		case Common::kRotation270:
+			SWAP(osdWidth, osdHeight);
+			dstX = kOSDIconTopMargin;
+			dstY = kOSDIconRightMargin;
+			break;
+		}
 
 		// Draw the OSD icon texture.
 		_pipeline->drawTexture(_osdIconSurface->getGLTexture(),
-		                       dstX, dstY, _osdIconSurface->getWidth(), _osdIconSurface->getHeight());
+		                       dstX, dstY, osdWidth, osdHeight);
 	}
 #endif
 
@@ -1102,7 +1123,7 @@ void OpenGLGraphicsManager::setMouseCursor(const void *buf, uint w, uint h, int
 		_cursor = createSurface(textureFormat, true, wantScaler, wantMask);
 		assert(_cursor);
 
-		updateLinearFiltering();
+		updateTextureSettings();
 
 #ifdef USE_SCALERS
 		if (wantScaler) {
@@ -1117,7 +1138,7 @@ void OpenGLGraphicsManager::setMouseCursor(const void *buf, uint w, uint h, int
 			_cursorMask = createSurface(maskFormat, true, wantScaler);
 			assert(_cursorMask);
 
-			updateLinearFiltering();
+			updateTextureSettings();
 
 #ifdef USE_SCALERS
 			if (wantScaler) {
@@ -1333,6 +1354,7 @@ void OpenGLGraphicsManager::osdMessageUpdateSurface() {
 	// readable in case it needs to be scaled and does not affect it
 	// otherwise.
 	_osdMessageSurface->enableLinearFiltering(true);
+	_osdMessageSurface->setRotation(getRotationMode());
 
 	_osdMessageSurface->allocate(width, height);
 
@@ -1391,6 +1413,7 @@ void OpenGLGraphicsManager::displayActivityIconOnOSD(const Graphics::Surface *ic
 		// readable in case it needs to be scaled and does not affect it
 		// otherwise.
 		_osdIconSurface->enableLinearFiltering(true);
+		_osdIconSurface->setRotation(getRotationMode());
 
 		_osdIconSurface->allocate(converted->w, converted->h);
 
@@ -1425,7 +1448,7 @@ void OpenGLGraphicsManager::grabPalette(byte *colors, uint start, uint num) cons
 
 void OpenGLGraphicsManager::handleResizeImpl(const int width, const int height) {
 	// Setup backbuffer size.
-	_targetBuffer->setSize(width, height, getRotationMode());
+	_targetBuffer->setSize(width, height);
 
 	int rotation = getRotationMode();
 	uint overlayWidth = width;
@@ -1480,7 +1503,7 @@ void OpenGLGraphicsManager::handleResizeImpl(const int width, const int height)
 	// Re-setup the scaling and filtering for the screen and cursor
 	recalculateDisplayAreas();
 	recalculateCursorScaling();
-	updateLinearFiltering();
+	updateTextureSettings();
 
 	// Something changed, so update the screen change ID.
 	++_screenChangeID;
@@ -1851,24 +1874,19 @@ void OpenGLGraphicsManager::recalculateDisplayAreas() {
 	// Setup drawing limitation for game graphics.
 	// This involves some trickery because OpenGL's viewport coordinate system
 	// is upside down compared to ours.
-	switch (getRotationMode()) {
-	case Common::kRotation90:
-	case Common::kRotation180:
-		_targetBuffer->setScissorBox(_gameDrawRect.top,
-					     _gameDrawRect.left,
-					     _gameDrawRect.height(),
-					     _gameDrawRect.width());
-		break;
-	default:
-		_targetBuffer->setScissorBox(_gameDrawRect.left,
-					     _windowHeight - _gameDrawRect.height() - _gameDrawRect.top,
-					     _gameDrawRect.width(),
-					     _gameDrawRect.height());
+	_targetBuffer->setScissorBox(_gameDrawRect.left,
+				     _windowHeight - _gameDrawRect.height() - _gameDrawRect.top,
+				     _gameDrawRect.width(),
+				     _gameDrawRect.height());
+
+	Common::RotationMode rotation = getRotationMode();
+	int rotatedWidth = _gameDrawRect.width();
+	int rotatedHeight = _gameDrawRect.height();
+	if (rotation == Common::kRotation90 || rotation == Common::kRotation270) {
+		SWAP(rotatedWidth, rotatedHeight);
 	}
-
-
-	_shakeOffsetScaled = Common::Point(_gameScreenShakeXOffset * _gameDrawRect.width() / (int)_currentState.gameWidth,
-		_gameScreenShakeYOffset * _gameDrawRect.height() / (int)_currentState.gameHeight);
+	_shakeOffsetScaled = Common::Point(_gameScreenShakeXOffset * rotatedWidth / (int)_currentState.gameWidth,
+	                                   _gameScreenShakeYOffset * rotatedHeight / (int)_currentState.gameHeight);
 
 	// Update the cursor position to adjust for new display area.
 	setMousePosition(_cursorX, _cursorY);
@@ -1901,6 +1919,8 @@ void OpenGLGraphicsManager::recalculateCursorScaling() {
 		return;
 	}
 
+	Common::RotationMode rotation = getRotationMode();
+
 	uint cursorWidth = _cursor->getWidth();
 	uint cursorHeight = _cursor->getHeight();
 
@@ -1914,8 +1934,14 @@ void OpenGLGraphicsManager::recalculateCursorScaling() {
 	// to the game screen.
 	// In 3D mode, there is no scaling
 	if (!_cursorDontScale && _gameScreen) {
-		const frac_t screenScaleFactorX = intToFrac(_gameDrawRect.width()) / _gameScreen->getWidth();
-		const frac_t screenScaleFactorY = intToFrac(_gameDrawRect.height()) / _gameScreen->getHeight();
+		int rotatedWidth = _gameDrawRect.width();
+		int rotatedHeight = _gameDrawRect.height();
+		if (rotation == Common::kRotation90 || rotation == Common::kRotation270) {
+			SWAP(rotatedWidth, rotatedHeight);
+		}
+
+		const frac_t screenScaleFactorX = intToFrac(rotatedWidth) / _gameScreen->getWidth();
+		const frac_t screenScaleFactorY = intToFrac(rotatedHeight) / _gameScreen->getHeight();
 
 		_cursorHotspotXScaled = fracToInt(_cursorHotspotXScaled * screenScaleFactorX);
 		_cursorWidthScaled    = fracToDouble(cursorWidth        * screenScaleFactorX);
@@ -1923,25 +1949,58 @@ void OpenGLGraphicsManager::recalculateCursorScaling() {
 		_cursorHotspotYScaled = fracToInt(_cursorHotspotYScaled * screenScaleFactorY);
 		_cursorHeightScaled   = fracToDouble(cursorHeight       * screenScaleFactorY);
 	}
+
+	switch (rotation) {
+	default:
+	case Common::kRotationNormal:
+		// Nothing to do
+		break;
+	case Common::kRotation90:
+		_cursorHotspotYScaled = _cursorHeightScaled - _cursorHotspotYScaled;
+		SWAP(_cursorHotspotXScaled, _cursorHotspotYScaled);
+		SWAP(_cursorWidthScaled, _cursorHeightScaled);
+		break;
+	case Common::kRotation180:
+		_cursorHotspotYScaled = _cursorHeightScaled - _cursorHotspotYScaled;
+		_cursorHotspotXScaled = _cursorWidthScaled - _cursorHotspotXScaled;
+		break;
+	case Common::kRotation270:
+		_cursorHotspotXScaled = _cursorWidthScaled - _cursorHotspotXScaled;
+		SWAP(_cursorHotspotXScaled, _cursorHotspotYScaled);
+		SWAP(_cursorWidthScaled, _cursorHeightScaled);
+		break;
+	}
 }
 
-void OpenGLGraphicsManager::updateLinearFiltering() {
+void OpenGLGraphicsManager::updateTextureSettings() {
+	Common::RotationMode rotation = getRotationMode();
+
 #if !USE_FORCED_GLES
 	if (_libretroPipeline) {
 		_libretroPipeline->enableLinearFiltering(_currentState.filtering);
+		_libretroPipeline->setRotation(rotation);
 	}
 #endif
 
 	if (_gameScreen) {
 		_gameScreen->enableLinearFiltering(_currentState.filtering);
+		_gameScreen->setRotation(rotation);
+	}
+
+#if defined(USE_OPENGL_GAME) || defined(USE_OPENGL_SHADERS)
+	if (_renderer3d) {
+		_renderer3d->setRotation(rotation);
 	}
+#endif
 
 	if (_cursor) {
 		_cursor->enableLinearFiltering(_currentState.filtering);
+		_cursor->setRotation(rotation);
 	}
 
 	if (_cursorMask) {
 		_cursorMask->enableLinearFiltering(_currentState.filtering);
+		_cursorMask->setRotation(rotation);
 	}
 
 	// The overlay UI should also obey the filtering choice (managed via the Filter Graphics checkbox in Graphics Tab).
@@ -1949,8 +2008,8 @@ void OpenGLGraphicsManager::updateLinearFiltering() {
 	// It may look crude, but it should be crispier and it's left to user choice to enable filtering.
 	if (_overlay) {
 		_overlay->enableLinearFiltering(_currentState.filtering);
+		_overlay->setRotation(rotation);
 	}
-
 }
 
 #ifdef USE_OSD
diff --git a/backends/graphics/opengl/opengl-graphics.h b/backends/graphics/opengl/opengl-graphics.h
index 5d95550a664..dfabc4f05ee 100644
--- a/backends/graphics/opengl/opengl-graphics.h
+++ b/backends/graphics/opengl/opengl-graphics.h
@@ -336,7 +336,7 @@ protected:
 	void recalculateDisplayAreas() override;
 	void handleResizeImpl(const int width, const int height) override;
 
-	void updateLinearFiltering();
+	void updateTextureSettings();
 
 	Pipeline *getPipeline() const { return _pipeline; }
 
diff --git a/backends/graphics/opengl/pipelines/libretro.cpp b/backends/graphics/opengl/pipelines/libretro.cpp
index 05e43eb5eda..a5d4fd53dbc 100644
--- a/backends/graphics/opengl/pipelines/libretro.cpp
+++ b/backends/graphics/opengl/pipelines/libretro.cpp
@@ -133,7 +133,7 @@ static const char *const g_compatFragment =
  * to the input coordinates space */
 class LibRetroTextureTarget : public TextureTarget {
 public:
-	bool setScaledSize(uint width, uint height, const Common::Rect &scalingRect) {
+	bool setScaledSize(uint width, uint height, const Common::Rect &scalingRect, Common::RotationMode rotation) {
 		Texture *texture = getTexture();
 		if (!texture->setSize(width, height)) {
 			return false;
@@ -151,27 +151,97 @@ public:
 		const float ratioW = (float)width  / scalingRect.width();
 		const float ratioH = (float)height / scalingRect.height();
 
-		// Setup scaling projection matrix.
+		// Setup scaling/rotating projection matrix.
 		// This projection takes window screen coordinates and converts it to input coordinates normalized
-		_projectionMatrix(0, 0) = 2.f * ratioW / texWidth;
-		_projectionMatrix(0, 1) = 0.f;
-		_projectionMatrix(0, 2) = 0.f;
-		_projectionMatrix(0, 3) = 0.f;
-
-		_projectionMatrix(1, 0) = 0.f;
-		_projectionMatrix(1, 1) = 2.f * ratioH / texHeight;
-		_projectionMatrix(1, 2) = 0.f;
-		_projectionMatrix(1, 3) = 0.f;
-
-		_projectionMatrix(2, 0) = 0.f;
-		_projectionMatrix(2, 1) = 0.f;
-		_projectionMatrix(2, 2) = 0.f;
-		_projectionMatrix(2, 3) = 0.f;
-
-		_projectionMatrix(3, 0) = -1.f - (2.f * scalingRect.left) * ratioW / texWidth;
-		_projectionMatrix(3, 1) = -1.f - (2.f * scalingRect.top) * ratioH / texHeight;
-		_projectionMatrix(3, 2) = 0.0f;
-		_projectionMatrix(3, 3) = 1.0f;
+		// The rotation is also inverted so 90° is in fact a -90° rotation.
+		// This is a resulting product of ROTATE * SCALE_TRANSLATE
+		switch (rotation) {
+		default:
+		case Common::kRotationNormal:
+			_projectionMatrix(0, 0) = 2.f * ratioW / texWidth;
+			_projectionMatrix(0, 1) = 0.f;
+			_projectionMatrix(0, 2) = 0.f;
+			_projectionMatrix(0, 3) = 0.f;
+
+			_projectionMatrix(1, 0) = 0.f;
+			_projectionMatrix(1, 1) = 2.f * ratioH / texHeight;
+			_projectionMatrix(1, 2) = 0.f;
+			_projectionMatrix(1, 3) = 0.f;
+
+			_projectionMatrix(2, 0) = 0.f;
+			_projectionMatrix(2, 1) = 0.f;
+			_projectionMatrix(2, 2) = 0.f;
+			_projectionMatrix(2, 3) = 0.f;
+
+			_projectionMatrix(3, 0) = -1.f - (2.f * scalingRect.left) * ratioW / texWidth;
+			_projectionMatrix(3, 1) = -1.f - (2.f * scalingRect.top) * ratioH / texHeight;
+			_projectionMatrix(3, 2) = 0.0f;
+			_projectionMatrix(3, 3) = 1.0f;
+			break;
+		case Common::kRotation90:
+			_projectionMatrix(0, 0) = 0.f;
+			_projectionMatrix(0, 1) = -2.f * ratioW / texWidth;
+			_projectionMatrix(0, 2) = 0.f;
+			_projectionMatrix(0, 3) = 0.f;
+
+			_projectionMatrix(1, 0) = 2.f * ratioH / texHeight;
+			_projectionMatrix(1, 1) = 0.f;
+			_projectionMatrix(1, 2) = 0.f;
+			_projectionMatrix(1, 3) = 0.f;
+
+			_projectionMatrix(2, 0) = 0.f;
+			_projectionMatrix(2, 1) = 0.f;
+			_projectionMatrix(2, 2) = 0.f;
+			_projectionMatrix(2, 3) = 0.f;
+
+			_projectionMatrix(3, 0) = -1.f - (2.f * scalingRect.top) * ratioH / texHeight;
+			_projectionMatrix(3, 1) = 1.f + (2.f * scalingRect.left) * ratioW / texWidth;
+			_projectionMatrix(3, 2) = 0.0f;
+			_projectionMatrix(3, 3) = 1.0f;
+			break;
+		case Common::kRotation180:
+			_projectionMatrix(0, 0) = -2.f * ratioW / texWidth;
+			_projectionMatrix(0, 1) = 0.f;
+			_projectionMatrix(0, 2) = 0.f;
+			_projectionMatrix(0, 3) = 0.f;
+
+			_projectionMatrix(1, 0) = 0.f;
+			_projectionMatrix(1, 1) = -2.f * ratioH / texHeight;
+			_projectionMatrix(1, 2) = 0.f;
+			_projectionMatrix(1, 3) = 0.f;
+
+			_projectionMatrix(2, 0) = 0.f;
+			_projectionMatrix(2, 1) = 0.f;
+			_projectionMatrix(2, 2) = 0.f;
+			_projectionMatrix(2, 3) = 0.f;
+
+			_projectionMatrix(3, 0) = 1.f + (2.f * scalingRect.left) * ratioW / texWidth;
+			_projectionMatrix(3, 1) = 1.f + (2.f * scalingRect.top) * ratioH / texHeight;
+			_projectionMatrix(3, 2) = 0.0f;
+			_projectionMatrix(3, 3) = 1.0f;
+			break;
+		case Common::kRotation270:
+			_projectionMatrix(0, 0) = 0.f;
+			_projectionMatrix(0, 1) = 2.f * ratioW / texWidth;
+			_projectionMatrix(0, 2) = 0.f;
+			_projectionMatrix(0, 3) = 0.f;
+
+			_projectionMatrix(1, 0) = -2.f * ratioH / texHeight;
+			_projectionMatrix(1, 1) = 0.f;
+			_projectionMatrix(1, 2) = 0.f;
+			_projectionMatrix(1, 3) = 0.f;
+
+			_projectionMatrix(2, 0) = 0.f;
+			_projectionMatrix(2, 1) = 0.f;
+			_projectionMatrix(2, 2) = 0.f;
+			_projectionMatrix(2, 3) = 0.f;
+
+			_projectionMatrix(3, 0) = 1.f + (2.f * scalingRect.top) * ratioH / texHeight;
+			_projectionMatrix(3, 1) = -1.f - (2.f * scalingRect.left) * ratioW / texWidth;
+			_projectionMatrix(3, 2) = 0.0f;
+			_projectionMatrix(3, 3) = 1.0f;
+			break;
+		}
 
 		// Directly apply changes when we are active.
 		if (isActive()) {
@@ -293,17 +363,62 @@ void LibRetroPipeline::finishScaling() {
 	 * so everything is flipped when we draw this texture.
 	 * Use custom coordinates to do the flipping. */
 	GLfloat coordinates[4*2];
-	coordinates[0] = _outputRect.left;
-	coordinates[1] = _outputRect.bottom;
 
-	coordinates[2] = _outputRect.right;
-	coordinates[3] = _outputRect.bottom;
+	switch (_rotation) {
+	default:
+	case Common::kRotationNormal:
+		coordinates[0] = _outputRect.left;
+		coordinates[1] = _outputRect.bottom;
+
+		coordinates[2] = _outputRect.right;
+		coordinates[3] = _outputRect.bottom;
+
+		coordinates[4] = _outputRect.left;
+		coordinates[5] = _outputRect.top;
+
+		coordinates[6] = _outputRect.right;
+		coordinates[7] = _outputRect.top;
+		break;
+	case Common::kRotation90:
+		coordinates[0] = _outputRect.left;
+		coordinates[1] = _outputRect.top;
 
-	coordinates[4] = _outputRect.left;
-	coordinates[5] = _outputRect.top;
+		coordinates[2] = _outputRect.left;
+		coordinates[3] = _outputRect.bottom;
 
-	coordinates[6] = _outputRect.right;
-	coordinates[7] = _outputRect.top;
+		coordinates[4] = _outputRect.right;
+		coordinates[5] = _outputRect.top;
+
+		coordinates[6] = _outputRect.right;
+		coordinates[7] = _outputRect.bottom;
+		break;
+	case Common::kRotation180:
+		coordinates[0] = _outputRect.right;
+		coordinates[1] = _outputRect.top;
+
+		coordinates[2] = _outputRect.left;
+		coordinates[3] = _outputRect.top;
+
+		coordinates[4] = _outputRect.right;
+		coordinates[5] = _outputRect.bottom;
+
+		coordinates[6] = _outputRect.left;
+		coordinates[7] = _outputRect.bottom;
+		break;
+	case Common::kRotation270:
+		coordinates[0] = _outputRect.right;
+		coordinates[1] = _outputRect.bottom;
+
+		coordinates[2] = _outputRect.right;
+		coordinates[3] = _outputRect.top;
+
+		coordinates[4] = _outputRect.left;
+		coordinates[5] = _outputRect.bottom;
+
+		coordinates[6] = _outputRect.left;
+		coordinates[7] = _outputRect.top;
+		break;
+	}
 
 	_outputPipeline.drawTexture(*_passes[_passes.size() - 1].target->getTexture(), coordinates);
 
@@ -635,7 +750,7 @@ void LibRetroPipeline::setPipelineState() {
 bool LibRetroPipeline::setupFBOs() {
 	// Setup the input targets sizes
 	for (auto &inputTarget : _inputTargets) {
-		if (!inputTarget.setScaledSize(_inputWidth, _inputHeight, _outputRect)) {
+		if (!inputTarget.setScaledSize(_inputWidth, _inputHeight, _outputRect, _rotation)) {
 			return false;
 		}
 	}
@@ -653,7 +768,7 @@ bool LibRetroPipeline::setupFBOs() {
 		pass.shaderPass->applyScale(sourceW, sourceH, viewportW, viewportH, &sourceW, &sourceH);
 
 		// Resize FBO to fit the output of the pass.
-		if (!pass.target->setSize((uint)sourceW, (uint)sourceH, Common::kRotationNormal)) {
+		if (!pass.target->setSize((uint)sourceW, (uint)sourceH)) {
 			return false;
 		}
 
diff --git a/backends/graphics/opengl/pipelines/libretro.h b/backends/graphics/opengl/pipelines/libretro.h
index 5a8ea684968..5b2047251f8 100644
--- a/backends/graphics/opengl/pipelines/libretro.h
+++ b/backends/graphics/opengl/pipelines/libretro.h
@@ -60,6 +60,7 @@ public:
 
 	/* Called by OpenGLGraphicsManager */
 	void enableLinearFiltering(bool enabled) { _linearFiltering = enabled; }
+	void setRotation(Common::RotationMode rotation) { if (_rotation != rotation) { _rotation = rotation; setPipelineState(); } }
 	/* Called by OpenGLGraphicsManager to setup the internal objects sizes */
 	void setDisplaySizes(uint inputWidth, uint inputHeight, const Common::Rect &outputRect);
 	/* Called by OpenGLGraphicsManager to indicate that next draws need to be scaled. */
@@ -101,6 +102,7 @@ private:
 	Common::Rect _outputRect;
 
 	bool _linearFiltering;
+	Common::RotationMode _rotation;
 
 	/* Determines if preset depends on frameCount or from previous frames */
 	bool _isAnimated;
diff --git a/backends/graphics/opengl/renderer3d.h b/backends/graphics/opengl/renderer3d.h
index 00f4523d02a..65b8d4334e7 100644
--- a/backends/graphics/opengl/renderer3d.h
+++ b/backends/graphics/opengl/renderer3d.h
@@ -50,6 +50,8 @@ public:
 	const Texture &getGLTexture() const { return _texture; }
 	bool hasTexture() const { return _texture.getGLTexture() != 0; }
 
+	void setRotation(Common::RotationMode rotation) { _texture.setRotation(rotation); }
+
 protected:
 	void setup();
 
diff --git a/backends/graphics/opengl/texture.cpp b/backends/graphics/opengl/texture.cpp
index b092f9b9db6..36705fd01fe 100644
--- a/backends/graphics/opengl/texture.cpp
+++ b/backends/graphics/opengl/texture.cpp
@@ -135,6 +135,10 @@ void TextureSurface::enableLinearFiltering(bool enable) {
 	_glTexture.enableLinearFiltering(enable);
 }
 
+void TextureSurface::setRotation(Common::RotationMode rotation) {
+	_glTexture.setRotation(rotation);
+}
+
 void TextureSurface::allocate(uint width, uint height) {
 	// Assure the texture can contain our user data.
 	_glTexture.setSize(width, height);
@@ -571,10 +575,14 @@ void TextureSurfaceCLUT8GPU::enableLinearFiltering(bool enable) {
 	_target->getTexture()->enableLinearFiltering(enable);
 }
 
+void TextureSurfaceCLUT8GPU::setRotation(Common::RotationMode rotation) {
+	_target->getTexture()->setRotation(rotation);
+}
+
 void TextureSurfaceCLUT8GPU::allocate(uint width, uint height) {
 	// Assure the texture can contain our user data.
 	_clut8Texture.setSize(width, height);
-	_target->setSize(width, height, Common::kRotationNormal);
+	_target->setSize(width, height);
 
 	// In case the needed texture dimension changed we will reinitialize the
 	// texture data buffer.
diff --git a/backends/graphics/opengl/texture.h b/backends/graphics/opengl/texture.h
index bc78550e7e8..5f530f7f518 100644
--- a/backends/graphics/opengl/texture.h
+++ b/backends/graphics/opengl/texture.h
@@ -30,6 +30,7 @@
 #include "graphics/surface.h"
 
 #include "common/rect.h"
+#include "common/rotationmode.h"
 
 class Scaler;
 
@@ -60,6 +61,13 @@ public:
 	 */
 	virtual void enableLinearFiltering(bool enable) = 0;
 
+	/**
+	 * Sets the rotate parameter of the texture
+	 *
+	 * @param rotation How to rotate the texture
+	 */
+	virtual void setRotation(Common::RotationMode rotation) = 0;
+
 	/**
 	 * Allocate storage for surface.
 	 *
@@ -170,6 +178,7 @@ public:
 	void recreate() override;
 
 	void enableLinearFiltering(bool enable) override;
+	void setRotation(Common::RotationMode rotation) override;
 
 	void allocate(uint width, uint height) override;
 
@@ -285,6 +294,7 @@ public:
 	void recreate() override;
 
 	void enableLinearFiltering(bool enable) override;
+	void setRotation(Common::RotationMode rotation) override;
 
 	void allocate(uint width, uint height) override;
 


Commit: 3f7d37b03fd89365cd313b00222a213f374ff191
    https://github.com/scummvm/scummvm/commit/3f7d37b03fd89365cd313b00222a213f374ff191
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2025-06-15T13:22:31+02:00

Commit Message:
COMMON: Make rotation mode fit other settings semantics

This also avoids configuration lookups at every frame update.

Changed paths:
    backends/graphics/graphics.h
    backends/graphics/opengl/opengl-graphics.cpp
    backends/graphics/openglsdl/openglsdl-graphics.cpp
    backends/graphics/sdl/sdl-graphics.cpp
    backends/graphics/sdl/sdl-graphics.h
    backends/graphics/surfacesdl/surfacesdl-graphics.cpp
    backends/graphics/windowed.h
    backends/modular-backend.cpp
    backends/modular-backend.h
    backends/platform/sdl/sailfish/sailfish.cpp
    base/main.cpp
    common/rotationmode.h
    common/system.cpp
    common/system.h
    engines/engine.cpp
    gui/options.cpp


diff --git a/backends/graphics/graphics.h b/backends/graphics/graphics.h
index efc5d3dc3c4..d551b460222 100644
--- a/backends/graphics/graphics.h
+++ b/backends/graphics/graphics.h
@@ -62,7 +62,7 @@ public:
 	virtual int getDefaultStretchMode() const { return 0; }
 	virtual bool setStretchMode(int mode) { return false; }
 	virtual int getStretchMode() const { return 0; }
-	virtual Common::RotationMode getRotationMode() const { return Common::kRotationNormal; }
+	virtual bool setRotationMode(Common::RotationMode rotation) { return false; }
 	virtual uint getDefaultScaler() const { return 0; }
 	virtual uint getDefaultScaleFactor() const { return 1; }
 	virtual bool setScaler(uint mode, int factor) { return false; }
diff --git a/backends/graphics/opengl/opengl-graphics.cpp b/backends/graphics/opengl/opengl-graphics.cpp
index 349f63a3c31..7c3245c77b3 100644
--- a/backends/graphics/opengl/opengl-graphics.cpp
+++ b/backends/graphics/opengl/opengl-graphics.cpp
@@ -864,7 +864,6 @@ void OpenGLGraphicsManager::updateScreen() {
 	}
 
 	if (_osdMessageSurface) {
-		Common::RotationMode rotationMode = getRotationMode();
 		// Update alpha value.
 		const int diff = g_system->getMillis(false) - _osdMessageFadeStartTime;
 		if (diff > 0) {
@@ -882,7 +881,7 @@ void OpenGLGraphicsManager::updateScreen() {
 
 		int osdWidth = _osdMessageSurface->getWidth(),
 		    osdHeight = _osdMessageSurface->getHeight();
-		if (rotationMode == Common::kRotation90 || rotationMode == Common::kRotation270) {
+		if (_rotationMode == Common::kRotation90 || _rotationMode == Common::kRotation270) {
 			SWAP(osdWidth, osdHeight);
 		}
 
@@ -907,11 +906,10 @@ void OpenGLGraphicsManager::updateScreen() {
 	}
 
 	if (_osdIconSurface) {
-		Common::RotationMode rotationMode = getRotationMode();
 		int osdWidth = _osdIconSurface->getWidth(),
 		    osdHeight = _osdIconSurface->getHeight();
 		int dstX, dstY;
-		switch (rotationMode) {
+		switch (_rotationMode) {
 		default:
 		case Common::kRotationNormal:
 			dstX = _windowWidth - osdWidth - kOSDIconRightMargin;
@@ -1354,7 +1352,7 @@ void OpenGLGraphicsManager::osdMessageUpdateSurface() {
 	// readable in case it needs to be scaled and does not affect it
 	// otherwise.
 	_osdMessageSurface->enableLinearFiltering(true);
-	_osdMessageSurface->setRotation(getRotationMode());
+	_osdMessageSurface->setRotation(_rotationMode);
 
 	_osdMessageSurface->allocate(width, height);
 
@@ -1413,7 +1411,7 @@ void OpenGLGraphicsManager::displayActivityIconOnOSD(const Graphics::Surface *ic
 		// readable in case it needs to be scaled and does not affect it
 		// otherwise.
 		_osdIconSurface->enableLinearFiltering(true);
-		_osdIconSurface->setRotation(getRotationMode());
+		_osdIconSurface->setRotation(_rotationMode);
 
 		_osdIconSurface->allocate(converted->w, converted->h);
 
@@ -1450,14 +1448,13 @@ void OpenGLGraphicsManager::handleResizeImpl(const int width, const int height)
 	// Setup backbuffer size.
 	_targetBuffer->setSize(width, height);
 
-	int rotation = getRotationMode();
 	uint overlayWidth = width;
 	uint overlayHeight = height;
 
 	int rotatedWidth = _windowWidth;
 	int rotatedHeight = _windowHeight;
 
-	if (rotation == Common::kRotation90 || rotation == Common::kRotation270) {
+	if (_rotationMode == Common::kRotation90 || _rotationMode == Common::kRotation270) {
 		overlayWidth = height;
 		overlayHeight = width;
 		rotatedWidth = _windowHeight;
@@ -1879,10 +1876,9 @@ void OpenGLGraphicsManager::recalculateDisplayAreas() {
 				     _gameDrawRect.width(),
 				     _gameDrawRect.height());
 
-	Common::RotationMode rotation = getRotationMode();
 	int rotatedWidth = _gameDrawRect.width();
 	int rotatedHeight = _gameDrawRect.height();
-	if (rotation == Common::kRotation90 || rotation == Common::kRotation270) {
+	if (_rotationMode == Common::kRotation90 || _rotationMode == Common::kRotation270) {
 		SWAP(rotatedWidth, rotatedHeight);
 	}
 	_shakeOffsetScaled = Common::Point(_gameScreenShakeXOffset * rotatedWidth / (int)_currentState.gameWidth,
@@ -1919,8 +1915,6 @@ void OpenGLGraphicsManager::recalculateCursorScaling() {
 		return;
 	}
 
-	Common::RotationMode rotation = getRotationMode();
-
 	uint cursorWidth = _cursor->getWidth();
 	uint cursorHeight = _cursor->getHeight();
 
@@ -1936,7 +1930,7 @@ void OpenGLGraphicsManager::recalculateCursorScaling() {
 	if (!_cursorDontScale && _gameScreen) {
 		int rotatedWidth = _gameDrawRect.width();
 		int rotatedHeight = _gameDrawRect.height();
-		if (rotation == Common::kRotation90 || rotation == Common::kRotation270) {
+		if (_rotationMode == Common::kRotation90 || _rotationMode == Common::kRotation270) {
 			SWAP(rotatedWidth, rotatedHeight);
 		}
 
@@ -1950,7 +1944,7 @@ void OpenGLGraphicsManager::recalculateCursorScaling() {
 		_cursorHeightScaled   = fracToDouble(cursorHeight       * screenScaleFactorY);
 	}
 
-	switch (rotation) {
+	switch (_rotationMode) {
 	default:
 	case Common::kRotationNormal:
 		// Nothing to do
@@ -1973,34 +1967,32 @@ void OpenGLGraphicsManager::recalculateCursorScaling() {
 }
 
 void OpenGLGraphicsManager::updateTextureSettings() {
-	Common::RotationMode rotation = getRotationMode();
-
 #if !USE_FORCED_GLES
 	if (_libretroPipeline) {
 		_libretroPipeline->enableLinearFiltering(_currentState.filtering);
-		_libretroPipeline->setRotation(rotation);
+		_libretroPipeline->setRotation(_rotationMode);
 	}
 #endif
 
 	if (_gameScreen) {
 		_gameScreen->enableLinearFiltering(_currentState.filtering);
-		_gameScreen->setRotation(rotation);
+		_gameScreen->setRotation(_rotationMode);
 	}
 
 #if defined(USE_OPENGL_GAME) || defined(USE_OPENGL_SHADERS)
 	if (_renderer3d) {
-		_renderer3d->setRotation(rotation);
+		_renderer3d->setRotation(_rotationMode);
 	}
 #endif
 
 	if (_cursor) {
 		_cursor->enableLinearFiltering(_currentState.filtering);
-		_cursor->setRotation(rotation);
+		_cursor->setRotation(_rotationMode);
 	}
 
 	if (_cursorMask) {
 		_cursorMask->enableLinearFiltering(_currentState.filtering);
-		_cursorMask->setRotation(rotation);
+		_cursorMask->setRotation(_rotationMode);
 	}
 
 	// The overlay UI should also obey the filtering choice (managed via the Filter Graphics checkbox in Graphics Tab).
@@ -2008,7 +2000,7 @@ void OpenGLGraphicsManager::updateTextureSettings() {
 	// It may look crude, but it should be crispier and it's left to user choice to enable filtering.
 	if (_overlay) {
 		_overlay->enableLinearFiltering(_currentState.filtering);
-		_overlay->setRotation(rotation);
+		_overlay->setRotation(_rotationMode);
 	}
 }
 
diff --git a/backends/graphics/openglsdl/openglsdl-graphics.cpp b/backends/graphics/openglsdl/openglsdl-graphics.cpp
index e2796f601b1..9b91d13f50f 100644
--- a/backends/graphics/openglsdl/openglsdl-graphics.cpp
+++ b/backends/graphics/openglsdl/openglsdl-graphics.cpp
@@ -286,10 +286,6 @@ void OpenGLSdlGraphicsManager::setFeatureState(OSystem::Feature f, bool enable)
 		}
 		break;
 
-	case OSystem::kFeatureRotationMode:
-		notifyResize(getWindowWidth(), getWindowHeight());
-		break;
-
 	default:
 		OpenGLGraphicsManager::setFeatureState(f, enable);
 	}
diff --git a/backends/graphics/sdl/sdl-graphics.cpp b/backends/graphics/sdl/sdl-graphics.cpp
index 0b1e41bc51d..f21ce9934c8 100644
--- a/backends/graphics/sdl/sdl-graphics.cpp
+++ b/backends/graphics/sdl/sdl-graphics.cpp
@@ -104,20 +104,13 @@ SdlGraphicsManager::State SdlGraphicsManager::getState() const {
 	state.fullscreen    = getFeatureState(OSystem::kFeatureFullscreenMode);
 	state.cursorPalette = getFeatureState(OSystem::kFeatureCursorPalette);
 	state.vsync         = getFeatureState(OSystem::kFeatureVSync);
+	state.rotation      = _rotationMode;
 #ifdef USE_RGB_COLOR
 	state.pixelFormat   = getScreenFormat();
 #endif
 	return state;
 }
 
-Common::RotationMode SdlGraphicsManager::getRotationMode() const {
-#if SDL_VERSION_ATLEAST(2, 0, 0)
-	return Common::parseRotationMode(ConfMan.getInt("rotation_mode"));
-#else
-	return Common::kRotationNormal;
-#endif
-}
-
 bool SdlGraphicsManager::setState(const State &state) {
 	beginGFXTransaction();
 #ifdef USE_RGB_COLOR
@@ -137,6 +130,7 @@ bool SdlGraphicsManager::setState(const State &state) {
 		setFeatureState(OSystem::kFeatureFullscreenMode, state.fullscreen);
 		setFeatureState(OSystem::kFeatureCursorPalette, state.cursorPalette);
 		setFeatureState(OSystem::kFeatureVSync, state.vsync);
+		setRotationMode(state.rotation);
 
 	if (endGFXTransaction() != OSystem::kTransactionSuccess) {
 		return false;
@@ -342,13 +336,6 @@ bool SdlGraphicsManager::createOrUpdateWindow(int width, int height, const Uint3
 	if (!_window) {
 		return false;
 	}
-	Common::RotationMode rotation = getRotationMode();
-
-	if (rotation == Common::kRotation90 || rotation == Common::kRotation270) {
-		int w = width, h = height;
-		width = h;
-		height = w;
-	}
 
 	// width *=3;
 	// height *=3;
diff --git a/backends/graphics/sdl/sdl-graphics.h b/backends/graphics/sdl/sdl-graphics.h
index bd1e45f95de..538483205b7 100644
--- a/backends/graphics/sdl/sdl-graphics.h
+++ b/backends/graphics/sdl/sdl-graphics.h
@@ -91,14 +91,14 @@ public:
 	 */
 	virtual bool notifyMousePosition(Common::Point &mouse);
 
-	Common::RotationMode getRotationMode() const override;
-
 	virtual bool showMouse(bool visible) override;
 	bool lockMouse(bool lock) override;
 
 	virtual bool saveScreenshot(const Common::Path &filename) const { return false; }
 	void saveScreenshot() override;
 
+	bool setRotationMode(Common::RotationMode rotation) override { _rotationMode = rotation; return true; }
+
 	// Override from Common::EventObserver
 	bool notifyEvent(const Common::Event &event) override;
 
@@ -112,6 +112,7 @@ public:
 		bool fullscreen;
 		bool cursorPalette;
 		bool vsync;
+		Common::RotationMode rotation;
 
 #ifdef USE_RGB_COLOR
 		Graphics::PixelFormat pixelFormat;
diff --git a/backends/graphics/surfacesdl/surfacesdl-graphics.cpp b/backends/graphics/surfacesdl/surfacesdl-graphics.cpp
index 7cd524df1ec..7ca67fda01b 100644
--- a/backends/graphics/surfacesdl/surfacesdl-graphics.cpp
+++ b/backends/graphics/surfacesdl/surfacesdl-graphics.cpp
@@ -302,9 +302,6 @@ void SurfaceSdlGraphicsManager::setFeatureState(OSystem::Feature f, bool enable)
 		if (enable)
 			_window->iconifyWindow();
 		break;
-	case OSystem::kFeatureRotationMode:
-		notifyResize(getWindowWidth(), getWindowHeight());
-		break;
 	default:
 		break;
 	}
@@ -3230,10 +3227,9 @@ void SurfaceSdlGraphicsManager::SDL_UpdateRects(SDL_Surface *screen, int numrect
 	SDL_Rect viewport;
 
 	Common::Rect &drawRect = (_overlayVisible) ? _overlayDrawRect : _gameDrawRect;
-	Common::RotationMode rotation = getRotationMode();
 
 	/* Destination rectangle represents the texture before rotation */
-	if (rotation == Common::kRotation90 || rotation == Common::kRotation270) {
+	if (_rotationMode == Common::kRotation90 || _rotationMode == Common::kRotation270) {
 		viewport.w = drawRect.height();
 		viewport.h = drawRect.width();
 		int delta = (viewport.w - viewport.h) / 2;
@@ -3246,7 +3242,7 @@ void SurfaceSdlGraphicsManager::SDL_UpdateRects(SDL_Surface *screen, int numrect
 		viewport.y = drawRect.top;
 	}
 
-	int rotangle = (int)rotation;
+	int rotangle = (int)_rotationMode;
 
 	SDL_RenderClear(_renderer);
 
diff --git a/backends/graphics/windowed.h b/backends/graphics/windowed.h
index 42821952206..84283bce44a 100644
--- a/backends/graphics/windowed.h
+++ b/backends/graphics/windowed.h
@@ -55,6 +55,7 @@ public:
 		_windowWidth(0),
 		_windowHeight(0),
 		_screenAlign(SCREEN_ALIGN_CENTER | SCREEN_ALIGN_MIDDLE),
+		_rotationMode(Common::kRotationNormal),
 		_overlayVisible(false),
 		_overlayInGUI(false),
 		_gameScreenShakeXOffset(0),
@@ -146,7 +147,7 @@ protected:
 		}
 
 		int windowX, windowY;
-		switch (getRotationMode()) {
+		switch (_rotationMode) {
 		default:
 		case Common::kRotationNormal:
 			windowX = targetX + (x * targetWidth + sourceWidth / 2) / sourceWidth;
@@ -193,7 +194,7 @@ protected:
 		y = CLIP<int>(y, sourceY, sourceMaxY);
 
 		int virtualX, virtualY;
-		switch (getRotationMode()) {
+		switch (_rotationMode) {
 		default:
 		case Common::kRotationNormal:
 			virtualX = ((x - sourceX) * targetWidth + sourceWidth / 2) / sourceWidth;
@@ -356,6 +357,11 @@ protected:
 	 */
 	int _screenAlign;
 
+	/**
+	 * How the screens need to be rotated on the screen
+	 */
+	Common::RotationMode _rotationMode;
+
 	/**
 	 * Whether the overlay (i.e. launcher, including the out-of-game launcher)
 	 * is visible or not.
@@ -444,11 +450,10 @@ protected:
 private:
 	void populateDisplayAreaDrawRect(const frac_t displayAspect, int originalWidth, int originalHeight, Common::Rect &drawRect) const {
 		int mode = getStretchMode();
-		Common::RotationMode rotation = getRotationMode();
 		int rotatedWindowWidth;
 		int rotatedWindowHeight;
 
-		if (rotation == Common::kRotation90 || rotation == Common::kRotation270) {
+		if (_rotationMode == Common::kRotation90 || _rotationMode == Common::kRotation270) {
 			rotatedWindowWidth = _windowHeight;
 			rotatedWindowHeight = _windowWidth;
 		} else {
@@ -533,7 +538,7 @@ private:
 		alignX += _gameScreenShakeXOffset * width / getWidth();
 		alignY += _gameScreenShakeYOffset * height / getHeight();
 
-		if (rotation == Common::kRotation90 || rotation == Common::kRotation270) {
+		if (_rotationMode == Common::kRotation90 || _rotationMode == Common::kRotation270) {
 			drawRect.top = alignX;
 			drawRect.left = alignY;
 			drawRect.setWidth(height);
diff --git a/backends/modular-backend.cpp b/backends/modular-backend.cpp
index e65c5486da9..68cae30c7a0 100644
--- a/backends/modular-backend.cpp
+++ b/backends/modular-backend.cpp
@@ -100,6 +100,10 @@ int ModularGraphicsBackend::getStretchMode() const {
 	return _graphicsManager->getStretchMode();
 }
 
+bool ModularGraphicsBackend::setRotationMode(Common::RotationMode rotation) {
+	return _graphicsManager->setRotationMode(rotation);
+}
+
 uint ModularGraphicsBackend::getDefaultScaler() const {
 	return _graphicsManager->getDefaultScaler();
 }
diff --git a/backends/modular-backend.h b/backends/modular-backend.h
index fb414296ab6..0b13a155e4d 100644
--- a/backends/modular-backend.h
+++ b/backends/modular-backend.h
@@ -77,6 +77,7 @@ public:
 	int getDefaultStretchMode() const override final;
 	bool setStretchMode(int mode) override final;
 	int getStretchMode() const override final;
+	bool setRotationMode(Common::RotationMode rotation) override final;
 	uint getDefaultScaler() const override final;
 	uint getDefaultScaleFactor() const override final;
 	using BaseBackend::setScaler;
diff --git a/backends/platform/sdl/sailfish/sailfish.cpp b/backends/platform/sdl/sailfish/sailfish.cpp
index 4022ac38e56..6d0d994ef1a 100644
--- a/backends/platform/sdl/sailfish/sailfish.cpp
+++ b/backends/platform/sdl/sailfish/sailfish.cpp
@@ -75,7 +75,7 @@ Common::String OSystem_SDL_Sailfish::getAppSuffix() {
 
 void OSystem_SDL_Sailfish::initBackend() {
 	if (!ConfMan.hasKey("rotation_mode")) {
-		ConfMan.setPath("rotation_mode", "90");
+		ConfMan.setInt("rotation_mode", 90);
 	}
 
 	if (!ConfMan.hasKey("savepath")) {
diff --git a/base/main.cpp b/base/main.cpp
index a11d5930d17..4ebcea52ad8 100644
--- a/base/main.cpp
+++ b/base/main.cpp
@@ -348,6 +348,7 @@ static void setupGraphics(OSystem &system) {
 		system.setStretchMode(ConfMan.get("stretch_mode").c_str());
 		system.setScaler(ConfMan.get("scaler").c_str(), ConfMan.getInt("scale_factor"));
 		system.setShader(ConfMan.getPath("shader"));
+		system.setRotationMode(ConfMan.getInt("rotation_mode"));
 
 #if defined(OPENDINGUX) || defined(MIYOO) || defined(MIYOOMINI) || defined(ATARI)
 		// 0, 0 means "autodetect" but currently only SDL supports
diff --git a/common/rotationmode.h b/common/rotationmode.h
index 15d31035e94..fce780a73c7 100644
--- a/common/rotationmode.h
+++ b/common/rotationmode.h
@@ -41,7 +41,7 @@ class String;
  * List of rotation modes.
  *
  */
-enum RotationMode {
+enum RotationMode : int {
 	kRotationNormal = 0,
 	kRotation90 = 90,
 	kRotation180 = 180,
diff --git a/common/system.cpp b/common/system.cpp
index 6d0b013e8c4..90f19047068 100644
--- a/common/system.cpp
+++ b/common/system.cpp
@@ -30,6 +30,7 @@
 #include "common/taskbar.h"
 #include "common/updates.h"
 #include "common/dialogs.h"
+#include "common/rotationmode.h"
 #include "common/str-enc.h"
 #include "common/textconsole.h"
 #include "common/text-to-speech.h"
@@ -218,6 +219,10 @@ bool OSystem::setStretchMode(const char *name) {
 	return false;
 }
 
+bool OSystem::setRotationMode(int rotation) {
+	return setRotationMode(Common::parseRotationMode(rotation));
+}
+
 void OSystem::fatalError() {
 	quit();
 	exit(1);
diff --git a/common/system.h b/common/system.h
index 8a662f50991..30f41558995 100644
--- a/common/system.h
+++ b/common/system.h
@@ -76,6 +76,8 @@ class HardwareInputSet;
 class Keymap;
 class KeymapperDefaultBindings;
 
+enum RotationMode : int;
+
 typedef Array<Keymap *> KeymapArray;
 }
 
@@ -992,6 +994,28 @@ public:
 	 */
 	virtual int getStretchMode() const { return 0; }
 
+	/**
+	 * Switch to the specified rotation
+	 *
+	 * If switching to the new rotation fails, this method returns false.
+	 *
+	 * @param rotation Rotation angle
+	 *
+	 * @return True if the switch was successful, false otherwise.
+	 */
+	virtual bool setRotationMode(Common::RotationMode rotation) { return false; }
+
+	/**
+	 * Switch to the specified rotation with the given int
+	 *
+	 * If switching to the new rotation fails, this method returns false.
+	 *
+	 * @param rotation Rotation angle
+	 *
+	 * @return True if the switch was successful, false otherwise.
+	 */
+	bool setRotationMode(int rotation);
+
 	/**
 	 * Return the ID of the 'default' scaler.
 	 *
diff --git a/engines/engine.cpp b/engines/engine.cpp
index b26862a4fbf..f4dbbfeed6b 100644
--- a/engines/engine.cpp
+++ b/engines/engine.cpp
@@ -253,6 +253,9 @@ void initCommonGFX(bool is3D) {
 	if (gameDomain->contains("stretch_mode"))
 		g_system->setStretchMode(ConfMan.get("stretch_mode").c_str());
 
+	if (gameDomain->contains("rotation_mode"))
+		g_system->setRotationMode(ConfMan.getInt("rotation_mode"));
+
 	if (gameDomain->contains("shader"))
 		g_system->setShader(ConfMan.getPath("shader"));
 
diff --git a/gui/options.cpp b/gui/options.cpp
index d700c203456..4bbed3cc329 100644
--- a/gui/options.cpp
+++ b/gui/options.cpp
@@ -822,6 +822,7 @@ void OptionsDialog::apply() {
 		g_system->setGraphicsMode(ConfMan.get("gfx_mode", _domain).c_str());
 		g_system->setStretchMode(ConfMan.get("stretch_mode", _domain).c_str());
 		g_system->setScaler(ConfMan.get("scaler", _domain).c_str(), ConfMan.getInt("scale_factor", _domain));
+		g_system->setRotationMode(ConfMan.getInt("rotation_mode", _domain));
 		g_system->setShader(ConfMan.getPath("shader", _domain));
 
 		if (ConfMan.hasKey("aspect_ratio"))
@@ -833,10 +834,6 @@ void OptionsDialog::apply() {
 		if (ConfMan.hasKey("vsync"))
 			g_system->setFeatureState(OSystem::kFeatureVSync, ConfMan.getBool("vsync", _domain));
 
-		if (g_system->hasFeature(OSystem::kFeatureRotationMode)) {
-			g_system->setFeatureState(OSystem::kFeatureRotationMode, ConfMan.hasKey("rotation_mode", _domain));
-		}
-
 		OSystem::TransactionError gfxError = g_system->endGFXTransaction();
 
 		// Since this might change the screen resolution we need to give


Commit: ce68acff93c156deeea0b4c635db17500b7098b5
    https://github.com/scummvm/scummvm/commit/ce68acff93c156deeea0b4c635db17500b7098b5
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2025-06-15T13:22:31+02:00

Commit Message:
BACKENDS: Avoid double call of getOverlayWidth/Height

Changed paths:
    backends/graphics/windowed.h


diff --git a/backends/graphics/windowed.h b/backends/graphics/windowed.h
index 84283bce44a..cd71cf44ad4 100644
--- a/backends/graphics/windowed.h
+++ b/backends/graphics/windowed.h
@@ -260,8 +260,10 @@ protected:
 		populateDisplayAreaDrawRect(getDesiredGameAspectRatio(), getWidth() * getGameRenderScale(), getHeight() * getGameRenderScale(), _gameDrawRect);
 
 		if (getOverlayHeight()) {
-			const frac_t overlayAspect = intToFrac(getOverlayWidth()) / getOverlayHeight();
-			populateDisplayAreaDrawRect(overlayAspect, getOverlayWidth(), getOverlayHeight(), _overlayDrawRect);
+			const int16 overlayWidth = getOverlayWidth(),
+			            overlayHeight = getOverlayHeight();
+			const frac_t overlayAspect = intToFrac(overlayWidth) / overlayHeight;
+			populateDisplayAreaDrawRect(overlayAspect, overlayWidth, overlayHeight, _overlayDrawRect);
 		}
 
 		if (_overlayInGUI) {




More information about the Scummvm-git-logs mailing list