From b380fc3b774169c6d8da8f50f4cbf7a11d20c42c Mon Sep 17 00:00:00 2001 From: Joe Date: Tue, 7 Mar 2023 21:11:58 +0100 Subject: [PATCH] Add OpenGL ES compatibility --- .../VideoRenderers/RPRendererOpenGLES.cpp | 158 +++++++++++------- .../VideoRenderers/RPRendererOpenGLES.h | 13 ++ .../RetroPlayer/shaders/gl/ShaderLutGL.cpp | 2 + .../RetroPlayer/shaders/gl/ShaderPresetGL.cpp | 14 +- .../RetroPlayer/shaders/gl/ShaderUtilsGL.cpp | 4 + 5 files changed, 131 insertions(+), 60 deletions(-) diff --git a/xbmc/cores/RetroPlayer/rendering/VideoRenderers/RPRendererOpenGLES.cpp b/xbmc/cores/RetroPlayer/rendering/VideoRenderers/RPRendererOpenGLES.cpp index b8e4259147d02..22616afb641b2 100644 --- a/xbmc/cores/RetroPlayer/rendering/VideoRenderers/RPRendererOpenGLES.cpp +++ b/xbmc/cores/RetroPlayer/rendering/VideoRenderers/RPRendererOpenGLES.cpp @@ -12,6 +12,7 @@ #include "cores/RetroPlayer/buffers/RenderBufferPoolOpenGLES.h" #include "cores/RetroPlayer/rendering/RenderContext.h" #include "cores/RetroPlayer/rendering/RenderVideoSettings.h" +#include "cores/RetroPlayer/shaders/gl/ShaderPresetGL.h" #include "utils/GLUtils.h" #include "utils/log.h" @@ -48,6 +49,9 @@ CRPRendererOpenGLES::CRPRendererOpenGLES(const CRenderSettings& renderSettings, std::shared_ptr bufferPool) : CRPBaseRenderer(renderSettings, context, std::move(bufferPool)) { + // Initialize CRPBaseRenderer + m_shaderPreset.reset(new SHADER::CShaderPresetGL(m_context)); + glGenBuffers(1, &m_mainIndexVBO); glGenBuffers(1, &m_mainVertexVBO); glGenBuffers(1, &m_blackbarsVertexVBO); @@ -245,7 +249,29 @@ void CRPRendererOpenGLES::Render(uint8_t alpha) const uint32_t color = (alpha << 24) | 0xFFFFFF; - glBindTexture(m_textureTarget, renderBuffer->TextureID()); + RenderBufferTextures* rbTextures; + const auto it = m_RBTexturesMap.find(renderBuffer); + if (it != m_RBTexturesMap.end()) + { + rbTextures = it->second.get(); + } + else + { + // We can't copy or move CGLTexture, so construct source/target in-place + rbTextures = new RenderBufferTextures{{// source texture + static_cast(renderBuffer->GetWidth()), + static_cast(renderBuffer->GetHeight()), + GL_RGB, renderBuffer->TextureID()}, + {// target texture + static_cast(m_context.GetScreenWidth()), + static_cast(m_context.GetScreenHeight())}}; + m_RBTexturesMap.emplace(renderBuffer, rbTextures); + } + + const auto sourceTexture = &rbTextures->source; + const auto targetTexture = &rbTextures->target; + + glBindTexture(m_textureTarget, sourceTexture->getMTexture()); GLint filter = GL_NEAREST; if (GetRenderSettings().VideoSettings().GetScalingMethod() == SCALINGMETHOD::LINEAR) @@ -255,63 +281,83 @@ void CRPRendererOpenGLES::Render(uint8_t alpha) glTexParameteri(m_textureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(m_textureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - m_context.EnableGUIShader(GL_SHADER_METHOD::TEXTURE_NOALPHA); + Updateshaders(); - GLubyte colour[4]; - GLubyte idx[4] = {0, 1, 3, 2}; // Determines order of triangle strip - struct PackedVertex + if (m_bUseShaderPreset) { - float x, y, z; - float u1, v1; - } vertex[4]; - - GLint vertLoc = m_context.GUIShaderGetPos(); - GLint loc = m_context.GUIShaderGetCoord0(); - GLint uniColLoc = m_context.GUIShaderGetUniCol(); - - // Setup color values - colour[0] = UTILS::GL::GetChannelFromARGB(UTILS::GL::ColorChannel::R, color); - colour[1] = UTILS::GL::GetChannelFromARGB(UTILS::GL::ColorChannel::G, color); - colour[2] = UTILS::GL::GetChannelFromARGB(UTILS::GL::ColorChannel::B, color); - colour[3] = UTILS::GL::GetChannelFromARGB(UTILS::GL::ColorChannel::A, color); - - for (unsigned int i = 0; i < 4; i++) + const CPoint destPoints[4] = {m_rotatedDestCoords[0], m_rotatedDestCoords[1], + m_rotatedDestCoords[2], m_rotatedDestCoords[3]}; + + targetTexture->CreateTextureObject(); + + SHADER::CShaderTextureGL source(*sourceTexture); + SHADER::CShaderTextureGL target(*targetTexture); + if (!m_shaderPreset->RenderUpdate(destPoints, &source, &target)) + { + m_shadersNeedUpdate = false; + m_bUseShaderPreset = false; + } + } + else { - // Setup vertex position values - vertex[i].x = m_rotatedDestCoords[i].x; - vertex[i].y = m_rotatedDestCoords[i].y; - vertex[i].z = 0.0f; + m_context.EnableGUIShader(GL_SHADER_METHOD::TEXTURE_NOALPHA); + + GLubyte colour[4]; + GLubyte idx[4] = {0, 1, 3, 2}; // Determines order of triangle strip + struct PackedVertex + { + float x, y, z; + float u1, v1; + } vertex[4]; + + GLint vertLoc = m_context.GUIShaderGetPos(); + GLint loc = m_context.GUIShaderGetCoord0(); + GLint uniColLoc = m_context.GUIShaderGetUniCol(); + + // Setup color values + colour[0] = UTILS::GL::GetChannelFromARGB(UTILS::GL::ColorChannel::R, color); + colour[1] = UTILS::GL::GetChannelFromARGB(UTILS::GL::ColorChannel::G, color); + colour[2] = UTILS::GL::GetChannelFromARGB(UTILS::GL::ColorChannel::B, color); + colour[3] = UTILS::GL::GetChannelFromARGB(UTILS::GL::ColorChannel::A, color); + + for (unsigned int i = 0; i < 4; i++) + { + // Setup vertex position values + vertex[i].x = m_rotatedDestCoords[i].x; + vertex[i].y = m_rotatedDestCoords[i].y; + vertex[i].z = 0.0f; + } + + // Setup texture coordinates + vertex[0].u1 = vertex[3].u1 = rect.x1; + vertex[0].v1 = vertex[1].v1 = rect.y1; + vertex[1].u1 = vertex[2].u1 = rect.x2; + vertex[2].v1 = vertex[3].v1 = rect.y2; + + glBindBuffer(GL_ARRAY_BUFFER, m_mainVertexVBO); + glBufferData(GL_ARRAY_BUFFER, sizeof(PackedVertex) * 4, &vertex[0], GL_STATIC_DRAW); + + glVertexAttribPointer(vertLoc, 3, GL_FLOAT, 0, sizeof(PackedVertex), + reinterpret_cast(offsetof(PackedVertex, x))); + glVertexAttribPointer(loc, 2, GL_FLOAT, 0, sizeof(PackedVertex), + reinterpret_cast(offsetof(PackedVertex, u1))); + + glEnableVertexAttribArray(vertLoc); + glEnableVertexAttribArray(loc); + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_mainIndexVBO); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLubyte) * 4, idx, GL_STATIC_DRAW); + + glUniform4f(uniColLoc, (colour[0] / 255.0f), (colour[1] / 255.0f), (colour[2] / 255.0f), + (colour[3] / 255.0f)); + glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_BYTE, 0); + + glDisableVertexAttribArray(vertLoc); + glDisableVertexAttribArray(loc); + + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + + m_context.DisableGUIShader(); } - - // Setup texture coordinates - vertex[0].u1 = vertex[3].u1 = rect.x1; - vertex[0].v1 = vertex[1].v1 = rect.y1; - vertex[1].u1 = vertex[2].u1 = rect.x2; - vertex[2].v1 = vertex[3].v1 = rect.y2; - - glBindBuffer(GL_ARRAY_BUFFER, m_mainVertexVBO); - glBufferData(GL_ARRAY_BUFFER, sizeof(PackedVertex) * 4, &vertex[0], GL_STATIC_DRAW); - - glVertexAttribPointer(vertLoc, 3, GL_FLOAT, 0, sizeof(PackedVertex), - reinterpret_cast(offsetof(PackedVertex, x))); - glVertexAttribPointer(loc, 2, GL_FLOAT, 0, sizeof(PackedVertex), - reinterpret_cast(offsetof(PackedVertex, u1))); - - glEnableVertexAttribArray(vertLoc); - glEnableVertexAttribArray(loc); - - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_mainIndexVBO); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLubyte) * 4, idx, GL_STATIC_DRAW); - - glUniform4f(uniColLoc, (colour[0] / 255.0f), (colour[1] / 255.0f), (colour[2] / 255.0f), - (colour[3] / 255.0f)); - glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_BYTE, 0); - - glDisableVertexAttribArray(vertLoc); - glDisableVertexAttribArray(loc); - - glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - - m_context.DisableGUIShader(); } diff --git a/xbmc/cores/RetroPlayer/rendering/VideoRenderers/RPRendererOpenGLES.h b/xbmc/cores/RetroPlayer/rendering/VideoRenderers/RPRendererOpenGLES.h index ca1f583df6c3e..aa6dfbd519787 100644 --- a/xbmc/cores/RetroPlayer/rendering/VideoRenderers/RPRendererOpenGLES.h +++ b/xbmc/cores/RetroPlayer/rendering/VideoRenderers/RPRendererOpenGLES.h @@ -13,8 +13,11 @@ #include "cores/RetroPlayer/buffers/BaseRenderBufferPool.h" #include "cores/RetroPlayer/buffers/video/RenderBufferSysMem.h" #include "cores/RetroPlayer/process/RPProcessInfo.h" +#include "guilib/TextureGL.h" #include +#include +#include #include #include @@ -24,6 +27,8 @@ namespace KODI { namespace RETRO { +class CRenderBufferOpenGLES; + class CRendererFactoryOpenGLES : public IRendererFactory { public: @@ -76,6 +81,14 @@ class CRPRendererOpenGLES : public CRPBaseRenderer GLuint m_blackbarsVertexVBO; GLenum m_textureTarget = GL_TEXTURE_2D; float m_clearColour = 0.0f; + + struct RenderBufferTextures + { + CGLTexture source; + CGLTexture target; + }; + + std::map> m_RBTexturesMap; }; } // namespace RETRO } // namespace KODI diff --git a/xbmc/cores/RetroPlayer/shaders/gl/ShaderLutGL.cpp b/xbmc/cores/RetroPlayer/shaders/gl/ShaderLutGL.cpp index 238cc7f21750e..345bb89c01962 100644 --- a/xbmc/cores/RetroPlayer/shaders/gl/ShaderLutGL.cpp +++ b/xbmc/cores/RetroPlayer/shaders/gl/ShaderLutGL.cpp @@ -67,8 +67,10 @@ std::unique_ptr CShaderLutGL::CreateLUTTexture(RETRO::CRenderCon glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, 0.0); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, MAX_FLOAT); +#ifndef HAS_GLES GLfloat blackBorder[4] = {0.0f, 0.0f, 0.0f, 0.0f}; glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, blackBorder); +#endif if (lut.mipmap) textureGL->SetMipmapping(); diff --git a/xbmc/cores/RetroPlayer/shaders/gl/ShaderPresetGL.cpp b/xbmc/cores/RetroPlayer/shaders/gl/ShaderPresetGL.cpp index 315ae00a69cf8..0b9b2fc591ed5 100644 --- a/xbmc/cores/RetroPlayer/shaders/gl/ShaderPresetGL.cpp +++ b/xbmc/cores/RetroPlayer/shaders/gl/ShaderPresetGL.cpp @@ -9,6 +9,7 @@ #include "ShaderPresetGL.h" #include "ServiceBroker.h" +#include "ShaderUtilsGL.h" #include "cores/RetroPlayer/rendering/RenderContext.h" #include "cores/RetroPlayer/shaders/ShaderPresetFactory.h" #include "cores/RetroPlayer/shaders/ShaderUtils.h" @@ -175,7 +176,7 @@ bool CShaderPresetGL::Update() if (!ReadPresetFile(m_presetPath)) { - CLog::Log(LOGERROR, "%s - couldn't load shader preset %s or the shaders it references", + CLog::Log(LOGERROR, "{} - couldn't load shader preset {} or the shaders it references", __func__, m_presetPath.c_str()); return false; } @@ -304,17 +305,22 @@ bool CShaderPresetGL::CreateShaderTextures() return false; } + auto wrapType = CShaderUtilsGL::TranslateWrapType(WRAP_TYPE_BORDER); + glBindTexture(GL_TEXTURE_2D, texture->getMTexture()); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_BORDER); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapType); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapType); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, wrapType); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_NEVER); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, 0.0); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, MAX_FLOAT); + +#ifndef HAS_GLES GLfloat blackBorder[4] = {0.0f, 0.0f, 0.0f, 0.0f}; glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, blackBorder); +#endif m_pShaderTextures.emplace_back(new CShaderTextureGL(*texture)); m_pShaders[shaderIdx]->SetSizes(prevSize, scaledSize); diff --git a/xbmc/cores/RetroPlayer/shaders/gl/ShaderUtilsGL.cpp b/xbmc/cores/RetroPlayer/shaders/gl/ShaderUtilsGL.cpp index 4442e085cc352..e5d464b242317 100644 --- a/xbmc/cores/RetroPlayer/shaders/gl/ShaderUtilsGL.cpp +++ b/xbmc/cores/RetroPlayer/shaders/gl/ShaderUtilsGL.cpp @@ -30,7 +30,11 @@ GLint CShaderUtilsGL::TranslateWrapType(WRAP_TYPE wrap) break; case WRAP_TYPE_BORDER: default: +#ifdef HAS_GLES + glWrap = GL_CLAMP_TO_EDGE; +#else glWrap = GL_CLAMP_TO_BORDER; +#endif break; }