From adda0dc063ed4a348a0b11e4eeed7598fc35aea7 Mon Sep 17 00:00:00 2001 From: Le Philousophe Date: Sun, 11 Jun 2023 12:21:27 +0200 Subject: [PATCH] BACKENDS: OPENGL: Allow the backend to specify the render target For now only backbuffer is used. --- .../graphics/android/android-graphics.cpp | 4 +- backends/graphics/opengl/opengl-graphics.cpp | 38 ++++++++++++------- backends/graphics/opengl/opengl-graphics.h | 5 ++- .../graphics/openglsdl/openglsdl-graphics.cpp | 4 +- 4 files changed, 32 insertions(+), 19 deletions(-) diff --git a/backends/graphics/android/android-graphics.cpp b/backends/graphics/android/android-graphics.cpp index a545bfa5836..28d73d490a2 100644 --- a/backends/graphics/android/android-graphics.cpp +++ b/backends/graphics/android/android-graphics.cpp @@ -96,11 +96,13 @@ void AndroidGraphicsManager::initSurface() { if (JNI::egl_bits_per_pixel == 16) { // We default to RGB565 and RGBA5551 which is closest to what we setup in Java side notifyContextCreate(OpenGL::kContextGLES2, + new OpenGL::Backbuffer(), Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0), Graphics::PixelFormat(2, 5, 5, 5, 1, 11, 6, 1, 0)); } else { // If not 16, this must be 24 or 32 bpp so make use of them notifyContextCreate(OpenGL::kContextGLES2, + new OpenGL::Backbuffer(), #ifdef SCUMM_BIG_ENDIAN Graphics::PixelFormat(3, 8, 8, 8, 0, 16, 8, 0, 0), Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0) @@ -234,7 +236,7 @@ void AndroidGraphicsManager::refreshScreen() { } void AndroidGraphicsManager::touchControlDraw(int16 x, int16 y, int16 w, int16 h, const Common::Rect &clip) { - _backBuffer.enableBlend(OpenGL::Framebuffer::kBlendModeTraditionalTransparency); + _targetBuffer->enableBlend(OpenGL::Framebuffer::kBlendModeTraditionalTransparency); OpenGL::Pipeline *pipeline = getPipeline(); pipeline->activate(); pipeline->drawTexture(_touchcontrols->getGLTexture(), diff --git a/backends/graphics/opengl/opengl-graphics.cpp b/backends/graphics/opengl/opengl-graphics.cpp index d93d00c5112..b537522ace6 100644 --- a/backends/graphics/opengl/opengl-graphics.cpp +++ b/backends/graphics/opengl/opengl-graphics.cpp @@ -71,7 +71,7 @@ namespace OpenGL { OpenGLGraphicsManager::OpenGLGraphicsManager() : _currentState(), _oldState(), _transactionMode(kTransactionNone), _screenChangeID(1 << (sizeof(int) * 8 - 2)), _pipeline(nullptr), _stretchMode(STRETCH_FIT), - _defaultFormat(), _defaultFormatAlpha(), + _defaultFormat(), _defaultFormatAlpha(), _targetBuffer(nullptr), _gameScreen(nullptr), _overlay(nullptr), _cursor(nullptr), _cursorMask(nullptr), _cursorHotspotX(0), _cursorHotspotY(0), @@ -105,6 +105,7 @@ OpenGLGraphicsManager::~OpenGLGraphicsManager() { ShaderManager::destroy(); #endif delete _pipeline; + delete _targetBuffer; } bool OpenGLGraphicsManager::hasFeature(OSystem::Feature f) const { @@ -609,16 +610,16 @@ void OpenGLGraphicsManager::renderCursor() { the inversion and opacity mask at once. We use 1-srcAlpha instead of srcAlpha so zero-fill is transparent. */ if (_cursorMask) { - _backBuffer.enableBlend(Framebuffer::kBlendModeMaskAlphaAndInvertByColor); + _targetBuffer->enableBlend(Framebuffer::kBlendModeMaskAlphaAndInvertByColor); _pipeline->drawTexture(_cursorMask->getGLTexture(), _cursorX - _cursorHotspotXScaled + _shakeOffsetScaled.x, _cursorY - _cursorHotspotYScaled + _shakeOffsetScaled.y, _cursorWidthScaled, _cursorHeightScaled); - _backBuffer.enableBlend(Framebuffer::kBlendModeAdditive); + _targetBuffer->enableBlend(Framebuffer::kBlendModeAdditive); } else - _backBuffer.enableBlend(Framebuffer::kBlendModePremultipliedTransparency); + _targetBuffer->enableBlend(Framebuffer::kBlendModePremultipliedTransparency); _pipeline->drawTexture(_cursor->getGLTexture(), _cursorX - _cursorHotspotXScaled + _shakeOffsetScaled.x, @@ -687,14 +688,14 @@ void OpenGLGraphicsManager::updateScreen() { // The scissor test is enabled to: // - Clip the cursor to the game screen // - Clip the game screen when the shake offset is non-zero - _backBuffer.enableScissorTest(true); + _targetBuffer->enableScissorTest(true); } // Don't draw cursor if it's not visible or there is none bool drawCursor = _cursorVisible && _cursor; // Alpha blending is disabled when drawing the screen - _backBuffer.enableBlend(Framebuffer::kBlendModeDisabled); + _targetBuffer->enableBlend(Framebuffer::kBlendModeDisabled); // First step: Draw the (virtual) game screen. _pipeline->drawTexture(_gameScreen->getGLTexture(), _gameDrawRect.left, _gameDrawRect.top, _gameDrawRect.width(), _gameDrawRect.height()); @@ -710,7 +711,7 @@ void OpenGLGraphicsManager::updateScreen() { drawCursor = false; // Everything we need to clip has been clipped - _backBuffer.enableScissorTest(false); + _targetBuffer->enableScissorTest(false); } // Overlay must not be scaled and its cursor won't be either @@ -722,7 +723,7 @@ void OpenGLGraphicsManager::updateScreen() { if (_overlayVisible) { int dstX = (_windowWidth - _overlayDrawRect.width()) / 2; int dstY = (_windowHeight - _overlayDrawRect.height()) / 2; - _backBuffer.enableBlend(Framebuffer::kBlendModeTraditionalTransparency); + _targetBuffer->enableBlend(Framebuffer::kBlendModeTraditionalTransparency); _pipeline->drawTexture(_overlay->getGLTexture(), dstX, dstY, _overlayDrawRect.width(), _overlayDrawRect.height()); } @@ -731,13 +732,13 @@ void OpenGLGraphicsManager::updateScreen() { renderCursor(); if (!_overlayVisible) { - _backBuffer.enableScissorTest(false); + _targetBuffer->enableScissorTest(false); } #ifdef USE_OSD // Fourth step: Draw the OSD. if (_osdMessageSurface || _osdIconSurface) { - _backBuffer.enableBlend(Framebuffer::kBlendModeTraditionalTransparency); + _targetBuffer->enableBlend(Framebuffer::kBlendModeTraditionalTransparency); } if (_osdMessageSurface) { @@ -1261,7 +1262,7 @@ void OpenGLGraphicsManager::grabPalette(byte *colors, uint start, uint num) cons void OpenGLGraphicsManager::handleResizeImpl(const int width, const int height) { // Setup backbuffer size. - _backBuffer.setSize(width, height); + _targetBuffer->setSize(width, height); uint overlayWidth = width; uint overlayHeight = height; @@ -1312,8 +1313,13 @@ void OpenGLGraphicsManager::handleResizeImpl(const int width, const int height) } void OpenGLGraphicsManager::notifyContextCreate(ContextType type, + Framebuffer *target, const Graphics::PixelFormat &defaultFormat, const Graphics::PixelFormat &defaultFormatAlpha) { + // Set up the target: backbuffer usually + delete _targetBuffer; + _targetBuffer = target; + // Initialize pipeline. delete _pipeline; _pipeline = nullptr; @@ -1361,9 +1367,9 @@ void OpenGLGraphicsManager::notifyContextCreate(ContextType type, // Setup backbuffer state. // Default to opaque black as clear color. - _backBuffer.setClearColor(0.0f, 0.0f, 0.0f, 1.0f); + _targetBuffer->setClearColor(0.0f, 0.0f, 0.0f, 1.0f); - _pipeline->setFramebuffer(&_backBuffer); + _pipeline->setFramebuffer(_targetBuffer); // 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 @@ -1450,6 +1456,10 @@ void OpenGLGraphicsManager::notifyContextDestroy() { _libretroPipeline = nullptr; #endif + // Destroy the target + delete _targetBuffer; + _targetBuffer = nullptr; + // Rest our context description since the context is gone soon. OpenGLContext.reset(); } @@ -1632,7 +1642,7 @@ void OpenGLGraphicsManager::recalculateDisplayAreas() { // Setup drawing limitation for game graphics. // This involves some trickery because OpenGL's viewport coordinate system // is upside down compared to ours. - _backBuffer.setScissorBox(_gameDrawRect.left, + _targetBuffer->setScissorBox(_gameDrawRect.left, _windowHeight - _gameDrawRect.height() - _gameDrawRect.top, _gameDrawRect.width(), _gameDrawRect.height()); diff --git a/backends/graphics/opengl/opengl-graphics.h b/backends/graphics/opengl/opengl-graphics.h index e60146df718..5532559da37 100644 --- a/backends/graphics/opengl/opengl-graphics.h +++ b/backends/graphics/opengl/opengl-graphics.h @@ -149,6 +149,7 @@ protected: */ void notifyContextCreate( ContextType type, + Framebuffer *target, const Graphics::PixelFormat &defaultFormat, const Graphics::PixelFormat &defaultFormatAlpha); @@ -339,9 +340,9 @@ protected: Graphics::PixelFormat _defaultFormatAlpha; /** - * Render back buffer. + * Render target. */ - Backbuffer _backBuffer; + Framebuffer *_targetBuffer; /** * The rendering surface for the virtual game screen. diff --git a/backends/graphics/openglsdl/openglsdl-graphics.cpp b/backends/graphics/openglsdl/openglsdl-graphics.cpp index 9f7a30950f4..bebd7b9ff21 100644 --- a/backends/graphics/openglsdl/openglsdl-graphics.cpp +++ b/backends/graphics/openglsdl/openglsdl-graphics.cpp @@ -547,7 +547,7 @@ bool OpenGLSdlGraphicsManager::setupMode(uint width, uint height) { warning("Unable to %s VSync: %s", _vsync ? "enable" : "disable", SDL_GetError()); } - notifyContextCreate(_glContextType, rgba8888, rgba8888); + notifyContextCreate(_glContextType, new OpenGL::Backbuffer(), rgba8888, rgba8888); int actualWidth, actualHeight; getWindowSizeFromSdl(&actualWidth, &actualHeight); @@ -616,7 +616,7 @@ bool OpenGLSdlGraphicsManager::setupMode(uint width, uint height) { _lastVideoModeLoad = SDL_GetTicks(); if (_hwScreen) { - notifyContextCreate(_glContextType, rgba8888, rgba8888); + notifyContextCreate(_glContextType, new OpenGL::Backbuffer(), rgba8888, rgba8888); handleResize(_hwScreen->w, _hwScreen->h); }