diff --git a/src/gui/kernel/qplatformgraphicsbufferhelper.cpp b/src/gui/kernel/qplatformgraphicsbufferhelper.cpp index 1d59c38598..7f2672bc5e 100644 --- a/src/gui/kernel/qplatformgraphicsbufferhelper.cpp +++ b/src/gui/kernel/qplatformgraphicsbufferhelper.cpp @@ -64,7 +64,7 @@ QT_BEGIN_NAMESPACE bound texture, otherwise returns false. */ bool QPlatformGraphicsBufferHelper::lockAndBindToTexture(QPlatformGraphicsBuffer *graphicsBuffer, - bool *swizzle, + bool *swizzle, bool *premultiplied, const QRect &rect) { if (graphicsBuffer->lock(QPlatformGraphicsBuffer::TextureAccess)) { @@ -74,8 +74,10 @@ bool QPlatformGraphicsBufferHelper::lockAndBindToTexture(QPlatformGraphicsBuffer } if (swizzle) *swizzle = false; + if (premultiplied) + *premultiplied = false; } else if (graphicsBuffer->lock(QPlatformGraphicsBuffer::SWReadAccess)) { - if (!bindSWToTexture(graphicsBuffer, swizzle, rect)) { + if (!bindSWToTexture(graphicsBuffer, swizzle, premultiplied, rect)) { qWarning("Failed to bind %sgraphicsbuffer to texture", "SW "); return false; } @@ -109,7 +111,7 @@ bool QPlatformGraphicsBufferHelper::lockAndBindToTexture(QPlatformGraphicsBuffer Returns true on success, otherwise false. */ bool QPlatformGraphicsBufferHelper::bindSWToTexture(const QPlatformGraphicsBuffer *graphicsBuffer, - bool *swizzleRandB, + bool *swizzleRandB, bool *premultipliedB, const QRect &subRect) { #ifndef QT_NO_OPENGL @@ -124,14 +126,30 @@ bool QPlatformGraphicsBufferHelper::bindSWToTexture(const QPlatformGraphicsBuffe Q_ASSERT(subRect.isEmpty() || QRect(QPoint(0,0), size).contains(subRect)); bool swizzle = false; + bool premultiplied = false; QImage::Format imageformat = QImage::toImageFormat(graphicsBuffer->format()); QImage image(graphicsBuffer->data(), size.width(), size.height(), graphicsBuffer->bytesPerLine(), imageformat); if (graphicsBuffer->bytesPerLine() != (size.width() * 4)) { image = image.convertToFormat(QImage::Format_RGBA8888); - } else if (imageformat == QImage::Format_RGB32) { - swizzle = true; - } else if (imageformat != QImage::Format_RGBA8888) { - image = image.convertToFormat(QImage::Format_RGBA8888); + } else { + switch (imageformat) { + case QImage::Format_ARGB32_Premultiplied: + premultiplied = true; + // no break + case QImage::Format_RGB32: + case QImage::Format_ARGB32: + swizzle = true; + break; + case QImage::Format_RGBA8888_Premultiplied: + premultiplied = true; + // no break + case QImage::Format_RGBX8888: + case QImage::Format_RGBA8888: + break; + default: + image = image.convertToFormat(QImage::Format_RGBA8888); + break; + } } QOpenGLFunctions *funcs = QOpenGLContext::currentContext()->functions(); @@ -170,6 +188,8 @@ bool QPlatformGraphicsBufferHelper::bindSWToTexture(const QPlatformGraphicsBuffe } if (swizzleRandB) *swizzleRandB = swizzle; + if (premultipliedB) + *premultipliedB = premultiplied; return true; diff --git a/src/gui/kernel/qplatformgraphicsbufferhelper.h b/src/gui/kernel/qplatformgraphicsbufferhelper.h index ded7810608..cc1a4918cd 100644 --- a/src/gui/kernel/qplatformgraphicsbufferhelper.h +++ b/src/gui/kernel/qplatformgraphicsbufferhelper.h @@ -39,8 +39,8 @@ QT_BEGIN_NAMESPACE namespace QPlatformGraphicsBufferHelper { - bool lockAndBindToTexture(QPlatformGraphicsBuffer *graphicsBuffer, bool *swizzleRandB, const QRect &rect = QRect()); - bool bindSWToTexture(const QPlatformGraphicsBuffer *graphicsBuffer, bool *swizzleRandB = Q_NULLPTR, const QRect &rect = QRect()); + bool lockAndBindToTexture(QPlatformGraphicsBuffer *graphicsBuffer, bool *swizzleRandB, bool *premultipliedB, const QRect &rect = QRect()); + bool bindSWToTexture(const QPlatformGraphicsBuffer *graphicsBuffer, bool *swizzleRandB = Q_NULLPTR, bool *premultipliedB = Q_NULLPTR, const QRect &rect = QRect()); } QT_END_NAMESPACE diff --git a/src/gui/painting/qplatformbackingstore.cpp b/src/gui/painting/qplatformbackingstore.cpp index 4b725fc79f..ef1652b48b 100644 --- a/src/gui/painting/qplatformbackingstore.cpp +++ b/src/gui/painting/qplatformbackingstore.cpp @@ -92,6 +92,7 @@ public: mutable GLuint textureId; mutable QSize textureSize; mutable bool needsSwizzle; + mutable bool premultiplied; QOpenGLTextureBlitter *blitter; #endif }; @@ -323,9 +324,6 @@ void QPlatformBackingStore::composeAndFlush(QWindow *window, const QRegion ®i blitTextureForWidget(textures, i, window, deviceWindowRect, d_ptr->blitter, offset); } - funcs->glEnable(GL_BLEND); - funcs->glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE); - // Backingstore texture with the normal widgets. GLuint textureId = 0; QOpenGLTextureBlitter::Origin origin = QOpenGLTextureBlitter::OriginTopLeft; @@ -345,7 +343,7 @@ void QPlatformBackingStore::composeAndFlush(QWindow *window, const QRegion ®i funcs->glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); funcs->glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - if (QPlatformGraphicsBufferHelper::lockAndBindToTexture(graphicsBuffer, &d_ptr->needsSwizzle)) { + if (QPlatformGraphicsBufferHelper::lockAndBindToTexture(graphicsBuffer, &d_ptr->needsSwizzle, &d_ptr->premultiplied)) { d_ptr->textureSize = graphicsBuffer->size(); } else { d_ptr->textureSize = QSize(0,0); @@ -354,7 +352,7 @@ void QPlatformBackingStore::composeAndFlush(QWindow *window, const QRegion ®i graphicsBuffer->unlock(); } else if (!region.isEmpty()){ funcs->glBindTexture(GL_TEXTURE_2D, d_ptr->textureId); - QPlatformGraphicsBufferHelper::lockAndBindToTexture(graphicsBuffer, &d_ptr->needsSwizzle); + QPlatformGraphicsBufferHelper::lockAndBindToTexture(graphicsBuffer, &d_ptr->needsSwizzle, &d_ptr->premultiplied); } if (graphicsBuffer->origin() == QPlatformGraphicsBuffer::OriginBottomLeft) @@ -364,10 +362,17 @@ void QPlatformBackingStore::composeAndFlush(QWindow *window, const QRegion ®i TextureFlags flags = 0; textureId = toTexture(deviceRegion(region, window, offset), &d_ptr->textureSize, &flags); d_ptr->needsSwizzle = (flags & TextureSwizzle) != 0; + d_ptr->premultiplied = (flags & TexturePremultiplied) != 0; if (flags & TextureFlip) origin = QOpenGLTextureBlitter::OriginBottomLeft; } + funcs->glEnable(GL_BLEND); + if (d_ptr->premultiplied) + funcs->glBlendFuncSeparate(GL_ONE, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE); + else + funcs->glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE); + if (textureId) { if (d_ptr->needsSwizzle) d_ptr->blitter->setSwizzleRB(true); @@ -443,10 +448,26 @@ GLuint QPlatformBackingStore::toTexture(const QRegion &dirtyRegion, QSize *textu QImage image = toImage(); QSize imageSize = image.size(); + bool needConvert = false; *flags = 0; - if (image.format() == QImage::Format_RGB32) + switch (image.format()) { + case QImage::Format_ARGB32_Premultiplied: + *flags |= TexturePremultiplied; + // no break + case QImage::Format_RGB32: + case QImage::Format_ARGB32: *flags |= TextureSwizzle; - + break; + case QImage::Format_RGBA8888_Premultiplied: + *flags |= TexturePremultiplied; + // no break + case QImage::Format_RGBX8888: + case QImage::Format_RGBA8888: + break; + default: + needConvert = true; + break; + } if (imageSize.isEmpty()) { *textureSize = imageSize; return 0; @@ -460,8 +481,7 @@ GLuint QPlatformBackingStore::toTexture(const QRegion &dirtyRegion, QSize *textu *textureSize = imageSize; - // Fast path for RGB32 and RGBA8888, convert everything else to RGBA8888. - if (image.format() != QImage::Format_RGB32 && image.format() != QImage::Format_RGBA8888) + if (needConvert) 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 eac97e9cf6..9c8da0d1db 100644 --- a/src/gui/painting/qplatformbackingstore.h +++ b/src/gui/painting/qplatformbackingstore.h @@ -118,7 +118,8 @@ public: virtual QImage toImage() const; enum TextureFlag { TextureSwizzle = 0x01, - TextureFlip = 0x02 + TextureFlip = 0x02, + TexturePremultiplied = 0x04, }; Q_DECLARE_FLAGS(TextureFlags, TextureFlag) virtual GLuint toTexture(const QRegion &dirtyRegion, QSize *textureSize, TextureFlags *flags) const;