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.
This commit is contained in:
parent
214a318811
commit
2aa3ed0005
1 changed files with 46 additions and 42 deletions
|
@ -366,58 +366,62 @@ 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;
|
||||
GLenum glFormat;
|
||||
GLenum type;
|
||||
QImage::Format uploadFormat;
|
||||
if (!GLPlatform::instance()->isGLES()) {
|
||||
const QImage::Format index = image.format();
|
||||
|
||||
if (index < sizeof(formatTable) / sizeof(formatTable[0]) && formatTable[index].internalFormat) {
|
||||
glFormat = formatTable[index].format;
|
||||
type = formatTable[index].type;
|
||||
uploadFormat = index;
|
||||
} else {
|
||||
glFormat = GL_BGRA;
|
||||
type = GL_UNSIGNED_INT_8_8_8_8_REV;
|
||||
uploadFormat = QImage::Format_ARGB32_Premultiplied;
|
||||
}
|
||||
} else {
|
||||
if (d->s_supportsARGB32) {
|
||||
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 {
|
||||
im = image.copy(src);
|
||||
}
|
||||
if (im.format() != uploadFormat) {
|
||||
im.convertTo(uploadFormat);
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
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;
|
||||
type = formatTable[index].type;
|
||||
im = img;
|
||||
} else {
|
||||
format = GL_BGRA;
|
||||
type = GL_UNSIGNED_INT_8_8_8_8_REV;
|
||||
im = img.convertToFormat(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());
|
||||
} 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());
|
||||
}
|
||||
}
|
||||
glTexSubImage2D(d->m_target, 0, offset.x(), offset.y(), width, height, glFormat, type, im.constBits());
|
||||
|
||||
unbind();
|
||||
|
||||
|
|
Loading…
Reference in a new issue