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 <paul.tvete@theqtcompany.com>
This commit is contained in:
Laszlo Agocs 2016-02-05 09:56:49 +01:00 committed by Jani Heikkinen
parent b6630a5181
commit 4c1b6cdd29

View File

@ -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