From 0bc4288689882e731fc1811c4de11fbc6d0c28ff Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Mon, 11 Jan 2016 11:32:44 +0100 Subject: 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 Reviewed-by: Gunnar Sletta --- src/gui/kernel/qplatformgraphicsbufferhelper.cpp | 34 +++++++++++++++++++----- 1 file changed, 27 insertions(+), 7 deletions(-) (limited to 'src/gui/kernel/qplatformgraphicsbufferhelper.cpp') 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; -- cgit v1.2.3 From 4f71654385438a015931a0c7be52f2c7188c9f7d Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Mon, 11 Jan 2016 16:33:45 +0100 Subject: Handle RGB30 formats in OpenGL backing-store integration Optimizes composition on platforms that may use 10-bit per color channel formats. Change-Id: Ib303c391d47795c79a4ba55d78dbb1c3c702d90a Reviewed-by: Laszlo Agocs --- src/gui/kernel/qplatformgraphicsbufferhelper.cpp | 54 ++++++++++++++++++++---- 1 file changed, 45 insertions(+), 9 deletions(-) (limited to 'src/gui/kernel/qplatformgraphicsbufferhelper.cpp') diff --git a/src/gui/kernel/qplatformgraphicsbufferhelper.cpp b/src/gui/kernel/qplatformgraphicsbufferhelper.cpp index 7f2672bc5e..c0c51b8d5e 100644 --- a/src/gui/kernel/qplatformgraphicsbufferhelper.cpp +++ b/src/gui/kernel/qplatformgraphicsbufferhelper.cpp @@ -40,6 +40,14 @@ #include #include +#ifndef GL_RGB10_A2 +#define GL_RGB10_A2 0x8059 +#endif + +#ifndef GL_UNSIGNED_INT_2_10_10_10_REV +#define GL_UNSIGNED_INT_2_10_10_10_REV 0x8368 +#endif + QT_BEGIN_NAMESPACE /*! @@ -115,7 +123,8 @@ bool QPlatformGraphicsBufferHelper::bindSWToTexture(const QPlatformGraphicsBuffe const QRect &subRect) { #ifndef QT_NO_OPENGL - if (!QOpenGLContext::currentContext()) + QOpenGLContext *ctx = QOpenGLContext::currentContext(); + if (!ctx) return false; if (!(graphicsBuffer->isLocked() & QPlatformGraphicsBuffer::SWReadAccess)) @@ -125,12 +134,16 @@ bool QPlatformGraphicsBufferHelper::bindSWToTexture(const QPlatformGraphicsBuffe Q_ASSERT(subRect.isEmpty() || QRect(QPoint(0,0), size).contains(subRect)); + GLenum internalFormat = GL_RGBA; + GLuint pixelType = GL_UNSIGNED_BYTE; + + bool needsConversion = false; 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); + needsConversion = true; } else { switch (imageformat) { case QImage::Format_ARGB32_Premultiplied: @@ -146,22 +159,45 @@ bool QPlatformGraphicsBufferHelper::bindSWToTexture(const QPlatformGraphicsBuffe case QImage::Format_RGBX8888: case QImage::Format_RGBA8888: break; + case QImage::Format_BGR30: + case QImage::Format_A2BGR30_Premultiplied: + if (!ctx->isOpenGLES() || ctx->format().majorVersion() >= 3) { + pixelType = GL_UNSIGNED_INT_2_10_10_10_REV; + internalFormat = GL_RGB10_A2; + premultiplied = true; + } else { + needsConversion = true; + } + break; + case QImage::Format_RGB30: + case QImage::Format_A2RGB30_Premultiplied: + if (!ctx->isOpenGLES() || ctx->format().majorVersion() >= 3) { + pixelType = GL_UNSIGNED_INT_2_10_10_10_REV; + internalFormat = GL_RGB10_A2; + premultiplied = true; + swizzle = true; + } else { + needsConversion = true; + } + break; default: - image = image.convertToFormat(QImage::Format_RGBA8888); + needsConversion = true; break; } } + if (needsConversion) + image = image.convertToFormat(QImage::Format_RGBA8888); - QOpenGLFunctions *funcs = QOpenGLContext::currentContext()->functions(); + QOpenGLFunctions *funcs = ctx->functions(); QRect rect = subRect; if (rect.isNull() || rect == QRect(QPoint(0,0),size)) { - funcs->glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size.width(), size.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, image.constBits()); + funcs->glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, size.width(), size.height(), 0, GL_RGBA, pixelType, image.constBits()); } else { #ifndef QT_OPENGL_ES_2 - if (!QOpenGLContext::currentContext()->isOpenGLES()) { + if (!ctx->isOpenGLES()) { funcs->glPixelStorei(GL_UNPACK_ROW_LENGTH, image.width()); - funcs->glTexSubImage2D(GL_TEXTURE_2D, 0, rect.x(), rect.y(), rect.width(), rect.height(), GL_RGBA, GL_UNSIGNED_BYTE, + funcs->glTexSubImage2D(GL_TEXTURE_2D, 0, rect.x(), rect.y(), rect.width(), rect.height(), GL_RGBA, pixelType, image.constScanLine(rect.y()) + rect.x() * 4); funcs->glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); } else @@ -178,10 +214,10 @@ bool QPlatformGraphicsBufferHelper::bindSWToTexture(const QPlatformGraphicsBuffe // OpenGL instead of copying, since there's no gap between scanlines if (rect.width() == size.width()) { - funcs->glTexSubImage2D(GL_TEXTURE_2D, 0, 0, rect.y(), rect.width(), rect.height(), GL_RGBA, GL_UNSIGNED_BYTE, + funcs->glTexSubImage2D(GL_TEXTURE_2D, 0, 0, rect.y(), rect.width(), rect.height(), GL_RGBA, pixelType, image.constScanLine(rect.y())); } else { - funcs->glTexSubImage2D(GL_TEXTURE_2D, 0, rect.x(), rect.y(), rect.width(), rect.height(), GL_RGBA, GL_UNSIGNED_BYTE, + funcs->glTexSubImage2D(GL_TEXTURE_2D, 0, rect.x(), rect.y(), rect.width(), rect.height(), GL_RGBA, pixelType, image.copy(rect).constBits()); } } -- cgit v1.2.3