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.
This commit is contained in:
Le Philousophe 2022-10-31 11:54:14 +01:00
parent 239c115249
commit 6632e909da
10 changed files with 70 additions and 70 deletions

View file

@ -206,8 +206,10 @@ void AndroidGraphicsManager::refreshScreen() {
void AndroidGraphicsManager::touchControlDraw(int16 x, int16 y, int16 w, int16 h, const Common::Rect &clip) { void AndroidGraphicsManager::touchControlDraw(int16 x, int16 y, int16 w, int16 h, const Common::Rect &clip) {
_backBuffer.enableBlend(OpenGL::Framebuffer::kBlendModeTraditionalTransparency); _backBuffer.enableBlend(OpenGL::Framebuffer::kBlendModeTraditionalTransparency);
OpenGL::Pipeline::getActivePipeline()->drawTexture(_touchcontrols->getGLTexture(), OpenGL::Pipeline *pipeline = getPipeline();
x, y, w, h, clip); pipeline->activate();
pipeline->drawTexture(_touchcontrols->getGLTexture(),
x, y, w, h, clip);
} }
void AndroidGraphicsManager::touchControlNotifyChanged() { void AndroidGraphicsManager::touchControlNotifyChanged() {

View file

@ -638,6 +638,8 @@ void OpenGLGraphicsManager::updateScreen() {
} }
_overlay->updateGLTexture(); _overlay->updateGLTexture();
_pipeline->activate();
// Clear the screen buffer. // Clear the screen buffer.
GL_CALL(glClear(GL_COLOR_BUFFER_BIT)); GL_CALL(glClear(GL_COLOR_BUFFER_BIT));
@ -656,12 +658,15 @@ void OpenGLGraphicsManager::updateScreen() {
// First step: Draw the (virtual) game screen. // First step: Draw the (virtual) game screen.
#if !USE_FORCED_GLES #if !USE_FORCED_GLES
if (_libretroPipeline && _libretroPipeline->isInitialized()) { 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); _gameScreenTarget->enableBlend(Framebuffer::kBlendModeDisabled);
const GLTexture &gameScreenTexture = _gameScreen->getGLTexture(); const GLTexture &gameScreenTexture = _gameScreen->getGLTexture();
const uint retroWidth = gameScreenTexture.getLogicalWidth(), const uint retroWidth = gameScreenTexture.getLogicalWidth(),
retroHeight = gameScreenTexture.getLogicalHeight(); retroHeight = gameScreenTexture.getLogicalHeight();
Pipeline::getActivePipeline()->drawTexture(gameScreenTexture, 0, 0, retroWidth, retroHeight); _pipeline->drawTexture(gameScreenTexture, 0, 0, retroWidth, retroHeight);
// Draw the cursor if necessary. // Draw the cursor if necessary.
// If overlay is visible we draw it later to have the cursor above overlay // If overlay is visible we draw it later to have the cursor above overlay
@ -678,18 +683,20 @@ void OpenGLGraphicsManager::updateScreen() {
cursorHeight = cursorTexture.getLogicalHeight(); cursorHeight = cursorTexture.getLogicalHeight();
_gameScreenTarget->enableBlend(Framebuffer::kBlendModePremultipliedTransparency); _gameScreenTarget->enableBlend(Framebuffer::kBlendModePremultipliedTransparency);
Pipeline::getActivePipeline()->drawTexture(cursorTexture, gameScreenCursorX, gameScreenCursorY, cursorWidth, cursorHeight); _pipeline->drawTexture(cursorTexture, gameScreenCursorX, gameScreenCursorY, cursorWidth, cursorHeight);
needsCursor = false; needsCursor = false;
} }
Pipeline::getActivePipeline()->setFramebuffer(lastFramebuffer);
Pipeline *lastPipeline = Pipeline::setPipeline(_libretroPipeline); _libretroPipeline->activate();
Pipeline::getActivePipeline()->drawTexture(*_gameScreenTarget->getTexture(), _gameDrawRect.left, _gameDrawRect.top, _gameDrawRect.width(), _gameDrawRect.height()); _libretroPipeline->drawTexture(*_gameScreenTarget->getTexture(), _gameDrawRect.left, _gameDrawRect.top, _gameDrawRect.width(), _gameDrawRect.height());
Pipeline::setPipeline(lastPipeline);
// Restore ShaderPipeline for the next steps
_pipeline->setFramebuffer(&_backBuffer);
_pipeline->activate();
} else } else
#endif #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. // Second step: Draw the overlay if visible.
@ -697,14 +704,14 @@ void OpenGLGraphicsManager::updateScreen() {
int dstX = (_windowWidth - _overlayDrawRect.width()) / 2; int dstX = (_windowWidth - _overlayDrawRect.width()) / 2;
int dstY = (_windowHeight - _overlayDrawRect.height()) / 2; int dstY = (_windowHeight - _overlayDrawRect.height()) / 2;
_backBuffer.enableBlend(Framebuffer::kBlendModeTraditionalTransparency); _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. // Third step: Draw the cursor if necessary.
if (needsCursor) { if (needsCursor) {
_backBuffer.enableBlend(Framebuffer::kBlendModePremultipliedTransparency); _backBuffer.enableBlend(Framebuffer::kBlendModePremultipliedTransparency);
Pipeline::getActivePipeline()->drawTexture(_cursor->getGLTexture(), _pipeline->drawTexture(_cursor->getGLTexture(),
_cursorX - _cursorHotspotXScaled + _shakeOffsetScaled.x, _cursorX - _cursorHotspotXScaled + _shakeOffsetScaled.x,
_cursorY - _cursorHotspotYScaled + _shakeOffsetScaled.y, _cursorY - _cursorHotspotYScaled + _shakeOffsetScaled.y,
_cursorWidthScaled, _cursorHeightScaled); _cursorWidthScaled, _cursorHeightScaled);
@ -734,17 +741,17 @@ void OpenGLGraphicsManager::updateScreen() {
} }
// Set the OSD transparency. // 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 dstX = (_windowWidth - _osdMessageSurface->getWidth()) / 2;
int dstY = (_windowHeight - _osdMessageSurface->getHeight()) / 2; int dstY = (_windowHeight - _osdMessageSurface->getHeight()) / 2;
// Draw the OSD texture. // Draw the OSD texture.
Pipeline::getActivePipeline()->drawTexture(_osdMessageSurface->getGLTexture(), _pipeline->drawTexture(_osdMessageSurface->getGLTexture(),
dstX, dstY, _osdMessageSurface->getWidth(), _osdMessageSurface->getHeight()); dstX, dstY, _osdMessageSurface->getWidth(), _osdMessageSurface->getHeight());
// Reset color. // 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) { if (_osdMessageAlpha <= 0) {
delete _osdMessageSurface; delete _osdMessageSurface;
@ -761,8 +768,8 @@ void OpenGLGraphicsManager::updateScreen() {
int dstY = kOSDIconTopMargin; int dstY = kOSDIconTopMargin;
// Draw the OSD icon texture. // Draw the OSD icon texture.
Pipeline::getActivePipeline()->drawTexture(_osdIconSurface->getGLTexture(), _pipeline->drawTexture(_osdIconSurface->getGLTexture(),
dstX, dstY, _osdIconSurface->getWidth(), _osdIconSurface->getHeight()); dstX, dstY, _osdIconSurface->getWidth(), _osdIconSurface->getHeight());
} }
#endif #endif
@ -1165,7 +1172,6 @@ void OpenGLGraphicsManager::notifyContextCreate(ContextType type,
const Graphics::PixelFormat &defaultFormat, const Graphics::PixelFormat &defaultFormat,
const Graphics::PixelFormat &defaultFormatAlpha) { const Graphics::PixelFormat &defaultFormatAlpha) {
// Initialize pipeline. // Initialize pipeline.
Pipeline::setPipeline(nullptr);
delete _pipeline; delete _pipeline;
_pipeline = nullptr; _pipeline = nullptr;
@ -1258,10 +1264,6 @@ void OpenGLGraphicsManager::notifyContextCreate(ContextType type,
_osdIconSurface->recreate(); _osdIconSurface->recreate();
} }
#endif #endif
// Everything is ready: activate the pipeline
Pipeline::setPipeline(_pipeline);
} }
void OpenGLGraphicsManager::notifyContextDestroy() { void OpenGLGraphicsManager::notifyContextDestroy() {
@ -1300,7 +1302,6 @@ void OpenGLGraphicsManager::notifyContextDestroy() {
#endif #endif
// Destroy rendering pipeline. // Destroy rendering pipeline.
Pipeline::setPipeline(nullptr);
delete _pipeline; delete _pipeline;
_pipeline = nullptr; _pipeline = nullptr;

View file

@ -324,6 +324,8 @@ protected:
void updateLinearFiltering(); void updateLinearFiltering();
Pipeline *getPipeline() const { return _pipeline; }
/** /**
* The default pixel format of the backend. * The default pixel format of the backend.
*/ */

View file

@ -32,6 +32,8 @@ CLUT8LookUpPipeline::CLUT8LookUpPipeline()
} }
void CLUT8LookUpPipeline::drawTextureInternal(const GLTexture &texture, const GLfloat *coordinates, const GLfloat *texcoords) { void CLUT8LookUpPipeline::drawTextureInternal(const GLTexture &texture, const GLfloat *coordinates, const GLfloat *texcoords) {
assert(isActive());
// Set the palette texture. // Set the palette texture.
GL_CALL(glActiveTexture(GL_TEXTURE1)); GL_CALL(glActiveTexture(GL_TEXTURE1));
if (_paletteTexture) { if (_paletteTexture) {

View file

@ -40,13 +40,23 @@ void FixedPipeline::activateInternal() {
} }
#endif #endif
GL_CALL(glEnable(GL_TEXTURE_2D)); GL_CALL(glEnable(GL_TEXTURE_2D));
GL_CALL(glColor4f(_r, _g, _b, _a));
} }
void FixedPipeline::setColor(GLfloat r, GLfloat g, GLfloat b, GLfloat 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) { void FixedPipeline::drawTextureInternal(const GLTexture &texture, const GLfloat *coordinates, const GLfloat *texcoords) {
assert(isActive());
texture.bind(); texture.bind();
GL_CALL(glTexCoordPointer(2, GL_FLOAT, 0, texcoords)); 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) { void FixedPipeline::setProjectionMatrix(const Math::Matrix4 &projectionMatrix) {
if (!isActive()) { assert(isActive());
return;
}
GL_CALL(glMatrixMode(GL_PROJECTION)); GL_CALL(glMatrixMode(GL_PROJECTION));
GL_CALL(glLoadMatrixf(projectionMatrix.getData())); GL_CALL(glLoadMatrixf(projectionMatrix.getData()));

View file

@ -29,6 +29,8 @@ namespace OpenGL {
#if !USE_FORCED_GLES2 #if !USE_FORCED_GLES2
class FixedPipeline : public Pipeline { class FixedPipeline : public Pipeline {
public: 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 setColor(GLfloat r, GLfloat g, GLfloat b, GLfloat a) override;
void setProjectionMatrix(const Math::Matrix4 &projectionMatrix) override; void setProjectionMatrix(const Math::Matrix4 &projectionMatrix) override;
@ -36,6 +38,8 @@ public:
protected: protected:
void activateInternal() override; void activateInternal() override;
void drawTextureInternal(const GLTexture &texture, const GLfloat *coordinates, const GLfloat *texcoords) override; void drawTextureInternal(const GLTexture &texture, const GLfloat *coordinates, const GLfloat *texcoords) override;
GLfloat _r, _g, _b, _a;
}; };
#endif // !USE_FORCED_GLES2 #endif // !USE_FORCED_GLES2

View file

@ -27,11 +27,19 @@ namespace OpenGL {
Pipeline *Pipeline::activePipeline = nullptr; Pipeline *Pipeline::activePipeline = nullptr;
Pipeline::Pipeline() Pipeline::Pipeline()
: _activeFramebuffer(nullptr), _isActive(false) { : _activeFramebuffer(nullptr) {
} }
void Pipeline::activate() { void Pipeline::activate() {
_isActive = true; if (activePipeline == this) {
return;
}
if (activePipeline) {
activePipeline->deactivate();
}
activePipeline = this;
if (_activeFramebuffer) { if (_activeFramebuffer) {
_activeFramebuffer->activate(this); _activeFramebuffer->activate(this);
@ -41,41 +49,29 @@ void Pipeline::activate() {
} }
void Pipeline::deactivate() { void Pipeline::deactivate() {
assert(isActive());
deactivateInternal(); deactivateInternal();
if (_activeFramebuffer) { if (_activeFramebuffer) {
_activeFramebuffer->deactivate(); _activeFramebuffer->deactivate();
} }
_isActive = false; activePipeline = nullptr;
} }
Framebuffer *Pipeline::setFramebuffer(Framebuffer *framebuffer) { Framebuffer *Pipeline::setFramebuffer(Framebuffer *framebuffer) {
Framebuffer *oldFramebuffer = _activeFramebuffer; Framebuffer *oldFramebuffer = _activeFramebuffer;
if (_isActive && oldFramebuffer) { if (isActive() && oldFramebuffer) {
oldFramebuffer->deactivate(); oldFramebuffer->deactivate();
} }
_activeFramebuffer = framebuffer; _activeFramebuffer = framebuffer;
if (_isActive && _activeFramebuffer) { if (isActive() && _activeFramebuffer) {
_activeFramebuffer->activate(this); _activeFramebuffer->activate(this);
} }
return oldFramebuffer; 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 } // End of namespace OpenGL

View file

@ -42,7 +42,7 @@ class Framebuffer;
class Pipeline { class Pipeline {
public: public:
Pipeline(); Pipeline();
virtual ~Pipeline() {} virtual ~Pipeline() { if (isActive()) deactivate(); }
/** /**
* Activate the pipeline. * Activate the pipeline.
@ -150,31 +150,13 @@ protected:
virtual void drawTextureInternal(const GLTexture &texture, const GLfloat *coordinates, const GLfloat *texcoords) = 0; 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; Framebuffer *_activeFramebuffer;
private: private:
bool _isActive;
/** Currently active rendering pipeline. */ /** Currently active rendering pipeline. */
static Pipeline *activePipeline; 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 } // End of namespace OpenGL

View file

@ -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) { void ShaderPipeline::drawTextureInternal(const GLTexture &texture, const GLfloat *coordinates, const GLfloat *texcoords) {
assert(isActive());
texture.bind(); texture.bind();
GL_CALL(glBindBuffer(GL_ARRAY_BUFFER, _coordsVBO)); 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) { void ShaderPipeline::setProjectionMatrix(const Math::Matrix4 &projectionMatrix) {
assert(isActive());
_activeShader->setUniform("projection", projectionMatrix); _activeShader->setUniform("projection", projectionMatrix);
} }
#endif // !USE_FORCED_GLES #endif // !USE_FORCED_GLES

View file

@ -796,13 +796,12 @@ void TextureCLUT8GPU::updateGLTexture() {
void TextureCLUT8GPU::lookUpColors() { void TextureCLUT8GPU::lookUpColors() {
// Setup pipeline to do color look up. // Setup pipeline to do color look up.
Pipeline *oldPipeline = Pipeline::setPipeline(_clut8Pipeline); _clut8Pipeline->activate();
// Do color look up. // Do color look up.
Pipeline::getActivePipeline()->drawTexture(_clut8Texture, _clut8Vertices); _clut8Pipeline->drawTexture(_clut8Texture, _clut8Vertices);
// Restore old state. _clut8Pipeline->deactivate();
Pipeline::setPipeline(oldPipeline);
} }
#endif // !USE_FORCED_GLES #endif // !USE_FORCED_GLES