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

lephilousophe noreply at scummvm.org
Sun Jun 1 06:24:54 UTC 2025


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

Summary:
40edc77e1d BACKENDS: SDL: Bail out immediately if window creation failed
870a5d1856 BACKENDS: OPENGL3D: Fix green/blue switch
6fd8589c6a BACKENDS: OPENGL3D: Cleanup Emscripten code
58a9879414 OPENGL: If texture can't be bound, don't do anything
0500a48f73 BACKENDS: SDL: Respect resizable when creating a window
4edc64ceee BACKENDS: SDL: Setup OpenGL attributes before creating any window
a6807baee9 PLAYGROUND3D: Don't disable texture 2D unit in shader mode
95ceac83f2 GRAPHICS: OPENGL: Allow to flip texture coordinates
c212c192a0 GRAPHICS: OPENGL: Don't query GLSL version string when not supported
962fe5ca01 PLAYGROUND3D: Make surface test work with POT textures
52a22918f1 GRAPHICS: OPENGL: Don't destroy an already destroyed texture
347ed95617 BACKENDS: OPENGL: Disable OpenGL features at pipeline activation
5d9524078a SDL: Properly store resizable state for later
f53d38f6dd SDL: Don't destroy the window when changing the maximized flag
41ef48ede2 BACKENDS: OPENGLSDL3D: Prefer RGB565 over RGBA5551
b1da854ce3 BACKENDS: OPENGL: Allow to disable the current pipeline whichever it is
3ebfe3aeec BACKENDS: OPENGLSDL: Factorize context destruction
24ee317adf BACKENDS: OPENGLSDL: Test several graphical modes
a04fbf4bdb BACKENDS: OPENGL: Allow to request a fixed-size window and antialiasing
45afd86a42 BACKENDS: OPENGL: Add 3D rendering support
f222c8256a BACKENDS: SDL: Don't hardcode 3D graphical backend
fb36820d86 ANDROID: Don't use the old 3D graphics manager
f33a321fe3 ANDROID: Cleanup the obsolete 3D graphics manager
fc1ca91446 IOS7: Don't use the old 3D graphics manager
3a3b109ed4 IOS7: Cleanup the obsolete 3D graphics manager
a2005c416a BACKENDS: SDL: Cleanup the obsolete 3D graphics manager
396e2deb73 ANDROID: Add antialiasing support
d6a38ca37f IOS7: Add anti-aliasing support
493e93595c ANDROID: Fix parameter inversion
1c5166f5ce ENGINES: Track screen changes during pause
c80b3820dd BASE: Allow users to set antialiasing on command line
ae2e6a6a27 ANDROID: Check the 3D status when applying touch settings
5d48384d1f OPENGL: Fix destroy ordering
0d852d576f BACKENDS: Allow to fetch the current GraphicsManager when it's nullptr
6d3075cc95 SDL: Notify graphics manager when the window is about to be destroyed
89d8cc805f BACKENDS: OPENGLSDL: Avoid extraneous context recreations
5bdaf97e5e SDL: Rework fullscreen switching and make it work for 3D
f5ba76279f BACKENDS: SURFACESDL: Fix unused variable warning
d659142a3b OPENGL: Detect imaging support
8d24daaf44 BACKENDS: SDL: Free the correct pointer
73a77734e2 ENGINES: Allow to override shaders on 3D games
a92c00545a BACKENDS: OPENGL: Fix fallback when shader fails to load
436cd89051 ENGINES: Also warn the user of GFX transaction errors in 3D mode
f4c99b0af4 PLAYGROUND3D: Remove memory leaks and static variables
9fbb12a077 SDL: Fix unused function warning on SDL3 too
13e9c12d95 PLAYGROUND3D: Add a mouse cursor
b096e3003e TWP: Let ImGui render the mouse cursor when displayed


Commit: 40edc77e1de9a89f7cb23d6295fa3ac7ade59e98
    https://github.com/scummvm/scummvm/commit/40edc77e1de9a89f7cb23d6295fa3ac7ade59e98
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2025-06-01T08:24:34+02:00

Commit Message:
BACKENDS: SDL: Bail out immediately if window creation failed

This allows to get the real SDL error message.

Changed paths:
    backends/platform/sdl/sdl-window.cpp


diff --git a/backends/platform/sdl/sdl-window.cpp b/backends/platform/sdl/sdl-window.cpp
index 73baa583a81..0f5cec055a4 100644
--- a/backends/platform/sdl/sdl-window.cpp
+++ b/backends/platform/sdl/sdl-window.cpp
@@ -505,6 +505,10 @@ bool SdlWindow::createOrUpdateWindow(int width, int height, uint32 flags) {
 		_window = SDL_CreateWindow(_windowCaption.c_str(), _lastX,
 								   _lastY, width, height, flags);
 #endif
+		if (!_window) {
+			return false;
+		}
+
 		if (_window) {
 			setupIcon();
 		}
@@ -548,10 +552,6 @@ bool SdlWindow::createOrUpdateWindow(int width, int height, uint32 flags) {
 	SDL_SetWindowResizable(_window, _resizable ? SDL_TRUE : SDL_FALSE);
 #endif
 
-	if (!_window) {
-		return false;
-	}
-
 #if defined(MACOSX)
 	// macOS windows with the flag SDL_WINDOW_FULLSCREEN_DESKTOP exiting their fullscreen space
 	// ignore the size set by SDL_SetWindowSize while they were in fullscreen mode.


Commit: 870a5d185677ad6b5075c625c18705911bbbc858
    https://github.com/scummvm/scummvm/commit/870a5d185677ad6b5075c625c18705911bbbc858
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2025-06-01T08:24:34+02:00

Commit Message:
BACKENDS: OPENGL3D: Fix green/blue switch

Changed paths:
    backends/graphics3d/openglsdl/openglsdl-graphics3d.cpp


diff --git a/backends/graphics3d/openglsdl/openglsdl-graphics3d.cpp b/backends/graphics3d/openglsdl/openglsdl-graphics3d.cpp
index 6f3fde9e509..a9b0c21e9e1 100644
--- a/backends/graphics3d/openglsdl/openglsdl-graphics3d.cpp
+++ b/backends/graphics3d/openglsdl/openglsdl-graphics3d.cpp
@@ -501,11 +501,11 @@ void OpenGLSdlGraphics3dManager::initializeOpenGLContext() const {
 #endif
 }
 
-OpenGLSdlGraphics3dManager::OpenGLPixelFormat::OpenGLPixelFormat(uint screenBytesPerPixel, uint red, uint blue, uint green, uint alpha, int samples) :
+OpenGLSdlGraphics3dManager::OpenGLPixelFormat::OpenGLPixelFormat(uint screenBytesPerPixel, uint red, uint green, uint blue, uint alpha, int samples) :
 		bytesPerPixel(screenBytesPerPixel),
 		redSize(red),
-		blueSize(blue),
 		greenSize(green),
+		blueSize(blue),
 		alphaSize(alpha),
 		multisampleSamples(samples) {
 


Commit: 6fd8589c6a9598b9988745d2e6f0d20476dc89d9
    https://github.com/scummvm/scummvm/commit/6fd8589c6a9598b9988745d2e6f0d20476dc89d9
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2025-06-01T08:24:34+02:00

Commit Message:
BACKENDS: OPENGL3D: Cleanup Emscripten code

Move the definitions where they belong and avoid a runtime check for the
GL renderer.

Changed paths:
    backends/graphics3d/opengl/framebuffer.cpp
    graphics/opengl/system_headers.h


diff --git a/backends/graphics3d/opengl/framebuffer.cpp b/backends/graphics3d/opengl/framebuffer.cpp
index 87b1fddafda..dccd6a14815 100644
--- a/backends/graphics3d/opengl/framebuffer.cpp
+++ b/backends/graphics3d/opengl/framebuffer.cpp
@@ -69,6 +69,13 @@ void FrameBuffer::init() {
 	glBindFramebuffer(GL_FRAMEBUFFER, _frameBuffer);
 	glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, getGLTexture(), 0);
 
+#ifdef EMSCRIPTEN
+		// See https://www.khronos.org/registry/webgl/specs/latest/1.0/#FBO_ATTACHMENTS
+		// and https://github.com/emscripten-core/emscripten/issues/4832
+	glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_STENCIL, getWidth(), getHeight());
+	glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, _renderBuffers[0]);
+	glBindRenderbuffer(GL_RENDERBUFFER, 0);
+#else
 	if (usePackedBuffer()) {
 		glBindRenderbuffer(GL_RENDERBUFFER, _renderBuffers[0]);
 		glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, getWidth(), getHeight());
@@ -78,29 +85,15 @@ void FrameBuffer::init() {
 	} else {
 		glBindRenderbuffer(GL_RENDERBUFFER, _renderBuffers[0]);
 
-		const char *glVersion = (const char *)glGetString(GL_VERSION);
-		if (strstr(glVersion, "WebGL 1.0") != NULL) {
-			// See https://www.khronos.org/registry/webgl/specs/latest/1.0/#FBO_ATTACHMENTS
-			// and https://github.com/emscripten-core/emscripten/issues/4832
-#ifndef GL_DEPTH_STENCIL
-#define GL_DEPTH_STENCIL 0x84F9
-#endif
-			glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_STENCIL, getWidth(), getHeight());
+		glRenderbufferStorage(GL_RENDERBUFFER, useDepthComponent24() ? GL_DEPTH_COMPONENT24 : GL_DEPTH_COMPONENT16, getWidth(), getHeight());
+		glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, _renderBuffers[0]);
 
-#ifndef GL_DEPTH_STENCIL_ATTACHMENT
-#define GL_DEPTH_STENCIL_ATTACHMENT 0x821A
-#endif
-			glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, _renderBuffers[0]);
-		} else {
-			glRenderbufferStorage(GL_RENDERBUFFER, useDepthComponent24() ? GL_DEPTH_COMPONENT24 : GL_DEPTH_COMPONENT16, getWidth(), getHeight());
-			glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, _renderBuffers[0]);
-
-			glBindRenderbuffer(GL_RENDERBUFFER, _renderBuffers[1]);
-			glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, getWidth(), getHeight());
-			glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, _renderBuffers[1]);
-		}
+		glBindRenderbuffer(GL_RENDERBUFFER, _renderBuffers[1]);
+		glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, getWidth(), getHeight());
+		glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, _renderBuffers[1]);
 		glBindRenderbuffer(GL_RENDERBUFFER, 0);
 	}
+#endif
 
 	glBindFramebuffer(GL_FRAMEBUFFER, _frameBuffer);
 	GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
diff --git a/graphics/opengl/system_headers.h b/graphics/opengl/system_headers.h
index 31799488385..b2b0dc908bc 100644
--- a/graphics/opengl/system_headers.h
+++ b/graphics/opengl/system_headers.h
@@ -123,4 +123,14 @@
 	#define GL_DRAW_FRAMEBUFFER_BINDING 0x8CA6
 #endif
 
+#if !defined(GL_DEPTH_STENCIL)
+	// For WebGL: see https://github.com/emscripten-core/emscripten/issues/4832
+	#define GL_DEPTH_STENCIL 0x84F9
+#endif
+
+#if !defined(GL_DEPTH_STENCIL_ATTACHMENT)
+	// For WebGL: see https://github.com/emscripten-core/emscripten/issues/4832
+	#define GL_DEPTH_STENCIL_ATTACHMENT 0x821A
+#endif
+
 #endif


Commit: 58a98794142efee89d64bd8cdbaeaf6d6840bf48
    https://github.com/scummvm/scummvm/commit/58a98794142efee89d64bd8cdbaeaf6d6840bf48
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2025-06-01T08:24:34+02:00

Commit Message:
OPENGL: If texture can't be bound, don't do anything

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


diff --git a/graphics/opengl/texture.cpp b/graphics/opengl/texture.cpp
index fd0b28023c5..e7800136e9d 100644
--- a/graphics/opengl/texture.cpp
+++ b/graphics/opengl/texture.cpp
@@ -53,7 +53,9 @@ void Texture::enableLinearFiltering(bool enable) {
 		_glFilter = GL_NEAREST;
 	}
 
-	bind();
+	if (!bind()) {
+		return;
+	}
 
 	GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, _glFilter));
 	GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, _glFilter));
@@ -95,7 +97,9 @@ void Texture::setWrapMode(WrapMode wrapMode) {
 	}
 
 
-	bind();
+	if (!bind()) {
+		return;
+	}
 
 	GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, glwrapMode));
 	GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, glwrapMode));
@@ -135,8 +139,12 @@ void Texture::create() {
 	}
 }
 
-void Texture::bind() const {
+bool Texture::bind() const {
+	if (!_glTexture) {
+		return false;
+	}
 	GL_CALL(glBindTexture(GL_TEXTURE_2D, _glTexture));
+	return true;
 }
 
 bool Texture::setSize(uint width, uint height) {
@@ -173,7 +181,10 @@ bool Texture::setSize(uint width, uint height) {
 
 		// Allocate storage for OpenGL texture if necessary.
 		if (oldWidth != _width || oldHeight != _height) {
-			bind();
+			if (!bind()) {
+				return false;
+			}
+
 			bool error;
 			GL_CALL_CHECK(error, glTexImage2D(GL_TEXTURE_2D, 0, _glIntFormat, _width, _height,
 			             0, _glFormat, _glType, nullptr));
@@ -187,7 +198,9 @@ bool Texture::setSize(uint width, uint height) {
 
 void Texture::updateArea(const Common::Rect &area, const Graphics::Surface &src) {
 	// Set the texture on the active texture unit.
-	bind();
+	if (!bind()) {
+		return;
+	}
 
 	// Update the actual texture.
 	// Although we have the area of the texture buffer we want to update we
diff --git a/graphics/opengl/texture.h b/graphics/opengl/texture.h
index a5cf69bc68b..eb0f438a8c5 100644
--- a/graphics/opengl/texture.h
+++ b/graphics/opengl/texture.h
@@ -87,8 +87,10 @@ public:
 
 	/**
 	 * Bind the texture to the active texture unit.
+	 *
+	 * @return Whether a texture really exists
 	 */
-	void bind() const;
+	bool bind() const;
 
 	/**
 	 * Sets the size of the texture in pixels.


Commit: 0500a48f7381db45d6e645d421bf997e83f40384
    https://github.com/scummvm/scummvm/commit/0500a48f7381db45d6e645d421bf997e83f40384
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2025-06-01T08:24:34+02:00

Commit Message:
BACKENDS: SDL: Respect resizable when creating a window

flags argument always contains the SDL_WINDOW_RESIZABLE bit.
This means that is must be removed if the window should not be
resizable.

Changed paths:
    backends/platform/sdl/sdl-window.cpp


diff --git a/backends/platform/sdl/sdl-window.cpp b/backends/platform/sdl/sdl-window.cpp
index 0f5cec055a4..60e606c6963 100644
--- a/backends/platform/sdl/sdl-window.cpp
+++ b/backends/platform/sdl/sdl-window.cpp
@@ -428,8 +428,8 @@ bool SdlWindow::createOrUpdateWindow(int width, int height, uint32 flags) {
 #endif
 
 #if SDL_VERSION_ATLEAST(2, 0, 0)
-	if (_resizable) {
-		flags |= SDL_WINDOW_RESIZABLE;
+	if (!_resizable) {
+		flags &= ~SDL_WINDOW_RESIZABLE;
 	}
 #endif
 
@@ -547,9 +547,9 @@ bool SdlWindow::createOrUpdateWindow(int width, int height, uint32 flags) {
 #endif
 
 #if SDL_VERSION_ATLEAST(3, 0, 0)
-	SDL_SetWindowResizable(_window, _resizable);
+	SDL_SetWindowResizable(_window, (flags & SDL_WINDOW_RESIZABLE) != 0);
 #elif SDL_VERSION_ATLEAST(2, 0, 5)
-	SDL_SetWindowResizable(_window, _resizable ? SDL_TRUE : SDL_FALSE);
+	SDL_SetWindowResizable(_window, (flags & SDL_WINDOW_RESIZABLE) ? SDL_TRUE : SDL_FALSE);
 #endif
 
 #if defined(MACOSX)


Commit: 4edc64ceeeeeb3af641e89ef621bd2e584a906fc
    https://github.com/scummvm/scummvm/commit/4edc64ceeeeeb3af641e89ef621bd2e584a906fc
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2025-06-01T08:24:34+02:00

Commit Message:
BACKENDS: SDL: Setup OpenGL attributes before creating any window

Changed paths:
    backends/graphics/openglsdl/openglsdl-graphics.cpp


diff --git a/backends/graphics/openglsdl/openglsdl-graphics.cpp b/backends/graphics/openglsdl/openglsdl-graphics.cpp
index 5bef5799d16..0b3b38c77c1 100644
--- a/backends/graphics/openglsdl/openglsdl-graphics.cpp
+++ b/backends/graphics/openglsdl/openglsdl-graphics.cpp
@@ -610,6 +610,13 @@ bool OpenGLSdlGraphicsManager::setupMode(uint width, uint height) {
 		_glContext = nullptr;
 	}
 
+	// Request a OpenGL (ES) context we can use.
+	// This must be done before any window creation
+	SDL_GL_ResetAttributes();
+	SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, _glContextProfileMask);
+	SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, _glContextMajor);
+	SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, _glContextMinor);
+
 #if SDL_VERSION_ATLEAST(3, 0, 0)
 	uint32 flags = SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_HIGH_PIXEL_DENSITY;
 #else
@@ -645,11 +652,6 @@ bool OpenGLSdlGraphicsManager::setupMode(uint width, uint height) {
 		flags |= SDL_WINDOW_MAXIMIZED;
 	}
 
-	// Request a OpenGL (ES) context we can use.
-	SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, _glContextProfileMask);
-	SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, _glContextMajor);
-	SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, _glContextMinor);
-
 #if defined(NINTENDO_SWITCH) && !SDL_VERSION_ATLEAST(3, 0, 0)
 	// Switch quirk: Switch seems to need this flag, otherwise the screen
 	// is zoomed when switching from Normal graphics mode to OpenGL


Commit: a6807baee95908094cab018a89caa20eb1269797
    https://github.com/scummvm/scummvm/commit/a6807baee95908094cab018a89caa20eb1269797
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2025-06-01T08:24:34+02:00

Commit Message:
PLAYGROUND3D: Don't disable texture 2D unit in shader mode

This is useless and invalid in GLES2.

Changed paths:
    engines/playground3d/gfx_opengl_shaders.cpp


diff --git a/engines/playground3d/gfx_opengl_shaders.cpp b/engines/playground3d/gfx_opengl_shaders.cpp
index 1ac66ef6fb9..8a83b0ea50a 100644
--- a/engines/playground3d/gfx_opengl_shaders.cpp
+++ b/engines/playground3d/gfx_opengl_shaders.cpp
@@ -230,7 +230,6 @@ void ShaderRenderer::drawCube(const Math::Vector3d &pos, const Math::Vector3d &r
 	glBlendFunc(GL_ONE, GL_ZERO);
 	glEnable(GL_DEPTH_TEST);
 	glDepthMask(GL_TRUE);
-	glDisable(GL_TEXTURE_2D);
 
 	auto rotateMatrix = (Math::Quaternion::fromEuler(roll.x(), roll.y(), roll.z(), Math::EO_XYZ)).inverse().toMatrix();
 	_cubeShader->use();
@@ -252,7 +251,6 @@ void ShaderRenderer::drawPolyOffsetTest(const Math::Vector3d &pos, const Math::V
 	glBlendFunc(GL_ONE, GL_ZERO);
 	glEnable(GL_DEPTH_TEST);
 	glDepthMask(GL_TRUE);
-	glDisable(GL_TEXTURE_2D);
 
 	auto rotateMatrix = (Math::Quaternion::fromEuler(roll.x(), roll.y(), roll.z(), Math::EO_XYZ)).inverse().toMatrix();
 	_offsetShader->use();
@@ -275,7 +273,6 @@ void ShaderRenderer::dimRegionInOut(float fade) {
 	glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
 	glDisable(GL_DEPTH_TEST);
 	glDepthMask(GL_FALSE);
-	glDisable(GL_TEXTURE_2D);
 
 	_fadeShader->use();
 	_fadeShader->setUniform1f("alphaLevel", 1.0 - fade);
@@ -288,7 +285,6 @@ void ShaderRenderer::drawInViewport() {
 	glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
 	glDisable(GL_DEPTH_TEST);
 	glDepthMask(GL_FALSE);
-	glDisable(GL_TEXTURE_2D);
 
 	_viewportShader->use();
 	_viewportShader->setUniform("offset", Math::Vector2d(0.0f, 0.0f));


Commit: 95ceac83f2f564c5f24f6de88c1ccc07840179d5
    https://github.com/scummvm/scummvm/commit/95ceac83f2f564c5f24f6de88c1ccc07840179d5
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2025-06-01T08:24:34+02:00

Commit Message:
GRAPHICS: OPENGL: Allow to flip texture coordinates

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


diff --git a/graphics/opengl/texture.cpp b/graphics/opengl/texture.cpp
index e7800136e9d..d5c9ef56368 100644
--- a/graphics/opengl/texture.cpp
+++ b/graphics/opengl/texture.cpp
@@ -147,7 +147,7 @@ bool Texture::bind() const {
 	return true;
 }
 
-bool Texture::setSize(uint width, uint height) {
+bool Texture::setSize(uint width, uint height, bool flip) {
 	const uint oldWidth  = _width;
 	const uint oldHeight = _height;
 
@@ -167,17 +167,31 @@ bool Texture::setSize(uint width, uint height) {
 		const GLfloat texWidth = (GLfloat)width / _width;
 		const GLfloat texHeight = (GLfloat)height / _height;
 
-		_texCoords[0] = 0;
-		_texCoords[1] = 0;
+		if (flip) {
+			_texCoords[0] = 0;
+			_texCoords[1] = texHeight;
 
-		_texCoords[2] = texWidth;
-		_texCoords[3] = 0;
+			_texCoords[2] = texWidth;
+			_texCoords[3] = texHeight;
 
-		_texCoords[4] = 0;
-		_texCoords[5] = texHeight;
+			_texCoords[4] = 0;
+			_texCoords[5] = 0;
 
-		_texCoords[6] = texWidth;
-		_texCoords[7] = texHeight;
+			_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;
+		}
 
 		// Allocate storage for OpenGL texture if necessary.
 		if (oldWidth != _width || oldHeight != _height) {
diff --git a/graphics/opengl/texture.h b/graphics/opengl/texture.h
index eb0f438a8c5..5a5e4d9ca6b 100644
--- a/graphics/opengl/texture.h
+++ b/graphics/opengl/texture.h
@@ -100,9 +100,10 @@ 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 setSize(uint width, uint height, bool flip = false);
 
 	/**
 	 * Copy image data to the texture.


Commit: c212c192a0c23c7359dfb355cbb8d1cb859856d4
    https://github.com/scummvm/scummvm/commit/c212c192a0c23c7359dfb355cbb8d1cb859856d4
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2025-06-01T08:24:34+02:00

Commit Message:
GRAPHICS: OPENGL: Don't query GLSL version string when not supported

Changed paths:
    graphics/opengl/context.cpp


diff --git a/graphics/opengl/context.cpp b/graphics/opengl/context.cpp
index 24ee7f4c485..a0b78ab0763 100644
--- a/graphics/opengl/context.cpp
+++ b/graphics/opengl/context.cpp
@@ -303,7 +303,7 @@ void Context::initialize(ContextType contextType) {
 		glGetIntegerv(GL_MAX_SAMPLES, (GLint *)&multisampleMaxSamples);
 	}
 
-	const char *glslVersionString = (const char *)glGetString(GL_SHADING_LANGUAGE_VERSION);
+	const char *glslVersionString = glslVersion ? (const char *)glGetString(GL_SHADING_LANGUAGE_VERSION) : "";
 
 	// Log features supported by GL context.
 	debug(5, "OpenGL version: %s", glGetString(GL_VERSION));


Commit: 962fe5ca01768fc4344257a752ea3f24a759b9fa
    https://github.com/scummvm/scummvm/commit/962fe5ca01768fc4344257a752ea3f24a759b9fa
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2025-06-01T08:24:34+02:00

Commit Message:
PLAYGROUND3D: Make surface test work with POT textures

NPOT doesn't work on old implementations

Changed paths:
    engines/playground3d/gfx.cpp
    engines/playground3d/gfx.h
    engines/playground3d/gfx_opengl.cpp
    engines/playground3d/gfx_opengl.h
    engines/playground3d/gfx_opengl_shaders.cpp
    engines/playground3d/gfx_opengl_shaders.h


diff --git a/engines/playground3d/gfx.cpp b/engines/playground3d/gfx.cpp
index 9e101cd6fd9..8d4c46d3c4b 100644
--- a/engines/playground3d/gfx.cpp
+++ b/engines/playground3d/gfx.cpp
@@ -70,7 +70,7 @@ const float Renderer::cubeVertices[] = {
 };
 
 Renderer::Renderer(OSystem *system)
-		: _system(system), _texture(nullptr) {
+		: _system(system) {
 }
 
 Renderer::~Renderer() {
diff --git a/engines/playground3d/gfx.h b/engines/playground3d/gfx.h
index 59df0f4c015..606b68c96aa 100644
--- a/engines/playground3d/gfx.h
+++ b/engines/playground3d/gfx.h
@@ -34,6 +34,17 @@
 
 namespace Playground3d {
 
+struct TextureType {
+	enum type {
+		RGBA8888 = 0,
+		RGB888   = 1,
+		RGB565   = 2,
+		RGBA5551 = 3,
+		RGBA4444 = 4,
+		MAX      = 5
+	};
+};
+
 class Renderer {
 public:
 	Renderer(OSystem *system);
@@ -85,7 +96,6 @@ protected:
 	Math::Matrix4 _mvpMatrix;
 
 	static const float cubeVertices[11 * 6 * 4];
-	Graphics::Surface *_texture;
 
 	Math::Matrix4 makeProjectionMatrix(float fov, float nearClip, float farClip) const;
 };
diff --git a/engines/playground3d/gfx_opengl.cpp b/engines/playground3d/gfx_opengl.cpp
index 232d5f8f8dc..177e4183828 100644
--- a/engines/playground3d/gfx_opengl.cpp
+++ b/engines/playground3d/gfx_opengl.cpp
@@ -25,6 +25,7 @@
 #if defined(USE_OPENGL_GAME)
 
 #include "graphics/opengl/context.h"
+#include "graphics/opengl/texture.h"
 #include "graphics/surface.h"
 
 #include "engines/playground3d/gfx.h"
@@ -56,20 +57,12 @@ static const GLfloat bitmapVertices[] = {
 	 0.2f, -0.2f,
 };
 
-static const GLfloat textCords[] = {
-	// S     T
-	0.0f, 0.0f,
-	1.0f, 0.0f,
-	0.0f, 1.0f,
-	1.0f, 1.0f,
-};
-
 Renderer *CreateGfxOpenGL(OSystem *system) {
 	return new OpenGLRenderer(system);
 }
 
 OpenGLRenderer::OpenGLRenderer(OSystem *system) :
-		Renderer(system) {
+		Renderer(system), _textures{} {
 }
 
 OpenGLRenderer::~OpenGLRenderer() {
@@ -89,20 +82,13 @@ void OpenGLRenderer::init() {
 	glDisable(GL_TEXTURE_2D);
 	glDisable(GL_LIGHTING);
 	glEnable(GL_DEPTH_TEST);
-
-	glGenTextures(5, _textureRgbaId);
-	glGenTextures(5, _textureRgbId);
-	glGenTextures(2, _textureRgb565Id);
-	glGenTextures(2, _textureRgba5551Id);
-	glGenTextures(2, _textureRgba4444Id);
 }
 
 void OpenGLRenderer::deinit() {
-	glDeleteTextures(5, _textureRgbaId);
-	glDeleteTextures(5, _textureRgbId);
-	glDeleteTextures(2, _textureRgb565Id);
-	glDeleteTextures(2, _textureRgba5551Id);
-	glDeleteTextures(2, _textureRgba4444Id);
+	for(int i = 0; i < ARRAYSIZE(_textures); i++) {
+		delete _textures[i];
+		_textures[i] = nullptr;
+	}
 }
 
 void OpenGLRenderer::clear(const Math::Vector4d &clearColor) {
@@ -111,38 +97,43 @@ void OpenGLRenderer::clear(const Math::Vector4d &clearColor) {
 }
 
 void OpenGLRenderer::loadTextureRGBA(Graphics::Surface *texture) {
-	glBindTexture(GL_TEXTURE_2D, _textureRgbaId[0]);
-	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texture->w, texture->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, texture->getPixels());
+	if (!_textures[TextureType::RGBA8888]) {
+		_textures[TextureType::RGBA8888] = new OpenGL::Texture(GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE);
+	}
+	_textures[TextureType::RGBA8888]->setSize(texture->w, texture->h);
+	_textures[TextureType::RGBA8888]->updateArea(Common::Rect(texture->w, texture->h), *texture);
 }
 
 void OpenGLRenderer::loadTextureRGB(Graphics::Surface *texture) {
-	glBindTexture(GL_TEXTURE_2D, _textureRgbId[0]);
-	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texture->w, texture->h, 0, GL_RGB, GL_UNSIGNED_BYTE, texture->getPixels());
+	if (!_textures[TextureType::RGB888]) {
+		_textures[TextureType::RGB888] = new OpenGL::Texture(GL_RGBA, GL_RGB, GL_UNSIGNED_BYTE);
+	}
+	_textures[TextureType::RGB888]->setSize(texture->w, texture->h);
+	_textures[TextureType::RGB888]->updateArea(Common::Rect(texture->w, texture->h), *texture);
 }
 
 void OpenGLRenderer::loadTextureRGB565(Graphics::Surface *texture) {
-	glBindTexture(GL_TEXTURE_2D, _textureRgb565Id[0]);
-	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texture->w, texture->h, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, texture->getPixels());
+	if (!_textures[TextureType::RGB565]) {
+		_textures[TextureType::RGB565] = new OpenGL::Texture(GL_RGBA, GL_RGB, GL_UNSIGNED_SHORT_5_6_5);
+	}
+	_textures[TextureType::RGB565]->setSize(texture->w, texture->h);
+	_textures[TextureType::RGB565]->updateArea(Common::Rect(texture->w, texture->h), *texture);
 }
 
 void OpenGLRenderer::loadTextureRGBA5551(Graphics::Surface *texture) {
-	glBindTexture(GL_TEXTURE_2D, _textureRgba5551Id[0]);
-	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texture->w, texture->h, 0, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, texture->getPixels());
+	if (!_textures[TextureType::RGBA5551]) {
+		_textures[TextureType::RGBA5551] = new OpenGL::Texture(GL_RGBA, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1);
+	}
+	_textures[TextureType::RGBA5551]->setSize(texture->w, texture->h);
+	_textures[TextureType::RGBA5551]->updateArea(Common::Rect(texture->w, texture->h), *texture);
 }
 
 void OpenGLRenderer::loadTextureRGBA4444(Graphics::Surface *texture) {
-	glBindTexture(GL_TEXTURE_2D, _textureRgba4444Id[0]);
-	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texture->w, texture->h, 0, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, texture->getPixels());
+	if (!_textures[TextureType::RGBA4444]) {
+		_textures[TextureType::RGBA4444] = new OpenGL::Texture(GL_RGBA, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4);
+	}
+	_textures[TextureType::RGBA4444]->setSize(texture->w, texture->h);
+	_textures[TextureType::RGBA4444]->updateArea(Common::Rect(texture->w, texture->h), *texture);
 }
 
 void OpenGLRenderer::setupViewport(int x, int y, int width, int height) {
@@ -342,37 +333,42 @@ void OpenGLRenderer::drawRgbaTexture() {
 	glTranslatef(-0.8f, 0.8f, 0);
 
 	glVertexPointer(2, GL_FLOAT, 2 * sizeof(GLfloat), bitmapVertices);
-	glTexCoordPointer(2, GL_FLOAT, 2 * sizeof(GLfloat), textCords);
-	glBindTexture(GL_TEXTURE_2D, _textureRgbaId[0]);
-	glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+	glTexCoordPointer(2, GL_FLOAT, 2 * sizeof(GLfloat), _textures[TextureType::RGBA8888]->getTexCoords());
+	if (_textures[TextureType::RGBA8888]->bind()) {
+		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+	}
 
 	glTranslatef(0.5, 0, 0);
 
 	glVertexPointer(2, GL_FLOAT, 2 * sizeof(GLfloat), bitmapVertices);
-	glTexCoordPointer(2, GL_FLOAT, 2 * sizeof(GLfloat), textCords);
-	glBindTexture(GL_TEXTURE_2D, _textureRgbId[0]);
-	glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+	glTexCoordPointer(2, GL_FLOAT, 2 * sizeof(GLfloat), _textures[TextureType::RGB888]->getTexCoords());
+	if (_textures[TextureType::RGB888]->bind()) {
+		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+	}
 
 	glTranslatef(0.5, 0, 0);
 
 	glVertexPointer(2, GL_FLOAT, 2 * sizeof(GLfloat), bitmapVertices);
-	glTexCoordPointer(2, GL_FLOAT, 2 * sizeof(GLfloat), textCords);
-	glBindTexture(GL_TEXTURE_2D, _textureRgb565Id[0]);
-	glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+	glTexCoordPointer(2, GL_FLOAT, 2 * sizeof(GLfloat), _textures[TextureType::RGB565]->getTexCoords());
+	if (_textures[TextureType::RGB565]->bind()) {
+		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+	}
 
 	glTranslatef(0.5, 0, 0);
 
 	glVertexPointer(2, GL_FLOAT, 2 * sizeof(GLfloat), bitmapVertices);
-	glTexCoordPointer(2, GL_FLOAT, 2 * sizeof(GLfloat), textCords);
-	glBindTexture(GL_TEXTURE_2D, _textureRgba5551Id[0]);
-	glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+	glTexCoordPointer(2, GL_FLOAT, 2 * sizeof(GLfloat), _textures[TextureType::RGBA5551]->getTexCoords());
+	if (_textures[TextureType::RGBA5551]->bind()) {
+		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+	}
 
 	glTranslatef(-1.5, -0.5, 0);
 
 	glVertexPointer(2, GL_FLOAT, 2 * sizeof(GLfloat), bitmapVertices);
-	glTexCoordPointer(2, GL_FLOAT, 2 * sizeof(GLfloat), textCords);
-	glBindTexture(GL_TEXTURE_2D, _textureRgba4444Id[0]);
-	glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+	glTexCoordPointer(2, GL_FLOAT, 2 * sizeof(GLfloat), _textures[TextureType::RGBA4444]->getTexCoords());
+	if (_textures[TextureType::RGBA4444]->bind()) {
+		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+	}
 
 	glDisableClientState(GL_VERTEX_ARRAY);
 	glDisableClientState(GL_TEXTURE_COORD_ARRAY);
diff --git a/engines/playground3d/gfx_opengl.h b/engines/playground3d/gfx_opengl.h
index a2656945230..97328af21b1 100644
--- a/engines/playground3d/gfx_opengl.h
+++ b/engines/playground3d/gfx_opengl.h
@@ -31,6 +31,10 @@
 
 #include "engines/playground3d/gfx.h"
 
+namespace OpenGL {
+class Texture;
+}
+
 namespace Playground3d {
 
 class OpenGLRenderer : public Renderer {
@@ -63,11 +67,7 @@ public:
 
 private:
 	Math::Vector3d _pos;
-	GLuint _textureRgbaId[5];
-	GLuint _textureRgbId[5];
-	GLuint _textureRgb565Id[2];
-	GLuint _textureRgba5551Id[2];
-	GLuint _textureRgba4444Id[2];
+	OpenGL::Texture *_textures[TextureType::MAX];
 
 	void drawFace(uint face);
 };
diff --git a/engines/playground3d/gfx_opengl_shaders.cpp b/engines/playground3d/gfx_opengl_shaders.cpp
index 8a83b0ea50a..6e77c3b733b 100644
--- a/engines/playground3d/gfx_opengl_shaders.cpp
+++ b/engines/playground3d/gfx_opengl_shaders.cpp
@@ -32,6 +32,7 @@
 #include "math/quat.h"
 
 #include "graphics/opengl/shader.h"
+#include "graphics/opengl/texture.h"
 
 #include "engines/playground3d/gfx.h"
 #include "engines/playground3d/gfx_opengl_shaders.h"
@@ -73,11 +74,11 @@ static const GLfloat boxVertices[] = {
 };
 
 static const GLfloat bitmapVertices[] = {
-	//  X      Y     S     T
-	-0.2f,  0.2f, 0.0f, 0.0f,
-	 0.2f,  0.2f, 1.0f, 0.0f,
-	-0.2f, -0.2f, 0.0f, 1.0f,
-	 0.2f, -0.2f, 1.0f, 1.0f,
+	//  X      Y
+	-0.2f,  0.2f,
+	 0.2f,  0.2f,
+	-0.2f, -0.2f,
+	 0.2f, -0.2f,
 };
 
 Renderer *CreateGfxOpenGLShader(OSystem *system) {
@@ -96,7 +97,8 @@ ShaderRenderer::ShaderRenderer(OSystem *system) :
 		_offsetVBO(0),
 		_fadeVBO(0),
 		_viewportVBO(0),
-		_bitmapVBO(0) {
+		_bitmapVBO(0),
+		_textures{} {
 }
 
 ShaderRenderer::~ShaderRenderer() {
@@ -144,22 +146,16 @@ void ShaderRenderer::init() {
 	static const char *bitmapAttributes[] = { "position", "texcoord", nullptr };
 	_bitmapShader = OpenGL::Shader::fromFiles("playground3d_bitmap", bitmapAttributes);
 	_bitmapVBO = OpenGL::Shader::createBuffer(GL_ARRAY_BUFFER, sizeof(bitmapVertices), bitmapVertices);
-	_bitmapShader->enableVertexAttribute("position", _bitmapVBO, 2, GL_FLOAT, GL_TRUE, 4 * sizeof(float), 0);
-	_bitmapShader->enableVertexAttribute("texcoord", _bitmapVBO, 2, GL_FLOAT, GL_TRUE, 4 * sizeof(float), 8);
-
-	glGenTextures(5, _textureRgbaId);
-	glGenTextures(5, _textureRgbId);
-	glGenTextures(2, _textureRgb565Id);
-	glGenTextures(2, _textureRgba5551Id);
-	glGenTextures(2, _textureRgba4444Id);
+	_bitmapShader->enableVertexAttribute("position", _bitmapVBO, 2, GL_FLOAT, GL_TRUE, 2 * sizeof(float), 0);
+	_bitmapTexVBO = OpenGL::Shader::createBuffer(GL_ARRAY_BUFFER, 4 * 2 * sizeof(GLfloat), nullptr, GL_DYNAMIC_DRAW);
+	_bitmapShader->enableVertexAttribute("texcoord", _bitmapTexVBO, 2, GL_FLOAT, GL_TRUE, 2 * sizeof(float), 0);
 }
 
 void ShaderRenderer::deinit() {
-	glDeleteTextures(5, _textureRgbaId);
-	glDeleteTextures(5, _textureRgbId);
-	glDeleteTextures(2, _textureRgb565Id);
-	glDeleteTextures(2, _textureRgba5551Id);
-	glDeleteTextures(2, _textureRgba4444Id);
+	for(int i = 0; i < ARRAYSIZE(_textures); i++) {
+		delete _textures[i];
+		_textures[i] = nullptr;
+	}
 }
 
 void ShaderRenderer::clear(const Math::Vector4d &clearColor) {
@@ -168,42 +164,43 @@ void ShaderRenderer::clear(const Math::Vector4d &clearColor) {
 }
 
 void ShaderRenderer::loadTextureRGBA(Graphics::Surface *texture) {
-	glBindTexture(GL_TEXTURE_2D, _textureRgbaId[0]);
-	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texture->w, texture->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, texture->getPixels());
-	glBindTexture(GL_TEXTURE_2D, _textureRgbaId[1]);
-	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texture->w, texture->h, 0, GL_BGRA, GL_UNSIGNED_BYTE, texture->getPixels());
+	if (!_textures[TextureType::RGBA8888]) {
+		_textures[TextureType::RGBA8888] = new OpenGL::Texture(GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE);
+	}
+	_textures[TextureType::RGBA8888]->setSize(texture->w, texture->h);
+	_textures[TextureType::RGBA8888]->updateArea(Common::Rect(texture->w, texture->h), *texture);
 }
 
 void ShaderRenderer::loadTextureRGB(Graphics::Surface *texture) {
-	glBindTexture(GL_TEXTURE_2D, _textureRgbId[0]);
-	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texture->w, texture->h, 0, GL_RGB, GL_UNSIGNED_BYTE, texture->getPixels());
+	if (!_textures[TextureType::RGB888]) {
+		_textures[TextureType::RGB888] = new OpenGL::Texture(GL_RGB, GL_RGB, GL_UNSIGNED_BYTE);
+	}
+	_textures[TextureType::RGB888]->setSize(texture->w, texture->h);
+	_textures[TextureType::RGB888]->updateArea(Common::Rect(texture->w, texture->h), *texture);
 }
 
 void ShaderRenderer::loadTextureRGB565(Graphics::Surface *texture) {
-	glBindTexture(GL_TEXTURE_2D, _textureRgb565Id[0]);
-	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texture->w, texture->h, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, texture->getPixels());
+	if (!_textures[TextureType::RGB565]) {
+		_textures[TextureType::RGB565] = new OpenGL::Texture(GL_RGB, GL_RGB, GL_UNSIGNED_SHORT_5_6_5);
+	}
+	_textures[TextureType::RGB565]->setSize(texture->w, texture->h);
+	_textures[TextureType::RGB565]->updateArea(Common::Rect(texture->w, texture->h), *texture);
 }
 
 void ShaderRenderer::loadTextureRGBA5551(Graphics::Surface *texture) {
-	glBindTexture(GL_TEXTURE_2D, _textureRgba5551Id[0]);
-	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texture->w, texture->h, 0, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, texture->getPixels());
+	if (!_textures[TextureType::RGBA5551]) {
+		_textures[TextureType::RGBA5551] = new OpenGL::Texture(GL_RGBA, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1);
+	}
+	_textures[TextureType::RGBA5551]->setSize(texture->w, texture->h);
+	_textures[TextureType::RGBA5551]->updateArea(Common::Rect(texture->w, texture->h), *texture);
 }
 
 void ShaderRenderer::loadTextureRGBA4444(Graphics::Surface *texture) {
-	glBindTexture(GL_TEXTURE_2D, _textureRgba4444Id[0]);
-	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texture->w, texture->h, 0, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, texture->getPixels());
+	if (!_textures[TextureType::RGBA4444]) {
+		_textures[TextureType::RGBA4444] = new OpenGL::Texture(GL_RGBA, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4);
+	}
+	_textures[TextureType::RGBA4444]->setSize(texture->w, texture->h);
+	_textures[TextureType::RGBA4444]->updateArea(Common::Rect(texture->w, texture->h), *texture);
 }
 
 void ShaderRenderer::setupViewport(int x, int y, int width, int height) {
@@ -315,37 +312,49 @@ void ShaderRenderer::drawRgbaTexture() {
 	glDepthMask(GL_FALSE);
 
 	_bitmapShader->use();
+	glBindBuffer(GL_ARRAY_BUFFER, _bitmapTexVBO);
 
 	offset.setX(-0.8f);
 	offset.setY(0.8f);
 	_bitmapShader->setUniform("offsetXY", offset);
-	glBindTexture(GL_TEXTURE_2D, _textureRgbaId[0]);
-	glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+	glBufferSubData(GL_ARRAY_BUFFER, 0, 4 * 2 * sizeof(GLfloat), _textures[TextureType::RGBA8888]->getTexCoords());
+	if (_textures[TextureType::RGBA8888]->bind()) {
+		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+	}
 
 	offset.setX(-0.3f);
 	offset.setY(0.8f);
 	_bitmapShader->setUniform("offsetXY", offset);
-	glBindTexture(GL_TEXTURE_2D, _textureRgbId[0]);
-	glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+	glBufferSubData(GL_ARRAY_BUFFER, 0, 4 * 2 * sizeof(GLfloat), _textures[TextureType::RGB888]->getTexCoords());
+	if (_textures[TextureType::RGB888]->bind()) {
+		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+	}
 
 	offset.setX(0.2f);
 	offset.setY(0.8f);
 	_bitmapShader->setUniform("offsetXY", offset);
-	glBindTexture(GL_TEXTURE_2D, _textureRgb565Id[0]);
-	glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+	glBufferSubData(GL_ARRAY_BUFFER, 0, 4 * 2 * sizeof(GLfloat), _textures[TextureType::RGB565]->getTexCoords());
+	if (_textures[TextureType::RGB565]->bind()) {
+		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+	}
 
 	offset.setX(0.7f);
 	offset.setY(0.8f);
 	_bitmapShader->setUniform("offsetXY", offset);
-	glBindTexture(GL_TEXTURE_2D, _textureRgba5551Id[0]);
-	glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+	glBufferSubData(GL_ARRAY_BUFFER, 0, 4 * 2 * sizeof(GLfloat), _textures[TextureType::RGBA5551]->getTexCoords());
+	if (_textures[TextureType::RGBA5551]->bind()) {
+		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+	}
 
 	offset.setX(-0.8f);
 	offset.setY(0.2f);
 	_bitmapShader->setUniform("offsetXY", offset);
-	glBindTexture(GL_TEXTURE_2D, _textureRgba4444Id[0]);
-	glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+	glBufferSubData(GL_ARRAY_BUFFER, 0, 4 * 2 * sizeof(GLfloat), _textures[TextureType::RGBA4444]->getTexCoords());
+	if (_textures[TextureType::RGBA4444]->bind()) {
+		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+	}
 
+	glBindBuffer(GL_ARRAY_BUFFER, 0);
 	_bitmapShader->unbind();
 }
 
diff --git a/engines/playground3d/gfx_opengl_shaders.h b/engines/playground3d/gfx_opengl_shaders.h
index e6fb3a51789..e6a606206e6 100644
--- a/engines/playground3d/gfx_opengl_shaders.h
+++ b/engines/playground3d/gfx_opengl_shaders.h
@@ -31,6 +31,10 @@
 
 #include "engines/playground3d/gfx.h"
 
+namespace OpenGL {
+class Texture;
+}
+
 namespace Playground3d {
 
 class ShaderRenderer : public Renderer {
@@ -73,14 +77,11 @@ private:
 	GLuint _fadeVBO;
 	GLuint _viewportVBO;
 	GLuint _bitmapVBO;
+	GLuint _bitmapTexVBO;
 
 	Common::Rect _currentViewport;
 	Math::Vector2d _pos;
-	GLuint _textureRgbaId[5];
-	GLuint _textureRgbId[5];
-	GLuint _textureRgb565Id[2];
-	GLuint _textureRgba5551Id[2];
-	GLuint _textureRgba4444Id[2];
+	OpenGL::Texture *_textures[TextureType::MAX];
 };
 
 } // End of namespace Playground3d


Commit: 52a22918f1cb9ba95d0b7e724988927e8ec54e0d
    https://github.com/scummvm/scummvm/commit/52a22918f1cb9ba95d0b7e724988927e8ec54e0d
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2025-06-01T08:24:34+02:00

Commit Message:
GRAPHICS: OPENGL: Don't destroy an already destroyed texture

This avoids spurious calls after the context have been destroyed too.

Changed paths:
    graphics/opengl/texture.cpp


diff --git a/graphics/opengl/texture.cpp b/graphics/opengl/texture.cpp
index d5c9ef56368..6cc30733eec 100644
--- a/graphics/opengl/texture.cpp
+++ b/graphics/opengl/texture.cpp
@@ -106,6 +106,9 @@ void Texture::setWrapMode(WrapMode wrapMode) {
 }
 
 void Texture::destroy() {
+	if (!_glTexture) {
+		return;
+	}
 	GL_CALL(glDeleteTextures(1, &_glTexture));
 	_glTexture = 0;
 }


Commit: 347ed956172686e133dfc1c4fc649282038a45f6
    https://github.com/scummvm/scummvm/commit/347ed956172686e133dfc1c4fc649282038a45f6
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2025-06-01T08:24:34+02:00

Commit Message:
BACKENDS: OPENGL: Disable OpenGL features at pipeline activation

These features can be disabled when we will render 3D.

Changed paths:
    backends/graphics/opengl/opengl-graphics.cpp
    backends/graphics/opengl/pipelines/fixed.cpp
    backends/graphics/opengl/pipelines/shader.cpp


diff --git a/backends/graphics/opengl/opengl-graphics.cpp b/backends/graphics/opengl/opengl-graphics.cpp
index 0686c69d7f5..bbea75ce40b 100644
--- a/backends/graphics/opengl/opengl-graphics.cpp
+++ b/backends/graphics/opengl/opengl-graphics.cpp
@@ -1374,11 +1374,6 @@ void OpenGLGraphicsManager::notifyContextCreate(ContextType type,
 		error("Can't initialize any pipeline");
 	}
 
-	// Disable 3D properties.
-	GL_CALL(glDisable(GL_CULL_FACE));
-	GL_CALL(glDisable(GL_DEPTH_TEST));
-	GL_CALL(glDisable(GL_DITHER));
-
 	_pipeline->setColor(1.0f, 1.0f, 1.0f, 1.0f);
 
 	// Setup backbuffer state.
diff --git a/backends/graphics/opengl/pipelines/fixed.cpp b/backends/graphics/opengl/pipelines/fixed.cpp
index 2f9c33236c1..e569d135d7e 100644
--- a/backends/graphics/opengl/pipelines/fixed.cpp
+++ b/backends/graphics/opengl/pipelines/fixed.cpp
@@ -28,6 +28,11 @@ namespace OpenGL {
 void FixedPipeline::activateInternal() {
 	Pipeline::activateInternal();
 
+	// Disable 3D properties.
+	GL_CALL(glDisable(GL_CULL_FACE));
+	GL_CALL(glDisable(GL_DEPTH_TEST));
+	GL_CALL(glDisable(GL_DITHER));
+
 	GL_CALL(glDisable(GL_LIGHTING));
 	GL_CALL(glDisable(GL_FOG));
 	GL_CALL(glShadeModel(GL_FLAT));
@@ -74,6 +79,9 @@ void FixedPipeline::setProjectionMatrix(const Math::Matrix4 &projectionMatrix) {
 
 	GL_CALL(glMatrixMode(GL_MODELVIEW));
 	GL_CALL(glLoadIdentity());
+
+	GL_CALL(glMatrixMode(GL_TEXTURE));
+	GL_CALL(glLoadIdentity());
 }
 #endif // !USE_FORCED_GLES2
 
diff --git a/backends/graphics/opengl/pipelines/shader.cpp b/backends/graphics/opengl/pipelines/shader.cpp
index 708a6111e08..b1ede3a8a11 100644
--- a/backends/graphics/opengl/pipelines/shader.cpp
+++ b/backends/graphics/opengl/pipelines/shader.cpp
@@ -52,6 +52,11 @@ ShaderPipeline::~ShaderPipeline() {
 void ShaderPipeline::activateInternal() {
 	Pipeline::activateInternal();
 
+	// Disable 3D properties.
+	GL_CALL(glDisable(GL_CULL_FACE));
+	GL_CALL(glDisable(GL_DEPTH_TEST));
+	GL_CALL(glDisable(GL_DITHER));
+
 	if (OpenGLContext.multitextureSupported) {
 		GL_CALL(glActiveTexture(GL_TEXTURE0));
 	}


Commit: 5d9524078a7526c1c5199ac3eaeb26be91d95f5d
    https://github.com/scummvm/scummvm/commit/5d9524078a7526c1c5199ac3eaeb26be91d95f5d
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2025-06-01T08:24:34+02:00

Commit Message:
SDL: Properly store resizable state for later

When the user disables the resize, make sure it's possible to enable it
back again if the backend allowed it.

Changed paths:
    backends/platform/sdl/sdl-window.cpp


diff --git a/backends/platform/sdl/sdl-window.cpp b/backends/platform/sdl/sdl-window.cpp
index 60e606c6963..dfbc77e7017 100644
--- a/backends/platform/sdl/sdl-window.cpp
+++ b/backends/platform/sdl/sdl-window.cpp
@@ -163,6 +163,12 @@ void SdlWindow::setWindowCaption(const Common::String &caption) {
 }
 
 void SdlWindow::setResizable(bool resizable) {
+#if SDL_VERSION_ATLEAST(2, 0, 0)
+	// Don't allow switching state if the window is not meant to be resized
+	if ((_lastFlags & SDL_WINDOW_RESIZABLE) == 0) {
+		return;
+	}
+#endif
 #if SDL_VERSION_ATLEAST(3, 0, 0)
 	if (_window) {
 		SDL_SetWindowResizable(_window, resizable);
@@ -428,6 +434,7 @@ bool SdlWindow::createOrUpdateWindow(int width, int height, uint32 flags) {
 #endif
 
 #if SDL_VERSION_ATLEAST(2, 0, 0)
+	bool allowResize = flags & SDL_WINDOW_RESIZABLE;
 	if (!_resizable) {
 		flags &= ~SDL_WINDOW_RESIZABLE;
 	}
@@ -551,6 +558,12 @@ bool SdlWindow::createOrUpdateWindow(int width, int height, uint32 flags) {
 #elif SDL_VERSION_ATLEAST(2, 0, 5)
 	SDL_SetWindowResizable(_window, (flags & SDL_WINDOW_RESIZABLE) ? SDL_TRUE : SDL_FALSE);
 #endif
+#if SDL_VERSION_ATLEAST(2, 0, 0)
+	// Restore the flag to allow switching resize state later
+	if (allowResize) {
+		flags |= SDL_WINDOW_RESIZABLE;
+	}
+#endif
 
 #if defined(MACOSX)
 	// macOS windows with the flag SDL_WINDOW_FULLSCREEN_DESKTOP exiting their fullscreen space


Commit: f53d38f6dd0191c967dd40ee2cabf1d1f9e53d49
    https://github.com/scummvm/scummvm/commit/f53d38f6dd0191c967dd40ee2cabf1d1f9e53d49
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2025-06-01T08:24:34+02:00

Commit Message:
SDL: Don't destroy the window when changing the maximized flag

Changed paths:
    backends/platform/sdl/sdl-window.cpp


diff --git a/backends/platform/sdl/sdl-window.cpp b/backends/platform/sdl/sdl-window.cpp
index dfbc77e7017..6eec2ade12e 100644
--- a/backends/platform/sdl/sdl-window.cpp
+++ b/backends/platform/sdl/sdl-window.cpp
@@ -441,13 +441,13 @@ bool SdlWindow::createOrUpdateWindow(int width, int height, uint32 flags) {
 #endif
 
 #if SDL_VERSION_ATLEAST(3, 0, 0)
-	const uint32 updateableFlagsMask = fullscreenMask | SDL_WINDOW_MOUSE_GRABBED | SDL_WINDOW_RESIZABLE;
+	const uint32 updateableFlagsMask = fullscreenMask | SDL_WINDOW_MOUSE_GRABBED | SDL_WINDOW_RESIZABLE | SDL_WINDOW_MAXIMIZED;
 #elif SDL_VERSION_ATLEAST(2, 0, 5)
 	// SDL_WINDOW_RESIZABLE can be updated without recreating the window starting with SDL 2.0.5
 	// Even though some users may switch the SDL version when it's linked dynamically, 2.0.5 is now getting quite old
-	const uint32 updateableFlagsMask = fullscreenMask | SDL_WINDOW_INPUT_GRABBED | SDL_WINDOW_RESIZABLE;
+	const uint32 updateableFlagsMask = fullscreenMask | SDL_WINDOW_INPUT_GRABBED | SDL_WINDOW_RESIZABLE | SDL_WINDOW_MAXIMIZED;
 #else
-	const uint32 updateableFlagsMask = fullscreenMask | SDL_WINDOW_INPUT_GRABBED;
+	const uint32 updateableFlagsMask = fullscreenMask | SDL_WINDOW_INPUT_GRABBED | SDL_WINDOW_MAXIMIZED;
 #endif
 
 	const uint32 oldNonUpdateableFlags = _lastFlags & ~updateableFlagsMask;
@@ -537,6 +537,11 @@ bool SdlWindow::createOrUpdateWindow(int width, int height, uint32 flags) {
 #endif
 		} else {
 			SDL_SetWindowSize(_window, width, height);
+			if (flags & SDL_WINDOW_MAXIMIZED) {
+				SDL_MaximizeWindow(_window);
+			} else {
+				SDL_RestoreWindow(_window);
+			}
 		}
 
 		SDL_SetWindowFullscreen(_window, fullscreenFlags);


Commit: 41ef48ede225922cec03cbbc17ed22c7fb356891
    https://github.com/scummvm/scummvm/commit/41ef48ede225922cec03cbbc17ed22c7fb356891
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2025-06-01T08:24:34+02:00

Commit Message:
BACKENDS: OPENGLSDL3D: Prefer RGB565 over RGBA5551

For the backbuffer, we don't need an alpha channel.

Changed paths:
    backends/graphics3d/openglsdl/openglsdl-graphics3d.cpp


diff --git a/backends/graphics3d/openglsdl/openglsdl-graphics3d.cpp b/backends/graphics3d/openglsdl/openglsdl-graphics3d.cpp
index a9b0c21e9e1..1fc3ebb5157 100644
--- a/backends/graphics3d/openglsdl/openglsdl-graphics3d.cpp
+++ b/backends/graphics3d/openglsdl/openglsdl-graphics3d.cpp
@@ -520,12 +520,12 @@ bool OpenGLSdlGraphics3dManager::createOrUpdateGLContext(uint gameWidth, uint ga
 	if (_antialiasing > 0 && !renderToFramebuffer) {
 		// Don't enable screen level multisampling when rendering to a framebuffer
 		pixelFormats.push_back(OpenGLPixelFormat(32, 8, 8, 8, 8, _antialiasing));
-		pixelFormats.push_back(OpenGLPixelFormat(16, 5, 5, 5, 1, _antialiasing));
 		pixelFormats.push_back(OpenGLPixelFormat(16, 5, 6, 5, 0, _antialiasing));
+		pixelFormats.push_back(OpenGLPixelFormat(16, 5, 5, 5, 1, _antialiasing));
 	}
 	pixelFormats.push_back(OpenGLPixelFormat(32, 8, 8, 8, 8, 0));
-	pixelFormats.push_back(OpenGLPixelFormat(16, 5, 5, 5, 1, 0));
 	pixelFormats.push_back(OpenGLPixelFormat(16, 5, 6, 5, 0, 0));
+	pixelFormats.push_back(OpenGLPixelFormat(16, 5, 5, 5, 1, 0));
 
 	bool clear = false;
 


Commit: b1da854ce371147ae432bc6886cdca23760aa359
    https://github.com/scummvm/scummvm/commit/b1da854ce371147ae432bc6886cdca23760aa359
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2025-06-01T08:24:34+02:00

Commit Message:
BACKENDS: OPENGL: Allow to disable the current pipeline whichever it is

This will be used by the 3D renderer.

Changed paths:
    backends/graphics/opengl/pipelines/pipeline.h


diff --git a/backends/graphics/opengl/pipelines/pipeline.h b/backends/graphics/opengl/pipelines/pipeline.h
index d6d1f042ed4..92a7c7c7544 100644
--- a/backends/graphics/opengl/pipelines/pipeline.h
+++ b/backends/graphics/opengl/pipelines/pipeline.h
@@ -23,8 +23,6 @@
 #define BACKENDS_GRAPHICS_OPENGL_PIPELINES_PIPELINE_H
 
 #include "graphics/opengl/system_headers.h"
-
-#include "backends/graphics/opengl/framebuffer.h"
 #include "graphics/opengl/texture.h"
 
 #include "math/matrix4.h"
@@ -41,6 +39,11 @@ class Framebuffer;
  */
 class Pipeline {
 public:
+	/**
+	 * Deactivate any pipeline.
+	 */
+	static void disable() { if (activePipeline) activePipeline->deactivate(); }
+
 	Pipeline();
 	virtual ~Pipeline() { if (isActive()) deactivate(); }
 


Commit: 3ebfe3aeecfec691b10111f81663c59c57ac43eb
    https://github.com/scummvm/scummvm/commit/3ebfe3aeecfec691b10111f81663c59c57ac43eb
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2025-06-01T08:24:34+02:00

Commit Message:
BACKENDS: OPENGLSDL: Factorize context destruction

Changed paths:
    backends/graphics/openglsdl/openglsdl-graphics.cpp
    backends/graphics/openglsdl/openglsdl-graphics.h


diff --git a/backends/graphics/openglsdl/openglsdl-graphics.cpp b/backends/graphics/openglsdl/openglsdl-graphics.cpp
index 0b3b38c77c1..a0c90a02387 100644
--- a/backends/graphics/openglsdl/openglsdl-graphics.cpp
+++ b/backends/graphics/openglsdl/openglsdl-graphics.cpp
@@ -224,7 +224,14 @@ OpenGLSdlGraphicsManager::OpenGLSdlGraphicsManager(SdlEventSource *eventSource,
 }
 
 OpenGLSdlGraphicsManager::~OpenGLSdlGraphicsManager() {
+	deinitOpenGLContext();
+}
+
+void OpenGLSdlGraphicsManager::deinitOpenGLContext() {
 #if SDL_VERSION_ATLEAST(2, 0, 0)
+	if (!_glContext) {
+		return;
+	}
 
 #ifdef USE_IMGUI
 	destroyImGui();
@@ -232,10 +239,13 @@ OpenGLSdlGraphicsManager::~OpenGLSdlGraphicsManager() {
 
 	notifyContextDestroy();
 	sdlGLDestroyContext(_glContext);
-#else
+
+	_glContext = nullptr;
+#else // SDL_VERSION_ATLEAST(2, 0, 0)
 	if (_hwScreen) {
 		notifyContextDestroy();
 	}
+	_hwScreen = nullptr;
 #endif
 }
 
@@ -552,6 +562,9 @@ bool OpenGLSdlGraphicsManager::saveScreenshot(const Common::Path &filename) cons
 }
 
 bool OpenGLSdlGraphicsManager::setupMode(uint width, uint height) {
+	// Destroy OpenGL context before messing with the window
+	deinitOpenGLContext();
+
 	// In case we request a fullscreen mode we will use the mode the user
 	// has chosen last time or the biggest mode available.
 	if (_wantsFullScreen) {
@@ -599,17 +612,6 @@ bool OpenGLSdlGraphicsManager::setupMode(uint width, uint height) {
 	const Graphics::PixelFormat rgba8888 = OpenGL::Texture::getRGBAPixelFormat();
 
 #if SDL_VERSION_ATLEAST(2, 0, 0)
-	if (_glContext) {
-		notifyContextDestroy();
-
-#ifdef USE_IMGUI
-		destroyImGui();
-#endif
-
-		sdlGLDestroyContext(_glContext);
-		_glContext = nullptr;
-	}
-
 	// Request a OpenGL (ES) context we can use.
 	// This must be done before any window creation
 	SDL_GL_ResetAttributes();
@@ -720,14 +722,6 @@ bool OpenGLSdlGraphicsManager::setupMode(uint width, uint height) {
 		flags |= SDL_RESIZABLE;
 	}
 
-	if (_hwScreen) {
-		// When a video mode has been setup already we notify the manager that
-		// the context is about to be destroyed.
-		// We do this because on Windows SDL_SetVideoMode can destroy and
-		// recreate the OpenGL context.
-		notifyContextDestroy();
-	}
-
 	SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, _vsync ? 1 : 0);
 
 	_hwScreen = SDL_SetVideoMode(width, height, 32, flags);
diff --git a/backends/graphics/openglsdl/openglsdl-graphics.h b/backends/graphics/openglsdl/openglsdl-graphics.h
index de676764fbe..336657da59e 100644
--- a/backends/graphics/openglsdl/openglsdl-graphics.h
+++ b/backends/graphics/openglsdl/openglsdl-graphics.h
@@ -67,6 +67,8 @@ protected:
 private:
 	bool setupMode(uint width, uint height);
 
+	void deinitOpenGLContext();
+
 #if SDL_VERSION_ATLEAST(2, 0, 0)
 	int _glContextProfileMask, _glContextMajor, _glContextMinor;
 


Commit: 24ee317adf28310e20c1fc9fd817ff9d683ea915
    https://github.com/scummvm/scummvm/commit/24ee317adf28310e20c1fc9fd817ff9d683ea915
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2025-06-01T08:24:34+02:00

Commit Message:
BACKENDS: OPENGLSDL: Test several graphical modes

Instead of sticking to RGBA8888 which may not be available on old
platforms with a 16-bits desktop, try all modes like the OpenGL 3D
backend.

Changed paths:
    backends/graphics/openglsdl/openglsdl-graphics.cpp


diff --git a/backends/graphics/openglsdl/openglsdl-graphics.cpp b/backends/graphics/openglsdl/openglsdl-graphics.cpp
index a0c90a02387..c2d60c95e8d 100644
--- a/backends/graphics/openglsdl/openglsdl-graphics.cpp
+++ b/backends/graphics/openglsdl/openglsdl-graphics.cpp
@@ -73,21 +73,14 @@ OpenGLSdlGraphicsManager::OpenGLSdlGraphicsManager(SdlEventSource *eventSource,
 #endif
 	  _graphicsScale(2), _gotResize(false), _wantsFullScreen(false), _ignoreResizeEvents(0),
 	  _desiredFullscreenWidth(0), _desiredFullscreenHeight(0) {
-	// Setup OpenGL attributes for SDL
-	SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
-	SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
-	SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
-	SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8);
-	SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);
-	SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
 
 	// Set up proper SDL OpenGL context creation.
 #if SDL_VERSION_ATLEAST(2, 0, 0)
-	// Context version 1.4 is chosen arbitrarily based on what most shader
+	// Context version 1.3 is chosen arbitrarily based on what most shader
 	// extensions were written against.
 	enum {
 		DEFAULT_GL_MAJOR = 1,
-		DEFAULT_GL_MINOR = 4,
+		DEFAULT_GL_MINOR = 3,
 
 		DEFAULT_GLES_MAJOR = 1,
 		DEFAULT_GLES_MINOR = 1,
@@ -163,7 +156,7 @@ OpenGLSdlGraphicsManager::OpenGLSdlGraphicsManager(SdlEventSource *eventSource,
 		_glContextType = OpenGL::kContextGL;
 	}
 #endif
-#else
+#else // SDL_VERSION_ATLEAST(2, 0, 0)
 	_glContextType = OpenGL::kContextGL;
 #endif
 
@@ -604,152 +597,205 @@ bool OpenGLSdlGraphicsManager::setupMode(uint width, uint height) {
 		ConfMan.setInt("last_fullscreen_mode_height", _desiredFullscreenHeight, Common::ConfigManager::kApplicationDomain);
 	}
 
-	// This is pretty confusing since RGBA8888 talks about the memory
-	// layout here. This is a different logical layout depending on
-	// whether we run on little endian or big endian. However, we can
-	// only safely assume that RGBA8888 in memory layout is supported.
-	// Thus, we chose this one.
-	const Graphics::PixelFormat rgba8888 = OpenGL::Texture::getRGBAPixelFormat();
+	Common::Array<Graphics::PixelFormat> formats;
+#if SDL_VERSION_ATLEAST(2, 0, 0)
+	if (_window->getSDLWindow() && _defaultFormat.bytesPerPixel > 0)
+#else
+	if (_hwScreen && _defaultFormat.bytesPerPixel > 0)
+#endif
+	{
+		formats = { _defaultFormat, _defaultFormatAlpha };
+	} else {
+		formats = {
+			// First format: RGB888/RGBA8888
+			OpenGL::Texture::getRGBPixelFormat(),
+			OpenGL::Texture::getRGBAPixelFormat(),
+			// Second format: RGB565/RGB5551
+			Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0),
+			Graphics::PixelFormat(2, 5, 5, 5, 1, 11, 6, 1, 0),
+			// Third format: RGB5551/RGB5551
+			Graphics::PixelFormat(2, 5, 5, 5, 1, 11, 6, 1, 0),
+			Graphics::PixelFormat(2, 5, 5, 5, 1, 11, 6, 1, 0)
+		};
+	}
+
+	for (Common::Array<Graphics::PixelFormat>::const_iterator it = formats.begin(); ; it += 2) {
+		if (it == formats.end()) {
+			// We failed to get a proper window
+			return false;
+		}
+
+#if SDL_VERSION_ATLEAST(2, 0, 0)
+		SDL_GL_ResetAttributes();
+#endif
+		SDL_GL_SetAttribute(SDL_GL_RED_SIZE, it->rBits());
+		SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, it->gBits());
+		SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, it->bBits());
+		SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, it->aBits());
+		if (_glContextType != OpenGL::kContextGLES) {
+			// Always request 24-bits depth buffer and stencil buffer even in 2D to avoid extraneous context switches
+			SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
+		} else {
+			SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);
+		}
+		SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
+		SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
+		SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 0);
+		SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 0);
 
 #if SDL_VERSION_ATLEAST(2, 0, 0)
-	// Request a OpenGL (ES) context we can use.
-	// This must be done before any window creation
-	SDL_GL_ResetAttributes();
-	SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, _glContextProfileMask);
-	SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, _glContextMajor);
-	SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, _glContextMinor);
+		// Request a OpenGL (ES) context we can use.
+		// This must be done before any window creation
+		SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, _glContextProfileMask);
+		SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, _glContextMajor);
+		SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, _glContextMinor);
 
 #if SDL_VERSION_ATLEAST(3, 0, 0)
-	uint32 flags = SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_HIGH_PIXEL_DENSITY;
+		uint32 flags = SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_HIGH_PIXEL_DENSITY;
 #else
-	uint32 flags = SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI;
+		uint32 flags = SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI;
 #endif
 
-	if (_wantsFullScreen) {
-		// On Linux/X11, when toggling to fullscreen, the window manager saves
-		// the window size to be able to restore it when going back to windowed mode.
-		// If the user configured ScummVM to start in fullscreen mode, we first
-		// create a window and then toggle it to fullscreen to give the window manager
-		// a chance to save the window size. That way if the user switches back
-		// to windowed mode, the window manager has a window size to apply instead
-		// of leaving the window at the fullscreen resolution size.
-		const char *driver = SDL_GetCurrentVideoDriver();
-		if (!_window->getSDLWindow() && driver && strcmp(driver, "x11") == 0) {
-			_window->createOrUpdateWindow(width, height, flags);
-		}
+		if (_wantsFullScreen) {
+			// On Linux/X11, when toggling to fullscreen, the window manager saves
+			// the window size to be able to restore it when going back to windowed mode.
+			// If the user configured ScummVM to start in fullscreen mode, we first
+			// create a window and then toggle it to fullscreen to give the window manager
+			// a chance to save the window size. That way if the user switches back
+			// to windowed mode, the window manager has a window size to apply instead
+			// of leaving the window at the fullscreen resolution size.
+			const char *driver = SDL_GetCurrentVideoDriver();
+			if (!_window->getSDLWindow() && driver && strcmp(driver, "x11") == 0) {
+				_window->createOrUpdateWindow(width, height, flags);
+			}
 
-		width  = _desiredFullscreenWidth;
-		height = _desiredFullscreenHeight;
+			width  = _desiredFullscreenWidth;
+			height = _desiredFullscreenHeight;
 
 #if SDL_VERSION_ATLEAST(3, 0, 0)
-		flags |= SDL_WINDOW_FULLSCREEN;
-		SDL_SetWindowFullscreenMode(_window->getSDLWindow(), NULL);
-		SDL_SyncWindow(_window->getSDLWindow());
+			flags |= SDL_WINDOW_FULLSCREEN;
+			SDL_SetWindowFullscreenMode(_window->getSDLWindow(), NULL);
+			SDL_SyncWindow(_window->getSDLWindow());
 #else
-		flags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
+			flags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
 #endif
-	}
+		}
 
-	if (!_wantsFullScreen && ConfMan.getBool("window_maximized", Common::ConfigManager::kApplicationDomain)) {
-		flags |= SDL_WINDOW_MAXIMIZED;
-	}
+		if (!_wantsFullScreen && ConfMan.getBool("window_maximized", Common::ConfigManager::kApplicationDomain)) {
+			flags |= SDL_WINDOW_MAXIMIZED;
+		}
 
 #if defined(NINTENDO_SWITCH) && !SDL_VERSION_ATLEAST(3, 0, 0)
-	// Switch quirk: Switch seems to need this flag, otherwise the screen
-	// is zoomed when switching from Normal graphics mode to OpenGL
-	flags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
+		// Switch quirk: Switch seems to need this flag, otherwise the screen
+		// is zoomed when switching from Normal graphics mode to OpenGL
+		flags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
 #endif
-	if (!createOrUpdateWindow(width, height, flags)) {
-		return false;
-	}
+		if (!createOrUpdateWindow(width, height, flags)) {
+			// Try the next pixel format
+			continue;
+		}
 
-	_glContext = SDL_GL_CreateContext(_window->getSDLWindow());
-	if (!_glContext) {
-		return false;
-	}
+		_glContext = SDL_GL_CreateContext(_window->getSDLWindow());
+		if (!_glContext) {
+			warning("SDL_GL_CreateContext failed: %s", SDL_GetError());
+			// Try the next pixel format
+			continue;
+		}
 
-	if (!sdlSetSwapInterval(_vsync ? 1 : 0)) {
-		warning("Unable to %s VSync: %s", _vsync ? "enable" : "disable", SDL_GetError());
-	}
+		if (!sdlSetSwapInterval(_vsync ? 1 : 0)) {
+			warning("Unable to %s VSync: %s", _vsync ? "enable" : "disable", SDL_GetError());
+		}
 
-	notifyContextCreate(_glContextType, new OpenGL::Backbuffer(), rgba8888, rgba8888);
-	int actualWidth, actualHeight;
-	getWindowSizeFromSdl(&actualWidth, &actualHeight);
+		notifyContextCreate(_glContextType, new OpenGL::Backbuffer(), it[0], it[1]);
+		int actualWidth, actualHeight;
+		getWindowSizeFromSdl(&actualWidth, &actualHeight);
 
-	handleResize(actualWidth, actualHeight);
+		handleResize(actualWidth, actualHeight);
 
 #ifdef USE_IMGUI
-	// Setup Dear ImGui
-	initImGui(nullptr, _glContext);
+		// Setup Dear ImGui
+		initImGui(nullptr, _glContext);
 #endif
 
 #ifdef WIN32
-	// WORKAROUND: Prevent (nearly) offscreen positioning of the ScummVM window by forcefully
-	// trigger a re-positioning event to center the window.
-	if (!_wantsFullScreen && !(SDL_GetWindowFlags(_window->getSDLWindow()) & SDL_WINDOW_MAXIMIZED)) {
-
-		// Read the current window position
-		int _xWindowPos;
-		SDL_GetWindowPosition(_window->getSDLWindow(), &_xWindowPos, nullptr);
-
-		// Relocate the window to the center of the screen in case we try to draw
-		// outside the window area. In this case, _xWindowPos always returns 0.
-		if (_xWindowPos == 0) {
-			SDL_SetWindowPosition(_window->getSDLWindow(), SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED);
+		// WORKAROUND: Prevent (nearly) offscreen positioning of the ScummVM window by forcefully
+		// trigger a re-positioning event to center the window.
+		if (!_wantsFullScreen && !(SDL_GetWindowFlags(_window->getSDLWindow()) & SDL_WINDOW_MAXIMIZED)) {
+
+			// Read the current window position
+			int _xWindowPos;
+			SDL_GetWindowPosition(_window->getSDLWindow(), &_xWindowPos, nullptr);
+
+			// Relocate the window to the center of the screen in case we try to draw
+			// outside the window area. In this case, _xWindowPos always returns 0.
+			if (_xWindowPos == 0) {
+				SDL_SetWindowPosition(_window->getSDLWindow(), SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED);
+			}
 		}
-	}
 #endif
-	return true;
-#else
-	// WORKAROUND: Working around infamous SDL bugs when switching
-	// resolutions too fast. This might cause the event system to supply
-	// incorrect mouse position events otherwise.
-	// Reference: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=665779
-	const uint32 curTime = SDL_GetTicks();
-	if (_hwScreen && (curTime < _lastVideoModeLoad || curTime - _lastVideoModeLoad < 100)) {
-		for (int i = 10; i > 0; --i) {
-			SDL_PumpEvents();
-			SDL_Delay(10);
+#else // SDL_VERSION_ATLEAST(2, 0, 0)
+		// WORKAROUND: Working around infamous SDL bugs when switching
+		// resolutions too fast. This might cause the event system to supply
+		// incorrect mouse position events otherwise.
+		// Reference: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=665779
+		const uint32 curTime = SDL_GetTicks();
+		if (_hwScreen && (curTime < _lastVideoModeLoad || curTime - _lastVideoModeLoad < 100)) {
+			for (int i = 10; i > 0; --i) {
+				SDL_PumpEvents();
+				SDL_Delay(10);
+			}
 		}
-	}
 
-	uint32 flags = SDL_OPENGL;
-	if (_wantsFullScreen) {
-		width  = _desiredFullscreenWidth;
-		height = _desiredFullscreenHeight;
-		flags |= SDL_FULLSCREEN;
-	} else {
-		flags |= SDL_RESIZABLE;
-	}
+		uint32 flags = SDL_OPENGL;
+		if (_wantsFullScreen) {
+			width  = _desiredFullscreenWidth;
+			height = _desiredFullscreenHeight;
+			flags |= SDL_FULLSCREEN;
+		} else {
+			flags |= SDL_RESIZABLE;
+		}
 
-	SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, _vsync ? 1 : 0);
+		SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, _vsync ? 1 : 0);
 
-	_hwScreen = SDL_SetVideoMode(width, height, 32, flags);
+		_hwScreen = SDL_SetVideoMode(width, height, 32, flags);
 
-	if (!_hwScreen) {
-		// We treat fullscreen requests as a "hint" for now. This means in
-		// case it is not available we simply ignore it.
-		if (_wantsFullScreen) {
-			_hwScreen = SDL_SetVideoMode(width, height, 32, SDL_OPENGL | SDL_RESIZABLE);
+		if (!_hwScreen) {
+			// We treat fullscreen requests as a "hint" for now. This means in
+			// case it is not available we simply ignore it.
+			if (_wantsFullScreen) {
+				_hwScreen = SDL_SetVideoMode(width, height, 32, SDL_OPENGL | SDL_RESIZABLE);
+			}
 		}
-	}
 
-	// Part of the WORKAROUND mentioned above.
-	_lastVideoModeLoad = SDL_GetTicks();
+		if (!_hwScreen) {
+			// Try the next pixel format
+			continue;
+		}
 
-	if (_hwScreen) {
-		notifyContextCreate(_glContextType, new OpenGL::Backbuffer(), rgba8888, rgba8888);
+		// Part of the WORKAROUND mentioned above.
+		_lastVideoModeLoad = SDL_GetTicks();
+
+		notifyContextCreate(_glContextType, new OpenGL::Backbuffer(), it[0], it[1]);
 		handleResize(_hwScreen->w, _hwScreen->h);
-	}
 
-	// Ignore resize events (from SDL) for a few frames, if this isn't
-	// caused by a notification from SDL. This avoids bad resizes to a
-	// (former) resolution for which we haven't processed an event yet.
-	if (!_gotResize)
-		_ignoreResizeEvents = 10;
+		// Ignore resize events (from SDL) for a few frames, if this isn't
+		// caused by a notification from SDL. This avoids bad resizes to a
+		// (former) resolution for which we haven't processed an event yet.
+		if (!_gotResize)
+			_ignoreResizeEvents = 10;
 
-	return _hwScreen != nullptr;
 #endif
+		// Display a warning if the effective pixel format is not the preferred one
+		if (it != formats.begin()) {
+			warning("Couldn't create a %d-bit visual, using to %d-bit instead",
+				formats.front().bpp(),
+				it->bpp());
+		}
+
+		return true;
+	}
+	// We should never end up here
+	return false;
 }
 
 bool OpenGLSdlGraphicsManager::notifyEvent(const Common::Event &event) {


Commit: a04fbf4bdbe7952cfb67c5945a7561f7a9414223
    https://github.com/scummvm/scummvm/commit/a04fbf4bdbe7952cfb67c5945a7561f7a9414223
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2025-06-01T08:24:34+02:00

Commit Message:
BACKENDS: OPENGL: Allow to request a fixed-size window and antialiasing

It's unused for now but will be soon.

Changed paths:
    backends/graphics/android/android-graphics.cpp
    backends/graphics/android/android-graphics.h
    backends/graphics/ios/ios-graphics.cpp
    backends/graphics/ios/ios-graphics.h
    backends/graphics/opengl/opengl-graphics.cpp
    backends/graphics/opengl/opengl-graphics.h
    backends/graphics/openglsdl/openglsdl-graphics.cpp
    backends/graphics/openglsdl/openglsdl-graphics.h
    backends/platform/libretro/include/libretro-graphics-opengl.h


diff --git a/backends/graphics/android/android-graphics.cpp b/backends/graphics/android/android-graphics.cpp
index d98dd235506..baa74a870c1 100644
--- a/backends/graphics/android/android-graphics.cpp
+++ b/backends/graphics/android/android-graphics.cpp
@@ -217,9 +217,15 @@ float AndroidGraphicsManager::getHiDPIScreenFactor() const {
 	return dpi[2] / 1.2f;
 }
 
-bool AndroidGraphicsManager::loadVideoMode(uint requestedWidth, uint requestedHeight, const Graphics::PixelFormat &format) {
+bool AndroidGraphicsManager::loadVideoMode(uint requestedWidth, uint requestedHeight, const Graphics::PixelFormat &format, bool resizable, int antialiasing) {
 	ENTER("%d, %d, %s", requestedWidth, requestedHeight, format.toString().c_str());
 
+	// As GLES2 provides FBO, OpenGL graphics manager must ask us for a resizable surface
+	assert(resizable);
+	if (antialiasing != 0) {
+		warning("Requesting antialiased video mode while not available");
+	}
+
 	// We get this whenever a new resolution is requested. Since Android is
 	// using a fixed output size we do nothing like that here.
 	return true;
diff --git a/backends/graphics/android/android-graphics.h b/backends/graphics/android/android-graphics.h
index 1e8ba5f1d05..70f20723601 100644
--- a/backends/graphics/android/android-graphics.h
+++ b/backends/graphics/android/android-graphics.h
@@ -101,7 +101,7 @@ protected:
 	void hideOverlay() override;
 
 
-	bool loadVideoMode(uint requestedWidth, uint requestedHeight, const Graphics::PixelFormat &format) override;
+	bool loadVideoMode(uint requestedWidth, uint requestedHeight, const Graphics::PixelFormat &format, bool resizable, int antialiasing) override;
 
 	void refreshScreen() override;
 
diff --git a/backends/graphics/ios/ios-graphics.cpp b/backends/graphics/ios/ios-graphics.cpp
index 5497160ce54..00927cb12a8 100644
--- a/backends/graphics/ios/ios-graphics.cpp
+++ b/backends/graphics/ios/ios-graphics.cpp
@@ -88,7 +88,13 @@ bool iOSGraphicsManager::setState(const iOSCommonGraphics::State &state) {
 }
 
 
-bool iOSGraphicsManager::loadVideoMode(uint requestedWidth, uint requestedHeight, const Graphics::PixelFormat &format) {
+bool iOSGraphicsManager::loadVideoMode(uint requestedWidth, uint requestedHeight, const Graphics::PixelFormat &format, bool resizable, int antialiasing) {
+	// As GLES2 provides FBO, OpenGL graphics manager must ask us for a resizable surface
+	assert(resizable);
+	if (antialiasing != 0) {
+		warning("Requesting antialiased video mode while not available");
+	}
+
 	/* The iOS and tvOS video modes are always full screen */
 	return true;
 }
diff --git a/backends/graphics/ios/ios-graphics.h b/backends/graphics/ios/ios-graphics.h
index 3fc7ef59011..4b2a130319b 100644
--- a/backends/graphics/ios/ios-graphics.h
+++ b/backends/graphics/ios/ios-graphics.h
@@ -93,7 +93,7 @@ public:
 protected:
 	void setSystemMousePosition(const int x, const int y) override {}
 
-	bool loadVideoMode(uint requestedWidth, uint requestedHeight, const Graphics::PixelFormat &format) override;
+	bool loadVideoMode(uint requestedWidth, uint requestedHeight, const Graphics::PixelFormat &format, bool resizable, int antialiasing) override;
 	void showOverlay(bool inGUI) override;
 	void hideOverlay() override;
 
diff --git a/backends/graphics/opengl/opengl-graphics.cpp b/backends/graphics/opengl/opengl-graphics.cpp
index bbea75ce40b..d1efb1e2cc8 100644
--- a/backends/graphics/opengl/opengl-graphics.cpp
+++ b/backends/graphics/opengl/opengl-graphics.cpp
@@ -426,11 +426,11 @@ OSystem::TransactionError OpenGLGraphicsManager::endGFXTransaction() {
 
 		if (!loadVideoMode(requestedWidth, requestedHeight,
 #ifdef USE_RGB_COLOR
-		                   _currentState.gameFormat
+		                   _currentState.gameFormat,
 #else
-		                   Graphics::PixelFormat::createFormatCLUT8()
+		                   Graphics::PixelFormat::createFormatCLUT8(),
 #endif
-		                  )
+				  true, 0)
 			|| !(shaderOK = loadShader(_currentState.shader))
 		   // HACK: This is really nasty but we don't have any guarantees of
 		   // a context existing before, which means we don't know the maximum
diff --git a/backends/graphics/opengl/opengl-graphics.h b/backends/graphics/opengl/opengl-graphics.h
index b32f9b44535..39110f3aa96 100644
--- a/backends/graphics/opengl/opengl-graphics.h
+++ b/backends/graphics/opengl/opengl-graphics.h
@@ -271,9 +271,11 @@ protected:
 	 * @parma requestedWidth  This is the requested actual game screen width.
 	 * @param requestedHeight This is the requested actual game screen height.
 	 * @param format          This is the requested pixel format of the virtual game screen.
+	 * @param resizable       This indicates that the window should not be resized because we can't handle it.
+	 * @param antialiasing    This is the requested antialiasing level.
 	 * @return true on success, false otherwise
 	 */
-	virtual bool loadVideoMode(uint requestedWidth, uint requestedHeight, const Graphics::PixelFormat &format) = 0;
+	virtual bool loadVideoMode(uint requestedWidth, uint requestedHeight, const Graphics::PixelFormat &format, bool resizable, int antialiasing) = 0;
 
 	bool loadShader(const Common::Path &fileName);
 
diff --git a/backends/graphics/openglsdl/openglsdl-graphics.cpp b/backends/graphics/openglsdl/openglsdl-graphics.cpp
index c2d60c95e8d..d6a3e3474ab 100644
--- a/backends/graphics/openglsdl/openglsdl-graphics.cpp
+++ b/backends/graphics/openglsdl/openglsdl-graphics.cpp
@@ -72,6 +72,7 @@ OpenGLSdlGraphicsManager::OpenGLSdlGraphicsManager(SdlEventSource *eventSource,
 	  _lastVideoModeLoad(0),
 #endif
 	  _graphicsScale(2), _gotResize(false), _wantsFullScreen(false), _ignoreResizeEvents(0),
+	  _effectiveAntialiasing(-1), _requestedAntialiasing(0), _resizable(true),
 	  _desiredFullscreenWidth(0), _desiredFullscreenHeight(0) {
 
 	// Set up proper SDL OpenGL context creation.
@@ -234,6 +235,7 @@ void OpenGLSdlGraphicsManager::deinitOpenGLContext() {
 	sdlGLDestroyContext(_glContext);
 
 	_glContext = nullptr;
+	_effectiveAntialiasing = -1;
 #else // SDL_VERSION_ATLEAST(2, 0, 0)
 	if (_hwScreen) {
 		notifyContextDestroy();
@@ -438,7 +440,7 @@ void OpenGLSdlGraphicsManager::notifyResize(const int width, const int height) {
 #endif
 }
 
-bool OpenGLSdlGraphicsManager::loadVideoMode(uint requestedWidth, uint requestedHeight, const Graphics::PixelFormat &format) {
+bool OpenGLSdlGraphicsManager::loadVideoMode(uint requestedWidth, uint requestedHeight, const Graphics::PixelFormat &format, bool resizable, int antialiasing) {
 	// This function should never be called from notifyResize thus we know
 	// that the requested size came from somewhere else.
 	_gotResize = false;
@@ -479,14 +481,12 @@ bool OpenGLSdlGraphicsManager::loadVideoMode(uint requestedWidth, uint requested
 		if (requestedHeight == 0)
 			requestedHeight = 100; // Add at least some sane value instead of dividing by zero
 	}
-
 #else
-		// Set the basic window size based on the desktop resolution
-		// since we cannot reliably determine the current window state
-		// on SDL1.
-		requestedWidth  = MAX<uint>(desktopRes.width() / 2, 640);
-		requestedHeight = requestedWidth * 3 / 4;
-
+	// Set the basic window size based on the desktop resolution
+	// since we cannot reliably determine the current window state
+	// on SDL1.
+	requestedWidth  = MAX<uint>(desktopRes.width() / 2, 640);
+	requestedHeight = requestedWidth * 3 / 4;
 #endif
 
 	// In order to prevent any unnecessary downscaling (e.g. when launching
@@ -515,6 +515,15 @@ bool OpenGLSdlGraphicsManager::loadVideoMode(uint requestedWidth, uint requested
 		requestedWidth  = requestedHeight * ratio;
 	}
 
+	// Force the requested size if not resizable
+	if (!resizable) {
+		requestedWidth = _lastRequestedWidth;
+		requestedHeight = _lastRequestedHeight;
+	}
+
+	_requestedAntialiasing = antialiasing;
+	_resizable = resizable;
+
 	// Set up the mode
 	return setupMode(requestedWidth, requestedHeight);
 }
@@ -555,6 +564,21 @@ bool OpenGLSdlGraphicsManager::saveScreenshot(const Common::Path &filename) cons
 }
 
 bool OpenGLSdlGraphicsManager::setupMode(uint width, uint height) {
+#if defined(USE_OPENGL_GAME) || defined(USE_OPENGL_SHADERS)
+	const bool supportsAntialiasing = g_system->getSupportedAntiAliasingLevels().size() > 0;
+#else
+	const bool supportsAntialiasing = false;
+#endif
+
+#if SDL_VERSION_ATLEAST(2, 0, 0)
+	// If current antialiasing is not what's expected, destroy the context and the window
+	// This will force to recreate it
+	if (supportsAntialiasing && _effectiveAntialiasing != _requestedAntialiasing && _glContext) {
+		deinitOpenGLContext();
+		_window->destroyWindow();
+	}
+#endif
+
 	// Destroy OpenGL context before messing with the window
 	deinitOpenGLContext();
 
@@ -619,10 +643,15 @@ bool OpenGLSdlGraphicsManager::setupMode(uint width, uint height) {
 		};
 	}
 
+	int antialiasing = supportsAntialiasing ? _requestedAntialiasing : 0;
 	for (Common::Array<Graphics::PixelFormat>::const_iterator it = formats.begin(); ; it += 2) {
 		if (it == formats.end()) {
-			// We failed to get a proper window
-			return false;
+			if (antialiasing == 0) {
+				// We failed to get a proper window
+				return false;
+			}
+			antialiasing = 0;
+			it = formats.begin();
 		}
 
 #if SDL_VERSION_ATLEAST(2, 0, 0)
@@ -640,8 +669,10 @@ bool OpenGLSdlGraphicsManager::setupMode(uint width, uint height) {
 		}
 		SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
 		SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
-		SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 0);
-		SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 0);
+		if (supportsAntialiasing) {
+			SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, antialiasing > 0);
+			SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, antialiasing);
+		}
 
 #if SDL_VERSION_ATLEAST(2, 0, 0)
 		// Request a OpenGL (ES) context we can use.
@@ -651,10 +682,13 @@ bool OpenGLSdlGraphicsManager::setupMode(uint width, uint height) {
 		SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, _glContextMinor);
 
 #if SDL_VERSION_ATLEAST(3, 0, 0)
-		uint32 flags = SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_HIGH_PIXEL_DENSITY;
+		uint32 flags = SDL_WINDOW_OPENGL | SDL_WINDOW_HIGH_PIXEL_DENSITY;
 #else
-		uint32 flags = SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI;
+		uint32 flags = SDL_WINDOW_OPENGL | SDL_WINDOW_ALLOW_HIGHDPI;
 #endif
+		if (_resizable) {
+			flags |= SDL_WINDOW_RESIZABLE;
+		}
 
 		if (_wantsFullScreen) {
 			// On Linux/X11, when toggling to fullscreen, the window manager saves
@@ -702,6 +736,9 @@ bool OpenGLSdlGraphicsManager::setupMode(uint width, uint height) {
 			continue;
 		}
 
+		// Now that we have a context, the AA is really effective
+		_effectiveAntialiasing = antialiasing;
+
 		if (!sdlSetSwapInterval(_vsync ? 1 : 0)) {
 			warning("Unable to %s VSync: %s", _vsync ? "enable" : "disable", SDL_GetError());
 		}
@@ -751,7 +788,10 @@ bool OpenGLSdlGraphicsManager::setupMode(uint width, uint height) {
 			width  = _desiredFullscreenWidth;
 			height = _desiredFullscreenHeight;
 			flags |= SDL_FULLSCREEN;
-		} else {
+		}
+		if (_resizable) {
+			// In SDL1.2, resizing the window may invalidate the context
+			// This would kill all the engine objects
 			flags |= SDL_RESIZABLE;
 		}
 
@@ -772,6 +812,9 @@ bool OpenGLSdlGraphicsManager::setupMode(uint width, uint height) {
 			continue;
 		}
 
+		// Now that we have a screen, the AA is really effective
+		_effectiveAntialiasing = antialiasing;
+
 		// Part of the WORKAROUND mentioned above.
 		_lastVideoModeLoad = SDL_GetTicks();
 
@@ -786,10 +829,14 @@ bool OpenGLSdlGraphicsManager::setupMode(uint width, uint height) {
 
 #endif
 		// Display a warning if the effective pixel format is not the preferred one
-		if (it != formats.begin()) {
-			warning("Couldn't create a %d-bit visual, using to %d-bit instead",
+		const bool wantsAA = _requestedAntialiasing > 0;
+		const bool gotAA = antialiasing > 0;
+		if (it != formats.begin() || (wantsAA && !gotAA)) {
+			warning("Couldn't create a %d-bit visual%s, using to %d-bit%s instead",
 				formats.front().bpp(),
-				it->bpp());
+				wantsAA && !gotAA ? " with AA" : "",
+				it->bpp(),
+				wantsAA && !gotAA ? " without AA" : "");
 		}
 
 		return true;
diff --git a/backends/graphics/openglsdl/openglsdl-graphics.h b/backends/graphics/openglsdl/openglsdl-graphics.h
index 336657da59e..796c0c88962 100644
--- a/backends/graphics/openglsdl/openglsdl-graphics.h
+++ b/backends/graphics/openglsdl/openglsdl-graphics.h
@@ -56,7 +56,7 @@ public:
 #endif
 
 protected:
-	bool loadVideoMode(uint requestedWidth, uint requestedHeight, const Graphics::PixelFormat &format) override;
+	bool loadVideoMode(uint requestedWidth, uint requestedHeight, const Graphics::PixelFormat &format, bool resizable, int antialiasing) override;
 
 	void refreshScreen() override;
 
@@ -92,6 +92,9 @@ private:
 #endif
 
 	OpenGL::ContextType _glContextType;
+	bool _resizable;
+	int _requestedAntialiasing;
+	int _effectiveAntialiasing;
 
 	uint _forceFrameUpdate = 0;
 	uint _lastRequestedWidth;
diff --git a/backends/platform/libretro/include/libretro-graphics-opengl.h b/backends/platform/libretro/include/libretro-graphics-opengl.h
index fbe502065b4..8a4a51c2fee 100644
--- a/backends/platform/libretro/include/libretro-graphics-opengl.h
+++ b/backends/platform/libretro/include/libretro-graphics-opengl.h
@@ -28,9 +28,9 @@ class Surface;
 class LibretroOpenGLGraphics : public OpenGL::OpenGLGraphicsManager {
 public:
 	LibretroOpenGLGraphics(OpenGL::ContextType contextType);
-	bool loadVideoMode(uint requestedWidth, uint requestedHeight, const Graphics::PixelFormat &format) override {
+	bool loadVideoMode(uint requestedWidth, uint requestedHeight, const Graphics::PixelFormat &format, bool resizable, int antialiasing) override {
 		return true;
-	};
+	}
 	void refreshScreen() override;
 	void setSystemMousePosition(const int x, const int y) override {};
 	void setMouseCursor(const void *buf, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor, bool dontScale, const Graphics::PixelFormat *format, const byte *mask) override;


Commit: 45afd86a424bacdfd02a208f13b5a6718ed92842
    https://github.com/scummvm/scummvm/commit/45afd86a424bacdfd02a208f13b5a6718ed92842
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2025-06-01T08:24:34+02:00

Commit Message:
BACKENDS: OPENGL: Add 3D rendering support

Changed paths:
  A backends/graphics/opengl/renderer3d.cpp
  A backends/graphics/opengl/renderer3d.h
    backends/graphics/opengl/opengl-graphics.cpp
    backends/graphics/opengl/opengl-graphics.h
    backends/graphics/openglsdl/openglsdl-graphics.cpp
    backends/module.mk


diff --git a/backends/graphics/opengl/opengl-graphics.cpp b/backends/graphics/opengl/opengl-graphics.cpp
index d1efb1e2cc8..d08167c3258 100644
--- a/backends/graphics/opengl/opengl-graphics.cpp
+++ b/backends/graphics/opengl/opengl-graphics.cpp
@@ -66,6 +66,10 @@
 #include "backends/graphics/opengl/pipelines/libretro/parser.h"
 #endif
 
+#if defined(USE_OPENGL_GAME) || defined(USE_OPENGL_SHADERS)
+#include "backends/graphics/opengl/renderer3d.h"
+#endif
+
 namespace OpenGL {
 
 OpenGLGraphicsManager::OpenGLGraphicsManager()
@@ -80,6 +84,9 @@ OpenGLGraphicsManager::OpenGLGraphicsManager()
 #if !USE_FORCED_GLES
 	  , _libretroPipeline(nullptr)
 #endif
+#if defined(USE_OPENGL_GAME) || defined(USE_OPENGL_SHADERS)
+	  , _renderer3d(nullptr)
+#endif
 #ifdef USE_OSD
 	  , _osdMessageChangeRequest(false), _osdMessageAlpha(0), _osdMessageFadeStartTime(0), _osdMessageSurface(nullptr),
 	  _osdIconSurface(nullptr)
@@ -94,6 +101,9 @@ OpenGLGraphicsManager::OpenGLGraphicsManager()
 
 OpenGLGraphicsManager::~OpenGLGraphicsManager() {
 	delete _gameScreen;
+#if defined(USE_OPENGL_GAME) || defined(USE_OPENGL_SHADERS)
+	delete _renderer3d;
+#endif
 	delete _overlay;
 	delete _cursor;
 	delete _cursorMask;
@@ -121,6 +131,15 @@ bool OpenGLGraphicsManager::hasFeature(OSystem::Feature f) const {
 	case OSystem::kFeatureScalers:
 #endif
 		return true;
+#if defined(USE_OPENGL_GAME) || defined(USE_OPENGL_SHADERS)
+	case OSystem::kFeatureOpenGLForGame:
+		// No 3D for GLES
+		return OpenGLContext.type != kContextGLES;
+#endif
+#if defined(USE_OPENGL_GAME) || defined(USE_OPENGL_SHADERS)
+	case OSystem::kFeatureShadersForGame:
+		return OpenGLContext.enginesShadersSupported;
+#endif
 
 #if !USE_FORCED_GLES
 	case OSystem::kFeatureShaders:
@@ -193,9 +212,17 @@ int OpenGLGraphicsManager::getDefaultGraphicsMode() const {
 bool OpenGLGraphicsManager::setGraphicsMode(int mode, uint flags) {
 	assert(_transactionMode != kTransactionNone);
 
+	if (flags & OSystem::kGfxModeRender3d) {
+		// In 3D, mode is not used
+		_currentState.graphicsMode = GFX_OPENGL;
+		_currentState.flags = flags;
+		return true;
+	}
+
 	switch (mode) {
 	case GFX_OPENGL:
 		_currentState.graphicsMode = mode;
+		_currentState.flags = flags;
 		return true;
 
 	default:
@@ -390,7 +417,8 @@ OSystem::TransactionError OpenGLGraphicsManager::endGFXTransaction() {
 
 	bool setupNewGameScreen = false;
 	if (   _oldState.gameWidth  != _currentState.gameWidth
-	    || _oldState.gameHeight != _currentState.gameHeight) {
+	    || _oldState.gameHeight != _currentState.gameHeight
+	    || _oldState.flags != _currentState.flags) {
 		setupNewGameScreen = true;
 	}
 
@@ -415,6 +443,36 @@ OSystem::TransactionError OpenGLGraphicsManager::endGFXTransaction() {
 	}
 #endif
 
+	const bool render3d = _currentState.flags & OSystem::kGfxModeRender3d;
+	assert(!render3d || OpenGLContext.type != kContextGLES);
+	const int antialiasing = render3d ? ConfMan.getInt("antialiasing") : 0;
+
+	// 2D engines always render on a texture that can be stretched
+	const bool engineSupportsArbitraryResolutions = !g_engine || !render3d || g_engine->hasFeature(Engine::kSupportsArbitraryResolutions);
+	// Prefer to render on framebuffer if antialiasing is requested: this avoids recreating the window
+	// This is only needed for 3D rendering
+	const bool renderToFrameBuffer = render3d && (!engineSupportsArbitraryResolutions
+#if !USE_FORCED_GLES
+			|| _libretroPipeline
+#endif
+			|| (antialiasing && OpenGLContext.framebufferObjectMultisampleSupported)) &&
+		OpenGLContext.framebufferObjectSupported;
+
+#if defined(USE_OPENGL_GAME) || defined(USE_OPENGL_SHADERS)
+	// Create the 3D renderer first to allow the platform specific code know we are in 3D
+	// The creation doesn't depend on any context existing
+	if (render3d && !_renderer3d) {
+		_renderer3d = new Renderer3D();
+	} else if (!render3d) {
+		delete _renderer3d;
+		_renderer3d = nullptr;
+	}
+#else
+	if (render3d) {
+		error("3D rendering is not available");
+	}
+#endif
+
 	do {
 		const uint desiredAspect = getDesiredGameAspectRatio();
 		const uint requestedWidth  = _currentState.gameWidth;
@@ -430,7 +488,8 @@ OSystem::TransactionError OpenGLGraphicsManager::endGFXTransaction() {
 #else
 		                   Graphics::PixelFormat::createFormatCLUT8(),
 #endif
-				  true, 0)
+				  renderToFrameBuffer || engineSupportsArbitraryResolutions,
+		                  renderToFrameBuffer ? 0 : antialiasing)
 			|| !(shaderOK = loadShader(_currentState.shader))
 		   // HACK: This is really nasty but we don't have any guarantees of
 		   // a context existing before, which means we don't know the maximum
@@ -507,35 +566,42 @@ OSystem::TransactionError OpenGLGraphicsManager::endGFXTransaction() {
 		delete _gameScreen;
 		_gameScreen = nullptr;
 
-		bool wantScaler = _currentState.scaleFactor > 1;
+		if (render3d) {
+#if defined(USE_OPENGL_GAME) || defined(USE_OPENGL_SHADERS)
+			_renderer3d->initSize(_currentState.gameWidth, _currentState.gameHeight, antialiasing, renderToFrameBuffer);
+			_renderer3d->enter3D();
+#endif
+		} else {
+			const bool wantScaler = _currentState.scaleFactor > 1;
 
 #ifdef USE_RGB_COLOR
-		_gameScreen = createSurface(_currentState.gameFormat, false, wantScaler);
+			_gameScreen = createSurface(_currentState.gameFormat, false, wantScaler);
 #else
-		_gameScreen = createSurface(Graphics::PixelFormat::createFormatCLUT8(), false, wantScaler);
+			_gameScreen = createSurface(Graphics::PixelFormat::createFormatCLUT8(), false, wantScaler);
 #endif
-		assert(_gameScreen);
-		if (_gameScreen->hasPalette()) {
-			_gameScreen->setPalette(0, 256, _gamePalette);
-		}
+			assert(_gameScreen);
+			if (_gameScreen->hasPalette()) {
+				_gameScreen->setPalette(0, 256, _gamePalette);
+			}
 
 #ifdef USE_SCALERS
-		if (wantScaler) {
-			_gameScreen->setScaler(_currentState.scalerIndex, _currentState.scaleFactor);
-		}
+			if (wantScaler) {
+				_gameScreen->setScaler(_currentState.scalerIndex, _currentState.scaleFactor);
+			}
 #endif
 
-		_gameScreen->allocate(_currentState.gameWidth, _currentState.gameHeight);
-		// We fill the screen to all black or index 0 for CLUT8.
+			_gameScreen->allocate(_currentState.gameWidth, _currentState.gameHeight);
+			// We fill the screen to all black or index 0 for CLUT8.
 #ifdef USE_RGB_COLOR
-		if (_currentState.gameFormat.bytesPerPixel == 1) {
-			_gameScreen->fill(0);
-		} else {
-			_gameScreen->fill(_gameScreen->getSurface()->format.RGBToColor(0, 0, 0));
-		}
+			if (_currentState.gameFormat.bytesPerPixel == 1) {
+				_gameScreen->fill(0);
+			} else {
+				_gameScreen->fill(_gameScreen->getSurface()->format.RGBToColor(0, 0, 0));
+			}
 #else
-		_gameScreen->fill(0);
+			_gameScreen->fill(0);
 #endif
+		}
 	}
 
 	// Update our display area and cursor scaling. This makes sure we pick up
@@ -582,14 +648,17 @@ int16 OpenGLGraphicsManager::getHeight() const {
 }
 
 void OpenGLGraphicsManager::copyRectToScreen(const void *buf, int pitch, int x, int y, int w, int h) {
+	assert(_gameScreen);
 	_gameScreen->copyRectToTexture(x, y, w, h, buf, pitch);
 }
 
 void OpenGLGraphicsManager::fillScreen(uint32 col) {
+	assert(_gameScreen);
 	_gameScreen->fill(col);
 }
 
 void OpenGLGraphicsManager::fillScreen(const Common::Rect &r, uint32 col) {
+	assert(_gameScreen);
 	_gameScreen->fill(r, col);
 }
 
@@ -638,7 +707,11 @@ void OpenGLGraphicsManager::updateScreen() {
 		rotatedHeight = _windowWidth;
 	}
 
-	if (!_gameScreen || !_pipeline) {
+	if ((!_gameScreen
+#if defined(USE_OPENGL_GAME) || defined(USE_OPENGL_SHADERS)
+		&& !_renderer3d
+#endif
+		) || !_pipeline) {
 		return;
 	}
 
@@ -659,8 +732,11 @@ void OpenGLGraphicsManager::updateScreen() {
 
 	// We only update the screen when there actually have been any changes.
 	if (   !_forceRedraw
-		&& !_cursorNeedsRedraw
-	    && !_gameScreen->isDirty()
+	    && !_cursorNeedsRedraw
+#if defined(USE_OPENGL_GAME) || defined(USE_OPENGL_SHADERS)
+	    && !_renderer3d
+#endif
+	    && !_gameScreen->isDirty() // if _renderer3d is nullptr, _gameScreen is not null
 #if !USE_FORCED_GLES
 	    && !(_libretroPipeline && _libretroPipeline->isAnimated())
 #endif
@@ -673,8 +749,17 @@ void OpenGLGraphicsManager::updateScreen() {
 		return;
 	}
 
+#if defined(USE_OPENGL_GAME) || defined(USE_OPENGL_SHADERS)
+	if (_renderer3d) {
+		_renderer3d->leave3D();
+	}
+#endif
+
 	// Update changes to textures.
-	_gameScreen->updateGLTexture();
+	if (_gameScreen) {
+		_gameScreen->updateGLTexture();
+	}
+
 	if (_cursorVisible && _cursor) {
 		_cursor->updateGLTexture();
 	}
@@ -691,8 +776,13 @@ void OpenGLGraphicsManager::updateScreen() {
 
 	_pipeline->activate();
 
-	// Clear the screen buffer.
-	GL_CALL(glClear(GL_COLOR_BUFFER_BIT));
+	// Clear the screen buffer (when the engine has not drawn on it directly).
+#if defined(USE_OPENGL_GAME) || defined(USE_OPENGL_SHADERS)
+	if (!_renderer3d || _renderer3d->hasTexture())
+#endif
+	{
+		GL_CALL(glClear(GL_COLOR_BUFFER_BIT));
+	}
 
 	if (!_overlayVisible) {
 		// The scissor test is enabled to:
@@ -708,7 +798,14 @@ void OpenGLGraphicsManager::updateScreen() {
 	_targetBuffer->enableBlend(Framebuffer::kBlendModeOpaque);
 
 	// First step: Draw the (virtual) game screen.
-	_pipeline->drawTexture(_gameScreen->getGLTexture(), _gameDrawRect.left, _gameDrawRect.top, _gameDrawRect.width(), _gameDrawRect.height());
+	if (_gameScreen) {
+		_pipeline->drawTexture(_gameScreen->getGLTexture(), _gameDrawRect.left, _gameDrawRect.top, _gameDrawRect.width(), _gameDrawRect.height());
+	}
+#if defined(USE_OPENGL_GAME) || defined(USE_OPENGL_SHADERS)
+	else if (_renderer3d && _renderer3d->hasTexture()) {
+		_pipeline->drawTexture(_renderer3d->getGLTexture(), _gameDrawRect.left, _gameDrawRect.top, _gameDrawRect.width(), _gameDrawRect.height());
+	}
+#endif
 
 	// Second step: Draw the cursor if necessary and we are not in GUI and it
 #if !USE_FORCED_GLES
@@ -800,13 +897,21 @@ void OpenGLGraphicsManager::updateScreen() {
 	_cursorNeedsRedraw = false;
 	_forceRedraw = false;
 	refreshScreen();
+
+#if defined(USE_OPENGL_GAME) || defined(USE_OPENGL_SHADERS)
+	if (_renderer3d) {
+		_renderer3d->enter3D();
+	}
+#endif
 }
 
 Graphics::Surface *OpenGLGraphicsManager::lockScreen() {
+	assert(_gameScreen);
 	return _gameScreen->getSurface();
 }
 
 void OpenGLGraphicsManager::unlockScreen() {
+	assert(_gameScreen);
 	_gameScreen->flagDirty();
 }
 
@@ -832,6 +937,24 @@ int16 OpenGLGraphicsManager::getOverlayHeight() const {
 	}
 }
 
+void OpenGLGraphicsManager::showOverlay(bool inGUI) {
+#if defined(USE_OPENGL_GAME) || defined(USE_OPENGL_SHADERS)
+	if (!_overlayVisible && _renderer3d) {
+		_renderer3d->showOverlay(getOverlayWidth(), getOverlayHeight());
+	}
+#endif
+	WindowedGraphicsManager::showOverlay(inGUI);
+}
+
+void OpenGLGraphicsManager::hideOverlay() {
+#if defined(USE_OPENGL_GAME) || defined(USE_OPENGL_SHADERS)
+	if (_overlayVisible && _renderer3d) {
+		_renderer3d->hideOverlay();
+	}
+#endif
+	WindowedGraphicsManager::hideOverlay();
+}
+
 Graphics::PixelFormat OpenGLGraphicsManager::getOverlayFormat() const {
 	return _overlay->getFormat();
 }
@@ -1251,6 +1374,7 @@ void OpenGLGraphicsManager::displayActivityIconOnOSD(const Graphics::Surface *ic
 }
 
 void OpenGLGraphicsManager::setPalette(const byte *colors, uint start, uint num) {
+	assert(_gameScreen);
 	assert(_gameScreen->hasPalette());
 
 	memcpy(_gamePalette + start * 3, colors, num * 3);
@@ -1261,6 +1385,7 @@ void OpenGLGraphicsManager::setPalette(const byte *colors, uint start, uint num)
 }
 
 void OpenGLGraphicsManager::grabPalette(byte *colors, uint start, uint num) const {
+	assert(_gameScreen);
 	assert(_gameScreen->hasPalette());
 
 	memcpy(colors, _gamePalette + start * 3, num * 3);
@@ -1403,6 +1528,12 @@ void OpenGLGraphicsManager::notifyContextCreate(ContextType type,
 		_gameScreen->recreate();
 	}
 
+#if defined(USE_OPENGL_GAME) || defined(USE_OPENGL_SHADERS)
+	if (_renderer3d) {
+		_renderer3d->recreate();
+	}
+#endif
+
 	if (_overlay) {
 		_overlay->recreate();
 	}
@@ -1431,6 +1562,12 @@ void OpenGLGraphicsManager::notifyContextDestroy() {
 		_gameScreen->destroy();
 	}
 
+#if defined(USE_OPENGL_GAME) || defined(USE_OPENGL_SHADERS)
+	if (_renderer3d) {
+		_renderer3d->destroy();
+	}
+#endif
+
 	if (_overlay) {
 		_overlay->destroy();
 	}
@@ -1632,15 +1769,32 @@ int OpenGLGraphicsManager::getGameRenderScale() const {
 }
 
 void OpenGLGraphicsManager::recalculateDisplayAreas() {
-	if (!_gameScreen) {
+	if (!_gameScreen
+#if defined(USE_OPENGL_GAME) || defined(USE_OPENGL_SHADERS)
+		&& !_renderer3d
+#endif
+		) {
 		return;
 	}
 
+#if defined(USE_OPENGL_GAME) || defined(USE_OPENGL_SHADERS)
+	const bool engineSupportsArbitraryResolutions = !g_engine || g_engine->hasFeature(Engine::kSupportsArbitraryResolutions);
+	if (_renderer3d && engineSupportsArbitraryResolutions) {
+		_currentState.gameWidth = getOverlayWidth();
+		_currentState.gameHeight = getOverlayHeight();
+		_renderer3d->resize(_currentState.gameWidth, _currentState.gameHeight);
+	}
+#endif
+
 	WindowedGraphicsManager::recalculateDisplayAreas();
 
 #if !USE_FORCED_GLES
 	if (_libretroPipeline) {
+#if defined(USE_OPENGL_GAME) || defined(USE_OPENGL_SHADERS)
+		const Texture &gameScreenTexture = _gameScreen ? _gameScreen->getGLTexture() : _renderer3d->getGLTexture();
+#else
 		const Texture &gameScreenTexture = _gameScreen->getGLTexture();
+#endif
 		_libretroPipeline->setDisplaySizes(gameScreenTexture.getLogicalWidth(), gameScreenTexture.getLogicalHeight(),
 				_gameDrawRect);
 	}
@@ -1691,7 +1845,11 @@ void OpenGLGraphicsManager::updateCursorPalette() {
 }
 
 void OpenGLGraphicsManager::recalculateCursorScaling() {
-	if (!_cursor || !_gameScreen) {
+	if (!_cursor || (!_gameScreen
+#if defined(USE_OPENGL_GAME) || defined(USE_OPENGL_SHADERS)
+		&& !_renderer3d
+#endif
+		)) {
 		return;
 	}
 
@@ -1706,7 +1864,8 @@ void OpenGLGraphicsManager::recalculateCursorScaling() {
 
 	// In case scaling is actually enabled we will scale the cursor according
 	// to the game screen.
-	if (!_cursorDontScale) {
+	// 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();
 
diff --git a/backends/graphics/opengl/opengl-graphics.h b/backends/graphics/opengl/opengl-graphics.h
index 39110f3aa96..aec17af63f5 100644
--- a/backends/graphics/opengl/opengl-graphics.h
+++ b/backends/graphics/opengl/opengl-graphics.h
@@ -49,6 +49,9 @@ class Pipeline;
 #if !USE_FORCED_GLES
 class LibRetroPipeline;
 #endif
+#if defined(USE_OPENGL_GAME) || defined(USE_OPENGL_SHADERS)
+class Renderer3D;
+#endif
 
 enum {
 	GFX_OPENGL = 0
@@ -115,6 +118,8 @@ public:
 
 	int16 getOverlayWidth() const override;
 	int16 getOverlayHeight() const override;
+	void showOverlay(bool inGUI) override;
+	void hideOverlay() override;
 
 	Graphics::PixelFormat getOverlayFormat() const override;
 
@@ -196,6 +201,7 @@ protected:
 #endif
 		bool aspectRatioCorrection;
 		int graphicsMode;
+		uint flags;
 		bool filtering;
 
 		uint scalerIndex;
@@ -354,6 +360,13 @@ protected:
 	 */
 	Surface *_gameScreen;
 
+#if defined(USE_OPENGL_GAME) || defined(USE_OPENGL_SHADERS)
+	/**
+	 * The rendering helper for 3D games.
+	 */
+	Renderer3D *_renderer3d;
+#endif
+
 	/**
 	 * The game palette if in CLUT8 mode.
 	 */
diff --git a/backends/graphics/opengl/renderer3d.cpp b/backends/graphics/opengl/renderer3d.cpp
new file mode 100644
index 00000000000..4a75574e63d
--- /dev/null
+++ b/backends/graphics/opengl/renderer3d.cpp
@@ -0,0 +1,430 @@
+/* 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 3 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, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "common/scummsys.h"
+
+#if defined(USE_OPENGL_GAME) || defined(USE_OPENGL_SHADERS)
+
+#include "backends/graphics/opengl/renderer3d.h"
+#include "backends/graphics/opengl/pipelines/pipeline.h"
+
+#include "common/system.h"
+#include "common/textconsole.h"
+
+namespace OpenGL {
+
+static void setupRenderbufferStorage(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height) {
+#if !USE_FORCED_GLES2 || defined(USE_GLAD)
+	if (samples > 1) {
+		glRenderbufferStorageMultisample(target, samples, internalformat, width, height);
+		return;
+	}
+#endif
+	glRenderbufferStorage(target, internalformat, width, height);
+}
+
+// This constructor must not depend on any existing GL context
+Renderer3D::Renderer3D() :
+	_texture(GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, false),
+	_renderBuffers{0, 0, 0}, _frameBuffers{0, 0}, _renderToFrameBuffer(false),
+	_samples(0), _stackLevel(0), _inOverlay(false),
+	_pendingScreenChangeWidth(-1), _pendingScreenChangeHeight(-1) {
+	_texture.enableLinearFiltering(true);
+}
+
+void Renderer3D::destroy() {
+	while (_stackLevel) {
+		enter3D();
+	}
+
+	if (_frameBuffers[0]) {
+		// Check that we did allocated some framebuffer before destroying them
+		// This avoids to call glDeleteFramebuffers and glDeleteRenderbuffers
+		// on platforms not supporting it
+		glDeleteFramebuffers(ARRAYSIZE(_frameBuffers), _frameBuffers);
+		glDeleteRenderbuffers(ARRAYSIZE(_renderBuffers), _renderBuffers);
+		memset(_renderBuffers, 0, sizeof(_renderBuffers));
+		memset(_frameBuffers, 0, sizeof(_frameBuffers));
+	}
+
+	_texture.destroy();
+}
+
+void Renderer3D::initSize(uint w, uint h, int samples, bool renderToFrameBuffer) {
+	_samples = samples;
+	_renderToFrameBuffer = renderToFrameBuffer;
+
+	if (!renderToFrameBuffer) {
+		destroy();
+		_texture.setSize(0, 0);
+		return;
+	}
+
+	_texture.setSize(w, h, true);
+	recreate();
+}
+
+void Renderer3D::resize(uint w, uint h) {
+	assert(!_stackLevel);
+
+	if (!_renderToFrameBuffer) {
+		return;
+	}
+
+	if (_inOverlay) {
+		// While the (GUI) overlay is active, the game doesn't renders
+		// So, instead of loosing the contents of the FBO because of a resize,
+		// just delay it to when we close the GUI.
+		_pendingScreenChangeWidth = w;
+		_pendingScreenChangeHeight = h;
+		return;
+	}
+
+	_texture.setSize(w, h, true);
+	setup();
+
+	// Rebind the framebuffer
+	if (_frameBuffers[1]) {
+		// We are using multisampling
+		glBindFramebuffer(GL_READ_FRAMEBUFFER, _frameBuffers[1]);
+		glBindFramebuffer(GL_DRAW_FRAMEBUFFER, _frameBuffers[0]);
+	} else if (_frameBuffers[0]) {
+		// Draw on framebuffer if one was setup
+		glBindFramebuffer(GL_FRAMEBUFFER, _frameBuffers[0]);
+	}
+}
+
+void Renderer3D::recreate() {
+	destroy();
+
+	if (!_renderToFrameBuffer) {
+		// No framebuffer was requested
+		return;
+	}
+
+	// A 1x antialiasing is not an antialiasing
+	if (_samples > 1) {
+#if !USE_FORCED_GLES2 || defined(USE_GLAD)
+		if (!OpenGLContext.framebufferObjectMultisampleSupported) {
+			warning("The current OpenGL context does not support multisample framebuffer objects");
+			_samples = 0;
+		}
+		if (_samples > OpenGLContext.multisampleMaxSamples) {
+			warning("Requested anti-aliasing with '%d' samples, but the current OpenGL context supports '%d' samples at most",
+					_samples, OpenGLContext.multisampleMaxSamples);
+			_samples = OpenGLContext.multisampleMaxSamples;
+		}
+#else
+		warning("multisample framebuffer objects support is not compiled in");
+		_samples = 0;
+#endif
+	} else {
+		_samples = 0;
+	}
+
+	setup();
+
+	// Context got destroyed
+	_stackLevel = 0;
+}
+
+void Renderer3D::setup() {
+	const bool multiSample = _samples > 1;
+	const uint w = _texture.getLogicalWidth();
+	const uint h = _texture.getLogicalHeight();
+
+	if (!_texture.getGLTexture()) {
+		_texture.create();
+	}
+	glBindTexture(GL_TEXTURE_2D, 0);
+
+	if (!_frameBuffers[0]) {
+		glGenFramebuffers(multiSample ? 2 : 1, _frameBuffers);
+		glGenRenderbuffers(multiSample ? 3 : 2, _renderBuffers);
+	}
+
+	glBindFramebuffer(GL_FRAMEBUFFER, _frameBuffers[multiSample ? 1 : 0]);
+	glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, _texture.getGLTexture(), 0);
+
+	if (multiSample) {
+		glBindFramebuffer(GL_FRAMEBUFFER, _frameBuffers[0]);
+		glBindRenderbuffer(GL_RENDERBUFFER, _renderBuffers[2]);
+		setupRenderbufferStorage(GL_RENDERBUFFER, _samples, GL_RGBA8, w, h);
+		glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, _renderBuffers[2]);
+	}
+
+#ifdef EMSCRIPTEN
+	// See https://www.khronos.org/registry/webgl/specs/latest/1.0/#FBO_ATTACHMENTS
+	glBindRenderbuffer(GL_RENDERBUFFER, _renderBuffers[0]);
+	setupRenderbufferStorage(GL_RENDERBUFFER, _samples, GL_DEPTH_STENCIL, w, h);
+	glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, _renderBuffers[0]);
+#else
+	if (OpenGLContext.packedDepthStencilSupported) {
+		glBindRenderbuffer(GL_RENDERBUFFER, _renderBuffers[0]);
+		setupRenderbufferStorage(GL_RENDERBUFFER, _samples, GL_DEPTH24_STENCIL8, w, h);
+		glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, _renderBuffers[0]);
+		glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, _renderBuffers[0]);
+	} else {
+		glBindRenderbuffer(GL_RENDERBUFFER, _renderBuffers[0]);
+		setupRenderbufferStorage(GL_RENDERBUFFER, _samples, OpenGLContext.OESDepth24 ? GL_DEPTH_COMPONENT24 : GL_DEPTH_COMPONENT16, w, h);
+		glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, _renderBuffers[0]);
+
+		glBindRenderbuffer(GL_RENDERBUFFER, _renderBuffers[1]);
+		setupRenderbufferStorage(GL_RENDERBUFFER, _samples, GL_STENCIL_INDEX8, w, h);
+		glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, _renderBuffers[1]);
+	}
+#endif
+	glBindRenderbuffer(GL_RENDERBUFFER, 0);
+
+	GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+	if (status != GL_FRAMEBUFFER_COMPLETE) {
+		error("Framebuffer is not complete! status: %d", status);
+	}
+
+	if (multiSample) {
+		glBindFramebuffer(GL_FRAMEBUFFER, _frameBuffers[1]);
+		status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+		if (status != GL_FRAMEBUFFER_COMPLETE) {
+			error("Target framebuffer is not complete! status: %d", status);
+		}
+	}
+
+	glBindFramebuffer(GL_FRAMEBUFFER, 0);
+}
+
+void Renderer3D::leave3D() {
+	if (OpenGLContext.type == kContextGL) {
+		// Save current state (only available on OpenGL)
+		glPushAttrib(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_ENABLE_BIT |
+		             GL_LIGHTING_BIT | GL_PIXEL_MODE_BIT | GL_SCISSOR_BIT |
+		             GL_TEXTURE_BIT | GL_TRANSFORM_BIT | GL_VIEWPORT_BIT);
+		glPushClientAttrib(GL_CLIENT_PIXEL_STORE_BIT | GL_CLIENT_VERTEX_ARRAY_BIT);
+
+		// prepare view
+		glMatrixMode(GL_PROJECTION);
+		glPushMatrix();
+		glMatrixMode(GL_MODELVIEW);
+		glPushMatrix();
+		glMatrixMode(GL_TEXTURE);
+		glPushMatrix();
+	} else {
+		// Save context by ourselves
+#define CTX_STATE(gl_param) _save ## gl_param = glIsEnabled(gl_param)
+#define CTX_BOOLEAN(gl_param) glGetBooleanv(gl_param, &_save ## gl_param)
+#define CTX_INTEGER(gl_param, count) glGetIntegerv(gl_param, _save ## gl_param)
+
+		CTX_STATE(GL_BLEND);
+		CTX_STATE(GL_CULL_FACE);
+		CTX_STATE(GL_DEPTH_TEST);
+		CTX_STATE(GL_DITHER);
+		CTX_STATE(GL_POLYGON_OFFSET_FILL);
+		CTX_STATE(GL_SCISSOR_TEST);
+		CTX_STATE(GL_STENCIL_TEST);
+
+		CTX_BOOLEAN(GL_DEPTH_WRITEMASK);
+
+		CTX_INTEGER(GL_BLEND_SRC_RGB, 1);
+		CTX_INTEGER(GL_BLEND_DST_RGB, 1);
+		CTX_INTEGER(GL_BLEND_SRC_ALPHA, 1);
+		CTX_INTEGER(GL_BLEND_DST_ALPHA, 1);
+
+		CTX_INTEGER(GL_SCISSOR_BOX, 4);
+		CTX_INTEGER(GL_VIEWPORT, 4);
+
+#undef CTX_INTEGER
+#undef CTX_BOOLEAN
+#undef CTX_STATE
+	}
+	_stackLevel++;
+
+	if (_frameBuffers[1]) {
+		// Frambuffer blit is impacted by scissor test, disable it
+		glDisable(GL_SCISSOR_TEST);
+		// We are using multisampling
+		glBindFramebuffer(GL_READ_FRAMEBUFFER, _frameBuffers[0]);
+		glBindFramebuffer(GL_DRAW_FRAMEBUFFER, _frameBuffers[1]);
+		const uint w = _texture.getLogicalWidth();
+		const uint h = _texture.getLogicalHeight();
+		glBlitFramebuffer(0, 0, w, h, 0, 0, w, h, GL_COLOR_BUFFER_BIT, GL_NEAREST);
+		glBindFramebuffer(GL_FRAMEBUFFER, 0);
+	} else if (_frameBuffers[0]) {
+		// Don't mess with the framebuffer if one was setup
+		glBindFramebuffer(GL_FRAMEBUFFER, 0);
+	}
+}
+
+void Renderer3D::enter3D() {
+	if (_frameBuffers[1]) {
+		// We are using multisampling
+		glBindFramebuffer(GL_READ_FRAMEBUFFER, _frameBuffers[1]);
+		glBindFramebuffer(GL_DRAW_FRAMEBUFFER, _frameBuffers[0]);
+	} else if (_frameBuffers[0]) {
+		// Draw on framebuffer if one was setup
+		glBindFramebuffer(GL_FRAMEBUFFER, _frameBuffers[0]);
+	}
+	glBindTexture(GL_TEXTURE_2D, 0);
+
+	Pipeline::disable();
+
+	if (_stackLevel) {
+		if (OpenGLContext.type == kContextGL) {
+			glMatrixMode(GL_TEXTURE);
+			glPopMatrix();
+			glMatrixMode(GL_MODELVIEW);
+			glPopMatrix();
+			glMatrixMode(GL_PROJECTION);
+			glPopMatrix();
+			glPopClientAttrib();
+			glPopAttrib();
+		} else {
+#define CTX_STATE(gl_param) _save ## gl_param ? glEnable(gl_param) : glDisable(gl_param)
+
+			CTX_STATE(GL_BLEND);
+			CTX_STATE(GL_CULL_FACE);
+			CTX_STATE(GL_DEPTH_TEST);
+			CTX_STATE(GL_DITHER);
+			CTX_STATE(GL_POLYGON_OFFSET_FILL);
+			CTX_STATE(GL_SCISSOR_TEST);
+			CTX_STATE(GL_STENCIL_TEST);
+
+			glDepthMask(_saveGL_DEPTH_WRITEMASK);
+
+			glBlendFuncSeparate(_saveGL_BLEND_SRC_RGB[0], _saveGL_BLEND_DST_RGB[0],
+					_saveGL_BLEND_SRC_ALPHA[0], _saveGL_BLEND_DST_ALPHA[0]);
+
+			glScissor(_saveGL_SCISSOR_BOX[0], _saveGL_SCISSOR_BOX[1],
+				_saveGL_SCISSOR_BOX[2], _saveGL_SCISSOR_BOX[3]);
+
+			glViewport(_saveGL_VIEWPORT[0], _saveGL_VIEWPORT[1],
+				_saveGL_VIEWPORT[2], _saveGL_VIEWPORT[3]);
+#undef CTX_STATE
+		}
+		_stackLevel--;
+	} else {
+		// 3D engine just starts, make sure the state is clean
+		glDisable(GL_BLEND);
+		glBlendEquation(GL_FUNC_ADD);
+		glBlendFunc(GL_ONE, GL_ZERO);
+
+		glDisable(GL_CULL_FACE);
+		glCullFace(GL_BACK);
+		glFrontFace(GL_CCW);
+
+		glDisable(GL_DEPTH_TEST);
+		glDepthFunc(GL_LESS);
+
+		glEnable(GL_DITHER);
+
+		glDisable(GL_POLYGON_OFFSET_FILL);
+		glPolygonOffset(0.f, 0.f);
+
+		glDisable(GL_SCISSOR_TEST);
+		glScissor(0, 0, g_system->getWidth(), g_system->getHeight());
+
+		glDisable(GL_STENCIL_TEST);
+		glStencilFunc(GL_ALWAYS, 0, -1u);
+		glStencilMask(-1u);
+		glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
+
+		glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+		glLineWidth(1.f);
+
+		glViewport(0, 0, g_system->getWidth(), g_system->getHeight());
+
+		if (OpenGLContext.type == kContextGL) {
+			glDisable(GL_ALPHA_TEST);
+			glAlphaFunc(GL_ALWAYS, 0);
+
+			glDisable(GL_COLOR_MATERIAL);
+			glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
+
+			glDisable(GL_FOG);
+			glDisable(GL_LIGHTING);
+			glDisable(GL_LINE_SMOOTH);
+			glEnable(GL_MULTISAMPLE);
+			glDisable(GL_NORMALIZE);
+			glDisable(GL_POLYGON_OFFSET_FILL);
+			glDisable(GL_POLYGON_STIPPLE);
+			glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+			glDisable(GL_TEXTURE_1D);
+			glDisable(GL_TEXTURE_2D);
+			glDisable(GL_TEXTURE_3D);
+			glDisable(GL_TEXTURE_CUBE_MAP);
+			glDisable(GL_TEXTURE_GEN_Q);
+			glDisable(GL_TEXTURE_GEN_R);
+			glDisable(GL_TEXTURE_GEN_S);
+			glDisable(GL_TEXTURE_GEN_T);
+
+			glDisableClientState(GL_COLOR_ARRAY);
+			glDisableClientState(GL_EDGE_FLAG_ARRAY);
+			glDisableClientState(GL_FOG_COORD_ARRAY);
+			glDisableClientState(GL_INDEX_ARRAY);
+			glDisableClientState(GL_NORMAL_ARRAY);
+			glDisableClientState(GL_SECONDARY_COLOR_ARRAY);
+			glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+			glDisableClientState(GL_VERTEX_ARRAY);
+
+			// The others targets are not modified by engines
+			glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_DONT_CARE);
+			glLogicOp(GL_COPY);
+			glPointSize(1.f);
+			glShadeModel(GL_SMOOTH);
+		}
+	}
+}
+
+void Renderer3D::showOverlay(uint w, uint h) {
+	_inOverlay = true;
+
+	if (_frameBuffers[0]) {
+		// We have a framebuffer: the texture already contains an image
+		return;
+	}
+
+	_texture.create();
+	_texture.setSize(w, h, true);
+	Graphics::Surface background;
+	background.create(w, h, Texture::getRGBAPixelFormat());
+	glReadPixels(0, 0, background.w, background.h, GL_RGBA, GL_UNSIGNED_BYTE, background.getPixels());
+	_texture.updateArea(Common::Rect(w, h), background);
+	background.free();
+}
+
+void Renderer3D::hideOverlay() {
+	_inOverlay = false;
+
+	if (!_frameBuffers[0]) {
+		// We don't have a framebuffer: destroy the texture we used to store the background
+		_texture.destroy();
+		return;
+	}
+
+	// We have a framebuffer: resize the screen if we have a pending change
+	if (_pendingScreenChangeWidth >= 0 && _pendingScreenChangeHeight >= 0) {
+		resize(_pendingScreenChangeWidth, _pendingScreenChangeHeight);
+		_pendingScreenChangeWidth = -1;
+		_pendingScreenChangeHeight = -1;
+	}
+}
+
+} // End of namespace OpenGL
+
+#endif
diff --git a/backends/graphics/opengl/renderer3d.h b/backends/graphics/opengl/renderer3d.h
new file mode 100644
index 00000000000..df8491b8832
--- /dev/null
+++ b/backends/graphics/opengl/renderer3d.h
@@ -0,0 +1,96 @@
+/* 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 3 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, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef BACKENDS_GRAPHICS_OPENGL_RENDERER3D_H
+#define BACKENDS_GRAPHICS_OPENGL_RENDERER3D_H
+
+#include "common/scummsys.h"
+
+#if defined(USE_OPENGL_GAME) || defined(USE_OPENGL_SHADERS)
+
+#include "graphics/opengl/texture.h"
+
+namespace OpenGL {
+
+class Renderer3D {
+public:
+	Renderer3D();
+	~Renderer3D() { destroy(); }
+
+	void initSize(uint w, uint h, int samples, bool renderToFrameBuffer);
+	void resize(uint w, uint h);
+	void recreate();
+	void destroy();
+
+	void leave3D();
+	void enter3D();
+
+	void showOverlay(uint w, uint h);
+	void hideOverlay();
+
+	const Texture &getGLTexture() const { return _texture; }
+	bool hasTexture() const { return _texture.getGLTexture() != 0; }
+
+protected:
+	void setup();
+
+	int _stackLevel;
+	bool _inOverlay;
+	int _pendingScreenChangeWidth;
+	int _pendingScreenChangeHeight;
+
+	bool _renderToFrameBuffer;
+	int _samples;
+	Texture _texture;
+	GLuint _renderBuffers[3];
+	GLuint _frameBuffers[2];
+
+#define CTX_STATE(gl_param) GLboolean _save ## gl_param
+#define CTX_BOOLEAN(gl_param) GLboolean _save ## gl_param
+#define CTX_INTEGER(gl_param, count) GLint _save ## gl_param[count]
+
+	CTX_STATE(GL_BLEND);
+	CTX_STATE(GL_CULL_FACE);
+	CTX_STATE(GL_DEPTH_TEST);
+	CTX_STATE(GL_DITHER);
+	CTX_STATE(GL_POLYGON_OFFSET_FILL);
+	CTX_STATE(GL_SCISSOR_TEST);
+	CTX_STATE(GL_STENCIL_TEST);
+
+	CTX_BOOLEAN(GL_DEPTH_WRITEMASK);
+
+	CTX_INTEGER(GL_BLEND_SRC_RGB, 1);
+	CTX_INTEGER(GL_BLEND_DST_RGB, 1);
+	CTX_INTEGER(GL_BLEND_SRC_ALPHA, 1);
+	CTX_INTEGER(GL_BLEND_DST_ALPHA, 1);
+	CTX_INTEGER(GL_SCISSOR_BOX, 4);
+	CTX_INTEGER(GL_VIEWPORT, 4);
+
+#undef CTX_INTEGER
+#undef CTX_BOOLEAN
+#undef CTX_STATE
+};
+
+} // End of namespace OpenGL
+
+#endif // defined(USE_OPENGL_GAME) || defined(USE_OPENGL_SHADERS)
+
+#endif
diff --git a/backends/graphics/openglsdl/openglsdl-graphics.cpp b/backends/graphics/openglsdl/openglsdl-graphics.cpp
index d6a3e3474ab..784efffd9e3 100644
--- a/backends/graphics/openglsdl/openglsdl-graphics.cpp
+++ b/backends/graphics/openglsdl/openglsdl-graphics.cpp
@@ -789,7 +789,11 @@ bool OpenGLSdlGraphicsManager::setupMode(uint width, uint height) {
 			height = _desiredFullscreenHeight;
 			flags |= SDL_FULLSCREEN;
 		}
+#if defined(USE_OPENGL_GAME) || defined(USE_OPENGL_SHADERS)
+		if (_resizable && !_renderer3d) {
+#else
 		if (_resizable) {
+#endif
 			// In SDL1.2, resizing the window may invalidate the context
 			// This would kill all the engine objects
 			flags |= SDL_RESIZABLE;
diff --git a/backends/module.mk b/backends/module.mk
index ca6a5dd4c0c..e624395c3f9 100644
--- a/backends/module.mk
+++ b/backends/module.mk
@@ -176,6 +176,7 @@ ifdef USE_OPENGL
 MODULE_OBJS += \
 	graphics/opengl/framebuffer.o \
 	graphics/opengl/opengl-graphics.o \
+	graphics/opengl/renderer3d.o \
 	graphics/opengl/shader.o \
 	graphics/opengl/texture.o \
 	graphics/opengl/pipelines/clut8.o \


Commit: f222c8256af78f26dee6130a1b0f744773213c45
    https://github.com/scummvm/scummvm/commit/f222c8256af78f26dee6130a1b0f744773213c45
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2025-06-01T08:24:34+02:00

Commit Message:
BACKENDS: SDL: Don't hardcode 3D graphical backend

Changed paths:
    backends/platform/sdl/sdl.cpp
    backends/platform/sdl/sdl.h


diff --git a/backends/platform/sdl/sdl.cpp b/backends/platform/sdl/sdl.cpp
index 92b920896fe..46f812b5938 100644
--- a/backends/platform/sdl/sdl.cpp
+++ b/backends/platform/sdl/sdl.cpp
@@ -996,36 +996,42 @@ bool OSystem_SDL::setGraphicsMode(int mode, uint flags) {
 	// It's also used to restore state from 3D to 2D GFX manager
 	SdlGraphicsManager *sdlGraphicsManager = dynamic_cast<SdlGraphicsManager *>(_graphicsManager);
 	_gfxManagerState = sdlGraphicsManager->getState();
-	bool supports3D = sdlGraphicsManager->hasFeature(kFeatureOpenGLForGame);
 
 	bool switchedManager = false;
 
 	// If the new mode and the current mode are not from the same graphics
 	// manager, delete and create the new mode graphics manager
-#if defined(USE_OPENGL_GAME) || defined(USE_OPENGL_SHADERS)
-	if (render3d && !supports3D) {
-		debug(1, "switching to OpenGL 3D graphics");
-		sdlGraphicsManager->deactivateManager();
-		delete sdlGraphicsManager;
-		_graphicsManager = sdlGraphicsManager = new OpenGLSdlGraphics3dManager(_eventSource, _window, _supportsFrameBuffer);
-		switchedManager = true;
-	} else
-#endif
-	{
-		for (uint i = 0; i < GraphicsManagerCount; ++i) {
+	if (render3d) {
+		uint best3DSupport = -1;
+		uint i;
+		// Make sure the requested mode supports 3D
+		for (i = 0; i < GraphicsManagerCount; ++i) {
+			if (_supports3D[i]) {
+				best3DSupport = i;
+			}
 			if (!(mode >= _firstMode[i] && mode <= _lastMode[i]))
 				continue;
-			if (_graphicsMode >= _firstMode[i] && _graphicsMode <= _lastMode[i] && !supports3D)
+			if (_supports3D[i])
 				break;
-			debug(1, "switching graphics manager");
-			if (sdlGraphicsManager) {
-				sdlGraphicsManager->deactivateManager();
-				delete sdlGraphicsManager;
-			}
-			_graphicsManager = sdlGraphicsManager = createGraphicsManager(_eventSource, _window, (GraphicsManagerType)i);
-			switchedManager = true;
+		}
+		if (i == GraphicsManagerCount) {
+			mode = _firstMode[best3DSupport];
+		}
+	}
+
+	for (uint i = 0; i < GraphicsManagerCount; ++i) {
+		if (!(mode >= _firstMode[i] && mode <= _lastMode[i]))
+			continue;
+		if (_graphicsMode >= _firstMode[i] && _graphicsMode <= _lastMode[i])
 			break;
+		debug(1, "switching graphics manager");
+		if (sdlGraphicsManager) {
+			sdlGraphicsManager->deactivateManager();
+			delete sdlGraphicsManager;
 		}
+		_graphicsManager = sdlGraphicsManager = createGraphicsManager(_eventSource, _window, (GraphicsManagerType)i);
+		switchedManager = true;
+		break;
 	}
 
 	_graphicsMode = mode;
@@ -1100,6 +1106,7 @@ void OSystem_SDL::setupGraphicsModes() {
 			srcMode++;
 		}
 		_lastMode[i] = _graphicsModes.size() - 1;
+		_supports3D[i] = manager->hasFeature(kFeatureOpenGLForGame);
 		delete manager;
 		assert(_defaultMode[i] != -1);
 	}
diff --git a/backends/platform/sdl/sdl.h b/backends/platform/sdl/sdl.h
index fa59d8e6f15..79ad1b44dd4 100644
--- a/backends/platform/sdl/sdl.h
+++ b/backends/platform/sdl/sdl.h
@@ -185,6 +185,7 @@ protected:
 	int _firstMode[GraphicsManagerCount];
 	int _lastMode[GraphicsManagerCount];
 	int _defaultMode[GraphicsManagerCount];
+	int _supports3D[GraphicsManagerCount];
 
 	/**
 	 * Create the merged graphics modes list.


Commit: fb36820d867d2a5be782b6da461b814b827365d5
    https://github.com/scummvm/scummvm/commit/fb36820d867d2a5be782b6da461b814b827365d5
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2025-06-01T08:24:34+02:00

Commit Message:
ANDROID: Don't use the old 3D graphics manager

It's useless now

Changed paths:
    backends/platform/android/android.cpp
    backends/platform/android/android.h


diff --git a/backends/platform/android/android.cpp b/backends/platform/android/android.cpp
index 67a46f55caf..c85deaab040 100644
--- a/backends/platform/android/android.cpp
+++ b/backends/platform/android/android.cpp
@@ -62,7 +62,6 @@
 #include "backends/fs/posix/posix-iostream.h"
 
 #include "backends/graphics/android/android-graphics.h"
-#include "backends/graphics3d/android/android-graphics3d.h"
 
 #include "backends/audiocd/default/default-audiocd.h"
 #include "backends/events/default/default-events.h"
@@ -719,11 +718,6 @@ bool OSystem_Android::hasFeature(Feature f) {
 			f == kFeatureTouchscreen) {
 		return true;
 	}
-	/* Even if we are using the 2D graphics manager,
-	 * we are at one initGraphics3d call of supporting GLES2 */
-	if (f == kFeatureOpenGLForGame) return true;
-	/* GLES2 always supports shaders */
-	if (f == kFeatureShadersForGame) return true;
 
 	if (f == kFeatureCpuNEON) {
 #if defined(__aarch64__)
@@ -1006,97 +1000,6 @@ Common::String OSystem_Android::getSystemProperty(const char *name) const {
 	return Common::String(value, len);
 }
 
-const OSystem::GraphicsMode *OSystem_Android::getSupportedGraphicsModes() const {
-	// We only support one mode
-	static const OSystem::GraphicsMode s_supportedGraphicsModes[] = {
-		{ "default", "Default", 0 },
-		{ 0, 0, 0 },
-	};
-
-	return s_supportedGraphicsModes;
-}
-
-int OSystem_Android::getDefaultGraphicsMode() const {
-	// We only support one mode
-	return 0;
-}
-
-bool OSystem_Android::setGraphicsMode(int mode, uint flags) {
-	bool render3d = flags & OSystem::kGfxModeRender3d;
-
-	// Very hacky way to set up the old graphics manager state, in case we
-	// switch from SDL->OpenGL or OpenGL->SDL.
-	//
-	// This is a probably temporary workaround to fix bugs like #5799
-	// "SDL/OpenGL: Crash when switching renderer backend".
-	//
-	// It's also used to restore state from 3D to 2D GFX manager
-	AndroidCommonGraphics *androidGraphicsManager = dynamic_cast<AndroidCommonGraphics *>(_graphicsManager);
-	AndroidCommonGraphics::State gfxManagerState = androidGraphicsManager->getState();
-	bool supports3D = _graphicsManager->hasFeature(kFeatureOpenGLForGame);
-
-	bool switchedManager = false;
-
-	// If the new mode and the current mode are not from the same graphics
-	// manager, delete and create the new mode graphics manager
-	debug(5, "requesting 3D: %d, supporting 3D: %d", render3d, supports3D);
-	if (render3d && !supports3D) {
-		debug(5, "switching to 3D graphics");
-		delete _graphicsManager;
-		_graphicsManager = nullptr;
-		AndroidGraphics3dManager *manager = new AndroidGraphics3dManager();
-		_graphicsManager = manager;
-		androidGraphicsManager = manager;
-		switchedManager = true;
-	} else if (!render3d && supports3D) {
-		debug(5, "switching to 2D graphics");
-		delete _graphicsManager;
-		_graphicsManager = nullptr;
-		AndroidGraphicsManager *manager = new AndroidGraphicsManager();
-		_graphicsManager = manager;
-		androidGraphicsManager = manager;
-		switchedManager = true;
-	}
-
-	androidGraphicsManager->syncVirtkeyboardState(_virtkeybd_on);
-
-	if (switchedManager) {
-		// Setup the graphics mode and size first
-		// This is needed so that we can check the supported pixel formats when
-		// restoring the state.
-		_graphicsManager->beginGFXTransaction();
-		if (!_graphicsManager->setGraphicsMode(mode, flags))
-			return false;
-		_graphicsManager->initSize(gfxManagerState.screenWidth, gfxManagerState.screenHeight);
-		_graphicsManager->endGFXTransaction();
-
-		// This failing will probably have bad consequences...
-		if (!androidGraphicsManager->setState(gfxManagerState)) {
-			return false;
-		}
-
-		// Next setup the cursor again
-		CursorMan.pushCursor(0, 0, 0, 0, 0, 0);
-		CursorMan.popCursor();
-
-		// Next setup cursor palette if needed
-		if (_graphicsManager->getFeatureState(kFeatureCursorPalette)) {
-			CursorMan.pushCursorPalette(0, 0, 0);
-			CursorMan.popCursorPalette();
-		}
-
-		_graphicsManager->beginGFXTransaction();
-		return true;
-	} else {
-		return _graphicsManager->setGraphicsMode(mode, flags);
-	}
-}
-
-int OSystem_Android::getGraphicsMode() const {
-	// We only support one mode
-	return 0;
-}
-
 #if defined(USE_OPENGL) && defined(USE_GLAD)
 void *OSystem_Android::getOpenGLProcAddress(const char *name) const {
 	// eglGetProcAddress exists since Android 2.3 (API Level 9)
diff --git a/backends/platform/android/android.h b/backends/platform/android/android.h
index 1df7f085e3b..86cb65a9451 100644
--- a/backends/platform/android/android.h
+++ b/backends/platform/android/android.h
@@ -270,11 +270,6 @@ public:
 	bool isConnectionLimited() override;
 	Common::String getSystemLanguage() const override;
 
-	const OSystem::GraphicsMode *getSupportedGraphicsModes() const override;
-	int getDefaultGraphicsMode() const override;
-	bool setGraphicsMode(int mode, uint flags) override;
-	int getGraphicsMode() const override;
-
 	OpenGL::ContextType getOpenGLType() const override { return OpenGL::kContextGLES2; }
 #if defined(USE_OPENGL) && defined(USE_GLAD)
 	void *getOpenGLProcAddress(const char *name) const override;


Commit: f33a321fe3efb79902e82e7357dc1c4b8e6752ed
    https://github.com/scummvm/scummvm/commit/f33a321fe3efb79902e82e7357dc1c4b8e6752ed
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2025-06-01T08:24:34+02:00

Commit Message:
ANDROID: Cleanup the obsolete 3D graphics manager

Changed paths:
  R backends/graphics3d/android/android-graphics3d.cpp
  R backends/graphics3d/android/android-graphics3d.h
  R backends/graphics3d/android/texture.cpp
  R backends/graphics3d/android/texture.h
    backends/graphics/android/android-graphics.cpp
    backends/graphics/android/android-graphics.h
    backends/module.mk
    backends/platform/android/android.cpp
    backends/platform/android/events.cpp


diff --git a/backends/graphics/android/android-graphics.cpp b/backends/graphics/android/android-graphics.cpp
index baa74a870c1..1862fb2b4c5 100644
--- a/backends/graphics/android/android-graphics.cpp
+++ b/backends/graphics/android/android-graphics.cpp
@@ -300,32 +300,3 @@ bool AndroidGraphicsManager::notifyMousePosition(Common::Point &mouse) {
 
 	return true;
 }
-
-AndroidCommonGraphics::State AndroidGraphicsManager::getState() const {
-	State state;
-
-	state.screenWidth   = getWidth();
-	state.screenHeight  = getHeight();
-	state.aspectRatio   = getFeatureState(OSystem::kFeatureAspectRatioCorrection);
-	state.fullscreen    = getFeatureState(OSystem::kFeatureFullscreenMode);
-	state.cursorPalette = getFeatureState(OSystem::kFeatureCursorPalette);
-#ifdef USE_RGB_COLOR
-	state.pixelFormat   = getScreenFormat();
-#endif
-	return state;
-}
-
-bool AndroidGraphicsManager::setState(const AndroidCommonGraphics::State &state) {
-	beginGFXTransaction();
-
-#ifdef USE_RGB_COLOR
-		initSize(state.screenWidth, state.screenHeight, &state.pixelFormat);
-#else
-		initSize(state.screenWidth, state.screenHeight, nullptr);
-#endif
-		setFeatureState(OSystem::kFeatureAspectRatioCorrection, state.aspectRatio);
-		setFeatureState(OSystem::kFeatureFullscreenMode, state.fullscreen);
-		setFeatureState(OSystem::kFeatureCursorPalette, state.cursorPalette);
-
-	return endGFXTransaction() == OSystem::kTransactionSuccess;
-}
diff --git a/backends/graphics/android/android-graphics.h b/backends/graphics/android/android-graphics.h
index 70f20723601..2b647ce9a02 100644
--- a/backends/graphics/android/android-graphics.h
+++ b/backends/graphics/android/android-graphics.h
@@ -27,65 +27,22 @@
 
 #include "backends/platform/android/touchcontrols.h"
 
-class AndroidCommonGraphics {
-public:
-	virtual ~AndroidCommonGraphics() {}
-
-	virtual void initSurface() = 0;
-	virtual void deinitSurface() = 0;
-	virtual void resizeSurface() = 0;
-
-	virtual Common::Point getMousePosition() = 0;
-	virtual bool notifyMousePosition(Common::Point &mouse) = 0;
-
-	virtual void syncVirtkeyboardState(bool virtkeybd_on) = 0;
-	virtual void applyTouchSettings() const = 0;
-
-	/**
-	 * A (subset) of the graphic manager's state. This is used when switching
-	 * between different Android graphic managers at runtime.
-	 */
-	struct State {
-		int screenWidth, screenHeight;
-		bool aspectRatio;
-		bool fullscreen;
-		bool cursorPalette;
-
-#ifdef USE_RGB_COLOR
-		Graphics::PixelFormat pixelFormat;
-#endif
-	};
-
-	/**
-	 * Gets the current state of the graphics manager.
-	 */
-	virtual State getState() const = 0;
-
-	/**
-	 * Sets up a basic state of the graphics manager.
-	 */
-	virtual bool setState(const State &state) = 0;
-};
-
 class AndroidGraphicsManager :
-	public OpenGL::OpenGLGraphicsManager, public AndroidCommonGraphics, public TouchControlsDrawer {
+	public OpenGL::OpenGLGraphicsManager, public TouchControlsDrawer {
 public:
 	AndroidGraphicsManager();
 	virtual ~AndroidGraphicsManager();
 
-	virtual void initSurface() override;
-	virtual void deinitSurface() override;
-	virtual void resizeSurface() override;
-
-	virtual AndroidCommonGraphics::State getState() const override;
-	virtual bool setState(const AndroidCommonGraphics::State &state) override;
+	void initSurface();
+	void deinitSurface();
+	void resizeSurface();
 
 	void updateScreen() override;
 
 	void displayMessageOnOSD(const Common::U32String &msg) override;
 
-	virtual bool notifyMousePosition(Common::Point &mouse) override;
-	virtual Common::Point getMousePosition() override { return Common::Point(_cursorX, _cursorY); }
+	bool notifyMousePosition(Common::Point &mouse);
+	Common::Point getMousePosition() { return Common::Point(_cursorX, _cursorY); }
 
 	float getHiDPIScreenFactor() const override;
 
@@ -93,6 +50,9 @@ public:
 	void touchControlNotifyChanged() override;
 	void touchControlDraw(uint8 alpha, int16 x, int16 y, int16 w, int16 h, const Common::Rect &clip) override;
 
+	void syncVirtkeyboardState(bool virtkeybd_on);
+	void applyTouchSettings() const;
+
 protected:
 	void recalculateDisplayAreas() override;
 	void setSystemMousePosition(const int x, const int y) override {}
@@ -105,9 +65,6 @@ protected:
 
 	void refreshScreen() override;
 
-	void syncVirtkeyboardState(bool virtkeybd_on) override;
-	void applyTouchSettings() const override;
-
 private:
 	OpenGL::Surface *_touchcontrols;
 	int _old_touch_mode;
diff --git a/backends/graphics3d/android/android-graphics3d.cpp b/backends/graphics3d/android/android-graphics3d.cpp
deleted file mode 100644
index 730801bcaf0..00000000000
--- a/backends/graphics3d/android/android-graphics3d.cpp
+++ /dev/null
@@ -1,1125 +0,0 @@
-/* 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 3 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, see <http://www.gnu.org/licenses/>.
- *
- */
-
-// Allow use of stuff in <time.h>
-#define FORBIDDEN_SYMBOL_EXCEPTION_time_h
-
-// Disable printf override in common/forbidden.h to avoid
-// clashes with log.h from the Android SDK.
-// That header file uses
-//   __attribute__ ((format(printf, 3, 4)))
-// which gets messed up by our override mechanism; this could
-// be avoided by either changing the Android SDK to use the equally
-// legal and valid
-//   __attribute__ ((format(printf, 3, 4)))
-// or by refining our printf override to use a varadic macro
-// (which then wouldn't be portable, though).
-// Anyway, for now we just disable the printf override globally
-// for the Android port
-#define FORBIDDEN_SYMBOL_EXCEPTION_printf
-
-#include "backends/platform/android/android.h"
-#include "backends/platform/android/jni-android.h"
-
-#include "common/tokenizer.h"
-#include "graphics/blit.h"
-#include "graphics/managed_surface.h"
-#include "graphics/opengl/shader.h"
-#include "graphics/opengl/context.h"
-
-#include "backends/graphics3d/android/android-graphics3d.h"
-
-// These helper macros let us setup our context only when the game has different settings than us
-#define CONTEXT_SAVE_STATE(gl_param) GLboolean saved ## gl_param; GLCALL(saved ## gl_param = glIsEnabled(gl_param))
-#define CONTEXT_SET_ENABLE(gl_param) if (!(saved ## gl_param)) { GLCALL(glEnable(gl_param)); }
-#define CONTEXT_SET_DISABLE(gl_param) if (saved ## gl_param) { GLCALL(glDisable(gl_param)); }
-// These helper macros do the opposite to get back what the game expected
-#define CONTEXT_RESET_ENABLE(gl_param) if (!(saved ## gl_param)) { GLCALL(glDisable(gl_param)); }
-#define CONTEXT_RESET_DISABLE(gl_param) if (saved ## gl_param) { GLCALL(glEnable(gl_param)); }
-
-AndroidGraphics3dManager::AndroidGraphics3dManager() :
-	_screenChangeID(0),
-	_graphicsMode(0),
-	_fullscreen(true),
-	_ar_correction(true),
-	_force_redraw(false),
-	_virtkeybd_on(false),
-	_game_texture(0),
-	_frame_buffer(0),
-	_cursorX(0),
-	_cursorY(0),
-	_overlay_texture(0),
-	_overlay_background(nullptr),
-	_show_overlay(false),
-	_mouse_texture(nullptr),
-	_mouse_texture_palette(nullptr),
-	_mouse_texture_rgb(nullptr),
-	_mouse_hotspot(),
-	_mouse_dont_scale(false),
-	_show_mouse(false),
-	_touchcontrols_texture(new GLES8888Texture()),
-	_old_touch_mode(OSystem_Android::TOUCH_MODE_TOUCHPAD) {
-
-	if (JNI::egl_bits_per_pixel == 16) {
-		// We default to RGB565 and RGBA5551 which is closest to what we setup in Java side
-		_game_texture = new GLES565Texture();
-		_overlay_texture = new GLES5551Texture();
-		_overlay_background = new GLES565Texture();
-		_mouse_texture_palette = new GLESFakePalette5551Texture();
-	} else {
-		// If not 16, this must be 24 or 32 bpp so make use of them
-		_game_texture = new GLES888Texture();
-		_overlay_texture = new GLES8888Texture();
-		_overlay_background = new GLES8888Texture();
-		_mouse_texture_palette = new GLESFakePalette8888Texture();
-	}
-	_mouse_texture = _mouse_texture_palette;
-
-	initSurface();
-
-	// in 3D, not in GUI
-	dynamic_cast<OSystem_Android *>(g_system)->applyTouchSettings(true, false);
-	dynamic_cast<OSystem_Android *>(g_system)->applyOrientationSettings();
-}
-
-AndroidGraphics3dManager::~AndroidGraphics3dManager() {
-	// Reinitialize OpenGL for other manager
-	glBindBuffer(GL_ARRAY_BUFFER, 0);
-	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
-	glBindFramebuffer(GL_FRAMEBUFFER, 0);
-	glBindRenderbuffer(GL_RENDERBUFFER, 0);
-	glUseProgram(0);
-
-	// Cleanup framebuffer before destroying context
-	delete _frame_buffer;
-	_frame_buffer = nullptr;
-
-	deinitSurface();
-
-	// These textures have been cleaned in deinitSurface
-	// Deleting them now without a context is harmless
-	delete _game_texture;
-	delete _overlay_texture;
-	delete _overlay_background;
-	delete _mouse_texture_palette;
-	delete _mouse_texture_rgb;
-	delete _touchcontrols_texture;
-}
-
-static void logExtensions() {
-	const char *ext_string =
-	    reinterpret_cast<const char *>(glGetString(GL_EXTENSIONS));
-
-	LOGI("Extensions:");
-
-	Common::String exts;
-	Common::StringTokenizer tokenizer(ext_string, " ");
-	while (!tokenizer.empty()) {
-		Common::String token = tokenizer.nextToken();
-
-		exts += token + " ";
-		if (exts.size() > 100) {
-			LOGI("\t%s", exts.c_str());
-			exts = "";
-		}
-	}
-
-	if (exts.size() > 0) {
-		LOGI("\t%s", exts.c_str());
-	}
-}
-
-
-void AndroidGraphics3dManager::initSurface() {
-	LOGD("initializing 3D surface");
-
-	assert(!JNI::haveSurface());
-
-	if (!JNI::initSurface()) {
-		error("JNI::initSurface failed");
-	}
-
-	_screenChangeID = JNI::surface_changeid;
-
-	// Initialize OpenGLES context.
-	OpenGLContext.initialize(OpenGL::kContextGLES2);
-	logExtensions();
-	GLESTexture::initGL();
-
-	if (_game_texture) {
-		_game_texture->reinit();
-		// We had a frame buffer initialized, we must renew it as the game textured got renewed
-		if (_frame_buffer) {
-			delete _frame_buffer;
-			_frame_buffer = new AndroidFrameBuffer(
-						_game_texture->getTextureFormat(), _game_texture->getTextureFormat(),
-						_game_texture->getTextureType(), _game_texture->getTextureName(),
-	                                        _game_texture->width(), _game_texture->height(),
-	                                        _game_texture->texWidth(), _game_texture->texHeight());
-
-		}
-	}
-
-	// We don't have any content to display: just make sure surface is clean
-	if (_overlay_background) {
-		_overlay_background->release();
-	}
-
-	if (_overlay_texture) {
-		_overlay_texture->reinit();
-		initOverlay();
-	}
-
-	if (_mouse_texture) {
-		_mouse_texture->reinit();
-	}
-
-	if (_mouse_texture_palette && _mouse_texture != _mouse_texture_palette) {
-		_mouse_texture_palette->reinit();
-	}
-
-	if (_touchcontrols_texture) {
-		_touchcontrols_texture->reinit();
-	}
-	dynamic_cast<OSystem_Android *>(g_system)->getTouchControls().setDrawer(
-	    this, JNI::egl_surface_width, JNI::egl_surface_height);
-
-	updateScreenRect();
-	// double buffered, flip twice
-	clearScreen(kClearUpdate, 2);
-}
-
-void AndroidGraphics3dManager::deinitSurface() {
-	if (!JNI::haveSurface()) {
-		return;
-	}
-
-	LOGD("deinitializing 3D surface");
-
-	_screenChangeID = JNI::surface_changeid;
-
-	// release texture resources
-	if (_game_texture) {
-		_game_texture->release();
-	}
-
-	if (_overlay_texture) {
-		_overlay_texture->release();
-	}
-
-	if (_overlay_background) {
-		_overlay_background->release();
-	}
-
-	if (_mouse_texture) {
-		_mouse_texture->release();
-	}
-
-	if (_mouse_texture_palette && _mouse_texture != _mouse_texture_palette) {
-		_mouse_texture_palette->release();
-	}
-
-	dynamic_cast<OSystem_Android *>(g_system)->getTouchControls().setDrawer(
-	    nullptr, 0, 0);
-	if (_touchcontrols_texture) {
-		_touchcontrols_texture->release();
-	}
-
-	OpenGLContext.reset();
-
-	JNI::deinitSurface();
-}
-
-void AndroidGraphics3dManager::resizeSurface() {
-	LOGD("resizing 3D surface");
-
-	if (!JNI::haveSurface()) {
-		initSurface();
-		return;
-	}
-
-	JNI::deinitSurface();
-	if (!JNI::initSurface()) {
-		error("JNI::initSurface failed");
-	}
-
-	_screenChangeID = JNI::surface_changeid;
-
-	if (_overlay_texture) {
-		initOverlay();
-	}
-
-	dynamic_cast<OSystem_Android *>(g_system)->getTouchControls().setDrawer(
-	    this, JNI::egl_surface_width, JNI::egl_surface_height);
-
-	updateScreenRect();
-	// double buffered, flip twice
-	clearScreen(kClearUpdate, 2);
-}
-
-void AndroidGraphics3dManager::updateScreen() {
-	//ENTER();
-
-	GLTHREADCHECK;
-
-	if (!JNI::haveSurface()) {
-		return;
-	}
-
-	// Sets _forceRedraw if needed
-	dynamic_cast<OSystem_Android *>(g_system)->getTouchControls().beforeDraw();
-
-	if (!_force_redraw &&
-	        !_game_texture->dirty() &&
-	        !_overlay_texture->dirty() &&
-	        !_mouse_texture->dirty()) {
-		return;
-	}
-
-	_force_redraw = false;
-
-	// Save the game state
-	GLint savedBlendSrcRGB, savedBlendDstRGB, savedBlendSrcAlpha, savedBlendDstAlpha,
-	      savedBlendEqRGB, savedBlendEqAlpha;
-	GLint savedViewport[4];
-	CONTEXT_SAVE_STATE(GL_BLEND);
-	GLCALL(glGetIntegerv(GL_BLEND_SRC_RGB, &savedBlendSrcRGB));
-	GLCALL(glGetIntegerv(GL_BLEND_DST_RGB, &savedBlendDstRGB));
-	GLCALL(glGetIntegerv(GL_BLEND_SRC_ALPHA, &savedBlendSrcAlpha));
-	GLCALL(glGetIntegerv(GL_BLEND_DST_ALPHA, &savedBlendDstAlpha));
-	GLCALL(glGetIntegerv(GL_BLEND_EQUATION_RGB, &savedBlendEqRGB));
-	GLCALL(glGetIntegerv(GL_BLEND_EQUATION_ALPHA, &savedBlendEqAlpha));
-	CONTEXT_SAVE_STATE(GL_CULL_FACE);
-	CONTEXT_SAVE_STATE(GL_DEPTH_TEST);
-	CONTEXT_SAVE_STATE(GL_DITHER);
-	CONTEXT_SAVE_STATE(GL_POLYGON_OFFSET_FILL);
-	CONTEXT_SAVE_STATE(GL_SAMPLE_ALPHA_TO_COVERAGE);
-	CONTEXT_SAVE_STATE(GL_SAMPLE_COVERAGE);
-	CONTEXT_SAVE_STATE(GL_SCISSOR_TEST);
-	CONTEXT_SAVE_STATE(GL_STENCIL_TEST);
-	GLCALL(glGetIntegerv(GL_VIEWPORT, savedViewport));
-
-	if (_frame_buffer) {
-		_frame_buffer->detach();
-	}
-
-	// Make sure everything we need is correctly set up
-	// Enable what we need and disable the other if it is not already
-	CONTEXT_SET_ENABLE(GL_BLEND);
-	if (savedBlendSrcRGB != GL_SRC_ALPHA ||
-	    savedBlendDstRGB != GL_ONE_MINUS_SRC_ALPHA ||
-	    savedBlendSrcAlpha != GL_SRC_ALPHA ||
-	    savedBlendDstAlpha != GL_ONE_MINUS_SRC_ALPHA) {
-		GLCALL(glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA));
-	}
-	if (savedBlendEqRGB != GL_FUNC_ADD ||
-	    savedBlendEqAlpha != GL_FUNC_ADD) {
-		GLCALL(glBlendEquation(GL_FUNC_ADD));
-	}
-	CONTEXT_SET_DISABLE(GL_CULL_FACE);
-	CONTEXT_SET_DISABLE(GL_DEPTH_TEST);
-	CONTEXT_SET_DISABLE(GL_DITHER);
-	CONTEXT_SET_DISABLE(GL_POLYGON_OFFSET_FILL);
-	CONTEXT_SET_DISABLE(GL_SAMPLE_ALPHA_TO_COVERAGE);
-	CONTEXT_SET_DISABLE(GL_SAMPLE_COVERAGE);
-	CONTEXT_SET_DISABLE(GL_SCISSOR_TEST);
-	CONTEXT_SET_DISABLE(GL_STENCIL_TEST);
-
-	GLCALL(glViewport(0, 0, JNI::egl_surface_width, JNI::egl_surface_height));
-
-	if (_frame_buffer) {
-		// clear pointer leftovers in dead areas
-		clearScreen(kClear);
-
-		_game_texture->drawTextureRect();
-	}
-
-	if (_show_overlay) {
-		// If the overlay is in game we expect the game to continue drawing
-		if (_overlay_in_gui) {
-			clearScreen(kClear);
-			if (_overlay_background && _overlay_background->getTextureName() != 0) {
-				GLCALL(_overlay_background->drawTextureRect());
-			}
-		}
-		GLCALL(_overlay_texture->drawTextureRect());
-
-		if (_show_mouse && !_mouse_texture->isEmpty()) {
-			_mouse_texture->drawTexture(_cursorX - _mouse_hotspot_scaled.x, _cursorY - _mouse_hotspot_scaled.y,
-						    _mouse_width_scaled, _mouse_width_scaled);
-		}
-	}
-
-	dynamic_cast<OSystem_Android *>(g_system)->getTouchControls().draw();
-
-	if (!JNI::swapBuffers()) {
-		LOGW("swapBuffers failed: 0x%x", glGetError());
-	}
-
-	// Here we restore back the GLES state so if we enabled something we disable it back if it needs too and vice versa
-
-	CONTEXT_RESET_ENABLE(GL_BLEND);
-	if (savedGL_BLEND && (
-	    savedBlendSrcRGB != GL_SRC_ALPHA ||
-	    savedBlendDstRGB != GL_ONE_MINUS_SRC_ALPHA ||
-	    savedBlendSrcAlpha != GL_SRC_ALPHA ||
-	    savedBlendDstAlpha != GL_ONE_MINUS_SRC_ALPHA)) {
-		GLCALL(glBlendFuncSeparate(savedBlendSrcRGB, savedBlendDstRGB,
-		                           savedBlendSrcAlpha, savedBlendDstAlpha));
-	}
-	if (savedGL_BLEND && (
-	    savedBlendEqRGB != GL_FUNC_ADD ||
-	    savedBlendEqAlpha != GL_FUNC_ADD)) {
-		GLCALL(glBlendEquationSeparate(savedBlendEqRGB, savedBlendEqAlpha));
-	}
-	CONTEXT_RESET_DISABLE(GL_CULL_FACE);
-	CONTEXT_RESET_DISABLE(GL_DEPTH_TEST);
-	CONTEXT_RESET_DISABLE(GL_DITHER);
-	CONTEXT_RESET_DISABLE(GL_POLYGON_OFFSET_FILL);
-	CONTEXT_RESET_DISABLE(GL_SAMPLE_ALPHA_TO_COVERAGE);
-	CONTEXT_RESET_DISABLE(GL_SAMPLE_COVERAGE);
-	CONTEXT_RESET_DISABLE(GL_SCISSOR_TEST);
-	CONTEXT_RESET_DISABLE(GL_STENCIL_TEST);
-
-	// Restore game viewport
-	GLCALL(glViewport(savedViewport[0], savedViewport[1], savedViewport[2], savedViewport[3]));
-
-	// Don't keep our texture attached to avoid the engine writing on it if it forgets to setup its own texture
-	GLCALL(glBindTexture(GL_TEXTURE_2D, 0));
-	// Unload our program to make sure engine will use its own
-	GLESBaseTexture::unbindShader();
-
-	if (_frame_buffer) {
-		_frame_buffer->attach();
-	}
-}
-
-void AndroidGraphics3dManager::displayMessageOnOSD(const Common::U32String &msg) {
-	ENTER("%s", msg.encode().c_str());
-
-	JNI::displayMessageOnOSD(msg);
-}
-
-Common::Point AndroidGraphics3dManager::convertScreenToVirtual(int &x, int &y) const {
-	const GLESBaseTexture *tex = getActiveTexture();
-	const Common::Rect &screenRect = tex->getDrawRect();
-
-	// Clip in place the coordinates that comes handy to call setMousePosition
-	x = CLIP<int>(x, screenRect.left, screenRect.right - 1);
-	y = CLIP<int>(y, screenRect.top, screenRect.bottom - 1);
-
-	// Now convert this to virtual coordinates using texture virtual size
-	const uint16 virtualWidth = tex->width();
-	const uint16 virtualHeight = tex->height();
-
-	int virtualX = ((x - screenRect.left) * virtualWidth + screenRect.width() / 2) / screenRect.width();
-	int virtualY = ((y - screenRect.top) * virtualHeight + screenRect.height() / 2) / screenRect.height();
-
-	return Common::Point(CLIP<int>(virtualX, 0, virtualWidth - 1),
-	                     CLIP<int>(virtualY, 0, virtualHeight - 1));
-}
-
-Common::Point AndroidGraphics3dManager::convertVirtualToScreen(int x, int y) const {
-	const GLESBaseTexture *tex = getActiveTexture();
-	const uint16 virtualWidth = tex->width();
-	const uint16 virtualHeight = tex->height();
-	const Common::Rect &screenRect = tex->getDrawRect();
-
-	int screenX = screenRect.left + (x * screenRect.width() + virtualWidth / 2) / virtualWidth;
-	int screenY = screenRect.top + (y * screenRect.height() + virtualHeight / 2) / virtualHeight;
-
-	return Common::Point(CLIP<int>(screenX, screenRect.left, screenRect.right - 1),
-	                     CLIP<int>(screenY, screenRect.top, screenRect.bottom - 1));
-}
-
-bool AndroidGraphics3dManager::notifyMousePosition(Common::Point &mouse) {
-	// At entry, mouse is in screen coordinates like the texture draw rectangle
-	int x = mouse.x, y = mouse.y;
-	Common::Point vMouse = convertScreenToVirtual(x, y);
-
-	// Our internal mouse position is in screen coordinates
-	// convertScreenToVirtual just clipped coordinates so we are safe
-	setMousePosition(x, y);
-
-	// Now modify mouse to translate to virtual coordinates for the caller
-	mouse = vMouse;
-
-	return true;
-}
-
-const OSystem::GraphicsMode *AndroidGraphics3dManager::getSupportedGraphicsModes() const {
-	static const OSystem::GraphicsMode s_supportedGraphicsModes[] = {
-		{ "default", "Default", 0 },
-		{ 0, 0, 0 },
-	};
-
-	return s_supportedGraphicsModes;
-}
-
-int AndroidGraphics3dManager::getDefaultGraphicsMode() const {
-	return 0;
-}
-
-bool AndroidGraphics3dManager::setGraphicsMode(int mode, uint flags) {
-	return true;
-}
-
-int AndroidGraphics3dManager::getGraphicsMode() const {
-	return _graphicsMode;
-}
-
-bool AndroidGraphics3dManager::hasFeature(OSystem::Feature f) const {
-	if (f == OSystem::kFeatureCursorPalette ||
-	        f == OSystem::kFeatureCursorAlpha ||
-	        f == OSystem::kFeatureOpenGLForGame ||
-	        f == OSystem::kFeatureAspectRatioCorrection) {
-		return true;
-	}
-	if (f == OSystem::kFeatureOverlaySupportsAlpha) {
-		return _overlay_texture->getPixelFormat().aBits() > 3;
-	}
-	return false;
-}
-
-void AndroidGraphics3dManager::setFeatureState(OSystem::Feature f, bool enable) {
-	switch (f) {
-	case OSystem::kFeatureFullscreenMode:
-		_fullscreen = enable;
-		updateScreenRect();
-		break;
-	case OSystem::kFeatureAspectRatioCorrection:
-		_ar_correction = enable;
-		updateScreenRect();
-		break;
-	default:
-		break;
-	}
-}
-
-bool AndroidGraphics3dManager::getFeatureState(OSystem::Feature f) const {
-	switch (f) {
-	case OSystem::kFeatureCursorPalette:
-		return true;
-	case OSystem::kFeatureFullscreenMode:
-		return _fullscreen;
-	case OSystem::kFeatureAspectRatioCorrection:
-		return _ar_correction;
-	default:
-		return false;
-	}
-}
-
-void AndroidGraphics3dManager::showOverlay(bool inGUI) {
-	ENTER();
-
-	if (_show_overlay && inGUI == _overlay_in_gui) {
-		return;
-	}
-
-	if (inGUI) {
-		_old_touch_mode = JNI::getTouchMode();
-		// in 3D, in overlay
-		dynamic_cast<OSystem_Android *>(g_system)->applyTouchSettings(true, true);
-		dynamic_cast<OSystem_Android *>(g_system)->applyOrientationSettings();
-	} else if (_overlay_in_gui) {
-		// Restore touch mode active before overlay was shown
-		JNI::setTouchMode(_old_touch_mode);
-	}
-
-	_show_overlay = true;
-	_overlay_in_gui = inGUI;
-	_force_redraw = true;
-
-	// If there is a game running capture the screen, so that it can be shown "below" the overlay.
-	if (_overlay_background) {
-		_overlay_background->release();
-
-		if (g_engine) {
-			GLint savedViewport[4];
-			GLCALL(glGetIntegerv(GL_VIEWPORT, savedViewport));
-
-			if (_frame_buffer) {
-				_frame_buffer->detach();
-			}
-
-			GLCALL(glViewport(0, 0, JNI::egl_surface_width, JNI::egl_surface_height));
-			_overlay_background->reinit();
-			_overlay_background->allocBuffer(_overlay_texture->width(), _overlay_texture->height());
-			_overlay_background->setDrawRect(0, 0,
-			                                 JNI::egl_surface_width, JNI::egl_surface_height);
-			_overlay_background->readPixels();
-			_overlay_background->setGameTexture();
-
-			// Restore game viewport
-			GLCALL(glViewport(savedViewport[0], savedViewport[1], savedViewport[2], savedViewport[3]));
-
-			if (_frame_buffer) {
-				_frame_buffer->attach();
-			}
-		}
-	}
-
-	if (inGUI) {
-		warpMouse(_overlay_texture->width() / 2, _overlay_texture->height() / 2);
-	}
-}
-
-void AndroidGraphics3dManager::hideOverlay() {
-	ENTER();
-
-	if (!_show_overlay) {
-		return;
-	}
-
-	_show_overlay = false;
-
-	_overlay_background->release();
-
-	if (_overlay_in_gui) {
-		// Restore touch mode active before overlay was shown
-		JNI::setTouchMode(_old_touch_mode);
-
-		warpMouse(_game_texture->width() / 2, _game_texture->height() / 2);
-
-		dynamic_cast<OSystem_Android *>(g_system)->applyOrientationSettings();
-	}
-
-	_overlay_in_gui = false;
-
-	// double buffered, flip twice
-	clearScreen(kClearUpdate, 2);
-}
-
-void AndroidGraphics3dManager::clearOverlay() {
-	ENTER();
-
-	GLTHREADCHECK;
-
-	_overlay_texture->fillBuffer(0);
-}
-
-void AndroidGraphics3dManager::grabOverlay(Graphics::Surface &surface) const {
-	ENTER("%p", &surface);
-
-	GLTHREADCHECK;
-
-	const Graphics::Surface *overlaySurface = _overlay_texture->surface_const();
-
-	assert(surface.w >= overlaySurface->w);
-	assert(surface.h >= overlaySurface->h);
-	assert(surface.format.bytesPerPixel == overlaySurface->format.bytesPerPixel);
-
-	const byte *src = (const byte *)overlaySurface->getPixels();
-	byte *dst = (byte *)surface.getPixels();
-	Graphics::copyBlit(dst, src, surface.pitch, overlaySurface->pitch,
-	                   overlaySurface->w, overlaySurface->h, overlaySurface->format.bytesPerPixel);
-}
-
-void AndroidGraphics3dManager::copyRectToOverlay(const void *buf, int pitch,
-        int x, int y, int w, int h) {
-	ENTER("%p, %d, %d, %d, %d, %d", buf, pitch, x, y, w, h);
-
-	GLTHREADCHECK;
-
-	_overlay_texture->updateBuffer(x, y, w, h, buf, pitch);
-}
-
-int16 AndroidGraphics3dManager::getOverlayHeight() const {
-	return _overlay_texture->height();
-}
-
-int16 AndroidGraphics3dManager::getOverlayWidth() const {
-	return _overlay_texture->width();
-}
-
-Graphics::PixelFormat AndroidGraphics3dManager::getOverlayFormat() const {
-	return _overlay_texture->getPixelFormat();
-}
-
-int16 AndroidGraphics3dManager::getHeight() const {
-	if (_frame_buffer)
-		return _frame_buffer->getHeight();
-	else
-		return _overlay_texture->height();
-}
-
-int16 AndroidGraphics3dManager::getWidth() const {
-	if (_frame_buffer)
-		return _frame_buffer->getWidth();
-	else
-		return _overlay_texture->width();
-}
-
-void AndroidGraphics3dManager::setPalette(const byte *colors, uint start, uint num) {
-	// We should never end up here in 3D
-	assert(false);
-}
-
-void AndroidGraphics3dManager::grabPalette(byte *colors, uint start, uint num) const {
-	// We should never end up here in 3D
-	assert(false);
-}
-
-Graphics::Surface *AndroidGraphics3dManager::lockScreen() {
-	// We should never end up here in 3D
-	assert(false);
-
-	return nullptr;
-}
-
-void AndroidGraphics3dManager::unlockScreen() {
-	// We should never end up here in 3D
-	assert(false);
-}
-
-void AndroidGraphics3dManager::fillScreen(uint32 col) {
-	// We should never end up here in 3D
-	assert(false);
-}
-
-void AndroidGraphics3dManager::fillScreen(const Common::Rect &r, uint32 col) {
-	// We should never end up here in 3D
-	assert(false);
-}
-
-void AndroidGraphics3dManager::copyRectToScreen(const void *buf, int pitch,
-        int x, int y, int w, int h) {
-	// We should never end up here in 3D
-	assert(false);
-}
-
-void AndroidGraphics3dManager::initSize(uint width, uint height,
-                                        const Graphics::PixelFormat *format) {
-	// resize game texture
-	ENTER("%d, %d, %p", width, height, format);
-
-	// We do only 3D with this manager and in 3D there is no format
-	assert(format == nullptr);
-
-	bool engineSupportsArbitraryResolutions = !g_engine ||
-	        g_engine->hasFeature(Engine::kSupportsArbitraryResolutions);
-	if (engineSupportsArbitraryResolutions) {
-		width = JNI::egl_surface_width;
-		height = JNI::egl_surface_height;
-	}
-
-	GLTHREADCHECK;
-
-	_game_texture->allocBuffer(width, height);
-	_game_texture->setGameTexture();
-
-	delete _frame_buffer;
-
-	if (!engineSupportsArbitraryResolutions) {
-		_frame_buffer = new AndroidFrameBuffer(_game_texture->getTextureFormat(), _game_texture->getTextureFormat(),
-		                                       _game_texture->getTextureType(), _game_texture->getTextureName(),
-		                                       _game_texture->width(), _game_texture->height(),
-		                                       _game_texture->texWidth(), _game_texture->texHeight());
-		_frame_buffer->attach();
-	}
-
-	// Don't know mouse size yet - it gets reallocated in
-	// setMouseCursor.  We need the palette allocated before
-	// setMouseCursor however, so just take a guess at the desired
-	// size (it's small).
-	_mouse_texture_palette->allocBuffer(20, 20);
-
-	updateScreenRect();
-
-	clearScreen(kClear);
-}
-
-int AndroidGraphics3dManager::getScreenChangeID() const {
-	return _screenChangeID;
-}
-
-bool AndroidGraphics3dManager::showMouse(bool visible) {
-	ENTER("%d", visible);
-
-	_show_mouse = visible;
-
-	return true;
-}
-
-void AndroidGraphics3dManager::warpMouse(int x, int y) {
-	// x and y are in virtual coordinates
-	ENTER("%d, %d", x, y);
-
-	// Check active coordinate instead of screen coordinate to avoid warping
-	// the mouse if it is still within the same virtual pixel
-	// Don't take the risk of modifying _cursorX and _cursorY
-	int cx = _cursorX, cy = _cursorY;
-	const Common::Point currentMouse = convertScreenToVirtual(cx, cy);
-	if (currentMouse.x == x && currentMouse.y == y) {
-		// Same virtual coordinates: nothing to do
-		return;
-	}
-
-	const Common::Point sMouse = convertVirtualToScreen(x, y);
-
-	// Our internal mouse position is in screen coordinates
-	// convertVirtualToScreen just clipped coordinates so we are safe
-	setMousePosition(sMouse.x, sMouse.y);
-
-	// Events pushed to Android system are in screen coordinates too
-	// They are converted back by notifyMousePosition later
-	Common::Event e;
-	e.type = Common::EVENT_MOUSEMOVE;
-	e.mouse = sMouse;
-
-	dynamic_cast<OSystem_Android *>(g_system)->pushEvent(e);
-}
-
-void AndroidGraphics3dManager::updateCursorScaling() {
-	// By default we use the unscaled versions.
-	_mouse_hotspot_scaled = _mouse_hotspot;
-	_mouse_width_scaled = _mouse_texture->width();
-	_mouse_height_scaled = _mouse_texture->height();
-
-	// In case scaling is actually enabled we will scale the cursor according
-	// to the game screen.
-	uint16 w = getWidth();
-	uint16 h = getHeight();
-
-	if (!_mouse_dont_scale && w && h) {
-		const frac_t screen_scale_factor_x = intToFrac(_game_texture->getDrawRect().width()) / w;
-		const frac_t screen_scale_factor_y = intToFrac(_game_texture->getDrawRect().height()) / h;
-
-		_mouse_hotspot_scaled = Common::Point(
-			fracToInt(_mouse_hotspot_scaled.x * screen_scale_factor_x),
-			fracToInt(_mouse_hotspot_scaled.y * screen_scale_factor_y));
-
-		_mouse_width_scaled  = fracToInt(_mouse_width_scaled * screen_scale_factor_x);
-		_mouse_height_scaled = fracToInt(_mouse_height_scaled * screen_scale_factor_y);
-	}
-}
-
-void AndroidGraphics3dManager::setMouseCursor(const void *buf, uint w, uint h,
-        int hotspotX, int hotspotY,
-        uint32 keycolor, bool dontScale,
-        const Graphics::PixelFormat *format, const byte *mask) {
-	ENTER("%p, %u, %u, %d, %d, %u, %d, %p, %p", buf, w, h, hotspotX, hotspotY,
-	      keycolor, dontScale, format, mask);
-
-	if (mask)
-		warning("AndroidGraphics3dManager::setMouseCursor: Masks are not supported");
-
-	GLTHREADCHECK;
-
-#ifdef USE_RGB_COLOR
-	if (format && format->bytesPerPixel > 1) {
-		if (_mouse_texture != _mouse_texture_rgb) {
-			LOGD("switching to rgb mouse cursor");
-
-			assert(!_mouse_texture_rgb);
-			if (JNI::egl_bits_per_pixel == 16) {
-				_mouse_texture_rgb = new GLES5551Texture();
-			} else {
-				_mouse_texture_rgb = new GLES8888Texture();
-			}
-			_mouse_texture_rgb->setLinearFilter(_graphicsMode == 1);
-			_mouse_texture_rgb->reinit();
-		}
-
-		_mouse_texture = _mouse_texture_rgb;
-	} else {
-		if (_mouse_texture != _mouse_texture_palette) {
-			LOGD("switching to paletted mouse cursor");
-		}
-
-		_mouse_texture = _mouse_texture_palette;
-
-		delete _mouse_texture_rgb;
-		_mouse_texture_rgb = 0;
-	}
-#endif
-
-	_mouse_texture->allocBuffer(w, h);
-
-	if (_mouse_texture == _mouse_texture_palette) {
-		assert(keycolor < 256);
-		_mouse_texture->setKeycolor(keycolor);
-	}
-
-	if (w == 0 || h == 0) {
-		return;
-	}
-
-	if (_mouse_texture == _mouse_texture_palette) {
-		_mouse_texture->updateBuffer(0, 0, w, h, buf, w);
-	} else {
-		uint16 pitch = _mouse_texture->pitch();
-		uint16 bpp = _mouse_texture->getPixelFormat().bytesPerPixel;
-
-		byte *tmp = new byte[pitch * h];
-
-		// meh, a n-bit cursor without alpha bits... this is so silly
-		if (!crossBlit(tmp, (const byte *)buf, pitch, w * format->bytesPerPixel, w, h,
-		               _mouse_texture->getPixelFormat(),
-		               *format)) {
-			LOGE("crossblit failed");
-
-			delete[] tmp;
-
-			_mouse_texture->allocBuffer(0, 0);
-
-			return;
-		}
-
-		if (format->bytesPerPixel == 2) {
-			const uint16 *s = (const uint16 *)buf;
-			byte *d = tmp;
-			for (uint16 y = 0; y < h; ++y, d += pitch / 2 - w)
-				for (uint16 x = 0; x < w; ++x, d++)
-					if (*s++ == (keycolor & 0xffff)) {
-						memset(d, 0, bpp);
-					}
-		} else if (format->bytesPerPixel == 4) {
-			const uint32 *s = (const uint32 *)buf;
-			byte *d = tmp;
-			for (uint16 y = 0; y < h; ++y, d += pitch / 2 - w)
-				for (uint16 x = 0; x < w; ++x, d++)
-					if (*s++ == (keycolor & 0xffffffff)) {
-						memset(d, 0, bpp);
-					}
-		} else {
-			error("AndroidGraphics3dManager::setMouseCursor: invalid bytesPerPixel %d", format->bytesPerPixel);
-		}
-
-		_mouse_texture->updateBuffer(0, 0, w, h, tmp, pitch);
-
-		delete[] tmp;
-	}
-
-	_mouse_hotspot = Common::Point(hotspotX, hotspotY);
-	_mouse_dont_scale = dontScale;
-
-	updateCursorScaling();
-}
-
-void AndroidGraphics3dManager::setCursorPalette(const byte *colors,
-        uint start, uint num) {
-	ENTER("%p, %u, %u", colors, start, num);
-
-	GLTHREADCHECK;
-
-	if (!_mouse_texture->hasPalette()) {
-		LOGD("switching to paletted mouse cursor");
-
-		_mouse_texture = _mouse_texture_palette;
-
-		delete _mouse_texture_rgb;
-		_mouse_texture_rgb = 0;
-	}
-
-	_mouse_texture->setPalette(colors, start, num);
-}
-
-bool AndroidGraphics3dManager::lockMouse(bool lock) {
-	_show_mouse = lock;
-	return true;
-}
-
-#ifdef USE_RGB_COLOR
-Graphics::PixelFormat AndroidGraphics3dManager::getScreenFormat() const {
-	return _game_texture->getPixelFormat();
-}
-
-Common::List<Graphics::PixelFormat> AndroidGraphics3dManager::getSupportedFormats() const {
-	Common::List<Graphics::PixelFormat> res;
-
-	// empty list
-
-	return res;
-}
-#endif
-
-void AndroidGraphics3dManager::updateScreenRect() {
-	Common::Rect rect(0, 0, JNI::egl_surface_width, JNI::egl_surface_height);
-
-	_overlay_texture->setDrawRect(rect);
-
-	// Clear the overlay background so it is not displayed distorted while resizing
-	_overlay_background->release();
-
-	uint16 w = getWidth();
-	uint16 h = getHeight();
-
-	if (w && h && _ar_correction) {
-
-		JNI::DPIValues dpi;
-		JNI::getDPI(dpi);
-
-		float screen_ar;
-		if (dpi[0] != 0.0 && dpi[1] != 0.0) {
-			// horizontal orientation
-			screen_ar = (dpi[1] * JNI::egl_surface_width) /
-			            (dpi[0] * JNI::egl_surface_height);
-		} else {
-			screen_ar = float(JNI::egl_surface_width) / float(JNI::egl_surface_height);
-		}
-
-		float game_ar = float(w) / float(h);
-
-		if (screen_ar > game_ar) {
-			rect.setWidth(round(JNI::egl_surface_height * game_ar));
-			rect.moveTo((JNI::egl_surface_width - rect.width()) / 2, 0);
-		} else {
-			rect.setHeight(round(JNI::egl_surface_width / game_ar));
-			if (_virtkeybd_on) {
-				rect.moveTo(0, (JNI::egl_surface_height - rect.height()));
-			} else {
-				rect.moveTo(0, (JNI::egl_surface_height - rect.height()) / 2);
-			}
-		}
-	}
-
-	_game_texture->setDrawRect(rect);
-
-	updateCursorScaling();
-}
-
-const GLESBaseTexture *AndroidGraphics3dManager::getActiveTexture() const {
-	if (!_frame_buffer || _show_overlay) {
-		return _overlay_texture;
-	} else {
-		return _game_texture;
-	}
-}
-
-void AndroidGraphics3dManager::initOverlay() {
-	// minimum of 320x200
-	// (surface can get smaller when opening the virtual keyboard on *QVGA*)
-	int overlay_width = MAX(JNI::egl_surface_width, 320);
-	int overlay_height = MAX(JNI::egl_surface_height, 200);
-
-	LOGI("overlay size is %ux%u", overlay_width, overlay_height);
-
-	_overlay_texture->allocBuffer(overlay_width, overlay_height);
-	_overlay_texture->setDrawRect(0, 0,
-	                              JNI::egl_surface_width, JNI::egl_surface_height);
-}
-
-void AndroidGraphics3dManager::clearScreen(FixupType type, byte count) {
-	assert(count > 0);
-
-	bool sm = _show_mouse;
-	_show_mouse = false;
-
-	CONTEXT_SAVE_STATE(GL_SCISSOR_TEST);
-	CONTEXT_SET_DISABLE(GL_SCISSOR_TEST);
-
-	for (byte i = 0; i < count; ++i) {
-		// clear screen
-		GLCALL(glClearColor(0.f, 0.f, 0.f, 1.f));
-		GLCALL(glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT));
-
-		switch (type) {
-		case kClear:
-			break;
-
-		case kClearSwap:
-			JNI::swapBuffers();
-			break;
-
-		case kClearUpdate:
-			_force_redraw = true;
-			updateScreen();
-			break;
-		}
-	}
-
-	CONTEXT_RESET_DISABLE(GL_SCISSOR_TEST);
-
-	_show_mouse = sm;
-	_force_redraw = true;
-}
-
-float AndroidGraphics3dManager::getHiDPIScreenFactor() const {
-	JNI::DPIValues dpi;
-	JNI::getDPI(dpi);
-	// Scale down the Android factor else the GUI is too big and
-	// there is not much options to go smaller
-	return dpi[2] / 1.2f;
-}
-
-AndroidCommonGraphics::State AndroidGraphics3dManager::getState() const {
-	AndroidCommonGraphics::State state;
-
-	state.screenWidth   = getWidth();
-	state.screenHeight  = getHeight();
-	state.aspectRatio   = getFeatureState(OSystem::kFeatureAspectRatioCorrection);
-	state.fullscreen    = getFeatureState(OSystem::kFeatureFullscreenMode);
-	state.cursorPalette = getFeatureState(OSystem::kFeatureCursorPalette);
-#ifdef USE_RGB_COLOR
-	state.pixelFormat   = _2d_pixel_format;
-#endif
-	return state;
-}
-
-bool AndroidGraphics3dManager::setState(const AndroidCommonGraphics::State &state) {
-	// In 3d we don't have a pixel format so we ignore it but store it for when leaving 3d mode
-	initSize(state.screenWidth, state.screenHeight, nullptr);
-#ifdef USE_RGB_COLOR
-	_2d_pixel_format = state.pixelFormat;
-#endif
-	setFeatureState(OSystem::kFeatureAspectRatioCorrection, state.aspectRatio);
-	setFeatureState(OSystem::kFeatureFullscreenMode, state.fullscreen);
-	setFeatureState(OSystem::kFeatureCursorPalette, state.cursorPalette);
-
-	return true;
-}
-
-void AndroidGraphics3dManager::touchControlInitSurface(const Graphics::ManagedSurface &surf) {
-	if (_touchcontrols_texture->width() == surf.w && _touchcontrols_texture->height() == surf.h) {
-		return;
-	}
-
-	_touchcontrols_texture->allocBuffer(surf.w, surf.h);
-	Graphics::Surface *dst = _touchcontrols_texture->surface();
-
-	Graphics::crossBlit(
-			(byte *)dst->getPixels(), (const byte *)surf.getPixels(),
-			dst->pitch, surf.pitch,
-			surf.w, surf.h,
-			surf.format, dst->format);
-}
-
-void AndroidGraphics3dManager::touchControlNotifyChanged() {
-	// Make sure we redraw the screen
-	_force_redraw = true;
-}
-
-void AndroidGraphics3dManager::touchControlDraw(uint8 alpha, int16 x, int16 y, int16 w, int16 h, const Common::Rect &clip) {
-	_touchcontrols_texture->setAlpha(alpha / 255.f);
-	_touchcontrols_texture->drawTexture(x, y, w, h, clip);
-}
-
-void AndroidGraphics3dManager::applyTouchSettings() const {
-	// in 3D, maybe in GUI
-	dynamic_cast<OSystem_Android *>(g_system)->applyTouchSettings(true, _show_overlay && _overlay_in_gui);
-}
-
-void AndroidGraphics3dManager::syncVirtkeyboardState(bool virtkeybd_on) {
-	_virtkeybd_on = virtkeybd_on;
-	updateScreenRect();
-	_force_redraw = true;
-}
diff --git a/backends/graphics3d/android/android-graphics3d.h b/backends/graphics3d/android/android-graphics3d.h
deleted file mode 100644
index 007a8ee9279..00000000000
--- a/backends/graphics3d/android/android-graphics3d.h
+++ /dev/null
@@ -1,197 +0,0 @@
-/* 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 3 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, see <http://www.gnu.org/licenses/>.
- *
- */
-
-#ifndef BACKENDS_GRAPHICS3D_ANDROID_ANDROID_GRAPHICS3D_H
-#define BACKENDS_GRAPHICS3D_ANDROID_ANDROID_GRAPHICS3D_H
-
-#include "common/scummsys.h"
-
-#include "backends/graphics/graphics.h"
-#include "backends/graphics/android/android-graphics.h"
-#include "backends/graphics3d/android/texture.h"
-
-#include "backends/platform/android/touchcontrols.h"
-
-class AndroidGraphics3dManager :
-	public GraphicsManager, public AndroidCommonGraphics, public TouchControlsDrawer {
-public:
-	AndroidGraphics3dManager();
-	virtual ~AndroidGraphics3dManager();
-
-	virtual void initSurface() override;
-	virtual void deinitSurface() override;
-	virtual void resizeSurface() override;
-
-	virtual AndroidCommonGraphics::State getState() const override;
-	virtual bool setState(const AndroidCommonGraphics::State &state) override;
-
-	void updateScreen() override;
-
-	void displayMessageOnOSD(const Common::U32String &msg);
-
-	virtual bool notifyMousePosition(Common::Point &mouse) override;
-	virtual Common::Point getMousePosition() override {
-		return Common::Point(_cursorX, _cursorY);
-	}
-	void setMousePosition(int x, int y) {
-		_cursorX = x;
-		_cursorY = y;
-	}
-
-	virtual void beginGFXTransaction() {}
-	virtual OSystem::TransactionError endGFXTransaction() {
-		return OSystem::kTransactionSuccess;
-	}
-
-	virtual const OSystem::GraphicsMode *getSupportedGraphicsModes() const override;
-	virtual int getDefaultGraphicsMode() const override;
-	virtual bool setGraphicsMode(int mode, uint flags = OSystem::kGfxModeNoFlags) override;
-	virtual int getGraphicsMode() const override;
-
-	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 showOverlay(bool inGUI) override;
-	virtual void hideOverlay() override;
-	virtual void clearOverlay() override;
-	virtual void grabOverlay(Graphics::Surface &surface) const override;
-	virtual void copyRectToOverlay(const void *buf, int pitch,
-	                               int x, int y, int w, int h) override;
-	virtual int16 getOverlayHeight() const override;
-	virtual int16 getOverlayWidth() const override;
-	virtual Graphics::PixelFormat getOverlayFormat() const override;
-	virtual bool isOverlayVisible() const override {
-		return _show_overlay;
-	}
-
-	virtual int16 getHeight() const override;
-	virtual int16 getWidth() const override;
-
-	// PaletteManager API
-	virtual void setPalette(const byte *colors, uint start, uint num) override;
-	virtual void grabPalette(byte *colors, uint start, uint num) const override;
-	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 fillScreen(const Common::Rect &r, uint32 col) override;
-
-	virtual void setShakePos(int shakeXOffset, int shakeYOffset) {};
-	virtual void setFocusRectangle(const Common::Rect &rect) {}
-	virtual void clearFocusRectangle() {}
-
-	virtual void initSize(uint width, uint height,
-	                      const Graphics::PixelFormat *format) override;
-	virtual int getScreenChangeID() const override;
-
-	virtual bool showMouse(bool visible) override;
-	virtual void warpMouse(int x, int y) override;
-	virtual bool lockMouse(bool lock) override;
-	virtual void setMouseCursor(const void *buf, uint w, uint h, int hotspotX,
-	                            int hotspotY, uint32 keycolor,
-	                            bool dontScale,
-	                            const Graphics::PixelFormat *format, const byte *mask) override;
-	virtual void setCursorPalette(const byte *colors, uint start, uint num) override;
-
-	float getHiDPIScreenFactor() const override;
-
-#ifdef USE_RGB_COLOR
-	virtual Graphics::PixelFormat getScreenFormat() const override;
-	virtual Common::List<Graphics::PixelFormat> getSupportedFormats() const override;
-#endif
-
-	void touchControlInitSurface(const Graphics::ManagedSurface &surf) override;
-	void touchControlNotifyChanged() override;
-	void touchControlDraw(uint8 alpha, int16 x, int16 y, int16 w, int16 h, const Common::Rect &clip) override;
-
-	void syncVirtkeyboardState(bool virtkeybd_on) override;
-	void applyTouchSettings() const override;
-
-protected:
-	void updateScreenRect();
-	void updateCursorScaling();
-	const GLESBaseTexture *getActiveTexture() const;
-
-	Common::Point convertScreenToVirtual(int &x, int &y) const;
-	Common::Point convertVirtualToScreen(int x, int y) const;
-
-	void setSystemMousePosition(int x, int y) {}
-
-	bool loadVideoMode(uint requestedWidth, uint requestedHeight, const Graphics::PixelFormat &format);
-
-private:
-	void initOverlay();
-
-	enum FixupType {
-		kClear = 0,     // glClear
-		kClearSwap,     // glClear + swapBuffers
-		kClearUpdate    // glClear + updateScreen
-	};
-
-	void clearScreen(FixupType type, byte count = 1);
-
-private:
-	int _screenChangeID;
-	int _graphicsMode;
-	bool _fullscreen;
-	bool _ar_correction;
-	bool _force_redraw;
-
-	bool _virtkeybd_on;
-
-	// Game layer
-	GLESTexture *_game_texture;
-	AndroidFrameBuffer *_frame_buffer;
-
-#ifdef USE_RGB_COLOR
-	// Backup of the previous pixel format to pass it back when we leave 3d
-	Graphics::PixelFormat _2d_pixel_format;
-#endif
-
-	/**
-	 * The position of the mouse cursor, in window coordinates.
-	 */
-	int _cursorX, _cursorY;
-
-	// Overlay layer
-	GLESTexture *_overlay_background;
-	GLESTexture *_overlay_texture;
-	bool _show_overlay;
-	bool _overlay_in_gui;
-
-	// Mouse layer
-	GLESBaseTexture *_mouse_texture;
-	GLESFakePaletteTexture *_mouse_texture_palette;
-	GLESTexture *_mouse_texture_rgb;
-	Common::Point _mouse_hotspot;
-	Common::Point _mouse_hotspot_scaled;
-	int _mouse_width_scaled, _mouse_height_scaled;
-	bool _mouse_dont_scale;
-	bool _show_mouse;
-
-	// Touch controls layer
-	GLESTexture *_touchcontrols_texture;
-	int _old_touch_mode;
-};
-
-#endif
diff --git a/backends/graphics3d/android/texture.cpp b/backends/graphics3d/android/texture.cpp
deleted file mode 100644
index 9572af9f89a..00000000000
--- a/backends/graphics3d/android/texture.cpp
+++ /dev/null
@@ -1,680 +0,0 @@
-/* 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 3 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, see <http://www.gnu.org/licenses/>.
- *
- */
-
-// Allow use of stuff in <time.h>
-#define FORBIDDEN_SYMBOL_EXCEPTION_time_h
-
-// Disable printf override in common/forbidden.h to avoid
-// clashes with log.h from the Android SDK.
-// That header file uses
-//   __attribute__ ((format(printf, 3, 4)))
-// which gets messed up by our override mechanism; this could
-// be avoided by either changing the Android SDK to use the equally
-// legal and valid
-//   __attribute__ ((format(printf, 3, 4)))
-// or by refining our printf override to use a varadic macro
-// (which then wouldn't be portable, though).
-// Anyway, for now we just disable the printf override globally
-// for the Android port
-#define FORBIDDEN_SYMBOL_EXCEPTION_printf
-
-#include "backends/platform/android/android.h"
-#include "backends/platform/android/jni-android.h"
-
-#include "base/main.h"
-#include "graphics/surface.h"
-#include "graphics/opengl/shader.h"
-#include "graphics/opengl/context.h"
-
-#include "common/rect.h"
-#include "common/array.h"
-#include "common/util.h"
-
-#include "backends/graphics3d/android/texture.h"
-
-
-AndroidFrameBuffer::AndroidFrameBuffer(GLenum glIntFormat, GLenum glFormat, GLenum glType, GLuint texture_name, uint width, uint height, uint texture_width, uint texture_height) :
-		OpenGL::FrameBuffer(glIntFormat, glFormat, glType, false) {
-	if (!OpenGLContext.framebufferObjectSupported) {
-		error("FrameBuffer Objects are not supported by the current OpenGL context");
-	}
-
-	_logicalWidth = width;
-	_logicalHeight = height;
-	_width = texture_width;
-	_height = texture_height;
-	_glTexture = texture_name;
-
-	if (_width != 0 && _height != 0) {
-		const GLfloat texWidth = (GLfloat)_logicalWidth / _width;
-		const GLfloat texHeight = (GLfloat)_logicalHeight / _height;
-
-		_texCoords[0] = 0;
-		_texCoords[1] = 0;
-
-		_texCoords[2] = texWidth;
-		_texCoords[3] = 0;
-
-		_texCoords[4] = 0;
-		_texCoords[5] = texHeight;
-
-		_texCoords[6] = texWidth;
-		_texCoords[7] = texHeight;
-	}
-
-	enableLinearFiltering(true);
-
-	init();
-}
-
-AndroidFrameBuffer::~AndroidFrameBuffer() {
-	// Prevent the texture from being deleted by the parent class
-	_glTexture = 0;
-}
-
-// Supported GL extensions
-bool GLESBaseTexture::_npot_supported = false;
-OpenGL::Shader *GLESBaseTexture::_box_shader = nullptr;
-GLuint GLESBaseTexture::_verticesVBO = 0;
-
-template<class T>
-static T nextHigher2(T k) {
-	if (k == 0) {
-		return 1;
-	}
-	--k;
-
-	for (uint i = 1; i < sizeof(T) * CHAR_BIT; i <<= 1) {
-		k = k | k >> i;
-	}
-
-	return k + 1;
-}
-
-static const GLfloat vertices[] = {
-	0.0, 0.0,
-	1.0, 0.0,
-	0.0, 1.0,
-	1.0, 1.0,
-};
-
-static const char *controlVertex =
-	"#version 100\n"
-	"attribute vec2 position;\n"
-	"attribute vec2 texcoord;\n"
-	"uniform vec2 offsetXY;\n"
-	"uniform vec2 sizeWH;\n"
-	"uniform vec4 clip;\n"
-	"uniform bool flipY;\n"
-	"varying vec2 Texcoord;\n"
-	"void main() {\n"
-		"Texcoord = clip.xy + texcoord * (clip.zw - clip.xy);\n"
-		"vec2 pos = offsetXY + position * sizeWH;\n"
-		"pos.x = pos.x * 2.0 - 1.0;\n"
-		"pos.y = pos.y * 2.0 - 1.0;\n"
-		"if (flipY)\n"
-			"pos.y *= -1.0;\n"
-		"gl_Position = vec4(pos, 0.0, 1.0);\n"
-	"}\n";
-
-static const char *controlFragment =
-	"#version 100\n"
-	"#ifdef GL_FRAGMENT_PRECISION_HIGH\n"
-		"precision highp float;\n"
-	"#else\n"
-		"precision mediump float;\n"
-	"#endif\n"
-	"varying vec2 Texcoord;\n"
-	"uniform float alpha;\n"
-	"uniform sampler2D tex;\n"
-	"void main() {\n"
-		"gl_FragColor = texture2D(tex, Texcoord) * vec4(1.0, 1.0, 1.0, alpha);\n"
-	"}\n";
-
-void GLESBaseTexture::initGL() {
-	_npot_supported = OpenGLContext.NPOTSupported;
-
-	const char *attributes[] = { "position", "texcoord", NULL };
-	_box_shader = OpenGL::Shader::fromStrings("control", controlVertex, controlFragment, attributes);
-	_verticesVBO = OpenGL::Shader::createBuffer(GL_ARRAY_BUFFER, sizeof(vertices), vertices);
-	_box_shader->enableVertexAttribute("position", _verticesVBO, 2, GL_FLOAT, GL_TRUE,
-	                                   2 * sizeof(float), 0);
-	_box_shader->enableVertexAttribute("texcoord", _verticesVBO, 2, GL_FLOAT, GL_TRUE,
-	                                   2 * sizeof(float), 0);
-}
-
-void GLESBaseTexture::unbindShader() {
-	if (_box_shader) {
-		_box_shader->unbind();
-	}
-}
-
-GLESBaseTexture::GLESBaseTexture(GLenum glFormat, GLenum glType,
-                                 Graphics::PixelFormat pixelFormat) :
-	_glFormat(glFormat),
-	_glType(glType),
-	_glFilter(GL_NEAREST),
-	_texture_name(0),
-	_surface(),
-	_texture_width(0),
-	_texture_height(0),
-	_alpha(1.f),
-	_draw_rect(),
-	_all_dirty(false),
-	_dirty_rect(),
-	_pixelFormat(pixelFormat),
-	_palettePixelFormat(),
-	_is_game_texture(false) {
-}
-
-GLESBaseTexture::~GLESBaseTexture() {
-	release();
-}
-
-void GLESBaseTexture::release() {
-	if (_texture_name) {
-		GLCALL(glDeleteTextures(1, &_texture_name));
-		_texture_name = 0;
-	}
-}
-
-void GLESBaseTexture::reinit() {
-	if (_texture_name) {
-		release();
-	}
-
-	GLCALL(glGenTextures(1, &_texture_name));
-
-	initSize();
-
-	setDirty();
-}
-
-void GLESBaseTexture::initSize() {
-	if (!_texture_name) {
-		return;
-	}
-
-	// Allocate room for the texture now, but pixel data gets uploaded
-	// later (perhaps with multiple TexSubImage2D operations).
-	GLCALL(glBindTexture(GL_TEXTURE_2D, _texture_name));
-	GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, _glFilter));
-	GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, _glFilter));
-	GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
-	GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
-	GLCALL(glTexImage2D(GL_TEXTURE_2D, 0, _glFormat,
-	                    _texture_width, _texture_height,
-	                    0, _glFormat, _glType, 0));
-}
-
-void GLESBaseTexture::setLinearFilter(bool value) {
-	if (value) {
-		_glFilter = GL_LINEAR;
-	} else {
-		_glFilter = GL_NEAREST;
-	}
-
-	if (!_texture_name) {
-		return;
-	}
-
-	GLCALL(glBindTexture(GL_TEXTURE_2D, _texture_name));
-
-	GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, _glFilter));
-	GLCALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, _glFilter));
-}
-
-void GLESBaseTexture::allocBuffer(GLuint w, GLuint h) {
-	if (w == _surface.w && h == _surface.h) {
-		return;
-	}
-
-	_surface.w = w;
-	_surface.h = h;
-	_surface.format = _pixelFormat;
-
-	if (_npot_supported) {
-		_texture_width = _surface.w;
-		_texture_height = _surface.h;
-	} else {
-		_texture_width = nextHigher2(_surface.w);
-		_texture_height = nextHigher2(_surface.h);
-	}
-
-	initSize();
-}
-
-void GLESBaseTexture::drawTexture(GLshort x, GLshort y, GLshort w, GLshort h,
-                                  const Common::Rect &clip) {
-	if (!_texture_name) {
-		return;
-	}
-
-	if (_all_dirty) {
-		_dirty_rect.top = 0;
-		_dirty_rect.left = 0;
-		_dirty_rect.bottom = _surface.h;
-		_dirty_rect.right = _surface.w;
-
-		_all_dirty = false;
-	}
-
-	if (!_dirty_rect.isEmpty()) {
-		void *tex = prepareTextureBuffer(_dirty_rect);
-
-		GLCALL(glBindTexture(GL_TEXTURE_2D, _texture_name));
-		GLCALL(glPixelStorei(GL_UNPACK_ALIGNMENT, 1));
-
-		GLCALL(glTexSubImage2D(GL_TEXTURE_2D, 0,
-		                       _dirty_rect.left, _dirty_rect.top,
-		                       _dirty_rect.width(), _dirty_rect.height(),
-		                       _glFormat, _glType, tex));
-	}
-
-
-//	LOGD("*** Texture %p: Drawing %dx%d rect to (%d,%d)", this, w, h, x, y);
-
-	assert(_box_shader);
-	_box_shader->use();
-
-	GLCALL(glBindTexture(GL_TEXTURE_2D, _texture_name));
-	const GLfloat offsetX    = float(x) / float(JNI::egl_surface_width);
-	const GLfloat offsetY    = float(y) / float(JNI::egl_surface_height);
-	const GLfloat sizeW      = float(w) / float(JNI::egl_surface_width);
-	const GLfloat sizeH      = float(h) / float(JNI::egl_surface_height);
-	Math::Vector4d clipV = Math::Vector4d(clip.left, clip.top, clip.right, clip.bottom);
-	clipV.x() /= _texture_width;
-	clipV.y() /= _texture_height;
-	clipV.z() /= _texture_width;
-	clipV.w() /= _texture_height;
-//	LOGD("*** Drawing at (%f,%f) , size %f x %f", float(x) / float(_surface.w), float(y) / float(_surface.h),  tex_width, tex_height);
-
-	_box_shader->setUniform1f("alpha", _alpha);
-	_box_shader->setUniform("offsetXY", Math::Vector2d(offsetX, offsetY));
-	_box_shader->setUniform("sizeWH", Math::Vector2d(sizeW, sizeH));
-	_box_shader->setUniform("clip", clipV);
-	_box_shader->setUniform("flipY", !_is_game_texture);
-
-	GLCALL(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4));
-
-	clearDirty();
-}
-
-const Graphics::PixelFormat &GLESBaseTexture::getPixelFormat() const {
-	return _pixelFormat;
-}
-
-GLESTexture::GLESTexture(GLenum glFormat, GLenum glType,
-                         Graphics::PixelFormat pixelFormat) :
-	GLESBaseTexture(glFormat, glType, pixelFormat),
-	_pixels(nullptr),
-	_buf(nullptr) {
-}
-
-GLESTexture::~GLESTexture() {
-	delete[] _buf;
-	delete[] _pixels;
-}
-
-void GLESTexture::allocBuffer(GLuint w, GLuint h) {
-	GLuint oldw = _surface.w;
-	GLuint oldh = _surface.h;
-
-	GLESBaseTexture::allocBuffer(w, h);
-
-	_surface.pitch = w * _pixelFormat.bytesPerPixel;
-
-	if (_surface.w == oldw && _surface.h == oldh) {
-		fillBuffer(0);
-		return;
-	}
-
-	delete[] _buf;
-	delete[] _pixels;
-
-	_pixels = new byte[w * h * _surface.format.bytesPerPixel];
-
-	_surface.setPixels(_pixels);
-
-	fillBuffer(0);
-
-	_buf = new byte[w * h * _surface.format.bytesPerPixel];
-}
-
-void GLESTexture::updateBuffer(GLuint x, GLuint y, GLuint w, GLuint h,
-                               const void *buf, int pitch_buf) {
-	setDirtyRect(Common::Rect(x, y, x + w, y + h));
-
-	const byte *src = (const byte *)buf;
-	byte *dst = _pixels + y * _surface.pitch + x * _surface.format.bytesPerPixel;
-
-	do {
-		memcpy(dst, src, w * _surface.format.bytesPerPixel);
-		dst += _surface.pitch;
-		src += pitch_buf;
-	} while (--h);
-}
-
-void GLESTexture::fillBuffer(uint32 color) {
-	assert(_surface.getPixels());
-
-	if (_pixelFormat.bytesPerPixel == 1 ||
-	        ((color & 0xff) == ((color >> 8) & 0xff))) {
-		memset(_pixels, color & 0xff, _surface.pitch * _surface.h);
-	} else {
-		Common::fill(_pixels, _pixels + _surface.pitch * _surface.h,
-		             (uint16)color);
-	}
-
-	setDirty();
-}
-
-void *GLESTexture::prepareTextureBuffer(const Common::Rect &rect) {
-	if (rect.width() == _surface.w) {
-		return _pixels + rect.top * _surface.pitch;
-	} else {
-		byte *tex = _buf;
-
-		byte *src = _pixels + rect.top * _surface.pitch +
-			    rect.left * _surface.format.bytesPerPixel;
-		byte *dst = _buf;
-
-		uint16 l = rect.width() * _surface.format.bytesPerPixel;
-
-		for (uint16 i = rect.height(); i > 0; --i) {
-			memcpy(dst, src, l);
-			src += _surface.pitch;
-			dst += l;
-		}
-
-		return tex;
-	}
-}
-
-void GLESTexture::readPixels() {
-	GLCALL(glReadPixels(0, 0, _surface.w, _surface.h, _glFormat, _glType,
-			    _pixels));
-	setDirty();
-}
-
-GLESFakePaletteTexture::GLESFakePaletteTexture(GLenum glFormat, GLenum glType,
-        Graphics::PixelFormat pixelFormat) :
-	GLESBaseTexture(glFormat, glType, pixelFormat),
-	_pixels(nullptr) {
-	_palettePixelFormat = pixelFormat;
-	_fake_format = Graphics::PixelFormat::createFormatCLUT8();
-}
-
-GLESFakePaletteTexture::~GLESFakePaletteTexture() {
-	delete[] _pixels;
-}
-
-void GLESFakePaletteTexture::allocBuffer(GLuint w, GLuint h) {
-	GLuint oldw = _surface.w;
-	GLuint oldh = _surface.h;
-
-	GLESBaseTexture::allocBuffer(w, h);
-
-	_surface.format = Graphics::PixelFormat::createFormatCLUT8();
-	_surface.pitch = w;
-
-	if (_surface.w == oldw && _surface.h == oldh) {
-		fillBuffer(0);
-		return;
-	}
-
-	delete[] _pixels;
-	_pixels = nullptr;
-
-	_pixels = new byte[w * h];
-
-	// fixup surface, for the outside this is a CLUT8 surface
-	_surface.setPixels(_pixels);
-
-	fillBuffer(0);
-}
-
-void GLESFakePaletteTexture::fillBuffer(uint32 color) {
-	assert(_surface.getPixels());
-	memset(_surface.getPixels(), color & 0xff, _surface.pitch * _surface.h);
-	setDirty();
-}
-
-void GLESFakePaletteTexture::updateBuffer(GLuint x, GLuint y,
-        GLuint w, GLuint h, const void *buf, int pitch_buf) {
-	setDirtyRect(Common::Rect(x, y, x + w, y + h));
-
-	const byte *src = (const byte *)buf;
-	byte *dst = _pixels + y * _surface.pitch + x;
-
-	do {
-		memcpy(dst, src, w);
-		dst += _surface.pitch;
-		src += pitch_buf;
-	} while (--h);
-}
-
-GLESFakePalette16Texture::GLESFakePalette16Texture(GLenum glFormat, GLenum glType,
-        Graphics::PixelFormat pixelFormat) :
-	GLESFakePaletteTexture(glFormat, glType, pixelFormat),
-	_palette(nullptr),
-	_buf(nullptr) {
-	_palette = new uint16[256];
-	memset(_palette, 0, sizeof(*_palette) * 256);
-}
-
-GLESFakePalette16Texture::~GLESFakePalette16Texture() {
-	delete[] _buf;
-	delete[] _palette;
-}
-
-void GLESFakePalette16Texture::allocBuffer(GLuint w, GLuint h) {
-	delete[] _buf;
-	_buf = nullptr;
-
-	GLESFakePaletteTexture::allocBuffer(w, h);
-
-	_buf = new uint16[w * h];
-}
-
-void *GLESFakePalette16Texture::prepareTextureBuffer(const Common::Rect &rect) {
-	int16 w = rect.width();
-
-	byte *src = _pixels + rect.top * _surface.pitch +
-		    rect.left;
-	uint16 *dst = _buf;
-	uint pitch_delta = _surface.pitch - w;
-
-	for (uint16 j = rect.height(); j > 0; --j) {
-		for (uint16 i = 0; i < w; ++i) {
-			*dst++ = _palette[*src++];
-		}
-		src += pitch_delta;
-	}
-
-	return _buf;
-}
-
-void GLESFakePalette16Texture::setPalette(const byte *colors, uint start, uint num) {
-	uint16 *p = _palette + start;
-
-	for (uint i = 0; i < num; ++i, colors += 3, ++p) {
-		*p = _palettePixelFormat.RGBToColor(colors[0], colors[1], colors[2]);
-	}
-}
-
-void GLESFakePalette16Texture::grabPalette(byte *colors, uint start, uint num) const {
-        const uint16 *p = _palette + start;
-
-        for (uint i = 0; i < num; ++i, colors += 3, ++p) {
-                _palettePixelFormat.colorToRGB(*p, colors[0], colors[1], colors[2]);
-        }
-}
-
-GLESFakePalette565Texture::GLESFakePalette565Texture() :
-	GLESFakePalette16Texture(GL_RGB, GL_UNSIGNED_SHORT_5_6_5,
-	                         GLES565Texture::pixelFormat()) {
-}
-
-GLESFakePalette5551Texture::GLESFakePalette5551Texture() :
-	GLESFakePalette16Texture(GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1,
-	                         GLES5551Texture::pixelFormat()),
-	_keycolor(0) {
-}
-
-void GLESFakePalette5551Texture::setKeycolor(byte color) {
-	uint16 *p = _palette + _keycolor;
-	*p |= 1;
-
-	_keycolor = color;
-
-	p = _palette + _keycolor;
-	*p &= ~1;
-}
-
-GLESFakePalette888Texture::GLESFakePalette888Texture() :
-	GLESFakePaletteTexture(GL_RGB, GL_UNSIGNED_BYTE,
-	                       GLES888Texture::pixelFormat()),
-	_palette(nullptr),
-	_buf(nullptr) {
-	_palette = new byte[256 * 3];
-	memset(_palette, 0, 256 * 3);
-}
-
-GLESFakePalette888Texture::~GLESFakePalette888Texture() {
-	delete[] _buf;
-	delete[] _palette;
-}
-
-void GLESFakePalette888Texture::allocBuffer(GLuint w, GLuint h) {
-	delete[] _buf;
-	_buf = nullptr;
-
-	GLESFakePaletteTexture::allocBuffer(w, h);
-
-	_buf = new byte[w * h * 3];
-}
-
-void *GLESFakePalette888Texture::prepareTextureBuffer(const Common::Rect &rect) {
-	int16 w = rect.width();
-
-	byte *src = _pixels + rect.top * _surface.pitch +
-		    rect.left;
-	byte *dst = _buf;
-	uint pitch_delta = _surface.pitch - w;
-
-	for (uint16 j = rect.height(); j > 0; --j) {
-		for (uint16 i = 0; i < w; ++i) {
-			byte c = *src++;
-			byte *p = _palette + c * 3;
-			*dst++ = *p++;
-			*dst++ = *p++;
-			*dst++ = *p++;
-		}
-		src += pitch_delta;
-	}
-
-	return _buf;
-}
-
-void GLESFakePalette888Texture::setPalette(const byte *colors, uint start, uint num) {
-	memcpy(_palette + start * 3, colors, num * 3);
-}
-
-void GLESFakePalette888Texture::grabPalette(byte *colors, uint start, uint num) const {
-	memcpy(colors, _palette + start * 3, num * 3);
-}
-
-GLESFakePalette8888Texture::GLESFakePalette8888Texture() :
-	GLESFakePaletteTexture(GL_RGBA, GL_UNSIGNED_BYTE,
-	                       GLES8888Texture::pixelFormat()),
-	_palette(nullptr),
-	_buf(nullptr),
-	_keycolor(0) {
-	_palette = new uint32[256];
-	memset(_palette, 0, sizeof(*_palette) * 256);
-}
-
-GLESFakePalette8888Texture::~GLESFakePalette8888Texture() {
-	delete[] _buf;
-	delete[] _palette;
-}
-
-void GLESFakePalette8888Texture::allocBuffer(GLuint w, GLuint h) {
-	delete[] _buf;
-	_buf = nullptr;
-
-	GLESFakePaletteTexture::allocBuffer(w, h);
-
-	_buf = new uint32[w * h];
-}
-
-void *GLESFakePalette8888Texture::prepareTextureBuffer(const Common::Rect &rect) {
-	int16 w = rect.width();
-
-	byte *src = _pixels + rect.top * _surface.pitch +
-		    rect.left;
-	uint32 *dst = _buf;
-	uint pitch_delta = _surface.pitch - w;
-
-	for (uint16 j = rect.height(); j > 0; --j) {
-		for (uint16 i = 0; i < w; ++i) {
-			*dst++ = _palette[*src++];
-		}
-		src += pitch_delta;
-	}
-
-	return _buf;
-}
-
-void GLESFakePalette8888Texture::setPalette(const byte *colors, uint start, uint num) {
-	// We use _palette as a uint32 to ensure proper alignment but we store bytes in a endian independent fashion
-	// because GL_UNSIGNED_BYTE is endian neutral
-	byte *p = (byte *)(_palette + start);
-
-	for (uint i = 0; i < num; ++i, colors += 3, p += 4) {
-		p[0] = colors[0];
-		p[1] = colors[1];
-		p[2] = colors[2];
-		p[3] = 255;
-	}
-}
-
-void GLESFakePalette8888Texture::setKeycolor(byte color) {
-	// _palette is endian neutral even though it's an uint32
-	byte *p = (byte *)(_palette + _keycolor);
-	p[3] = 255;
-
-	_keycolor = color;
-
-	p = (byte *)(_palette + _keycolor);
-	p[3] = 0;
-}
-
-void GLESFakePalette8888Texture::grabPalette(byte *colors, uint start, uint num) const {
-	const byte *p = (byte *)(_palette + start);
-
-        for (uint i = 0; i < num; ++i, colors += 3, p += 4) {
-		colors[0] = p[0];
-		colors[1] = p[1];
-		colors[2] = p[2];
-        }
-}
diff --git a/backends/graphics3d/android/texture.h b/backends/graphics3d/android/texture.h
deleted file mode 100644
index 67acbc60adf..00000000000
--- a/backends/graphics3d/android/texture.h
+++ /dev/null
@@ -1,400 +0,0 @@
-/* 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 3 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, see <http://www.gnu.org/licenses/>.
- *
- */
-
-#ifndef BACKENDS_GRAPHICS3D_ANDROID_TEXTURE_H
-#define BACKENDS_GRAPHICS3D_ANDROID_TEXTURE_H
-
-#define GL_GLEXT_PROTOTYPES
-#include <GLES/gl.h>
-
-#include "backends/graphics3d/opengl/framebuffer.h"
-#include "graphics/surface.h"
-#include "graphics/pixelformat.h"
-
-#include "common/rect.h"
-#include "common/array.h"
-
-namespace OpenGL {
-class Shader;
-}
-
-class AndroidFrameBuffer : public OpenGL::FrameBuffer {
-public:
-	AndroidFrameBuffer(GLenum glIntFormat, GLenum glFormat, GLenum glType, GLuint texture_name, uint width, uint height, uint texture_width, uint texture_height);
-	~AndroidFrameBuffer();
-};
-
-class GLESBaseTexture {
-public:
-	static void initGL();
-	static void unbindShader();
-
-protected:
-	GLESBaseTexture(GLenum glFormat, GLenum glType,
-	                Graphics::PixelFormat pixelFormat);
-
-public:
-	virtual ~GLESBaseTexture();
-
-	void release();
-	void reinit();
-
-	void setLinearFilter(bool value);
-
-	virtual void allocBuffer(GLuint w, GLuint h);
-
-	virtual void updateBuffer(GLuint x, GLuint y, GLuint width, GLuint height,
-	                          const void *buf, int pitch_buf) = 0;
-	virtual void fillBuffer(uint32 color) = 0;
-
-	void drawTexture(GLshort x, GLshort y, GLshort w, GLshort h) {
-		drawTexture(x, y, w, h, Common::Rect(0, 0, width(), height()));
-	}
-	void drawTexture(GLshort x, GLshort y, GLshort w, GLshort h, const Common::Rect &clip);
-
-	inline void setDrawRect(const Common::Rect &rect) {
-		_draw_rect = rect;
-	}
-
-	inline void setDrawRect(int16 w, int16 h) {
-		_draw_rect = Common::Rect(w, h);
-	}
-
-	inline void setDrawRect(int16 x1, int16 y1, int16 x2, int16 y2) {
-		_draw_rect = Common::Rect(x1, y1, x2, y2);
-	}
-
-	inline const Common::Rect &getDrawRect() const {
-		return _draw_rect;
-	}
-
-	inline void drawTextureRect() {
-		drawTexture(_draw_rect.left, _draw_rect.top,
-		            _draw_rect.width(), _draw_rect.height());
-	}
-
-	inline void drawTextureOrigin() {
-		drawTexture(0, 0, _surface.w, _surface.h);
-	}
-
-	inline GLuint width() const {
-		return _surface.w;
-	}
-
-	inline GLuint height() const {
-		return _surface.h;
-	}
-
-	inline GLuint texWidth() const {
-		return _texture_width;
-	}
-
-	inline GLuint texHeight() const {
-		return _texture_height;
-	}
-
-	inline uint16 pitch() const {
-		return _surface.pitch;
-	}
-
-	inline bool isEmpty() const {
-		return _surface.w == 0 || _surface.h == 0;
-	}
-
-	inline const Graphics::Surface *surface_const() const {
-		return &_surface;
-	}
-
-	inline Graphics::Surface *surface() {
-		setDirty();
-		return &_surface;
-	}
-
-	virtual void setPalette(const byte *colors, uint start, uint num) = 0;
-	virtual void setKeycolor(byte color) = 0;
-	virtual void grabPalette(byte *colors, uint start, uint num) const = 0;
-
-	inline bool hasPalette() const {
-		return _palettePixelFormat.bytesPerPixel > 0;
-	}
-
-	inline bool dirty() const {
-		return _all_dirty || !_dirty_rect.isEmpty();
-	}
-
-	virtual const Graphics::PixelFormat &getPixelFormat() const;
-
-	inline const Graphics::PixelFormat &getPalettePixelFormat() const {
-		return _palettePixelFormat;
-	}
-
-	GLuint getTextureName() const {
-		return _texture_name;
-	}
-
-	GLenum getTextureFormat() const {
-		return _glFormat;
-	}
-
-	GLenum getTextureType() const {
-		return _glType;
-	}
-
-	void setGameTexture() {
-		_is_game_texture = true;
-	}
-
-	void setAlpha(float alpha) {
-		_alpha = alpha;
-	}
-
-protected:
-	void initSize();
-
-	virtual void *prepareTextureBuffer(const Common::Rect &rect) = 0;
-
-	inline void setDirty() {
-		_all_dirty = true;
-	}
-
-	inline void clearDirty() {
-		_all_dirty = false;
-		_dirty_rect.top = 0;
-		_dirty_rect.left = 0;
-		_dirty_rect.bottom = 0;
-		_dirty_rect.right = 0;
-	}
-
-	inline void setDirtyRect(const Common::Rect &r) {
-		if (!_all_dirty) {
-			if (_dirty_rect.isEmpty()) {
-				_dirty_rect = r;
-			} else {
-				_dirty_rect.extend(r);
-			}
-		}
-	}
-
-	GLenum _glFormat;
-	GLenum _glType;
-	GLint _glFilter;
-
-	GLuint _texture_name;
-	Graphics::Surface _surface;
-	GLuint _texture_width;
-	GLuint _texture_height;
-
-	Common::Rect _draw_rect;
-
-	bool _all_dirty;
-	Common::Rect _dirty_rect;
-
-	Graphics::PixelFormat _pixelFormat;
-	Graphics::PixelFormat _palettePixelFormat;
-
-	bool _is_game_texture;
-
-	GLfloat _alpha;
-
-	static bool _npot_supported;
-	static OpenGL::Shader *_box_shader;
-	static GLuint _verticesVBO;
-
-};
-
-class GLESTexture : public GLESBaseTexture {
-protected:
-	GLESTexture(GLenum glFormat, GLenum glType,
-	            Graphics::PixelFormat pixelFormat);
-
-public:
-	virtual ~GLESTexture();
-
-	void allocBuffer(GLuint w, GLuint h) override;
-
-	void updateBuffer(GLuint x, GLuint y, GLuint width, GLuint height,
-	                          const void *buf, int pitch_buf) override;
-	void fillBuffer(uint32 color) override;
-
-	void setPalette(const byte *colors, uint start, uint num) override {}
-	void setKeycolor(byte color) override {};
-	void grabPalette(byte *colors, uint start, uint num) const override {}
-
-	void readPixels();
-
-protected:
-	void *prepareTextureBuffer(const Common::Rect &rect) override;
-
-	byte *_pixels;
-	byte *_buf;
-};
-
-// RGBA4444 texture
-class GLES4444Texture : public GLESTexture {
-public:
-	GLES4444Texture() : GLESTexture(GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, pixelFormat()) {}
-	virtual ~GLES4444Texture() {}
-
-	static Graphics::PixelFormat pixelFormat() {
-		return Graphics::PixelFormat(2, 4, 4, 4, 4, 12, 8, 4, 0);
-	}
-};
-
-// RGBA5551 texture
-class GLES5551Texture : public GLESTexture {
-public:
-	GLES5551Texture() : GLESTexture(GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, pixelFormat()) {}
-	virtual ~GLES5551Texture() {}
-
-	static inline Graphics::PixelFormat pixelFormat() {
-		return Graphics::PixelFormat(2, 5, 5, 5, 1, 11, 6, 1, 0);
-	}
-};
-
-// RGB565 texture
-class GLES565Texture : public GLESTexture {
-public:
-	GLES565Texture() : GLESTexture(GL_RGB, GL_UNSIGNED_SHORT_5_6_5, pixelFormat()) {}
-	virtual ~GLES565Texture() {}
-
-	static inline Graphics::PixelFormat pixelFormat() {
-		return Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0);
-	}
-};
-
-class GLES888Texture : public GLESTexture {
-public:
-	GLES888Texture() : GLESTexture(GL_RGB, GL_UNSIGNED_BYTE, pixelFormat()) {}
-	virtual ~GLES888Texture() {}
-
-	static Graphics::PixelFormat pixelFormat() {
-		return OpenGL::Texture::getRGBPixelFormat();
-	}
-};
-
-class GLES8888Texture : public GLESTexture {
-public:
-	GLES8888Texture() : GLESTexture(GL_RGBA, GL_UNSIGNED_BYTE, pixelFormat()) {}
-	virtual ~GLES8888Texture() {}
-
-	static Graphics::PixelFormat pixelFormat() {
-		return OpenGL::Texture::getRGBAPixelFormat();
-	}
-};
-
-class GLESFakePaletteTexture : public GLESBaseTexture {
-protected:
-	GLESFakePaletteTexture(GLenum glFormat, GLenum glType,
-	                       Graphics::PixelFormat pixelFormat);
-
-public:
-	virtual ~GLESFakePaletteTexture();
-
-	void allocBuffer(GLuint w, GLuint h) override;
-	void updateBuffer(GLuint x, GLuint y, GLuint width, GLuint height,
-	                          const void *buf, int pitch_buf) override;
-	void fillBuffer(uint32 color) override;
-
-	const Graphics::PixelFormat &getPixelFormat() const override {
-		return _fake_format;
-	}
-
-protected:
-	Graphics::PixelFormat _fake_format;
-	byte *_pixels;
-};
-
-class GLESFakePalette16Texture : public GLESFakePaletteTexture {
-protected:
-	GLESFakePalette16Texture(GLenum glFormat, GLenum glType,
-	                       Graphics::PixelFormat pixelFormat);
-public:
-	virtual ~GLESFakePalette16Texture();
-
-	void allocBuffer(GLuint w, GLuint h) override;
-
-	void setPalette(const byte *colors, uint start, uint num) override;
-	void grabPalette(byte *colors, uint start, uint num) const override;
-
-protected:
-	void *prepareTextureBuffer(const Common::Rect &rect) override;
-
-	uint16 *_palette;
-	uint16 *_buf;
-};
-
-class GLESFakePalette565Texture : public GLESFakePalette16Texture {
-public:
-	GLESFakePalette565Texture();
-	virtual ~GLESFakePalette565Texture() {}
-
-	void setKeycolor(byte color) override {};
-};
-
-class GLESFakePalette5551Texture : public GLESFakePalette16Texture {
-public:
-	GLESFakePalette5551Texture();
-	virtual ~GLESFakePalette5551Texture() {}
-
-	void setKeycolor(byte color) override;
-
-protected:
-	byte _keycolor;
-};
-
-class GLESFakePalette888Texture : public GLESFakePaletteTexture {
-public:
-	GLESFakePalette888Texture();
-	virtual ~GLESFakePalette888Texture();
-
-	void allocBuffer(GLuint w, GLuint h) override;
-
-	void setPalette(const byte *colors, uint start, uint num) override;
-	void setKeycolor(byte color) override {};
-	void grabPalette(byte *colors, uint start, uint num) const override;
-
-protected:
-	void *prepareTextureBuffer(const Common::Rect &rect) override;
-
-	byte *_palette;
-	byte *_buf;
-};
-
-class GLESFakePalette8888Texture : public GLESFakePaletteTexture {
-public:
-	GLESFakePalette8888Texture();
-	virtual ~GLESFakePalette8888Texture();
-
-	void allocBuffer(GLuint w, GLuint h) override;
-
-	void setPalette(const byte *colors, uint start, uint num) override;
-	void setKeycolor(byte color) override;
-	void grabPalette(byte *colors, uint start, uint num) const override;
-
-protected:
-	void *prepareTextureBuffer(const Common::Rect &rect) override;
-
-	uint32 *_palette;
-	uint32 *_buf;
-	byte _keycolor;
-};
-
-#endif
diff --git a/backends/module.mk b/backends/module.mk
index e624395c3f9..b38c79dfba2 100644
--- a/backends/module.mk
+++ b/backends/module.mk
@@ -327,11 +327,6 @@ MODULE_OBJS += \
 	fs/android/android-posix-fs.o \
 	fs/android/android-saf-fs.o \
 	graphics/android/android-graphics.o \
-	graphics3d/android/android-graphics3d.o \
-	graphics3d/android/texture.o \
-	graphics3d/opengl/framebuffer.o \
-	graphics3d/opengl/surfacerenderer.o \
-	graphics3d/opengl/tiledsurface.o \
 	mutex/pthread/pthread-mutex.o
 endif
 
diff --git a/backends/platform/android/android.cpp b/backends/platform/android/android.cpp
index c85deaab040..40d02070cb1 100644
--- a/backends/platform/android/android.cpp
+++ b/backends/platform/android/android.cpp
@@ -587,7 +587,7 @@ void OSystem_Android::initBackend() {
 void OSystem_Android::engineInit() {
 	_engineRunning = true;
 	updateOnScreenControls();
-	dynamic_cast<AndroidCommonGraphics *>(_graphicsManager)->applyTouchSettings();
+	dynamic_cast<AndroidGraphicsManager *>(_graphicsManager)->applyTouchSettings();
 
 	JNI::setCurrentGame(ConfMan.getActiveDomainName());
 }
diff --git a/backends/platform/android/events.cpp b/backends/platform/android/events.cpp
index 65b0e96f970..091157a1b1a 100644
--- a/backends/platform/android/events.cpp
+++ b/backends/platform/android/events.cpp
@@ -627,7 +627,7 @@ void OSystem_Android::pushEvent(int type, int arg1, int arg2, int arg3,
 				break;
 
 			ev0.type = Common::EVENT_MOUSEMOVE;
-			ev0.mouse = dynamic_cast<AndroidCommonGraphics *>(_graphicsManager)->getMousePosition();
+			ev0.mouse = dynamic_cast<AndroidGraphicsManager *>(_graphicsManager)->getMousePosition();
 			{
 				int16 *c;
 				int s;
@@ -669,7 +669,7 @@ void OSystem_Android::pushEvent(int type, int arg1, int arg2, int arg3,
 				return;
 			}
 
-			ev0.mouse = dynamic_cast<AndroidCommonGraphics *>(_graphicsManager)->getMousePosition();
+			ev0.mouse = dynamic_cast<AndroidGraphicsManager *>(_graphicsManager)->getMousePosition();
 			pushEvent(ev0);
 			break;
 		}
@@ -719,7 +719,7 @@ void OSystem_Android::pushEvent(int type, int arg1, int arg2, int arg3,
 
 	case JE_DOWN:
 //		LOGD("JE_DOWN");
-		_touch_pt_down = dynamic_cast<AndroidCommonGraphics *>(_graphicsManager)->getMousePosition();
+		_touch_pt_down = dynamic_cast<AndroidGraphicsManager *>(_graphicsManager)->getMousePosition();
 		// If the cursor was outside the area (because the screen rotated) clip it
 		// to not scroll several times to make the cursor appear in the area
 		// Do not clamp the cursor position while rotating the screen because if the user rotated by mistake
@@ -773,7 +773,7 @@ void OSystem_Android::pushEvent(int type, int arg1, int arg2, int arg3,
 		ev0.type = Common::EVENT_MOUSEMOVE;
 
 		if (_touch_mode == TOUCH_MODE_TOUCHPAD) {
-			ev0.mouse = dynamic_cast<AndroidCommonGraphics *>(_graphicsManager)->getMousePosition();
+			ev0.mouse = dynamic_cast<AndroidGraphicsManager *>(_graphicsManager)->getMousePosition();
 		} else {
 			ev0.mouse.x = arg1;
 			ev0.mouse.y = arg2;
@@ -859,7 +859,7 @@ void OSystem_Android::pushEvent(int type, int arg1, int arg2, int arg3,
 //		LOGD("JE_DOUBLE_TAP - x: %d y: %d, arg3: %d", arg1, arg2, arg3);
 
 		ev0.type = Common::EVENT_MOUSEMOVE;
-		ev0.mouse = dynamic_cast<AndroidCommonGraphics *>(_graphicsManager)->getMousePosition();
+		ev0.mouse = dynamic_cast<AndroidGraphicsManager *>(_graphicsManager)->getMousePosition();
 
 //		LOGD("JE_DOUBLE_TAP 2 - x: %d y: %d, type: %d, arg3: %d", ev0.mouse.x , ev0.mouse.y, ev0.type, arg3);
 
@@ -934,7 +934,7 @@ void OSystem_Android::pushEvent(int type, int arg1, int arg2, int arg3,
 		ev0.type = Common::EVENT_MOUSEMOVE;
 
 		if (_touch_mode == TOUCH_MODE_TOUCHPAD) {
-			ev0.mouse = dynamic_cast<AndroidCommonGraphics *>(_graphicsManager)->getMousePosition();
+			ev0.mouse = dynamic_cast<AndroidGraphicsManager *>(_graphicsManager)->getMousePosition();
 		} else {
 			ev0.mouse.x = arg3;
 			ev0.mouse.y = arg4;
@@ -1092,7 +1092,7 @@ void OSystem_Android::pushEvent(int type, int arg1, int arg2, int arg3,
 		break;
 
 	case JE_BALL:
-		ev0.mouse = dynamic_cast<AndroidCommonGraphics *>(_graphicsManager)->getMousePosition();
+		ev0.mouse = dynamic_cast<AndroidGraphicsManager *>(_graphicsManager)->getMousePosition();
 
 		switch (arg1) {
 		case AMOTION_EVENT_ACTION_DOWN:
@@ -1214,7 +1214,7 @@ void OSystem_Android::pushEvent(int type, int arg1, int arg2, int arg3,
 			ev0.mouse.x = arg1;
 			ev0.mouse.y = arg2;
 		}
-//		ev0.mouse = dynamic_cast<AndroidCommonGraphics *>(_graphicsManager)->getMousePosition();
+//		ev0.mouse = dynamic_cast<AndroidGraphicsManager *>(_graphicsManager)->getMousePosition();
 		pushEvent(ev0);
 		break;
 
@@ -1236,7 +1236,7 @@ void OSystem_Android::pushEvent(int type, int arg1, int arg2, int arg3,
 			ev0.mouse.x = arg1;
 			ev0.mouse.y = arg2;
 		}
-//		ev0.mouse = dynamic_cast<AndroidCommonGraphics *>(_graphicsManager)->getMousePosition();
+//		ev0.mouse = dynamic_cast<AndroidGraphicsManager *>(_graphicsManager)->getMousePosition();
 		pushEvent(ev0);
 		break;
 
@@ -1463,7 +1463,7 @@ bool OSystem_Android::pollEvent(Common::Event &event) {
 			// Keep a dangling surface until we get a resize
 			if (JNI::egl_surface_width > 0 && JNI::egl_surface_height > 0) {
 				// surface changed
-				dynamic_cast<AndroidCommonGraphics *>(_graphicsManager)->resizeSurface();
+				dynamic_cast<AndroidGraphicsManager *>(_graphicsManager)->resizeSurface();
 
 				event.type = Common::EVENT_SCREEN_CHANGED;
 
@@ -1473,7 +1473,7 @@ bool OSystem_Android::pollEvent(Common::Event &event) {
 
 		if (_virtkeybd_on != JNI::virt_keyboard_state) {
 			_virtkeybd_on = JNI::virt_keyboard_state;
-			dynamic_cast<AndroidCommonGraphics *>(_graphicsManager)->syncVirtkeyboardState(_virtkeybd_on);
+			dynamic_cast<AndroidGraphicsManager *>(_graphicsManager)->syncVirtkeyboardState(_virtkeybd_on);
 		}
 
 		if (JNI::pause) {
@@ -1540,7 +1540,7 @@ bool OSystem_Android::pollEvent(Common::Event &event) {
 
 	if (Common::isMouseEvent(event)) {
 		if (_graphicsManager)
-			return dynamic_cast<AndroidCommonGraphics *>(_graphicsManager)->notifyMousePosition(event.mouse);
+			return dynamic_cast<AndroidGraphicsManager *>(_graphicsManager)->notifyMousePosition(event.mouse);
 	}
 
 	return true;
@@ -1584,7 +1584,7 @@ void OSystem_Android::setupTouchMode(int oldValue, int newValue) {
 	if (newValue == TOUCH_MODE_TOUCHPAD) {
 		// Make sure we have a proper touch point if we switch to touchpad mode with finger down
 		if (_graphicsManager) {
-			_touch_pt_down = dynamic_cast<AndroidCommonGraphics *>(_graphicsManager)->getMousePosition();
+			_touch_pt_down = dynamic_cast<AndroidGraphicsManager *>(_graphicsManager)->getMousePosition();
 		} else {
 			_touch_pt_down.x = 0;
 			_touch_pt_down.y = 0;


Commit: fc1ca914469c7cf45af69d3cdb1edec82cc51b1e
    https://github.com/scummvm/scummvm/commit/fc1ca914469c7cf45af69d3cdb1edec82cc51b1e
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2025-06-01T08:24:34+02:00

Commit Message:
IOS7: Don't use the old 3D graphics manager

It's useless now

Changed paths:
    backends/platform/ios7/ios7_osys_main.cpp
    backends/platform/ios7/ios7_osys_main.h


diff --git a/backends/platform/ios7/ios7_osys_main.cpp b/backends/platform/ios7/ios7_osys_main.cpp
index 697ea25d345..b0f279f7640 100644
--- a/backends/platform/ios7/ios7_osys_main.cpp
+++ b/backends/platform/ios7/ios7_osys_main.cpp
@@ -48,7 +48,6 @@
 #include "gui/gui-manager.h"
 
 #include "backends/graphics/ios/ios-graphics.h"
-#include "backends/graphics3d/ios/ios-graphics3d.h"
 #include "backends/saves/default/default-saves.h"
 #include "backends/timer/default/default-timer.h"
 #include "backends/mutex/pthread/pthread-mutex.h"
@@ -154,8 +153,6 @@ bool OSystem_iOS7::hasFeature(Feature f) {
 	case kFeatureOpenUrl:
 	case kFeatureNoQuit:
 	case kFeatureKbdMouseSpeed:
-	case kFeatureOpenGLForGame:
-	case kFeatureShadersForGame:
 	case kFeatureTouchscreen:
 #ifdef SCUMMVM_NEON
 	case kFeatureCpuNEON:
@@ -189,65 +186,6 @@ bool OSystem_iOS7::getFeatureState(Feature f) {
 	}
 }
 
-bool OSystem_iOS7::setGraphicsMode(int mode, uint flags) {
-	bool render3d = flags & OSystem::kGfxModeRender3d;
-
-	// Utilize the same way to switch between 2D and 3D graphics manager as
-	// in SDL based backends and Android.
-	iOSCommonGraphics *commonGraphics = dynamic_cast<iOSCommonGraphics *>(_graphicsManager);
-	iOSCommonGraphics::State gfxManagerState = commonGraphics->getState();
-
-	bool supports3D = _graphicsManager->hasFeature(kFeatureOpenGLForGame);
-	bool switchedManager = false;
-
-	// If the new mode and the current mode are not from the same graphics
-	// manager, delete and create the new mode graphics manager
-	if (render3d && !supports3D) {
-		delete _graphicsManager;
-		iOSGraphics3dManager *manager = new iOSGraphics3dManager();
-		_graphicsManager = manager;
-		commonGraphics = manager;
-		switchedManager = true;
-	} else if (!render3d && supports3D) {
-		delete _graphicsManager;
-		iOSGraphicsManager *manager = new iOSGraphicsManager();
-		_graphicsManager = manager;
-		commonGraphics = manager;
-		switchedManager = true;
-	}
-
-	if (switchedManager) {
-		// Setup the graphics mode and size first
-		// This is needed so that we can check the supported pixel formats when
-		// restoring the state.
-		_graphicsManager->beginGFXTransaction();
-		if (!_graphicsManager->setGraphicsMode(mode, flags))
-			return false;
-		_graphicsManager->initSize(gfxManagerState.screenWidth, gfxManagerState.screenHeight);
-		_graphicsManager->endGFXTransaction();
-
-		// This failing will probably have bad consequences...
-		//if (!androidGraphicsManager->setState(gfxManagerState)) {
-		//	return false;
-		//}
-
-		// Next setup the cursor again
-		CursorMan.pushCursor(0, 0, 0, 0, 0, 0);
-		CursorMan.popCursor();
-
-		// Next setup cursor palette if needed
-		if (_graphicsManager->getFeatureState(kFeatureCursorPalette)) {
-			CursorMan.pushCursorPalette(0, 0, 0);
-			CursorMan.popCursorPalette();
-		}
-
-		_graphicsManager->beginGFXTransaction();
-		return true;
-	} else {
-		return _graphicsManager->setGraphicsMode(mode, flags);
-	}
- }
-
 void OSystem_iOS7::suspendLoop() {
 	bool done = false;
 
diff --git a/backends/platform/ios7/ios7_osys_main.h b/backends/platform/ios7/ios7_osys_main.h
index 2695119744f..9c237732178 100644
--- a/backends/platform/ios7/ios7_osys_main.h
+++ b/backends/platform/ios7/ios7_osys_main.h
@@ -96,8 +96,6 @@ public:
 	void setFeatureState(Feature f, bool enable) override;
 	bool getFeatureState(Feature f) override;
 
-	bool setGraphicsMode(int mode, uint flags) override;
-
 	TouchMode getCurrentTouchMode() const { return _currentTouchMode; };
 	void setCurrentTouchMode(TouchMode mode) { _currentTouchMode = mode; };
 


Commit: 3a3b109ed48ace93215bc4a7b5127263dcd7423b
    https://github.com/scummvm/scummvm/commit/3a3b109ed48ace93215bc4a7b5127263dcd7423b
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2025-06-01T08:24:34+02:00

Commit Message:
IOS7: Cleanup the obsolete 3D graphics manager

Changed paths:
  R backends/graphics3d/ios/ios-graphics3d.cpp
  R backends/graphics3d/ios/ios-graphics3d.h
    backends/graphics/ios/ios-graphics.cpp
    backends/graphics/ios/ios-graphics.h
    backends/module.mk
    backends/platform/ios7/ios7_osys_events.cpp


diff --git a/backends/graphics/ios/ios-graphics.cpp b/backends/graphics/ios/ios-graphics.cpp
index 00927cb12a8..145f87f737d 100644
--- a/backends/graphics/ios/ios-graphics.cpp
+++ b/backends/graphics/ios/ios-graphics.cpp
@@ -60,34 +60,6 @@ void iOSGraphicsManager::notifyResize(const int width, const int height) {
 	handleResize(width, height);
 }
 
-iOSCommonGraphics::State iOSGraphicsManager::getState() const {
-	State state;
-
-	state.screenWidth   = getWidth();
-	state.screenHeight  = getHeight();
-	state.aspectRatio   = getFeatureState(OSystem::kFeatureAspectRatioCorrection);
-	state.cursorPalette = getFeatureState(OSystem::kFeatureCursorPalette);
-#ifdef USE_RGB_COLOR
-	state.pixelFormat   = getScreenFormat();
-#endif
-	return state;
-}
-
-bool iOSGraphicsManager::setState(const iOSCommonGraphics::State &state) {
-	beginGFXTransaction();
-
-#ifdef USE_RGB_COLOR
-	initSize(state.screenWidth, state.screenHeight, &state.pixelFormat);
-#else
-	initSize(state.screenWidth, state.screenHeight, nullptr);
-#endif
-	setFeatureState(OSystem::kFeatureAspectRatioCorrection, state.aspectRatio);
-	setFeatureState(OSystem::kFeatureCursorPalette, state.cursorPalette);
-
-	return endGFXTransaction() == OSystem::kTransactionSuccess;
-}
-
-
 bool iOSGraphicsManager::loadVideoMode(uint requestedWidth, uint requestedHeight, const Graphics::PixelFormat &format, bool resizable, int antialiasing) {
 	// As GLES2 provides FBO, OpenGL graphics manager must ask us for a resizable surface
 	assert(resizable);
diff --git a/backends/graphics/ios/ios-graphics.h b/backends/graphics/ios/ios-graphics.h
index 4b2a130319b..5d89c80504e 100644
--- a/backends/graphics/ios/ios-graphics.h
+++ b/backends/graphics/ios/ios-graphics.h
@@ -27,66 +27,19 @@
 
 #include "backends/graphics/opengl/opengl-graphics.h"
 
-class iOSCommonGraphics {
-public:
-	virtual ~iOSCommonGraphics() {}
-
-	virtual void initSurface() = 0;
-	virtual void deinitSurface() = 0;
-
-	/**
-	 * Notify the graphics manager about a resize event. This happens on
-	 * iDevices when switching to portrait mode or landscape mode.
-	 */
-	virtual void notifyResize(const int width, const int height) = 0;
-
-	virtual Common::Point getMousePosition() = 0;
-	virtual bool notifyMousePosition(Common::Point &mouse) = 0;
-
-	/**
-	 * A (subset) of the graphic manager's state. This is used when switching
-	 * between 2D and 3D graphic managers at runtime.
-	 */
-	struct State {
-		int screenWidth, screenHeight;
-		bool aspectRatio;
-		bool cursorPalette;
-
-#ifdef USE_RGB_COLOR
-		Graphics::PixelFormat pixelFormat;
-#endif
-	};
-
-	/**
-	 * Gets the current state of the graphics manager.
-	 */
-	virtual State getState() const = 0;
-
-	/**
-	 * Sets up a basic state of the graphics manager.
-	 */
-	virtual bool setState(const State &state) = 0;
-
-protected:
-	int _old_touch_mode;
-};
-
 class iOSGraphicsManager :
-  public OpenGL::OpenGLGraphicsManager, public iOSCommonGraphics {
+  public OpenGL::OpenGLGraphicsManager {
 public:
 	iOSGraphicsManager();
 	virtual ~iOSGraphicsManager();
 
-	void initSurface() override;
-	void deinitSurface() override;
-
-	void notifyResize(const int width, const int height) override;
+	void initSurface();
+	void deinitSurface();
 
-	virtual iOSCommonGraphics::State getState() const override;
-	virtual bool setState(const iOSCommonGraphics::State &state) override;
+	void notifyResize(const int width, const int height);
 
-	bool notifyMousePosition(Common::Point &mouse) override;
-	Common::Point getMousePosition() override { return Common::Point(_cursorX, _cursorY); }
+	bool notifyMousePosition(Common::Point &mouse);
+	Common::Point getMousePosition() { return Common::Point(_cursorX, _cursorY); }
 
 	float getHiDPIScreenFactor() const override;
 
@@ -98,6 +51,8 @@ protected:
 	void hideOverlay() override;
 
 	void refreshScreen() override;
+
+	int _old_touch_mode;
 };
 
 #endif
diff --git a/backends/graphics3d/ios/ios-graphics3d.cpp b/backends/graphics3d/ios/ios-graphics3d.cpp
deleted file mode 100644
index d61d958edf6..00000000000
--- a/backends/graphics3d/ios/ios-graphics3d.cpp
+++ /dev/null
@@ -1,527 +0,0 @@
-/* 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 3 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, see <http://www.gnu.org/licenses/>.
- *
- */
-
-#define FORBIDDEN_SYMBOL_ALLOW_ALL
-
-#include "common/scummsys.h"
-
-#if defined(USE_OPENGL_GAME) || defined(USE_OPENGL_SHADERS)
-
-#include "backends/graphics3d/ios/ios-graphics3d.h"
-#include "backends/platform/ios7/ios7_osys_main.h"
-#include "graphics/opengl/context.h"
-#include "graphics/opengl/texture.h"
-#include "graphics/blit.h"
-#include "common/translation.h"
-
-#include "engines/engine.h"
-
-iOSGraphics3dManager::iOSGraphics3dManager() :
-	_screenChangeCount(0),
-	_stretchMode(STRETCH_FIT),
-	_mouseDontScale(false),
-	_aspectRatioCorrection(true),
-	_overlayScreen(nullptr),
-	_overlayBackground(nullptr),
-	_mouseSurface(nullptr),
-	_surfaceRenderer(nullptr),
-	_frameBuffer(nullptr),
-	_glFBO(0) {
-
-	ConfMan.registerDefault("aspect_ratio", true);
-
-	memset(_glRBOs, 0, sizeof(_glRBOs));
-
-	initSurface();
-}
-
-iOSGraphics3dManager::~iOSGraphics3dManager() {
-	delete _overlayScreen;
-	delete _overlayBackground;
-	delete _mouseSurface;
-	delete _surfaceRenderer;
-	delete _frameBuffer;
-}
-
-void iOSGraphics3dManager::initSurface() {
-	OSystem_iOS7 *sys = dynamic_cast<OSystem_iOS7 *>(g_system);
-
-	// Create OpenGL context if not existing
-	GLuint glRBO = sys->createOpenGLContext();
-
-	OpenGLContext.initialize(OpenGL::kContextGLES2);
-
-	// Create the framebuffer attached to ObjC provided RBO
-	glGenFramebuffers(1, &_glFBO);
-	glBindFramebuffer(GL_FRAMEBUFFER, _glFBO);
-	glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, glRBO);
-
-	// Attach a depth and stencil buffer
-	createDepthAndStencilBuffer(sys->getScreenWidth(), sys->getScreenHeight());
-
-	GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
-	if (status != GL_FRAMEBUFFER_COMPLETE)
-		error("Framebuffer is not complete! status: %d", status);
-	glBindFramebuffer(GL_FRAMEBUFFER, 0);
-
-	_old_touch_mode = kTouchModeTouchpad;
-
-	//initSize will be called to set the size
-}
-
-void iOSGraphics3dManager::deinitSurface() {
-	glDeleteFramebuffers(1, &_glFBO);
-	glDeleteRenderbuffers(2, _glRBOs);
-
-	OpenGLContext.destroy();
-	dynamic_cast<OSystem_iOS7 *>(g_system)->destroyOpenGLContext();
-}
-
-void iOSGraphics3dManager::createDepthAndStencilBuffer(int width, int height) {
-	glGenRenderbuffers(2, _glRBOs);
-	glBindRenderbuffer(GL_RENDERBUFFER, _glRBOs[0]);
-
-	if (OpenGLContext.packedDepthStencilSupported) {
-		glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, width, height);
-		glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, _glRBOs[0]);
-		glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, _glRBOs[0]);
-	} else {
-		glRenderbufferStorage(GL_RENDERBUFFER, OpenGLContext.OESDepth24 ? GL_DEPTH_COMPONENT24 : GL_DEPTH_COMPONENT16,
-				width, height);
-		glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, _glRBOs[0]);
-
-		glBindRenderbuffer(GL_RENDERBUFFER, _glRBOs[1]);
-		glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8,
-				width, height);
-		glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, _glRBOs[1]);
-	}
-	glBindRenderbuffer(GL_RENDERBUFFER, 0);
-}
-
-void iOSGraphics3dManager::updateDepthAndStencilBuffer(int width, int height) {
-	glBindRenderbuffer(GL_RENDERBUFFER, _glRBOs[0]);
-	if (OpenGLContext.packedDepthStencilSupported) {
-	  glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, width, height);
-	} else {
-	  glRenderbufferStorage(GL_RENDERBUFFER, OpenGLContext.OESDepth24 ? GL_DEPTH_COMPONENT24 : GL_DEPTH_COMPONENT16,
-							width, height);
-	  glBindRenderbuffer(GL_RENDERBUFFER, _glRBOs[1]);
-	  glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8,
-							width, height);
-	}
-	glBindRenderbuffer(GL_RENDERBUFFER, 0);
-}
-
-void iOSGraphics3dManager::notifyResize(const int width, const int height) {
-	updateDepthAndStencilBuffer(width, height);
-	handleResize(width, height);
-}
-
-iOSCommonGraphics::State iOSGraphics3dManager::getState() const {
-	State state;
-
-	state.screenWidth   = getWidth();
-	state.screenHeight  = getHeight();
-	state.aspectRatio   = getFeatureState(OSystem::kFeatureAspectRatioCorrection);
-	state.cursorPalette = getFeatureState(OSystem::kFeatureCursorPalette);
-#ifdef USE_RGB_COLOR
-	state.pixelFormat   = getScreenFormat();
-#endif
-	return state;
-}
-
-bool iOSGraphics3dManager::setState(const iOSCommonGraphics::State &state) {
-	initSize(state.screenWidth, state.screenHeight, nullptr);
-	setFeatureState(OSystem::kFeatureAspectRatioCorrection, state.aspectRatio);
-	setFeatureState(OSystem::kFeatureCursorPalette, state.cursorPalette);
-
-	return true;
-}
-
-bool iOSGraphics3dManager::gameNeedsAspectRatioCorrection() const {
-	if (_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.
-		return (width == 320 && height == 200) || (width == 640 && height == 400);
-	}
-	return false;
-}
-
-bool iOSGraphics3dManager::hasFeature(OSystem::Feature f) const {
-	if ((f == OSystem::kFeatureOpenGLForGame) ||
-		(f == OSystem::kFeatureAspectRatioCorrection) ||
-		(f == OSystem::kFeatureStretchMode) ||
-		(f == OSystem::kFeatureCursorAlpha) ||
-		(f == OSystem::kFeatureOverlaySupportsAlpha && _overlayFormat.aBits() > 3)) {
-		return true;
-	}
-	return false;
-}
-
-bool iOSGraphics3dManager::getFeatureState(OSystem::Feature f) const {
-	switch (f) {
-	case OSystem::kFeatureAspectRatioCorrection:
-		return _aspectRatioCorrection;
-	default:
-		return false;
-	}
-}
-
-void iOSGraphics3dManager::setFeatureState(OSystem::Feature f, bool enable) {
-	switch (f) {
-	case OSystem::kFeatureAspectRatioCorrection:
-		_aspectRatioCorrection = enable;
-		break;
-	default:
-		break;
-	}
-}
-
-const OSystem::GraphicsMode *iOSGraphics3dManager::getSupportedGraphicsModes() const {
-	static const OSystem::GraphicsMode s_supportedGraphicsModes[] = {
-		{ "default", "Default", 0 },
-		{ 0, 0, 0 },
-	};
-
-	return s_supportedGraphicsModes;
-}
-
-int iOSGraphics3dManager::getDefaultGraphicsMode() const {
-	return 0;
-}
-
-bool iOSGraphics3dManager::setGraphicsMode(int mode, uint flags) {
-	assert(flags & OSystem::kGfxModeRender3d);
-	return true;
-}
-
-int iOSGraphics3dManager::getGraphicsMode() const {
-	return 0;
-}
-
-void iOSGraphics3dManager::initSize(uint w, uint h, const Graphics::PixelFormat *format) {
-	OSystem_iOS7 *sys = dynamic_cast<OSystem_iOS7 *>(g_system);
-
-	bool engineSupportsArbitraryResolutions = !g_engine ||
-			g_engine->hasFeature(Engine::kSupportsArbitraryResolutions);
-	if (!engineSupportsArbitraryResolutions) {
-		if (_frameBuffer) {
-			delete _frameBuffer;
-		}
-		// If the game can't adapt to any resolution, render it to a framebuffer
-		// so it can be scaled to fill the available space.
-		_frameBuffer = new OpenGL::FrameBuffer(w, h);
-		_frameBuffer->attach();
-	}
-
-	_surfaceRenderer = OpenGL::createBestSurfaceRenderer();
-	_overlayFormat = OpenGL::Texture::getRGBAPixelFormat();
-
-	handleResize(sys->getScreenWidth(), sys->getScreenHeight());
-}
-
-int16 iOSGraphics3dManager::getHeight() const {
-	if (_frameBuffer)
-		return _frameBuffer->getHeight();
-	else
-		return _overlayScreen->getHeight();
-}
-
-int16 iOSGraphics3dManager::getWidth() const {
-	if (_frameBuffer)
-		return _frameBuffer->getWidth();
-	else
-		return _overlayScreen->getWidth();
-}
-
-float iOSGraphics3dManager::getHiDPIScreenFactor() const {
-	return dynamic_cast<OSystem_iOS7 *>(g_system)->getSystemHiDPIScreenFactor();
-}
-
-void iOSGraphics3dManager::setMouseCursor(const void *buf, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor, bool dontScale, const Graphics::PixelFormat *format, const byte *mask) {
-
-	if (w == 0 || h == 0)
-		return;
-
-	const Graphics::PixelFormat pixelFormat = format ? *format : Graphics::PixelFormat::createFormatCLUT8();
-
-	if (_mouseSurface == nullptr)
-		_mouseSurface = new OpenGL::TiledSurface(w, h, pixelFormat);
-
-	_mouseHotspot = Common::Point(hotspotX, hotspotY);
-	_mouseDontScale = dontScale;
-
-	_mouseSurface->copyRectToSurface(buf, _mouseSurface->getBackingSurface()->pitch, hotspotX, hotspotY, w, h);
-
-	updateCursorScaling();
-}
-
-void iOSGraphics3dManager::handleResizeImpl(const int width, const int height) {
-	// Update the overlay
-	delete _overlayScreen;
-	_overlayScreen = new OpenGL::TiledSurface(width, height, _overlayFormat);
-
-	delete _mouseSurface;
-	_mouseSurface = nullptr;
-
-	// Clear the overlay background so it is not displayed distorted while resizing
-	delete _overlayBackground;
-	_overlayBackground = nullptr;
-
-	// Re-setup the scaling for the screen
-	recalculateDisplayAreas();
-
-	// Something changed, so update the screen change ID.
-	_screenChangeCount++;
-}
-
-void iOSGraphics3dManager::updateScreen() {
-	GLint prevStateViewport[4];
-	glGetIntegerv(GL_VIEWPORT, prevStateViewport);
-
-	// Make sure our framebuffer is still bound
-	glBindFramebuffer(GL_FRAMEBUFFER, _glFBO);
-
-	if (_frameBuffer) {
-		_surfaceRenderer->prepareState();
-		glViewport(_gameDrawRect.left, _windowHeight - _gameDrawRect.top - _gameDrawRect.height(), _gameDrawRect.width(), _gameDrawRect.height());
-		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
-		_surfaceRenderer->render(_frameBuffer, Math::Rect2d(Math::Vector2d(0, 0), Math::Vector2d(1, 1)));
-		_surfaceRenderer->restorePreviousState();
-	}
-
-	if (_overlayVisible) {
-		_overlayScreen->update();
-
-		// If the overlay is in game we expect the game to continue calling OpenGL
-		if (_overlayBackground && _overlayInGUI) {
-			_overlayBackground->update();
-		}
-
-		if (_cursorVisible && _mouseSurface) {
-			_mouseSurface->update();
-		}
-
-		_surfaceRenderer->prepareState();
-
-		glViewport(_overlayDrawRect.left, _windowHeight - _overlayDrawRect.top - _overlayDrawRect.height(), getOverlayWidth(), getOverlayHeight());
-		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
-
-		if (_overlayBackground) {
-			_overlayBackground->draw(_surfaceRenderer);
-		}
-
-		_surfaceRenderer->enableAlphaBlending(true);
-		_surfaceRenderer->setFlipY(true);
-
-		_overlayScreen->draw(_surfaceRenderer);
-
-		if (_cursorVisible && _mouseSurface) {
-			glViewport(_cursorX - _mouseHotspotScaled.x, _overlayScreen->getHeight() - _cursorY - _mouseHeightScaled - _mouseHotspotScaled.y, _mouseWidthScaled, _mouseHeightScaled);
-			_mouseSurface->draw(_surfaceRenderer);
-		}
-		_surfaceRenderer->restorePreviousState();
-	}
-
-	if (_frameBuffer) {
-		_frameBuffer->attach();
-	}
-
-	dynamic_cast<OSystem_iOS7 *>(g_system)->refreshScreen();
-	glViewport(prevStateViewport[0], prevStateViewport[1], prevStateViewport[2], prevStateViewport[3]);
-}
-
-const OSystem::GraphicsMode glStretchModes[] = {
-	{"center", _s("Center"), STRETCH_CENTER},
-	{"pixel-perfect", _s("Pixel-perfect scaling"), STRETCH_INTEGRAL},
-	{"even-pixels", _s("Even pixels scaling"), STRETCH_INTEGRAL_AR},
-	{"fit", _s("Fit to window"), STRETCH_FIT},
-	{"stretch", _s("Stretch to window"), STRETCH_STRETCH},
-	{"fit_force_aspect", _s("Fit to window (4:3)"), STRETCH_FIT_FORCE_ASPECT},
-	{nullptr, nullptr, 0}
-};
-
-const OSystem::GraphicsMode *iOSGraphics3dManager::getSupportedStretchModes() const {
-	return glStretchModes;
-}
-
-int iOSGraphics3dManager::getDefaultStretchMode() const {
-	return STRETCH_FIT;
-}
-
-bool iOSGraphics3dManager::setStretchMode(int mode) {
-	if (mode == _stretchMode)
-		return true;
-
-	// Check this is a valid mode
-	const OSystem::GraphicsMode *sm = getSupportedStretchModes();
-	bool found = false;
-	while (sm->name) {
-		if (sm->id == mode) {
-			found = true;
-			break;
-		}
-		sm++;
-	}
-	if (!found) {
-		warning("unknown stretch mode %d", mode);
-		return false;
-	}
-
-	_stretchMode = mode;
-	return true;
-}
-
-int iOSGraphics3dManager::getStretchMode() const {
-	return _stretchMode;
-}
-
-void iOSGraphics3dManager::clearOverlay() {
-	_overlayScreen->fill(0);
-}
-
-void iOSGraphics3dManager::grabOverlay(Graphics::Surface &surface) const {
-	const Graphics::Surface *overlayData = _overlayScreen->getBackingSurface();
-
-	assert(surface.w >= overlayData->w);
-	assert(surface.h >= overlayData->h);
-	assert(surface.format.bytesPerPixel == overlayData->format.bytesPerPixel);
-
-	const byte *src = (const byte *)overlayData->getPixels();
-	byte *dst = (byte *)surface.getPixels();
-	Graphics::copyBlit(dst, src, surface.pitch, overlayData->pitch, overlayData->w, overlayData->h, overlayData->format.bytesPerPixel);
-}
-
-void iOSGraphics3dManager::copyRectToOverlay(const void *buf, int pitch, int x, int y, int w, int h) {
-	_overlayScreen->copyRectToSurface(buf, pitch, x, y, w, h);
-}
-
-int16 iOSGraphics3dManager::getOverlayHeight() const {
-	return _overlayScreen->getHeight();
-}
-
-int16 iOSGraphics3dManager::getOverlayWidth() const {
-	return _overlayScreen->getWidth();
-}
-
-void iOSGraphics3dManager::showOverlay(bool inGUI) {
-	if (_overlayVisible && _overlayInGUI == inGUI) {
-		return;
-	}
-
-	// Don't change touch mode when not changing mouse coordinates
-	if (inGUI) {
-		_old_touch_mode = dynamic_cast<OSystem_iOS7 *>(g_system)->getCurrentTouchMode();
-		// in 3D, in overlay
-		dynamic_cast<OSystem_iOS7 *>(g_system)->applyTouchSettings(true, true);
-	} else if (_overlayInGUI) {
-		// Restore touch mode active before overlay was shown
-		dynamic_cast<OSystem_iOS7 *>(g_system)->setCurrentTouchMode(static_cast<TouchMode>(_old_touch_mode));
-	}
-
-	WindowedGraphicsManager::showOverlay(inGUI);
-
-	delete _overlayBackground;
-	_overlayBackground = nullptr;
-
-	if (g_engine) {
-		if (_frameBuffer)
-			_frameBuffer->detach();
-
-		// If there is a game running capture the screen, so that it can be shown "below" the overlay.
-		_overlayBackground = new OpenGL::TiledSurface(_overlayScreen->getWidth(), _overlayScreen->getHeight(), _overlayFormat);
-		Graphics::Surface *background = _overlayBackground->getBackingSurface();
-		glReadPixels(0, 0, background->w, background->h, GL_RGBA, GL_UNSIGNED_BYTE, background->getPixels());
-
-		if (_frameBuffer)
-			_frameBuffer->attach();
-	}
-}
-
-void iOSGraphics3dManager::hideOverlay() {
-	if (!_overlayVisible) {
-		return;
-	}
-
-	if (_overlayInGUI) {
-		// Restore touch mode active before overlay was shown
-		dynamic_cast<OSystem_iOS7 *>(g_system)->setCurrentTouchMode(static_cast<TouchMode>(_old_touch_mode));
-	}
-
-	WindowedGraphicsManager::hideOverlay();
-
-	delete _overlayBackground;
-	_overlayBackground = nullptr;
-
-	if (_surfaceRenderer) {
-		_surfaceRenderer->prepareState();
-		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
-		_surfaceRenderer->restorePreviousState();
-		updateScreen();
-		_surfaceRenderer->prepareState();
-		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
-		_surfaceRenderer->restorePreviousState();
-		updateScreen();
-	}
-}
-
-bool iOSGraphics3dManager::showMouse(bool visible) {
-	return WindowedGraphicsManager::showMouse(visible);
-}
-
-bool iOSGraphics3dManager::notifyMousePosition(Common::Point &mouse) {
-	mouse.x = CLIP<int16>(mouse.x, _activeArea.drawRect.left, _activeArea.drawRect.right);
-	mouse.y = CLIP<int16>(mouse.y, _activeArea.drawRect.top, _activeArea.drawRect.bottom);
-
-	setMousePosition(mouse.x, mouse.y);
-	mouse = convertWindowToVirtual(mouse.x, mouse.y);
-
-	return true;
-}
-
-void iOSGraphics3dManager::updateCursorScaling() {
-	// By default we use the unscaled versions.
-	_mouseHotspotScaled = _mouseHotspot;
-	_mouseWidthScaled = _mouseSurface->getWidth();
-	_mouseHeightScaled = _mouseSurface->getHeight();
-
-	// In case scaling is actually enabled we will scale the cursor according
-	// to the game screen.
-	uint16 w = getWidth();
-	uint16 h = getHeight();
-
-	if (!_mouseDontScale && w && h) {
-		const frac_t screen_scale_factor_x = intToFrac(_gameDrawRect.width()) / w;
-		const frac_t screen_scale_factor_y = intToFrac(_gameDrawRect.height()) / h;
-
-		_mouseHotspotScaled = Common::Point(
-			fracToInt(_mouseHotspotScaled.x * screen_scale_factor_x),
-			fracToInt(_mouseHotspotScaled.y * screen_scale_factor_y));
-
-		_mouseWidthScaled  = fracToInt(_mouseWidthScaled * screen_scale_factor_x);
-		_mouseHeightScaled = fracToInt(_mouseHeightScaled * screen_scale_factor_y);
-	}
-}
-
-#endif
diff --git a/backends/graphics3d/ios/ios-graphics3d.h b/backends/graphics3d/ios/ios-graphics3d.h
deleted file mode 100644
index e77a80b4283..00000000000
--- a/backends/graphics3d/ios/ios-graphics3d.h
+++ /dev/null
@@ -1,148 +0,0 @@
-/* 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 3 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, see <http://www.gnu.org/licenses/>.
- *
- */
-
-#ifndef BACKENDS_GRAPHICS3D_IOS_IOS_GRAPHICS3D_H
-#define BACKENDS_GRAPHICS3D_IOS_IOS_GRAPHICS3D_H
-
-#if defined(USE_OPENGL_GAME) || defined(USE_OPENGL_SHADERS)
-
-#include "common/scummsys.h"
-
-#include "backends/graphics/windowed.h"
-#include "backends/graphics/ios/ios-graphics.h"
-#include "backends/graphics3d/opengl/framebuffer.h"
-#include "backends/graphics3d/opengl/tiledsurface.h"
-#include "backends/graphics3d/opengl/surfacerenderer.h"
-
-class iOSGraphics3dManager : virtual public WindowedGraphicsManager, public iOSCommonGraphics {
-public:
-	iOSGraphics3dManager();
-	virtual ~iOSGraphics3dManager();
-
-	//WindowedGraphicsManager
-	bool gameNeedsAspectRatioCorrection() const override;
-	void handleResizeImpl(const int width, const int height) override;
-	virtual void setSystemMousePosition(const int x, const int y) override {};
-
-	//iOSCommonGraphics
-	void initSurface() override;
-	void deinitSurface() override;
-
-	void notifyResize(const int width, const int height) override;
-
-	virtual iOSCommonGraphics::State getState() const override;
-	virtual bool setState(const iOSCommonGraphics::State &state) override;
-
-	bool notifyMousePosition(Common::Point &mouse) override;
-	Common::Point getMousePosition() override { return Common::Point(_cursorX, _cursorY); }
-
-	// GraphicsManager API - Features
-	bool hasFeature(OSystem::Feature f) const override;
-	bool getFeatureState(OSystem::Feature f) const override;
-	void setFeatureState(OSystem::Feature f, bool enable) override;
-
-	const OSystem::GraphicsMode *getSupportedGraphicsModes() const override;
-	int getDefaultGraphicsMode() const override;
-	bool setGraphicsMode(int mode, uint flags = OSystem::kGfxModeNoFlags) override;
-	int getGraphicsMode() const override;
-
-	void beginGFXTransaction() override {}
-	OSystem::TransactionError endGFXTransaction() override {
-		return OSystem::kTransactionSuccess;
-	}
-
-	// GraphicsManager API - Graphics mode
-#ifdef USE_RGB_COLOR
-	Graphics::PixelFormat getScreenFormat() const override { return _overlayFormat; }
-	Common::List<Graphics::PixelFormat> getSupportedFormats() const override {
-		Common::List<Graphics::PixelFormat> supportedFormats;
-		return supportedFormats;
-	}
-#endif
-	int getScreenChangeID() const override { return _screenChangeCount; }
-	void initSize(uint w, uint h, const Graphics::PixelFormat *format) override;
-	int16 getHeight() const override;
-	int16 getWidth() const override;
-
-	float getHiDPIScreenFactor() const override;
-
-	// GraphicsManager API - Draw methods
-	void updateScreen() override;
-	// Following methods are not used by 3D graphics managers
-	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 nullptr; }
-	void unlockScreen() override {}
-	void fillScreen(uint32 col) override {}
-	void fillScreen(const Common::Rect &r, uint32 col) override {}
-	void setShakePos(int shakeXOffset, int shakeYOffset) override {};
-	void setFocusRectangle(const Common::Rect& rect) override {}
-	void clearFocusRectangle() override {}
-
-	// GraphicsManager API - Overlay
-	const OSystem::GraphicsMode *getSupportedStretchModes() const override;
-	int getDefaultStretchMode() const override;
-	bool setStretchMode(int mode) override;
-	int getStretchMode() const override;
-	void showOverlay(bool inGUI) override;
-	void hideOverlay() override;
-	Graphics::PixelFormat getOverlayFormat() const override { return _overlayFormat; }
-	void clearOverlay() override;
-	void grabOverlay(Graphics::Surface &surface) const override;
-	void copyRectToOverlay(const void *buf, int pitch, int x, int y, int w, int h) override;
-	int16 getOverlayWidth() const override;
-	int16 getOverlayHeight() const override;
-
-	// GraphicsManager API - Mouse
-	bool showMouse(bool visible) override;
-	void setMouseCursor(const void *buf, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor, bool dontScale = false, const Graphics::PixelFormat *format = NULL, const byte *mask = NULL) override;
-	void setCursorPalette(const byte *colors, uint start, uint num) override {}
-
-protected:
-	void updateCursorScaling();
-	void createDepthAndStencilBuffer(int width, int height);
-	void updateDepthAndStencilBuffer(int width, int height);
-
-	int _screenChangeCount;
-	int _stretchMode;
-	bool _aspectRatioCorrection;
-	bool _mouseDontScale;
-	Common::Point _mouseHotspot;
-	Common::Point _mouseHotspotScaled;
-	int _mouseWidthScaled, _mouseHeightScaled;
-
-	Graphics::PixelFormat _overlayFormat;
-	OpenGL::TiledSurface *_overlayScreen;
-	OpenGL::TiledSurface *_overlayBackground;
-	OpenGL::TiledSurface *_mouseSurface;
-	OpenGL::SurfaceRenderer *_surfaceRenderer;
-
-	// FBO used to render games not supporting arbitrary resolutions
-	OpenGL::FrameBuffer *_frameBuffer;
-	// FBO used as a backbuffer for Apple API
-	GLuint _glFBO;
-	// RBOs used for depth and stencil buffer only
-	GLuint _glRBOs[2];
-};
-
-#endif
-#endif
diff --git a/backends/module.mk b/backends/module.mk
index b38c79dfba2..aa048a59e06 100644
--- a/backends/module.mk
+++ b/backends/module.mk
@@ -411,11 +411,7 @@ ifdef IPHONE
 MODULE_OBJS += \
 	mutex/pthread/pthread-mutex.o \
 	graphics/ios/ios-graphics.o \
-	graphics/ios/renderbuffer.o \
-	graphics3d/ios/ios-graphics3d.o \
-	graphics3d/opengl/framebuffer.o \
-	graphics3d/opengl/surfacerenderer.o \
-	graphics3d/opengl/tiledsurface.o
+	graphics/ios/renderbuffer.o
 endif
 
 ifeq ($(BACKEND),maemo)
diff --git a/backends/platform/ios7/ios7_osys_events.cpp b/backends/platform/ios7/ios7_osys_events.cpp
index 3d455a511d6..6263d2014a6 100644
--- a/backends/platform/ios7/ios7_osys_events.cpp
+++ b/backends/platform/ios7/ios7_osys_events.cpp
@@ -142,7 +142,7 @@ bool OSystem_iOS7::pollEvent(Common::Event &event) {
 
 		case kInputScreenChanged:
 			rebuildSurface();
-			dynamic_cast<iOSCommonGraphics *>(_graphicsManager)->notifyResize(getScreenWidth(), getScreenHeight());
+			dynamic_cast<iOSGraphicsManager *>(_graphicsManager)->notifyResize(getScreenWidth(), getScreenHeight());
 			event.type = Common::EVENT_SCREEN_CHANGED;
 			break;
 
@@ -165,7 +165,7 @@ bool OSystem_iOS7::handleEvent_touchBegan(Common::Event &event, int x, int y) {
 
 	if (_currentTouchMode == kTouchModeDirect) {
 		Common::Point mouse(x, y);
-		dynamic_cast<iOSCommonGraphics *>(_graphicsManager)->notifyMousePosition(mouse);
+		dynamic_cast<iOSGraphicsManager *>(_graphicsManager)->notifyMousePosition(mouse);
 	}
 
 	return false;
@@ -182,7 +182,7 @@ bool OSystem_iOS7::handleEvent_touchMoved(Common::Event &event, int x, int y) {
 	} else {
 		// Update mouse position
 		Common::Point mousePos(x, y);
-		dynamic_cast<iOSCommonGraphics *>(_graphicsManager)->notifyMousePosition(mousePos);
+		dynamic_cast<iOSGraphicsManager *>(_graphicsManager)->notifyMousePosition(mousePos);
 		event.type = Common::EVENT_MOUSEMOVE;
 		handleEvent_mouseEvent(event, deltaX, deltaY);
 	}
@@ -210,20 +210,20 @@ void OSystem_iOS7::handleEvent_mouseRightButtonUp(Common::Event &event, int x, i
 }
 
 void OSystem_iOS7::handleEvent_mouseDelta(Common::Event &event, int deltaX, int deltaY) {
-	Common::Point mouseOldPos = dynamic_cast<iOSCommonGraphics *>(_graphicsManager)->getMousePosition();
+	Common::Point mouseOldPos = dynamic_cast<iOSGraphicsManager *>(_graphicsManager)->getMousePosition();
 
 	Common::Point newMousePos((int)(mouseOldPos.x - (int)((float)deltaX * getMouseSpeed())), (int)(mouseOldPos.y - (int)((float)deltaY * getMouseSpeed())));
 
 	// Update mouse position
-	dynamic_cast<iOSCommonGraphics *>(_graphicsManager)->notifyMousePosition(newMousePos);
+	dynamic_cast<iOSGraphicsManager *>(_graphicsManager)->notifyMousePosition(newMousePos);
 
 	event.type = Common::EVENT_MOUSEMOVE;
 	handleEvent_mouseEvent(event, deltaX, deltaY);
 }
 
 void OSystem_iOS7::handleEvent_mouseEvent(Common::Event &event, int relX, int relY) {
-	Common::Point mouse = dynamic_cast<iOSCommonGraphics *>(_graphicsManager)->getMousePosition();
-	dynamic_cast<iOSCommonGraphics *>(_graphicsManager)->notifyMousePosition(mouse);
+	Common::Point mouse = dynamic_cast<iOSGraphicsManager *>(_graphicsManager)->getMousePosition();
+	dynamic_cast<iOSGraphicsManager *>(_graphicsManager)->notifyMousePosition(mouse);
 
 	event.relMouse.x = relX;
 	event.relMouse.y = relY;


Commit: a2005c416a7f2223cd6ae36b440ff1004c123d9e
    https://github.com/scummvm/scummvm/commit/a2005c416a7f2223cd6ae36b440ff1004c123d9e
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2025-06-01T08:24:34+02:00

Commit Message:
BACKENDS: SDL: Cleanup the obsolete 3D graphics manager

Also remove the now unused common parts

Changed paths:
  R backends/graphics3d/opengl/framebuffer.cpp
  R backends/graphics3d/opengl/framebuffer.h
  R backends/graphics3d/opengl/surfacerenderer.cpp
  R backends/graphics3d/opengl/surfacerenderer.h
  R backends/graphics3d/opengl/tiledsurface.cpp
  R backends/graphics3d/opengl/tiledsurface.h
  R backends/graphics3d/openglsdl/openglsdl-graphics3d.cpp
  R backends/graphics3d/openglsdl/openglsdl-graphics3d.h
    backends/module.mk
    backends/platform/sdl/sdl.cpp


diff --git a/backends/graphics3d/opengl/framebuffer.cpp b/backends/graphics3d/opengl/framebuffer.cpp
deleted file mode 100644
index dccd6a14815..00000000000
--- a/backends/graphics3d/opengl/framebuffer.cpp
+++ /dev/null
@@ -1,180 +0,0 @@
-/* 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 3 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, see <http://www.gnu.org/licenses/>.
- *
- */
-
-#include "common/textconsole.h"
-#include "common/util.h"
-
-#if defined(USE_OPENGL_GAME) || defined(USE_OPENGL_SHADERS)
-
-#include "backends/graphics3d/opengl/framebuffer.h"
-
-#include "graphics/opengl/context.h"
-
-#if !defined(GL_DEPTH24_STENCIL8)
-#define GL_DEPTH24_STENCIL8 GL_DEPTH24_STENCIL8_OES
-#endif
-#if !defined(GL_DEPTH_COMPONENT24)
-#define GL_DEPTH_COMPONENT24 GL_DEPTH_COMPONENT24_OES
-#endif
-
-namespace OpenGL {
-
-static bool usePackedBuffer() {
-	return OpenGLContext.packedDepthStencilSupported;
-}
-
-static bool useDepthComponent24() {
-	return OpenGLContext.OESDepth24;
-}
-
-FrameBuffer::FrameBuffer(uint width, uint height) :
-		Texture(GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE) {
-	if (!OpenGLContext.framebufferObjectSupported) {
-		error("FrameBuffer Objects are not supported by the current OpenGL context");
-	}
-
-	setSize(width, height);
-	enableLinearFiltering(true);
-
-	init();
-}
-
-FrameBuffer::~FrameBuffer() {
-	glDeleteRenderbuffers(2, _renderBuffers);
-	glDeleteFramebuffers(1, &_frameBuffer);
-}
-
-void FrameBuffer::init() {
-	glGenFramebuffers(1, &_frameBuffer);
-	glGenRenderbuffers(2, _renderBuffers);
-
-	glBindFramebuffer(GL_FRAMEBUFFER, _frameBuffer);
-	glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, getGLTexture(), 0);
-
-#ifdef EMSCRIPTEN
-		// See https://www.khronos.org/registry/webgl/specs/latest/1.0/#FBO_ATTACHMENTS
-		// and https://github.com/emscripten-core/emscripten/issues/4832
-	glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_STENCIL, getWidth(), getHeight());
-	glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, _renderBuffers[0]);
-	glBindRenderbuffer(GL_RENDERBUFFER, 0);
-#else
-	if (usePackedBuffer()) {
-		glBindRenderbuffer(GL_RENDERBUFFER, _renderBuffers[0]);
-		glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, getWidth(), getHeight());
-		glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, _renderBuffers[0]);
-		glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, _renderBuffers[0]);
-		glBindRenderbuffer(GL_RENDERBUFFER, 0);
-	} else {
-		glBindRenderbuffer(GL_RENDERBUFFER, _renderBuffers[0]);
-
-		glRenderbufferStorage(GL_RENDERBUFFER, useDepthComponent24() ? GL_DEPTH_COMPONENT24 : GL_DEPTH_COMPONENT16, getWidth(), getHeight());
-		glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, _renderBuffers[0]);
-
-		glBindRenderbuffer(GL_RENDERBUFFER, _renderBuffers[1]);
-		glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, getWidth(), getHeight());
-		glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, _renderBuffers[1]);
-		glBindRenderbuffer(GL_RENDERBUFFER, 0);
-	}
-#endif
-
-	glBindFramebuffer(GL_FRAMEBUFFER, _frameBuffer);
-	GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
-	if (status != GL_FRAMEBUFFER_COMPLETE)
-		error("Framebuffer is not complete! status: %d", status);
-
-	glBindTexture(GL_TEXTURE_2D, 0);
-	glBindFramebuffer(GL_FRAMEBUFFER, 0);
-}
-
-void FrameBuffer::attach() {
-	glBindFramebuffer(GL_FRAMEBUFFER, _frameBuffer);
-	glViewport(0, 0, getLogicalWidth(), getLogicalHeight());
-}
-
-void FrameBuffer::detach() {
-	glBindFramebuffer(GL_FRAMEBUFFER, 0);
-}
-
-#if !USE_FORCED_GLES2 || defined(USE_GLAD)
-MultiSampleFrameBuffer::MultiSampleFrameBuffer(uint width, uint height, int samples)
-		: FrameBuffer(width,height) {
-	if (!OpenGLContext.framebufferObjectMultisampleSupported) {
-		error("The current OpenGL context does not support multisample framebuffer objects!");
-	}
-
-	if (samples > OpenGLContext.multisampleMaxSamples) {
-		warning("Requested anti-aliasing with '%d' samples, but the current OpenGL context supports '%d' samples at most",
-		        samples, OpenGLContext.multisampleMaxSamples);
-	}
-
-	_msSamples = MIN(samples, OpenGLContext.multisampleMaxSamples);
-
-	init();
-}
-
-MultiSampleFrameBuffer::~MultiSampleFrameBuffer() {
-	glDeleteRenderbuffers(1, &_msColorId);
-	glDeleteRenderbuffers(1, &_msDepthId);
-	glBindFramebuffer(GL_FRAMEBUFFER, 0);
-	glDeleteFramebuffers(1, &_msFrameBufferId);
-}
-
-void MultiSampleFrameBuffer::init() {
-	glGenFramebuffers(1, &_msFrameBufferId);
-	glBindFramebuffer(GL_FRAMEBUFFER, _msFrameBufferId);
-
-	glGenRenderbuffers(1, &_msColorId);
-	glBindRenderbuffer(GL_RENDERBUFFER, _msColorId);
-	glRenderbufferStorageMultisample(GL_RENDERBUFFER, _msSamples, GL_RGBA8, getWidth(), getHeight());
-
-	glGenRenderbuffers(1, &_msDepthId);
-	glBindRenderbuffer(GL_RENDERBUFFER, _msDepthId);
-	glRenderbufferStorageMultisample(GL_RENDERBUFFER, _msSamples, GL_DEPTH24_STENCIL8, getWidth(), getHeight());
-
-	glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, _msColorId);
-	glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, _msDepthId);
-	glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, _msDepthId);
-
-	GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
-	if (status != GL_FRAMEBUFFER_COMPLETE)
-		error("Framebuffer is not complete! status: %d", status);
-
-	glBindFramebuffer(GL_FRAMEBUFFER, 0);
-}
-
-void MultiSampleFrameBuffer::attach() {
-	glBindFramebuffer(GL_READ_FRAMEBUFFER, getFrameBufferName());
-	glBindFramebuffer(GL_DRAW_FRAMEBUFFER, _msFrameBufferId);
-	glViewport(0, 0, getLogicalWidth(), getLogicalHeight());
-}
-
-void MultiSampleFrameBuffer::detach() {
-	glBindFramebuffer(GL_READ_FRAMEBUFFER, _msFrameBufferId);
-	glBindFramebuffer(GL_DRAW_FRAMEBUFFER, getFrameBufferName());
-	glBlitFramebuffer(0, 0, getLogicalWidth(), getLogicalHeight(), 0, 0, getLogicalWidth(), getLogicalHeight(), GL_COLOR_BUFFER_BIT, GL_NEAREST);
-	glBindFramebuffer(GL_FRAMEBUFFER, 0);
-}
-
-#endif // !USE_FORCED_GLES2 || defined(USE_GLAD)
-
-} // End of namespace OpenGL
-
-#endif
diff --git a/backends/graphics3d/opengl/framebuffer.h b/backends/graphics3d/opengl/framebuffer.h
deleted file mode 100644
index c0973544223..00000000000
--- a/backends/graphics3d/opengl/framebuffer.h
+++ /dev/null
@@ -1,76 +0,0 @@
-/* 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 3 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, see <http://www.gnu.org/licenses/>.
- *
- */
-
-#ifndef BACKENDS_GRAPHICS3D_OPENGL_FRAMEBUFFER_H
-#define BACKENDS_GRAPHICS3D_OPENGL_FRAMEBUFFER_H
-
-#include "graphics/opengl/system_headers.h"
-
-#include "graphics/opengl/texture.h"
-
-#if defined(USE_OPENGL_GAME) || defined(USE_OPENGL_SHADERS)
-
-namespace OpenGL {
-
-class FrameBuffer : public Texture {
-public:
-	FrameBuffer(uint width, uint height);
-	virtual ~FrameBuffer();
-
-	virtual void attach();
-	virtual void detach();
-
-protected:
-	FrameBuffer(GLenum glIntFormat, GLenum glFormat, GLenum glType, bool autoCreate)
-		: Texture(glIntFormat, glFormat, glType, autoCreate) {}
-
-	GLuint getFrameBufferName() const { return _frameBuffer; }
-
-	void init();
-
-private:
-	GLuint _renderBuffers[2];
-	GLuint _frameBuffer;
-};
-
-#if !USE_FORCED_GLES2 || defined(USE_GLAD)
-class MultiSampleFrameBuffer : public FrameBuffer {
-public:
-	MultiSampleFrameBuffer(uint width, uint height, int samples);
-	virtual ~MultiSampleFrameBuffer();
-
-	virtual void attach();
-	virtual void detach();
-
-private:
-	void init();
-	GLuint _msFrameBufferId;
-	GLuint _msColorId;
-	GLuint _msDepthId;
-	GLuint _msSamples;
-};
-#endif
-
-} // End of namespace OpenGL
-
-#endif // defined(USE_OPENGL_GAME) || defined(USE_OPENGL_SHADERS)
-
-#endif
diff --git a/backends/graphics3d/opengl/surfacerenderer.cpp b/backends/graphics3d/opengl/surfacerenderer.cpp
deleted file mode 100644
index 6b189650cac..00000000000
--- a/backends/graphics3d/opengl/surfacerenderer.cpp
+++ /dev/null
@@ -1,290 +0,0 @@
-/* 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 3 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, see <http://www.gnu.org/licenses/>.
- *
- */
-
-#include "common/scummsys.h"
-
-#if defined(USE_OPENGL_GAME) || defined(USE_OPENGL_SHADERS)
-
-#include "backends/graphics3d/opengl/surfacerenderer.h"
-#include "graphics/opengl/texture.h"
-
-#include "graphics/opengl/context.h"
-
-#if defined(USE_OPENGL_SHADERS)
-#include "graphics/opengl/shader.h"
-#endif
-
-namespace OpenGL {
-
-SurfaceRenderer *createBestSurfaceRenderer() {
-#if defined(USE_OPENGL_SHADERS)
-	if (OpenGLContext.shadersSupported) {
-		return new ShaderSurfaceRenderer();
-	}
-#endif
-
-#if defined(USE_OPENGL_GAME)
-	return new FixedSurfaceRenderer();
-#else
-	error("Could not create an appropriate surface renderer for the current OpenGL context");
-#endif
-}
-
-struct SurfaceVertex {
-	float x;
-	float y;
-	float u;
-	float v;
-};
-
-SurfaceRenderer::SurfaceRenderer() :
-		_flipY(false),
-		_alphaBlending(false) {
-}
-
-SurfaceRenderer::~SurfaceRenderer() {
-}
-
-void SurfaceRenderer::setFlipY(bool flipY) {
-	_flipY = flipY;
-}
-
-void SurfaceRenderer::enableAlphaBlending(bool enable) {
-	if (_alphaBlending != enable) {
-		glEnable(GL_BLEND);
-		glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-	} else {
-		glDisable(GL_BLEND);
-	}
-	_alphaBlending = enable;
-}
-
-#if defined(USE_OPENGL_GAME)
-
-FixedSurfaceRenderer::~FixedSurfaceRenderer() {
-}
-
-void FixedSurfaceRenderer::prepareState() {
-	// Save current state
-	glPushAttrib(GL_TRANSFORM_BIT | GL_VIEWPORT_BIT | GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_SCISSOR_BIT | GL_PIXEL_MODE_BIT | GL_TEXTURE_BIT);
-
-	// prepare view
-	glMatrixMode(GL_PROJECTION);
-	glPushMatrix();
-	glLoadIdentity();
-	glOrtho(0, 1.0, 1.0, 0, 0, 1);
-
-	glMatrixMode(GL_MODELVIEW);
-	glPushMatrix();
-	glLoadIdentity();
-
-	glMatrixMode(GL_TEXTURE);
-	glPushMatrix();
-	glLoadIdentity();
-
-	glDisable(GL_LIGHTING);
-	glEnable(GL_TEXTURE_2D);
-	glDisable(GL_DEPTH_TEST);
-	glDisable(GL_ALPHA_TEST);
-	glDisable(GL_SCISSOR_TEST);
-	glDepthMask(GL_FALSE);
-}
-
-void FixedSurfaceRenderer::render(const Texture *tex, const Math::Rect2d &dest) {
-	float texcropX = tex->getLogicalWidth() / float(tex->getWidth());
-	float texcropY = tex->getLogicalHeight() / float(tex->getHeight());
-	float texTop    = _flipY ? 0.0f : texcropY;
-	float texBottom = _flipY ? texcropY : 0.0f;
-
-	float offsetX = dest.getTopLeft().getX();
-	float offsetY = _flipY ? dest.getTopLeft().getY() : 1.0f - dest.getTopLeft().getY() - dest.getHeight();
-	float sizeX   = fabsf(dest.getWidth());
-	float sizeY   = fabsf(dest.getHeight());
-
-	SurfaceVertex vertices[4];
-	vertices[0].x = offsetX;
-	vertices[0].y = offsetY;
-	vertices[0].u = 0.0f;
-	vertices[0].v = texTop;
-	vertices[1].x = offsetX + sizeX;
-	vertices[1].y = offsetY;
-	vertices[1].u = texcropX;
-	vertices[1].v = texTop;
-	vertices[2].x = offsetX + sizeX;
-	vertices[2].y = offsetY + sizeY;
-	vertices[2].u = texcropX;
-	vertices[2].v = texBottom;
-	vertices[3].x = offsetX;
-	vertices[3].y = offsetY + sizeY;
-	vertices[3].u = 0.0f;
-	vertices[3].v = texBottom;
-
-	glColor4f(1.0, 1.0, 1.0, 1.0);
-
-	tex->bind();
-
-	glEnableClientState(GL_VERTEX_ARRAY);
-	glEnableClientState(GL_TEXTURE_COORD_ARRAY);
-
-	glVertexPointer(2, GL_FLOAT, sizeof(SurfaceVertex), &vertices[0].x);
-	glTexCoordPointer(2, GL_FLOAT, sizeof(SurfaceVertex), &vertices[0].u);
-
-	glDrawArrays(GL_QUADS, 0, 4);
-
-	glDisableClientState(GL_VERTEX_ARRAY);
-	glDisableClientState(GL_TEXTURE_COORD_ARRAY);
-}
-
-void FixedSurfaceRenderer::restorePreviousState() {
-	glMatrixMode(GL_PROJECTION);
-	glPopMatrix();
-
-	glMatrixMode(GL_MODELVIEW);
-	glPopMatrix();
-
-	glMatrixMode(GL_TEXTURE);
-	glPopMatrix();
-
-	glPopAttrib();
-
-	_flipY = false;
-	_alphaBlending = false;
-}
-
-#endif
-
-#if defined(USE_OPENGL_SHADERS)
-
-static const char *const boxVertex =
-	"attribute vec2 position;\n"
-	"attribute vec2 texcoord;\n"
-	"uniform vec2 offsetXY;\n"
-	"uniform vec2 sizeWH;\n"
-	"uniform vec2 texcrop;\n"
-// OGLES2 on AmigaOS doesn't support uniform booleans
-#if defined(__amigaos4__)
-	"uniform mediump int flipY;\n"
-#else
-	"uniform bool flipY;\n"
-#endif
-	"varying vec2 Texcoord;\n"
-	"void main() {\n"
-		"Texcoord = texcoord * texcrop;\n"
-		"vec2 pos = offsetXY + position * sizeWH;\n"
-		"pos.x = pos.x * 2.0 - 1.0;\n"
-		"pos.y = pos.y * 2.0 - 1.0;\n"
-#if defined(__amigaos4__)
-		"if (flipY != 0)\n"
-#else
-		"if (flipY)\n"
-#endif
-			"pos.y *= -1.0;\n"
-		"gl_Position = vec4(pos, 0.0, 1.0);\n"
-	"}\n";
-
-static const char *const boxFragment =
-	"#ifdef GL_ES\n"
-		"#ifdef GL_FRAGMENT_PRECISION_HIGH\n"
-			"precision highp float;\n"
-		"#else\n"
-			"precision mediump float;\n"
-		"#endif\n"
-	"#endif\n"
-	"varying vec2 Texcoord;\n"
-	"uniform sampler2D tex;\n"
-	"void main() {\n"
-		"gl_FragColor = texture2D(tex, Texcoord);\n"
-	"}\n";
-
-ShaderSurfaceRenderer::ShaderSurfaceRenderer() {
-	const GLfloat vertices[] = {
-		0.0, 0.0,
-		1.0, 0.0,
-		0.0, 1.0,
-		1.0, 1.0,
-	};
-
-	// Setup the box shader used to render the overlay
-	const char *attributes[] = { "position", "texcoord", nullptr };
-	_boxShader = Shader::fromStrings("box", boxVertex, boxFragment, attributes);
-	_boxVerticesVBO = Shader::createBuffer(GL_ARRAY_BUFFER, sizeof(vertices), vertices);
-	_boxShader->enableVertexAttribute("position", _boxVerticesVBO, 2, GL_FLOAT, GL_TRUE, 2 * sizeof(float), 0);
-	_boxShader->enableVertexAttribute("texcoord", _boxVerticesVBO, 2, GL_FLOAT, GL_TRUE, 2 * sizeof(float), 0);
-}
-
-void ShaderSurfaceRenderer::prepareState() {
-	_boxShader->use();
-
-	_prevStateDepthTest = glIsEnabled(GL_DEPTH_TEST);
-	glDisable(GL_DEPTH_TEST);
-	glGetBooleanv(GL_DEPTH_WRITEMASK, &_prevStateDepthWriteMask);
-	glDepthMask(GL_FALSE);
-	_prevStateBlend = glIsEnabled(GL_BLEND);
-	glGetIntegerv(GL_BLEND_SRC_RGB, &_prevStateBlendSrcRGB);
-	glGetIntegerv(GL_BLEND_DST_RGB, &_prevStateBlendDstRGB);
-	glGetIntegerv(GL_BLEND_SRC_ALPHA, &_prevStateBlendSrcAlpha);
-	glGetIntegerv(GL_BLEND_DST_ALPHA, &_prevStateBlendDstAlpha);
-	glGetIntegerv(GL_VIEWPORT, _prevStateViewport);
-	_prevStateScissorTest = glIsEnabled(GL_SCISSOR_TEST);
-	glDisable(GL_SCISSOR_TEST);
-}
-
-void ShaderSurfaceRenderer::render(const Texture *tex, const Math::Rect2d &dest) {
-	tex->bind();
-
-	float texcropX = tex->getLogicalWidth() / float(tex->getWidth());
-	float texcropY = tex->getLogicalHeight() / float(tex->getHeight());
-	_boxShader->setUniform("texcrop", Math::Vector2d(texcropX, texcropY));
-	_boxShader->setUniform("flipY", _flipY);
-
-	_boxShader->setUniform("offsetXY", dest.getTopLeft());
-	_boxShader->setUniform("sizeWH", Math::Vector2d(fabsf(dest.getWidth()), fabsf(dest.getHeight())));
-
-	glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
-	glBindTexture(GL_TEXTURE_2D, 0);
-}
-
-void ShaderSurfaceRenderer::restorePreviousState() {
-	_prevStateDepthTest ? glEnable(GL_DEPTH_TEST) : glDisable(GL_DEPTH_TEST);
-	glDepthMask(_prevStateDepthWriteMask);
-	_prevStateScissorTest ? glEnable(GL_SCISSOR_TEST) : glDisable(GL_SCISSOR_TEST);
-	_prevStateBlend ? glEnable(GL_BLEND) : glDisable(GL_BLEND);
-	glBlendFuncSeparate(_prevStateBlendSrcRGB, _prevStateBlendDstRGB,
-		_prevStateBlendSrcAlpha, _prevStateBlendDstAlpha);
-	glViewport(_prevStateViewport[0], _prevStateViewport[1], _prevStateViewport[2], _prevStateViewport[3]);
-
-	_flipY = false;
-	_alphaBlending = false;
-
-	_boxShader->unbind();
-}
-
-ShaderSurfaceRenderer::~ShaderSurfaceRenderer() {
-	Shader::freeBuffer(_boxVerticesVBO);
-
-	delete _boxShader;
-}
-
-#endif
-
-} // End of namespace OpenGL
-
-#endif
diff --git a/backends/graphics3d/opengl/surfacerenderer.h b/backends/graphics3d/opengl/surfacerenderer.h
deleted file mode 100644
index ece185160d0..00000000000
--- a/backends/graphics3d/opengl/surfacerenderer.h
+++ /dev/null
@@ -1,125 +0,0 @@
-/* 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 3 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, see <http://www.gnu.org/licenses/>.
- *
- */
-
-#ifndef BACKENDS_GRAPHICS3D_OPENGL_SURFACE_RENDERER_H
-#define BACKENDS_GRAPHICS3D_OPENGL_SURFACE_RENDERER_H
-
-#include "math/rect2d.h"
-
-#include "graphics/opengl/system_headers.h"
-
-namespace OpenGL {
-
-class Shader;
-class Texture;
-
-/**
- * A renderer to draw textures as two dimensional surfaces to the screen.
- */
-class SurfaceRenderer {
-public:
-	SurfaceRenderer();
-	virtual ~SurfaceRenderer();
-
-	/**
-	 * Push the current OpenGL state, and set up the adequate state for calling the render method.
-	 */
-	virtual void prepareState() = 0;
-
-	/**
-	 * Draw a 2D surface from the specified texture.
-	 *
-	 * The destination rectangle must be specified in the following coordinates system:
-	 * x: left [0.0, 1.0] right
-	 * y: top [0.0, 1.0] bottom
-	 *
-	 */
-	virtual void render(const Texture *tex, const Math::Rect2d &dest) = 0;
-
-	/**
-	 * Pop the OpenGL state to restore it as it was before calling the prepareState method.
-	 */
-	virtual void restorePreviousState() = 0;
-
-	/**
-	 * Invert the surface along the Y coordinate
-	 *
-	 * Causes the image to be drawn upside down
-	 */
-	void setFlipY(bool flipY);
-
-	/**
-	 * Set the alpha blending with already drawn content
-	 */
-	void enableAlphaBlending(bool enable);
-
-protected:
-	bool _flipY;
-	bool _alphaBlending;
-};
-
-#if defined(USE_OPENGL_GAME)
-
-class FixedSurfaceRenderer : public SurfaceRenderer {
-public:
-	virtual ~FixedSurfaceRenderer();
-
-	// SurfaceRenderer API
-	void prepareState() override;
-	void render(const Texture *tex, const Math::Rect2d &dest) override;
-	void restorePreviousState() override;
-};
-
-#endif
-
-#if defined(USE_OPENGL_SHADERS)
-
-class ShaderSurfaceRenderer : public SurfaceRenderer {
-public:
-	ShaderSurfaceRenderer();
-	virtual ~ShaderSurfaceRenderer();
-
-	// SurfaceRenderer API
-	void prepareState() override;
-	void render(const Texture *tex, const Math::Rect2d &dest) override;
-	void restorePreviousState() override;
-
-private:
-	Shader *_boxShader;
-	GLuint _boxVerticesVBO;
-	GLboolean _prevStateDepthTest;
-	GLboolean _prevStateDepthWriteMask;
-	GLboolean _prevStateBlend;
-	GLboolean _prevStateScissorTest;
-	GLint _prevStateBlendSrcRGB;
-	GLint _prevStateBlendDstRGB;
-	GLint _prevStateBlendSrcAlpha;
-	GLint _prevStateBlendDstAlpha;
-	GLint _prevStateViewport[4];
-};
-
-#endif
-
-SurfaceRenderer *createBestSurfaceRenderer();
-
-} // End of namespace OpenGL
-
-#endif // GRAPHICS_OPENGL_SURFACE_RENDERER_H
diff --git a/backends/graphics3d/opengl/tiledsurface.cpp b/backends/graphics3d/opengl/tiledsurface.cpp
deleted file mode 100644
index 01f19f1f74b..00000000000
--- a/backends/graphics3d/opengl/tiledsurface.cpp
+++ /dev/null
@@ -1,131 +0,0 @@
-/* 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 3 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, see <http://www.gnu.org/licenses/>.
- *
- */
-
-#include "common/textconsole.h"
-
-#if defined(USE_OPENGL_GAME) || defined(USE_OPENGL_SHADERS)
-
-#include "backends/graphics3d/opengl/tiledsurface.h"
-#include "backends/graphics3d/opengl/surfacerenderer.h"
-#include "graphics/opengl/texture.h"
-
-namespace OpenGL {
-
-TiledSurface::TiledSurface(uint width, uint height, const Graphics::PixelFormat &pixelFormat) {
-	_backingSurface.create(width, height, pixelFormat);
-
-	for (uint y = 0; y < height; y += maxTextureSize) {
-		for (uint x = 0; x < width; x += maxTextureSize) {
-			uint textureWidth = (x + maxTextureSize >= width) ? (width - x) : maxTextureSize;
-			uint textureHeight = (y + maxTextureSize >= height) ? (height - y) : maxTextureSize;
-
-			_tiles.push_back(Tile());
-
-			Tile &tile = _tiles.back();
-			tile.rect = Common::Rect(textureWidth, textureHeight);
-			tile.rect.translate(x, y);
-			tile.texture = new Texture(GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE);
-			tile.texture->setSize(textureWidth, textureHeight);
-			tile.texture->enableLinearFiltering(true);
-			tile.dirty = true;
-		}
-	}
-}
-
-TiledSurface::~TiledSurface() {
-	for (uint i = 0; i < _tiles.size(); i++) {
-		delete _tiles[i].texture;
-	}
-	_backingSurface.free();
-}
-
-void TiledSurface::copyRectToSurface(const void *src, int srcPitch, int x, int y, int w, int h) {
-	_backingSurface.copyRectToSurface(src, srcPitch, x, y, w, h);
-
-	Common::Rect destRect = Common::Rect(w, h);
-	destRect.translate(x, y);
-
-	for (uint i = 0; i < _tiles.size(); i++) {
-		if (_tiles[i].rect.intersects(destRect) || _tiles[i].rect.contains(destRect)) {
-			_tiles[i].dirty = true;
-		}
-	}
-}
-
-void TiledSurface::update() {
-	for (uint i = 0; i < _tiles.size(); i++) {
-		Tile &tile = _tiles[i];
-		if (tile.dirty) {
-			const Common::Rect rect(tile.rect.width(), tile.rect.height());
-
-			// TODO: Restore support for GL_UNPACK_ROW_LENGTH?
-			Graphics::Surface subSurface = _backingSurface.getSubArea(tile.rect);
-			Graphics::Surface *conv = subSurface.convertTo(OpenGL::Texture::getRGBAPixelFormat());
-
-			tile.texture->updateArea(rect, *conv);
-
-			conv->free();
-			delete conv;
-
-			tile.dirty = false;
-		}
-	}
-}
-
-void TiledSurface::draw(SurfaceRenderer *surfaceRenderer) const {
-	for (uint i = 0; i < _tiles.size(); i++) {
-		const Tile &tile = _tiles[i];
-
-		assert(tile.texture);
-		assert(!tile.dirty);
-
-		Math::Vector2d topLeft = Math::Vector2d(tile.rect.left / (float)_backingSurface.w, tile.rect.top / (float)_backingSurface.h);
-		Math::Vector2d bottomRight = Math::Vector2d(tile.rect.right / (float)_backingSurface.w, tile.rect.bottom / (float)_backingSurface.h);
-
-		surfaceRenderer->render(tile.texture, Math::Rect2d(topLeft, bottomRight));
-	}
-}
-
-void TiledSurface::fill(uint32 color) {
-	Common::Rect rect = Common::Rect(_backingSurface.w, _backingSurface.h);
-	_backingSurface.fillRect(rect, color);
-
-	invalidateAllTiles();
-}
-
-void TiledSurface::invalidateAllTiles() {
-	for (uint i = 0; i < _tiles.size(); i++) {
-		_tiles[i].dirty = true;
-	}
-}
-
-Graphics::Surface *TiledSurface::getBackingSurface() {
-	invalidateAllTiles();
-	return &_backingSurface;
-}
-
-const Graphics::Surface *TiledSurface::getBackingSurface() const {
-	return &_backingSurface;
-}
-
-} // End of namespace OpenGL
-
-#endif
diff --git a/backends/graphics3d/opengl/tiledsurface.h b/backends/graphics3d/opengl/tiledsurface.h
deleted file mode 100644
index f32717667cc..00000000000
--- a/backends/graphics3d/opengl/tiledsurface.h
+++ /dev/null
@@ -1,126 +0,0 @@
-/* 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 3 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, see <http://www.gnu.org/licenses/>.
- *
- */
-
-#ifndef BACKENDS_GRAPHICS3D_OPENGL_TILED_SURFACE_H
-#define BACKENDS_GRAPHICS3D_OPENGL_TILED_SURFACE_H
-
-#include "graphics/opengl/system_headers.h"
-
-#include "common/array.h"
-#include "common/rect.h"
-
-#include "graphics/surface.h"
-
-namespace OpenGL {
-
-class Texture;
-class SurfaceRenderer;
-
-/**
- * Surface implementation using OpenGL texture tiles
- */
-class TiledSurface {
-public:
-	TiledSurface(uint width, uint height, const Graphics::PixelFormat &pixelFormat);
-	~TiledSurface();
-
-	/**
-	 * Copy image data to the surface.
-	 *
-	 * The format of the input data needs to match the format returned by
-	 * getFormat.
-	 * This does not immediately updates the textures.
-	 *
-	 * @param x        X coordinate of upper left corner to copy data to.
-	 * @param y        Y coordinate of upper left corner to copy data to.
-	 * @param w        Width of the image data to copy.
-	 * @param h        Height of the image data to copy.
-	 * @param src      Pointer to image data.
-	 * @param srcPitch The number of bytes in a row of the image data.
-	 */
-	void copyRectToSurface(const void *src, int srcPitch, int x, int y, int w, int h);
-
-	/**
-	 * Update the OpenGL textures from the backing surface
-	 */
-	void update();
-
-	/**
-	 * Draw as a 2D surface
-	 *
-	 * The destination rect is as follow :
-	 * x: left [0.0, 1.0] right
-	 * y: top [0.0, 1.0] bottom
-	 *
-	 * @param surfaceRenderer
-	 */
-	void draw(SurfaceRenderer *surfaceRenderer) const;
-
-	/**
-	 * Fill the surface with a fixed color.
-	 *
-	 * @param color Color value in format returned by getFormat.
-	 */
-	void fill(uint32 color);
-
-	/**
-	 * Get the backing surface
-	 *
-	 * This can be used to update the image data, but causes a full update.
-	 * Using copyRectToSurface is preferred
-	 */
-	Graphics::Surface *getBackingSurface();
-
-	/**
-	 * Get the backing surface
-	 *
-	 * This const version can be used to read image data without causing
-	 * a full texture invalidation.
-	 */
-	const Graphics::Surface *getBackingSurface() const;
-
-	/**
-	 * Get the dimensions in pixels of the surface
-	 *
-	 * This does not include the unused area in the textures at the edges
-	 * of the grid.
-	 */
-	uint16 getWidth() const { return _backingSurface.w; }
-	uint16 getHeight() const { return _backingSurface.h; }
-
-private:
-	static const uint maxTextureSize = 256;
-
-	struct Tile {
-		Texture *texture;
-		Common::Rect rect;
-		bool dirty;
-	};
-
-	Graphics::Surface _backingSurface;
-	Common::Array<Tile> _tiles;
-
-	void invalidateAllTiles();
-};
-
-} // End of namespace OpenGL
-
-#endif
diff --git a/backends/graphics3d/openglsdl/openglsdl-graphics3d.cpp b/backends/graphics3d/openglsdl/openglsdl-graphics3d.cpp
deleted file mode 100644
index 1fc3ebb5157..00000000000
--- a/backends/graphics3d/openglsdl/openglsdl-graphics3d.cpp
+++ /dev/null
@@ -1,944 +0,0 @@
-/* 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 3 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, see <http://www.gnu.org/licenses/>.
- *
- */
-
-#include "common/scummsys.h"
-
-#if defined(USE_OPENGL_GAME) || defined(USE_OPENGL_SHADERS)
-
-#include "backends/graphics3d/openglsdl/openglsdl-graphics3d.h"
-#include "backends/graphics3d/opengl/surfacerenderer.h"
-#include "backends/graphics3d/opengl/tiledsurface.h"
-#include "backends/graphics3d/opengl/framebuffer.h"
-#include "backends/events/sdl/sdl-events.h"
-
-#include "common/config-manager.h"
-#include "common/file.h"
-#include "common/translation.h"
-
-#include "engines/engine.h"
-
-#include "graphics/blit.h"
-#include "graphics/opengl/context.h"
-#include "graphics/opengl/system_headers.h"
-#include "graphics/opengl/texture.h"
-
-#ifdef USE_PNG
-#include "image/png.h"
-#else
-#include "image/bmp.h"
-#endif
-
-#if SDL_VERSION_ATLEAST(3, 0, 0)
-static bool sdlGetAttribute(SDL_GLAttr attr, int *value) {
-	return SDL_GL_GetAttribute(attr, value);
-}
-#elif !USE_FORCED_GLES2
-static bool sdlGetAttribute(SDL_GLattr attr, int *value) {
-	return SDL_GL_GetAttribute(attr, value) == 0;
-}
-#endif
-
-#if SDL_VERSION_ATLEAST(3, 0, 0)
-static void sdlGLDestroyContext(SDL_GLContext context) {
-	SDL_GL_DestroyContext(context);
-}
-#elif SDL_VERSION_ATLEAST(2, 0, 0)
-static void sdlGLDestroyContext(SDL_GLContext context) {
-	SDL_GL_DeleteContext(context);
-}
-#endif
-
-#if SDL_VERSION_ATLEAST(3, 0, 0)
-static bool sdlSetSwapInterval(int interval) {
-	return SDL_GL_SetSwapInterval(interval);
-}
-#elif SDL_VERSION_ATLEAST(2, 0, 0)
-static bool sdlSetSwapInterval(int interval) {
-	return SDL_GL_SetSwapInterval(interval) == 0;
-}
-#endif
-
-OpenGLSdlGraphics3dManager::OpenGLSdlGraphics3dManager(SdlEventSource *eventSource, SdlWindow *window, bool supportsFrameBuffer)
-	: SdlGraphicsManager(eventSource, window),
-#if SDL_VERSION_ATLEAST(2, 0, 0)
-	_glContext(nullptr),
-#endif
-	_supportsFrameBuffer(supportsFrameBuffer),
-	_overlayScreen(nullptr),
-	_overlayBackground(nullptr),
-	_fullscreen(false),
-	_lockAspectRatio(true),
-	_stretchMode(STRETCH_FIT),
-	_frameBuffer(nullptr),
-	_surfaceRenderer(nullptr),
-	_engineRequestedWidth(0),
-	_engineRequestedHeight(0),
-	_transactionMode(kTransactionNone) {
-	ConfMan.registerDefault("antialiasing", 0);
-	ConfMan.registerDefault("aspect_ratio", true);
-
-	// Don't start at zero so that the value is never the same as the surface graphics manager
-	_screenChangeCount = 1 << (sizeof(int) * 5 - 2);
-
-	// Set up proper SDL OpenGL context creation.
-#if SDL_VERSION_ATLEAST(2, 0, 0)
-	enum {
-#ifdef USE_OPENGL_SHADERS
-		DEFAULT_GL_MAJOR = 2,
-		DEFAULT_GL_MINOR = 1,
-#else
-		DEFAULT_GL_MAJOR = 1,
-		DEFAULT_GL_MINOR = 3,
-#endif
-
-		DEFAULT_GLES2_MAJOR = 2,
-		DEFAULT_GLES2_MINOR = 0
-	};
-
-#if USE_FORCED_GLES2
-	_glContextType = OpenGL::kContextGLES2;
-	_glContextProfileMask = SDL_GL_CONTEXT_PROFILE_ES;
-	_glContextMajor = DEFAULT_GLES2_MAJOR;
-	_glContextMinor = DEFAULT_GLES2_MINOR;
-#else
-	bool noDefaults = false;
-
-	// Obtain the default GL(ES) context SDL2 tries to setup.
-	//
-	// Please note this might not actually be SDL2's defaults when multiple
-	// instances of this object have been created. But that is no issue
-	// because then we already set up what we want to use.
-	//
-	// In case no defaults are given we prefer OpenGL over OpenGL ES.
-	if (!sdlGetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, &_glContextProfileMask)) {
-		_glContextProfileMask = 0;
-		noDefaults = true;
-	}
-
-	if (!sdlGetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, &_glContextMajor)) {
-		noDefaults = true;
-	}
-
-	if (!sdlGetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, &_glContextMinor)) {
-		noDefaults = true;
-	}
-
-	if (noDefaults) {
-		if (_glContextProfileMask == SDL_GL_CONTEXT_PROFILE_ES) {
-			_glContextMajor = DEFAULT_GLES2_MAJOR;
-			_glContextMinor = DEFAULT_GLES2_MINOR;
-		} else {
-			_glContextProfileMask = 0;
-			_glContextMajor = DEFAULT_GL_MAJOR;
-			_glContextMinor = DEFAULT_GL_MINOR;
-		}
-	}
-
-	if (_glContextProfileMask == SDL_GL_CONTEXT_PROFILE_ES) {
-		// TODO: Support GLES1 for games
-		_glContextType = OpenGL::kContextGLES2;
-	} else if (_glContextProfileMask == SDL_GL_CONTEXT_PROFILE_CORE) {
-		_glContextType = OpenGL::kContextGL;
-
-		// Core profile does not allow legacy functionality, which we use.
-		// Thus we request a standard OpenGL context.
-		_glContextProfileMask = 0;
-		_glContextMajor = DEFAULT_GL_MAJOR;
-		_glContextMinor = DEFAULT_GL_MINOR;
-	} else {
-		_glContextType = OpenGL::kContextGL;
-	}
-#endif
-#else
-	_glContextType = OpenGL::kContextGL;
-#endif
-
-	_vsync = ConfMan.getBool("vsync");
-}
-
-OpenGLSdlGraphics3dManager::~OpenGLSdlGraphics3dManager() {
-	closeOverlay();
-#if SDL_VERSION_ATLEAST(2, 0, 0)
-	deinitializeRenderer();
-#endif
-}
-
-bool OpenGLSdlGraphics3dManager::hasFeature(OSystem::Feature f) const {
-	return
-		(f == OSystem::kFeatureFullscreenMode) ||
-		(f == OSystem::kFeatureOpenGLForGame) ||
-#if SDL_VERSION_ATLEAST(2, 0, 0)
-		(f == OSystem::kFeatureFullscreenToggleKeepsContext) ||
-#endif
-		(f == OSystem::kFeatureVSync) ||
-		(f == OSystem::kFeatureAspectRatioCorrection) ||
-		(f == OSystem::kFeatureStretchMode) ||
-		(f == OSystem::kFeatureOverlaySupportsAlpha && _overlayFormat.aBits() > 3);
-}
-
-bool OpenGLSdlGraphics3dManager::getFeatureState(OSystem::Feature f) const {
-	switch (f) {
-		case OSystem::kFeatureVSync:
-			return _vsync;
-		case OSystem::kFeatureFullscreenMode:
-			return _fullscreen;
-		case OSystem::kFeatureAspectRatioCorrection:
-			return _lockAspectRatio;
-		default:
-			return false;
-	}
-}
-
-void OpenGLSdlGraphics3dManager::setFeatureState(OSystem::Feature f, bool enable) {
-	switch (f) {
-		case OSystem::kFeatureFullscreenMode:
-			if (_fullscreen != enable) {
-				_fullscreen = enable;
-				if (_transactionMode == kTransactionNone)
-					createOrUpdateScreen();
-			}
-			break;
-		case OSystem::kFeatureVSync:
-			assert(_transactionMode != kTransactionNone);
-			_vsync = enable;
-			break;
-		case OSystem::kFeatureAspectRatioCorrection:
-			_lockAspectRatio = enable;
-			break;
-		default:
-			break;
-	}
-}
-
-void OpenGLSdlGraphics3dManager::beginGFXTransaction() {
-	assert(_transactionMode == kTransactionNone);
-
-	_transactionMode = kTransactionActive;
-}
-
-OSystem::TransactionError OpenGLSdlGraphics3dManager::endGFXTransaction() {
-	assert(_transactionMode != kTransactionNone);
-
-	setupScreen();
-
-	_transactionMode = kTransactionNone;
-	return OSystem::kTransactionSuccess;
-}
-
-const OSystem::GraphicsMode glGraphicsModes[] = {
-	{ "opengl3d", "OpenGL 3D", 0 },
-	{ nullptr, nullptr, 0 }
-};
-
-const OSystem::GraphicsMode *OpenGLSdlGraphics3dManager::getSupportedGraphicsModes() const {
-	return glGraphicsModes;
-}
-
-int OpenGLSdlGraphics3dManager::getDefaultGraphicsMode() const {
-	return 0;
-}
-
-bool OpenGLSdlGraphics3dManager::setGraphicsMode(int mode, uint flags) {
-	assert(_transactionMode != kTransactionNone);
-	assert(flags & OSystem::kGfxModeRender3d);
-
-	return true;
-}
-
-int OpenGLSdlGraphics3dManager::getGraphicsMode() const {
-	return 0;
-}
-
-const OSystem::GraphicsMode glStretchModes[] = {
-	{"center", _s("Center"), STRETCH_CENTER},
-	{"pixel-perfect", _s("Pixel-perfect scaling"), STRETCH_INTEGRAL},
-	{"even-pixels", _s("Even pixels scaling"), STRETCH_INTEGRAL_AR},
-	{"fit", _s("Fit to window"), STRETCH_FIT},
-	{"stretch", _s("Stretch to window"), STRETCH_STRETCH},
-	{"fit_force_aspect", _s("Fit to window (4:3)"), STRETCH_FIT_FORCE_ASPECT},
-	{nullptr, nullptr, 0}
-};
-
-const OSystem::GraphicsMode *OpenGLSdlGraphics3dManager::getSupportedStretchModes() const {
-	return glStretchModes;
-}
-
-int OpenGLSdlGraphics3dManager::getDefaultStretchMode() const {
-	return STRETCH_FIT;
-}
-
-bool OpenGLSdlGraphics3dManager::setStretchMode(int mode) {
-	assert(_transactionMode != kTransactionNone);
-
-	if (mode == _stretchMode)
-		return true;
-
-	// Check this is a valid mode
-	const OSystem::GraphicsMode *sm = getSupportedStretchModes();
-	bool found = false;
-	while (sm->name) {
-		if (sm->id == mode) {
-			found = true;
-			break;
-		}
-		sm++;
-	}
-	if (!found) {
-		warning("unknown stretch mode %d", mode);
-		return false;
-	}
-
-	_stretchMode = mode;
-	return true;
-}
-
-int OpenGLSdlGraphics3dManager::getStretchMode() const {
-	return _stretchMode;
-}
-
-void OpenGLSdlGraphics3dManager::initSize(uint w, uint h, const Graphics::PixelFormat *format) {
-	_engineRequestedWidth = w;
-	_engineRequestedHeight = h;
-	if (_transactionMode == kTransactionNone)
-		setupScreen();
-}
-
-void OpenGLSdlGraphics3dManager::setupScreen() {
-	assert(_transactionMode == kTransactionActive);
-
-	closeOverlay();
-
-	_antialiasing = ConfMan.getInt("antialiasing");
-
-#if SDL_VERSION_ATLEAST(2, 0, 0)
-	bool needsWindowReset = false;
-	if (_window->getSDLWindow() && SDL_GL_GetCurrentContext()) {
-		// The anti-aliasing setting cannot be changed without recreating the window.
-		// So check if the window needs to be recreated.
-
-		int currentSamples = 0;
-
-		#if defined(__EMSCRIPTEN__)
-		// SDL_GL_MULTISAMPLESAMPLES isn't available on a  WebGL 1.0 context
-		// (or not bridged in Emscripten?). This forces a windows reset.
-		currentSamples = -1;
-		#else
-		SDL_GL_GetAttribute(SDL_GL_MULTISAMPLESAMPLES, &currentSamples);
-		#endif
-
-		// When rendering to a framebuffer, MSAA is enabled on that framebuffer, not on the screen
-		int targetSamples = shouldRenderToFramebuffer() ? 0 : _antialiasing;
-
-		if (currentSamples != targetSamples) {
-			needsWindowReset = true;
-		}
-	}
-
-	deinitializeRenderer();
-
-	if (needsWindowReset) {
-		_window->destroyWindow();
-	}
-#endif
-
-	createOrUpdateScreen();
-
-	int glflag;
-	const GLubyte *str;
-	str = glGetString(GL_VENDOR);
-	debug(2, "INFO: OpenGL Vendor: %s", str);
-	str = glGetString(GL_RENDERER);
-	debug(2, "INFO: OpenGL Renderer: %s", str);
-	str = glGetString(GL_VERSION);
-	debug(2, "INFO: OpenGL Version: %s", str);
-	SDL_GL_GetAttribute(SDL_GL_RED_SIZE, &glflag);
-	debug(2, "INFO: OpenGL Red bits: %d", glflag);
-	SDL_GL_GetAttribute(SDL_GL_GREEN_SIZE, &glflag);
-	debug(2, "INFO: OpenGL Green bits: %d", glflag);
-	SDL_GL_GetAttribute(SDL_GL_BLUE_SIZE, &glflag);
-	debug(2, "INFO: OpenGL Blue bits: %d", glflag);
-	SDL_GL_GetAttribute(SDL_GL_ALPHA_SIZE, &glflag);
-	debug(2, "INFO: OpenGL Alpha bits: %d", glflag);
-	SDL_GL_GetAttribute(SDL_GL_DEPTH_SIZE, &glflag);
-	debug(2, "INFO: OpenGL Z buffer depth bits: %d", glflag);
-	SDL_GL_GetAttribute(SDL_GL_DOUBLEBUFFER, &glflag);
-	debug(2, "INFO: OpenGL Double Buffer: %d", glflag);
-	SDL_GL_GetAttribute(SDL_GL_STENCIL_SIZE, &glflag);
-	debug(2, "INFO: OpenGL Stencil buffer bits: %d", glflag);
-#ifdef USE_OPENGL_SHADERS
-	debug(2, "INFO: GLSL version: %s", glGetString(GL_SHADING_LANGUAGE_VERSION));
-#endif
-}
-
-void OpenGLSdlGraphics3dManager::createOrUpdateScreen() {
-	closeOverlay();
-
-	// If the game can't adapt to any resolution, render it to a framebuffer
-	// so it can be scaled to fill the available space.
-	bool engineSupportsArbitraryResolutions = !g_engine || g_engine->hasFeature(Engine::kSupportsArbitraryResolutions);
-	bool renderToFrameBuffer = shouldRenderToFramebuffer();
-
-	// Choose the effective window size or fullscreen mode
-	uint effectiveWidth;
-	uint effectiveHeight;
-	if (_fullscreen && (engineSupportsArbitraryResolutions || renderToFrameBuffer)) {
-		Common::Rect fullscreenResolution = getPreferredFullscreenResolution();
-		effectiveWidth = fullscreenResolution.width();
-		effectiveHeight = fullscreenResolution.height();
-	} else {
-		effectiveWidth = _engineRequestedWidth;
-		effectiveHeight = _engineRequestedHeight;
-	}
-
-	if (!createOrUpdateGLContext(_engineRequestedWidth, _engineRequestedHeight,
-	                             effectiveWidth, effectiveHeight,
-	                             renderToFrameBuffer, engineSupportsArbitraryResolutions)) {
-		warning("SDL Error: %s", SDL_GetError());
-		g_system->quit();
-	}
-
-#if SDL_VERSION_ATLEAST(3, 0, 0)
-	int obtainedWidth = 0, obtainedHeight = 0;
-	SDL_GetWindowSizeInPixels(_window->getSDLWindow(), &obtainedWidth, &obtainedHeight);
-#elif SDL_VERSION_ATLEAST(2, 0, 1)
-	int obtainedWidth = 0, obtainedHeight = 0;
-	SDL_GL_GetDrawableSize(_window->getSDLWindow(), &obtainedWidth, &obtainedHeight);
-#else
-	int obtainedWidth = effectiveWidth;
-	int obtainedHeight = effectiveHeight;
-#endif
-
-	_surfaceRenderer = OpenGL::createBestSurfaceRenderer();
-	_overlayFormat = OpenGL::Texture::getRGBAPixelFormat();
-
-	if (renderToFrameBuffer) {
-		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
-		_frameBuffer = createFramebuffer(_engineRequestedWidth, _engineRequestedHeight);
-		_frameBuffer->attach();
-		handleResize(_engineRequestedWidth, _engineRequestedHeight);
-	} else {
-		handleResize(obtainedWidth, obtainedHeight);
-	}
-}
-
-void OpenGLSdlGraphics3dManager::notifyResize(const int width, const int height) {
-#if SDL_VERSION_ATLEAST(2, 0, 0)
-	// Get the updated size directly from SDL, in case there are multiple
-	// resize events in the message queue.
-#if SDL_VERSION_ATLEAST(3, 0, 0)
-	int newWidth = 0, newHeight = 0;
-	SDL_GetWindowSizeInPixels(_window->getSDLWindow(), &newWidth, &newHeight);
-#else
-	int newWidth = 0, newHeight = 0;
-	SDL_GL_GetDrawableSize(_window->getSDLWindow(), &newWidth, &newHeight);
-#endif
-
-	if (newWidth == _overlayScreen->getWidth() && newHeight == _overlayScreen->getHeight()) {
-		return; // nothing to do
-	}
-
-	handleResize(newWidth, newHeight);
-#else
-	handleResize(width, height);
-#endif
-}
-
-void OpenGLSdlGraphics3dManager::handleResizeImpl(const int width, const int height) {
-	// Update the overlay
-	delete _overlayScreen;
-	_overlayScreen = new OpenGL::TiledSurface(width, height, _overlayFormat);
-
-	// Clear the overlay background so it is not displayed distorted while resizing
-	delete _overlayBackground;
-	_overlayBackground = nullptr;
-
-	// Re-setup the scaling for the screen
-	recalculateDisplayAreas();
-
-	// Something changed, so update the screen change ID.
-	_screenChangeCount++;
-}
-
-bool OpenGLSdlGraphics3dManager::gameNeedsAspectRatioCorrection() const {
-	if (_lockAspectRatio) {
-		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.
-		return (width == 320 && height == 200) || (width == 640 && height == 400);
-	}
-
-	return false;
-}
-
-void OpenGLSdlGraphics3dManager::initializeOpenGLContext() const {
-	OpenGLContext.initialize(_glContextType);
-
-#if SDL_VERSION_ATLEAST(2, 0, 0)
-	if (!sdlSetSwapInterval(_vsync ? 1 : 0)) {
-		warning("Unable to %s VSync: %s", _vsync ? "enable" : "disable", SDL_GetError());
-	}
-#endif
-}
-
-OpenGLSdlGraphics3dManager::OpenGLPixelFormat::OpenGLPixelFormat(uint screenBytesPerPixel, uint red, uint green, uint blue, uint alpha, int samples) :
-		bytesPerPixel(screenBytesPerPixel),
-		redSize(red),
-		greenSize(green),
-		blueSize(blue),
-		alphaSize(alpha),
-		multisampleSamples(samples) {
-
-}
-
-bool OpenGLSdlGraphics3dManager::createOrUpdateGLContext(uint gameWidth, uint gameHeight,
-													   uint effectiveWidth, uint effectiveHeight,
-													   bool renderToFramebuffer,
-													   bool engineSupportsArbitraryResolutions) {
-	// Build a list of OpenGL pixel formats usable by ScummVM
-	Common::Array<OpenGLPixelFormat> pixelFormats;
-	if (_antialiasing > 0 && !renderToFramebuffer) {
-		// Don't enable screen level multisampling when rendering to a framebuffer
-		pixelFormats.push_back(OpenGLPixelFormat(32, 8, 8, 8, 8, _antialiasing));
-		pixelFormats.push_back(OpenGLPixelFormat(16, 5, 6, 5, 0, _antialiasing));
-		pixelFormats.push_back(OpenGLPixelFormat(16, 5, 5, 5, 1, _antialiasing));
-	}
-	pixelFormats.push_back(OpenGLPixelFormat(32, 8, 8, 8, 8, 0));
-	pixelFormats.push_back(OpenGLPixelFormat(16, 5, 6, 5, 0, 0));
-	pixelFormats.push_back(OpenGLPixelFormat(16, 5, 5, 5, 1, 0));
-
-	bool clear = false;
-
-	// Unfortunately, SDL does not provide a list of valid pixel formats
-	// for the current OpenGL implementation and hardware.
-	// SDL may not be able to create a screen with the preferred pixel format.
-	// Try all the pixel formats in the list until SDL returns a valid screen.
-	Common::Array<OpenGLPixelFormat>::const_iterator it = pixelFormats.begin();
-	for (; it != pixelFormats.end(); it++) {
-		SDL_GL_SetAttribute(SDL_GL_RED_SIZE, it->redSize);
-		SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, it->greenSize);
-		SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, it->blueSize);
-		SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, it->alphaSize);
-		SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
-		SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
-		SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
-		SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, it->multisampleSamples > 0);
-		SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, it->multisampleSamples);
-#if !SDL_VERSION_ATLEAST(2, 0, 0)
-		SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, _vsync ? 1 : 0);
-#endif
-#if SDL_VERSION_ATLEAST(2, 0, 0)
-		SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, _glContextProfileMask);
-		SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, _glContextMajor);
-		SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, _glContextMinor);
-#endif
-
-#if SDL_VERSION_ATLEAST(2, 0, 0)
-		uint32 sdlflags = SDL_WINDOW_OPENGL;
-
-#ifdef NINTENDO_SWITCH
-		// Switch quirk: Switch seems to need this flag, otherwise the screen
-		// is zoomed when switching from Normal graphics mode to OpenGL
-		sdlflags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
-#endif
-
-		if (renderToFramebuffer || engineSupportsArbitraryResolutions) {
-			sdlflags |= SDL_WINDOW_RESIZABLE;
-		}
-
-		if (_fullscreen) {
-			// On Linux/X11, when toggling to fullscreen, the window manager saves
-			// the window size to be able to restore it when going back to windowed mode.
-			// If the user configured ScummVM to start in fullscreen mode, we first
-			// create a window and then toggle it to fullscreen to give the window manager
-			// a chance to save the window size. That way if the user switches back
-			// to windowed mode, the window manager has a window size to apply instead
-			// of leaving the window at the fullscreen resolution size.
-			if (!_window->getSDLWindow()) {
-				_window->createOrUpdateWindow(gameWidth, gameHeight, sdlflags);
-			}
-
-			sdlflags |= SDL_WINDOW_FULLSCREEN;
-		}
-
-		if (_window->createOrUpdateWindow(effectiveWidth, effectiveHeight, sdlflags)) {
-			// Get the current GL context from SDL in case the previous one
-			// was destroyed because the window was recreated.
-			_glContext = SDL_GL_GetCurrentContext();
-			if (!_glContext) {
-				_glContext = SDL_GL_CreateContext(_window->getSDLWindow());
-				if (_glContext) {
-					clear = true;
-				}
-			}
-
-			if (_glContext) {
-				assert(SDL_GL_GetCurrentWindow() == _window->getSDLWindow());
-				break;
-			}
-		}
-
-		_window->destroyWindow();
-#else
-		uint32 sdlflags = SDL_OPENGL;
-		if (_fullscreen)
-			sdlflags |= SDL_FULLSCREEN;
-
-		SDL_Surface *screen = SDL_SetVideoMode(effectiveWidth, effectiveHeight, it->bytesPerPixel, sdlflags);
-		if (screen) {
-			break;
-		}
-#endif
-	}
-
-	// Display a warning if the effective pixel format is not the preferred one
-	if (it != pixelFormats.begin() && it != pixelFormats.end()) {
-		bool wantsAA = pixelFormats.front().multisampleSamples > 0;
-		bool gotAA = it->multisampleSamples > 0;
-
-		warning("Couldn't create a %d-bit visual%s, using to %d-bit%s instead",
-		        pixelFormats.front().bytesPerPixel,
-		        wantsAA && !gotAA ? " with AA" : "",
-		        it->bytesPerPixel,
-		        wantsAA && !gotAA ? " without AA" : "");
-	}
-
-	if (it == pixelFormats.end())
-		return false;
-
-	initializeOpenGLContext();
-
-#ifdef USE_IMGUI
-	if (clear && _glContext) {
-		// Setup Dear ImGui
-		initImGui(nullptr, _glContext);
-	}
-#endif
-
-
-	if (clear)
-		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
-
-	return true;
-}
-
-bool OpenGLSdlGraphics3dManager::shouldRenderToFramebuffer() const {
-	bool engineSupportsArbitraryResolutions = !g_engine || g_engine->hasFeature(Engine::kSupportsArbitraryResolutions);
-	return !engineSupportsArbitraryResolutions && _supportsFrameBuffer;
-}
-
-void OpenGLSdlGraphics3dManager::drawOverlay() {
-	_surfaceRenderer->prepareState();
-
-	glViewport(_overlayDrawRect.left, _windowHeight - _overlayDrawRect.top - _overlayDrawRect.height(), _overlayDrawRect.width(), _overlayDrawRect.height());
-	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
-
-	if (_overlayBackground) {
-		_overlayBackground->draw(_surfaceRenderer);
-	}
-
-	_surfaceRenderer->enableAlphaBlending(true);
-	_surfaceRenderer->setFlipY(true);
-	_overlayScreen->draw(_surfaceRenderer);
-
-	_surfaceRenderer->restorePreviousState();
-}
-
-OpenGL::FrameBuffer *OpenGLSdlGraphics3dManager::createFramebuffer(uint width, uint height) {
-#if !USE_FORCED_GLES2 || defined(USE_GLAD)
-	if (_antialiasing && OpenGLContext.framebufferObjectMultisampleSupported) {
-		return new OpenGL::MultiSampleFrameBuffer(width, height, _antialiasing);
-	} else
-#endif
-	{
-		return new OpenGL::FrameBuffer(width, height);
-	}
-}
-
-void OpenGLSdlGraphics3dManager::updateScreen() {
-
-	GLint prevStateViewport[4];
-	glGetIntegerv(GL_VIEWPORT, prevStateViewport);
-	if (_frameBuffer) {
-		_frameBuffer->detach();
-		_surfaceRenderer->prepareState();
-		glViewport(_gameDrawRect.left, _windowHeight - _gameDrawRect.top - _gameDrawRect.height(), _gameDrawRect.width(), _gameDrawRect.height());
-		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
-		_surfaceRenderer->render(_frameBuffer, Math::Rect2d(Math::Vector2d(0, 0), Math::Vector2d(1, 1)));
-		_surfaceRenderer->restorePreviousState();
-	}
-
-	if (_overlayVisible) {
-		_overlayScreen->update();
-
-		// If the overlay is in game we expect the game to continue calling OpenGL
-		if (_overlayBackground && _overlayInGUI) {
-			_overlayBackground->update();
-		}
-
-		drawOverlay();
-	}
-
-#ifdef EMSCRIPTEN
-	if (_queuedScreenshot) {
-		SdlGraphicsManager::saveScreenshot();
-		_queuedScreenshot = false;
-	}
-#endif
-
-#if defined(USE_IMGUI) && SDL_VERSION_ATLEAST(2, 0, 0)
-	renderImGui();
-#endif
-
-#if SDL_VERSION_ATLEAST(2, 0, 0)
-	SDL_GL_SwapWindow(_window->getSDLWindow());
-#else
-	SDL_GL_SwapBuffers();
-#endif
-
-	if (_frameBuffer) {
-		_frameBuffer->attach();
-	}
-	glViewport(prevStateViewport[0], prevStateViewport[1], prevStateViewport[2], prevStateViewport[3]);
-}
-
-int16 OpenGLSdlGraphics3dManager::getHeight() const {
-	if (_frameBuffer)
-		return _frameBuffer->getHeight();
-	else
-		return _overlayScreen->getHeight();
-}
-
-int16 OpenGLSdlGraphics3dManager::getWidth() const {
-	if (_frameBuffer)
-		return _frameBuffer->getWidth();
-	else
-		return _overlayScreen->getWidth();
-}
-
-#pragma mark -
-#pragma mark --- Overlays ---
-#pragma mark -
-
-void OpenGLSdlGraphics3dManager::showOverlay(bool inGUI) {
-	if (_overlayVisible && _overlayInGUI == inGUI) {
-		return;
-	}
-
-	WindowedGraphicsManager::showOverlay(inGUI);
-
-	delete _overlayBackground;
-	_overlayBackground = nullptr;
-
-	if (g_engine) {
-		if (_frameBuffer)
-			_frameBuffer->detach();
-		// If there is a game running capture the screen, so that it can be shown "below" the overlay.
-		_overlayBackground = new OpenGL::TiledSurface(_overlayScreen->getWidth(), _overlayScreen->getHeight(), _overlayFormat);
-		Graphics::Surface *background = _overlayBackground->getBackingSurface();
-		glReadPixels(0, 0, background->w, background->h, GL_RGBA, GL_UNSIGNED_BYTE, background->getPixels());
-		if (_frameBuffer)
-			_frameBuffer->attach();
-	}
-}
-
-void OpenGLSdlGraphics3dManager::hideOverlay() {
-	if (!_overlayVisible) {
-		return;
-	}
-	WindowedGraphicsManager::hideOverlay();
-
-	delete _overlayBackground;
-	_overlayBackground = nullptr;
-
-	if (_surfaceRenderer) {
-		// If there is double buffering we need to redraw twice
-		_surfaceRenderer->prepareState();
-		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
-		_surfaceRenderer->restorePreviousState();
-		updateScreen();
-		_surfaceRenderer->prepareState();
-		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
-		_surfaceRenderer->restorePreviousState();
-		updateScreen();
-	}
-}
-
-void OpenGLSdlGraphics3dManager::copyRectToOverlay(const void *buf, int pitch, int x, int y, int w, int h) {
-	_overlayScreen->copyRectToSurface(buf, pitch, x, y, w, h);
-}
-
-void OpenGLSdlGraphics3dManager::clearOverlay() {
-	_overlayScreen->fill(0);
-}
-
-void OpenGLSdlGraphics3dManager::grabOverlay(Graphics::Surface &surface) const {
-	const Graphics::Surface *overlayData = _overlayScreen->getBackingSurface();
-
-	assert(surface.w >= overlayData->w);
-	assert(surface.h >= overlayData->h);
-	assert(surface.format.bytesPerPixel == overlayData->format.bytesPerPixel);
-
-	const byte *src = (const byte *)overlayData->getPixels();
-	byte *dst = (byte *)surface.getPixels();
-	Graphics::copyBlit(dst, src, surface.pitch, overlayData->pitch, overlayData->w, overlayData->h, overlayData->format.bytesPerPixel);
-}
-
-void OpenGLSdlGraphics3dManager::closeOverlay() {
-	if (_overlayScreen) {
-		delete _overlayScreen;
-		_overlayScreen = nullptr;
-	}
-
-	delete _surfaceRenderer;
-	_surfaceRenderer = nullptr;
-
-	delete _frameBuffer;
-	_frameBuffer = nullptr;
-
-	OpenGLContext.reset();
-}
-
-int16 OpenGLSdlGraphics3dManager::getOverlayHeight() const {
-	return _overlayScreen->getHeight();
-}
-
-int16 OpenGLSdlGraphics3dManager::getOverlayWidth() const {
-	return _overlayScreen->getWidth();
-}
-
-bool OpenGLSdlGraphics3dManager::showMouse(bool visible) {
-#if SDL_VERSION_ATLEAST(3, 0, 0)
-	if (visible) {
-		SDL_ShowCursor();
-	} else {
-		SDL_HideCursor();
-	}
-#elif SDL_VERSION_ATLEAST(2, 0, 0)
-	SDL_ShowCursor(visible ? SDL_ENABLE : SDL_DISABLE);
-#endif
-	return true;
-}
-
-void OpenGLSdlGraphics3dManager::showSystemMouseCursor(bool visible) {
-	// HACK: SdlGraphicsManager disables the system cursor when the mouse is in the
-	// active draw rect, however the 3D graphics manager uses it instead of the
-	// standard mouse graphic.
-}
-
-#if SDL_VERSION_ATLEAST(2, 0, 0)
-void OpenGLSdlGraphics3dManager::deinitializeRenderer() {
-#ifdef USE_IMGUI
-	destroyImGui();
-#endif
-
-	sdlGLDestroyContext(_glContext);
-	_glContext = nullptr;
-}
-#endif // SDL_VERSION_ATLEAST(2, 0, 0)
-
-#ifdef EMSCRIPTEN
-void OpenGLSdlGraphics3dManager::saveScreenshot() {
-	_queuedScreenshot = true;
-}
-#endif
-
-bool OpenGLSdlGraphics3dManager::saveScreenshot(const Common::Path &filename) const {
-	// Largely based on the implementation from ScummVM
-	uint width = _overlayScreen->getWidth();
-	uint height = _overlayScreen->getHeight();
-
-#ifdef EMSCRIPTEN
-	const uint lineSize        = width * 4; // RGBA (see comment below)
-#else
-	uint linePaddingSize = width % 4;
-	uint lineSize = width * 3 + linePaddingSize;
-#endif
-
-	Common::DumpFile out;
-	if (!out.open(filename)) {
-		return false;
-	}
-
-	Common::Array<uint8> pixels;
-	pixels.resize(lineSize * height);
-#ifdef EMSCRIPTEN
-	// WebGL doesn't support GL_RGB, see https://registry.khronos.org/webgl/specs/latest/1.0/#5.14.12:
-	// "Only two combinations of format and type are accepted. The first is format RGBA and type UNSIGNED_BYTE.
-	// The second is an implementation-chosen format. " and the implementation-chosen formats are buggy:
-	// https://github.com/KhronosGroup/WebGL/issues/2747
-	glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, &pixels.front());
-	const Graphics::PixelFormat format(OpenGL::Texture::getRGBAPixelFormat());
-#else
-
-	if (_frameBuffer) {
-		_frameBuffer->detach();
-	}
-	glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, &pixels.front());
-	if (_frameBuffer) {
-		_frameBuffer->attach();
-	}
-
-	const Graphics::PixelFormat format(OpenGL::Texture::getRGBPixelFormat());
-#endif
-
-	Graphics::Surface data;
-	data.init(width, height, lineSize, &pixels.front(), format);
-	data.flipVertical(Common::Rect(width, height));
-#ifdef USE_PNG
-	return Image::writePNG(out, data);
-#else
-	return Image::writeBMP(out, data);
-#endif
-}
-
-#if defined(USE_IMGUI) && SDL_VERSION_ATLEAST(2, 0, 0)
-void *OpenGLSdlGraphics3dManager::getImGuiTexture(const Graphics::Surface &image, const byte *palette, int palCount) {
-	// Create a OpenGL texture identifier
-	GLuint image_texture;
-	glGenTextures(1, &image_texture);
-	glBindTexture(GL_TEXTURE_2D, image_texture);
-
-	// Setup filtering parameters for display
-	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); // This is required on WebGL for non power-of-two textures
-	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); // Same
-
-	// Upload pixels into texture
-	Graphics::Surface *s = image.convertTo(OpenGL::Texture::getRGBPixelFormat());
-	glPixelStorei(GL_UNPACK_ALIGNMENT, s->format.bytesPerPixel);
-
-	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, s->w, s->h, 0, GL_RGB, GL_UNSIGNED_BYTE, s->getPixels());
-	s->free();
-	delete s;
-	return (void *)(intptr_t)image_texture;
-}
-
-void OpenGLSdlGraphics3dManager::freeImGuiTexture(void *texture) {
-	GLuint textureID = (intptr_t)texture;
-	glDeleteTextures(1, &textureID);
-}
-#endif
-
-#endif
diff --git a/backends/graphics3d/openglsdl/openglsdl-graphics3d.h b/backends/graphics3d/openglsdl/openglsdl-graphics3d.h
deleted file mode 100644
index c022cb8dc86..00000000000
--- a/backends/graphics3d/openglsdl/openglsdl-graphics3d.h
+++ /dev/null
@@ -1,213 +0,0 @@
-/* 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 3 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, see <http://www.gnu.org/licenses/>.
- *
- */
-
-#ifndef BACKENDS_GRAPHICS3D_OPENGLSDL_GRAPHICS3D_H
-#define BACKENDS_GRAPHICS3D_OPENGLSDL_GRAPHICS3D_H
-
-#include "backends/graphics/sdl/sdl-graphics.h"
-
-#include "math/rect2d.h"
-
-#if defined(USE_OPENGL_GAME) || defined(USE_OPENGL_SHADERS)
-
-#include "graphics/opengl/context.h"
-
-namespace OpenGL {
-	class FrameBuffer;
-	class SurfaceRenderer;
-	class TiledSurface;
-}
-
-/**
- * SDL OpenGL based graphics manager
- *
- * Used when rendering games with OpenGL
- */
-class OpenGLSdlGraphics3dManager : public SdlGraphicsManager {
-public:
-	OpenGLSdlGraphics3dManager(SdlEventSource *eventSource, SdlWindow *window, bool supportsFrameBuffer);
-	virtual ~OpenGLSdlGraphics3dManager();
-
-	// GraphicsManager API - Features
-	bool hasFeature(OSystem::Feature f) const override;
-	bool getFeatureState(OSystem::Feature f) const override;
-	void setFeatureState(OSystem::Feature f, bool enable) override;
-
-	const OSystem::GraphicsMode *getSupportedGraphicsModes() const override;
-	int getDefaultGraphicsMode() const override;
-	bool setGraphicsMode(int mode, uint flags = OSystem::kGfxModeNoFlags) override;
-	int getGraphicsMode() const override;
-
-	const OSystem::GraphicsMode *getSupportedStretchModes() const override;
-	int getDefaultStretchMode() const override;
-	bool setStretchMode(int mode) override;
-	int getStretchMode() const override;
-
-	void beginGFXTransaction() override;
-	OSystem::TransactionError endGFXTransaction() override;
-
-	// GraphicsManager API - Graphics mode
-#ifdef USE_RGB_COLOR
-	Graphics::PixelFormat getScreenFormat() const override { return _overlayFormat; }
-	Common::List<Graphics::PixelFormat> getSupportedFormats() const override {
-		Common::List<Graphics::PixelFormat> supportedFormats;
-		return supportedFormats;
-	}
-#endif
-	int getScreenChangeID() const override { return _screenChangeCount; }
-	void initSize(uint w, uint h, const Graphics::PixelFormat *format) override;
-	int16 getHeight() const override;
-	int16 getWidth() const override;
-
-	// GraphicsManager API - Draw methods
-	void updateScreen() override;
-	// Following methods are not used by 3D graphics managers
-	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 nullptr; }
-	void unlockScreen() override {}
-	void fillScreen(uint32 col) override {}
-	void fillScreen(const Common::Rect &r, uint32 col) override {}
-	void setShakePos(int shakeXOffset, int shakeYOffset) override {};
-	void setFocusRectangle(const Common::Rect& rect) override {}
-	void clearFocusRectangle() override {}
-
-	// GraphicsManager API - Overlay
-	void showOverlay(bool inGUI) override;
-	void hideOverlay() override;
-	Graphics::PixelFormat getOverlayFormat() const override { return _overlayFormat; }
-	void clearOverlay() override;
-	void grabOverlay(Graphics::Surface &surface) const override;
-	void copyRectToOverlay(const void *buf, int pitch, int x, int y, int w, int h) override;
-	int16 getOverlayWidth() const override;
-	int16 getOverlayHeight() const override;
-
-	// GraphicsManager API - Mouse
-	bool showMouse(bool visible) override;
-	void setMouseCursor(const void *buf, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor, bool dontScale = false, const Graphics::PixelFormat *format = NULL, const byte *mask = NULL) override {}
-	void setCursorPalette(const byte *colors, uint start, uint num) override {}
-
-	// SdlGraphicsManager API
-	void notifyVideoExpose() override {};
-	void notifyResize(const int width, const int height) override;
-
-	bool gameNeedsAspectRatioCorrection() const override;
-
-	void showSystemMouseCursor(bool visible) override;
-
-#if defined(USE_IMGUI) && SDL_VERSION_ATLEAST(2, 0, 0)
-	void *getImGuiTexture(const Graphics::Surface &image, const byte *palette, int palCount) override;
-	void freeImGuiTexture(void *texture) override;
-#endif
-
-protected:
-#if SDL_VERSION_ATLEAST(2, 0, 0)
-	int _glContextProfileMask, _glContextMajor, _glContextMinor;
-	SDL_GLContext _glContext;
-	void deinitializeRenderer();
-#endif
-
-	OpenGL::ContextType _glContextType;
-
-	bool _supportsFrameBuffer;
-
-	struct OpenGLPixelFormat {
-		uint bytesPerPixel;
-		uint redSize;
-		uint blueSize;
-		uint greenSize;
-		uint alphaSize;
-		int multisampleSamples;
-
-		OpenGLPixelFormat(uint screenBytesPerPixel, uint red, uint blue, uint green, uint alpha, int samples);
-	};
-
-	/**
-	 * Initialize an OpenGL window matching as closely as possible the required properties
-	 *
-	 * When unable to create a context with anti-aliasing this tries without.
-	 * When unable to create a context with the desired pixel depth this tries lower values.
-	 */
-	bool createOrUpdateGLContext(uint gameWidth, uint gameHeight, uint effectiveWidth, uint effectiveHeight,
-	                             bool renderToFramebuffer, bool engineSupportsArbitraryResolutions);
-
-	void createOrUpdateScreen();
-	void setupScreen();
-
-	void handleResizeImpl(const int width, const int height) override;
-
-#ifdef EMSCRIPTEN
-	/**
-	 * See https://registry.khronos.org/webgl/specs/latest/1.0/#2 :
-	 * " By default, after compositing the contents of the drawing buffer shall be cleared to their default values [...]
-	 *   Techniques like synchronous drawing buffer access (e.g., calling readPixels or toDataURL in the same function
-	 *   that renders to the drawing buffer) can be used to get the contents of the drawing buffer "
-	 *
-	 * This means we need to take the screenshot at the correct time, which we do by queueing taking the screenshot
-	 * for the next frame instead of taking it right away.
-	 */
-	bool _queuedScreenshot = false;
-	void saveScreenshot() override;
-#endif
-
-	bool saveScreenshot(const Common::Path &filename) const override;
-
-	uint _engineRequestedWidth, _engineRequestedHeight;
-
-	int _screenChangeCount;
-	int _antialiasing;
-	int _stretchMode;
-	bool _vsync;
-	bool _fullscreen;
-	bool _lockAspectRatio;
-
-	OpenGL::TiledSurface *_overlayScreen;
-	OpenGL::TiledSurface *_overlayBackground;
-	OpenGL::SurfaceRenderer *_surfaceRenderer;
-
-	Graphics::PixelFormat _overlayFormat;
-
-	void initializeOpenGLContext() const;
-	void drawOverlay();
-	void closeOverlay();
-
-	OpenGL::FrameBuffer *_frameBuffer;
-	OpenGL::FrameBuffer *createFramebuffer(uint width, uint height);
-	bool shouldRenderToFramebuffer() const;
-
-protected:
-
-	enum TransactionMode {
-		kTransactionNone = 0,
-		kTransactionActive = 1,
-		kTransactionRollback = 2
-	};
-
-	/**
-	 * The current transaction mode.
-	 */
-	TransactionMode _transactionMode;
-};
-
-#endif // defined(USE_OPENGL_GAME) || defined(USE_OPENGL_SHADERS)
-
-#endif
diff --git a/backends/module.mk b/backends/module.mk
index aa048a59e06..e73da595cbc 100644
--- a/backends/module.mk
+++ b/backends/module.mk
@@ -231,11 +231,7 @@ endif
 
 ifdef USE_OPENGL
 MODULE_OBJS += \
-	graphics/openglsdl/openglsdl-graphics.o \
-	graphics3d/opengl/framebuffer.o \
-	graphics3d/opengl/surfacerenderer.o \
-	graphics3d/opengl/tiledsurface.o \
-	graphics3d/openglsdl/openglsdl-graphics3d.o
+	graphics/openglsdl/openglsdl-graphics.o
 endif
 
 ifdef USE_DISCORD
diff --git a/backends/platform/sdl/sdl.cpp b/backends/platform/sdl/sdl.cpp
index 46f812b5938..03073c9de59 100644
--- a/backends/platform/sdl/sdl.cpp
+++ b/backends/platform/sdl/sdl.cpp
@@ -52,7 +52,6 @@
 #include "backends/graphics/openglsdl/openglsdl-graphics.h"
 #endif
 #if defined(USE_OPENGL_GAME) || defined(USE_OPENGL_SHADERS)
-#include "backends/graphics3d/openglsdl/openglsdl-graphics3d.h"
 #include "graphics/opengl/context.h"
 #endif
 #if defined(USE_SCUMMVMDLC) && defined(USE_LIBCURL)
@@ -219,9 +218,9 @@ bool OSystem_SDL::hasFeature(Feature f) {
 		return _eventSource->isJoystickConnected();
 	}
 #if defined(USE_OPENGL_GAME) || defined(USE_OPENGL_SHADERS)
-	/* Even if we are using the 2D graphics manager,
+	/* Even if we are using the SDL graphics manager,
 	 * we are at one initGraphics3d call of supporting OpenGL */
-	if (f == kFeatureOpenGLForGame) return true;
+	if (f == kFeatureOpenGLForGame) return _oglType != OpenGL::kContextNone && OpenGLContext.type != OpenGL::kContextGLES;
 	if (f == kFeatureShadersForGame) return _supportsShaders;
 #endif
 #if defined(USE_SCUMMVMDLC) && defined(USE_LIBCURL)


Commit: 396e2deb73f2d4dd94da1f2a7602defb84836e63
    https://github.com/scummvm/scummvm/commit/396e2deb73f2d4dd94da1f2a7602defb84836e63
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2025-06-01T08:24:34+02:00

Commit Message:
ANDROID: Add antialiasing support

Changed paths:
    backends/platform/android/android.cpp
    backends/platform/android/android.h


diff --git a/backends/platform/android/android.cpp b/backends/platform/android/android.cpp
index 40d02070cb1..3a9c075146e 100644
--- a/backends/platform/android/android.cpp
+++ b/backends/platform/android/android.cpp
@@ -1000,6 +1000,37 @@ Common::String OSystem_Android::getSystemProperty(const char *name) const {
 	return Common::String(value, len);
 }
 
+#if defined(USE_OPENGL_GAME) || defined(USE_OPENGL_SHADERS)
+Common::Array<uint> OSystem_Android::getSupportedAntiAliasingLevels() const {
+	Common::Array<uint> levels;
+
+	if (!OpenGLContext.framebufferObjectMultisampleSupported) {
+		return levels;
+	}
+
+	GLint numLevels = 0;
+	GLint *glLevels;
+
+	// We take the format used by Renderer3D
+	glGetInternalformativ(GL_RENDERBUFFER, GL_RGBA8, GL_NUM_SAMPLE_COUNTS, 1, &numLevels);
+	if (numLevels == 0) {
+		return levels;
+	}
+
+	glLevels = new GLint[numLevels];
+	glGetInternalformativ(GL_RENDERBUFFER, GL_RGBA8, GL_SAMPLES, numLevels, glLevels);
+
+	// SDL returns values in ascending order while glGetInternalformativ returns them in descending order.
+	// Revert our result to match SDL
+	for(numLevels--; numLevels >= 0; numLevels--) {
+		levels.push_back(glLevels[numLevels]);
+	}
+
+	delete glLevels;
+	return levels;
+}
+#endif
+
 #if defined(USE_OPENGL) && defined(USE_GLAD)
 void *OSystem_Android::getOpenGLProcAddress(const char *name) const {
 	// eglGetProcAddress exists since Android 2.3 (API Level 9)
diff --git a/backends/platform/android/android.h b/backends/platform/android/android.h
index 86cb65a9451..41bd3f072d6 100644
--- a/backends/platform/android/android.h
+++ b/backends/platform/android/android.h
@@ -270,7 +270,10 @@ public:
 	bool isConnectionLimited() override;
 	Common::String getSystemLanguage() const override;
 
+#if defined(USE_OPENGL_GAME) || defined(USE_OPENGL_SHADERS)
 	OpenGL::ContextType getOpenGLType() const override { return OpenGL::kContextGLES2; }
+	Common::Array<uint> getSupportedAntiAliasingLevels() const override;
+#endif
 #if defined(USE_OPENGL) && defined(USE_GLAD)
 	void *getOpenGLProcAddress(const char *name) const override;
 #endif


Commit: d6a38ca37f84b674f9224f54ed904d273131b40e
    https://github.com/scummvm/scummvm/commit/d6a38ca37f84b674f9224f54ed904d273131b40e
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2025-06-01T08:24:34+02:00

Commit Message:
IOS7: Add anti-aliasing support

Changed paths:
    backends/platform/ios7/ios7_osys_main.cpp
    backends/platform/ios7/ios7_osys_main.h


diff --git a/backends/platform/ios7/ios7_osys_main.cpp b/backends/platform/ios7/ios7_osys_main.cpp
index b0f279f7640..bac29971d6f 100644
--- a/backends/platform/ios7/ios7_osys_main.cpp
+++ b/backends/platform/ios7/ios7_osys_main.cpp
@@ -111,6 +111,37 @@ OSystem_iOS7::~OSystem_iOS7() {
 	delete _graphicsManager;
 }
 
+#if defined(USE_OPENGL_GAME) || defined(USE_OPENGL_SHADERS)
+Common::Array<uint> OSystem_iOS7::getSupportedAntiAliasingLevels() const {
+	Common::Array<uint> levels;
+
+	if (!OpenGLContext.framebufferObjectMultisampleSupported) {
+		return levels;
+	}
+
+	GLint numLevels;
+	GLint *glLevels;
+
+	// We take the format used by Renderer3D
+	glGetInternalformativ(GL_RENDERBUFFER, GL_RGBA8, GL_NUM_SAMPLE_COUNTS, 1, &numLevels);
+	if (numLevels == 0) {
+		return levels;
+	}
+
+	glLevels = new GLint[numLevels];
+	glGetInternalformativ(GL_RENDERBUFFER, GL_RGBA8, GL_SAMPLES, numLevels, glLevels);
+
+	// SDL returns values in ascending order while glGetInternalformativ returns them in descending order.
+	// Revert our result to match SDL
+	for(numLevels--; numLevels >= 0; numLevels--) {
+		levels.push_back(glLevels[numLevels]);
+	}
+
+	delete glLevels;
+	return levels;
+}
+#endif
+
 #if defined(USE_OPENGL) && defined(USE_GLAD)
 void *OSystem_iOS7::getOpenGLProcAddress(const char *name) const {
 	return dlsym(RTLD_DEFAULT, name);
diff --git a/backends/platform/ios7/ios7_osys_main.h b/backends/platform/ios7/ios7_osys_main.h
index 9c237732178..df74599e15b 100644
--- a/backends/platform/ios7/ios7_osys_main.h
+++ b/backends/platform/ios7/ios7_osys_main.h
@@ -117,6 +117,7 @@ public:
 #endif
 #if defined(USE_OPENGL_GAME) || defined(USE_OPENGL_SHADERS)
 	OpenGL::ContextType getOpenGLType() const override { return OpenGL::kContextGLES2; }
+	Common::Array<uint> getSupportedAntiAliasingLevels() const override;
 #endif
 
 public:


Commit: 493e93595c4226967d0bd340db82ac9b13670b73
    https://github.com/scummvm/scummvm/commit/493e93595c4226967d0bd340db82ac9b13670b73
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2025-06-01T08:24:34+02:00

Commit Message:
ANDROID: Fix parameter inversion

This fixes a segfault when starting in 16-bits rendering mode.

Changed paths:
    backends/graphics/android/android-graphics.cpp


diff --git a/backends/graphics/android/android-graphics.cpp b/backends/graphics/android/android-graphics.cpp
index 1862fb2b4c5..7dc69b4f45f 100644
--- a/backends/graphics/android/android-graphics.cpp
+++ b/backends/graphics/android/android-graphics.cpp
@@ -268,7 +268,7 @@ void AndroidGraphicsManager::touchControlInitSurface(const Graphics::ManagedSurf
 			(byte *)dst->getPixels(), (const byte *)surf.getPixels(),
 			dst->pitch, surf.pitch,
 			surf.w, surf.h,
-			surf.format, dst->format);
+			dst->format, surf.format);
 	_touchcontrols->updateGLTexture();
 }
 


Commit: 1c5166f5cecc3b357aaf09ca46591a655988ef2e
    https://github.com/scummvm/scummvm/commit/1c5166f5cecc3b357aaf09ca46591a655988ef2e
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2025-06-01T08:24:34+02:00

Commit Message:
ENGINES: Track screen changes during pause

This allows the engine to react to screen changes which happened when it
was unable to track them.

Changed paths:
    engines/engine.cpp
    engines/engine.h


diff --git a/engines/engine.cpp b/engines/engine.cpp
index 9ca49844961..820581eb67b 100644
--- a/engines/engine.cpp
+++ b/engines/engine.cpp
@@ -145,6 +145,7 @@ Engine::Engine(OSystem *syst)
 		_metaEngine(nullptr),
 		_pauseLevel(0),
 		_pauseStartTime(0),
+		_pauseScreenChangeID(-1),
 		_saveSlotToLoad(-1),
 		_autoSaving(false),
 		_engineStartTime(_system->getMillis()),
@@ -702,6 +703,7 @@ PauseToken Engine::pauseEngine() {
 
 	if (_pauseLevel == 1) {
 		_pauseStartTime = _system->getMillis();
+		_pauseScreenChangeID = g_system->getScreenChangeID();
 		pauseEngineIntern(true);
 	}
 
@@ -714,6 +716,13 @@ void Engine::resumeEngine() {
 	_pauseLevel--;
 
 	if (_pauseLevel == 0) {
+		if (_pauseScreenChangeID != g_system->getScreenChangeID()) {
+			// Inject a screen change event in the event loop for the engine
+			Common::Event ev;
+			ev.type = Common::EVENT_SCREEN_CHANGED;
+			g_system->getEventManager()->pushEvent(ev);
+		}
+		_pauseScreenChangeID = -1;
 		pauseEngineIntern(false);
 		_engineStartTime += _system->getMillis() - _pauseStartTime;
 		_pauseStartTime = 0;
diff --git a/engines/engine.h b/engines/engine.h
index e75c5951803..90da7dcecb9 100644
--- a/engines/engine.h
+++ b/engines/engine.h
@@ -202,6 +202,11 @@ private:
 	 */
 	uint32 _pauseStartTime;
 
+	/**
+	 * The screen change ID when the pause was started
+	 */
+	int _pauseScreenChangeID;
+
 	/**
 	 * The time when the engine was started.
 	 *


Commit: c80b3820ddd5d0a5257394bba93143515796b35b
    https://github.com/scummvm/scummvm/commit/c80b3820ddd5d0a5257394bba93143515796b35b
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2025-06-01T08:24:34+02:00

Commit Message:
BASE: Allow users to set antialiasing on command line

Changed paths:
    base/commandLine.cpp


diff --git a/base/commandLine.cpp b/base/commandLine.cpp
index 3a9b29241b6..7a2d28c979a 100644
--- a/base/commandLine.cpp
+++ b/base/commandLine.cpp
@@ -190,6 +190,7 @@ static const char HELP_STRING4[] =
 	"  --no-show-fps            Set the turn off display FPS info in 3D games\n"
 	"  --random-seed=SEED       Set the random seed used to initialize entropy\n"
 	"  --renderer=RENDERER      Select 3D renderer (software, opengl, opengl_shaders)\n"
+	"  --antialiasing=SAMPLES   Select the antialiasing level\n"
 	"  --aspect-ratio           Enable aspect ratio correction\n"
 	"  --[no-]dirtyrects        Enable dirty rectangles optimisation in software renderer\n"
 	"                           (default: enabled)\n"
@@ -922,6 +923,9 @@ Common::String parseCommandLine(Common::StringMap &settings, int argc, const cha
 					usage("Unrecognized renderer type '%s'", option);
 			END_OPTION
 
+			DO_LONG_OPTION_INT("antialiasing")
+			END_OPTION
+
 			DO_LONG_OPTION_BOOL("show-fps")
 			END_OPTION
 


Commit: ae2e6a6a272d322756724dedb45aac9e9ed11467
    https://github.com/scummvm/scummvm/commit/ae2e6a6a272d322756724dedb45aac9e9ed11467
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2025-06-01T08:24:34+02:00

Commit Message:
ANDROID: Check the 3D status when applying touch settings

Now that there is one backend for all 2D and 3D, the state must be
checked.

Changed paths:
    backends/graphics/android/android-graphics.cpp
    backends/graphics/android/android-graphics.h


diff --git a/backends/graphics/android/android-graphics.cpp b/backends/graphics/android/android-graphics.cpp
index 7dc69b4f45f..ebf86337064 100644
--- a/backends/graphics/android/android-graphics.cpp
+++ b/backends/graphics/android/android-graphics.cpp
@@ -56,8 +56,9 @@ AndroidGraphicsManager::AndroidGraphicsManager() :
 	// Initialize our OpenGL ES context.
 	initSurface();
 
-	// not in 3D, not in GUI
-	dynamic_cast<OSystem_Android *>(g_system)->applyTouchSettings(false, false);
+	_rendering3d = (_renderer3d != nullptr);
+	// maybe in 3D, not in GUI
+	dynamic_cast<OSystem_Android *>(g_system)->applyTouchSettings(_rendering3d, false);
 	dynamic_cast<OSystem_Android *>(g_system)->applyOrientationSettings();
 }
 
@@ -185,8 +186,8 @@ void AndroidGraphicsManager::showOverlay(bool inGUI) {
 	// Don't change touch mode when not changing mouse coordinates
 	if (inGUI) {
 		_old_touch_mode = JNI::getTouchMode();
-		// not in 3D, in overlay
-		dynamic_cast<OSystem_Android *>(g_system)->applyTouchSettings(false, true);
+		// maybe in 3D, in overlay
+		dynamic_cast<OSystem_Android *>(g_system)->applyTouchSettings(_renderer3d != nullptr, true);
 		dynamic_cast<OSystem_Android *>(g_system)->applyOrientationSettings();
 	} else if (_overlayInGUI) {
 		// Restore touch mode active before overlay was shown
@@ -226,6 +227,13 @@ bool AndroidGraphicsManager::loadVideoMode(uint requestedWidth, uint requestedHe
 		warning("Requesting antialiased video mode while not available");
 	}
 
+	const bool render3d = (_renderer3d != nullptr);
+	if (_rendering3d != render3d) {
+		_rendering3d = render3d;
+		// 3D status changed: refresh the touch mode
+		applyTouchSettings();
+	}
+
 	// We get this whenever a new resolution is requested. Since Android is
 	// using a fixed output size we do nothing like that here.
 	return true;
@@ -241,8 +249,8 @@ void AndroidGraphicsManager::refreshScreen() {
 }
 
 void AndroidGraphicsManager::applyTouchSettings() const {
-	// not in 3D, maybe in GUI
-	dynamic_cast<OSystem_Android *>(g_system)->applyTouchSettings(false, _overlayVisible && _overlayInGUI);
+	// maybe in 3D, maybe in GUI
+	dynamic_cast<OSystem_Android *>(g_system)->applyTouchSettings(_renderer3d != nullptr, _overlayVisible && _overlayInGUI);
 }
 
 void AndroidGraphicsManager::syncVirtkeyboardState(bool virtkeybd_on) {
diff --git a/backends/graphics/android/android-graphics.h b/backends/graphics/android/android-graphics.h
index 2b647ce9a02..1f289a1141a 100644
--- a/backends/graphics/android/android-graphics.h
+++ b/backends/graphics/android/android-graphics.h
@@ -68,6 +68,7 @@ protected:
 private:
 	OpenGL::Surface *_touchcontrols;
 	int _old_touch_mode;
+	bool _rendering3d;
 };
 
 #endif


Commit: 5d48384d1f75f6b4a5711e47667a132501942cea
    https://github.com/scummvm/scummvm/commit/5d48384d1f75f6b4a5711e47667a132501942cea
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2025-06-01T08:24:34+02:00

Commit Message:
OPENGL: Fix destroy ordering

Shader pipeline expects the framebuffer to be alive when cleaning up.
A SIGSEGV can happen when notifyContextCreate is called twice in a row.
This should never happen, but better be safe.

Changed paths:
    backends/graphics/opengl/opengl-graphics.cpp


diff --git a/backends/graphics/opengl/opengl-graphics.cpp b/backends/graphics/opengl/opengl-graphics.cpp
index d08167c3258..a18a62e177c 100644
--- a/backends/graphics/opengl/opengl-graphics.cpp
+++ b/backends/graphics/opengl/opengl-graphics.cpp
@@ -1458,11 +1458,8 @@ void OpenGLGraphicsManager::notifyContextCreate(ContextType type,
 	Framebuffer *target,
 	const Graphics::PixelFormat &defaultFormat,
 	const Graphics::PixelFormat &defaultFormatAlpha) {
-	// Set up the target: backbuffer usually
-	delete _targetBuffer;
-	_targetBuffer = target;
 
-	// Initialize pipeline.
+	// Destroy the existing pipeline first (as it depends on the framebuffer)
 	delete _pipeline;
 	_pipeline = nullptr;
 
@@ -1471,6 +1468,10 @@ void OpenGLGraphicsManager::notifyContextCreate(ContextType type,
 	_libretroPipeline = nullptr;
 #endif
 
+	// Set up the target: backbuffer usually
+	delete _targetBuffer;
+	_targetBuffer = target;
+
 	OpenGLContext.initialize(type);
 
 	// Try to setup LibRetro pipeline first if available.


Commit: 0d852d576f5efbe7db9f672323b21c86814abdaa
    https://github.com/scummvm/scummvm/commit/0d852d576f5efbe7db9f672323b21c86814abdaa
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2025-06-01T08:24:34+02:00

Commit Message:
BACKENDS: Allow to fetch the current GraphicsManager when it's nullptr

This function was never used before so there is no consequences.

Changed paths:
    backends/modular-backend.cpp
    backends/modular-backend.h


diff --git a/backends/modular-backend.cpp b/backends/modular-backend.cpp
index 47955f1b29f..d079cd09f17 100644
--- a/backends/modular-backend.cpp
+++ b/backends/modular-backend.cpp
@@ -52,11 +52,6 @@ bool ModularGraphicsBackend::getFeatureState(Feature f) {
 	return _graphicsManager->getFeatureState(f);
 }
 
-GraphicsManager *ModularGraphicsBackend::getGraphicsManager() {
-	assert(_graphicsManager);
-	return (GraphicsManager *)_graphicsManager;
-}
-
 const OSystem::GraphicsMode *ModularGraphicsBackend::getSupportedGraphicsModes() const {
 	return _graphicsManager->getSupportedGraphicsModes();
 }
diff --git a/backends/modular-backend.h b/backends/modular-backend.h
index c8af74e836a..bee9c08a8fc 100644
--- a/backends/modular-backend.h
+++ b/backends/modular-backend.h
@@ -62,7 +62,7 @@ public:
 	/** @name Graphics */
 	//@{
 
-	GraphicsManager *getGraphicsManager();
+	GraphicsManager *getGraphicsManager() { return _graphicsManager; }
 	const GraphicsMode *getSupportedGraphicsModes() const override;
 	int getDefaultGraphicsMode() const override;
 	bool setGraphicsMode(int mode, uint flags = kGfxModeNoFlags) override;


Commit: 6d3075cc953db462de317c6831ed8b34ab0ca978
    https://github.com/scummvm/scummvm/commit/6d3075cc953db462de317c6831ed8b34ab0ca978
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2025-06-01T08:24:34+02:00

Commit Message:
SDL: Notify graphics manager when the window is about to be destroyed

This is only supported on SDL2.
On SDL1.2, the window is completely managed by SDL and we cannot know
when it would get destroyed.

Changed paths:
    backends/graphics/sdl/sdl-graphics.h
    backends/platform/sdl/sdl-window.cpp


diff --git a/backends/graphics/sdl/sdl-graphics.h b/backends/graphics/sdl/sdl-graphics.h
index 591b3df6640..c5033e2cb44 100644
--- a/backends/graphics/sdl/sdl-graphics.h
+++ b/backends/graphics/sdl/sdl-graphics.h
@@ -197,6 +197,9 @@ public:
 		_hintedHeight = 0;
 	}
 
+	// Called by SdlWindow when the window is about to be destroyed
+	virtual void destroyingWindow() {}
+
 protected:
 	Uint32 _lastFlags;
 	bool _allowWindowSizeReset;
diff --git a/backends/platform/sdl/sdl-window.cpp b/backends/platform/sdl/sdl-window.cpp
index 6eec2ade12e..e19925412af 100644
--- a/backends/platform/sdl/sdl-window.cpp
+++ b/backends/platform/sdl/sdl-window.cpp
@@ -22,6 +22,7 @@
 #define FORBIDDEN_SYMBOL_ALLOW_ALL
 
 #include "backends/platform/sdl/sdl-window.h"
+#include "backends/platform/sdl/sdl.h"
 
 #include "common/textconsole.h"
 #include "common/util.h"
@@ -596,6 +597,15 @@ void SdlWindow::destroyWindow() {
 		if (!(_lastFlags & fullscreenMask)) {
 			SDL_GetWindowPosition(_window, &_lastX, &_lastY);
 		}
+		// Notify the graphics manager that we are about to delete its window
+		OSystem_SDL *system = dynamic_cast<OSystem_SDL *>(g_system);
+		assert(system);
+		GraphicsManager *graphics = system->getGraphicsManager();
+		if (graphics) {
+			SdlGraphicsManager *sdlGraphics = dynamic_cast<SdlGraphicsManager *>(graphics);
+			assert(sdlGraphics);
+			sdlGraphics->destroyingWindow();
+		}
 		SDL_DestroyWindow(_window);
 		_window = nullptr;
 	}


Commit: 89d8cc805fe138d3d39df9ad21640590642a645e
    https://github.com/scummvm/scummvm/commit/89d8cc805fe138d3d39df9ad21640590642a645e
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2025-06-01T08:24:34+02:00

Commit Message:
BACKENDS: OPENGLSDL: Avoid extraneous context recreations

Changed paths:
    backends/graphics/openglsdl/openglsdl-graphics.cpp
    backends/graphics/openglsdl/openglsdl-graphics.h


diff --git a/backends/graphics/openglsdl/openglsdl-graphics.cpp b/backends/graphics/openglsdl/openglsdl-graphics.cpp
index 784efffd9e3..9edd2ff7799 100644
--- a/backends/graphics/openglsdl/openglsdl-graphics.cpp
+++ b/backends/graphics/openglsdl/openglsdl-graphics.cpp
@@ -244,6 +244,13 @@ void OpenGLSdlGraphicsManager::deinitOpenGLContext() {
 #endif
 }
 
+#if SDL_VERSION_ATLEAST(2, 0, 0)
+void OpenGLSdlGraphicsManager::destroyingWindow() {
+	// We are about to destroy the window: cleanup the context first
+	deinitOpenGLContext();
+}
+#endif
+
 bool OpenGLSdlGraphicsManager::hasFeature(OSystem::Feature f) const {
 	switch (f) {
 	case OSystem::kFeatureFullscreenMode:
@@ -571,17 +578,13 @@ bool OpenGLSdlGraphicsManager::setupMode(uint width, uint height) {
 #endif
 
 #if SDL_VERSION_ATLEAST(2, 0, 0)
-	// If current antialiasing is not what's expected, destroy the context and the window
+	// If current antialiasing is not what's expected, destroy the window (and the context)
 	// This will force to recreate it
 	if (supportsAntialiasing && _effectiveAntialiasing != _requestedAntialiasing && _glContext) {
-		deinitOpenGLContext();
 		_window->destroyWindow();
 	}
 #endif
 
-	// Destroy OpenGL context before messing with the window
-	deinitOpenGLContext();
-
 	// In case we request a fullscreen mode we will use the mode the user
 	// has chosen last time or the biggest mode available.
 	if (_wantsFullScreen) {
@@ -729,11 +732,15 @@ bool OpenGLSdlGraphicsManager::setupMode(uint width, uint height) {
 			continue;
 		}
 
-		_glContext = SDL_GL_CreateContext(_window->getSDLWindow());
-		if (!_glContext) {
-			warning("SDL_GL_CreateContext failed: %s", SDL_GetError());
-			// Try the next pixel format
-			continue;
+		const bool newContext = !_glContext;
+		if (newContext) {
+			// If createOrUpdateWindow reused the exisiting window, _glContext will still have its previous value
+			_glContext = SDL_GL_CreateContext(_window->getSDLWindow());
+			if (!_glContext) {
+				warning("SDL_GL_CreateContext failed: %s", SDL_GetError());
+				// Try the next pixel format
+				continue;
+			}
 		}
 
 		// Now that we have a context, the AA is really effective
@@ -743,15 +750,19 @@ bool OpenGLSdlGraphicsManager::setupMode(uint width, uint height) {
 			warning("Unable to %s VSync: %s", _vsync ? "enable" : "disable", SDL_GetError());
 		}
 
-		notifyContextCreate(_glContextType, new OpenGL::Backbuffer(), it[0], it[1]);
+		if (newContext) {
+			notifyContextCreate(_glContextType, new OpenGL::Backbuffer(), it[0], it[1]);
+		}
 		int actualWidth, actualHeight;
 		getWindowSizeFromSdl(&actualWidth, &actualHeight);
 
 		handleResize(actualWidth, actualHeight);
 
 #ifdef USE_IMGUI
-		// Setup Dear ImGui
-		initImGui(nullptr, _glContext);
+		if (newContext) {
+			// Setup Dear ImGui
+			initImGui(nullptr, _glContext);
+		}
 #endif
 
 #ifdef WIN32
@@ -783,6 +794,9 @@ bool OpenGLSdlGraphicsManager::setupMode(uint width, uint height) {
 			}
 		}
 
+		// Destroy OpenGL context before messing with the window: in SDL1.2 we can't now when the window will get destroyed or not
+		deinitOpenGLContext();
+
 		uint32 flags = SDL_OPENGL;
 		if (_wantsFullScreen) {
 			width  = _desiredFullscreenWidth;
diff --git a/backends/graphics/openglsdl/openglsdl-graphics.h b/backends/graphics/openglsdl/openglsdl-graphics.h
index 796c0c88962..d8008fb6bfb 100644
--- a/backends/graphics/openglsdl/openglsdl-graphics.h
+++ b/backends/graphics/openglsdl/openglsdl-graphics.h
@@ -55,6 +55,10 @@ public:
 	void freeImGuiTexture(void *texture) override;
 #endif
 
+#if SDL_VERSION_ATLEAST(2, 0, 0)
+	void destroyingWindow() override;
+#endif
+
 protected:
 	bool loadVideoMode(uint requestedWidth, uint requestedHeight, const Graphics::PixelFormat &format, bool resizable, int antialiasing) override;
 


Commit: 5bdaf97e5ede1bf9a7a4c8349351a5021dcae32f
    https://github.com/scummvm/scummvm/commit/5bdaf97e5ede1bf9a7a4c8349351a5021dcae32f
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2025-06-01T08:24:34+02:00

Commit Message:
SDL: Rework fullscreen switching and make it work for 3D

kFeatureFullscreenToggleKeepsContext was a feature only used internally
by the SDL backend. Remove it and replace it by a virtual function.
Make the common code agnostic of the 3D rendering mode.

Changed paths:
    backends/graphics/openglsdl/openglsdl-graphics.cpp
    backends/graphics/openglsdl/openglsdl-graphics.h
    backends/graphics/sdl/sdl-graphics.cpp
    backends/graphics/sdl/sdl-graphics.h
    backends/graphics/surfacesdl/surfacesdl-graphics.cpp
    backends/graphics/surfacesdl/surfacesdl-graphics.h
    common/system.h


diff --git a/backends/graphics/openglsdl/openglsdl-graphics.cpp b/backends/graphics/openglsdl/openglsdl-graphics.cpp
index 9edd2ff7799..d5831444a09 100644
--- a/backends/graphics/openglsdl/openglsdl-graphics.cpp
+++ b/backends/graphics/openglsdl/openglsdl-graphics.cpp
@@ -257,7 +257,6 @@ bool OpenGLSdlGraphicsManager::hasFeature(OSystem::Feature f) const {
 	case OSystem::kFeatureIconifyWindow:
 	case OSystem::kFeatureVSync:
 #if SDL_VERSION_ATLEAST(2, 0, 0)
-	case OSystem::kFeatureFullscreenToggleKeepsContext:
 	case OSystem::kFeatureRotationMode:
 #endif
 		return true;
@@ -326,6 +325,21 @@ bool OpenGLSdlGraphicsManager::getFeatureState(OSystem::Feature f) const {
 	}
 }
 
+bool OpenGLSdlGraphicsManager::canSwitchFullscreen() const {
+#if SDL_VERSION_ATLEAST(2, 0, 0)
+	// In SDL2+, we can always switch the fullscreen state
+	// The OpenGL context is not reset in this case.
+	return true;
+#elif defined(USE_OPENGL_GAME) || defined(USE_OPENGL_SHADERS)
+	// In SDL 1.2, we can only switch dynamically if we are in 2D
+	// In 3D, the context may get reset which would upset the engine.
+	return _renderer3d == nullptr;
+#else
+	// In SDL1.2 with only 2D, no problem
+	return true;
+#endif
+}
+
 float OpenGLSdlGraphicsManager::getHiDPIScreenFactor() const {
 	return _window->getDpiScalingFactor();
 }
diff --git a/backends/graphics/openglsdl/openglsdl-graphics.h b/backends/graphics/openglsdl/openglsdl-graphics.h
index d8008fb6bfb..9bac8bcefc0 100644
--- a/backends/graphics/openglsdl/openglsdl-graphics.h
+++ b/backends/graphics/openglsdl/openglsdl-graphics.h
@@ -68,6 +68,8 @@ protected:
 
 	bool saveScreenshot(const Common::Path &filename) const override;
 
+	bool canSwitchFullscreen() const override;
+
 private:
 	bool setupMode(uint width, uint height);
 
diff --git a/backends/graphics/sdl/sdl-graphics.cpp b/backends/graphics/sdl/sdl-graphics.cpp
index f82d5a52716..4a955fc0a45 100644
--- a/backends/graphics/sdl/sdl-graphics.cpp
+++ b/backends/graphics/sdl/sdl-graphics.cpp
@@ -501,20 +501,14 @@ bool SdlGraphicsManager::notifyEvent(const Common::Event &event) {
 }
 
 void SdlGraphicsManager::toggleFullScreen() {
-	/* Don't use g_system for kFeatureOpenGLForGame as it's always supported
-	 * We want to check if we are a 3D graphics manager */
-	bool is3D = hasFeature(OSystem::kFeatureOpenGLForGame);
-
 	if (!g_system->hasFeature(OSystem::kFeatureFullscreenMode) ||
-	   (!g_system->hasFeature(OSystem::kFeatureFullscreenToggleKeepsContext) && is3D)) {
+	   !canSwitchFullscreen()) {
 		return;
 	}
 
-	if (!is3D)
-		beginGFXTransaction();
+	beginGFXTransaction();
 	setFeatureState(OSystem::kFeatureFullscreenMode, !getFeatureState(OSystem::kFeatureFullscreenMode));
-	if (!is3D)
-		endGFXTransaction();
+	endGFXTransaction();
 #ifdef USE_OSD
 	if (getFeatureState(OSystem::kFeatureFullscreenMode))
 		displayMessageOnOSD(_("Fullscreen mode"));
diff --git a/backends/graphics/sdl/sdl-graphics.h b/backends/graphics/sdl/sdl-graphics.h
index c5033e2cb44..bd1e45f95de 100644
--- a/backends/graphics/sdl/sdl-graphics.h
+++ b/backends/graphics/sdl/sdl-graphics.h
@@ -212,6 +212,11 @@ protected:
 	SdlEventSource *_eventSource;
 	SdlWindow *_window;
 
+	/**
+	 * @returns whether switching the fullscreen state is currently safe
+	 */
+	virtual bool canSwitchFullscreen() const { return false; }
+
 private:
 	void toggleFullScreen();
 
diff --git a/backends/graphics/surfacesdl/surfacesdl-graphics.cpp b/backends/graphics/surfacesdl/surfacesdl-graphics.cpp
index 9867f925eb7..e215d0201ff 100644
--- a/backends/graphics/surfacesdl/surfacesdl-graphics.cpp
+++ b/backends/graphics/surfacesdl/surfacesdl-graphics.cpp
@@ -268,7 +268,6 @@ bool SurfaceSdlGraphicsManager::hasFeature(OSystem::Feature f) const {
 #endif
 		(f == OSystem::kFeatureFilteringMode) ||
 #if SDL_VERSION_ATLEAST(2, 0, 0)
-		(f == OSystem::kFeatureFullscreenToggleKeepsContext) ||
 		(f == OSystem::kFeatureStretchMode) ||
 		(f == OSystem::kFeatureRotationMode) ||
 		(f == OSystem::kFeatureVSync) ||
diff --git a/backends/graphics/surfacesdl/surfacesdl-graphics.h b/backends/graphics/surfacesdl/surfacesdl-graphics.h
index ce716bd5e19..0ddf4f64732 100644
--- a/backends/graphics/surfacesdl/surfacesdl-graphics.h
+++ b/backends/graphics/surfacesdl/surfacesdl-graphics.h
@@ -449,6 +449,9 @@ protected:
 	virtual void setGraphicsModeIntern();
 	virtual void getDefaultResolution(uint &w, uint &h);
 
+	// In SurfaceSDL mode we never render in 3D and can always switch the fullscreen state
+	bool canSwitchFullscreen() const override { return true; }
+
 private:
 	void setFullscreenMode(bool enable);
 	void handleScalerHotkeys(uint mode, int factor);
diff --git a/common/system.h b/common/system.h
index 8b6735faf27..522a6e1d97b 100644
--- a/common/system.h
+++ b/common/system.h
@@ -514,17 +514,6 @@ public:
 		 */
 		kFeatureVSync,
 
-		/**
-		 * When a backend supports this feature, it guarantees the graphics
-		 * context is not destroyed when switching to and from fullscreen.
-		 *
-		 * For OpenGL, that means the context is kept with all of its content:
-		 * texture, programs, etc.
-		 *
-		 * For TinyGL, that means the backbuffer surface is kept.
-		 */
-		kFeatureFullscreenToggleKeepsContext,
-
 		/**
 		 * The presence of this feature indicates whether the displayLogFile()
 		 * call is supported.


Commit: f5ba76279fd20535fb6955ec686ab6bcd9083c5c
    https://github.com/scummvm/scummvm/commit/f5ba76279fd20535fb6955ec686ab6bcd9083c5c
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2025-06-01T08:24:34+02:00

Commit Message:
BACKENDS: SURFACESDL: Fix unused variable warning

Changed paths:
    backends/graphics/surfacesdl/surfacesdl-graphics.cpp


diff --git a/backends/graphics/surfacesdl/surfacesdl-graphics.cpp b/backends/graphics/surfacesdl/surfacesdl-graphics.cpp
index e215d0201ff..1c33ddf034a 100644
--- a/backends/graphics/surfacesdl/surfacesdl-graphics.cpp
+++ b/backends/graphics/surfacesdl/surfacesdl-graphics.cpp
@@ -1439,7 +1439,9 @@ void SurfaceSdlGraphicsManager::internUpdateScreen() {
 	}
 
 	// Only draw anything if necessary
+#if SDL_VERSION_ATLEAST(2, 0, 0)
 	bool doPresent = false;
+#endif
 	if (actualDirtyRects > 0 || _cursorNeedsRedraw) {
 		SDL_Rect *r;
 		SDL_Rect dst;
@@ -1637,7 +1639,9 @@ void SurfaceSdlGraphicsManager::internUpdateScreen() {
 		// Finally, blit all our changes to the screen
 		if (!_displayDisabled) {
 			updateScreen(_dirtyRectList, actualDirtyRects);
+#if SDL_VERSION_ATLEAST(2, 0, 0)
 			doPresent = true;
+#endif
 		}
 	}
 


Commit: d659142a3b1df4e1603b42facec108bf8362c5d8
    https://github.com/scummvm/scummvm/commit/d659142a3b1df4e1603b42facec108bf8362c5d8
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2025-06-01T08:24:34+02:00

Commit Message:
OPENGL: Detect imaging support

3D renderer initializes context using functions from this optional part
of OpenGL 1.2.
This fixes a segfault on Windows XP OpenGL.

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


diff --git a/backends/graphics/opengl/renderer3d.cpp b/backends/graphics/opengl/renderer3d.cpp
index 4a75574e63d..1da9d48c3b8 100644
--- a/backends/graphics/opengl/renderer3d.cpp
+++ b/backends/graphics/opengl/renderer3d.cpp
@@ -321,8 +321,10 @@ void Renderer3D::enter3D() {
 	} else {
 		// 3D engine just starts, make sure the state is clean
 		glDisable(GL_BLEND);
-		glBlendEquation(GL_FUNC_ADD);
-		glBlendFunc(GL_ONE, GL_ZERO);
+		if (OpenGLContext.imagingSupported) {
+			glBlendEquation(GL_FUNC_ADD);
+			glBlendFunc(GL_ONE, GL_ZERO);
+		}
 
 		glDisable(GL_CULL_FACE);
 		glCullFace(GL_BACK);
diff --git a/graphics/opengl/context.cpp b/graphics/opengl/context.cpp
index a0b78ab0763..3e573c9d6d5 100644
--- a/graphics/opengl/context.cpp
+++ b/graphics/opengl/context.cpp
@@ -64,6 +64,7 @@ void Context::reset() {
 	glslVersion = 0;
 
 	NPOTSupported = false;
+	imagingSupported = false;
 	shadersSupported = false;
 	enginesShadersSupported = false;
 	multitextureSupported = false;
@@ -175,6 +176,8 @@ void Context::initialize(ContextType contextType) {
 
 		if (token == "GL_ARB_texture_non_power_of_two" || token == "GL_OES_texture_npot") {
 			NPOTSupported = true;
+		} else if (token == "GL_ARB_imaging") {
+			imagingSupported = true;
 		} else if (token == "GL_ARB_multitexture") {
 			multitextureSupported = true;
 		} else if (token == "GL_ARB_framebuffer_object") {
@@ -214,6 +217,9 @@ void Context::initialize(ContextType contextType) {
 		// GLES2 always has (limited) NPOT support.
 		NPOTSupported = true;
 
+		// GLES2 always has imaging support
+		imagingSupported = true;
+
 		// GLES2 always has shader support.
 		shadersSupported = true;
 		// GLES2 should always have GLSL ES 1.00 support but let's make sure
@@ -255,6 +261,9 @@ void Context::initialize(ContextType contextType) {
 		// ScummVM does not support multisample FBOs with GLES for now
 		framebufferObjectMultisampleSupported = false;
 
+		// GLES always has imaging support
+		imagingSupported = true;
+
 		packedPixelsSupported = true;
 		textureEdgeClampSupported = true;
 		// No border clamping in GLES
@@ -282,8 +291,9 @@ void Context::initialize(ContextType contextType) {
 			textureEdgeClampSupported = true;
 			textureMaxLevelSupported = true;
 		}
-		// OpenGL 1.3 adds texture border clamp support
+		// OpenGL 1.3 adds texture border clamp support and mandatory imaging support
 		if (isGLVersionOrHigher(1, 3)) {
+			imagingSupported = true;
 			textureBorderClampSupported = true;
 		}
 		// OpenGL 1.4 adds texture mirror repeat support
@@ -314,6 +324,7 @@ void Context::initialize(ContextType contextType) {
 	debug(5, "OpenGL: GLSL version: %d", glslVersion);
 	debug(5, "OpenGL: Max texture size: %d", maxTextureSize);
 	debug(5, "OpenGL: NPOT texture support: %d", NPOTSupported);
+	debug(5, "OpenGL: Imaging support: %d", imagingSupported);
 	debug(5, "OpenGL: Shader support: %d", shadersSupported);
 	debug(5, "OpenGL: Shader support for engines: %d", enginesShadersSupported);
 	debug(5, "OpenGL: Multitexture support: %d", multitextureSupported);
diff --git a/graphics/opengl/context.h b/graphics/opengl/context.h
index 9079dbebad1..50d4ca6772e 100644
--- a/graphics/opengl/context.h
+++ b/graphics/opengl/context.h
@@ -75,6 +75,9 @@ public:
 	/** Whether GL_ARB_texture_non_power_of_two is available or not. */
 	bool NPOTSupported;
 
+	/** Whether GL_ARB_imaging is available or not. */
+	bool imagingSupported;
+
 	/** Whether shader support is available or not. */
 	bool shadersSupported;
 


Commit: 8d24daaf4425b45407322ec5db749bd327b43e87
    https://github.com/scummvm/scummvm/commit/8d24daaf4425b45407322ec5db749bd327b43e87
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2025-06-01T08:24:34+02:00

Commit Message:
BACKENDS: SDL: Free the correct pointer

The data returned by SDL_GetPreferredLocales is allocated in one block.

Changed paths:
    backends/platform/sdl/sdl.cpp


diff --git a/backends/platform/sdl/sdl.cpp b/backends/platform/sdl/sdl.cpp
index 03073c9de59..9301008fdd6 100644
--- a/backends/platform/sdl/sdl.cpp
+++ b/backends/platform/sdl/sdl.cpp
@@ -724,7 +724,7 @@ Common::String OSystem_SDL::getSystemLanguage() const {
 		SDL_Locale *locales = *pLocales;
 		if (locales[0].language != NULL) {
 			Common::String str = Common::String::format("%s_%s", locales[0].country, locales[0].language);
-			SDL_free(locales);
+			SDL_free(pLocales);
 			return str;
 		}
 		SDL_free(pLocales);


Commit: 73a77734e2171241d7d3f2d4a819f559a7af8f84
    https://github.com/scummvm/scummvm/commit/73a77734e2171241d7d3f2d4a819f559a7af8f84
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2025-06-01T08:24:34+02:00

Commit Message:
ENGINES: Allow to override shaders on 3D games

Changed paths:
    engines/engine.cpp


diff --git a/engines/engine.cpp b/engines/engine.cpp
index 820581eb67b..c0b3f5823a4 100644
--- a/engines/engine.cpp
+++ b/engines/engine.cpp
@@ -253,20 +253,20 @@ void initCommonGFX(bool is3D) {
 	if (gameDomain->contains("stretch_mode"))
 		g_system->setStretchMode(ConfMan.get("stretch_mode").c_str());
 
+	if (gameDomain->contains("shader"))
+		g_system->setShader(ConfMan.getPath("shader"));
+
 	// Stop here for hardware-accelerated 3D games
 	if (is3D)
 		return;
 
-	// Set up filtering, scaling and shaders for 2D games
+	// Set up filtering, scaling for 2D games
 	if (gameDomain->contains("filtering"))
 		g_system->setFeatureState(OSystem::kFeatureFilteringMode, ConfMan.getBool("filtering"));
 
 	if (gameDomain->contains("scaler") || gameDomain->contains("scale_factor"))
 		g_system->setScaler(ConfMan.get("scaler").c_str(), ConfMan.getInt("scale_factor"));
 
-	if (gameDomain->contains("shader"))
-		g_system->setShader(ConfMan.getPath("shader"));
-
 	// TODO: switching between OpenGL and SurfaceSDL is quite fragile
 	// and the SDL backend doesn't really need this so leave it out
 	// for now to avoid regressions


Commit: a92c00545af4f09d1281702488a9711af5763f9e
    https://github.com/scummvm/scummvm/commit/a92c00545af4f09d1281702488a9711af5763f9e
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2025-06-01T08:24:34+02:00

Commit Message:
BACKENDS: OPENGL: Fix fallback when shader fails to load

And indicates to the user that the shader failed to apply.

Changed paths:
    backends/graphics/opengl/opengl-graphics.cpp
    engines/engine.cpp


diff --git a/backends/graphics/opengl/opengl-graphics.cpp b/backends/graphics/opengl/opengl-graphics.cpp
index a18a62e177c..c41e6c17ef0 100644
--- a/backends/graphics/opengl/opengl-graphics.cpp
+++ b/backends/graphics/opengl/opengl-graphics.cpp
@@ -498,6 +498,15 @@ OSystem::TransactionError OpenGLGraphicsManager::endGFXTransaction() {
 		   || (   _currentState.gameWidth  > (uint)OpenGLContext.maxTextureSize
 		       || _currentState.gameHeight > (uint)OpenGLContext.maxTextureSize)) {
 			if (_transactionMode == kTransactionActive) {
+				// If the shader failed, it means that loadVideoMode succeeded
+				// Mark the error and continue without it
+				if (!shaderOK && !_currentState.shader.empty()) {
+					transactionError |= OSystem::kTransactionShaderChangeFailed;
+
+					_currentState.shader.clear();
+					_transactionMode = kTransactionRollback;
+					continue;
+				}
 				// Try to setup the old state in case its valid and is
 				// actually different from the new one.
 				if (_oldState.valid && _oldState != _currentState) {
@@ -542,12 +551,6 @@ OSystem::TransactionError OpenGLGraphicsManager::endGFXTransaction() {
 					// Try to set up the old state.
 					continue;
 				}
-				// If the shader failed and we had not a valid old state, try to unset the shader and do it again
-				if (!shaderOK && !_currentState.shader.empty()) {
-					_currentState.shader.clear();
-					_transactionMode = kTransactionRollback;
-					continue;
-				}
 			}
 
 			// DON'T use error(), as this tries to bring up the debug
diff --git a/engines/engine.cpp b/engines/engine.cpp
index c0b3f5823a4..cf502d0858f 100644
--- a/engines/engine.cpp
+++ b/engines/engine.cpp
@@ -450,6 +450,11 @@ int initGraphicsAny(const Graphics::ModeWithFormatList &modes, int start) {
 		dialog.runModal();
 	}
 
+	if (gfxError & OSystem::kTransactionShaderChangeFailed) {
+		GUI::MessageDialog dialog(_("Could not apply shader setting."));
+		dialog.runModal();
+	}
+
 	return candidate;
 }
 


Commit: 436cd89051098d009939a38b0cecb4875aec8e44
    https://github.com/scummvm/scummvm/commit/436cd89051098d009939a38b0cecb4875aec8e44
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2025-06-01T08:24:34+02:00

Commit Message:
ENGINES: Also warn the user of GFX transaction errors in 3D mode

Changed paths:
    engines/engine.cpp


diff --git a/engines/engine.cpp b/engines/engine.cpp
index cf502d0858f..b26862a4fbf 100644
--- a/engines/engine.cpp
+++ b/engines/engine.cpp
@@ -360,53 +360,14 @@ void initGraphicsModes(const Graphics::ModeList &modes) {
 	g_system->initSizeHint(modes);
 }
 
-/**
- * Inits any of the modes in "modes". "modes" is in the order of preference.
- * Return value is index in modes of resulting mode.
- */
-int initGraphicsAny(const Graphics::ModeWithFormatList &modes, int start) {
-	int candidate = -1;
-	OSystem::TransactionError gfxError = OSystem::kTransactionSizeChangeFailed;
-	int last_width = 0, last_height = 0;
-
-	for (candidate = start; candidate < (int)modes.size(); candidate++) {
-		g_system->beginGFXTransaction();
-		initCommonGFX(false);
-#ifdef USE_RGB_COLOR
-		if (modes[candidate].hasFormat)
-			g_system->initSize(modes[candidate].width, modes[candidate].height, &modes[candidate].format);
-		else {
-			Graphics::PixelFormat bestFormat = g_system->getSupportedFormats().front();
-			g_system->initSize(modes[candidate].width, modes[candidate].height, &bestFormat);
-		}
-#else
-		g_system->initSize(modes[candidate].width, modes[candidate].height);
-#endif
-		last_width = modes[candidate].width;
-		last_height = modes[candidate].height;
-
-		gfxError = g_system->endGFXTransaction();
-
-		if (!splash && !GUI::GuiManager::instance()._launched)
-			splashScreen();
-
-		if (gfxError == OSystem::kTransactionSuccess)
-			return candidate;
-
-		// If error is related to resolution, continue
-		if (gfxError & (OSystem::kTransactionSizeChangeFailed | OSystem::kTransactionFormatNotSupported))
-			continue;
-
-		break;
-	}
-
+static void warnTransactionFailures(OSystem::TransactionError gfxError, int width, int height) {
 	// Error out on size switch failure
 	if (gfxError & OSystem::kTransactionSizeChangeFailed) {
 		Common::U32String message;
-		message = Common::U32String::format(_("Could not switch to resolution '%dx%d'."), last_width, last_height);
+		message = Common::U32String::format(_("Could not switch to resolution '%dx%d'."), width, height);
 
 		GUIErrorMessage(message);
-		error("Could not switch to resolution '%dx%d'.", last_width, last_height);
+		error("Could not switch to resolution '%dx%d'.", width, height);
 	}
 
 	// Just show warnings then these occur:
@@ -454,6 +415,49 @@ int initGraphicsAny(const Graphics::ModeWithFormatList &modes, int start) {
 		GUI::MessageDialog dialog(_("Could not apply shader setting."));
 		dialog.runModal();
 	}
+}
+
+/**
+ * Inits any of the modes in "modes". "modes" is in the order of preference.
+ * Return value is index in modes of resulting mode.
+ */
+int initGraphicsAny(const Graphics::ModeWithFormatList &modes, int start) {
+	int candidate = -1;
+	OSystem::TransactionError gfxError = OSystem::kTransactionSizeChangeFailed;
+	int last_width = 0, last_height = 0;
+
+	for (candidate = start; candidate < (int)modes.size(); candidate++) {
+		g_system->beginGFXTransaction();
+		initCommonGFX(false);
+#ifdef USE_RGB_COLOR
+		if (modes[candidate].hasFormat)
+			g_system->initSize(modes[candidate].width, modes[candidate].height, &modes[candidate].format);
+		else {
+			Graphics::PixelFormat bestFormat = g_system->getSupportedFormats().front();
+			g_system->initSize(modes[candidate].width, modes[candidate].height, &bestFormat);
+		}
+#else
+		g_system->initSize(modes[candidate].width, modes[candidate].height);
+#endif
+		last_width = modes[candidate].width;
+		last_height = modes[candidate].height;
+
+		gfxError = g_system->endGFXTransaction();
+
+		if (!splash && !GUI::GuiManager::instance()._launched)
+			splashScreen();
+
+		if (gfxError == OSystem::kTransactionSuccess)
+			return candidate;
+
+		// If error is related to resolution, continue
+		if (gfxError & (OSystem::kTransactionSizeChangeFailed | OSystem::kTransactionFormatNotSupported))
+			continue;
+
+		break;
+	}
+
+	warnTransactionFailures(gfxError, last_width, last_height);
 
 	return candidate;
 }
@@ -500,13 +504,15 @@ void initGraphics3d(int width, int height) {
 		g_system->setGraphicsMode(0, OSystem::kGfxModeRender3d);
 		initCommonGFX(true);
 		g_system->initSize(width, height);
-	g_system->endGFXTransaction();
+	OSystem::TransactionError gfxError = g_system->endGFXTransaction();
 
 	if (!splash && !GUI::GuiManager::instance()._launched) {
 		Common::Event event;
 		(void)g_system->getEventManager()->pollEvent(event);
 		splashScreen();
 	}
+
+	warnTransactionFailures(gfxError, width, height);
 }
 
 void GUIErrorMessageWithURL(const Common::U32String &msg, const char *url) {


Commit: f4c99b0af4d4392525c099d68304c35566cf0419
    https://github.com/scummvm/scummvm/commit/f4c99b0af4d4392525c099d68304c35566cf0419
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2025-06-01T08:24:34+02:00

Commit Message:
PLAYGROUND3D: Remove memory leaks and static variables

Changed paths:
    engines/playground3d/gfx_opengl_shaders.cpp
    engines/playground3d/gfx_tinygl.cpp
    engines/playground3d/gfx_tinygl.h
    engines/playground3d/playground3d.cpp
    engines/playground3d/playground3d.h


diff --git a/engines/playground3d/gfx_opengl_shaders.cpp b/engines/playground3d/gfx_opengl_shaders.cpp
index 6e77c3b733b..79cc37cc9cf 100644
--- a/engines/playground3d/gfx_opengl_shaders.cpp
+++ b/engines/playground3d/gfx_opengl_shaders.cpp
@@ -156,6 +156,24 @@ void ShaderRenderer::deinit() {
 		delete _textures[i];
 		_textures[i] = nullptr;
 	}
+
+	delete _cubeShader;
+	_cubeShader = nullptr;
+	delete _offsetShader;
+	_offsetShader = nullptr;
+	delete _fadeShader;
+	_fadeShader = nullptr;
+	delete _viewportShader;
+	_viewportShader = nullptr;
+	delete _bitmapShader;
+	_bitmapShader = nullptr;
+
+	OpenGL::Shader::freeBuffer(_cubeVBO);
+	OpenGL::Shader::freeBuffer(_offsetVBO);
+	OpenGL::Shader::freeBuffer(_fadeVBO);
+	OpenGL::Shader::freeBuffer(_viewportVBO);
+	OpenGL::Shader::freeBuffer(_bitmapVBO);
+	OpenGL::Shader::freeBuffer(_bitmapTexVBO);
 }
 
 void ShaderRenderer::clear(const Math::Vector4d &clearColor) {
diff --git a/engines/playground3d/gfx_tinygl.cpp b/engines/playground3d/gfx_tinygl.cpp
index 399d09f8b30..3770500e1e2 100644
--- a/engines/playground3d/gfx_tinygl.cpp
+++ b/engines/playground3d/gfx_tinygl.cpp
@@ -84,10 +84,6 @@ TinyGLRenderer::TinyGLRenderer(OSystem *system) :
 		_blitImageRgba4444(nullptr) {
 }
 
-TinyGLRenderer::~TinyGLRenderer() {
-	TinyGL::destroyContext(_context);
-}
-
 void TinyGLRenderer::init() {
 	debug("Initializing Software 3D Renderer");
 
@@ -128,6 +124,7 @@ void TinyGLRenderer::deinit() {
 	tglDeleteBlitImage(_blitImageRgb565);
 	tglDeleteBlitImage(_blitImageRgba5551);
 	tglDeleteBlitImage(_blitImageRgba4444);
+	TinyGL::destroyContext(_context);
 }
 
 void TinyGLRenderer::loadTextureRGBA(Graphics::Surface *texture) {
diff --git a/engines/playground3d/gfx_tinygl.h b/engines/playground3d/gfx_tinygl.h
index 8728153b334..489c5ca6e90 100644
--- a/engines/playground3d/gfx_tinygl.h
+++ b/engines/playground3d/gfx_tinygl.h
@@ -36,7 +36,6 @@ namespace Playground3d {
 class TinyGLRenderer : public Renderer {
 public:
 	TinyGLRenderer(OSystem *_system);
-	virtual ~TinyGLRenderer();
 
 	void init() override;
 	void deinit() override;
diff --git a/engines/playground3d/playground3d.cpp b/engines/playground3d/playground3d.cpp
index 175ab9ea2d4..41aced0d0cd 100644
--- a/engines/playground3d/playground3d.cpp
+++ b/engines/playground3d/playground3d.cpp
@@ -72,13 +72,11 @@ void Playground3dEngine::genTextures() {
 	_rgba4444Texture = generateRgbaTexture(120, 120, pixelFormatRGB4444);
 }
 
-static int testId;
-static bool texturesGenerated;
 Playground3dEngine::Playground3dEngine(OSystem *syst)
 		: Engine(syst), _system(syst), _gfx(nullptr), _frameLimiter(nullptr),
 		_rotateAngleX(0), _rotateAngleY(0), _rotateAngleZ(0), _fogEnable(false),
 		_clearColor(0.0f, 0.0f, 0.0f, 1.0f), _fogColor(0.0f, 0.0f, 0.0f, 1.0f),
-		_fade(1.0f), _fadeIn(false), _scissorEnable(false),
+		_testId(0), _fade(1.0f), _fadeIn(false), _scissorEnable(false),
 		_rgbaTexture(nullptr), _rgbTexture(nullptr), _rgb565Texture(nullptr),
 		_rgba5551Texture(nullptr), _rgba4444Texture(nullptr) {
 }
@@ -86,6 +84,19 @@ Playground3dEngine::Playground3dEngine(OSystem *syst)
 Playground3dEngine::~Playground3dEngine() {
 	delete _frameLimiter;
 	delete _gfx;
+
+	if (_rgbaTexture) {
+		_rgbaTexture->free();
+		delete _rgbaTexture;
+		_rgbTexture->free();
+		delete _rgbTexture;
+		_rgb565Texture->free();
+		delete _rgb565Texture;
+		_rgba5551Texture->free();
+		delete _rgba5551Texture;
+		_rgba4444Texture->free();
+		delete _rgba4444Texture;
+	}
 }
 
 Common::Error Playground3dEngine::run() {
@@ -96,14 +107,12 @@ Common::Error Playground3dEngine::run() {
 
 	_system->showMouse(true);
 
-	texturesGenerated = false;
-
 	// 1 - rotated colorfull cube
 	// 2 - rotated two triangles with depth offset
 	// 3 - fade in/out
 	// 4 - moving filled rectangle in viewport
 	// 5 - drawing RGBA pattern texture to check endian correctness
-	testId = 1;
+	_testId = 1;
 	_fogEnable = false;
 	_scissorEnable = false;
 
@@ -111,7 +120,7 @@ Common::Error Playground3dEngine::run() {
 		_fogColor = Math::Vector4d(1.0f, 1.0f, 1.0f, 1.0f);
 	}
 
-	switch (testId) {
+	switch (_testId) {
 		case 1:
 			_clearColor = Math::Vector4d(0.5f, 0.5f, 0.5f, 1.0f);
 			_rotateAngleX = 45, _rotateAngleY = 45, _rotateAngleZ = 10;
@@ -127,8 +136,9 @@ Common::Error Playground3dEngine::run() {
 			break;
 		case 5: {
 			_clearColor = Math::Vector4d(0.5f, 0.5f, 0.5f, 1.0f);
-			genTextures();
-			texturesGenerated = true;
+			if (!_rgbaTexture) {
+				genTextures();
+			}
 			break;
 		}
 		default:
@@ -137,14 +147,9 @@ Common::Error Playground3dEngine::run() {
 
 	while (!shouldQuit()) {
 		processInput();
-		drawFrame(testId);
+		drawFrame();
 	}
 
-	delete _rgbaTexture;
-	delete _rgbTexture;
-	delete _rgb565Texture;
-	delete _rgba5551Texture;
-	delete _rgba4444Texture;
 	_gfx->deinit();
 	_system->showMouse(false);
 
@@ -164,10 +169,10 @@ void Playground3dEngine::processInput() {
 
 		switch (event.customType) {
 		case kActionSwitchTest:
-			testId++;
-			if (testId > 5)
-				testId = 1;
-			switch (testId) {
+			_testId++;
+			if (_testId > 5)
+				_testId = 1;
+			switch (_testId) {
 				case 1:
 					_clearColor = Math::Vector4d(0.5f, 0.5f, 0.5f, 1.0f);
 					_rotateAngleX = 45, _rotateAngleY = 45, _rotateAngleZ = 10;
@@ -183,9 +188,8 @@ void Playground3dEngine::processInput() {
 					break;
 				case 5: {
 					_clearColor = Math::Vector4d(0.5f, 0.5f, 0.5f, 1.0f);
-					if (!texturesGenerated) {
+					if (!_rgbaTexture) {
 						genTextures();
-						texturesGenerated = true;
 					}
 					break;
 				}
@@ -270,7 +274,7 @@ void Playground3dEngine::drawRgbaTexture() {
 	_gfx->drawRgbaTexture();
 }
 
-void Playground3dEngine::drawFrame(int id) {
+void Playground3dEngine::drawFrame() {
 	_gfx->clear(_clearColor);
 
 	float pitch = 0.0f;
@@ -287,7 +291,7 @@ void Playground3dEngine::drawFrame(int id) {
 
 	_gfx->disableFog();
 
-	switch (id) {
+	switch (_testId) {
 		case 1:
 			if (_fogEnable) {
 				_gfx->enableFog(_fogColor);
diff --git a/engines/playground3d/playground3d.h b/engines/playground3d/playground3d.h
index 42a4f14ce1c..5c1a787e704 100644
--- a/engines/playground3d/playground3d.h
+++ b/engines/playground3d/playground3d.h
@@ -51,7 +51,7 @@ public:
 
 	void processInput();
 
-	void drawFrame(int testId);
+	void drawFrame();
 
 private:
 	OSystem *_system;
@@ -59,6 +59,7 @@ private:
 	Graphics::FrameLimiter *_frameLimiter;
 	Math::Vector4d _clearColor;
 	Math::Vector4d _fogColor;
+	int _testId;
 	float _fade;
 	bool _fadeIn;
 	bool _fogEnable;


Commit: 9fbb12a077578a836b54917a293c0e453d4d299e
    https://github.com/scummvm/scummvm/commit/9fbb12a077578a836b54917a293c0e453d4d299e
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2025-06-01T08:24:34+02:00

Commit Message:
SDL: Fix unused function warning on SDL3 too

Changed paths:
    backends/graphics/openglsdl/openglsdl-graphics.cpp
    backends/platform/sdl/sdl.cpp


diff --git a/backends/graphics/openglsdl/openglsdl-graphics.cpp b/backends/graphics/openglsdl/openglsdl-graphics.cpp
index d5831444a09..ba2335c574f 100644
--- a/backends/graphics/openglsdl/openglsdl-graphics.cpp
+++ b/backends/graphics/openglsdl/openglsdl-graphics.cpp
@@ -54,15 +54,17 @@ static bool sdlSetSwapInterval(int interval) {
 }
 #endif
 
+#if !USE_FORCED_GL && !USE_FORCED_GLES && !USE_FORCED_GLES2
 #if SDL_VERSION_ATLEAST(3, 0, 0)
 static bool sdlGetAttribute(SDL_GLAttr attr, int *value) {
 	return SDL_GL_GetAttribute(attr, value);
 }
-#elif !USE_FORCED_GL && !USE_FORCED_GLES && !USE_FORCED_GLES2
+#else
 static bool sdlGetAttribute(SDL_GLattr attr, int *value) {
 	return SDL_GL_GetAttribute(attr, value) == 0;
 }
 #endif
+#endif
 
 OpenGLSdlGraphicsManager::OpenGLSdlGraphicsManager(SdlEventSource *eventSource, SdlWindow *window)
 	: SdlGraphicsManager(eventSource, window), _lastRequestedHeight(0),
diff --git a/backends/platform/sdl/sdl.cpp b/backends/platform/sdl/sdl.cpp
index 9301008fdd6..8ea510470dc 100644
--- a/backends/platform/sdl/sdl.cpp
+++ b/backends/platform/sdl/sdl.cpp
@@ -78,15 +78,17 @@
 #include <SDL_clipboard.h>
 #endif
 
+#if (defined(USE_OPENGL_GAME) || defined(USE_OPENGL_SHADERS)) && !USE_FORCED_GLES2
 #if SDL_VERSION_ATLEAST(3, 0, 0)
 static bool sdlGetAttribute(SDL_GLAttr attr, int *value) {
 	return SDL_GL_GetAttribute(attr, value);
 }
-#elif SDL_VERSION_ATLEAST(2, 0, 0) && !USE_FORCED_GLES2
+#elif SDL_VERSION_ATLEAST(2, 0, 0)
 static bool sdlGetAttribute(SDL_GLattr attr, int *value) {
 	return SDL_GL_GetAttribute(attr, value) == 0;
 }
 #endif
+#endif
 
 OSystem_SDL::OSystem_SDL()
 	:


Commit: 13e9c12d95b656b0af00d3bfa426bb0721d6cd7c
    https://github.com/scummvm/scummvm/commit/13e9c12d95b656b0af00d3bfa426bb0721d6cd7c
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2025-06-01T08:24:34+02:00

Commit Message:
PLAYGROUND3D: Add a mouse cursor

With the SDL 3D manager the system cursor was used.
This is not the case anymore.

Changed paths:
    engines/playground3d/playground3d.cpp


diff --git a/engines/playground3d/playground3d.cpp b/engines/playground3d/playground3d.cpp
index 41aced0d0cd..cc020350e70 100644
--- a/engines/playground3d/playground3d.cpp
+++ b/engines/playground3d/playground3d.cpp
@@ -24,6 +24,7 @@
 #include "common/error.h"
 #include "common/events.h"
 
+#include "graphics/cursorman.h"
 #include "graphics/renderer.h"
 
 #include "engines/util.h"
@@ -105,7 +106,8 @@ Common::Error Playground3dEngine::run() {
 
 	_frameLimiter = new Graphics::FrameLimiter(_system, ConfMan.getInt("engine_speed"));
 
-	_system->showMouse(true);
+	CursorMan.setDefaultArrowCursor();
+	CursorMan.showMouse(true);
 
 	// 1 - rotated colorfull cube
 	// 2 - rotated two triangles with depth offset
@@ -151,7 +153,7 @@ Common::Error Playground3dEngine::run() {
 	}
 
 	_gfx->deinit();
-	_system->showMouse(false);
+	CursorMan.showMouse(false);
 
 	return Common::kNoError;
 }
@@ -163,7 +165,7 @@ void Playground3dEngine::processInput() {
 		if (event.type == Common::EVENT_SCREEN_CHANGED) {
 			_gfx->computeScreenViewport();
 		}
-		if (event.type != Common::EVENT_CUSTOM_ENGINE_ACTION_START)	{
+		if (event.type != Common::EVENT_CUSTOM_ENGINE_ACTION_START) {
 			continue;
 		}
 


Commit: b096e3003eb6b804199e981e63b3c52e291366ed
    https://github.com/scummvm/scummvm/commit/b096e3003eb6b804199e981e63b3c52e291366ed
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2025-06-01T08:24:34+02:00

Commit Message:
TWP: Let ImGui render the mouse cursor when displayed

The system cursor is never displayed because we are in relative mode.

Changed paths:
    engines/twp/debugtools.cpp


diff --git a/engines/twp/debugtools.cpp b/engines/twp/debugtools.cpp
index bbcfc2a2b0f..b7cf9d5fbd2 100644
--- a/engines/twp/debugtools.cpp
+++ b/engines/twp/debugtools.cpp
@@ -625,12 +625,15 @@ void onImGuiInit() {
 }
 
 void onImGuiRender() {
+	ImGuiIO& io = ImGui::GetIO();
 	if (!debugChannelSet(-1, kDebugConsole)) {
-		ImGui::GetIO().ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange | ImGuiConfigFlags_NoMouse;
+		io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange | ImGuiConfigFlags_NoMouse;
+		io.MouseDrawCursor = false;
 		return;
 	}
 
-	ImGui::GetIO().ConfigFlags &= ~(ImGuiConfigFlags_NoMouseCursorChange | ImGuiConfigFlags_NoMouse);
+	io.ConfigFlags &= ~(ImGuiConfigFlags_NoMouseCursorChange | ImGuiConfigFlags_NoMouse);
+	io.MouseDrawCursor = true;
 	drawGeneral();
 	drawThreads();
 	drawObjects();




More information about the Scummvm-git-logs mailing list