Add flip support to QPlatformBackingStore::toTexture()

Necessary for iOS. In addition to swizzle we also need to communicate the need
for flipping, so switch to flags instead of bools.

Task-number: QTBUG-40034
Change-Id: I055e591afd838878503be6f5f69aa7347965d9cf
Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@theqtcompany.com>
bb10
Laszlo Agocs 2015-04-21 11:05:07 +02:00
parent 4a4faedc3d
commit 39e3977cc5
2 changed files with 49 additions and 26 deletions

View File

@ -308,7 +308,11 @@ void QPlatformBackingStore::composeAndFlush(QWindow *window, const QRegion &regi
textureId = d_ptr->textureId;
} else {
// Backingstore texture with the normal widgets.
textureId = toTexture(deviceRegion(region, window), &d_ptr->textureSize, &d_ptr->needsSwizzle);
TextureFlags flags = 0;
textureId = toTexture(deviceRegion(region, window), &d_ptr->textureSize, &flags);
d_ptr->needsSwizzle = (flags & TextureSwizzle) != 0;
if (flags & TextureFlip)
origin = QOpenGLTextureBlitter::OriginBottomLeft;
}
if (textureId) {
@ -354,43 +358,55 @@ QImage QPlatformBackingStore::toImage() const
backingstore as an OpenGL texture. \a dirtyRegion is the part of the
backingstore which may have changed since the last call to this function. The
caller of this function must ensure that there is a current context.
The size of the texture is returned in \a textureSize.
The ownership of the texture is not transferred. The caller must not store
the return value between calls, but instead call this function before each use.
The default implementation returns a cached texture if \a dirtyRegion is
empty and the window has not been resized, otherwise it retrieves the
content using toImage() and performs a texture upload.
The default implementation returns a cached texture if \a dirtyRegion is empty and
\a textureSize matches the backingstore size, otherwise it retrieves the content using
toImage() and performs a texture upload. This works only if the value of \a textureSize
is preserved between the calls to this function.
If the red and blue components have to swapped, \a needsSwizzle will be set to \c true.
This allows creating textures from images in formats like QImage::Format_RGB32 without
any further image conversion. Instead, the swizzling will be done in the shaders when
performing composition. Other formats, that do not need such swizzling due to being
already byte ordered RGBA, for example QImage::Format_RGBA8888, must result in having \a
needsSwizzle set to false.
If the red and blue components have to swapped, \a flags will be set to include \c
TextureSwizzle. This allows creating textures from images in formats like
QImage::Format_RGB32 without any further image conversion. Instead, the swizzling will
be done in the shaders when performing composition. Other formats, that do not need
such swizzling due to being already byte ordered RGBA, for example
QImage::Format_RGBA8888, must result in having \a needsSwizzle set to false.
If the image has to be flipped (e.g. because the texture is attached to an FBO), \a
flags will be set to include \c TextureFlip.
*/
GLuint QPlatformBackingStore::toTexture(const QRegion &dirtyRegion, QSize *textureSize, bool *needsSwizzle) const
GLuint QPlatformBackingStore::toTexture(const QRegion &dirtyRegion, QSize *textureSize, TextureFlags *flags) const
{
Q_ASSERT(textureSize);
Q_ASSERT(flags);
QImage image = toImage();
QSize imageSize = image.size();
if (imageSize.isEmpty())
return 0;
bool resized = d_ptr->textureSize != imageSize;
*flags = 0;
if (image.format() == QImage::Format_RGB32)
*flags |= TextureSwizzle;
if (imageSize.isEmpty()) {
*textureSize = imageSize;
return 0;
}
// Must rely on the input only, not d_ptr.
// With the default composeAndFlush() textureSize is &d_ptr->textureSize.
bool resized = *textureSize != imageSize;
if (dirtyRegion.isEmpty() && !resized)
return d_ptr->textureId;
*textureSize = imageSize;
// Fast path for RGB32 and RGBA8888, convert everything else to RGBA8888.
if (image.format() == QImage::Format_RGB32) {
if (needsSwizzle)
*needsSwizzle = true;
} else {
if (needsSwizzle)
*needsSwizzle = false;
if (image.format() != QImage::Format_RGBA8888)
image = image.convertToFormat(QImage::Format_RGBA8888);
}
if (image.format() != QImage::Format_RGB32 && image.format() != QImage::Format_RGBA8888)
image = image.convertToFormat(QImage::Format_RGBA8888);
QOpenGLFunctions *funcs = QOpenGLContext::currentContext()->functions();
@ -412,8 +428,6 @@ GLuint QPlatformBackingStore::toTexture(const QRegion &dirtyRegion, QSize *textu
funcs->glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, imageSize.width(), imageSize.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE,
const_cast<uchar*>(image.constBits()));
if (textureSize)
*textureSize = imageSize;
} else {
funcs->glBindTexture(GL_TEXTURE_2D, d_ptr->textureId);
QRect imageRect = image.rect();

View File

@ -114,7 +114,12 @@ public:
QPlatformTextureList *textures, QOpenGLContext *context,
bool translucentBackground);
virtual QImage toImage() const;
virtual GLuint toTexture(const QRegion &dirtyRegion, QSize *textureSize, bool *needsSwizzle) const;
enum TextureFlag {
TextureSwizzle = 0x01,
TextureFlip = 0x02
};
Q_DECLARE_FLAGS(TextureFlags, TextureFlag)
virtual GLuint toTexture(const QRegion &dirtyRegion, QSize *textureSize, TextureFlags *flags) const;
#endif
virtual QPlatformGraphicsBuffer *graphicsBuffer() const;
@ -130,6 +135,10 @@ private:
QPlatformBackingStorePrivate *d_ptr;
};
#ifndef QT_NO_OPENGL
Q_DECLARE_OPERATORS_FOR_FLAGS(QPlatformBackingStore::TextureFlags)
#endif
QT_END_NAMESPACE
#endif // QPLATFORMBACKINGSTORE_H