diff options
author | Jani Hautakangas <jani.hautakangas@nokia.com> | 2011-05-10 20:41:09 (GMT) |
---|---|---|
committer | Jani Hautakangas <jani.hautakangas@nokia.com> | 2011-06-09 10:31:54 (GMT) |
commit | 489baff3d49f7acce8d36dd98d27885ca207d6e7 (patch) | |
tree | f9b7a0decd67048b52c0513b7665ccd46135a8ce /src/opengl | |
parent | 7b0762c17f9899e68c0f67480a81b25c6f0c7dda (diff) | |
download | Qt-489baff3d49f7acce8d36dd98d27885ca207d6e7.zip Qt-489baff3d49f7acce8d36dd98d27885ca207d6e7.tar.gz Qt-489baff3d49f7acce8d36dd98d27885ca207d6e7.tar.bz2 |
Simplify texture pooling logic in GL graphics system.
Remove ugly TemporarilyCachedBindOption and use QGLTexture
objects as texture pool entries instead of QGLPixmapData.
Make texture pooling totally Symbian specific, remove
VG like texture pooling code and use common texture binding
path which is used on other platforms also on Symbian.
QGLPixmapData should be only used to bind SgImage based
textures (will be implemented by another commit).
Task-number: QTBUG-19180
Reviewed-by: Samuel Rødal
Diffstat (limited to 'src/opengl')
-rw-r--r-- | src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp | 28 | ||||
-rw-r--r-- | src/opengl/opengl.pro | 4 | ||||
-rw-r--r-- | src/opengl/qgl.cpp | 33 | ||||
-rw-r--r-- | src/opengl/qgl.h | 1 | ||||
-rw-r--r-- | src/opengl/qgl_p.h | 27 | ||||
-rw-r--r-- | src/opengl/qgltexturepool.cpp | 136 | ||||
-rw-r--r-- | src/opengl/qgltexturepool_p.h | 37 | ||||
-rw-r--r-- | src/opengl/qgraphicssystem_gl.cpp | 3 | ||||
-rw-r--r-- | src/opengl/qpixmapdata_gl_p.h | 28 | ||||
-rw-r--r-- | src/opengl/qpixmapdata_symbiangl.cpp (renamed from src/opengl/qpixmapdata_poolgl.cpp) | 123 | ||||
-rw-r--r-- | src/opengl/qwindowsurface_gl.cpp | 62 |
11 files changed, 191 insertions, 291 deletions
diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp index 56c1fd0..803f949 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp @@ -1331,14 +1331,11 @@ void QGL2PaintEngineEx::drawPixmap(const QRectF& dest, const QPixmap & pixmap, c ensureActive(); d->transferMode(ImageDrawingMode); - QGLContext::BindOptions bindOptions = QGLContext::InternalBindOption|QGLContext::CanFlipNativePixmapBindOption; -#ifdef QGL_USE_TEXTURE_POOL - bindOptions |= QGLContext::TemporarilyCachedBindOption; -#endif - glActiveTexture(GL_TEXTURE0 + QT_IMAGE_TEXTURE_UNIT); QGLTexture *texture = - ctx->d_func()->bindTexture(pixmap, GL_TEXTURE_2D, GL_RGBA, bindOptions); + ctx->d_func()->bindTexture(pixmap, GL_TEXTURE_2D, GL_RGBA, + QGLContext::InternalBindOption + | QGLContext::CanFlipNativePixmapBindOption); GLfloat top = texture->options & QGLContext::InvertedYBindOption ? (pixmap.height() - src.top()) : src.top(); GLfloat bottom = texture->options & QGLContext::InvertedYBindOption ? (pixmap.height() - src.bottom()) : src.bottom(); @@ -1350,12 +1347,6 @@ void QGL2PaintEngineEx::drawPixmap(const QRectF& dest, const QPixmap & pixmap, c d->updateTextureFilter(GL_TEXTURE_2D, GL_CLAMP_TO_EDGE, state()->renderHints & QPainter::SmoothPixmapTransform, texture->id); d->drawTexture(dest, srcRect, pixmap.size(), isOpaque, isBitmap); - - if (texture->options&QGLContext::TemporarilyCachedBindOption) { - // pixmap was temporarily cached as a QImage texture by pooling system - // and should be destroyed immediately - QGLTextureCache::instance()->remove(ctx, texture->id); - } } void QGL2PaintEngineEx::drawImage(const QRectF& dest, const QImage& image, const QRectF& src, @@ -1380,23 +1371,12 @@ void QGL2PaintEngineEx::drawImage(const QRectF& dest, const QImage& image, const glActiveTexture(GL_TEXTURE0 + QT_IMAGE_TEXTURE_UNIT); - QGLContext::BindOptions bindOptions = QGLContext::InternalBindOption; -#ifdef QGL_USE_TEXTURE_POOL - bindOptions |= QGLContext::TemporarilyCachedBindOption; -#endif - - QGLTexture *texture = ctx->d_func()->bindTexture(image, GL_TEXTURE_2D, GL_RGBA, bindOptions); + QGLTexture *texture = ctx->d_func()->bindTexture(image, GL_TEXTURE_2D, GL_RGBA, QGLContext::InternalBindOption); GLuint id = texture->id; d->updateTextureFilter(GL_TEXTURE_2D, GL_CLAMP_TO_EDGE, state()->renderHints & QPainter::SmoothPixmapTransform, id); d->drawTexture(dest, src, image.size(), !image.hasAlphaChannel()); - - if (texture->options&QGLContext::TemporarilyCachedBindOption) { - // image was temporarily cached by texture pooling system - // and should be destroyed immediately - QGLTextureCache::instance()->remove(ctx, texture->id); - } } void QGL2PaintEngineEx::drawStaticTextItem(QStaticTextItem *textItem) diff --git a/src/opengl/opengl.pro b/src/opengl/opengl.pro index 6d79584..4375358 100644 --- a/src/opengl/opengl.pro +++ b/src/opengl/opengl.pro @@ -148,10 +148,10 @@ embedded { } symbian { - DEFINES += QGL_USE_TEXTURE_POOL QGL_NO_PRESERVED_SWAP + DEFINES += QGL_NO_PRESERVED_SWAP SOURCES -= qpixmapdata_gl.cpp SOURCES += qgl_symbian.cpp \ - qpixmapdata_poolgl.cpp \ + qpixmapdata_symbiangl.cpp \ qglpixelbuffer_egl.cpp \ qgl_egl.cpp \ qgltexturepool.cpp diff --git a/src/opengl/qgl.cpp b/src/opengl/qgl.cpp index d09190f..6248cfe 100644 --- a/src/opengl/qgl.cpp +++ b/src/opengl/qgl.cpp @@ -93,7 +93,7 @@ #include "qlibrary.h" #include <qmutex.h> -#ifdef QGL_USE_TEXTURE_POOL +#ifdef Q_OS_SYMBIAN #include <private/qgltexturepool_p.h> #endif @@ -1835,6 +1835,7 @@ QGLTextureCache::~QGLTextureCache() void QGLTextureCache::insert(QGLContext* ctx, qint64 key, QGLTexture* texture, int cost) { QWriteLocker locker(&m_lock); + if (m_cache.totalCost() + cost > m_cache.maxCost()) { // the cache is full - make an attempt to remove something const QList<QGLTextureCacheKey> keys = m_cache.keys(); @@ -2026,10 +2027,6 @@ struct DDSFormat { the pixmap/image that it stems from, e.g. installing destruction hooks in them. - \omitvalue TemporarilyCachedBindOption Used by paint engines on some - platforms to indicate that the pixmap or image texture is possibly - cached only temporarily and must be destroyed immediately after the use. - \omitvalue InternalBindOption */ @@ -2537,7 +2534,8 @@ QGLTexture* QGLContextPrivate::bindTexture(const QImage &image, GLenum target, G #endif const QImage &constRef = img; // to avoid detach in bits()... -#ifdef QGL_USE_TEXTURE_POOL +#ifdef Q_OS_SYMBIAN + // On Symbian we always use texture pool to reserve the texture QGLTexturePool::instance()->createPermanentTexture(tx_id, target, 0, internalFormat, @@ -2549,6 +2547,7 @@ QGLTexture* QGLContextPrivate::bindTexture(const QImage &image, GLenum target, G glTexImage2D(target, 0, internalFormat, img.width(), img.height(), 0, externalFormat, pixel_type, constRef.bits()); #endif + #if defined(QT_OPENGL_ES_2) if (genMipmap) glGenerateMipmap(target); @@ -2572,6 +2571,13 @@ QGLTexture* QGLContextPrivate::bindTexture(const QImage &image, GLenum target, G QGLTexture *texture = new QGLTexture(q, tx_id, target, options); QGLTextureCache::instance()->insert(q, key, texture, cost); +#ifdef Q_OS_SYMBIAN + // Store the key so that QGLTexturePool + // is able to release this texture when needed. + texture->boundKey = key; + // And append to LRU list + QGLTexturePool::instance()->useTexture(texture); +#endif return texture; } @@ -2651,6 +2657,20 @@ QGLTexture *QGLContextPrivate::bindTexture(const QPixmap &pixmap, GLenum target, #endif if (!texture) { +#ifdef Q_OS_SYMBIAN + // On Symbian pixmaps are backed up by native CFbsBitmap + // which can be shared across processes. QVolatileImage wraps + // it and provides locking mechanism to pixel access. + QVolatileImage volatileImage = pd->toVolatileImage(); + if (volatileImage.isNull()) { // TODO: raster graphics system don't provide volatile image (yet) + // NOTE! On Symbian raster graphics system QPixmap::toImage() makes deep copy + texture = bindTexture(pixmap.toImage(), target, format, key, options); + } else { + volatileImage.beginDataAccess(); + texture = bindTexture(volatileImage.imageRef(), target, format, key, options); + volatileImage.endDataAccess(true); + } +#else QImage image = pixmap.toImage(); // If the system depth is 16 and the pixmap doesn't have an alpha channel // then we convert it to RGB16 in the hope that it gets uploaded as a 16 @@ -2658,6 +2678,7 @@ QGLTexture *QGLContextPrivate::bindTexture(const QPixmap &pixmap, GLenum target, if (pixmap.depth() == 16 && !image.hasAlphaChannel() ) image = image.convertToFormat(QImage::Format_RGB16); texture = bindTexture(image, target, format, key, options); +#endif } // NOTE: bindTexture(const QImage&, GLenum, GLint, const qint64, bool) should never return null Q_ASSERT(texture); diff --git a/src/opengl/qgl.h b/src/opengl/qgl.h index e070f5f..cd61ee5 100644 --- a/src/opengl/qgl.h +++ b/src/opengl/qgl.h @@ -329,7 +329,6 @@ public: MemoryManagedBindOption = 0x0010, // internal flag CanFlipNativePixmapBindOption = 0x0020, // internal flag - TemporarilyCachedBindOption = 0x0040, // internal flag DefaultBindOption = LinearFilteringBindOption | InvertedYBindOption diff --git a/src/opengl/qgl_p.h b/src/opengl/qgl_p.h index f64c65b..2fb7e58 100644 --- a/src/opengl/qgl_p.h +++ b/src/opengl/qgl_p.h @@ -64,6 +64,12 @@ #include "qcache.h" #include "qglpaintdevice_p.h" +#ifdef Q_OS_SYMBIAN +#include "qgltexturepool_p.h" + +class QGLPixmapData; +#endif + #ifndef QT_NO_EGL #include <QtGui/private/qegl_p.h> #endif @@ -540,6 +546,14 @@ public: options(opt) #if defined(Q_WS_X11) , boundPixmap(0) +#elif defined(Q_OS_SYMBIAN) + , boundPixmap(0) + , boundKey(0) + , nextLRU(0) + , prevLRU(0) + , inLRU(false) + , failedToAlloc(false) + , inTexturePool(false) #endif {} @@ -551,7 +565,7 @@ public: #endif context->d_ptr->texture_destroyer->emitFreeTexture(context, boundPixmap, id); } - } + } QGLContext *context; GLuint id; @@ -571,6 +585,17 @@ public: (const char *buf, int len, const char *format = 0); QSize bindCompressedTextureDDS(const char *buf, int len); QSize bindCompressedTexturePVR(const char *buf, int len); + +#ifdef Q_OS_SYMBIAN + QGLPixmapData* boundPixmap; + qint64 boundKey; + + QGLTexture *nextLRU; + QGLTexture *prevLRU; + mutable bool inLRU; + mutable bool failedToAlloc; + mutable bool inTexturePool; +#endif }; struct QGLTextureCacheKey { diff --git a/src/opengl/qgltexturepool.cpp b/src/opengl/qgltexturepool.cpp index d809328..9ad66f2 100644 --- a/src/opengl/qgltexturepool.cpp +++ b/src/opengl/qgltexturepool.cpp @@ -41,6 +41,7 @@ #include "qgltexturepool_p.h" #include "qpixmapdata_gl_p.h" +#include "qgl_p.h" QT_BEGIN_NAMESPACE @@ -53,8 +54,8 @@ class QGLTexturePoolPrivate public: QGLTexturePoolPrivate() : lruFirst(0), lruLast(0) {} - QGLPixmapData *lruFirst; - QGLPixmapData *lruLast; + QGLTexture *lruFirst; + QGLTexture *lruLast; }; QGLTexturePool::QGLTexturePool() @@ -73,36 +74,36 @@ QGLTexturePool *QGLTexturePool::instance() return qt_gl_texture_pool; } -GLuint QGLTexturePool::createTextureForPixmap(GLenum target, +GLuint QGLTexturePool::createTexture(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, - QGLPixmapData *data) + QGLTexture *texture) { - GLuint texture; - glGenTextures(1, &texture); - glBindTexture(target, texture); + GLuint tex; + glGenTextures(1, &tex); + glBindTexture(target, tex); do { glTexImage2D(target, level, internalformat, width, height, 0, format, type, 0); GLenum error = glGetError(); if (error == GL_NO_ERROR) { - if (data) - moveToHeadOfLRU(data); - return texture; + if (texture) + moveToHeadOfLRU(texture); + return tex; } else if (error != GL_OUT_OF_MEMORY) { qWarning("QGLTexturePool: cannot create temporary texture because of invalid params"); return 0; } - } while (reclaimSpace(internalformat, width, height, format, type, data)); - qWarning("QGLTexturePool: cannot reclaim sufficient space for a %dx%d pixmap", + } while (reclaimSpace(internalformat, width, height, format, type, texture)); + qWarning("QGLTexturePool: cannot reclaim sufficient space for a %dx%d texture", width, height); return 0; } -bool QGLTexturePool::createPermanentTexture(GLuint texture, +bool QGLTexturePool::createPermanentTexture(GLuint tex, GLenum target, GLint level, GLint internalformat, @@ -112,7 +113,7 @@ bool QGLTexturePool::createPermanentTexture(GLuint texture, GLenum type, const GLvoid *data) { - glBindTexture(target, texture); + glBindTexture(target, tex); do { glTexImage2D(target, level, internalformat, width, height, 0, format, type, data); @@ -124,32 +125,21 @@ bool QGLTexturePool::createPermanentTexture(GLuint texture, return false; } } while (reclaimSpace(internalformat, width, height, format, type, 0)); - qWarning("QGLTexturePool: cannot reclaim sufficient space for a %dx%d pixmap", + qWarning("QGLTexturePool: cannot reclaim sufficient space for a %dx%d texture", width, height); return 0; } -void QGLTexturePool::releaseTexture(QGLPixmapData *data, GLuint texture) +void QGLTexturePool::useTexture(QGLTexture *texture) { - // Very simple strategy at the moment: just destroy the texture. - if (data) - removeFromLRU(data); - - QGLWidget *shareWidget = qt_gl_share_widget(); - if (shareWidget) { - QGLShareContextScope ctx(shareWidget->context()); - glDeleteTextures(1, &texture); - } -} - -void QGLTexturePool::useTexture(QGLPixmapData *data) -{ - moveToHeadOfLRU(data); + moveToHeadOfLRU(texture); + texture->inTexturePool = true; } -void QGLTexturePool::detachTexture(QGLPixmapData *data) +void QGLTexturePool::detachTexture(QGLTexture *texture) { - removeFromLRU(data); + removeFromLRU(texture); + texture->inTexturePool = false; } bool QGLTexturePool::reclaimSpace(GLint internalformat, @@ -157,7 +147,7 @@ bool QGLTexturePool::reclaimSpace(GLint internalformat, GLsizei height, GLenum format, GLenum type, - QGLPixmapData *data) + QGLTexture *texture) { Q_UNUSED(internalformat); // For future use in picking the best texture to eject. Q_UNUSED(width); @@ -167,19 +157,22 @@ bool QGLTexturePool::reclaimSpace(GLint internalformat, bool succeeded = false; bool wasInLRU = false; - if (data) { - wasInLRU = data->inLRU; - moveToHeadOfLRU(data); + if (texture) { + wasInLRU = texture->inLRU; + moveToHeadOfLRU(texture); } - QGLPixmapData *lrudata = pixmapLRU(); - if (lrudata && lrudata != data) { - lrudata->reclaimTexture(); + QGLTexture *lrutexture = textureLRU(); + if (lrutexture && lrutexture != texture) { + if (lrutexture->boundPixmap) + lrutexture->boundPixmap->reclaimTexture(); + else + QGLTextureCache::instance()->remove(lrutexture->boundKey); succeeded = true; } - if (data && !wasInLRU) - removeFromLRU(data); + if (texture && !wasInLRU) + removeFromLRU(texture); return succeeded; } @@ -187,55 +180,58 @@ bool QGLTexturePool::reclaimSpace(GLint internalformat, void QGLTexturePool::hibernate() { Q_D(QGLTexturePool); - QGLPixmapData *pd = d->lruLast; - while (pd) { - QGLPixmapData *prevLRU = pd->prevLRU; - pd->inTexturePool = false; - pd->inLRU = false; - pd->nextLRU = 0; - pd->prevLRU = 0; - pd->hibernate(); - pd = prevLRU; + QGLTexture *texture = d->lruLast; + while (texture) { + QGLTexture *prevLRU = texture->prevLRU; + texture->inTexturePool = false; + texture->inLRU = false; + texture->nextLRU = 0; + texture->prevLRU = 0; + if (texture->boundPixmap) + texture->boundPixmap->hibernate(); + else + QGLTextureCache::instance()->remove(texture->boundKey); + texture = prevLRU; } d->lruFirst = 0; d->lruLast = 0; } -void QGLTexturePool::moveToHeadOfLRU(QGLPixmapData *data) +void QGLTexturePool::moveToHeadOfLRU(QGLTexture *texture) { Q_D(QGLTexturePool); - if (data->inLRU) { - if (!data->prevLRU) + if (texture->inLRU) { + if (!texture->prevLRU) return; // Already at the head of the list. - removeFromLRU(data); + removeFromLRU(texture); } - data->inLRU = true; - data->nextLRU = d->lruFirst; - data->prevLRU = 0; + texture->inLRU = true; + texture->nextLRU = d->lruFirst; + texture->prevLRU = 0; if (d->lruFirst) - d->lruFirst->prevLRU = data; + d->lruFirst->prevLRU = texture; else - d->lruLast = data; - d->lruFirst = data; + d->lruLast = texture; + d->lruFirst = texture; } -void QGLTexturePool::removeFromLRU(QGLPixmapData *data) +void QGLTexturePool::removeFromLRU(QGLTexture *texture) { Q_D(QGLTexturePool); - if (!data->inLRU) + if (!texture->inLRU) return; - if (data->nextLRU) - data->nextLRU->prevLRU = data->prevLRU; + if (texture->nextLRU) + texture->nextLRU->prevLRU = texture->prevLRU; else - d->lruLast = data->prevLRU; - if (data->prevLRU) - data->prevLRU->nextLRU = data->nextLRU; + d->lruLast = texture->prevLRU; + if (texture->prevLRU) + texture->prevLRU->nextLRU = texture->nextLRU; else - d->lruFirst = data->nextLRU; - data->inLRU = false; + d->lruFirst = texture->nextLRU; + texture->inLRU = false; } -QGLPixmapData *QGLTexturePool::pixmapLRU() +QGLTexture *QGLTexturePool::textureLRU() { Q_D(QGLTexturePool); return d->lruLast; diff --git a/src/opengl/qgltexturepool_p.h b/src/opengl/qgltexturepool_p.h index 27b730c..07f9700 100644 --- a/src/opengl/qgltexturepool_p.h +++ b/src/opengl/qgltexturepool_p.h @@ -58,7 +58,7 @@ QT_BEGIN_NAMESPACE -class QGLPixmapData; +class QGLTexture; class QGLTexturePoolPrivate; class QGLTexturePool @@ -70,18 +70,18 @@ public: static QGLTexturePool *instance(); // Create a new texture with the specified parameters and associate - // it with "data". The QGLPixmapData will be notified when the + // it with "texture". The QGLTexture will be notified when the // texture needs to be reclaimed by the pool. // // This function will call reclaimSpace() when texture creation fails. - GLuint createTextureForPixmap(GLenum target, + GLuint createTexture(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, - QGLPixmapData *data); + QGLTexture *texture); // Create a permanent texture with the specified parameters. // If there is insufficient space for the texture, @@ -100,40 +100,37 @@ public: GLenum type, const GLvoid *data); - // Release a texture that is no longer required. - void releaseTexture(QGLPixmapData *data, GLuint texture); - - // Notify the pool that a QGLPixmapData object is using + // Notify the pool that a QGLTexture object is using // an texture again. This allows the pool to move the texture - // within a least-recently-used list of QGLPixmapData objects. - void useTexture(QGLPixmapData *data); + // within a least-recently-used list of QGLTexture objects. + void useTexture(QGLTexture *texture); // Notify the pool that the texture associated with a - // QGLPixmapData is being detached from the pool. The caller + // QGLTexture is being detached from the pool. The caller // will become responsible for calling glDeleteTextures(). - void detachTexture(QGLPixmapData *data); + void detachTexture(QGLTexture *texture); // Reclaim space for an image allocation with the specified parameters. // Returns true if space was reclaimed, or false if there is no - // further space that can be reclaimed. The "data" parameter - // indicates the pixmap that is trying to obtain space which should + // further space that can be reclaimed. The "texture" parameter + // indicates the texture that is trying to obtain space which should // not itself be reclaimed. bool reclaimSpace(GLint internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, - QGLPixmapData *data); + QGLTexture *data); - // Hibernate the image pool because the context is about to be + // Hibernate the texture pool because the context is about to be // destroyed. All textures left in the pool should be released. void hibernate(); protected: - // Helper functions for managing the LRU list of QGLPixmapData objects. - void moveToHeadOfLRU(QGLPixmapData *data); - void removeFromLRU(QGLPixmapData *data); - QGLPixmapData *pixmapLRU(); + // Helper functions for managing the LRU list of QGLTexture objects. + void moveToHeadOfLRU(QGLTexture *texture); + void removeFromLRU(QGLTexture *texture); + QGLTexture *textureLRU(); private: QScopedPointer<QGLTexturePoolPrivate> d_ptr; diff --git a/src/opengl/qgraphicssystem_gl.cpp b/src/opengl/qgraphicssystem_gl.cpp index 8530b52..265bf22 100644 --- a/src/opengl/qgraphicssystem_gl.cpp +++ b/src/opengl/qgraphicssystem_gl.cpp @@ -55,9 +55,6 @@ #if defined(Q_OS_SYMBIAN) #include <QtGui/private/qapplication_p.h> -#endif - -#ifdef QGL_USE_TEXTURE_POOL #include "private/qgltexturepool_p.h" #endif diff --git a/src/opengl/qpixmapdata_gl_p.h b/src/opengl/qpixmapdata_gl_p.h index 909f264..bf1a303 100644 --- a/src/opengl/qpixmapdata_gl_p.h +++ b/src/opengl/qpixmapdata_gl_p.h @@ -70,12 +70,6 @@ class QGLFramebufferObject; class QGLFramebufferObjectFormat; class QGLPixmapData; -#ifdef QGL_USE_TEXTURE_POOL -void qt_gl_register_pixmap(QGLPixmapData *pd); -void qt_gl_unregister_pixmap(QGLPixmapData *pd); -void qt_gl_hibernate_pixmaps(); -#endif - #ifdef Q_OS_SYMBIAN class QNativeImageHandleProvider; #endif @@ -143,7 +137,7 @@ public: GLuint bind(bool copyBack = true) const; QGLTexture *texture() const; -#ifdef QGL_USE_TEXTURE_POOL +#ifdef Q_OS_SYMBIAN void destroyTexture(); // Detach this image from the image pool. void detachTextureFromPool(); @@ -158,9 +152,8 @@ public: // texture objects to reuse storage. void reclaimTexture(); void forceToImage(); -#endif -#ifdef Q_OS_SYMBIAN + QVolatileImage toVolatileImage() const { return m_source; } QImage::Format idealFormat(QImage &image, Qt::ImageConversionFlags flags); void* toNativeType(NativeType type); void fromNativeType(void* pixmap, NativeType type); @@ -218,23 +211,6 @@ private: mutable QGLPixmapGLPaintDevice m_glDevice; -#ifdef QGL_USE_TEXTURE_POOL - QGLPixmapData *nextLRU; - QGLPixmapData *prevLRU; - mutable bool inLRU; - mutable bool failedToAlloc; - mutable bool inTexturePool; - - QGLPixmapData *next; - QGLPixmapData *prev; - - friend class QGLTexturePool; - - friend void qt_gl_register_pixmap(QGLPixmapData *pd); - friend void qt_gl_unregister_pixmap(QGLPixmapData *pd); - friend void qt_gl_hibernate_pixmaps(); -#endif - friend class QGLPixmapGLPaintDevice; friend class QMeeGoPixmapData; friend class QMeeGoLivePixmapData; diff --git a/src/opengl/qpixmapdata_poolgl.cpp b/src/opengl/qpixmapdata_symbiangl.cpp index c69ac5d..8c3d61a 100644 --- a/src/opengl/qpixmapdata_poolgl.cpp +++ b/src/opengl/qpixmapdata_symbiangl.cpp @@ -247,43 +247,14 @@ QGLPixmapData::QGLPixmapData(PixelType type) , m_dirty(false) , m_hasFillColor(false) , m_hasAlpha(false) - , inLRU(false) - , failedToAlloc(false) - , inTexturePool(false) { setSerialNumber(++qt_gl_pixmap_serial); m_glDevice.setPixmapData(this); - - qt_gl_register_pixmap(this); } QGLPixmapData::~QGLPixmapData() { delete m_engine; - - destroyTexture(); - qt_gl_unregister_pixmap(this); -} - -void QGLPixmapData::destroyTexture() -{ - if (inTexturePool) { - QGLTexturePool *pool = QGLTexturePool::instance(); - if (m_texture.id) - pool->releaseTexture(this, m_texture.id); - } else { - if (m_texture.id) { - QGLWidget *shareWidget = qt_gl_share_widget(); - if (shareWidget) { - QGLShareContextScope ctx(shareWidget->context()); - glDeleteTextures(1, &m_texture.id); - } - } - } - m_texture.id = 0; - inTexturePool = false; - - releaseNativeImageHandle(); } QPixmapData *QGLPixmapData::createCompatiblePixmapData() const @@ -298,11 +269,13 @@ bool QGLPixmapData::isValid() const bool QGLPixmapData::isValidContext(const QGLContext *ctx) const { - if (ctx == m_ctx) - return true; - - const QGLContext *share_ctx = qt_gl_share_widget()->context(); - return ctx == share_ctx || QGLContext::areSharing(ctx, share_ctx); + // On Symbian, we usually want to treat QGLPixmapData as + // raster pixmap data because that's well known and tested + // execution path which is used on other platforms as well. + // That's why if source pixels are valid we return false + // to simulate raster pixmaps. Only QPixmaps created from + // SgImage will enable usage of QGLPixmapData. + return false; } void QGLPixmapData::resize(int width, int height) @@ -353,27 +326,25 @@ void QGLPixmapData::ensureCreated() const if (!m_source.isNull() && m_source.format() == QImage::Format_RGB16) type = GL_UNSIGNED_SHORT_5_6_5; - m_texture.options &= ~QGLContext::MemoryManagedBindOption; - if (!m_texture.id) { - m_texture.id = QGLTexturePool::instance()->createTextureForPixmap( + m_texture.id = QGLTexturePool::instance()->createTexture( target, 0, internal_format, w, h, external_format, type, - const_cast<QGLPixmapData*>(this)); + &m_texture); if (!m_texture.id) { - failedToAlloc = true; + m_texture.failedToAlloc = true; return; } glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - inTexturePool = true; - } else if (inTexturePool) { + m_texture.inTexturePool = true; + } else if (m_texture.inTexturePool) { glBindTexture(target, m_texture.id); - QGLTexturePool::instance()->useTexture(const_cast<QGLPixmapData*>(this)); + QGLTexturePool::instance()->useTexture(&m_texture); } if (!m_source.isNull() && m_texture.id) { @@ -753,15 +724,8 @@ void QGLPixmapData::copyBackFromRenderFbo(bool keepCurrentFboBound) const bool QGLPixmapData::useFramebufferObjects() const { -#ifdef Q_OS_SYMBIAN - // We don't want to use FBOs on Symbian + // We don't use FBOs on Symbian for now return false; -#else - return QGLFramebufferObject::hasOpenGLFramebufferObjects() - && QGLFramebufferObject::hasOpenGLFramebufferBlit() - && qt_gl_preferGL2Engine() - && (w * h > 32*32); // avoid overhead of FBOs for small pixmaps -#endif } QPaintEngine* QGLPixmapData::paintEngine() const @@ -845,40 +809,6 @@ QGLTexture* QGLPixmapData::texture() const return &m_texture; } -void QGLPixmapData::detachTextureFromPool() -{ - if (inTexturePool) { - QGLTexturePool::instance()->detachTexture(this); - inTexturePool = false; - } -} - -void QGLPixmapData::hibernate() -{ - // If the image was imported (e.g, from an SgImage under Symbian), then - // skip the hibernation, there is no sense in copying it back to main - // memory because the data is most likely shared between several processes. - bool skipHibernate = (m_texture.id && m_source.isNull()); -#if defined(Q_OS_SYMBIAN) - // However we have to proceed normally if the image was retrieved via - // a handle provider. - skipHibernate &= !nativeImageHandleProvider; -#endif - if (skipHibernate) - return; - - forceToImage(); - destroyTexture(); -} - -void QGLPixmapData::reclaimTexture() -{ - if (!inTexturePool) - return; - forceToImage(); - destroyTexture(); -} - Q_GUI_EXPORT int qt_defaultDpiX(); Q_GUI_EXPORT int qt_defaultDpiY(); @@ -928,6 +858,31 @@ void QGLPixmapData::forceToImage() m_dirty = true; } +void QGLPixmapData::destroyTexture() +{ + // Destroy SgImage texture +} + +void QGLPixmapData::detachTextureFromPool() +{ + QGLTexturePool::instance()->detachTexture(&m_texture); +} + +void QGLPixmapData::hibernate() +{ + destroyTexture(); +} + +void QGLPixmapData::reclaimTexture() +{ + if (!m_texture.inTexturePool) + return; + + forceToImage(); + + destroyTexture(); +} + QGLPaintDevice *QGLPixmapData::glDevice() const { return &m_glDevice; diff --git a/src/opengl/qwindowsurface_gl.cpp b/src/opengl/qwindowsurface_gl.cpp index 238d127..17b2044 100644 --- a/src/opengl/qwindowsurface_gl.cpp +++ b/src/opengl/qwindowsurface_gl.cpp @@ -184,7 +184,7 @@ QGLGraphicsSystem::QGLGraphicsSystem(bool useX11GL) class QGLGlobalShareWidget { public: - QGLGlobalShareWidget() : firstPixmap(0), widgetRefCount(0), widget(0), initializing(false) {} + QGLGlobalShareWidget() : refCount(0), widget(0), initializing(false) {} QGLWidget *shareWidget() { if (!initializing && !widget && !cleanedUp) { @@ -223,9 +223,7 @@ public: } static bool cleanedUp; - - QGLPixmapData *firstPixmap; - int widgetRefCount; + int refCount; private: QGLWidget *widget; @@ -257,43 +255,6 @@ void qt_destroy_gl_share_widget() _qt_gl_share_widget()->destroy(); } -#ifdef QGL_USE_TEXTURE_POOL -void qt_gl_register_pixmap(QGLPixmapData *pd) -{ - QGLGlobalShareWidget *shared = _qt_gl_share_widget(); - pd->next = shared->firstPixmap; - pd->prev = 0; - if (shared->firstPixmap) - shared->firstPixmap->prev = pd; - shared->firstPixmap = pd; -} - -void qt_gl_unregister_pixmap(QGLPixmapData *pd) -{ - if (pd->next) - pd->next->prev = pd->prev; - if (pd->prev) { - pd->prev->next = pd->next; - } else { - QGLGlobalShareWidget *shared = _qt_gl_share_widget(); - if (shared) - shared->firstPixmap = pd->next; - } -} - -void qt_gl_hibernate_pixmaps() -{ - QGLGlobalShareWidget *shared = _qt_gl_share_widget(); - - // Scan all QGLPixmapData objects in the system and hibernate them. - QGLPixmapData *pd = shared->firstPixmap; - while (pd != 0) { - pd->hibernate(); - pd = pd->next; - } -} -#endif - struct QGLWindowSurfacePrivate { QGLFramebufferObject *fbo; @@ -393,18 +354,10 @@ QGLWindowSurface::~QGLWindowSurface() if (QGLGlobalShareWidget::cleanedUp) return; - --(_qt_gl_share_widget()->widgetRefCount); - -#ifdef QGL_USE_TEXTURE_POOL - if (_qt_gl_share_widget()->widgetRefCount <= 0) { - // All of the widget window surfaces have been destroyed - // but we still have GL pixmaps active. Ask them to hibernate - // to free up GPU resources until a widget is shown again. - // This may eventually cause the EGLContext to be destroyed - // because nothing in the system needs a context, which will - // free up even more GPU resources. - qt_gl_hibernate_pixmaps(); + --(_qt_gl_share_widget()->refCount); +#ifdef Q_OS_SYMBIAN + if (_qt_gl_share_widget()->refCount <= 0) { // Destroy the context if necessary. if (!qt_gl_share_widget()->context()->isSharing()) qt_destroy_gl_share_widget(); @@ -458,7 +411,7 @@ void QGLWindowSurface::hijackWindow(QWidget *widget) ctx->create(qt_gl_share_widget()->context()); if (widget != qt_gl_share_widget()) - ++(_qt_gl_share_widget()->widgetRefCount); + ++(_qt_gl_share_widget()->refCount); #ifndef QT_NO_EGL static bool checkedForNOKSwapRegion = false; @@ -495,6 +448,7 @@ void QGLWindowSurface::hijackWindow(QWidget *widget) voidPtr = &widgetPrivate->extraData()->glContext; d_ptr->contexts << ctxPtr; + #ifndef Q_OS_SYMBIAN qDebug() << "hijackWindow() context created for" << widget << d_ptr->contexts.size(); #endif @@ -870,7 +824,7 @@ void QGLWindowSurface::updateGeometry() { #ifdef Q_OS_SYMBIAN // Symbian needs to recreate the context when native window size changes if (d_ptr->size != geometry().size()) { if (window() != qt_gl_share_widget()) - --(_qt_gl_share_widget()->widgetRefCount); + --(_qt_gl_share_widget()->refCount); delete wd->extraData()->glContext; wd->extraData()->glContext = 0; |