--- a/src/opengl/qgl.cpp Tue Feb 02 00:43:10 2010 +0200
+++ b/src/opengl/qgl.cpp Wed Mar 31 11:06:36 2010 +0300
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
@@ -104,6 +104,10 @@
QGLExtensionFuncs QGLContextPrivate::qt_extensionFuncs;
#endif
+#ifdef Q_WS_X11
+extern const QX11Info *qt_x11Info(const QPaintDevice *pd);
+#endif
+
struct QGLThreadContext {
QGLContext *context;
};
@@ -124,9 +128,6 @@
};
Q_GLOBAL_STATIC(QGLDefaultOverlayFormat, defaultOverlayFormatInstance)
-QGLExtensions::Extensions QGLExtensions::glExtensions = 0;
-bool QGLExtensions::nvidiaFboNeedsFinish = false;
-
Q_GLOBAL_STATIC(QGLSignalProxy, theSignalProxy)
QGLSignalProxy *QGLSignalProxy::instance()
{
@@ -154,11 +155,9 @@
// falling back to the GL 1 engine..
static bool mac_x1600_check_done = false;
if (!mac_x1600_check_done) {
- QGLWidget *tmp = 0;
- if (!QGLContext::currentContext()) {
- tmp = new QGLWidget();
- tmp->makeCurrent();
- }
+ QGLTemporaryContext *tmp = 0;
+ if (!QGLContext::currentContext())
+ tmp = new QGLTemporaryContext();
if (strstr((char *) glGetString(GL_RENDERER), "X1600"))
engineType = QPaintEngine::OpenGL;
if (tmp)
@@ -178,7 +177,7 @@
// from an old GL 1.1 server to a GL 2.x client. In that case we can't
// use GL 2.0.
if ((QGLFormat::openGLVersionFlags() & QGLFormat::OpenGL_Version_2_0)
- && (QGLExtensions::glExtensions & QGLExtensions::FragmentShader)
+ && (QGLExtensions::glExtensions() & QGLExtensions::FragmentShader)
&& qgetenv("QT_GL_USE_OPENGL1ENGINE").isEmpty())
engineType = QPaintEngine::OpenGL2;
else
@@ -1250,7 +1249,7 @@
static bool cachedDefault = false;
static OpenGLVersionFlags defaultVersionFlags = OpenGL_Version_None;
QGLContext *currentCtx = const_cast<QGLContext *>(QGLContext::currentContext());
- QGLWidget *dummy = 0;
+ QGLTemporaryContext *tmpContext = 0;
if (currentCtx && currentCtx->d_func()->version_flags_cached)
return currentCtx->d_func()->version_flags;
@@ -1261,8 +1260,7 @@
} else {
if (!hasOpenGL())
return defaultVersionFlags;
- dummy = new QGLWidget;
- dummy->makeCurrent(); // glGetString() needs a current context
+ tmpContext = new QGLTemporaryContext;
cachedDefault = true;
}
}
@@ -1273,9 +1271,9 @@
currentCtx->d_func()->version_flags_cached = true;
currentCtx->d_func()->version_flags = versionFlags;
}
- if (dummy) {
+ if (tmpContext) {
defaultVersionFlags = versionFlags;
- delete dummy;
+ delete tmpContext;
}
return versionFlags;
@@ -1436,6 +1434,18 @@
m_guards = guard->m_next;
}
+const QGLContext *qt_gl_transfer_context(const QGLContext *ctx)
+{
+ if (!ctx)
+ return 0;
+ QList<const QGLContext *> shares
+ (QGLContextPrivate::contextGroup(ctx)->shares());
+ if (shares.size() >= 2)
+ return (ctx == shares.at(0)) ? shares.at(1) : shares.at(0);
+ else
+ return 0;
+}
+
QGLContextPrivate::~QGLContextPrivate()
{
if (!group->m_refs.deref()) {
@@ -1481,9 +1491,13 @@
max_texture_size = -1;
version_flags_cached = false;
version_flags = QGLFormat::OpenGL_Version_None;
+ extension_flags_cached = false;
+ extension_flags = 0;
current_fbo = 0;
default_fbo = 0;
active_engine = 0;
+ for (int i = 0; i < QT_GL_VERTEX_ARRAY_TRACKED_COUNT; ++i)
+ vertexAttributeArraysEnabledState[i] = false;
}
QGLContext* QGLContext::currentCtx = 0;
@@ -1541,7 +1555,7 @@
QImage qt_gl_read_texture(const QSize &size, bool alpha_format, bool include_alpha)
{
- QImage img(size, alpha_format ? QImage::Format_ARGB32 : QImage::Format_RGB32);
+ QImage img(size, alpha_format ? QImage::Format_ARGB32_Premultiplied : QImage::Format_RGB32);
int w = size.width();
int h = size.height();
#if !defined(QT_OPENGL_ES_2) && !defined(QT_OPENGL_ES_1) && !defined(QT_OPENGL_ES_1_CL)
@@ -1580,22 +1594,18 @@
Q_ASSERT(qt_gl_texture_cache == 0);
qt_gl_texture_cache = this;
- QImagePixmapCleanupHooks::instance()->addPixmapModificationHook(cleanupTextures);
-#ifdef Q_WS_X11
- QImagePixmapCleanupHooks::instance()->addPixmapDestructionHook(cleanupPixmapSurfaces);
-#endif
- QImagePixmapCleanupHooks::instance()->addImageHook(imageCleanupHook);
+ QImagePixmapCleanupHooks::instance()->addPixmapDataModificationHook(cleanupTexturesForPixampData);
+ QImagePixmapCleanupHooks::instance()->addPixmapDataDestructionHook(cleanupBeforePixmapDestruction);
+ QImagePixmapCleanupHooks::instance()->addImageHook(cleanupTexturesForCacheKey);
}
QGLTextureCache::~QGLTextureCache()
{
qt_gl_texture_cache = 0;
- QImagePixmapCleanupHooks::instance()->removePixmapModificationHook(cleanupTextures);
-#ifdef Q_WS_X11
- QImagePixmapCleanupHooks::instance()->removePixmapDestructionHook(cleanupPixmapSurfaces);
-#endif
- QImagePixmapCleanupHooks::instance()->removeImageHook(imageCleanupHook);
+ QImagePixmapCleanupHooks::instance()->removePixmapDataModificationHook(cleanupTexturesForPixampData);
+ QImagePixmapCleanupHooks::instance()->removePixmapDataDestructionHook(cleanupBeforePixmapDestruction);
+ QImagePixmapCleanupHooks::instance()->removeImageHook(cleanupTexturesForCacheKey);
}
void QGLTextureCache::insert(QGLContext* ctx, qint64 key, QGLTexture* texture, int cost)
@@ -1651,41 +1661,33 @@
a hook that removes textures from the cache when a pixmap/image
is deref'ed
*/
-void QGLTextureCache::imageCleanupHook(qint64 cacheKey)
-{
- // ### remove when the GL texture cache becomes thread-safe
- if (qApp->thread() != QThread::currentThread())
- return;
- QGLTexture *texture = instance()->getTexture(cacheKey);
- if (texture && texture->options & QGLContext::MemoryManagedBindOption)
- instance()->remove(cacheKey);
-}
-
-
-void QGLTextureCache::cleanupTextures(QPixmap* pixmap)
+void QGLTextureCache::cleanupTexturesForCacheKey(qint64 cacheKey)
{
// ### remove when the GL texture cache becomes thread-safe
if (qApp->thread() == QThread::currentThread()) {
- const qint64 cacheKey = pixmap->cacheKey();
- QGLTexture *texture = instance()->getTexture(cacheKey);
- if (texture && texture->options & QGLContext::MemoryManagedBindOption)
- instance()->remove(cacheKey);
+ instance()->remove(cacheKey);
+ Q_ASSERT(instance()->getTexture(cacheKey) == 0);
}
}
+
+void QGLTextureCache::cleanupTexturesForPixampData(QPixmapData* pmd)
+{
+ cleanupTexturesForCacheKey(pmd->cacheKey());
+}
+
+void QGLTextureCache::cleanupBeforePixmapDestruction(QPixmapData* pmd)
+{
+ // Remove any bound textures first:
+ cleanupTexturesForPixampData(pmd);
+
#if defined(Q_WS_X11)
-void QGLTextureCache::cleanupPixmapSurfaces(QPixmap* pixmap)
-{
- // Remove any bound textures first:
- cleanupTextures(pixmap);
-
- QPixmapData *pd = pixmap->data_ptr().data();
- if (pd->classId() == QPixmapData::X11Class) {
- Q_ASSERT(pd->ref == 1); // Make sure reference counting isn't broken
- QGLContextPrivate::destroyGlSurfaceForPixmap(pd);
+ if (pmd->classId() == QPixmapData::X11Class) {
+ Q_ASSERT(pmd->ref == 0); // Make sure reference counting isn't broken
+ QGLContextPrivate::destroyGlSurfaceForPixmap(pmd);
}
-}
#endif
+}
void QGLTextureCache::deleteIfEmpty()
{
@@ -1729,12 +1731,6 @@
#define GL_GENERATE_MIPMAP_HINT_SGIS 0x8192
#endif
-Q_GLOBAL_STATIC(QGLShareRegister, _qgl_share_reg)
-Q_OPENGL_EXPORT QGLShareRegister* qgl_share_reg()
-{
- return _qgl_share_reg();
-}
-
/*!
\class QGLContext
\brief The QGLContext class encapsulates an OpenGL rendering context.
@@ -1874,6 +1870,35 @@
{
}
+#define ctx q_ptr
+void QGLContextPrivate::setVertexAttribArrayEnabled(int arrayIndex, bool enabled)
+{
+ Q_ASSERT(arrayIndex < QT_GL_VERTEX_ARRAY_TRACKED_COUNT);
+ Q_ASSERT(glEnableVertexAttribArray);
+
+ if (vertexAttributeArraysEnabledState[arrayIndex] && !enabled)
+ glDisableVertexAttribArray(arrayIndex);
+
+ if (!vertexAttributeArraysEnabledState[arrayIndex] && enabled)
+ glEnableVertexAttribArray(arrayIndex);
+
+ vertexAttributeArraysEnabledState[arrayIndex] = enabled;
+}
+
+void QGLContextPrivate::syncGlState()
+{
+ Q_ASSERT(glEnableVertexAttribArray);
+ for (int i = 0; i < QT_GL_VERTEX_ARRAY_TRACKED_COUNT; ++i) {
+ if (vertexAttributeArraysEnabledState[i])
+ glEnableVertexAttribArray(i);
+ else
+ glDisableVertexAttribArray(i);
+ }
+
+}
+#undef ctx
+
+
/*!
\overload
@@ -2055,8 +2080,9 @@
// NOTE: bindTexture(const QImage&, GLenum, GLint, const qint64, bool) should never return null
Q_ASSERT(texture);
- if (texture->id > 0)
- QImagePixmapCleanupHooks::enableCleanupHooks(image);
+ // Enable the cleanup hooks for this image so that the texture cache entry is removed when the
+ // image gets deleted:
+ QImagePixmapCleanupHooks::enableCleanupHooks(image);
return texture;
}
@@ -2110,7 +2136,8 @@
int tx_h = qt_next_power_of_two(image.height());
QImage img = image;
- if (!(QGLExtensions::glExtensions & QGLExtensions::NPOTTextures)
+
+ if (!(QGLExtensions::glExtensions() & QGLExtensions::NPOTTextures)
&& !(QGLFormat::openGLVersionFlags() & QGLFormat::OpenGL_ES_Version_2_0)
&& (target == GL_TEXTURE_2D && (tx_w != image.width() || tx_h != image.height())))
{
@@ -2132,7 +2159,7 @@
bool genMipmap = false;
#endif
if (glFormat.directRendering()
- && (QGLExtensions::glExtensions & QGLExtensions::GenerateMipmap)
+ && (QGLExtensions::glExtensions() & QGLExtensions::GenerateMipmap)
&& target == GL_TEXTURE_2D
&& (options & QGLContext::MipmapBindOption))
{
@@ -2160,9 +2187,12 @@
bool premul = options & QGLContext::PremultipliedAlphaBindOption;
GLenum externalFormat;
GLuint pixel_type;
- if (QGLExtensions::glExtensions & QGLExtensions::BGRATextureFormat) {
+ if (QGLExtensions::glExtensions() & QGLExtensions::BGRATextureFormat) {
externalFormat = GL_BGRA;
- pixel_type = GL_UNSIGNED_INT_8_8_8_8_REV;
+ if (QGLFormat::openGLVersionFlags() & QGLFormat::OpenGL_Version_1_2)
+ pixel_type = GL_UNSIGNED_INT_8_8_8_8_REV;
+ else
+ pixel_type = GL_UNSIGNED_BYTE;
} else {
externalFormat = GL_RGBA;
pixel_type = GL_UNSIGNED_BYTE;
@@ -2241,12 +2271,9 @@
qgl_byteSwapImage(img, pixel_type);
}
#ifdef QT_OPENGL_ES
- // OpenGL/ES requires that the internal and external formats be identical.
- // This is typically used to convert GL_RGBA into GL_BGRA.
- // Also, we need to use GL_UNSIGNED_BYTE when the format is GL_BGRA.
+ // OpenGL/ES requires that the internal and external formats be
+ // identical.
internalFormat = externalFormat;
- if (pixel_type == GL_UNSIGNED_INT_8_8_8_8_REV)
- pixel_type = GL_UNSIGNED_BYTE;
#endif
#ifdef QGL_BIND_TEXTURE_DEBUG
printf(" - uploading, image.format=%d, externalFormat=0x%x, internalFormat=0x%x, pixel_type=0x%x\n",
@@ -2278,6 +2305,7 @@
int cost = img.width()*img.height()*4/1024;
QGLTexture *texture = new QGLTexture(q, tx_id, target, options);
QGLTextureCache::instance()->insert(q, key, texture, cost);
+
return texture;
}
@@ -2322,7 +2350,10 @@
#if defined(Q_WS_X11)
// Try to use texture_from_pixmap
- if (pd->classId() == QPixmapData::X11Class && pd->pixelType() == QPixmapData::PixmapType) {
+ const QX11Info *xinfo = qt_x11Info(paintDevice);
+ if (pd->classId() == QPixmapData::X11Class && pd->pixelType() == QPixmapData::PixmapType
+ && xinfo && xinfo->screen() == pixmap.x11Info().screen())
+ {
texture = bindTextureFromNativePixmap(pd, key, options);
if (texture) {
texture->options |= QGLContext::MemoryManagedBindOption;
@@ -2391,7 +2422,7 @@
return 0;
Q_D(QGLContext);
- QGLTexture *texture = d->bindTexture(image, target, format, false, DefaultBindOption);
+ QGLTexture *texture = d->bindTexture(image, target, format, DefaultBindOption);
return texture->id;
}
@@ -2531,11 +2562,13 @@
for (int i = 0; i < ddsKeys.size(); ++i) {
GLuint texture = dds_cache->value(ddsKeys.at(i));
if (id == texture) {
- glDeleteTextures(1, &texture);
dds_cache->remove(ddsKeys.at(i));
- return;
+ break;
}
}
+
+ // Finally, actually delete the texture ID
+ glDeleteTextures(1, &id);
}
#ifdef Q_MAC_COMPAT_GL_FUNCTIONS
@@ -2954,7 +2987,7 @@
wd->usesDoubleBufferedGLContext = d->glFormat.doubleBuffer();
}
if (d->sharing) // ok, we managed to share
- qgl_share_reg()->addShare(this, shareContext);
+ QGLContextGroup::addShare(this, shareContext);
return d->valid;
}
@@ -4360,6 +4393,13 @@
\note This function temporarily disables depth-testing when the
text is drawn.
+ \note This function can only be used inside a
+ QPainter::beginNativePainting()/QPainter::endNativePainting() block
+ if the default OpenGL paint engine is QPaintEngine::OpenGL. To make
+ QPaintEngine::OpenGL the default GL engine, call
+ QGL::setPreferredPaintEngine(QPaintEngine::OpenGL) before the
+ QApplication constructor.
+
\l{Overpainting Example}{Overpaint} with QPainter::drawText() instead.
*/
@@ -4378,9 +4418,18 @@
int height = d->glcx->device()->height();
bool auto_swap = autoBufferSwap();
+ QPaintEngine::Type oldEngineType = qgl_engine_selector()->preferredPaintEngine();
+
QPaintEngine *engine = paintEngine();
- if (engine->type() == QPaintEngine::OpenGL2)
- static_cast<QGL2PaintEngineEx *>(engine)->setRenderTextActive(true);
+ if (engine && (oldEngineType == QPaintEngine::OpenGL2) && engine->isActive()) {
+ qWarning("QGLWidget::renderText(): Calling renderText() while a GL 2 paint engine is"
+ " active on the same device is not allowed.");
+ return;
+ }
+
+ // this changes what paintEngine() returns
+ qgl_engine_selector()->setPreferredPaintEngine(QPaintEngine::OpenGL);
+ engine = paintEngine();
QPainter *p;
bool reuse_painter = false;
if (engine->isActive()) {
@@ -4400,11 +4449,6 @@
setAutoBufferSwap(false);
// disable glClear() as a result of QPainter::begin()
d->disable_clear_on_painter_begin = true;
- if (engine->type() == QPaintEngine::OpenGL2) {
- qt_save_gl_state();
- glMatrixMode(GL_MODELVIEW);
- glLoadIdentity();
- }
p = new QPainter(this);
}
@@ -4428,11 +4472,8 @@
delete p;
setAutoBufferSwap(auto_swap);
d->disable_clear_on_painter_begin = false;
- if (engine->type() == QPaintEngine::OpenGL2)
- qt_restore_gl_state();
}
- if (engine->type() == QPaintEngine::OpenGL2)
- static_cast<QGL2PaintEngineEx *>(engine)->setRenderTextActive(false);
+ qgl_engine_selector()->setPreferredPaintEngine(oldEngineType);
#else // QT_OPENGL_ES
Q_UNUSED(x);
Q_UNUSED(y);
@@ -4480,9 +4521,18 @@
&win_x, &win_y, &win_z);
win_y = height - win_y; // y is inverted
+ QPaintEngine::Type oldEngineType = qgl_engine_selector()->preferredPaintEngine();
QPaintEngine *engine = paintEngine();
- if (engine->type() == QPaintEngine::OpenGL2)
- static_cast<QGL2PaintEngineEx *>(engine)->setRenderTextActive(true);
+
+ if (engine && (oldEngineType == QPaintEngine::OpenGL2) && engine->isActive()) {
+ qWarning("QGLWidget::renderText(): Calling renderText() while a GL 2 paint engine is"
+ " active on the same device is not allowed.");
+ return;
+ }
+
+ // this changes what paintEngine() returns
+ qgl_engine_selector()->setPreferredPaintEngine(QPaintEngine::OpenGL);
+ engine = paintEngine();
QPainter *p;
bool reuse_painter = false;
bool use_depth_testing = glIsEnabled(GL_DEPTH_TEST);
@@ -4496,8 +4546,6 @@
setAutoBufferSwap(false);
// disable glClear() as a result of QPainter::begin()
d->disable_clear_on_painter_begin = true;
- if (engine->type() == QPaintEngine::OpenGL2)
- qt_save_gl_state();
p = new QPainter(this);
}
@@ -4526,13 +4574,10 @@
} else {
p->end();
delete p;
- if (engine->type() == QPaintEngine::OpenGL2)
- qt_restore_gl_state();
setAutoBufferSwap(auto_swap);
d->disable_clear_on_painter_begin = false;
}
- if (engine->type() == QPaintEngine::OpenGL2)
- static_cast<QGL2PaintEngineEx *>(engine)->setRenderTextActive(false);
+ qgl_engine_selector()->setPreferredPaintEngine(oldEngineType);
#else // QT_OPENGL_ES
Q_UNUSED(x);
Q_UNUSED(y);
@@ -4844,9 +4889,13 @@
#endif // QT3_SUPPORT
-void QGLExtensions::init_extensions()
+/*
+ Returns the GL extensions for the current context.
+*/
+QGLExtensions::Extensions QGLExtensions::currentContextExtensions()
{
QGLExtensionMatcher extensions(reinterpret_cast<const char *>(glGetString(GL_EXTENSIONS)));
+ Extensions glExtensions;
if (extensions.match("GL_ARB_texture_rectangle"))
glExtensions |= TextureRectangle;
@@ -4907,6 +4956,46 @@
if (extensions.match("GL_EXT_bgra"))
glExtensions |= BGRATextureFormat;
+
+ return glExtensions;
+}
+
+/*
+ Returns the GL extensions for the current QGLContext. If there is no
+ current QGLContext, a default context will be created and the extensions
+ for that context will be returned instead.
+*/
+QGLExtensions::Extensions QGLExtensions::glExtensions()
+{
+ QGLTemporaryContext *tmpContext = 0;
+ static bool cachedDefault = false;
+ static Extensions defaultExtensions = 0;
+ QGLContext *currentCtx = const_cast<QGLContext *>(QGLContext::currentContext());
+
+ if (currentCtx && currentCtx->d_func()->extension_flags_cached)
+ return currentCtx->d_func()->extension_flags;
+
+ if (!currentCtx) {
+ if (cachedDefault) {
+ return defaultExtensions;
+ } else {
+ tmpContext = new QGLTemporaryContext;
+ cachedDefault = true;
+ }
+ }
+
+ Extensions extensionFlags = currentContextExtensions();
+ if (currentCtx) {
+ currentCtx->d_func()->extension_flags_cached = true;
+ currentCtx->d_func()->extension_flags = extensionFlags;
+ } else {
+ defaultExtensions = extensionFlags;
+ }
+
+ if (tmpContext)
+ delete tmpContext;
+
+ return extensionFlags;
}
/*
@@ -4918,7 +5007,6 @@
glDevice.setWidget(q);
- QGLExtensions::init();
glcx = 0;
autoSwap = true;
@@ -4928,8 +5016,6 @@
if (!glcx)
glcx = new QGLContext(QGLFormat::defaultFormat(), q);
-
- q->setAttribute(Qt::WA_NoSystemBackground);
}
#if defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_WS_QWS)
@@ -4953,7 +5039,7 @@
}
#endif
-void QGLShareRegister::addShare(const QGLContext *context, const QGLContext *share) {
+void QGLContextGroup::addShare(const QGLContext *context, const QGLContext *share) {
Q_ASSERT(context && share);
if (context->d_ptr->group == share->d_ptr->group)
return;
@@ -4974,11 +5060,7 @@
group->m_shares.append(context);
}
-QList<const QGLContext *> QGLShareRegister::shares(const QGLContext *context) {
- return context->d_ptr->group->m_shares;
-}
-
-void QGLShareRegister::removeShare(const QGLContext *context) {
+void QGLContextGroup::removeShare(const QGLContext *context) {
// Remove the context from the group.
QGLContextGroup *group = context->d_ptr->group;
if (group->m_shares.isEmpty())
@@ -5173,7 +5255,7 @@
}
#if !defined(QT_OPENGL_ES)
if (!glCompressedTexImage2D) {
- if (!(QGLExtensions::glExtensions & QGLExtensions::TextureCompression)) {
+ if (!(QGLExtensions::glExtensions() & QGLExtensions::TextureCompression)) {
qWarning("QGLContext::bindTexture(): The GL implementation does "
"not support texture compression extensions.");
return QSize();
@@ -5212,7 +5294,7 @@
return QSize();
// Bail out if the necessary extension is not present.
- if (!(QGLExtensions::glExtensions & QGLExtensions::DDSTextureCompression)) {
+ if (!(QGLExtensions::glExtensions() & QGLExtensions::DDSTextureCompression)) {
qWarning("QGLContext::bindTexture(): DDS texture compression is not supported.");
return QSize();
}
@@ -5322,13 +5404,13 @@
// Bail out if the necessary extension is not present.
if (textureFormat == GL_ETC1_RGB8_OES) {
- if (!(QGLExtensions::glExtensions &
+ if (!(QGLExtensions::glExtensions() &
QGLExtensions::ETC1TextureCompression)) {
qWarning("QGLContext::bindTexture(): ETC1 texture compression is not supported.");
return QSize();
}
} else {
- if (!(QGLExtensions::glExtensions &
+ if (!(QGLExtensions::glExtensions() &
QGLExtensions::PVRTCTextureCompression)) {
qWarning("QGLContext::bindTexture(): PVRTC texture compression is not supported.");
return QSize();
@@ -5369,7 +5451,7 @@
quint32 level = 0;
quint32 width = pvrHeader->width;
quint32 height = pvrHeader->height;
- while (bufferSize > 0 && level < pvrHeader->mipMapCount) {
+ while (bufferSize > 0 && level <= pvrHeader->mipMapCount) {
quint32 size =
(qMax(width, minWidth) * qMax(height, minHeight) *
pvrHeader->bitsPerPixel) / 8;