diff options
Diffstat (limited to 'src/gui')
-rw-r--r-- | src/gui/painting/qplatformbackingstore.cpp | 41 | ||||
-rw-r--r-- | src/gui/painting/qplatformbackingstore.h | 6 |
2 files changed, 37 insertions, 10 deletions
diff --git a/src/gui/painting/qplatformbackingstore.cpp b/src/gui/painting/qplatformbackingstore.cpp index e5b06f499c..66a56ac32f 100644 --- a/src/gui/painting/qplatformbackingstore.cpp +++ b/src/gui/painting/qplatformbackingstore.cpp @@ -80,6 +80,7 @@ public: #ifndef QT_NO_OPENGL mutable GLuint textureId; mutable QSize textureSize; + mutable bool needsSwizzle; QOpenGLTextureBlitter *blitter; #endif }; @@ -229,13 +230,16 @@ static QRegion deviceRegion(const QRegion ®ion, QWindow *window) void QPlatformBackingStore::composeAndFlush(QWindow *window, const QRegion ®ion, const QPoint &offset, - QPlatformTextureList *textures, QOpenGLContext *context) + QPlatformTextureList *textures, QOpenGLContext *context, + bool translucentBackground) { Q_UNUSED(offset); context->makeCurrent(window); QOpenGLFunctions *funcs = context->functions(); funcs->glViewport(0, 0, window->width() * window->devicePixelRatio(), window->height() * window->devicePixelRatio()); + funcs->glClearColor(0, 0, 0, translucentBackground ? 0 : 1); + funcs->glClear(GL_COLOR_BUFFER_BIT); if (!d_ptr->blitter) { d_ptr->blitter = new QOpenGLTextureBlitter; @@ -257,15 +261,22 @@ void QPlatformBackingStore::composeAndFlush(QWindow *window, const QRegion ®i funcs->glEnable(GL_BLEND); funcs->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + // Do not write out alpha. We need blending, but only for RGB. The toplevel may have + // alpha enabled in which case blending (writing out < 1.0 alpha values) would lead to + // semi-transparency even when it is not wanted. + funcs->glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE); // Backingstore texture with the normal widgets. - GLuint textureId = toTexture(deviceRegion(region, window), &d_ptr->textureSize); + GLuint textureId = toTexture(deviceRegion(region, window), &d_ptr->textureSize, &d_ptr->needsSwizzle); if (textureId) { QMatrix4x4 target = QOpenGLTextureBlitter::targetTransform(QRect(QPoint(), d_ptr->textureSize), windowRect); - d_ptr->blitter->setSwizzleRB(true); + if (d_ptr->needsSwizzle) + d_ptr->blitter->setSwizzleRB(true); d_ptr->blitter->blit(textureId, target, QOpenGLTextureBlitter::OriginTopLeft); - d_ptr->blitter->setSwizzleRB(false); + if (d_ptr->needsSwizzle) + d_ptr->blitter->setSwizzleRB(false); } + funcs->glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); // Textures for renderToTexture widgets that have WA_AlwaysStackOnTop set. for (int i = 0; i < textures->count(); ++i) { @@ -308,9 +319,15 @@ QImage QPlatformBackingStore::toImage() const The default implementation returns a cached texture if \a dirtyRegion is empty and the window has not been resized, otherwise it retrieves the content using toImage() and performs a texture upload. - */ -GLuint QPlatformBackingStore::toTexture(const QRegion &dirtyRegion, QSize *textureSize) const + If the red and blue components have to swapped, \a needsSwizzle will be set to \c true. + This allows creating textures from images in formats like QImage::Format_RGB32 without + any further image conversion. Instead, the swizzling will be done in the shaders when + performing composition. Other formats, that do not need such swizzling due to being + already byte ordered RGBA, for example QImage::Format_RGBA8888, must result in having \a + needsSwizzle set to false. + */ +GLuint QPlatformBackingStore::toTexture(const QRegion &dirtyRegion, QSize *textureSize, bool *needsSwizzle) const { QImage image = toImage(); QSize imageSize = image.size(); @@ -321,8 +338,16 @@ GLuint QPlatformBackingStore::toTexture(const QRegion &dirtyRegion, QSize *textu if (dirtyRegion.isEmpty() && !resized) return d_ptr->textureId; - if (image.format() != QImage::Format_RGB32 && image.format() != QImage::Format_RGBA8888) - image = image.convertToFormat(QImage::Format_RGBA8888); + // Fast path for RGB32 and RGBA8888, convert everything else to RGBA8888. + if (image.format() == QImage::Format_RGB32) { + if (needsSwizzle) + *needsSwizzle = true; + } else { + if (needsSwizzle) + *needsSwizzle = false; + if (image.format() != QImage::Format_RGBA8888) + image = image.convertToFormat(QImage::Format_RGBA8888); + } QOpenGLFunctions *funcs = QOpenGLContext::currentContext()->functions(); diff --git a/src/gui/painting/qplatformbackingstore.h b/src/gui/painting/qplatformbackingstore.h index fe0f460ed9..2c183f6d6f 100644 --- a/src/gui/painting/qplatformbackingstore.h +++ b/src/gui/painting/qplatformbackingstore.h @@ -110,9 +110,11 @@ public: // offset is the (child) window's offset in relation to the window surface. virtual void flush(QWindow *window, const QRegion ®ion, const QPoint &offset) = 0; #ifndef QT_NO_OPENGL - virtual void composeAndFlush(QWindow *window, const QRegion ®ion, const QPoint &offset, QPlatformTextureList *textures, QOpenGLContext *context); + virtual void composeAndFlush(QWindow *window, const QRegion ®ion, const QPoint &offset, + QPlatformTextureList *textures, QOpenGLContext *context, + bool translucentBackground); virtual QImage toImage() const; - virtual GLuint toTexture(const QRegion &dirtyRegion, QSize *textureSize) const; + virtual GLuint toTexture(const QRegion &dirtyRegion, QSize *textureSize, bool *needsSwizzle) const; #endif virtual void resize(const QSize &size, const QRegion &staticContents) = 0; |