From 4c1b6cdd292bc571a4104fff8b5b54d47970cca1 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Fri, 5 Feb 2016 09:56:49 +0100 Subject: Support arbitrary strides in the QPlatformBackingStore compositor Otherwise platform backingstores providing QImages with extra pixels would break horribly. The only such platform is wayland for now. Previously the need to support this case was masked by the RGBA8888 image conversion that happened always with wayland due to its ARGB32_Pre format. With the recent improvements this is not done anymore and so the problems became apparent. Task-number: QTBUG-50894 Change-Id: I27d7a1c8e25d152ca1227af1e2c38f7d4b6acbab Reviewed-by: Paul Olav Tvete --- src/gui/painting/qplatformbackingstore.cpp | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/src/gui/painting/qplatformbackingstore.cpp b/src/gui/painting/qplatformbackingstore.cpp index 5ac903c71d..33d5e76e52 100644 --- a/src/gui/painting/qplatformbackingstore.cpp +++ b/src/gui/painting/qplatformbackingstore.cpp @@ -516,7 +516,23 @@ GLuint QPlatformBackingStore::toTexture(const QRegion &dirtyRegion, QSize *textu if (needsConversion) image = image.convertToFormat(QImage::Format_RGBA8888); + // The image provided by the backingstore may have a stride larger than width * 4, for + // instance on platforms that manually implement client-side decorations. + static const int bytesPerPixel = 4; + const int strideInPixels = image.bytesPerLine() / bytesPerPixel; + const bool hasUnpackRowLength = !ctx->isOpenGLES() || ctx->format().majorVersion() >= 3; + QOpenGLFunctions *funcs = ctx->functions(); + + if (hasUnpackRowLength) { + funcs->glPixelStorei(GL_UNPACK_ROW_LENGTH, strideInPixels); + } else if (strideInPixels != image.width()) { + // No UNPACK_ROW_LENGTH on ES 2.0 and yet we would need it. This case is typically + // hit with QtWayland which is rarely used in combination with a ES2.0-only GL + // implementation. Therefore, accept the performance hit and do a copy. + image = image.copy(); + } + if (resized) { if (d_ptr->textureId) funcs->glDeleteTextures(1, &d_ptr->textureId); @@ -538,11 +554,9 @@ GLuint QPlatformBackingStore::toTexture(const QRegion &dirtyRegion, QSize *textu QRect imageRect = image.rect(); QRect rect = dirtyRegion.boundingRect() & imageRect; - if (!ctx->isOpenGLES() || ctx->format().majorVersion() >= 3) { - funcs->glPixelStorei(GL_UNPACK_ROW_LENGTH, image.width()); + if (hasUnpackRowLength) { 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); + image.constScanLine(rect.y()) + rect.x() * bytesPerPixel); } else { // if the rect is wide enough it's cheaper to just // extend it instead of doing an image copy @@ -564,6 +578,9 @@ GLuint QPlatformBackingStore::toTexture(const QRegion &dirtyRegion, QSize *textu } } + if (hasUnpackRowLength) + funcs->glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); + return d_ptr->textureId; } #endif // QT_NO_OPENGL -- cgit v1.2.3