From 2a1934940eb8847ba6d9b8b0f6059f6f3aeebaf8 Mon Sep 17 00:00:00 2001 From: falkTX Date: Sat, 20 Sep 2025 23:36:10 +0200 Subject: [PATCH] Fix BGR/BGRA image use under GLES, auto-convert as needed Signed-off-by: falkTX --- dgl/OpenGL.hpp | 16 +++++++++ dgl/src/OpenGL.cpp | 28 ++++++++++++++++ dgl/src/OpenGL3.cpp | 69 ++++++++++++++++++++++++++++++++++++++ dgl/src/nanovg/nanovg_gl.h | 8 ++--- 4 files changed, 117 insertions(+), 4 deletions(-) diff --git a/dgl/OpenGL.hpp b/dgl/OpenGL.hpp index 01f15a2a..46d5aecb 100644 --- a/dgl/OpenGL.hpp +++ b/dgl/OpenGL.hpp @@ -249,6 +249,18 @@ public: */ void drawAt(const GraphicsContext& context, const Point& pos) override; + #ifdef DGL_USE_GLES + /** + Get the image format. + */ + ImageFormat getFormat() const noexcept; + + /** + Get the raw image data. + */ + const char* getRawData() const noexcept; + #endif + /** TODO document this. */ @@ -312,6 +324,10 @@ private: bool setupCalled; bool textureInit; GLuint textureId; + #ifdef DGL_USE_GLES + mutable char* convertedData; + mutable const char* rawDataLast; + #endif }; // -------------------------------------------------------------------------------------------------------------------- diff --git a/dgl/src/OpenGL.cpp b/dgl/src/OpenGL.cpp index 65548857..989db626 100644 --- a/dgl/src/OpenGL.cpp +++ b/dgl/src/OpenGL.cpp @@ -37,6 +37,10 @@ OpenGLImage::OpenGLImage() setupCalled(false), textureInit(false), textureId(0) + #ifdef DGL_USE_GLES + , convertedData(nullptr) + , rawDataLast(nullptr) + #endif { } @@ -45,6 +49,10 @@ OpenGLImage::OpenGLImage(const char* const rdata, const uint w, const uint h, co setupCalled(false), textureInit(true), textureId(0) + #ifdef DGL_USE_GLES + , convertedData(nullptr) + , rawDataLast(nullptr) + #endif { glGenTextures(1, &textureId); DISTRHO_SAFE_ASSERT(textureId != 0); @@ -55,6 +63,10 @@ OpenGLImage::OpenGLImage(const char* const rdata, const Size& s, const Ima setupCalled(false), textureInit(true), textureId(0) + #ifdef DGL_USE_GLES + , convertedData(nullptr) + , rawDataLast(nullptr) + #endif { glGenTextures(1, &textureId); DISTRHO_SAFE_ASSERT(textureId != 0); @@ -65,6 +77,10 @@ OpenGLImage::OpenGLImage(const OpenGLImage& image) setupCalled(false), textureInit(true), textureId(0) + #ifdef DGL_USE_GLES + , convertedData(nullptr) + , rawDataLast(nullptr) + #endif { glGenTextures(1, &textureId); DISTRHO_SAFE_ASSERT(textureId != 0); @@ -74,6 +90,10 @@ OpenGLImage::~OpenGLImage() { if (textureId != 0) glDeleteTextures(1, &textureId); + + #ifdef DGL_USE_GLES + std::free(convertedData); + #endif } void OpenGLImage::loadFromMemory(const char* const rdata, const Size& s, const ImageFormat fmt) noexcept @@ -111,6 +131,10 @@ OpenGLImage::OpenGLImage(const char* const rdata, const uint w, const uint h, co setupCalled(false), textureInit(true), textureId(0) + #ifdef DGL_USE_GLES + , convertedData(nullptr) + , rawDataLast(nullptr) + #endif { glGenTextures(1, &textureId); DISTRHO_SAFE_ASSERT(textureId != 0); @@ -121,6 +145,10 @@ OpenGLImage::OpenGLImage(const char* const rdata, const Size& s, const GLe setupCalled(false), textureInit(true), textureId(0) + #ifdef DGL_USE_GLES + , convertedData(nullptr) + , rawDataLast(nullptr) + #endif { glGenTextures(1, &textureId); DISTRHO_SAFE_ASSERT(textureId != 0); diff --git a/dgl/src/OpenGL3.cpp b/dgl/src/OpenGL3.cpp index 35e35980..90497ec1 100644 --- a/dgl/src/OpenGL3.cpp +++ b/dgl/src/OpenGL3.cpp @@ -562,6 +562,70 @@ void OpenGLImage::drawAt(const GraphicsContext& context, const Point& pos) glBindTexture(GL_TEXTURE_2D, 0); } +#ifdef DGL_USE_GLES +ImageFormat OpenGLImage::getFormat() const noexcept +{ + switch (format) + { + case kImageFormatBGR: + return kImageFormatRGB; + case kImageFormatBGRA: + return kImageFormatRGBA; + default: + return format; + } +} + +const char* OpenGLImage::getRawData() const noexcept +{ + if (rawDataLast != rawData) + { + if (format == kImageFormatBGR || format == kImageFormatBGRA) + { + const uint w = size.getWidth(); + const uint h = size.getHeight(); + + std::free(convertedData); + + if (format == kImageFormatBGR) + { + convertedData = static_cast(std::malloc(sizeof(char) * 3 * w * h)); + for (int i = 0; i < w * h; ++i) + { + convertedData[i * 3 + 0] = rawData[i * 3 + 2]; + convertedData[i * 3 + 1] = rawData[i * 3 + 1]; + convertedData[i * 3 + 2] = rawData[i * 3 + 0]; + } + } + else + { + convertedData = static_cast(std::malloc(sizeof(char) * 4 * w * h)); + for (int i = 0; i < w * h; ++i) + { + convertedData[i * 4 + 0] = rawData[i * 4 + 2]; + convertedData[i * 4 + 1] = rawData[i * 4 + 1]; + convertedData[i * 4 + 2] = rawData[i * 4 + 0]; + convertedData[i * 4 + 3] = rawData[i * 4 + 3]; + } + } + } + else + { + std::free(convertedData); + convertedData = nullptr; + } + + rawDataLast = rawData; + } + + return + #ifdef DGL_USE_GLES + convertedData != nullptr ? convertedData : + #endif + rawData; +} +#endif + #ifdef DGL_ALLOW_DEPRECATED_METHODS void OpenGLImage::draw() { @@ -634,6 +698,9 @@ void ImageBaseKnob::onDisplay() DISTRHO_SAFE_ASSERT_RETURN(imageFormat != kImageFormatBGR && imageFormat != kImageFormatBGRA,); #endif + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + const GLfloat color[4] = { 1.0f, 1.0f, 1.0f, 1.0f }; glUniform4fv(gl3context.color, 1, color); @@ -748,6 +815,8 @@ void ImageBaseKnob::onDisplay() glUniform1i(gl3context.usingTexture, 0); glBindBuffer(GL_ARRAY_BUFFER, 0); glBindTexture(GL_TEXTURE_2D, 0); + + glDisable(GL_BLEND); } template class ImageBaseKnob; diff --git a/dgl/src/nanovg/nanovg_gl.h b/dgl/src/nanovg/nanovg_gl.h index 5e328c80..feb50278 100644 --- a/dgl/src/nanovg/nanovg_gl.h +++ b/dgl/src/nanovg/nanovg_gl.h @@ -834,10 +834,10 @@ static int glnvg__renderCreateTexture(void* uptr, int type, int w, int h, int im tex->data = (uint8_t*)malloc(sizeof(uint8_t) * 4 * w * h); for (int i = 0; i < w * h; ++i) { - tex->data[i*3+0] = data[i*3+3]; - tex->data[i*3+1] = data[i*3+2]; - tex->data[i*3+2] = data[i*3+1]; - tex->data[i*3+3] = data[i*3+0]; + tex->data[i*4+0] = data[i*4+2]; + tex->data[i*4+1] = data[i*4+1]; + tex->data[i*4+2] = data[i*4+0]; + tex->data[i*4+3] = data[i*4+3]; } data = tex->data; glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);