OPENGL: Add compatibility checks for LibRetro shader support

This commit is contained in:
Cameron Cawley 2022-06-30 21:13:00 +01:00 committed by Eugene Sandulenko
parent cdbb0fa32f
commit c5705561b0
3 changed files with 62 additions and 21 deletions

View file

@ -61,19 +61,24 @@
#include "common/text-to-speech.h" #include "common/text-to-speech.h"
#if !USE_FORCED_GLES
#include "backends/graphics/opengl/pipelines/libretro/parser.h" #include "backends/graphics/opengl/pipelines/libretro/parser.h"
#endif
namespace OpenGL { namespace OpenGL {
OpenGLGraphicsManager::OpenGLGraphicsManager() OpenGLGraphicsManager::OpenGLGraphicsManager()
: _currentState(), _oldState(), _transactionMode(kTransactionNone), _screenChangeID(1 << (sizeof(int) * 8 - 2)), : _currentState(), _oldState(), _transactionMode(kTransactionNone), _screenChangeID(1 << (sizeof(int) * 8 - 2)),
_pipeline(nullptr), _libretroPipeline(nullptr), _stretchMode(STRETCH_FIT), _pipeline(nullptr), _stretchMode(STRETCH_FIT),
_defaultFormat(), _defaultFormatAlpha(), _defaultFormat(), _defaultFormatAlpha(),
_gameScreen(nullptr), _gameScreenTarget(nullptr), _overlay(nullptr), _gameScreen(nullptr), _overlay(nullptr),
_cursor(nullptr), _cursor(nullptr),
_cursorHotspotX(0), _cursorHotspotY(0), _cursorHotspotX(0), _cursorHotspotY(0),
_cursorHotspotXScaled(0), _cursorHotspotYScaled(0), _cursorWidthScaled(0), _cursorHeightScaled(0), _cursorHotspotXScaled(0), _cursorHotspotYScaled(0), _cursorWidthScaled(0), _cursorHeightScaled(0),
_cursorKeyColor(0), _cursorDontScale(false), _cursorPaletteEnabled(false), _shakeOffsetScaled() _cursorKeyColor(0), _cursorDontScale(false), _cursorPaletteEnabled(false), _shakeOffsetScaled()
#if !USE_FORCED_GLES
, _libretroPipeline(nullptr), _gameScreenTarget(nullptr)
#endif
#ifdef USE_OSD #ifdef USE_OSD
, _osdMessageChangeRequest(false), _osdMessageAlpha(0), _osdMessageFadeStartTime(0), _osdMessageSurface(nullptr), , _osdMessageChangeRequest(false), _osdMessageAlpha(0), _osdMessageFadeStartTime(0), _osdMessageSurface(nullptr),
_osdIconSurface(nullptr) _osdIconSurface(nullptr)
@ -87,7 +92,6 @@ OpenGLGraphicsManager::OpenGLGraphicsManager()
} }
OpenGLGraphicsManager::~OpenGLGraphicsManager() { OpenGLGraphicsManager::~OpenGLGraphicsManager() {
delete _gameScreenTarget;
delete _gameScreen; delete _gameScreen;
delete _overlay; delete _overlay;
delete _cursor; delete _cursor;
@ -96,6 +100,7 @@ OpenGLGraphicsManager::~OpenGLGraphicsManager() {
delete _osdIconSurface; delete _osdIconSurface;
#endif #endif
#if !USE_FORCED_GLES #if !USE_FORCED_GLES
delete _gameScreenTarget;
ShaderManager::destroy(); ShaderManager::destroy();
#endif #endif
} }
@ -456,11 +461,13 @@ OSystem::TransactionError OpenGLGraphicsManager::endGFXTransaction() {
delete _gameScreen; delete _gameScreen;
_gameScreen = nullptr; _gameScreen = nullptr;
#if !USE_FORCED_GLES
if (_gameScreenTarget != nullptr) { if (_gameScreenTarget != nullptr) {
_gameScreenTarget->destroy(); _gameScreenTarget->destroy();
delete _gameScreenTarget; delete _gameScreenTarget;
_gameScreenTarget = nullptr; _gameScreenTarget = nullptr;
} }
#endif
bool wantScaler = _currentState.scaleFactor > 1; bool wantScaler = _currentState.scaleFactor > 1;
@ -493,11 +500,13 @@ OSystem::TransactionError OpenGLGraphicsManager::endGFXTransaction() {
_gameScreen->fill(0); _gameScreen->fill(0);
#endif #endif
#if !USE_FORCED_GLES
if (_libretroPipeline) { if (_libretroPipeline) {
_gameScreenTarget = new TextureTarget(); _gameScreenTarget = new TextureTarget();
_gameScreenTarget->create(); _gameScreenTarget->create();
_gameScreenTarget->setSize(_currentState.gameWidth, _currentState.gameHeight); _gameScreenTarget->setSize(_currentState.gameWidth, _currentState.gameHeight);
} }
#endif
} }
// Update our display area and cursor scaling. This makes sure we pick up // Update our display area and cursor scaling. This makes sure we pick up
@ -603,25 +612,31 @@ void OpenGLGraphicsManager::updateScreen() {
// Alpha blending is disabled when drawing the screen // Alpha blending is disabled when drawing the screen
_backBuffer.enableBlend(Framebuffer::kBlendModeDisabled); _backBuffer.enableBlend(Framebuffer::kBlendModeDisabled);
bool needsCursor = _cursorVisible && _cursor;
// First step: Draw the (virtual) game screen. // First step: Draw the (virtual) game screen.
if (_libretroPipeline) { #if !USE_FORCED_GLES
if (_libretroPipeline && _libretroPipeline->isInitialized()) {
Framebuffer *lastFramebuffer = Pipeline::getActivePipeline()->setFramebuffer(_gameScreenTarget); Framebuffer *lastFramebuffer = Pipeline::getActivePipeline()->setFramebuffer(_gameScreenTarget);
_gameScreenTarget->enableBlend(Framebuffer::kBlendModeDisabled); _gameScreenTarget->enableBlend(Framebuffer::kBlendModeDisabled);
Pipeline::getActivePipeline()->drawTexture(_gameScreen->getGLTexture(), 0, 0, _gameScreen->getWidth(), _gameScreen->getHeight()); Pipeline::getActivePipeline()->drawTexture(_gameScreen->getGLTexture(), 0, 0, _gameScreen->getWidth(), _gameScreen->getHeight());
// Draw the cursor if necessary. // Draw the cursor if necessary.
if (_cursorVisible && _cursor && !_overlayVisible) { if (needsCursor && !_overlayVisible) {
int gameScreenCursorX = (_cursorX - _gameDrawRect.left) * _gameScreen->getWidth() / _gameDrawRect.width() - _cursorHotspotX; int gameScreenCursorX = (_cursorX - _gameDrawRect.left) * _gameScreen->getWidth() / _gameDrawRect.width() - _cursorHotspotX;
int gameScreenCursorY = (_cursorY - _gameDrawRect.top) * _gameScreen->getHeight() / _gameDrawRect.height() - _cursorHotspotY; int gameScreenCursorY = (_cursorY - _gameDrawRect.top) * _gameScreen->getHeight() / _gameDrawRect.height() - _cursorHotspotY;
_gameScreenTarget->enableBlend(Framebuffer::kBlendModePremultipliedTransparency); _gameScreenTarget->enableBlend(Framebuffer::kBlendModePremultipliedTransparency);
Pipeline::getActivePipeline()->drawTexture(_cursor->getGLTexture(), gameScreenCursorX, gameScreenCursorY, _cursor->getWidth(), _cursor->getHeight()); Pipeline::getActivePipeline()->drawTexture(_cursor->getGLTexture(), gameScreenCursorX, gameScreenCursorY, _cursor->getWidth(), _cursor->getHeight());
needsCursor = false;
} }
Pipeline::getActivePipeline()->setFramebuffer(lastFramebuffer); Pipeline::getActivePipeline()->setFramebuffer(lastFramebuffer);
Pipeline *lastPipeline = Pipeline::setPipeline(_libretroPipeline); Pipeline *lastPipeline = Pipeline::setPipeline(_libretroPipeline);
Pipeline::getActivePipeline()->drawTexture(*_gameScreenTarget->getTexture(), _gameDrawRect.left, _gameDrawRect.top, _gameDrawRect.width(), _gameDrawRect.height()); Pipeline::getActivePipeline()->drawTexture(*_gameScreenTarget->getTexture(), _gameDrawRect.left, _gameDrawRect.top, _gameDrawRect.width(), _gameDrawRect.height());
Pipeline::setPipeline(lastPipeline); Pipeline::setPipeline(lastPipeline);
} else { } else
#endif
{
Pipeline::getActivePipeline()->drawTexture(_gameScreen->getGLTexture(), _gameDrawRect.left, _gameDrawRect.top, _gameDrawRect.width(), _gameDrawRect.height()); Pipeline::getActivePipeline()->drawTexture(_gameScreen->getGLTexture(), _gameDrawRect.left, _gameDrawRect.top, _gameDrawRect.width(), _gameDrawRect.height());
} }
@ -634,7 +649,7 @@ void OpenGLGraphicsManager::updateScreen() {
} }
// Third step: Draw the cursor if necessary. // Third step: Draw the cursor if necessary.
if (_cursorVisible && _cursor && (_overlayVisible || !_libretroPipeline)) { if (needsCursor) {
_backBuffer.enableBlend(Framebuffer::kBlendModePremultipliedTransparency); _backBuffer.enableBlend(Framebuffer::kBlendModePremultipliedTransparency);
Pipeline::getActivePipeline()->drawTexture(_cursor->getGLTexture(), Pipeline::getActivePipeline()->drawTexture(_cursor->getGLTexture(),
@ -1109,10 +1124,12 @@ void OpenGLGraphicsManager::notifyContextCreate(ContextType type,
delete _pipeline; delete _pipeline;
_pipeline = nullptr; _pipeline = nullptr;
#if !USE_FORCED_GLES
if (_libretroPipeline) { if (_libretroPipeline) {
delete _libretroPipeline; delete _libretroPipeline;
_libretroPipeline = nullptr; _libretroPipeline = nullptr;
} }
#endif
OpenGLContext.initialize(type); OpenGLContext.initialize(type);
@ -1120,14 +1137,6 @@ void OpenGLGraphicsManager::notifyContextCreate(ContextType type,
if (OpenGLContext.shadersSupported) { if (OpenGLContext.shadersSupported) {
ShaderMan.notifyCreate(); ShaderMan.notifyCreate();
_pipeline = new ShaderPipeline(ShaderMan.query(ShaderManager::kDefault)); _pipeline = new ShaderPipeline(ShaderMan.query(ShaderManager::kDefault));
// Load selected shader preset from config file
if (ConfMan.hasKey("shader_scaler", Common::ConfigManager::kApplicationDomain)) {
Common::FSNode shaderPreset(ConfMan.get("shader_scaler", Common::ConfigManager::kApplicationDomain));
if (shaderPreset.isReadable()) {
_libretroPipeline = new LibRetroPipeline(shaderPreset);
}
}
} }
#endif #endif
@ -1144,10 +1153,6 @@ void OpenGLGraphicsManager::notifyContextCreate(ContextType type,
_pipeline->setColor(1.0f, 1.0f, 1.0f, 1.0f); _pipeline->setColor(1.0f, 1.0f, 1.0f, 1.0f);
if (_libretroPipeline) {
_libretroPipeline->setColor(1.0f, 1.0f, 1.0f, 1.0f);
}
// Setup backbuffer state. // Setup backbuffer state.
// Default to black as clear color. // Default to black as clear color.
@ -1155,9 +1160,26 @@ void OpenGLGraphicsManager::notifyContextCreate(ContextType type,
_pipeline->setFramebuffer(&_backBuffer); _pipeline->setFramebuffer(&_backBuffer);
if (_libretroPipeline) { // Setup LibRetro pipeline.
#if !USE_FORCED_GLES
if (LibRetroPipeline::isSupportedByContext()) {
_libretroPipeline = new LibRetroPipeline();
// Load selected shader preset from config file
// TODO: Handle this in endGFXTransaction()
if (ConfMan.hasKey("shader_scaler", Common::ConfigManager::kApplicationDomain)) {
Common::FSNode shaderPreset(ConfMan.get("shader_scaler", Common::ConfigManager::kApplicationDomain));
if (shaderPreset.isReadable()) {
if (!_libretroPipeline->open(shaderPreset))
warning("Failed to load %s", shaderPreset.getName().c_str());
}
}
_libretroPipeline->setColor(1.0f, 1.0f, 1.0f, 1.0f);
_libretroPipeline->setFramebuffer(&_backBuffer); _libretroPipeline->setFramebuffer(&_backBuffer);
} }
#endif
// We use a "pack" alignment (when reading from textures) to 4 here, // 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 // since the only place where we really use it is the BMP screenshot
@ -1179,9 +1201,11 @@ void OpenGLGraphicsManager::notifyContextCreate(ContextType type,
_gameScreen->recreate(); _gameScreen->recreate();
} }
#if !USE_FORCED_GLES
if (_gameScreenTarget) { if (_gameScreenTarget) {
_gameScreenTarget->create(); _gameScreenTarget->create();
} }
#endif
if (_overlay) { if (_overlay) {
_overlay->recreate(); _overlay->recreate();
@ -1211,9 +1235,11 @@ void OpenGLGraphicsManager::notifyContextDestroy() {
_gameScreen->destroy(); _gameScreen->destroy();
} }
#if !USE_FORCED_GLES
if (_gameScreenTarget) { if (_gameScreenTarget) {
_gameScreenTarget->destroy(); _gameScreenTarget->destroy();
} }
#endif
if (_overlay) { if (_overlay) {
_overlay->destroy(); _overlay->destroy();
@ -1244,10 +1270,12 @@ void OpenGLGraphicsManager::notifyContextDestroy() {
delete _pipeline; delete _pipeline;
_pipeline = nullptr; _pipeline = nullptr;
#if !USE_FORCED_GLES
if (_libretroPipeline) { if (_libretroPipeline) {
delete _libretroPipeline; delete _libretroPipeline;
_libretroPipeline = nullptr; _libretroPipeline = nullptr;
} }
#endif
// Rest our context description since the context is gone soon. // Rest our context description since the context is gone soon.
OpenGLContext.reset(); OpenGLContext.reset();

View file

@ -44,6 +44,9 @@ namespace OpenGL {
class Surface; class Surface;
class Pipeline; class Pipeline;
#if !USE_FORCED_GLES
class LibRetroPipeline;
#endif
enum { enum {
GFX_OPENGL = 0 GFX_OPENGL = 0
@ -290,10 +293,12 @@ private:
*/ */
Pipeline *_pipeline; Pipeline *_pipeline;
#if !USE_FORCED_GLES
/** /**
* OpenGL pipeline used for post-processing. * OpenGL pipeline used for post-processing.
*/ */
Pipeline *_libretroPipeline; LibRetroPipeline *_libretroPipeline;
#endif
protected: protected:
/** /**
@ -333,11 +338,13 @@ protected:
*/ */
byte _gamePalette[3 * 256]; byte _gamePalette[3 * 256];
#if !USE_FORCED_GLES
/** /**
* The render target for the virtual game screen. Used when * The render target for the virtual game screen. Used when
* LibRetro shaders are enabled. * LibRetro shaders are enabled.
*/ */
TextureTarget *_gameScreenTarget; TextureTarget *_gameScreenTarget;
#endif
// //
// Overlay // Overlay

View file

@ -63,6 +63,12 @@ public:
void close(); void close();
bool isInitialized() const { return _shaderPreset != nullptr; } bool isInitialized() const { return _shaderPreset != nullptr; }
static bool isSupportedByContext() {
return OpenGLContext.shadersSupported
&& OpenGLContext.multitextureSupported
&& OpenGLContext.framebufferObjectSupported;
}
private: private:
virtual void activateInternal(); virtual void activateInternal();
virtual void deactivateInternal(); virtual void deactivateInternal();