Use texture unpacking for QImage uploads when possible

This change avoids unnecessary copying of QImage data when updating
textures using QImages that have non-ARGB32_Premultiplied formats.

There are three cases where texture unpacking can not be done/is
not worth doing: if GLES is used, and the extension for unpacking
subimages is not supported; if the entire image is being updated;
or if a format conversion needs to be done, in which case only the
region to update will have its format converted, and the resulting
image can be passed directly to glTexSubImage2d without setting
unpacking parameters.
remotes/origin/work/abstract-egl-backend-no-surface
Manuel Stoeckl 5 years ago committed by Vlad Zahorodnii
parent 214a318811
commit 2aa3ed0005
  1. 82
      src/libkwineffects/kwingltexture.cpp

@ -366,59 +366,63 @@ void GLTexture::update(const QImage &image, const QPoint &offset, const QRect &s
Q_D(GLTexture);
Q_ASSERT(!d->m_foreign);
bool useUnpack = !src.isNull() && d->s_supportsUnpack && d->s_supportsARGB32 && image.format() == QImage::Format_ARGB32_Premultiplied;
int width = image.width();
int height = image.height();
QImage tmpImage;
if (!src.isNull()) {
if (useUnpack) {
glPixelStorei(GL_UNPACK_ROW_LENGTH, image.width());
glPixelStorei(GL_UNPACK_SKIP_PIXELS, src.x());
glPixelStorei(GL_UNPACK_SKIP_ROWS, src.y());
} else {
tmpImage = image.copy(src);
}
width = src.width();
height = src.height();
}
const QImage &img = tmpImage.isNull() ? image : tmpImage;
bind();
GLenum glFormat;
GLenum type;
QImage::Format uploadFormat;
if (!GLPlatform::instance()->isGLES()) {
QImage im;
GLenum format;
GLenum type;
const QImage::Format index = image.format();
if (index < sizeof(formatTable) / sizeof(formatTable[0]) && formatTable[index].internalFormat) {
format = formatTable[index].format;
glFormat = formatTable[index].format;
type = formatTable[index].type;
im = img;
uploadFormat = index;
} else {
format = GL_BGRA;
glFormat = GL_BGRA;
type = GL_UNSIGNED_INT_8_8_8_8_REV;
im = img.convertToFormat(QImage::Format_ARGB32_Premultiplied);
uploadFormat = QImage::Format_ARGB32_Premultiplied;
}
glTexSubImage2D(d->m_target, 0, offset.x(), offset.y(), width, height,
format, type, im.constBits());
} else {
if (d->s_supportsARGB32) {
const QImage im = img.convertToFormat(QImage::Format_ARGB32_Premultiplied);
glTexSubImage2D(d->m_target, 0, offset.x(), offset.y(), width, height,
GL_BGRA_EXT, GL_UNSIGNED_BYTE, im.constBits());
glFormat = GL_BGRA_EXT;
type = GL_UNSIGNED_BYTE;
uploadFormat = QImage::Format_ARGB32_Premultiplied;
} else {
glFormat = GL_RGBA;
type = GL_UNSIGNED_BYTE;
uploadFormat = QImage::Format_RGBA8888_Premultiplied;
}
}
bool useUnpack = d->s_supportsUnpack && image.format() == uploadFormat && !src.isNull();
QImage im;
if (useUnpack) {
im = image;
Q_ASSERT(im.depth() % 8 == 0);
glPixelStorei(GL_UNPACK_ROW_LENGTH, im.bytesPerLine() / (im.depth() / 8));
glPixelStorei(GL_UNPACK_SKIP_PIXELS, src.x());
glPixelStorei(GL_UNPACK_SKIP_ROWS, src.y());
} else {
if (src.isNull()) {
im = image;
} else {
const QImage im = img.convertToFormat(QImage::Format_RGBA8888_Premultiplied);
glTexSubImage2D(d->m_target, 0, offset.x(), offset.y(), width, height,
GL_RGBA, GL_UNSIGNED_BYTE, im.constBits());
im = image.copy(src);
}
if (im.format() != uploadFormat) {
im.convertTo(uploadFormat);
}
}
int width = image.width();
int height = image.height();
if (!src.isNull()) {
width = src.width();
height = src.height();
}
bind();
glTexSubImage2D(d->m_target, 0, offset.x(), offset.y(), width, height, glFormat, type, im.constBits());
unbind();
if (useUnpack) {

Loading…
Cancel
Save