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

lephilousophe noreply at scummvm.org
Sun Nov 6 19:03:09 UTC 2022


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

Summary:
c6451a2ec9 GUI: Fix top dialog only drawing
96fd0b8418 BACKENDS: OPENGL: Fix missing default case
479ef6a851 BACKENDS: OPENGL: Simplify size logic
b329308b7a BACKENDS: OPENGL: Don't load a preset with no pass
2d910e353b BACKENDS: OPENGL: When closing reset _isAnimated to keep performace
29c25ed566 BACKENDS: OPENGL: Store projection matrix as a Matrix4
9b951944bc BACKENDS: OPENGL: Activate framebuffer with a specific pipeline
769fe03a4b BACKENDS: OPENGL: Use override keyword
239c115249 BACKENDS: OPENGL: Rename drawTexture override
6632e909da BACKENDS: OPENGL: Hide active pipeline and activate it as needed
70cf4e9e3e BACKENDS: OPENGL: Move framebuffer out of common activate code
f9005454bd BACKENDS: OPENGL: Allow to copy render settings between framebuffers
5484ebffae BACKENDS: OPENGL: Rework LibRetro pipeline
9d1910854b BACKENDS: OPENGL: Match vertex coordinates with RetroArch
a6dd037079 BACKENDS: OPENGL: Add support for previous frames in LibRetro
52903aff8a BACKENDS: OPENGL: Close old preset before opening a new one
e5c1a4249a BACKENDS: OPENGL: When no shader is selected, close


Commit: c6451a2ec9adf13d2df51a334a0861dff92ef4b0
    https://github.com/scummvm/scummvm/commit/c6451a2ec9adf13d2df51a334a0861dff92ef4b0
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2022-11-06T20:02:59+01:00

Commit Message:
GUI: Fix top dialog only drawing

Before that the parent was also drawn.

Changed paths:
    gui/gui-manager.cpp


diff --git a/gui/gui-manager.cpp b/gui/gui-manager.cpp
index 4316086d90b..174b625ca4e 100644
--- a/gui/gui-manager.cpp
+++ b/gui/gui-manager.cpp
@@ -393,15 +393,22 @@ void GuiManager::redraw() {
 			// This case is an optimization to avoid redrawing the whole dialog
 			// stack when opening a new dialog.
 
-			_theme->drawToBackbuffer();
+			if (_displayTopDialogOnly) {
+				// When displaying only the top dialog clear the screen
+				if (_redrawStatus == kRedrawOpenDialog) {
+					_theme->clearAll();
+					_theme->drawToBackbuffer();
+				}
+			} else {
+				_theme->drawToBackbuffer();
 
-			if (_redrawStatus == kRedrawOpenDialog && _dialogStack.size() > 1) {
-				Dialog *previousDialog = _dialogStack[_dialogStack.size() - 2];
-				previousDialog->drawDialog(kDrawLayerForeground);
-			}
+				if (_redrawStatus == kRedrawOpenDialog && _dialogStack.size() > 1) {
+					Dialog *previousDialog = _dialogStack[_dialogStack.size() - 2];
+					previousDialog->drawDialog(kDrawLayerForeground);
+				}
 
-			if (!_displayTopDialogOnly)
 				_theme->applyScreenShading(shading);
+			}
 
 			_dialogStack.top()->drawDialog(kDrawLayerBackground);
 


Commit: 96fd0b84188656921cef45aebff6ec0e6e93328c
    https://github.com/scummvm/scummvm/commit/96fd0b84188656921cef45aebff6ec0e6e93328c
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2022-11-06T20:02:59+01:00

Commit Message:
BACKENDS: OPENGL: Fix missing default case

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


diff --git a/backends/graphics/opengl/texture.cpp b/backends/graphics/opengl/texture.cpp
index 79c485ae82b..27ac83fcd5a 100644
--- a/backends/graphics/opengl/texture.cpp
+++ b/backends/graphics/opengl/texture.cpp
@@ -99,6 +99,7 @@ void GLTexture::setWrapMode(WrapMode wrapMode) {
 #endif
 		// fall through
 		case kWrapModeRepeat:
+		default:
 			glwrapMode = GL_REPEAT;
 	}
 


Commit: 479ef6a85180e5559b7dd91a3f67cecd061a9b6a
    https://github.com/scummvm/scummvm/commit/479ef6a85180e5559b7dd91a3f67cecd061a9b6a
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2022-11-06T20:02:59+01:00

Commit Message:
BACKENDS: OPENGL: Simplify size logic

Changed paths:
    backends/graphics/opengl/pipelines/libretro.cpp
    backends/graphics/opengl/pipelines/libretro.h


diff --git a/backends/graphics/opengl/pipelines/libretro.cpp b/backends/graphics/opengl/pipelines/libretro.cpp
index d2a76d53c3b..5380bbeaa9d 100644
--- a/backends/graphics/opengl/pipelines/libretro.cpp
+++ b/backends/graphics/opengl/pipelines/libretro.cpp
@@ -142,17 +142,21 @@ void LibRetroPipeline::drawTexture(const GLTexture &texture, const GLfloat *coor
 
 	// Get back screen size from texture coordinates.
 	// FIXME: We assume a fixed set of triangle strip
-	GLfloat w, h;
-	w = coordinates[6] - coordinates[0];
-	h = coordinates[7] - coordinates[1];
-	setOutputSize(w, h);
+	GLfloat outputWidth, outputHeight;
+	outputWidth = coordinates[6] - coordinates[0];
+	outputHeight = coordinates[7] - coordinates[1];
+
+	bool outputSizeChanged = (_outputWidth != outputWidth || _outputHeight != outputHeight);
+	// Save output dimensions.
+	_outputWidth  = outputWidth;
+	_outputHeight = outputHeight;
+
 
 	// In case texture dimensions or viewport dimensions changed, we need to
 	// update the pipeline's state.
 	if (   texture.getLogicalWidth() != _inputWidth
 		|| texture.getLogicalHeight() != _inputHeight
-		|| _outputSizeChanged) {
-		_outputSizeChanged = false;
+		|| outputSizeChanged) {
 		_inputWidth  = texture.getLogicalWidth();
 		_inputHeight = texture.getLogicalHeight();
 
@@ -188,14 +192,6 @@ void LibRetroPipeline::activateInternal() {
 void LibRetroPipeline::deactivateInternal() {
 }
 
-void LibRetroPipeline::setOutputSize(uint outputWidth, uint outputHeight) {
-	_outputSizeChanged = (_outputWidth != outputWidth || _outputHeight != outputHeight);
-
-	// Save output dimensions.
-	_outputWidth  = outputWidth;
-	_outputHeight = outputHeight;
-}
-
 bool LibRetroPipeline::open(const Common::FSNode &shaderPreset) {
 	_shaderPreset = LibRetro::parsePreset(shaderPreset);
 	if (!_shaderPreset)
@@ -425,11 +421,6 @@ bool LibRetroPipeline::loadPasses() {
 
 
 	// Now try to setup FBOs with some dummy size to make sure it could work
-	uint bakInputWidth = _inputWidth;
-	uint bakInputHeight = _inputHeight;
-	uint bakOutputWidth = _outputWidth;
-	uint bakOutputHeight = _outputHeight;
-
 	_inputWidth = 320;
 	_inputHeight = 200;
 	_outputWidth = 640;
@@ -437,12 +428,10 @@ bool LibRetroPipeline::loadPasses() {
 
 	bool ret = setupFBOs();
 
-	_inputWidth = bakInputWidth;
-	_inputHeight = bakInputHeight;
-	_outputWidth = bakOutputWidth;
-	_outputHeight = bakOutputHeight;
-	// Force to reset everything at next draw
-	_outputSizeChanged = true;
+	_inputWidth = 0;
+	_inputHeight = 0;
+	_outputWidth = 0;
+	_outputHeight = 0;
 
 	if (!ret) {
 		return false;
diff --git a/backends/graphics/opengl/pipelines/libretro.h b/backends/graphics/opengl/pipelines/libretro.h
index 9c238331cb6..1452a66cfa7 100644
--- a/backends/graphics/opengl/pipelines/libretro.h
+++ b/backends/graphics/opengl/pipelines/libretro.h
@@ -56,8 +56,6 @@ public:
 
 	virtual void setProjectionMatrix(const GLfloat *projectionMatrix);
 
-	void setOutputSize(uint outputWidth, uint outputHeight);
-
 	bool open(const Common::FSNode &shaderPreset);
 	void close();
 
@@ -88,7 +86,6 @@ private:
 	uint _inputWidth;
 	uint _inputHeight;
 
-	bool _outputSizeChanged;
 	uint _outputWidth;
 	uint _outputHeight;
 


Commit: b329308b7ab988e11076ad058fd0dfca0ae94ed0
    https://github.com/scummvm/scummvm/commit/b329308b7ab988e11076ad058fd0dfca0ae94ed0
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2022-11-06T20:02:59+01:00

Commit Message:
BACKENDS: OPENGL: Don't load a preset with no pass

Changed paths:
    backends/graphics/opengl/pipelines/libretro.cpp


diff --git a/backends/graphics/opengl/pipelines/libretro.cpp b/backends/graphics/opengl/pipelines/libretro.cpp
index 5380bbeaa9d..9e03fd6cfef 100644
--- a/backends/graphics/opengl/pipelines/libretro.cpp
+++ b/backends/graphics/opengl/pipelines/libretro.cpp
@@ -279,6 +279,11 @@ static void stripShaderParameters(char *source, UniformsMap &uniforms) {
 }
 
 bool LibRetroPipeline::loadPasses() {
+	// Error out if there are no passes
+	if (!_shaderPreset->passes.size()) {
+		return false;
+	}
+
 	// First of all, build the aliases list
 	Common::String aliasesDefines;
 	Common::StringArray aliases;


Commit: 2d910e353b4c63b117591b92ae994febd4d39999
    https://github.com/scummvm/scummvm/commit/2d910e353b4c63b117591b92ae994febd4d39999
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2022-11-06T20:02:59+01:00

Commit Message:
BACKENDS: OPENGL: When closing reset _isAnimated to keep performace

Changed paths:
    backends/graphics/opengl/pipelines/libretro.cpp


diff --git a/backends/graphics/opengl/pipelines/libretro.cpp b/backends/graphics/opengl/pipelines/libretro.cpp
index 9e03fd6cfef..b04afca1940 100644
--- a/backends/graphics/opengl/pipelines/libretro.cpp
+++ b/backends/graphics/opengl/pipelines/libretro.cpp
@@ -228,6 +228,8 @@ void LibRetroPipeline::close() {
 
 	delete _shaderPreset;
 	_shaderPreset = nullptr;
+
+	_isAnimated = false;
 }
 
 static Common::FSNode getChildRecursive(const Common::FSNode &basePath, const Common::String &fileName) {


Commit: 29c25ed566fd3befa7605f2689974770f8c26619
    https://github.com/scummvm/scummvm/commit/29c25ed566fd3befa7605f2689974770f8c26619
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2022-11-06T20:02:59+01:00

Commit Message:
BACKENDS: OPENGL: Store projection matrix as a Matrix4

This avoids extraneous copies when dealing with Shader class.

Changed paths:
    backends/graphics/opengl/framebuffer.cpp
    backends/graphics/opengl/framebuffer.h
    backends/graphics/opengl/pipelines/fixed.cpp
    backends/graphics/opengl/pipelines/fixed.h
    backends/graphics/opengl/pipelines/libretro.cpp
    backends/graphics/opengl/pipelines/libretro.h
    backends/graphics/opengl/pipelines/pipeline.h
    backends/graphics/opengl/pipelines/shader.cpp
    backends/graphics/opengl/pipelines/shader.h


diff --git a/backends/graphics/opengl/framebuffer.cpp b/backends/graphics/opengl/framebuffer.cpp
index 969b02de060..4ca1a69752a 100644
--- a/backends/graphics/opengl/framebuffer.cpp
+++ b/backends/graphics/opengl/framebuffer.cpp
@@ -154,25 +154,25 @@ void Backbuffer::setDimensions(uint width, uint height) {
 	_viewport[3] = height;
 
 	// Setup orthogonal projection matrix.
-	_projectionMatrix[ 0] =  2.0f / width;
-	_projectionMatrix[ 1] =  0.0f;
-	_projectionMatrix[ 2] =  0.0f;
-	_projectionMatrix[ 3] =  0.0f;
-
-	_projectionMatrix[ 4] =  0.0f;
-	_projectionMatrix[ 5] = -2.0f / height;
-	_projectionMatrix[ 6] =  0.0f;
-	_projectionMatrix[ 7] =  0.0f;
-
-	_projectionMatrix[ 8] =  0.0f;
-	_projectionMatrix[ 9] =  0.0f;
-	_projectionMatrix[10] =  0.0f;
-	_projectionMatrix[11] =  0.0f;
-
-	_projectionMatrix[12] = -1.0f;
-	_projectionMatrix[13] =  1.0f;
-	_projectionMatrix[14] =  0.0f;
-	_projectionMatrix[15] =  1.0f;
+	_projectionMatrix(0, 0) =  2.0f / width;
+	_projectionMatrix(0, 1) =  0.0f;
+	_projectionMatrix(0, 2) =  0.0f;
+	_projectionMatrix(0, 3) =  0.0f;
+
+	_projectionMatrix(1, 0) =  0.0f;
+	_projectionMatrix(1, 1) = -2.0f / height;
+	_projectionMatrix(1, 2) =  0.0f;
+	_projectionMatrix(1, 3) =  0.0f;
+
+	_projectionMatrix(2, 0) =  0.0f;
+	_projectionMatrix(2, 1) =  0.0f;
+	_projectionMatrix(2, 2) =  0.0f;
+	_projectionMatrix(2, 3) =  0.0f;
+
+	_projectionMatrix(3, 0) = -1.0f;
+	_projectionMatrix(3, 1) =  1.0f;
+	_projectionMatrix(3, 2) =  0.0f;
+	_projectionMatrix(3, 3) =  1.0f;
 
 	// Directly apply changes when we are active.
 	if (isActive()) {
@@ -240,25 +240,25 @@ bool TextureTarget::setSize(uint width, uint height) {
 	_viewport[3] = texHeight;
 
 	// Setup orthogonal projection matrix.
-	_projectionMatrix[ 0] =  2.0f / texWidth;
-	_projectionMatrix[ 1] =  0.0f;
-	_projectionMatrix[ 2] =  0.0f;
-	_projectionMatrix[ 3] =  0.0f;
-
-	_projectionMatrix[ 4] =  0.0f;
-	_projectionMatrix[ 5] =  2.0f / texHeight;
-	_projectionMatrix[ 6] =  0.0f;
-	_projectionMatrix[ 7] =  0.0f;
-
-	_projectionMatrix[ 8] =  0.0f;
-	_projectionMatrix[ 9] =  0.0f;
-	_projectionMatrix[10] =  0.0f;
-	_projectionMatrix[11] =  0.0f;
-
-	_projectionMatrix[12] = -1.0f;
-	_projectionMatrix[13] = -1.0f;
-	_projectionMatrix[14] =  0.0f;
-	_projectionMatrix[15] =  1.0f;
+	_projectionMatrix(0, 0) =  2.0f / texWidth;
+	_projectionMatrix(0, 1) =  0.0f;
+	_projectionMatrix(0, 2) =  0.0f;
+	_projectionMatrix(0, 3) =  0.0f;
+
+	_projectionMatrix(1, 0) =  0.0f;
+	_projectionMatrix(1, 1) =  2.0f / texHeight;
+	_projectionMatrix(1, 2) =  0.0f;
+	_projectionMatrix(1, 3) =  0.0f;
+
+	_projectionMatrix(2, 0) =  0.0f;
+	_projectionMatrix(2, 1) =  0.0f;
+	_projectionMatrix(2, 2) =  0.0f;
+	_projectionMatrix(2, 3) =  0.0f;
+
+	_projectionMatrix(3, 0) = -1.0f;
+	_projectionMatrix(3, 1) = -1.0f;
+	_projectionMatrix(3, 2) =  0.0f;
+	_projectionMatrix(3, 3) =  1.0f;
 
 	// Directly apply changes when we are active.
 	if (isActive()) {
diff --git a/backends/graphics/opengl/framebuffer.h b/backends/graphics/opengl/framebuffer.h
index 914c01a253c..02ede375707 100644
--- a/backends/graphics/opengl/framebuffer.h
+++ b/backends/graphics/opengl/framebuffer.h
@@ -24,6 +24,8 @@
 
 #include "graphics/opengl/system_headers.h"
 
+#include "math/matrix4.h"
+
 namespace OpenGL {
 
 /**
@@ -82,14 +84,14 @@ public:
 	/**
 	 * Obtain projection matrix of the framebuffer.
 	 */
-	const GLfloat *getProjectionMatrix() const { return _projectionMatrix; }
+	const Math::Matrix4 &getProjectionMatrix() const { return _projectionMatrix; }
 protected:
 	bool isActive() const { return _isActive; }
 
 	GLint _viewport[4];
 	void applyViewport();
 
-	GLfloat _projectionMatrix[4*4];
+	Math::Matrix4 _projectionMatrix;
 	void applyProjectionMatrix();
 
 	/**
diff --git a/backends/graphics/opengl/pipelines/fixed.cpp b/backends/graphics/opengl/pipelines/fixed.cpp
index ab30d05d927..5e191d9f8e8 100644
--- a/backends/graphics/opengl/pipelines/fixed.cpp
+++ b/backends/graphics/opengl/pipelines/fixed.cpp
@@ -54,13 +54,13 @@ void FixedPipeline::drawTexture(const GLTexture &texture, const GLfloat *coordin
 	GL_CALL(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4));
 }
 
-void FixedPipeline::setProjectionMatrix(const GLfloat *projectionMatrix) {
+void FixedPipeline::setProjectionMatrix(const Math::Matrix4 &projectionMatrix) {
 	if (!isActive()) {
 		return;
 	}
 
 	GL_CALL(glMatrixMode(GL_PROJECTION));
-	GL_CALL(glLoadMatrixf(projectionMatrix));
+	GL_CALL(glLoadMatrixf(projectionMatrix.getData()));
 
 	GL_CALL(glMatrixMode(GL_MODELVIEW));
 	GL_CALL(glLoadIdentity());
diff --git a/backends/graphics/opengl/pipelines/fixed.h b/backends/graphics/opengl/pipelines/fixed.h
index d1adc02ae36..0aed601a22b 100644
--- a/backends/graphics/opengl/pipelines/fixed.h
+++ b/backends/graphics/opengl/pipelines/fixed.h
@@ -33,7 +33,7 @@ public:
 
 	virtual void drawTexture(const GLTexture &texture, const GLfloat *coordinates, const GLfloat *texcoords);
 
-	virtual void setProjectionMatrix(const GLfloat *projectionMatrix);
+	virtual void setProjectionMatrix(const Math::Matrix4 &projectionMatrix);
 
 protected:
 	virtual void activateInternal();
diff --git a/backends/graphics/opengl/pipelines/libretro.cpp b/backends/graphics/opengl/pipelines/libretro.cpp
index b04afca1940..479798d61a4 100644
--- a/backends/graphics/opengl/pipelines/libretro.cpp
+++ b/backends/graphics/opengl/pipelines/libretro.cpp
@@ -180,7 +180,7 @@ void LibRetroPipeline::drawTexture(const GLTexture &texture, const GLfloat *coor
 	_frameCount++;
 }
 
-void LibRetroPipeline::setProjectionMatrix(const GLfloat *projectionMatrix) {
+void LibRetroPipeline::setProjectionMatrix(const Math::Matrix4 &projectionMatrix) {
 	if (_applyProjectionChanges) {
 		ShaderPipeline::setProjectionMatrix(projectionMatrix);
 	}
@@ -489,9 +489,7 @@ bool LibRetroPipeline::setupFBOs() {
 		pass.vertexCoord[7] = (uint)sourceH;
 
 		// Set projection matrix in passes's shader.
-		Math::Matrix4 m4;
-		m4.setData(pass.target->getProjectionMatrix());
-		pass.shader->setUniform("MVPMatrix", m4);
+		pass.shader->setUniform("MVPMatrix", pass.target->getProjectionMatrix());
 	}
 	return true;
 }
diff --git a/backends/graphics/opengl/pipelines/libretro.h b/backends/graphics/opengl/pipelines/libretro.h
index 1452a66cfa7..a0c41b96553 100644
--- a/backends/graphics/opengl/pipelines/libretro.h
+++ b/backends/graphics/opengl/pipelines/libretro.h
@@ -54,7 +54,7 @@ public:
 
 	virtual void drawTexture(const GLTexture &texture, const GLfloat *coordinates, const GLfloat *texcoords);
 
-	virtual void setProjectionMatrix(const GLfloat *projectionMatrix);
+	virtual void setProjectionMatrix(const Math::Matrix4 &projectionMatrix);
 
 	bool open(const Common::FSNode &shaderPreset);
 	void close();
diff --git a/backends/graphics/opengl/pipelines/pipeline.h b/backends/graphics/opengl/pipelines/pipeline.h
index ee16d63f96a..72cf98f024a 100644
--- a/backends/graphics/opengl/pipelines/pipeline.h
+++ b/backends/graphics/opengl/pipelines/pipeline.h
@@ -26,6 +26,8 @@
 
 #include "backends/graphics/opengl/texture.h"
 
+#include "math/matrix4.h"
+
 namespace OpenGL {
 
 class Framebuffer;
@@ -127,7 +129,7 @@ public:
 	 *
 	 * This is intended to be only ever be used by Framebuffer subclasses.
 	 */
-	virtual void setProjectionMatrix(const GLfloat *projectionMatrix) = 0;
+	virtual void setProjectionMatrix(const Math::Matrix4 &projectionMatrix) = 0;
 
 protected:
 	/**
diff --git a/backends/graphics/opengl/pipelines/shader.cpp b/backends/graphics/opengl/pipelines/shader.cpp
index 6d0c3f14eb0..d4a6d7eb49d 100644
--- a/backends/graphics/opengl/pipelines/shader.cpp
+++ b/backends/graphics/opengl/pipelines/shader.cpp
@@ -87,10 +87,8 @@ void ShaderPipeline::drawTexture(const GLTexture &texture, const GLfloat *coordi
 	GL_CALL(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4));
 }
 
-void ShaderPipeline::setProjectionMatrix(const GLfloat *projectionMatrix) {
-	Math::Matrix4 m4;
-	m4.setData(projectionMatrix);
-	_activeShader->setUniform("projection", m4);
+void ShaderPipeline::setProjectionMatrix(const Math::Matrix4 &projectionMatrix) {
+	_activeShader->setUniform("projection", projectionMatrix);
 }
 #endif // !USE_FORCED_GLES
 
diff --git a/backends/graphics/opengl/pipelines/shader.h b/backends/graphics/opengl/pipelines/shader.h
index dc8d365c494..39483aa51e1 100644
--- a/backends/graphics/opengl/pipelines/shader.h
+++ b/backends/graphics/opengl/pipelines/shader.h
@@ -38,7 +38,7 @@ public:
 
 	virtual void drawTexture(const GLTexture &texture, const GLfloat *coordinates, const GLfloat *texcoords);
 
-	virtual void setProjectionMatrix(const GLfloat *projectionMatrix);
+	virtual void setProjectionMatrix(const Math::Matrix4 &projectionMatrix);
 
 protected:
 	virtual void activateInternal();


Commit: 9b951944bcc242b874c91c0cfd544632b1c6f49a
    https://github.com/scummvm/scummvm/commit/9b951944bcc242b874c91c0cfd544632b1c6f49a
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2022-11-06T20:02:59+01:00

Commit Message:
BACKENDS: OPENGL: Activate framebuffer with a specific pipeline

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


diff --git a/backends/graphics/opengl/framebuffer.cpp b/backends/graphics/opengl/framebuffer.cpp
index 4ca1a69752a..e830acd3d0e 100644
--- a/backends/graphics/opengl/framebuffer.cpp
+++ b/backends/graphics/opengl/framebuffer.cpp
@@ -20,19 +20,20 @@
  */
 
 #include "backends/graphics/opengl/framebuffer.h"
-#include "backends/graphics/opengl/texture.h"
 #include "backends/graphics/opengl/pipelines/pipeline.h"
+#include "backends/graphics/opengl/texture.h"
 #include "graphics/opengl/debug.h"
 
 namespace OpenGL {
 
 Framebuffer::Framebuffer()
-	: _viewport(), _projectionMatrix(), _isActive(false), _clearColor(),
+	: _viewport(), _projectionMatrix(), _pipeline(nullptr), _clearColor(),
 	  _blendState(kBlendModeDisabled), _scissorTestState(false), _scissorBox() {
 }
 
-void Framebuffer::activate() {
-	_isActive = true;
+void Framebuffer::activate(Pipeline *pipeline) {
+	assert(pipeline);
+	_pipeline = pipeline;
 
 	applyViewport();
 	applyProjectionMatrix();
@@ -45,9 +46,9 @@ void Framebuffer::activate() {
 }
 
 void Framebuffer::deactivate() {
-	_isActive = false;
-
 	deactivateInternal();
+
+	_pipeline = nullptr;
 }
 
 void Framebuffer::setClearColor(GLfloat r, GLfloat g, GLfloat b, GLfloat a) {
@@ -97,7 +98,8 @@ void Framebuffer::applyViewport() {
 }
 
 void Framebuffer::applyProjectionMatrix() {
-	Pipeline::getActivePipeline()->setProjectionMatrix(_projectionMatrix);
+	assert(_pipeline);
+	_pipeline->setProjectionMatrix(_projectionMatrix);
 }
 
 void Framebuffer::applyClearColor() {
diff --git a/backends/graphics/opengl/framebuffer.h b/backends/graphics/opengl/framebuffer.h
index 02ede375707..c0724e7366c 100644
--- a/backends/graphics/opengl/framebuffer.h
+++ b/backends/graphics/opengl/framebuffer.h
@@ -28,11 +28,12 @@
 
 namespace OpenGL {
 
+class Pipeline;
+
 /**
  * Object describing a framebuffer OpenGL can render to.
  */
 class Framebuffer {
-	friend class Pipeline;
 public:
 	Framebuffer();
 	virtual ~Framebuffer() {};
@@ -86,7 +87,7 @@ public:
 	 */
 	const Math::Matrix4 &getProjectionMatrix() const { return _projectionMatrix; }
 protected:
-	bool isActive() const { return _isActive; }
+	bool isActive() const { return _pipeline != nullptr; }
 
 	GLint _viewport[4];
 	void applyViewport();
@@ -109,11 +110,11 @@ protected:
 	 */
 	virtual void deactivateInternal() {}
 
-private:
+public:
 	/**
 	 * Accessor to activate framebuffer for pipeline.
 	 */
-	void activate();
+	void activate(Pipeline *pipeline);
 
 	/**
 	 * Accessor to deactivate framebuffer from pipeline.
@@ -121,7 +122,7 @@ private:
 	void deactivate();
 
 private:
-	bool _isActive;
+	Pipeline *_pipeline;
 
 	GLfloat _clearColor[4];
 	void applyClearColor();
diff --git a/backends/graphics/opengl/pipelines/pipeline.cpp b/backends/graphics/opengl/pipelines/pipeline.cpp
index 815d93924f6..6541adde08e 100644
--- a/backends/graphics/opengl/pipelines/pipeline.cpp
+++ b/backends/graphics/opengl/pipelines/pipeline.cpp
@@ -34,7 +34,7 @@ void Pipeline::activate() {
 	_isActive = true;
 
 	if (_activeFramebuffer) {
-		_activeFramebuffer->activate();
+		_activeFramebuffer->activate(this);
 	}
 
 	activateInternal();
@@ -58,7 +58,7 @@ Framebuffer *Pipeline::setFramebuffer(Framebuffer *framebuffer) {
 
 	_activeFramebuffer = framebuffer;
 	if (_isActive && _activeFramebuffer) {
-		_activeFramebuffer->activate();
+		_activeFramebuffer->activate(this);
 	}
 
 	return oldFramebuffer;
diff --git a/backends/graphics/opengl/pipelines/pipeline.h b/backends/graphics/opengl/pipelines/pipeline.h
index 72cf98f024a..4861b5bc767 100644
--- a/backends/graphics/opengl/pipelines/pipeline.h
+++ b/backends/graphics/opengl/pipelines/pipeline.h
@@ -24,6 +24,7 @@
 
 #include "graphics/opengl/system_headers.h"
 
+#include "backends/graphics/opengl/framebuffer.h"
 #include "backends/graphics/opengl/texture.h"
 
 #include "math/matrix4.h"


Commit: 769fe03a4b035eb7a641c9f4d2c239fbdc97069e
    https://github.com/scummvm/scummvm/commit/769fe03a4b035eb7a641c9f4d2c239fbdc97069e
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2022-11-06T20:02:59+01:00

Commit Message:
BACKENDS: OPENGL: Use override keyword

Changed paths:
    backends/graphics/opengl/framebuffer.h
    backends/graphics/opengl/pipelines/clut8.h
    backends/graphics/opengl/pipelines/fixed.h
    backends/graphics/opengl/pipelines/libretro.h
    backends/graphics/opengl/pipelines/shader.h
    backends/graphics/opengl/texture.h


diff --git a/backends/graphics/opengl/framebuffer.h b/backends/graphics/opengl/framebuffer.h
index c0724e7366c..7b34bf188fd 100644
--- a/backends/graphics/opengl/framebuffer.h
+++ b/backends/graphics/opengl/framebuffer.h
@@ -148,7 +148,7 @@ public:
 	void setDimensions(uint width, uint height);
 
 protected:
-	virtual void activateInternal();
+	void activateInternal() override;
 };
 
 #if !USE_FORCED_GLES
@@ -163,7 +163,7 @@ class GLTexture;
 class TextureTarget : public Framebuffer {
 public:
 	TextureTarget();
-	virtual ~TextureTarget();
+	~TextureTarget() override;
 
 	/**
 	 * Notify that the GL context is about to be destroyed.
@@ -186,7 +186,7 @@ public:
 	GLTexture *getTexture() const { return _texture; }
 
 protected:
-	virtual void activateInternal();
+	void activateInternal() override;
 
 private:
 	GLTexture *_texture;
diff --git a/backends/graphics/opengl/pipelines/clut8.h b/backends/graphics/opengl/pipelines/clut8.h
index 532db3e91ea..4cd87db3c33 100644
--- a/backends/graphics/opengl/pipelines/clut8.h
+++ b/backends/graphics/opengl/pipelines/clut8.h
@@ -33,7 +33,7 @@ public:
 
 	void setPaletteTexture(const GLTexture *paletteTexture) { _paletteTexture = paletteTexture; }
 
-	virtual void drawTexture(const GLTexture &texture, const GLfloat *coordinates, const GLfloat *texcoords);
+	void drawTexture(const GLTexture &texture, const GLfloat *coordinates, const GLfloat *texcoords) override;
 
 private:
 	const GLTexture *_paletteTexture;
diff --git a/backends/graphics/opengl/pipelines/fixed.h b/backends/graphics/opengl/pipelines/fixed.h
index 0aed601a22b..3b97bca9652 100644
--- a/backends/graphics/opengl/pipelines/fixed.h
+++ b/backends/graphics/opengl/pipelines/fixed.h
@@ -29,14 +29,14 @@ namespace OpenGL {
 #if !USE_FORCED_GLES2
 class FixedPipeline : public Pipeline {
 public:
-	virtual void setColor(GLfloat r, GLfloat g, GLfloat b, GLfloat a);
+	void setColor(GLfloat r, GLfloat g, GLfloat b, GLfloat a) override;
 
-	virtual void drawTexture(const GLTexture &texture, const GLfloat *coordinates, const GLfloat *texcoords);
+	void drawTexture(const GLTexture &texture, const GLfloat *coordinates, const GLfloat *texcoords) override;
 
-	virtual void setProjectionMatrix(const Math::Matrix4 &projectionMatrix);
+	void setProjectionMatrix(const Math::Matrix4 &projectionMatrix) override;
 
 protected:
-	virtual void activateInternal();
+	void activateInternal() override;
 };
 #endif // !USE_FORCED_GLES2
 
diff --git a/backends/graphics/opengl/pipelines/libretro.h b/backends/graphics/opengl/pipelines/libretro.h
index a0c41b96553..4b449ef0367 100644
--- a/backends/graphics/opengl/pipelines/libretro.h
+++ b/backends/graphics/opengl/pipelines/libretro.h
@@ -50,11 +50,11 @@ class LibRetroPipeline : public ShaderPipeline {
 public:
 	LibRetroPipeline();
 	LibRetroPipeline(const Common::FSNode &shaderPreset);
-	virtual ~LibRetroPipeline();
+	~LibRetroPipeline() override;
 
-	virtual void drawTexture(const GLTexture &texture, const GLfloat *coordinates, const GLfloat *texcoords);
+	void drawTexture(const GLTexture &texture, const GLfloat *coordinates, const GLfloat *texcoords) override;
 
-	virtual void setProjectionMatrix(const Math::Matrix4 &projectionMatrix);
+	void setProjectionMatrix(const Math::Matrix4 &projectionMatrix) override;
 
 	bool open(const Common::FSNode &shaderPreset);
 	void close();
@@ -68,8 +68,8 @@ public:
 			&& OpenGLContext.framebufferObjectSupported;
 	}
 private:
-	virtual void activateInternal();
-	virtual void deactivateInternal();
+	void activateInternal() override;
+	void deactivateInternal() override;
 
 	bool loadTextures();
 	bool loadPasses();
diff --git a/backends/graphics/opengl/pipelines/shader.h b/backends/graphics/opengl/pipelines/shader.h
index 39483aa51e1..c0f6ca4797d 100644
--- a/backends/graphics/opengl/pipelines/shader.h
+++ b/backends/graphics/opengl/pipelines/shader.h
@@ -32,17 +32,17 @@ class Shader;
 class ShaderPipeline : public Pipeline {
 public:
 	ShaderPipeline(Shader *shader);
-	~ShaderPipeline();
+	~ShaderPipeline() override;
 
-	virtual void setColor(GLfloat r, GLfloat g, GLfloat b, GLfloat a);
+	void setColor(GLfloat r, GLfloat g, GLfloat b, GLfloat a) override;
 
-	virtual void drawTexture(const GLTexture &texture, const GLfloat *coordinates, const GLfloat *texcoords);
+	void drawTexture(const GLTexture &texture, const GLfloat *coordinates, const GLfloat *texcoords) override;
 
-	virtual void setProjectionMatrix(const Math::Matrix4 &projectionMatrix);
+	void setProjectionMatrix(const Math::Matrix4 &projectionMatrix) override;
 
 protected:
-	virtual void activateInternal();
-	virtual void deactivateInternal();
+	void activateInternal() override;
+	void deactivateInternal() override;
 
 	GLuint _coordsVBO;
 	GLuint _texcoordsVBO;
diff --git a/backends/graphics/opengl/texture.h b/backends/graphics/opengl/texture.h
index 58f6cd397fe..3ba19d0c1fd 100644
--- a/backends/graphics/opengl/texture.h
+++ b/backends/graphics/opengl/texture.h
@@ -279,29 +279,29 @@ public:
 	 * @param format      The format used for the texture input.
 	 */
 	Texture(GLenum glIntFormat, GLenum glFormat, GLenum glType, const Graphics::PixelFormat &format);
-	virtual ~Texture();
+	~Texture() override;
 
-	virtual void destroy();
+	void destroy() override;
 
-	virtual void recreate();
+	void recreate() override;
 
-	virtual void enableLinearFiltering(bool enable);
+	void enableLinearFiltering(bool enable) override;
 
-	virtual void allocate(uint width, uint height);
+	void allocate(uint width, uint height) override;
 
-	virtual uint getWidth() const { return _userPixelData.w; }
-	virtual uint getHeight() const { return _userPixelData.h; }
+	uint getWidth() const override { return _userPixelData.w; }
+	uint getHeight() const override { return _userPixelData.h; }
 
 	/**
 	 * @return The logical format of the texture data.
 	 */
-	virtual Graphics::PixelFormat getFormat() const { return _format; }
+	Graphics::PixelFormat getFormat() const override { return _format; }
 
-	virtual Graphics::Surface *getSurface() { return &_userPixelData; }
-	virtual const Graphics::Surface *getSurface() const { return &_userPixelData; }
+	Graphics::Surface *getSurface() override { return &_userPixelData; }
+	const Graphics::Surface *getSurface() const override { return &_userPixelData; }
 
-	virtual void updateGLTexture();
-	virtual const GLTexture &getGLTexture() const { return _glTexture; }
+	void updateGLTexture() override;
+	const GLTexture &getGLTexture() const override { return _glTexture; }
 protected:
 	const Graphics::PixelFormat _format;
 
@@ -317,21 +317,21 @@ private:
 class FakeTexture : public Texture {
 public:
 	FakeTexture(GLenum glIntFormat, GLenum glFormat, GLenum glType, const Graphics::PixelFormat &format, const Graphics::PixelFormat &fakeFormat);
-	virtual ~FakeTexture();
+	~FakeTexture() override;
 
-	virtual void allocate(uint width, uint height);
+	void allocate(uint width, uint height) override;
 
-	virtual Graphics::PixelFormat getFormat() const { return _fakeFormat; }
+	Graphics::PixelFormat getFormat() const override { return _fakeFormat; }
 
-	virtual bool hasPalette() const { return (_palette != nullptr); }
+	bool hasPalette() const override { return (_palette != nullptr); }
 
-	virtual void setColorKey(uint colorKey);
-	virtual void setPalette(uint start, uint colors, const byte *palData);
+	void setColorKey(uint colorKey) override;
+	void setPalette(uint start, uint colors, const byte *palData) override;
 
-	virtual Graphics::Surface *getSurface() { return &_rgbData; }
-	virtual const Graphics::Surface *getSurface() const { return &_rgbData; }
+	Graphics::Surface *getSurface() override { return &_rgbData; }
+	const Graphics::Surface *getSurface() const override { return &_rgbData; }
 
-	virtual void updateGLTexture();
+	void updateGLTexture() override;
 protected:
 	Graphics::Surface _rgbData;
 	Graphics::PixelFormat _fakeFormat;
@@ -341,39 +341,39 @@ protected:
 class TextureRGB555 : public FakeTexture {
 public:
 	TextureRGB555();
-	virtual ~TextureRGB555() {};
+	~TextureRGB555() override {}
 
-	virtual void updateGLTexture();
+	void updateGLTexture() override;
 };
 
 class TextureRGBA8888Swap : public FakeTexture {
 public:
 	TextureRGBA8888Swap();
-	virtual ~TextureRGBA8888Swap() {};
+	~TextureRGBA8888Swap() override {}
 
-	virtual void updateGLTexture();
+	void updateGLTexture() override;
 };
 
 #ifdef USE_SCALERS
 class ScaledTexture : public FakeTexture {
 public:
 	ScaledTexture(GLenum glIntFormat, GLenum glFormat, GLenum glType, const Graphics::PixelFormat &format, const Graphics::PixelFormat &fakeFormat);
-	virtual ~ScaledTexture();
+	~ScaledTexture() override;
 
-	virtual void allocate(uint width, uint height);
+	void allocate(uint width, uint height) override;
 
-	virtual uint getWidth() const { return _rgbData.w; }
-	virtual uint getHeight() const { return _rgbData.h; }
-	virtual Graphics::PixelFormat getFormat() const { return _fakeFormat; }
+	uint getWidth() const override { return _rgbData.w; }
+	uint getHeight() const override { return _rgbData.h; }
+	Graphics::PixelFormat getFormat() const override { return _fakeFormat; }
 
-	virtual bool hasPalette() const { return (_palette != nullptr); }
+	bool hasPalette() const override { return (_palette != nullptr); }
 
-	virtual Graphics::Surface *getSurface() { return &_rgbData; }
-	virtual const Graphics::Surface *getSurface() const { return &_rgbData; }
+	Graphics::Surface *getSurface() override { return &_rgbData; }
+	const Graphics::Surface *getSurface() const override { return &_rgbData; }
 
-	virtual void updateGLTexture();
+	void updateGLTexture() override;
 
-	virtual void setScaler(uint scalerIndex, int scaleFactor);
+	void setScaler(uint scalerIndex, int scaleFactor) override;
 protected:
 	Graphics::Surface *_convData;
 	Scaler *_scaler;
@@ -390,33 +390,33 @@ class CLUT8LookUpPipeline;
 class TextureCLUT8GPU : public Surface {
 public:
 	TextureCLUT8GPU();
-	virtual ~TextureCLUT8GPU();
+	~TextureCLUT8GPU() override;
 
-	virtual void destroy();
+	void destroy() override;
 
-	virtual void recreate();
+	void recreate() override;
 
-	virtual void enableLinearFiltering(bool enable);
+	void enableLinearFiltering(bool enable) override;
 
-	virtual void allocate(uint width, uint height);
+	void allocate(uint width, uint height) override;
 
-	virtual bool isDirty() const { return _paletteDirty || Surface::isDirty(); }
+	bool isDirty() const override { return _paletteDirty || Surface::isDirty(); }
 
-	virtual uint getWidth() const { return _userPixelData.w; }
-	virtual uint getHeight() const { return _userPixelData.h; }
+	uint getWidth() const override { return _userPixelData.w; }
+	uint getHeight() const override { return _userPixelData.h; }
 
-	virtual Graphics::PixelFormat getFormat() const;
+	Graphics::PixelFormat getFormat() const override;
 
-	virtual bool hasPalette() const { return true; }
+	bool hasPalette() const override { return true; }
 
-	virtual void setColorKey(uint colorKey);
-	virtual void setPalette(uint start, uint colors, const byte *palData);
+	void setColorKey(uint colorKey) override;
+	void setPalette(uint start, uint colors, const byte *palData) override;
 
-	virtual Graphics::Surface *getSurface() { return &_userPixelData; }
-	virtual const Graphics::Surface *getSurface() const { return &_userPixelData; }
+	Graphics::Surface *getSurface() override { return &_userPixelData; }
+	const Graphics::Surface *getSurface() const override { return &_userPixelData; }
 
-	virtual void updateGLTexture();
-	virtual const GLTexture &getGLTexture() const;
+	void updateGLTexture() override;
+	const GLTexture &getGLTexture() const override;
 
 	static bool isSupportedByContext() {
 		return OpenGLContext.shadersSupported


Commit: 239c115249763d5520538547dac2d6f87e389a4b
    https://github.com/scummvm/scummvm/commit/239c115249763d5520538547dac2d6f87e389a4b
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2022-11-06T20:02:59+01:00

Commit Message:
BACKENDS: OPENGL: Rename drawTexture override

This prevents name hiding when using directly a subclass of Pipeline

Changed paths:
    backends/graphics/opengl/pipelines/clut8.cpp
    backends/graphics/opengl/pipelines/clut8.h
    backends/graphics/opengl/pipelines/fixed.cpp
    backends/graphics/opengl/pipelines/fixed.h
    backends/graphics/opengl/pipelines/libretro.cpp
    backends/graphics/opengl/pipelines/libretro.h
    backends/graphics/opengl/pipelines/pipeline.h
    backends/graphics/opengl/pipelines/shader.cpp
    backends/graphics/opengl/pipelines/shader.h


diff --git a/backends/graphics/opengl/pipelines/clut8.cpp b/backends/graphics/opengl/pipelines/clut8.cpp
index 0d8a587847b..09707b258b8 100644
--- a/backends/graphics/opengl/pipelines/clut8.cpp
+++ b/backends/graphics/opengl/pipelines/clut8.cpp
@@ -31,7 +31,7 @@ CLUT8LookUpPipeline::CLUT8LookUpPipeline()
 	: ShaderPipeline(ShaderMan.query(ShaderManager::kCLUT8LookUp)), _paletteTexture(nullptr) {
 }
 
-void CLUT8LookUpPipeline::drawTexture(const GLTexture &texture, const GLfloat *coordinates, const GLfloat *texcoords) {
+void CLUT8LookUpPipeline::drawTextureInternal(const GLTexture &texture, const GLfloat *coordinates, const GLfloat *texcoords) {
 	// Set the palette texture.
 	GL_CALL(glActiveTexture(GL_TEXTURE1));
 	if (_paletteTexture) {
@@ -39,7 +39,7 @@ void CLUT8LookUpPipeline::drawTexture(const GLTexture &texture, const GLfloat *c
 	}
 
 	GL_CALL(glActiveTexture(GL_TEXTURE0));
-	ShaderPipeline::drawTexture(texture, coordinates, texcoords);
+	ShaderPipeline::drawTextureInternal(texture, coordinates, texcoords);
 }
 #endif // !USE_FORCED_GLES
 
diff --git a/backends/graphics/opengl/pipelines/clut8.h b/backends/graphics/opengl/pipelines/clut8.h
index 4cd87db3c33..1b19a0ad5e3 100644
--- a/backends/graphics/opengl/pipelines/clut8.h
+++ b/backends/graphics/opengl/pipelines/clut8.h
@@ -33,7 +33,8 @@ public:
 
 	void setPaletteTexture(const GLTexture *paletteTexture) { _paletteTexture = paletteTexture; }
 
-	void drawTexture(const GLTexture &texture, const GLfloat *coordinates, const GLfloat *texcoords) override;
+protected:
+	void drawTextureInternal(const GLTexture &texture, const GLfloat *coordinates, const GLfloat *texcoords) override;
 
 private:
 	const GLTexture *_paletteTexture;
diff --git a/backends/graphics/opengl/pipelines/fixed.cpp b/backends/graphics/opengl/pipelines/fixed.cpp
index 5e191d9f8e8..e0de0ab7127 100644
--- a/backends/graphics/opengl/pipelines/fixed.cpp
+++ b/backends/graphics/opengl/pipelines/fixed.cpp
@@ -46,7 +46,7 @@ void FixedPipeline::setColor(GLfloat r, GLfloat g, GLfloat b, GLfloat a) {
 	GL_CALL(glColor4f(r, g, b, a));
 }
 
-void FixedPipeline::drawTexture(const GLTexture &texture, const GLfloat *coordinates, const GLfloat *texcoords) {
+void FixedPipeline::drawTextureInternal(const GLTexture &texture, const GLfloat *coordinates, const GLfloat *texcoords) {
 	texture.bind();
 
 	GL_CALL(glTexCoordPointer(2, GL_FLOAT, 0, texcoords));
diff --git a/backends/graphics/opengl/pipelines/fixed.h b/backends/graphics/opengl/pipelines/fixed.h
index 3b97bca9652..5b4f1509297 100644
--- a/backends/graphics/opengl/pipelines/fixed.h
+++ b/backends/graphics/opengl/pipelines/fixed.h
@@ -31,12 +31,11 @@ class FixedPipeline : public Pipeline {
 public:
 	void setColor(GLfloat r, GLfloat g, GLfloat b, GLfloat a) override;
 
-	void drawTexture(const GLTexture &texture, const GLfloat *coordinates, const GLfloat *texcoords) override;
-
 	void setProjectionMatrix(const Math::Matrix4 &projectionMatrix) override;
 
 protected:
 	void activateInternal() override;
+	void drawTextureInternal(const GLTexture &texture, const GLfloat *coordinates, const GLfloat *texcoords) override;
 };
 #endif // !USE_FORCED_GLES2
 
diff --git a/backends/graphics/opengl/pipelines/libretro.cpp b/backends/graphics/opengl/pipelines/libretro.cpp
index 479798d61a4..9b07c5d4858 100644
--- a/backends/graphics/opengl/pipelines/libretro.cpp
+++ b/backends/graphics/opengl/pipelines/libretro.cpp
@@ -134,7 +134,7 @@ LibRetroPipeline::~LibRetroPipeline() {
 	close();
 }
 
-void LibRetroPipeline::drawTexture(const GLTexture &texture, const GLfloat *coordinates, const GLfloat *texcoords) {
+void LibRetroPipeline::drawTextureInternal(const GLTexture &texture, const GLfloat *coordinates, const GLfloat *texcoords) {
 	Framebuffer *const targetBuffer = _activeFramebuffer;
 
 	// Set input texture for 1st pass to texture to draw.
@@ -174,7 +174,7 @@ void LibRetroPipeline::drawTexture(const GLTexture &texture, const GLfloat *coor
 	_applyProjectionChanges = false;
 
 	ShaderPipeline::activateInternal();
-	ShaderPipeline::drawTexture(*_passes[_passes.size() - 1].target->getTexture(), coordinates, texcoords);
+	ShaderPipeline::drawTextureInternal(*_passes[_passes.size() - 1].target->getTexture(), coordinates, texcoords);
 	ShaderPipeline::deactivateInternal();
 
 	_frameCount++;
diff --git a/backends/graphics/opengl/pipelines/libretro.h b/backends/graphics/opengl/pipelines/libretro.h
index 4b449ef0367..e425476fc45 100644
--- a/backends/graphics/opengl/pipelines/libretro.h
+++ b/backends/graphics/opengl/pipelines/libretro.h
@@ -52,8 +52,6 @@ public:
 	LibRetroPipeline(const Common::FSNode &shaderPreset);
 	~LibRetroPipeline() override;
 
-	void drawTexture(const GLTexture &texture, const GLfloat *coordinates, const GLfloat *texcoords) override;
-
 	void setProjectionMatrix(const Math::Matrix4 &projectionMatrix) override;
 
 	bool open(const Common::FSNode &shaderPreset);
@@ -70,6 +68,7 @@ public:
 private:
 	void activateInternal() override;
 	void deactivateInternal() override;
+	void drawTextureInternal(const GLTexture &texture, const GLfloat *coordinates, const GLfloat *texcoords) override;
 
 	bool loadTextures();
 	bool loadPasses();
diff --git a/backends/graphics/opengl/pipelines/pipeline.h b/backends/graphics/opengl/pipelines/pipeline.h
index 4861b5bc767..a388c9422ea 100644
--- a/backends/graphics/opengl/pipelines/pipeline.h
+++ b/backends/graphics/opengl/pipelines/pipeline.h
@@ -83,23 +83,25 @@ public:
 	 * @param texture     Texture to use for drawing.
 	 * @param coordinates x1, y1, x2, y2 coordinates where to draw the texture.
 	 */
-	virtual void drawTexture(const GLTexture &texture, const GLfloat *coordinates, const GLfloat *texcoords) = 0;
+	inline void drawTexture(const GLTexture &texture, const GLfloat *coordinates, const GLfloat *texcoords) {
+		drawTextureInternal(texture, coordinates, texcoords);
+	}
 
-	void drawTexture(const GLTexture &texture, const GLfloat *coordinates) {
-		drawTexture(texture, coordinates, texture.getTexCoords());
+	inline void drawTexture(const GLTexture &texture, const GLfloat *coordinates) {
+		drawTextureInternal(texture, coordinates, texture.getTexCoords());
 	}
 
-	void drawTexture(const GLTexture &texture, GLfloat x, GLfloat y, GLfloat w, GLfloat h) {
+	inline void drawTexture(const GLTexture &texture, GLfloat x, GLfloat y, GLfloat w, GLfloat h) {
 		const GLfloat coordinates[4*2] = {
 			x,     y,
 			x + w, y,
 			x,     y + h,
 			x + w, y + h
 		};
-		drawTexture(texture, coordinates, texture.getTexCoords());
+		drawTextureInternal(texture, coordinates, texture.getTexCoords());
 	}
 
-	void drawTexture(const GLTexture &texture, GLfloat x, GLfloat y, GLfloat w, GLfloat h, const Common::Rect &clip) {
+	inline void drawTexture(const GLTexture &texture, GLfloat x, GLfloat y, GLfloat w, GLfloat h, const Common::Rect &clip) {
 		const GLfloat coordinates[4*2] = {
 			x,     y,
 			x + w, y,
@@ -122,7 +124,7 @@ public:
 			(float)clip.right / tw, (float)clip.bottom / th
 		};
 
-		drawTexture(texture, coordinates, texcoords);
+		drawTextureInternal(texture, coordinates, texcoords);
 	}
 
 	/**
@@ -146,6 +148,8 @@ protected:
 	 */
 	virtual void deactivateInternal() {}
 
+	virtual void drawTextureInternal(const GLTexture &texture, const GLfloat *coordinates, const GLfloat *texcoords) = 0;
+
 	bool isActive() const { return _isActive; }
 
 	Framebuffer *_activeFramebuffer;
diff --git a/backends/graphics/opengl/pipelines/shader.cpp b/backends/graphics/opengl/pipelines/shader.cpp
index d4a6d7eb49d..62367b29ca1 100644
--- a/backends/graphics/opengl/pipelines/shader.cpp
+++ b/backends/graphics/opengl/pipelines/shader.cpp
@@ -75,7 +75,7 @@ void ShaderPipeline::setColor(GLfloat r, GLfloat g, GLfloat b, GLfloat a) {
 	}
 }
 
-void ShaderPipeline::drawTexture(const GLTexture &texture, const GLfloat *coordinates, const GLfloat *texcoords) {
+void ShaderPipeline::drawTextureInternal(const GLTexture &texture, const GLfloat *coordinates, const GLfloat *texcoords) {
 	texture.bind();
 
 	GL_CALL(glBindBuffer(GL_ARRAY_BUFFER, _coordsVBO));
diff --git a/backends/graphics/opengl/pipelines/shader.h b/backends/graphics/opengl/pipelines/shader.h
index c0f6ca4797d..6a217d2bb1b 100644
--- a/backends/graphics/opengl/pipelines/shader.h
+++ b/backends/graphics/opengl/pipelines/shader.h
@@ -36,13 +36,12 @@ public:
 
 	void setColor(GLfloat r, GLfloat g, GLfloat b, GLfloat a) override;
 
-	void drawTexture(const GLTexture &texture, const GLfloat *coordinates, const GLfloat *texcoords) override;
-
 	void setProjectionMatrix(const Math::Matrix4 &projectionMatrix) override;
 
 protected:
 	void activateInternal() override;
 	void deactivateInternal() override;
+	void drawTextureInternal(const GLTexture &texture, const GLfloat *coordinates, const GLfloat *texcoords) override;
 
 	GLuint _coordsVBO;
 	GLuint _texcoordsVBO;


Commit: 6632e909dac00fb04fdd365557fa3ceb1b4b4d30
    https://github.com/scummvm/scummvm/commit/6632e909dac00fb04fdd365557fa3ceb1b4b4d30
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2022-11-06T20:02:59+01:00

Commit Message:
BACKENDS: OPENGL: Hide active pipeline and activate it as needed

This removes the idea of global pipeline.
The activePipeline is kept for pipeline lifecycle management only.

Changed paths:
    backends/graphics/android/android-graphics.cpp
    backends/graphics/opengl/opengl-graphics.cpp
    backends/graphics/opengl/opengl-graphics.h
    backends/graphics/opengl/pipelines/clut8.cpp
    backends/graphics/opengl/pipelines/fixed.cpp
    backends/graphics/opengl/pipelines/fixed.h
    backends/graphics/opengl/pipelines/pipeline.cpp
    backends/graphics/opengl/pipelines/pipeline.h
    backends/graphics/opengl/pipelines/shader.cpp
    backends/graphics/opengl/texture.cpp


diff --git a/backends/graphics/android/android-graphics.cpp b/backends/graphics/android/android-graphics.cpp
index 2541d8c3210..f4499b04571 100644
--- a/backends/graphics/android/android-graphics.cpp
+++ b/backends/graphics/android/android-graphics.cpp
@@ -206,8 +206,10 @@ void AndroidGraphicsManager::refreshScreen() {
 
 void AndroidGraphicsManager::touchControlDraw(int16 x, int16 y, int16 w, int16 h, const Common::Rect &clip) {
 	_backBuffer.enableBlend(OpenGL::Framebuffer::kBlendModeTraditionalTransparency);
-	OpenGL::Pipeline::getActivePipeline()->drawTexture(_touchcontrols->getGLTexture(),
-	                                                   x, y, w, h, clip);
+	OpenGL::Pipeline *pipeline = getPipeline();
+	pipeline->activate();
+	pipeline->drawTexture(_touchcontrols->getGLTexture(),
+	                      x, y, w, h, clip);
 }
 
 void AndroidGraphicsManager::touchControlNotifyChanged() {
diff --git a/backends/graphics/opengl/opengl-graphics.cpp b/backends/graphics/opengl/opengl-graphics.cpp
index 40383a9cac6..f6cc5ce27ec 100644
--- a/backends/graphics/opengl/opengl-graphics.cpp
+++ b/backends/graphics/opengl/opengl-graphics.cpp
@@ -638,6 +638,8 @@ void OpenGLGraphicsManager::updateScreen() {
 	}
 	_overlay->updateGLTexture();
 
+	_pipeline->activate();
+
 	// Clear the screen buffer.
 	GL_CALL(glClear(GL_COLOR_BUFFER_BIT));
 
@@ -656,12 +658,15 @@ void OpenGLGraphicsManager::updateScreen() {
 	// First step: Draw the (virtual) game screen.
 #if !USE_FORCED_GLES
 	if (_libretroPipeline && _libretroPipeline->isInitialized()) {
-		Framebuffer *lastFramebuffer = Pipeline::getActivePipeline()->setFramebuffer(_gameScreenTarget);
+		// Use the ShaderPipeline to draw the game screen and game cursor
+		_pipeline->setFramebuffer(_gameScreenTarget);
+
 		_gameScreenTarget->enableBlend(Framebuffer::kBlendModeDisabled);
+
 		const GLTexture &gameScreenTexture = _gameScreen->getGLTexture();
 		const uint retroWidth = gameScreenTexture.getLogicalWidth(),
 		           retroHeight = gameScreenTexture.getLogicalHeight();
-		Pipeline::getActivePipeline()->drawTexture(gameScreenTexture, 0, 0, retroWidth, retroHeight);
+		_pipeline->drawTexture(gameScreenTexture, 0, 0, retroWidth, retroHeight);
 
 		// Draw the cursor if necessary.
 		// If overlay is visible we draw it later to have the cursor above overlay
@@ -678,18 +683,20 @@ void OpenGLGraphicsManager::updateScreen() {
 					   cursorHeight = cursorTexture.getLogicalHeight();
 
 			_gameScreenTarget->enableBlend(Framebuffer::kBlendModePremultipliedTransparency);
-			Pipeline::getActivePipeline()->drawTexture(cursorTexture, gameScreenCursorX, gameScreenCursorY, cursorWidth, cursorHeight);
+			_pipeline->drawTexture(cursorTexture, gameScreenCursorX, gameScreenCursorY, cursorWidth, cursorHeight);
 			needsCursor = false;
 		}
-		Pipeline::getActivePipeline()->setFramebuffer(lastFramebuffer);
 
-		Pipeline *lastPipeline = Pipeline::setPipeline(_libretroPipeline);
-		Pipeline::getActivePipeline()->drawTexture(*_gameScreenTarget->getTexture(), _gameDrawRect.left, _gameDrawRect.top, _gameDrawRect.width(), _gameDrawRect.height());
-		Pipeline::setPipeline(lastPipeline);
+		_libretroPipeline->activate();
+		_libretroPipeline->drawTexture(*_gameScreenTarget->getTexture(), _gameDrawRect.left, _gameDrawRect.top, _gameDrawRect.width(), _gameDrawRect.height());
+
+		// Restore ShaderPipeline for the next steps
+		_pipeline->setFramebuffer(&_backBuffer);
+		_pipeline->activate();
 	} else
 #endif
 	{
-		Pipeline::getActivePipeline()->drawTexture(_gameScreen->getGLTexture(), _gameDrawRect.left, _gameDrawRect.top, _gameDrawRect.width(), _gameDrawRect.height());
+		_pipeline->drawTexture(_gameScreen->getGLTexture(), _gameDrawRect.left, _gameDrawRect.top, _gameDrawRect.width(), _gameDrawRect.height());
 	}
 
 	// Second step: Draw the overlay if visible.
@@ -697,14 +704,14 @@ void OpenGLGraphicsManager::updateScreen() {
 		int dstX = (_windowWidth - _overlayDrawRect.width()) / 2;
 		int dstY = (_windowHeight - _overlayDrawRect.height()) / 2;
 		_backBuffer.enableBlend(Framebuffer::kBlendModeTraditionalTransparency);
-		Pipeline::getActivePipeline()->drawTexture(_overlay->getGLTexture(), dstX, dstY, _overlayDrawRect.width(), _overlayDrawRect.height());
+		_pipeline->drawTexture(_overlay->getGLTexture(), dstX, dstY, _overlayDrawRect.width(), _overlayDrawRect.height());
 	}
 
 	// Third step: Draw the cursor if necessary.
 	if (needsCursor) {
 		_backBuffer.enableBlend(Framebuffer::kBlendModePremultipliedTransparency);
 
-		Pipeline::getActivePipeline()->drawTexture(_cursor->getGLTexture(),
+		_pipeline->drawTexture(_cursor->getGLTexture(),
 		                         _cursorX - _cursorHotspotXScaled + _shakeOffsetScaled.x,
 		                         _cursorY - _cursorHotspotYScaled + _shakeOffsetScaled.y,
 		                         _cursorWidthScaled, _cursorHeightScaled);
@@ -734,17 +741,17 @@ void OpenGLGraphicsManager::updateScreen() {
 		}
 
 		// Set the OSD transparency.
-		Pipeline::getActivePipeline()->setColor(1.0f, 1.0f, 1.0f, _osdMessageAlpha / 100.0f);
+		_pipeline->setColor(1.0f, 1.0f, 1.0f, _osdMessageAlpha / 100.0f);
 
 		int dstX = (_windowWidth - _osdMessageSurface->getWidth()) / 2;
 		int dstY = (_windowHeight - _osdMessageSurface->getHeight()) / 2;
 
 		// Draw the OSD texture.
-		Pipeline::getActivePipeline()->drawTexture(_osdMessageSurface->getGLTexture(),
+		_pipeline->drawTexture(_osdMessageSurface->getGLTexture(),
 		                                           dstX, dstY, _osdMessageSurface->getWidth(), _osdMessageSurface->getHeight());
 
 		// Reset color.
-		Pipeline::getActivePipeline()->setColor(1.0f, 1.0f, 1.0f, 1.0f);
+		_pipeline->setColor(1.0f, 1.0f, 1.0f, 1.0f);
 
 		if (_osdMessageAlpha <= 0) {
 			delete _osdMessageSurface;
@@ -761,8 +768,8 @@ void OpenGLGraphicsManager::updateScreen() {
 		int dstY = kOSDIconTopMargin;
 
 		// Draw the OSD icon texture.
-		Pipeline::getActivePipeline()->drawTexture(_osdIconSurface->getGLTexture(),
-		                                           dstX, dstY, _osdIconSurface->getWidth(), _osdIconSurface->getHeight());
+		_pipeline->drawTexture(_osdIconSurface->getGLTexture(),
+		                       dstX, dstY, _osdIconSurface->getWidth(), _osdIconSurface->getHeight());
 	}
 #endif
 
@@ -1165,7 +1172,6 @@ void OpenGLGraphicsManager::notifyContextCreate(ContextType type,
 	const Graphics::PixelFormat &defaultFormat,
 	const Graphics::PixelFormat &defaultFormatAlpha) {
 	// Initialize pipeline.
-	Pipeline::setPipeline(nullptr);
 	delete _pipeline;
 	_pipeline = nullptr;
 
@@ -1258,10 +1264,6 @@ void OpenGLGraphicsManager::notifyContextCreate(ContextType type,
 		_osdIconSurface->recreate();
 	}
 #endif
-
-	// Everything is ready: activate the pipeline
-	Pipeline::setPipeline(_pipeline);
-
 }
 
 void OpenGLGraphicsManager::notifyContextDestroy() {
@@ -1300,7 +1302,6 @@ void OpenGLGraphicsManager::notifyContextDestroy() {
 #endif
 
 	// Destroy rendering pipeline.
-	Pipeline::setPipeline(nullptr);
 	delete _pipeline;
 	_pipeline = nullptr;
 
diff --git a/backends/graphics/opengl/opengl-graphics.h b/backends/graphics/opengl/opengl-graphics.h
index e88d9858f3e..3b65fd27ce2 100644
--- a/backends/graphics/opengl/opengl-graphics.h
+++ b/backends/graphics/opengl/opengl-graphics.h
@@ -324,6 +324,8 @@ protected:
 
 	void updateLinearFiltering();
 
+	Pipeline *getPipeline() const { return _pipeline; }
+
 	/**
 	 * The default pixel format of the backend.
 	 */
diff --git a/backends/graphics/opengl/pipelines/clut8.cpp b/backends/graphics/opengl/pipelines/clut8.cpp
index 09707b258b8..2f6b5cb07b5 100644
--- a/backends/graphics/opengl/pipelines/clut8.cpp
+++ b/backends/graphics/opengl/pipelines/clut8.cpp
@@ -32,6 +32,8 @@ CLUT8LookUpPipeline::CLUT8LookUpPipeline()
 }
 
 void CLUT8LookUpPipeline::drawTextureInternal(const GLTexture &texture, const GLfloat *coordinates, const GLfloat *texcoords) {
+	assert(isActive());
+
 	// Set the palette texture.
 	GL_CALL(glActiveTexture(GL_TEXTURE1));
 	if (_paletteTexture) {
diff --git a/backends/graphics/opengl/pipelines/fixed.cpp b/backends/graphics/opengl/pipelines/fixed.cpp
index e0de0ab7127..95539921796 100644
--- a/backends/graphics/opengl/pipelines/fixed.cpp
+++ b/backends/graphics/opengl/pipelines/fixed.cpp
@@ -40,13 +40,23 @@ void FixedPipeline::activateInternal() {
 	}
 #endif
 	GL_CALL(glEnable(GL_TEXTURE_2D));
+	GL_CALL(glColor4f(_r, _g, _b, _a));
 }
 
 void FixedPipeline::setColor(GLfloat r, GLfloat g, GLfloat b, GLfloat a) {
-	GL_CALL(glColor4f(r, g, b, a));
+	_r = r;
+	_g = g;
+	_b = b;
+	_a = a;
+
+	if (isActive()) {
+		GL_CALL(glColor4f(r, g, b, a));
+	}
 }
 
 void FixedPipeline::drawTextureInternal(const GLTexture &texture, const GLfloat *coordinates, const GLfloat *texcoords) {
+	assert(isActive());
+
 	texture.bind();
 
 	GL_CALL(glTexCoordPointer(2, GL_FLOAT, 0, texcoords));
@@ -55,9 +65,7 @@ void FixedPipeline::drawTextureInternal(const GLTexture &texture, const GLfloat
 }
 
 void FixedPipeline::setProjectionMatrix(const Math::Matrix4 &projectionMatrix) {
-	if (!isActive()) {
-		return;
-	}
+	assert(isActive());
 
 	GL_CALL(glMatrixMode(GL_PROJECTION));
 	GL_CALL(glLoadMatrixf(projectionMatrix.getData()));
diff --git a/backends/graphics/opengl/pipelines/fixed.h b/backends/graphics/opengl/pipelines/fixed.h
index 5b4f1509297..7de0979a099 100644
--- a/backends/graphics/opengl/pipelines/fixed.h
+++ b/backends/graphics/opengl/pipelines/fixed.h
@@ -29,6 +29,8 @@ namespace OpenGL {
 #if !USE_FORCED_GLES2
 class FixedPipeline : public Pipeline {
 public:
+	FixedPipeline() : _r(0.f), _g(0.f), _b(0.f), _a(0.f) {}
+
 	void setColor(GLfloat r, GLfloat g, GLfloat b, GLfloat a) override;
 
 	void setProjectionMatrix(const Math::Matrix4 &projectionMatrix) override;
@@ -36,6 +38,8 @@ public:
 protected:
 	void activateInternal() override;
 	void drawTextureInternal(const GLTexture &texture, const GLfloat *coordinates, const GLfloat *texcoords) override;
+
+	GLfloat _r, _g, _b, _a;
 };
 #endif // !USE_FORCED_GLES2
 
diff --git a/backends/graphics/opengl/pipelines/pipeline.cpp b/backends/graphics/opengl/pipelines/pipeline.cpp
index 6541adde08e..b32f14e0624 100644
--- a/backends/graphics/opengl/pipelines/pipeline.cpp
+++ b/backends/graphics/opengl/pipelines/pipeline.cpp
@@ -27,11 +27,19 @@ namespace OpenGL {
 Pipeline *Pipeline::activePipeline = nullptr;
 
 Pipeline::Pipeline()
-	: _activeFramebuffer(nullptr), _isActive(false) {
+	: _activeFramebuffer(nullptr) {
 }
 
 void Pipeline::activate() {
-	_isActive = true;
+	if (activePipeline == this) {
+		return;
+	}
+
+	if (activePipeline) {
+		activePipeline->deactivate();
+	}
+
+	activePipeline = this;
 
 	if (_activeFramebuffer) {
 		_activeFramebuffer->activate(this);
@@ -41,41 +49,29 @@ void Pipeline::activate() {
 }
 
 void Pipeline::deactivate() {
+	assert(isActive());
+
 	deactivateInternal();
 
 	if (_activeFramebuffer) {
 		_activeFramebuffer->deactivate();
 	}
 
-	_isActive = false;
+	activePipeline = nullptr;
 }
 
 Framebuffer *Pipeline::setFramebuffer(Framebuffer *framebuffer) {
 	Framebuffer *oldFramebuffer = _activeFramebuffer;
-	if (_isActive && oldFramebuffer) {
+	if (isActive() && oldFramebuffer) {
 		oldFramebuffer->deactivate();
 	}
 
 	_activeFramebuffer = framebuffer;
-	if (_isActive && _activeFramebuffer) {
+	if (isActive() && _activeFramebuffer) {
 		_activeFramebuffer->activate(this);
 	}
 
 	return oldFramebuffer;
 }
 
-Pipeline *Pipeline::setPipeline(Pipeline *pipeline) {
-	Pipeline *oldPipeline = activePipeline;
-	if (oldPipeline) {
-		oldPipeline->deactivate();
-	}
-
-	activePipeline = pipeline;
-	if (activePipeline) {
-		activePipeline->activate();
-	}
-
-	return oldPipeline;
-}
-
 } // End of namespace OpenGL
diff --git a/backends/graphics/opengl/pipelines/pipeline.h b/backends/graphics/opengl/pipelines/pipeline.h
index a388c9422ea..cc654d2d4b0 100644
--- a/backends/graphics/opengl/pipelines/pipeline.h
+++ b/backends/graphics/opengl/pipelines/pipeline.h
@@ -42,7 +42,7 @@ class Framebuffer;
 class Pipeline {
 public:
 	Pipeline();
-	virtual ~Pipeline() {}
+	virtual ~Pipeline() { if (isActive()) deactivate(); }
 
 	/**
 	 * Activate the pipeline.
@@ -150,31 +150,13 @@ protected:
 
 	virtual void drawTextureInternal(const GLTexture &texture, const GLfloat *coordinates, const GLfloat *texcoords) = 0;
 
-	bool isActive() const { return _isActive; }
+	bool isActive() const { return activePipeline == this; }
 
 	Framebuffer *_activeFramebuffer;
 
 private:
-	bool _isActive;
-
 	/** Currently active rendering pipeline. */
 	static Pipeline *activePipeline;
-
-public:
-	/**
-	 * Set new pipeline.
-	 *
-	 * Client is responsible for any memory management related to pipelines.
-	 *
-	 * @param pipeline Pipeline to activate.
-	 * @return Formerly active pipeline.
-	 */
-	static Pipeline *setPipeline(Pipeline *pipeline);
-
-	/**
-	 * Query the currently active rendering pipeline.
-	 */
-	static Pipeline *getActivePipeline() { return activePipeline; }
 };
 
 } // End of namespace OpenGL
diff --git a/backends/graphics/opengl/pipelines/shader.cpp b/backends/graphics/opengl/pipelines/shader.cpp
index 62367b29ca1..827025049e2 100644
--- a/backends/graphics/opengl/pipelines/shader.cpp
+++ b/backends/graphics/opengl/pipelines/shader.cpp
@@ -76,6 +76,8 @@ void ShaderPipeline::setColor(GLfloat r, GLfloat g, GLfloat b, GLfloat a) {
 }
 
 void ShaderPipeline::drawTextureInternal(const GLTexture &texture, const GLfloat *coordinates, const GLfloat *texcoords) {
+	assert(isActive());
+
 	texture.bind();
 
 	GL_CALL(glBindBuffer(GL_ARRAY_BUFFER, _coordsVBO));
@@ -88,6 +90,8 @@ void ShaderPipeline::drawTextureInternal(const GLTexture &texture, const GLfloat
 }
 
 void ShaderPipeline::setProjectionMatrix(const Math::Matrix4 &projectionMatrix) {
+	assert(isActive());
+
 	_activeShader->setUniform("projection", projectionMatrix);
 }
 #endif // !USE_FORCED_GLES
diff --git a/backends/graphics/opengl/texture.cpp b/backends/graphics/opengl/texture.cpp
index 27ac83fcd5a..d8da9fa9526 100644
--- a/backends/graphics/opengl/texture.cpp
+++ b/backends/graphics/opengl/texture.cpp
@@ -796,13 +796,12 @@ void TextureCLUT8GPU::updateGLTexture() {
 
 void TextureCLUT8GPU::lookUpColors() {
 	// Setup pipeline to do color look up.
-	Pipeline *oldPipeline = Pipeline::setPipeline(_clut8Pipeline);
+	_clut8Pipeline->activate();
 
 	// Do color look up.
-	Pipeline::getActivePipeline()->drawTexture(_clut8Texture, _clut8Vertices);
+	_clut8Pipeline->drawTexture(_clut8Texture, _clut8Vertices);
 
-	// Restore old state.
-	Pipeline::setPipeline(oldPipeline);
+	_clut8Pipeline->deactivate();
 }
 #endif // !USE_FORCED_GLES
 


Commit: 70cf4e9e3ead98c4c1393546fc3a747abe68d5a9
    https://github.com/scummvm/scummvm/commit/70cf4e9e3ead98c4c1393546fc3a747abe68d5a9
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2022-11-06T20:02:59+01:00

Commit Message:
BACKENDS: OPENGL: Move framebuffer out of common activate code

This allows more control over activation process.

Changed paths:
    backends/graphics/opengl/pipelines/fixed.cpp
    backends/graphics/opengl/pipelines/libretro.cpp
    backends/graphics/opengl/pipelines/pipeline.cpp
    backends/graphics/opengl/pipelines/pipeline.h
    backends/graphics/opengl/pipelines/shader.cpp


diff --git a/backends/graphics/opengl/pipelines/fixed.cpp b/backends/graphics/opengl/pipelines/fixed.cpp
index 95539921796..370438a37e4 100644
--- a/backends/graphics/opengl/pipelines/fixed.cpp
+++ b/backends/graphics/opengl/pipelines/fixed.cpp
@@ -26,6 +26,8 @@ namespace OpenGL {
 
 #if !USE_FORCED_GLES2
 void FixedPipeline::activateInternal() {
+	Pipeline::activateInternal();
+
 	GL_CALL(glDisable(GL_LIGHTING));
 	GL_CALL(glDisable(GL_FOG));
 	GL_CALL(glShadeModel(GL_FLAT));
diff --git a/backends/graphics/opengl/pipelines/libretro.cpp b/backends/graphics/opengl/pipelines/libretro.cpp
index 9b07c5d4858..3d7a732e41a 100644
--- a/backends/graphics/opengl/pipelines/libretro.cpp
+++ b/backends/graphics/opengl/pipelines/libretro.cpp
@@ -187,9 +187,11 @@ void LibRetroPipeline::setProjectionMatrix(const Math::Matrix4 &projectionMatrix
 }
 
 void LibRetroPipeline::activateInternal() {
+	// Don't call anything, we call ShaderPipeline::activateInternal in due time
 }
 
 void LibRetroPipeline::deactivateInternal() {
+	// Don't call anything, we call ShaderPipeline::deactivateInternal in due time
 }
 
 bool LibRetroPipeline::open(const Common::FSNode &shaderPreset) {
diff --git a/backends/graphics/opengl/pipelines/pipeline.cpp b/backends/graphics/opengl/pipelines/pipeline.cpp
index b32f14e0624..243fcaaeab8 100644
--- a/backends/graphics/opengl/pipelines/pipeline.cpp
+++ b/backends/graphics/opengl/pipelines/pipeline.cpp
@@ -41,11 +41,13 @@ void Pipeline::activate() {
 
 	activePipeline = this;
 
+	activateInternal();
+}
+
+void Pipeline::activateInternal() {
 	if (_activeFramebuffer) {
 		_activeFramebuffer->activate(this);
 	}
-
-	activateInternal();
 }
 
 void Pipeline::deactivate() {
@@ -53,11 +55,13 @@ void Pipeline::deactivate() {
 
 	deactivateInternal();
 
+	activePipeline = nullptr;
+}
+
+void Pipeline::deactivateInternal() {
 	if (_activeFramebuffer) {
 		_activeFramebuffer->deactivate();
 	}
-
-	activePipeline = nullptr;
 }
 
 Framebuffer *Pipeline::setFramebuffer(Framebuffer *framebuffer) {
diff --git a/backends/graphics/opengl/pipelines/pipeline.h b/backends/graphics/opengl/pipelines/pipeline.h
index cc654d2d4b0..ecab37851b0 100644
--- a/backends/graphics/opengl/pipelines/pipeline.h
+++ b/backends/graphics/opengl/pipelines/pipeline.h
@@ -141,12 +141,12 @@ protected:
 	 * This sets the OpenGL state to make use of drawing with the given
 	 * OpenGL pipeline.
 	 */
-	virtual void activateInternal() = 0;
+	virtual void activateInternal();
 
 	/**
 	 * Deactivate the pipeline.
 	 */
-	virtual void deactivateInternal() {}
+	virtual void deactivateInternal();
 
 	virtual void drawTextureInternal(const GLTexture &texture, const GLfloat *coordinates, const GLfloat *texcoords) = 0;
 
diff --git a/backends/graphics/opengl/pipelines/shader.cpp b/backends/graphics/opengl/pipelines/shader.cpp
index 827025049e2..a30adbc1252 100644
--- a/backends/graphics/opengl/pipelines/shader.cpp
+++ b/backends/graphics/opengl/pipelines/shader.cpp
@@ -50,6 +50,8 @@ ShaderPipeline::~ShaderPipeline() {
 }
 
 void ShaderPipeline::activateInternal() {
+	Pipeline::activateInternal();
+
 	if (OpenGLContext.multitextureSupported) {
 		GL_CALL(glActiveTexture(GL_TEXTURE0));
 	}
@@ -63,6 +65,8 @@ void ShaderPipeline::activateInternal() {
 
 void ShaderPipeline::deactivateInternal() {
 	_activeShader->unbind();
+
+	Pipeline::deactivateInternal();
 }
 
 void ShaderPipeline::setColor(GLfloat r, GLfloat g, GLfloat b, GLfloat a) {


Commit: f9005454bdc64c27fc0b4b713943bb380c23400d
    https://github.com/scummvm/scummvm/commit/f9005454bdc64c27fc0b4b713943bb380c23400d
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2022-11-06T20:02:59+01:00

Commit Message:
BACKENDS: OPENGL: Allow to copy render settings between framebuffers

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


diff --git a/backends/graphics/opengl/framebuffer.cpp b/backends/graphics/opengl/framebuffer.cpp
index e830acd3d0e..59096fffd97 100644
--- a/backends/graphics/opengl/framebuffer.cpp
+++ b/backends/graphics/opengl/framebuffer.cpp
@@ -136,6 +136,28 @@ void Framebuffer::applyScissorBox() {
 	GL_CALL(glScissor(_scissorBox[0], _scissorBox[1], _scissorBox[2], _scissorBox[3]));
 }
 
+void Framebuffer::copyRenderStateFrom(const Framebuffer &other, uint copyMask) {
+	if (copyMask & kCopyMaskClearColor) {
+		memcpy(_clearColor, other._clearColor, sizeof(_clearColor));
+	}
+	if (copyMask & kCopyMaskBlendState) {
+		_blendState = other._blendState;
+	}
+	if (copyMask & kCopyMaskScissorState) {
+		_scissorTestState = other._scissorTestState;
+	}
+	if (copyMask & kCopyMaskScissorBox) {
+		memcpy(_scissorBox, other._scissorBox, sizeof(_scissorBox));
+	}
+
+	if (isActive()) {
+		applyClearColor();
+		applyBlendState();
+		applyScissorTestState();
+		applyScissorBox();
+	}
+}
+
 //
 // Backbuffer implementation
 //
diff --git a/backends/graphics/opengl/framebuffer.h b/backends/graphics/opengl/framebuffer.h
index 7b34bf188fd..8e7f57013be 100644
--- a/backends/graphics/opengl/framebuffer.h
+++ b/backends/graphics/opengl/framebuffer.h
@@ -86,6 +86,22 @@ public:
 	 * Obtain projection matrix of the framebuffer.
 	 */
 	const Math::Matrix4 &getProjectionMatrix() const { return _projectionMatrix; }
+
+	enum CopyMask {
+		kCopyMaskClearColor   = (1 << 0),
+		kCopyMaskBlendState   = (1 << 1),
+		kCopyMaskScissorState = (1 << 2),
+		kCopyMaskScissorBox   = (1 << 4),
+
+		kCopyMaskAll          = kCopyMaskClearColor | kCopyMaskBlendState |
+		                        kCopyMaskScissorState | kCopyMaskScissorBox,
+	};
+
+	/**
+	 * Copy rendering state from another framebuffer
+	 */
+	void copyRenderStateFrom(const Framebuffer &other, uint copyMask);
+
 protected:
 	bool isActive() const { return _pipeline != nullptr; }
 


Commit: 5484ebffaec02963d8c3583f0b918777d8e4989e
    https://github.com/scummvm/scummvm/commit/5484ebffaec02963d8c3583f0b918777d8e4989e
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2022-11-06T20:02:59+01:00

Commit Message:
BACKENDS: OPENGL: Rework LibRetro pipeline

This makes LibRetro behave almost like other pipelines and make the code
in OpenGLGraphicsManager somewhat simpler.

Changed paths:
    backends/graphics/opengl/opengl-graphics.cpp
    backends/graphics/opengl/opengl-graphics.h
    backends/graphics/opengl/pipelines/libretro.cpp
    backends/graphics/opengl/pipelines/libretro.h


diff --git a/backends/graphics/opengl/opengl-graphics.cpp b/backends/graphics/opengl/opengl-graphics.cpp
index f6cc5ce27ec..fc61303d34f 100644
--- a/backends/graphics/opengl/opengl-graphics.cpp
+++ b/backends/graphics/opengl/opengl-graphics.cpp
@@ -77,7 +77,7 @@ OpenGLGraphicsManager::OpenGLGraphicsManager()
 	  _cursorHotspotXScaled(0), _cursorHotspotYScaled(0), _cursorWidthScaled(0), _cursorHeightScaled(0),
 	  _cursorKeyColor(0), _cursorDontScale(false), _cursorPaletteEnabled(false), _shakeOffsetScaled()
 #if !USE_FORCED_GLES
-	  , _libretroPipeline(nullptr), _gameScreenTarget(nullptr)
+	  , _libretroPipeline(nullptr)
 #endif
 #ifdef USE_OSD
 	  , _osdMessageChangeRequest(false), _osdMessageAlpha(0), _osdMessageFadeStartTime(0), _osdMessageSurface(nullptr),
@@ -100,7 +100,6 @@ OpenGLGraphicsManager::~OpenGLGraphicsManager() {
 	delete _osdIconSurface;
 #endif
 #if !USE_FORCED_GLES
-	delete _gameScreenTarget;
 	ShaderManager::destroy();
 #endif
 }
@@ -494,14 +493,6 @@ OSystem::TransactionError OpenGLGraphicsManager::endGFXTransaction() {
 		delete _gameScreen;
 		_gameScreen = nullptr;
 
-#if !USE_FORCED_GLES
-		if (_gameScreenTarget != nullptr) {
-			_gameScreenTarget->destroy();
-			delete _gameScreenTarget;
-			_gameScreenTarget = nullptr;
-		}
-#endif
-
 		bool wantScaler = _currentState.scaleFactor > 1;
 
 #ifdef USE_RGB_COLOR
@@ -531,17 +522,6 @@ OSystem::TransactionError OpenGLGraphicsManager::endGFXTransaction() {
 #else
 		_gameScreen->fill(0);
 #endif
-
-#if !USE_FORCED_GLES
-		if (_libretroPipeline) {
-			_gameScreenTarget = new TextureTarget();
-			_gameScreenTarget->create();
-			// To take software scaler into account we need to create a framebuffer matching the size of the _gameScreen output texture
-			// We cheat a little because ScaledTexture does everything it can to hide the real size
-			const GLTexture &gameScreenTexture = _gameScreen->getGLTexture();
-			_gameScreenTarget->setSize(gameScreenTexture.getLogicalWidth(), gameScreenTexture.getLogicalHeight());
-		}
-#endif
 	}
 
 	// Update our display area and cursor scaling. This makes sure we pick up
@@ -638,6 +618,12 @@ void OpenGLGraphicsManager::updateScreen() {
 	}
 	_overlay->updateGLTexture();
 
+#if !USE_FORCED_GLES
+	if (_libretroPipeline) {
+		_libretroPipeline->beginScaling();
+	}
+#endif
+
 	_pipeline->activate();
 
 	// Clear the screen buffer.
@@ -653,54 +639,17 @@ void OpenGLGraphicsManager::updateScreen() {
 	// Alpha blending is disabled when drawing the screen
 	_backBuffer.enableBlend(Framebuffer::kBlendModeDisabled);
 
-	bool needsCursor = _cursorVisible && _cursor;
-
 	// First step: Draw the (virtual) game screen.
-#if !USE_FORCED_GLES
-	if (_libretroPipeline && _libretroPipeline->isInitialized()) {
-		// Use the ShaderPipeline to draw the game screen and game cursor
-		_pipeline->setFramebuffer(_gameScreenTarget);
-
-		_gameScreenTarget->enableBlend(Framebuffer::kBlendModeDisabled);
-
-		const GLTexture &gameScreenTexture = _gameScreen->getGLTexture();
-		const uint retroWidth = gameScreenTexture.getLogicalWidth(),
-		           retroHeight = gameScreenTexture.getLogicalHeight();
-		_pipeline->drawTexture(gameScreenTexture, 0, 0, retroWidth, retroHeight);
-
-		// Draw the cursor if necessary.
-		// If overlay is visible we draw it later to have the cursor above overlay
-		if (needsCursor && !_overlayVisible) {
-			// Do all calculations in window coordinates
-			int gameScreenCursorX = _cursorX - _gameDrawRect.left - _cursorHotspotXScaled + _shakeOffsetScaled.x;
-			int gameScreenCursorY = _cursorY - _gameDrawRect.top - _cursorHotspotYScaled + _shakeOffsetScaled.y;
-			// Scale to come back to libretro input surface coordinates
-			gameScreenCursorX = gameScreenCursorX * retroWidth / _gameDrawRect.width();
-			gameScreenCursorY = gameScreenCursorY * retroHeight / _gameDrawRect.height();
-
-			const GLTexture &cursorTexture = _cursor->getGLTexture();
-			const uint cursorWidth = cursorTexture.getLogicalWidth(),
-					   cursorHeight = cursorTexture.getLogicalHeight();
-
-			_gameScreenTarget->enableBlend(Framebuffer::kBlendModePremultipliedTransparency);
-			_pipeline->drawTexture(cursorTexture, gameScreenCursorX, gameScreenCursorY, cursorWidth, cursorHeight);
-			needsCursor = false;
-		}
-
-		_libretroPipeline->activate();
-		_libretroPipeline->drawTexture(*_gameScreenTarget->getTexture(), _gameDrawRect.left, _gameDrawRect.top, _gameDrawRect.width(), _gameDrawRect.height());
-
-		// Restore ShaderPipeline for the next steps
-		_pipeline->setFramebuffer(&_backBuffer);
-		_pipeline->activate();
-	} else
-#endif
-	{
-		_pipeline->drawTexture(_gameScreen->getGLTexture(), _gameDrawRect.left, _gameDrawRect.top, _gameDrawRect.width(), _gameDrawRect.height());
-	}
+	_pipeline->drawTexture(_gameScreen->getGLTexture(), _gameDrawRect.left, _gameDrawRect.top, _gameDrawRect.width(), _gameDrawRect.height());
 
 	// Second step: Draw the overlay if visible.
 	if (_overlayVisible) {
+#if !USE_FORCED_GLES
+		// Overlay must not be scaled and its cursor won't be either
+		if (_libretroPipeline) {
+			_libretroPipeline->finishScaling();
+		}
+#endif
 		int dstX = (_windowWidth - _overlayDrawRect.width()) / 2;
 		int dstY = (_windowHeight - _overlayDrawRect.height()) / 2;
 		_backBuffer.enableBlend(Framebuffer::kBlendModeTraditionalTransparency);
@@ -708,7 +657,7 @@ void OpenGLGraphicsManager::updateScreen() {
 	}
 
 	// Third step: Draw the cursor if necessary.
-	if (needsCursor) {
+	if (_cursorVisible && _cursor) {
 		_backBuffer.enableBlend(Framebuffer::kBlendModePremultipliedTransparency);
 
 		_pipeline->drawTexture(_cursor->getGLTexture(),
@@ -717,6 +666,12 @@ void OpenGLGraphicsManager::updateScreen() {
 		                         _cursorWidthScaled, _cursorHeightScaled);
 	}
 
+#if !USE_FORCED_GLES
+	if (_libretroPipeline) {
+		_libretroPipeline->finishScaling();
+	}
+#endif
+
 	if (!_overlayVisible) {
 		_backBuffer.enableScissorTest(false);
 	}
@@ -1176,27 +1131,38 @@ void OpenGLGraphicsManager::notifyContextCreate(ContextType type,
 	_pipeline = nullptr;
 
 #if !USE_FORCED_GLES
-	if (_libretroPipeline) {
-		delete _libretroPipeline;
-		_libretroPipeline = nullptr;
-	}
+	// _libretroPipeline has just been destroyed as the pipeline
+	_libretroPipeline = nullptr;
 #endif
 
 	OpenGLContext.initialize(type);
 
+	// Try to setup LibRetro pipeline first if available.
 #if !USE_FORCED_GLES
-	if (OpenGLContext.shadersSupported) {
+	if (LibRetroPipeline::isSupportedByContext()) {
+		ShaderMan.notifyCreate();
+		_libretroPipeline = new LibRetroPipeline();
+		_pipeline = _libretroPipeline;
+	}
+#endif
+
+#if !USE_FORCED_GLES
+	if (!_pipeline && OpenGLContext.shadersSupported) {
 		ShaderMan.notifyCreate();
 		_pipeline = new ShaderPipeline(ShaderMan.query(ShaderManager::kDefault));
 	}
 #endif
 
 #if !USE_FORCED_GLES2
-	if (_pipeline == nullptr) {
+	if (!_pipeline) {
 		_pipeline = new FixedPipeline();
 	}
 #endif
 
+	if (!_pipeline) {
+		error("Can't initialize any pipeline");
+	}
+
 	// Disable 3D properties.
 	GL_CALL(glDisable(GL_CULL_FACE));
 	GL_CALL(glDisable(GL_DEPTH_TEST));
@@ -1211,16 +1177,6 @@ void OpenGLGraphicsManager::notifyContextCreate(ContextType type,
 
 	_pipeline->setFramebuffer(&_backBuffer);
 
-	// Setup LibRetro pipeline.
-
-#if !USE_FORCED_GLES
-	if (LibRetroPipeline::isSupportedByContext()) {
-		_libretroPipeline = new LibRetroPipeline();
-		_libretroPipeline->setColor(1.0f, 1.0f, 1.0f, 1.0f);
-		_libretroPipeline->setFramebuffer(&_backBuffer);
-	}
-#endif
-
 	// We use a "pack" alignment (when reading from textures) to 4 here,
 	// since the only place where we really use it is the BMP screenshot
 	// code and that requires the same alignment too.
@@ -1241,12 +1197,6 @@ void OpenGLGraphicsManager::notifyContextCreate(ContextType type,
 		_gameScreen->recreate();
 	}
 
-#if !USE_FORCED_GLES
-	if (_gameScreenTarget) {
-		_gameScreenTarget->create();
-	}
-#endif
-
 	if (_overlay) {
 		_overlay->recreate();
 	}
@@ -1271,12 +1221,6 @@ void OpenGLGraphicsManager::notifyContextDestroy() {
 		_gameScreen->destroy();
 	}
 
-#if !USE_FORCED_GLES
-	if (_gameScreenTarget) {
-		_gameScreenTarget->destroy();
-	}
-#endif
-
 	if (_overlay) {
 		_overlay->destroy();
 	}
@@ -1306,10 +1250,8 @@ void OpenGLGraphicsManager::notifyContextDestroy() {
 	_pipeline = nullptr;
 
 #if !USE_FORCED_GLES
-	if (_libretroPipeline) {
-		delete _libretroPipeline;
-		_libretroPipeline = nullptr;
-	}
+	// _libretroPipeline has just been destroyed as the pipeline
+	_libretroPipeline = nullptr;
 #endif
 
 	// Rest our context description since the context is gone soon.
@@ -1483,6 +1425,14 @@ void OpenGLGraphicsManager::recalculateDisplayAreas() {
 
 	WindowedGraphicsManager::recalculateDisplayAreas();
 
+#if !USE_FORCED_GLES
+	if (_libretroPipeline) {
+		const GLTexture &gameScreenTexture = _gameScreen->getGLTexture();
+		_libretroPipeline->setDisplaySizes(gameScreenTexture.getLogicalWidth(), gameScreenTexture.getLogicalHeight(),
+				_gameDrawRect);
+	}
+#endif
+
 	// Setup drawing limitation for game graphics.
 	// This involves some trickery because OpenGL's viewport coordinate system
 	// is upside down compared to ours.
@@ -1542,26 +1492,17 @@ void OpenGLGraphicsManager::recalculateCursorScaling() {
 
 void OpenGLGraphicsManager::updateLinearFiltering() {
 #if !USE_FORCED_GLES
-	if (_libretroPipeline && _libretroPipeline->isInitialized()) {
-		// Apply filtering in LibRetro first input texture which is _gameScreenTarget
-		if (_gameScreen) {
-			_gameScreen->enableLinearFiltering(false);
-			_gameScreenTarget->getTexture()->enableLinearFiltering(_currentState.filtering);
-		}
-
-		if (_cursor) {
-			_cursor->enableLinearFiltering(_currentState.filtering && _overlayVisible);
-		}
-	} else
+	if (_libretroPipeline) {
+		_libretroPipeline->enableLinearFiltering(_currentState.filtering);
+	}
 #endif
-	{
-		if (_gameScreen) {
-			_gameScreen->enableLinearFiltering(_currentState.filtering);
-		}
 
-		if (_cursor) {
-			_cursor->enableLinearFiltering(_currentState.filtering);
-		}
+	if (_gameScreen) {
+		_gameScreen->enableLinearFiltering(_currentState.filtering);
+	}
+
+	if (_cursor) {
+		_cursor->enableLinearFiltering(_currentState.filtering);
 	}
 
 	// The overlay UI should also obey the filtering choice (managed via the Filter Graphics checkbox in Graphics Tab).
diff --git a/backends/graphics/opengl/opengl-graphics.h b/backends/graphics/opengl/opengl-graphics.h
index 3b65fd27ce2..3b27c6e33cf 100644
--- a/backends/graphics/opengl/opengl-graphics.h
+++ b/backends/graphics/opengl/opengl-graphics.h
@@ -351,14 +351,6 @@ protected:
 	 */
 	byte _gamePalette[3 * 256];
 
-#if !USE_FORCED_GLES
-	/**
-	 * The render target for the virtual game screen. Used when
-	 * LibRetro shaders are enabled.
-	 */
-	TextureTarget *_gameScreenTarget;
-#endif
-
 	//
 	// Overlay
 	//
diff --git a/backends/graphics/opengl/pipelines/libretro.cpp b/backends/graphics/opengl/pipelines/libretro.cpp
index 3d7a732e41a..34168b34470 100644
--- a/backends/graphics/opengl/pipelines/libretro.cpp
+++ b/backends/graphics/opengl/pipelines/libretro.cpp
@@ -115,86 +115,212 @@ static const char *g_compatFragment =
 		"#endif\n"
 	"#endif\n";
 
+/* This TextureTarget handles the scaling of coordinates from the window coordinates space
+ * to the input coordinates space */
+class LibRetroTextureTarget : public TextureTarget {
+public:
+	bool setScaledSize(uint width, uint height, const Common::Rect &scalingRect) {
+		GLTexture *texture = getTexture();
+		if (!texture->setSize(width, height)) {
+			return false;
+		}
+
+		const uint texWidth  = texture->getWidth();
+		const uint texHeight = texture->getHeight();
+
+		// Set viewport dimensions.
+		_viewport[0] = 0;
+		_viewport[1] = 0;
+		_viewport[2] = texWidth;
+		_viewport[3] = texHeight;
+
+		const float ratioW = (float)width  / scalingRect.width();
+		const float ratioH = (float)height / scalingRect.height();
+
+		// Setup scaling projection matrix.
+		// This projection takes window screen coordinates and converts it to input coordinates normalized
+		_projectionMatrix(0, 0) = 2.f * ratioW / texWidth;
+		_projectionMatrix(0, 1) = 0.f;
+		_projectionMatrix(0, 2) = 0.f;
+		_projectionMatrix(0, 3) = 0.f;
+
+		_projectionMatrix(1, 0) = 0.f;
+		_projectionMatrix(1, 1) = 2.f * ratioH / texHeight;
+		_projectionMatrix(1, 2) = 0.f;
+		_projectionMatrix(1, 3) = 0.f;
+
+		_projectionMatrix(2, 0) = 0.f;
+		_projectionMatrix(2, 1) = 0.f;
+		_projectionMatrix(2, 2) = 0.f;
+		_projectionMatrix(2, 3) = 0.f;
+
+		_projectionMatrix(3, 0) = -1.f - (2.f * scalingRect.left) * ratioW / texWidth;
+		_projectionMatrix(3, 1) = -1.f - (2.f * scalingRect.top) * ratioH / texHeight;
+		_projectionMatrix(3, 2) = 0.0f;
+		_projectionMatrix(3, 3) = 1.0f;
+
+		// Directly apply changes when we are active.
+		if (isActive()) {
+			applyViewport();
+			applyProjectionMatrix();
+		}
+		return true;
+	}
+};
+
+/* This Pipeline is used by the Framebuffer objects in the LibRetro passes.
+ * It does nothing as everything is already handled by us. */
+class FakePipeline : public Pipeline {
+public:
+	FakePipeline() {}
+	void setColor(GLfloat r, GLfloat g, GLfloat b, GLfloat a) override { }
+	void setProjectionMatrix(const Math::Matrix4 &projectionMatrix) override {}
+protected:
+	void activateInternal() override {}
+	void deactivateInternal() override {}
+	void drawTextureInternal(const GLTexture &texture, const GLfloat *coordinates, const GLfloat *texcoords) override { }
+};
+
 LibRetroPipeline::LibRetroPipeline()
-	: ShaderPipeline(ShaderMan.query(ShaderManager::kDefault)),
-	  _shaderPreset(nullptr), _applyProjectionChanges(false),
-	  _inputWidth(0), _inputHeight(0), _outputWidth(0), _outputHeight(0),
+	: _inputPipeline(ShaderMan.query(ShaderManager::kDefault)),
+	  _outputPipeline(ShaderMan.query(ShaderManager::kDefault)),
+	  _inputTarget(new LibRetroTextureTarget()), _needsScaling(false),
+	  _shaderPreset(nullptr), _linearFiltering(false),
+	  _inputWidth(0), _inputHeight(0),
 	  _isAnimated(false), _frameCount(0) {
+	_inputPipeline.setFramebuffer(_inputTarget);
 }
 
 LibRetroPipeline::LibRetroPipeline(const Common::FSNode &shaderPreset)
-	: ShaderPipeline(ShaderMan.query(ShaderManager::kDefault)),
-	  _shaderPreset(nullptr), _applyProjectionChanges(false),
-	  _inputWidth(0), _inputHeight(0), _outputWidth(0), _outputHeight(0),
+	: _inputPipeline(ShaderMan.query(ShaderManager::kDefault)),
+	  _outputPipeline(ShaderMan.query(ShaderManager::kDefault)),
+	  _inputTarget(new LibRetroTextureTarget()), _needsScaling(false),
+	  _shaderPreset(nullptr), _linearFiltering(false),
+	  _inputWidth(0), _inputHeight(0),
 	  _isAnimated(false), _frameCount(0) {
+	_inputPipeline.setFramebuffer(_inputTarget);
 	open(shaderPreset);
 }
 
 LibRetroPipeline::~LibRetroPipeline() {
 	close();
+	delete _inputTarget;
+}
+
+/** Small helper to overcome that texture passed to drawTexture is const
+ * This is not that clean but this allows to keep the OpenGLGraphicsManager code simple
+ */
+static void setLinearFiltering(GLuint glTexture, bool enable) {
+	GLuint glFilter;
+	if (enable) {
+		glFilter = GL_LINEAR;
+	} else {
+		glFilter = GL_NEAREST;
+	}
+
+	GL_CALL(glBindTexture(GL_TEXTURE_2D, glTexture));
+
+	GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, glFilter));
+	GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, glFilter));
 }
 
 void LibRetroPipeline::drawTextureInternal(const GLTexture &texture, const GLfloat *coordinates, const GLfloat *texcoords) {
-	Framebuffer *const targetBuffer = _activeFramebuffer;
+	if (!_needsScaling) {
+		_outputPipeline.drawTexture(texture, coordinates, texcoords);
+		return;
+	}
 
-	// Set input texture for 1st pass to texture to draw.
-	_passes[0].inputTexture = &texture;
+	// Disable linear filtering: we apply it after merging all to be scaled surfaces
+	setLinearFiltering(texture.getGLTexture(), false);
 
-	// Get back screen size from texture coordinates.
-	// FIXME: We assume a fixed set of triangle strip
-	GLfloat outputWidth, outputHeight;
-	outputWidth = coordinates[6] - coordinates[0];
-	outputHeight = coordinates[7] - coordinates[1];
+	/* OpenGLGraphicsManager only knows about _activeFramebuffer and modify framebuffer here
+	 * So let's synchronize our _inputTarget with it.
+	 * Don't synchronize the scissor test as coordinates are wrong and we should not need it*/
+	_inputTarget->copyRenderStateFrom(*_activeFramebuffer,
+			Framebuffer::kCopyMaskClearColor | Framebuffer::kCopyMaskBlendState);
 
-	bool outputSizeChanged = (_outputWidth != outputWidth || _outputHeight != outputHeight);
-	// Save output dimensions.
-	_outputWidth  = outputWidth;
-	_outputHeight = outputHeight;
+	/* The backend sends us the coordinates in screen coordinates system
+	 * So, when we are before libretro scaling, we need to scale back coordinates
+	 * to our own coordinates system */
+	_inputPipeline.drawTexture(texture, coordinates, texcoords);
 
+	if (_linearFiltering) {
+		// Enable back linear filtering as if nothing happened
+		setLinearFiltering(texture.getGLTexture(), true);
+	}
+}
 
-	// In case texture dimensions or viewport dimensions changed, we need to
-	// update the pipeline's state.
-	if (   texture.getLogicalWidth() != _inputWidth
-		|| texture.getLogicalHeight() != _inputHeight
-		|| outputSizeChanged) {
-		_inputWidth  = texture.getLogicalWidth();
-		_inputHeight = texture.getLogicalHeight();
+void LibRetroPipeline::beginScaling() {
+	if (_shaderPreset != nullptr) {
+		_needsScaling = true;
+		_inputTarget->getTexture()->enableLinearFiltering(_linearFiltering);
+	}
+}
 
-		setPipelineState();
+void LibRetroPipeline::finishScaling() {
+	if (!_needsScaling) {
+		return;
 	}
 
+	/* As we have now finished to render everything in the input pipeline
+	 * we can do the render through all libretro passes */
+
 	// Now we can actually draw the texture with the setup passes.
 	for (PassArray::const_iterator i = _passes.begin(), end = _passes.end(); i != end; ++i) {
 		renderPass(*i);
 	}
+	_frameCount++;
 
-	// Finally, we need to render the result to the active framebuffer.
-	_applyProjectionChanges = true;
-	setFramebuffer(targetBuffer);
-	_applyProjectionChanges = false;
+	// Clear the output buffer.
+	_activeFramebuffer->activate(this);
+	// Disable scissor test for clearing, it will get enabled back when activating the output pipeline
+	GL_CALL(glDisable(GL_SCISSOR_TEST));
+	GL_CALL(glClear(GL_COLOR_BUFFER_BIT));
 
-	ShaderPipeline::activateInternal();
-	ShaderPipeline::drawTextureInternal(*_passes[_passes.size() - 1].target->getTexture(), coordinates, texcoords);
-	ShaderPipeline::deactivateInternal();
+	// Finally, we need to render the result to the output pipeline
+	_outputPipeline.setFramebuffer(_activeFramebuffer);
+	_outputPipeline.activate();
 
-	_frameCount++;
+	_outputPipeline.drawTexture(*_passes[_passes.size() - 1].target->getTexture(), _outputRect.left, _outputRect.top, _outputRect.width(), _outputRect.height());
+
+	_needsScaling = false;
+}
+
+void LibRetroPipeline::setDisplaySizes(uint inputWidth, uint inputHeight, const Common::Rect &outputRect) {
+	_inputWidth = inputWidth;
+	_inputHeight = inputHeight;
+	_outputRect = outputRect;
+
+	_inputTarget->setScaledSize(inputWidth, inputHeight, outputRect);
+
+	setPipelineState();
+}
+
+void LibRetroPipeline::setColor(GLfloat r, GLfloat g, GLfloat b, GLfloat a) {
+	_inputPipeline.setColor(r, g, b, a);
+	_outputPipeline.setColor(r, g, b, a);
 }
 
 void LibRetroPipeline::setProjectionMatrix(const Math::Matrix4 &projectionMatrix) {
-	if (_applyProjectionChanges) {
-		ShaderPipeline::setProjectionMatrix(projectionMatrix);
-	}
 }
 
 void LibRetroPipeline::activateInternal() {
-	// Don't call anything, we call ShaderPipeline::activateInternal in due time
+	// Don't call Pipeline::activateInternal as our framebuffer is passed to _outputPipeline
+	if (_needsScaling) {
+		_inputPipeline.activate();
+	} else {
+		_outputPipeline.setFramebuffer(_activeFramebuffer);
+		_outputPipeline.activate();
+	}
 }
 
 void LibRetroPipeline::deactivateInternal() {
-	// Don't call anything, we call ShaderPipeline::deactivateInternal in due time
+	// Don't call Pipeline::deactivateInternal as our framebuffer is passed to _outputPipeline
 }
 
 bool LibRetroPipeline::open(const Common::FSNode &shaderPreset) {
+	_inputTarget->create();
+
 	_shaderPreset = LibRetro::parsePreset(shaderPreset);
 	if (!_shaderPreset)
 		return false;
@@ -209,6 +335,8 @@ bool LibRetroPipeline::open(const Common::FSNode &shaderPreset) {
 		return false;
 	}
 
+	setPipelineState();
+
 	return true;
 }
 
@@ -232,6 +360,9 @@ void LibRetroPipeline::close() {
 	_shaderPreset = nullptr;
 
 	_isAnimated = false;
+	_needsScaling = false;
+
+	_inputTarget->destroy();
 }
 
 static Common::FSNode getChildRecursive(const Common::FSNode &basePath, const Common::String &fileName) {
@@ -408,7 +539,9 @@ bool LibRetroPipeline::loadPasses() {
 
 		pass.buildTexCoords(passId, aliases);
 		pass.buildTexSamplers(passId, _textures, aliases);
-		if (passId > 0) {
+		if (passId == 0) {
+			_passes[0].inputTexture = _inputTarget->getTexture();
+		} else {
 			GLTexture *const texture = _passes[passId - 1].target->getTexture();
 			texture->enableLinearFiltering(i->filteringMode == LibRetro::kFilteringModeLinear);
 			texture->setWrapMode(i->wrapMode);
@@ -428,19 +561,20 @@ bool LibRetroPipeline::loadPasses() {
 		}
 	}
 
-
 	// Now try to setup FBOs with some dummy size to make sure it could work
+	uint bakInputWidth = _inputWidth;
+	uint bakInputHeight = _inputHeight;
+	Common::Rect bakOutputRect = _outputRect;
+
 	_inputWidth = 320;
 	_inputHeight = 200;
-	_outputWidth = 640;
-	_outputHeight = 480;
+	_outputRect = Common::Rect(640, 480);
 
 	bool ret = setupFBOs();
 
-	_inputWidth = 0;
-	_inputHeight = 0;
-	_outputWidth = 0;
-	_outputHeight = 0;
+	_inputWidth = bakInputWidth;
+	_inputHeight = bakInputHeight;
+	_outputRect = bakOutputRect;
 
 	if (!ret) {
 		return false;
@@ -463,8 +597,8 @@ bool LibRetroPipeline::setupFBOs() {
 	float sourceW = _inputWidth;
 	float sourceH = _inputHeight;
 
-	const float viewportW = _outputWidth;
-	const float viewportH = _outputHeight;
+	const float viewportW = _outputRect.width();
+	const float viewportH = _outputRect.height();
 
 	for (PassArray::size_type i = 0; i < _passes.size(); ++i) {
 		Pass &pass = _passes[i];
@@ -655,8 +789,11 @@ void LibRetroPipeline::Pass::addTexSampler(const Common::String &prefix, uint *u
 
 void LibRetroPipeline::renderPass(const Pass &pass) {
 	// Activate shader and framebuffer to be used for rendering.
+	FakePipeline fakePipeline;
+
 	pass.shader->use();
-	setFramebuffer(pass.target);
+	// We don't need to set the projection matrix here so let's use a fake pipeline
+	pass.target->activate(&fakePipeline);
 
 	if (pass.hasFrameCount) {
 		uint frameCount = _frameCount;
@@ -675,6 +812,8 @@ void LibRetroPipeline::renderPass(const Pass &pass) {
 	// Actually draw something.
 	GL_CALL(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4));
 
+	pass.target->deactivate();
+
 	// Unbind shader.
 	pass.shader->unbind();
 }
diff --git a/backends/graphics/opengl/pipelines/libretro.h b/backends/graphics/opengl/pipelines/libretro.h
index e425476fc45..29dca1da82a 100644
--- a/backends/graphics/opengl/pipelines/libretro.h
+++ b/backends/graphics/opengl/pipelines/libretro.h
@@ -42,22 +42,32 @@ struct ShaderPass;
 } // End of namespace LibRetro
 
 class TextureTarget;
+class LibRetroTextureTarget;
 
 /**
  * Pipeline implementation using Libretro shader presets.
  */
-class LibRetroPipeline : public ShaderPipeline {
+class LibRetroPipeline : public Pipeline {
 public:
 	LibRetroPipeline();
 	LibRetroPipeline(const Common::FSNode &shaderPreset);
 	~LibRetroPipeline() override;
 
+	void setColor(GLfloat r, GLfloat g, GLfloat b, GLfloat a) override;
 	void setProjectionMatrix(const Math::Matrix4 &projectionMatrix) override;
 
 	bool open(const Common::FSNode &shaderPreset);
 	void close();
 
-	bool isInitialized() const { return _shaderPreset != nullptr; }
+	/* Called by OpenGLGraphicsManager */
+	void enableLinearFiltering(bool enabled) { _linearFiltering = enabled; }
+	/* Called by OpenGLGraphicsManager to setup the internal objects sizes */
+	void setDisplaySizes(uint inputWidth, uint inputHeight, const Common::Rect &outputRect);
+	/* Called by OpenGLGraphicsManager to indicate that next draws need to be scaled. */
+	void beginScaling();
+	/* Called by OpenGLGraphicsManager to indicate that next draws don't need to be scaled.
+	 * This must be called to execute scaling. */
+	void finishScaling();
 	bool isAnimated() const { return _isAnimated; }
 
 	static bool isSupportedByContext() {
@@ -78,20 +88,27 @@ private:
 	void setupPassUniforms(const uint id);
 	void setShaderTexUniforms(const Common::String &prefix, Shader *shader, const GLTexture &texture);
 
-	const LibRetro::ShaderPreset *_shaderPreset;
+	/* Pipelines used to draw all layers
+	 * First before the scaler then after it to draw on screen
+	 */
+	ShaderPipeline _inputPipeline;
+	ShaderPipeline _outputPipeline;
+	bool _needsScaling;
 
-	bool _applyProjectionChanges;
+	const LibRetro::ShaderPreset *_shaderPreset;
 
 	uint _inputWidth;
 	uint _inputHeight;
+	Common::Rect _outputRect;
 
-	uint _outputWidth;
-	uint _outputHeight;
+	bool _linearFiltering;
 
 	/* Determines if preset depends on frameCount or from previous frames */
 	bool _isAnimated;
 	uint _frameCount;
 
+	LibRetroTextureTarget *_inputTarget;
+
 	struct Texture {
 		Texture() : textureData(nullptr), glTexture(nullptr) {}
 		Texture(Graphics::Surface *tD, GLTexture *glTex) : textureData(tD), glTexture(glTex) {}


Commit: 9d1910854b3f78f5ac1cef9930212050609f70dc
    https://github.com/scummvm/scummvm/commit/9d1910854b3f78f5ac1cef9930212050609f70dc
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2022-11-06T20:02:59+01:00

Commit Message:
BACKENDS: OPENGL: Match vertex coordinates with RetroArch

This makes work shaders which ignore them.
A flip is done when rendering to output pipeline because RetroArch
renders directly on the back buffer

Changed paths:
    backends/graphics/opengl/pipelines/libretro.cpp


diff --git a/backends/graphics/opengl/pipelines/libretro.cpp b/backends/graphics/opengl/pipelines/libretro.cpp
index 34168b34470..161654852c6 100644
--- a/backends/graphics/opengl/pipelines/libretro.cpp
+++ b/backends/graphics/opengl/pipelines/libretro.cpp
@@ -281,7 +281,23 @@ void LibRetroPipeline::finishScaling() {
 	_outputPipeline.setFramebuffer(_activeFramebuffer);
 	_outputPipeline.activate();
 
-	_outputPipeline.drawTexture(*_passes[_passes.size() - 1].target->getTexture(), _outputRect.left, _outputRect.top, _outputRect.width(), _outputRect.height());
+	/* In retroarch, the shader directly draws on the backbuffer while we drew on a texture
+	 * so everything is flipped when we draw this texture.
+	 * Use custom coordinates to do the flipping. */
+	GLfloat coordinates[4*2];
+	coordinates[0] = _outputRect.left;
+	coordinates[1] = _outputRect.bottom;
+
+	coordinates[2] = _outputRect.right;
+	coordinates[3] = _outputRect.bottom;
+
+	coordinates[4] = _outputRect.left;
+	coordinates[5] = _outputRect.top;
+
+	coordinates[6] = _outputRect.right;
+	coordinates[7] = _outputRect.top;
+
+	_outputPipeline.drawTexture(*_passes[_passes.size() - 1].target->getTexture(), coordinates);
 
 	_needsScaling = false;
 }
@@ -612,17 +628,35 @@ bool LibRetroPipeline::setupFBOs() {
 		}
 
 		// Store draw coordinates.
-		pass.vertexCoord[0] = 0;
-		pass.vertexCoord[1] = 0;
+		/* RetroArch draws the last pass directly on FB0 and adapts its vertex coordinates for this.
+		 * We don't se we should not have to take this into account but some shaders (like metacrt) ignore
+		 * the vertex coordinates while drawing and everything gets upside down.
+		 * So we act like RetroArch here and flip the texture when rendering on the output pipeline. */
+		if (i != _passes.size() - 1) {
+			pass.vertexCoord[0] = 0;
+			pass.vertexCoord[1] = 0;
+
+			pass.vertexCoord[2] = (uint)sourceW;
+			pass.vertexCoord[3] = 0;
+
+			pass.vertexCoord[4] = 0;
+			pass.vertexCoord[5] = (uint)sourceH;
+
+			pass.vertexCoord[6] = (uint)sourceW;
+			pass.vertexCoord[7] = (uint)sourceH;
+		} else {
+			pass.vertexCoord[0] = 0;
+			pass.vertexCoord[1] = (uint)sourceH;
 
-		pass.vertexCoord[2] = (uint)sourceW;
-		pass.vertexCoord[3] = 0;
+			pass.vertexCoord[2] = (uint)sourceW;
+			pass.vertexCoord[3] = (uint)sourceH;
 
-		pass.vertexCoord[4] = 0;
-		pass.vertexCoord[5] = (uint)sourceH;
+			pass.vertexCoord[4] = 0;
+			pass.vertexCoord[5] = 0;
 
-		pass.vertexCoord[6] = (uint)sourceW;
-		pass.vertexCoord[7] = (uint)sourceH;
+			pass.vertexCoord[6] = (uint)sourceW;
+			pass.vertexCoord[7] = 0;
+		}
 
 		// Set projection matrix in passes's shader.
 		pass.shader->setUniform("MVPMatrix", pass.target->getProjectionMatrix());


Commit: a6dd037079f71336137e1ce6ad72e9b930a9ea76
    https://github.com/scummvm/scummvm/commit/a6dd037079f71336137e1ce6ad72e9b930a9ea76
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2022-11-06T20:02:59+01:00

Commit Message:
BACKENDS: OPENGL: Add support for previous frames in LibRetro

Changed paths:
    backends/graphics/opengl/pipelines/libretro.cpp
    backends/graphics/opengl/pipelines/libretro.h


diff --git a/backends/graphics/opengl/pipelines/libretro.cpp b/backends/graphics/opengl/pipelines/libretro.cpp
index 161654852c6..31389bf9f05 100644
--- a/backends/graphics/opengl/pipelines/libretro.cpp
+++ b/backends/graphics/opengl/pipelines/libretro.cpp
@@ -184,27 +184,22 @@ protected:
 LibRetroPipeline::LibRetroPipeline()
 	: _inputPipeline(ShaderMan.query(ShaderManager::kDefault)),
 	  _outputPipeline(ShaderMan.query(ShaderManager::kDefault)),
-	  _inputTarget(new LibRetroTextureTarget()), _needsScaling(false),
-	  _shaderPreset(nullptr), _linearFiltering(false),
-	  _inputWidth(0), _inputHeight(0),
+	  _needsScaling(false), _shaderPreset(nullptr), _linearFiltering(false),
+	  _currentTarget(uint(-1)), _inputWidth(0), _inputHeight(0),
 	  _isAnimated(false), _frameCount(0) {
-	_inputPipeline.setFramebuffer(_inputTarget);
 }
 
 LibRetroPipeline::LibRetroPipeline(const Common::FSNode &shaderPreset)
 	: _inputPipeline(ShaderMan.query(ShaderManager::kDefault)),
 	  _outputPipeline(ShaderMan.query(ShaderManager::kDefault)),
-	  _inputTarget(new LibRetroTextureTarget()), _needsScaling(false),
-	  _shaderPreset(nullptr), _linearFiltering(false),
-	  _inputWidth(0), _inputHeight(0),
+	  _needsScaling(false), _shaderPreset(nullptr), _linearFiltering(false),
+	  _currentTarget(uint(-1)), _inputWidth(0), _inputHeight(0),
 	  _isAnimated(false), _frameCount(0) {
-	_inputPipeline.setFramebuffer(_inputTarget);
 	open(shaderPreset);
 }
 
 LibRetroPipeline::~LibRetroPipeline() {
 	close();
-	delete _inputTarget;
 }
 
 /** Small helper to overcome that texture passed to drawTexture is const
@@ -234,9 +229,9 @@ void LibRetroPipeline::drawTextureInternal(const GLTexture &texture, const GLflo
 	setLinearFiltering(texture.getGLTexture(), false);
 
 	/* OpenGLGraphicsManager only knows about _activeFramebuffer and modify framebuffer here
-	 * So let's synchronize our _inputTarget with it.
+	 * So let's synchronize our _inputTargets with it.
 	 * Don't synchronize the scissor test as coordinates are wrong and we should not need it*/
-	_inputTarget->copyRenderStateFrom(*_activeFramebuffer,
+	_inputTargets[_currentTarget].copyRenderStateFrom(*_activeFramebuffer,
 			Framebuffer::kCopyMaskClearColor | Framebuffer::kCopyMaskBlendState);
 
 	/* The backend sends us the coordinates in screen coordinates system
@@ -253,7 +248,7 @@ void LibRetroPipeline::drawTextureInternal(const GLTexture &texture, const GLflo
 void LibRetroPipeline::beginScaling() {
 	if (_shaderPreset != nullptr) {
 		_needsScaling = true;
-		_inputTarget->getTexture()->enableLinearFiltering(_linearFiltering);
+		_inputTargets[_currentTarget].getTexture()->enableLinearFiltering(_linearFiltering);
 	}
 }
 
@@ -269,8 +264,16 @@ void LibRetroPipeline::finishScaling() {
 	for (PassArray::const_iterator i = _passes.begin(), end = _passes.end(); i != end; ++i) {
 		renderPass(*i);
 	}
+
+	// Prepare for the next frame
 	_frameCount++;
 
+	_currentTarget++;
+	if (_currentTarget >= _inputTargets.size()) {
+		_currentTarget = 0;
+	}
+	_passes[0].inputTexture = _inputTargets[_currentTarget].getTexture();
+
 	// Clear the output buffer.
 	_activeFramebuffer->activate(this);
 	// Disable scissor test for clearing, it will get enabled back when activating the output pipeline
@@ -307,8 +310,6 @@ void LibRetroPipeline::setDisplaySizes(uint inputWidth, uint inputHeight, const
 	_inputHeight = inputHeight;
 	_outputRect = outputRect;
 
-	_inputTarget->setScaledSize(inputWidth, inputHeight, outputRect);
-
 	setPipelineState();
 }
 
@@ -323,6 +324,7 @@ void LibRetroPipeline::setProjectionMatrix(const Math::Matrix4 &projectionMatrix
 void LibRetroPipeline::activateInternal() {
 	// Don't call Pipeline::activateInternal as our framebuffer is passed to _outputPipeline
 	if (_needsScaling) {
+		_inputPipeline.setFramebuffer(&_inputTargets[_currentTarget]);
 		_inputPipeline.activate();
 	} else {
 		_outputPipeline.setFramebuffer(_activeFramebuffer);
@@ -335,8 +337,6 @@ void LibRetroPipeline::deactivateInternal() {
 }
 
 bool LibRetroPipeline::open(const Common::FSNode &shaderPreset) {
-	_inputTarget->create();
-
 	_shaderPreset = LibRetro::parsePreset(shaderPreset);
 	if (!_shaderPreset)
 		return false;
@@ -378,7 +378,8 @@ void LibRetroPipeline::close() {
 	_isAnimated = false;
 	_needsScaling = false;
 
-	_inputTarget->destroy();
+	_inputTargets.resize(0);
+	_currentTarget = uint(-1);
 }
 
 static Common::FSNode getChildRecursive(const Common::FSNode &basePath, const Common::String &fileName) {
@@ -450,6 +451,7 @@ bool LibRetroPipeline::loadPasses() {
 	}
 
 	_isAnimated = false;
+	uint maxPrevCount = 0;
 
 	// parameters are shared among all passes so we load them first and apply them to all shaders
 	UniformsMap uniformParams;
@@ -555,14 +557,16 @@ bool LibRetroPipeline::loadPasses() {
 
 		pass.buildTexCoords(passId, aliases);
 		pass.buildTexSamplers(passId, _textures, aliases);
-		if (passId == 0) {
-			_passes[0].inputTexture = _inputTarget->getTexture();
-		} else {
+		if (passId > 0) {
 			GLTexture *const texture = _passes[passId - 1].target->getTexture();
 			texture->enableLinearFiltering(i->filteringMode == LibRetro::kFilteringModeLinear);
 			texture->setWrapMode(i->wrapMode);
 			pass.inputTexture = texture;
 		}
+
+		if (pass.prevCount > maxPrevCount) {
+			maxPrevCount = pass.prevCount;
+		}
 	}
 
 	// Apply preset parameters last to override all others
@@ -577,6 +581,16 @@ bool LibRetroPipeline::loadPasses() {
 		}
 	}
 
+	// Create enough FBO for previous frames and current image
+	// All textures are created and destroyed at this moment
+	// FBOs are created on demand and destroyed here
+	_isAnimated |= (maxPrevCount > 0);
+
+	_inputTargets.resize(maxPrevCount + 1);
+
+	_currentTarget = 0;
+	_passes[0].inputTexture = _inputTargets[_currentTarget].getTexture();
+
 	// Now try to setup FBOs with some dummy size to make sure it could work
 	uint bakInputWidth = _inputWidth;
 	uint bakInputHeight = _inputHeight;
@@ -610,6 +624,13 @@ void LibRetroPipeline::setPipelineState() {
 }
 
 bool LibRetroPipeline::setupFBOs() {
+	// Setup the input targets sizes
+	for (Common::Array<LibRetroTextureTarget>::iterator it = _inputTargets.begin(); it != _inputTargets.end(); it++) {
+		if (!it->setScaledSize(_inputWidth, _inputHeight, _outputRect)) {
+			return false;
+		}
+	}
+
 	float sourceW = _inputWidth;
 	float sourceH = _inputHeight;
 
@@ -689,8 +710,7 @@ void LibRetroPipeline::setupPassUniforms(const uint id) {
 		}
 	}
 
-	// TODO: We do not support Prev right now. Instead we always use the orig
-	// texture for these.
+	// All frames always have the same sizes: we reset them all at once
 	setShaderTexUniforms("Prev", shader, *_passes[0].inputTexture);
 	for (uint prevId = 1; prevId <= 6; ++prevId) {
 		setShaderTexUniforms(Common::String::format("Prev%u", prevId), shader, *_passes[0].inputTexture);
@@ -799,26 +819,33 @@ void LibRetroPipeline::Pass::buildTexSamplers(const uint id, const TextureArray
 	addTexSampler("Orig", &sampler, TextureSampler::kTypePass, 0);
 
 	// 4. Step: Assign previous render inputs.
-	addTexSampler("Prev", &sampler, TextureSampler::kTypePrev, 0);
+	if (addTexSampler("Prev", &sampler, TextureSampler::kTypePrev, 0)) {
+		prevCount = 1;
+	}
 	for (uint prevId = 1; prevId <= 6; ++prevId) {
-		addTexSampler(Common::String::format("Prev%u", prevId), &sampler, TextureSampler::kTypePrev, prevId);
+		if (addTexSampler(Common::String::format("Prev%u", prevId), &sampler, TextureSampler::kTypePrev, prevId)) {
+			prevCount = prevId + 1;
+		}
 	}
 }
 
-void LibRetroPipeline::Pass::addTexSampler(const Common::String &prefix, uint *unit, const TextureSampler::Type type, const uint index, const bool prefixIsId) {
+bool LibRetroPipeline::Pass::addTexSampler(const Common::String &prefix, uint *unit, const TextureSampler::Type type, const uint index, const bool prefixIsId) {
 	const Common::String id = prefixIsId ? prefix : (prefix + "Texture");
 
 	/* Search in the samplers if we already have one for the texture */
 	for(TextureSamplerArray::iterator it = texSamplers.begin(); it != texSamplers.end(); it++) {
 		if (it->type == type && it->index == index) {
-			shader->setUniform(id, it->unit);
-			return;
+			return shader->setUniform(id, it->unit);
 		}
 	}
 
-	if (shader->setUniform(id, *unit)) {
-		texSamplers.push_back(TextureSampler((*unit)++, type, index));
+	if (!shader->setUniform(id, *unit)) {
+		return false;
 	}
+
+	texSamplers.push_back(TextureSampler((*unit)++, type, index));
+
+	return true;
 }
 
 void LibRetroPipeline::renderPass(const Pass &pass) {
@@ -869,7 +896,7 @@ void LibRetroPipeline::renderPassSetupCoordinates(const Pass &pass) {
 			break;
 
 		case Pass::TexCoordAttribute::kTypePrev:
-			// TODO: Properly support Prev
+			// All frames always have the same tex coordinates: we reset them all at once
 			texCoords = _passes[0].inputTexture->getTexCoords();
 			break;
 		}
@@ -905,11 +932,13 @@ void LibRetroPipeline::renderPassSetupTextures(const Pass &pass) {
 			texture = _passes[i->index].inputTexture;
 			break;
 
-		case Pass::TextureSampler::kTypePrev:
-			// TODO: Properly support Prev
-			texture = _passes[0].inputTexture;
+		case Pass::TextureSampler::kTypePrev: {
+			assert(i->index < _inputTargets.size() - 1);
+			texture = _inputTargets[(_currentTarget - i->index - 1
+					+ _inputTargets.size()) % _inputTargets.size()].getTexture();
 			break;
 		}
+		}
 
 		if (!texture) {
 			continue;
diff --git a/backends/graphics/opengl/pipelines/libretro.h b/backends/graphics/opengl/pipelines/libretro.h
index 29dca1da82a..377fa38afbf 100644
--- a/backends/graphics/opengl/pipelines/libretro.h
+++ b/backends/graphics/opengl/pipelines/libretro.h
@@ -107,7 +107,8 @@ private:
 	bool _isAnimated;
 	uint _frameCount;
 
-	LibRetroTextureTarget *_inputTarget;
+	Common::Array<LibRetroTextureTarget> _inputTargets;
+	uint _currentTarget;
 
 	struct Texture {
 		Texture() : textureData(nullptr), glTexture(nullptr) {}
@@ -124,11 +125,11 @@ private:
 
 	struct Pass {
 		Pass()
-			: shaderPass(nullptr), shader(nullptr), target(nullptr),
-			  texCoords(), texSamplers(), inputTexture(nullptr), vertexCoord(), hasFrameCount(false) {}
+			: shaderPass(nullptr), shader(nullptr), target(nullptr), texCoords(), texSamplers(),
+			inputTexture(nullptr), vertexCoord(), hasFrameCount(false), prevCount(0) {}
 		Pass(const LibRetro::ShaderPass *sP, Shader *s, TextureTarget *t)
-			: shaderPass(sP), shader(s), target(t), texCoords(),
-			  texSamplers(), inputTexture(nullptr), vertexCoord(), hasFrameCount(false) {}
+			: shaderPass(sP), shader(s), target(t), texCoords(), texSamplers(),
+			inputTexture(nullptr), vertexCoord(), hasFrameCount(false), prevCount(0) {}
 
 		const LibRetro::ShaderPass *shaderPass;
 		Shader *shader;
@@ -237,7 +238,7 @@ private:
 		 */
 		void buildTexSamplers(const uint id, const TextureArray &textures, const Common::StringArray &aliases);
 
-		void addTexSampler(const Common::String &name, uint *unit, const TextureSampler::Type type, const uint index, const bool prefixIsId = false);
+		bool addTexSampler(const Common::String &name, uint *unit, const TextureSampler::Type type, const uint index, const bool prefixIsId = false);
 
 		/**
 		 * Input texture of the pass.
@@ -254,6 +255,11 @@ private:
 		 * Allows to speed up if it is not here
 		 */
 		bool hasFrameCount;
+
+		/**
+		 * The number of previous frames this pass needs
+		 */
+		uint prevCount;
 	};
 
 	typedef Common::Array<Pass> PassArray;


Commit: 52903aff8a20d0a78d46a42863963fb0b8d65c70
    https://github.com/scummvm/scummvm/commit/52903aff8a20d0a78d46a42863963fb0b8d65c70
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2022-11-06T20:02:59+01:00

Commit Message:
BACKENDS: OPENGL: Close old preset before opening a new one

Changed paths:
    backends/graphics/opengl/pipelines/libretro.cpp


diff --git a/backends/graphics/opengl/pipelines/libretro.cpp b/backends/graphics/opengl/pipelines/libretro.cpp
index 31389bf9f05..d065ff770a7 100644
--- a/backends/graphics/opengl/pipelines/libretro.cpp
+++ b/backends/graphics/opengl/pipelines/libretro.cpp
@@ -337,6 +337,8 @@ void LibRetroPipeline::deactivateInternal() {
 }
 
 bool LibRetroPipeline::open(const Common::FSNode &shaderPreset) {
+	close();
+
 	_shaderPreset = LibRetro::parsePreset(shaderPreset);
 	if (!_shaderPreset)
 		return false;


Commit: e5c1a4249aa2ea91b811de87ae66f87dd38923bb
    https://github.com/scummvm/scummvm/commit/e5c1a4249aa2ea91b811de87ae66f87dd38923bb
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2022-11-06T20:02:59+01:00

Commit Message:
BACKENDS: OPENGL: When no shader is selected, close

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 fc61303d34f..22357b5482e 100644
--- a/backends/graphics/opengl/opengl-graphics.cpp
+++ b/backends/graphics/opengl/opengl-graphics.cpp
@@ -355,6 +355,8 @@ bool OpenGLGraphicsManager::loadShader(const Common::String &fileName) {
 			warning("Failed to load shader %s", fileName.c_str());
 			return false;
 		}
+	} else {
+		_libretroPipeline->close();
 	}
 #endif
 




More information about the Scummvm-git-logs mailing list