diff options
author | Thomas Zander <t.zander@nokia.com> | 2010-03-02 12:17:49 (GMT) |
---|---|---|
committer | Thomas Zander <t.zander@nokia.com> | 2010-03-02 12:17:49 (GMT) |
commit | d0c6958922627154bd907569e1ce5b830cb353f6 (patch) | |
tree | cbd6a74c2c008205ce596ab57fdd483764f20554 /src/opengl/qgl.cpp | |
parent | 984c227bb23cff57fbad6710fdac5c5dfc056409 (diff) | |
parent | 04bda2f714ab2b8352d00a36cec906cdc0ca53ea (diff) | |
download | Qt-d0c6958922627154bd907569e1ce5b830cb353f6.zip Qt-d0c6958922627154bd907569e1ce5b830cb353f6.tar.gz Qt-d0c6958922627154bd907569e1ce5b830cb353f6.tar.bz2 |
Merge branch 'master' into gcce
Diffstat (limited to 'src/opengl/qgl.cpp')
-rw-r--r-- | src/opengl/qgl.cpp | 62 |
1 files changed, 35 insertions, 27 deletions
diff --git a/src/opengl/qgl.cpp b/src/opengl/qgl.cpp index cfcbbf8..73cd6a8 100644 --- a/src/opengl/qgl.cpp +++ b/src/opengl/qgl.cpp @@ -1692,22 +1692,23 @@ QGLTextureCache::QGLTextureCache() Q_ASSERT(qt_gl_texture_cache == 0); qt_gl_texture_cache = this; - QImagePixmapCleanupHooks::instance()->addPixmapDataModificationHook(cleanupTextures); + QImagePixmapCleanupHooks::instance()->addPixmapDataModificationHook(cleanupTexturesForPixampData); QImagePixmapCleanupHooks::instance()->addPixmapDataDestructionHook(cleanupBeforePixmapDestruction); - QImagePixmapCleanupHooks::instance()->addImageHook(imageCleanupHook); + QImagePixmapCleanupHooks::instance()->addImageHook(cleanupTexturesForCacheKey); } QGLTextureCache::~QGLTextureCache() { qt_gl_texture_cache = 0; - QImagePixmapCleanupHooks::instance()->removePixmapDataModificationHook(cleanupTextures); + QImagePixmapCleanupHooks::instance()->removePixmapDataModificationHook(cleanupTexturesForPixampData); QImagePixmapCleanupHooks::instance()->removePixmapDataDestructionHook(cleanupBeforePixmapDestruction); - QImagePixmapCleanupHooks::instance()->removeImageHook(imageCleanupHook); + QImagePixmapCleanupHooks::instance()->removeImageHook(cleanupTexturesForCacheKey); } 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<qint64> keys = m_cache.keys(); @@ -1725,6 +1726,7 @@ void QGLTextureCache::insert(QGLContext* ctx, qint64 key, QGLTexture* texture, i bool QGLTextureCache::remove(QGLContext* ctx, GLuint textureId) { + QWriteLocker locker(&m_lock); QList<qint64> keys = m_cache.keys(); for (int i = 0; i < keys.size(); ++i) { QGLTexture *tex = m_cache.object(keys.at(i)); @@ -1739,6 +1741,7 @@ bool QGLTextureCache::remove(QGLContext* ctx, GLuint textureId) void QGLTextureCache::removeContextTextures(QGLContext* ctx) { + QWriteLocker locker(&m_lock); QList<qint64> keys = m_cache.keys(); for (int i = 0; i < keys.size(); ++i) { const qint64 &key = keys.at(i); @@ -1759,32 +1762,22 @@ QGLTextureCache* QGLTextureCache::instance() a hook that removes textures from the cache when a pixmap/image is deref'ed */ -void QGLTextureCache::imageCleanupHook(qint64 cacheKey) +void QGLTextureCache::cleanupTexturesForCacheKey(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); + instance()->remove(cacheKey); + Q_ASSERT(instance()->getTexture(cacheKey) == 0); } -void QGLTextureCache::cleanupTextures(QPixmapData* pmd) +void QGLTextureCache::cleanupTexturesForPixampData(QPixmapData* pmd) { - // ### remove when the GL texture cache becomes thread-safe - if (qApp->thread() == QThread::currentThread()) { - const qint64 cacheKey = pmd->cacheKey(); - QGLTexture *texture = instance()->getTexture(cacheKey); - if (texture && texture->options & QGLContext::MemoryManagedBindOption) - instance()->remove(cacheKey); - } + cleanupTexturesForCacheKey(pmd->cacheKey()); } void QGLTextureCache::cleanupBeforePixmapDestruction(QPixmapData* pmd) { // Remove any bound textures first: - cleanupTextures(pmd); + cleanupTexturesForPixampData(pmd); #if defined(Q_WS_X11) if (pmd->classId() == QPixmapData::X11Class) { @@ -2185,8 +2178,9 @@ QGLTexture *QGLContextPrivate::bindTexture(const QImage &image, GLenum target, G // 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; } @@ -2240,6 +2234,7 @@ QGLTexture* QGLContextPrivate::bindTexture(const QImage &image, GLenum target, G int tx_h = qt_next_power_of_two(image.height()); QImage img = image; + 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()))) @@ -2393,7 +2388,7 @@ QGLTexture* QGLContextPrivate::bindTexture(const QImage &image, GLenum target, G #ifndef QT_NO_DEBUG GLenum error = glGetError(); if (error != GL_NO_ERROR) { - qWarning(" - texture upload failed, error code 0x%x\n", error); + qWarning(" - texture upload failed, error code 0x%x, enum: %d (%x)\n", error, target, target); } #endif @@ -2408,6 +2403,7 @@ QGLTexture* QGLContextPrivate::bindTexture(const QImage &image, GLenum target, G 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; } @@ -2524,7 +2520,7 @@ GLuint QGLContext::bindTexture(const QImage &image, GLenum target, GLint format) 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; } @@ -2664,11 +2660,13 @@ void QGLContext::deleteTexture(GLuint id) 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 @@ -3292,6 +3290,7 @@ void QGLContextPrivate::setCurrentContext(QGLContext *context) */ + /***************************************************************************** QGLWidget implementation *****************************************************************************/ @@ -3412,6 +3411,15 @@ void QGLContextPrivate::setCurrentContext(QGLContext *context) One approach to doing this is shown in the \l{Overpainting Example}{Overpainting} example. + \section1 Threading + + It is possible to render into a QGLWidget from another thread, but it + requires that all access to the GL context is safe guarded. The Qt GUI + thread will try to use the context in resizeEvent and paintEvent, so in + order for threaded rendering using a GL widget to work, these functions + need to be intercepted in the GUI thread and handled accordingly in the + application. + \e{OpenGL is a trademark of Silicon Graphics, Inc. in the United States and other countries.} @@ -5551,7 +5559,7 @@ QSize QGLTexture::bindCompressedTexturePVR(const char *buf, int len) 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; |