summaryrefslogtreecommitdiffstats
path: root/src/gui/painting/qplatformbackingstore.cpp
diff options
context:
space:
mode:
authorLaszlo Agocs <laszlo.agocs@digia.com>2014-08-13 10:05:52 +0200
committerJørgen Lind <jorgen.lind@digia.com>2014-08-13 16:14:19 +0200
commit5621a7c5014ac337d41a00ca8f53f172bd17b792 (patch)
tree9dd679d1ea0319c989377a0e940b152e0a169350 /src/gui/painting/qplatformbackingstore.cpp
parent6c3c1a4cb8e4973b8e603edfbe608e1b1587f3f2 (diff)
Fix composition for windows with alpha
While we will cover the entire surface with our textured quads, the clear is still necessary in order to make top-levels with TranslucentBackground render correctly: We don't want to blend transparent areas with undefined content that is in the surface's framebuffer. Blending is problematic for alpha values. We now prevent the blended alpha from being written out. This ensures that in examples like qquickviewcomparison, where the backingstore image contains an alpha of 0.5 while the QQuickWidget texture 1.0, the result is still an alpha value of 1.0 in the final image. Writing out an alpha of 0.5 would break on systems where windows get an alpha buffer by default. hellogl2 can now take a --transparent parameter which makes the QOpenGLWidget being cleared to transparent in order to verify it works in combination with Qt::WA_TranslucentBackground. The swapped red and blue problem is also corrected. RGBA8888 does not need swizzling. The only format that needs this is RGB32. Task-number: QTBUG-40716 Change-Id: I54a9fd3a91a1b59575b38cdb908835315514e40f Reviewed-by: Jørgen Lind <jorgen.lind@digia.com>
Diffstat (limited to 'src/gui/painting/qplatformbackingstore.cpp')
-rw-r--r--src/gui/painting/qplatformbackingstore.cpp41
1 files changed, 33 insertions, 8 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 &region, QWindow *window)
void QPlatformBackingStore::composeAndFlush(QWindow *window, const QRegion &region,
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 &regi
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();