Optimize OpenGL binding of ARGB32PM backing store
Detect premultiplied backing store and upload it without conversion and adjust blend to not multiply alpha again. Task-number: QTBUG-50381 Change-Id: I51939c4f82fbb0c48eaca6e2475bf4cf3722bc2d Reviewed-by: Laszlo Agocs <laszlo.agocs@theqtcompany.com> Reviewed-by: Gunnar Sletta <gunnar@sletta.org>
This commit is contained in:
parent
18119a58de
commit
0bc4288689
@ -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;
|
||||
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user