From 29e88fd8f066c14a405a52bbfe3715dc3e5e891f Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Mon, 29 Jun 2015 16:55:06 +0200 Subject: Do not use 16 bits per color on GLES unless GL_EXT_texture_norm16 (and so GL_RGBA16) is present. Change-Id: Ic15b81b8134fda147e96301b7f78cabe07a05d9e Reviewed-by: Allan Sandfeld Jensen --- src/gui/opengl/qopenglextensions_p.h | 3 +- src/gui/opengl/qopenglfunctions.cpp | 7 ++- src/gui/opengl/qopenglgradientcache.cpp | 79 +++++++++++++++++++++++++++------ src/gui/opengl/qopenglgradientcache_p.h | 3 ++ 4 files changed, 75 insertions(+), 17 deletions(-) diff --git a/src/gui/opengl/qopenglextensions_p.h b/src/gui/opengl/qopenglextensions_p.h index efe5421f56..e50ca1a94c 100644 --- a/src/gui/opengl/qopenglextensions_p.h +++ b/src/gui/opengl/qopenglextensions_p.h @@ -114,7 +114,8 @@ public: GeometryShaders = 0x00080000, MapBufferRange = 0x00100000, Sized8Formats = 0x00200000, - DiscardFramebuffer = 0x00400000 + DiscardFramebuffer = 0x00400000, + Sized16Formats = 0x00800000 }; Q_DECLARE_FLAGS(OpenGLExtensions, OpenGLExtension) diff --git a/src/gui/opengl/qopenglfunctions.cpp b/src/gui/opengl/qopenglfunctions.cpp index 280430c064..2579f0e77f 100644 --- a/src/gui/opengl/qopenglfunctions.cpp +++ b/src/gui/opengl/qopenglfunctions.cpp @@ -419,11 +419,14 @@ static int qt_gl_resolve_extensions() // We don't match GL_APPLE_texture_format_BGRA8888 here because it has different semantics. if (extensionMatcher.match("GL_IMG_texture_format_BGRA8888") || extensionMatcher.match("GL_EXT_texture_format_BGRA8888")) extensions |= QOpenGLExtensions::BGRATextureFormat; - if (extensionMatcher.match("GL_EXT_discard_framebuffer")) extensions |= QOpenGLExtensions::DiscardFramebuffer; + if (extensionMatcher.match("GL_EXT_texture_norm16")) + extensions |= QOpenGLExtensions::Sized16Formats; } else { - extensions |= QOpenGLExtensions::ElementIndexUint | QOpenGLExtensions::MapBuffer; + extensions |= QOpenGLExtensions::ElementIndexUint + | QOpenGLExtensions::MapBuffer + | QOpenGLExtensions::Sized16Formats; if (format.version() >= qMakePair(1, 2)) extensions |= QOpenGLExtensions::BGRATextureFormat; diff --git a/src/gui/opengl/qopenglgradientcache.cpp b/src/gui/opengl/qopenglgradientcache.cpp index 6622d4805f..13bad9aabb 100644 --- a/src/gui/opengl/qopenglgradientcache.cpp +++ b/src/gui/opengl/qopenglgradientcache.cpp @@ -39,10 +39,6 @@ #include "qopenglfunctions.h" #include "qopenglextensions_p.h" -#ifndef GL_RGBA8 -#define GL_RGBA8 0x8058 -#endif - #ifndef GL_RGBA16 #define GL_RGBA16 0x805B #endif @@ -147,19 +143,19 @@ GLuint QOpenGL2GradientCache::addCacheElement(quint64 hash_val, const QGradient } CacheInfo cache_entry(gradient.stops(), opacity, gradient.interpolationMode()); - QRgba64 buffer[1024]; - generateGradientColorTable(gradient, buffer, paletteSize(), opacity); funcs->glGenTextures(1, &cache_entry.texId); funcs->glBindTexture(GL_TEXTURE_2D, cache_entry.texId); - GLenum internalFormat = GL_RGBA16; - if (QOpenGLContext::currentContext()->isOpenGLES()) { - if (static_cast(funcs)->hasOpenGLExtension(QOpenGLExtensions::Sized8Formats)) - internalFormat = GL_RGBA8; - else - internalFormat = GL_RGBA; // Let OpenGLES use whatever it prefers. + if (static_cast(funcs)->hasOpenGLExtension(QOpenGLExtensions::Sized16Formats)) { + QRgba64 buffer[1024]; + generateGradientColorTable(gradient, buffer, paletteSize(), opacity); + funcs->glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16, paletteSize(), 1, + 0, GL_RGBA, GL_UNSIGNED_SHORT, buffer); + } else { + uint buffer[1024]; + generateGradientColorTable(gradient, buffer, paletteSize(), opacity); + funcs->glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, paletteSize(), 1, + 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer); } - funcs->glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, paletteSize(), 1, - 0, GL_RGBA, GL_UNSIGNED_SHORT, buffer); return cache.insert(hash_val, cache_entry).value().texId; } @@ -220,4 +216,59 @@ void QOpenGL2GradientCache::generateGradientColorTable(const QGradient& gradient colorTable[size-1] = last_color; } +void QOpenGL2GradientCache::generateGradientColorTable(const QGradient& gradient, uint *colorTable, int size, qreal opacity) const +{ + int pos = 0; + QGradientStops s = gradient.stops(); + QVector colors(s.size()); + + for (int i = 0; i < s.size(); ++i) + colors[i] = s[i].second.rgba(); // Qt LIES! It returns ARGB (on little-endian AND on big-endian) + + bool colorInterpolation = (gradient.interpolationMode() == QGradient::ColorInterpolation); + + uint alpha = qRound(opacity * 256); + uint current_color = ARGB_COMBINE_ALPHA(colors[0], alpha); + qreal incr = 1.0 / qreal(size); + qreal fpos = 1.5 * incr; + colorTable[pos++] = ARGB2RGBA(qPremultiply(current_color)); + + while (fpos <= s.first().first) { + colorTable[pos] = colorTable[pos - 1]; + pos++; + fpos += incr; + } + + if (colorInterpolation) + current_color = qPremultiply(current_color); + + for (int i = 0; i < s.size() - 1; ++i) { + qreal delta = 1/(s[i+1].first - s[i].first); + uint next_color = ARGB_COMBINE_ALPHA(colors[i+1], alpha); + if (colorInterpolation) + next_color = qPremultiply(next_color); + + while (fpos < s[i+1].first && pos < size) { + int dist = int(256 * ((fpos - s[i].first) * delta)); + int idist = 256 - dist; + if (colorInterpolation) + colorTable[pos] = ARGB2RGBA(INTERPOLATE_PIXEL_256(current_color, idist, next_color, dist)); + else + colorTable[pos] = ARGB2RGBA(qPremultiply(INTERPOLATE_PIXEL_256(current_color, idist, next_color, dist))); + ++pos; + fpos += incr; + } + current_color = next_color; + } + + Q_ASSERT(s.size() > 0); + + uint last_color = ARGB2RGBA(qPremultiply(ARGB_COMBINE_ALPHA(colors[s.size() - 1], alpha))); + for (;pos < size; ++pos) + colorTable[pos] = last_color; + + // Make sure the last color stop is represented at the end of the table + colorTable[size-1] = last_color; +} + QT_END_NAMESPACE diff --git a/src/gui/opengl/qopenglgradientcache_p.h b/src/gui/opengl/qopenglgradientcache_p.h index d368f4bcfc..61949d5b7c 100644 --- a/src/gui/opengl/qopenglgradientcache_p.h +++ b/src/gui/opengl/qopenglgradientcache_p.h @@ -86,6 +86,9 @@ private: inline void generateGradientColorTable(const QGradient& gradient, QRgba64 *colorTable, int size, qreal opacity) const; + inline void generateGradientColorTable(const QGradient& gradient, + uint *colorTable, + int size, qreal opacity) const; GLuint addCacheElement(quint64 hash_val, const QGradient &gradient, qreal opacity); void cleanCache(); -- cgit v1.2.3