src/opengl/qgl.cpp
changeset 33 3e2da88830cd
parent 30 5dc02b23752f
child 37 758a864f9613
--- a/src/opengl/qgl.cpp	Tue Jul 06 15:10:48 2010 +0300
+++ b/src/opengl/qgl.cpp	Wed Aug 18 10:37:55 2010 +0300
@@ -91,6 +91,7 @@
 #include "qcolormap.h"
 #include "qfile.h"
 #include "qlibrary.h"
+#include <qmutex.h>
 
 
 QT_BEGIN_NAMESPACE
@@ -1255,6 +1256,8 @@
                             QGLFormat::OpenGL_Version_2_1 |
                             QGLFormat::OpenGL_Version_3_0;
             switch (versionString[2].toAscii()) {
+            case '3':
+                versionFlags |= QGLFormat::OpenGL_Version_3_3;
             case '2':
                 versionFlags |= QGLFormat::OpenGL_Version_3_2;
             case '1':
@@ -1263,9 +1266,23 @@
                 break;
             default:
                 versionFlags |= QGLFormat::OpenGL_Version_3_1 |
-                                QGLFormat::OpenGL_Version_3_2;
+                                QGLFormat::OpenGL_Version_3_2 |
+                                QGLFormat::OpenGL_Version_3_3;
                 break;
             }
+        } else if (versionString.startsWith(QLatin1String("4."))) {
+            versionFlags |= QGLFormat::OpenGL_Version_1_1 |
+                            QGLFormat::OpenGL_Version_1_2 |
+                            QGLFormat::OpenGL_Version_1_3 |
+                            QGLFormat::OpenGL_Version_1_4 |
+                            QGLFormat::OpenGL_Version_1_5 |
+                            QGLFormat::OpenGL_Version_2_0 |
+                            QGLFormat::OpenGL_Version_2_1 |
+                            QGLFormat::OpenGL_Version_3_0 |
+                            QGLFormat::OpenGL_Version_3_1 |
+                            QGLFormat::OpenGL_Version_3_2 |
+                            QGLFormat::OpenGL_Version_3_3 |
+                            QGLFormat::OpenGL_Version_4_0;
         } else {
             versionFlags |= QGLFormat::OpenGL_Version_1_1 |
                             QGLFormat::OpenGL_Version_1_2 |
@@ -1276,7 +1293,9 @@
                             QGLFormat::OpenGL_Version_2_1 |
                             QGLFormat::OpenGL_Version_3_0 |
                             QGLFormat::OpenGL_Version_3_1 |
-                            QGLFormat::OpenGL_Version_3_2;
+                            QGLFormat::OpenGL_Version_3_2 |
+                            QGLFormat::OpenGL_Version_3_3 |
+                            QGLFormat::OpenGL_Version_4_0;
         }
     }
     return versionFlags;
@@ -1315,6 +1334,10 @@
 
     \value OpenGL_Version_3_2  OpenGL version 3.2 or higher is present.
 
+    \value OpenGL_Version_3_3  OpenGL version 3.3 or higher is present.
+
+    \value OpenGL_Version_4_0  OpenGL version 4.0 or higher is present.
+
     \value OpenGL_ES_CommonLite_Version_1_0  OpenGL ES version 1.0 Common Lite or higher is present.
 
     \value OpenGL_ES_Common_Version_1_0  OpenGL ES version 1.0 Common or higher is present.
@@ -1502,6 +1525,32 @@
         && a.d->profile == b.d->profile);
 }
 
+#ifndef QT_NO_DEBUG_STREAM
+QDebug operator<<(QDebug dbg, const QGLFormat &f)
+{
+    const QGLFormatPrivate * const d = f.d;
+
+    dbg.nospace() << "QGLFormat("
+                  << "options " << d->opts
+                  << ", plane " << d->pln
+                  << ", depthBufferSize " << d->depthSize
+                  << ", accumBufferSize " << d->accumSize
+                  << ", stencilBufferSize " << d->stencilSize
+                  << ", redBufferSize " << d->redSize
+                  << ", greenBufferSize " << d->greenSize
+                  << ", blueBufferSize " << d->blueSize
+                  << ", alphaBufferSize " << d->alphaSize
+                  << ", samples " << d->numSamples
+                  << ", swapInterval " << d->swapInterval
+                  << ", majorVersion " << d->majorVersion
+                  << ", minorVersion " << d->minorVersion
+                  << ", profile " << d->profile
+                  << ')';
+
+    return dbg.space();
+}
+#endif
+
 
 /*!
     Returns false if all the options of the two QGLFormat objects
@@ -1515,10 +1564,33 @@
     return !(a == b);
 }
 
+struct QGLContextGroupList {
+    void append(QGLContextGroup *group) {
+        QMutexLocker locker(&m_mutex);
+        m_list.append(group);
+    }
+
+    void remove(QGLContextGroup *group) {
+        QMutexLocker locker(&m_mutex);
+        m_list.removeOne(group);
+    }
+
+    QList<QGLContextGroup *> m_list;
+    QMutex m_mutex;
+};
+
+Q_GLOBAL_STATIC(QGLContextGroupList, qt_context_groups)
+
 /*****************************************************************************
   QGLContext implementation
  *****************************************************************************/
 
+QGLContextGroup::QGLContextGroup(const QGLContext *context)
+    : m_context(context), m_guards(0), m_refs(1)
+{
+    qt_context_groups()->append(this);
+}
+
 QGLContextGroup::~QGLContextGroup()
 {
     // Clear any remaining QGLSharedResourceGuard objects on the group.
@@ -1528,6 +1600,7 @@
         guard->m_id = 0;
         guard = guard->m_next;
     }
+    qt_context_groups()->remove(this);
 }
 
 void QGLContextGroup::addGuard(QGLSharedResourceGuard *guard)
@@ -1736,7 +1809,7 @@
     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();
+        const QList<QGLTextureCacheKey> keys = m_cache.keys();
         int i = 0;
         while (i < m_cache.count()
                && (m_cache.totalCost() + cost > m_cache.maxCost())) {
@@ -1746,13 +1819,26 @@
             ++i;
         }
     }
-    m_cache.insert(key, texture, cost);
+    const QGLTextureCacheKey cacheKey = {key, QGLContextPrivate::contextGroup(ctx)};
+    m_cache.insert(cacheKey, texture, cost);
+}
+
+void QGLTextureCache::remove(qint64 key)
+{
+    QWriteLocker locker(&m_lock);
+    QMutexLocker groupLocker(&qt_context_groups()->m_mutex);
+    QList<QGLContextGroup *>::const_iterator it = qt_context_groups()->m_list.constBegin();
+    while (it != qt_context_groups()->m_list.constEnd()) {
+        const QGLTextureCacheKey cacheKey = {key, *it};
+        m_cache.remove(cacheKey);
+        ++it;
+    }
 }
 
 bool QGLTextureCache::remove(QGLContext* ctx, GLuint textureId)
 {
     QWriteLocker locker(&m_lock);
-    QList<qint64> keys = m_cache.keys();
+    QList<QGLTextureCacheKey> keys = m_cache.keys();
     for (int i = 0; i < keys.size(); ++i) {
         QGLTexture *tex = m_cache.object(keys.at(i));
         if (tex->id == textureId && tex->context == ctx) {
@@ -1767,9 +1853,9 @@
 void QGLTextureCache::removeContextTextures(QGLContext* ctx)
 {
     QWriteLocker locker(&m_lock);
-    QList<qint64> keys = m_cache.keys();
+    QList<QGLTextureCacheKey> keys = m_cache.keys();
     for (int i = 0; i < keys.size(); ++i) {
-        const qint64 &key = keys.at(i);
+        const QGLTextureCacheKey &key = keys.at(i);
         if (m_cache.object(key)->context == ctx)
             m_cache.remove(key);
     }
@@ -1782,7 +1868,6 @@
 void QGLTextureCache::cleanupTexturesForCacheKey(qint64 cacheKey)
 {
     qt_gl_texture_cache()->remove(cacheKey);
-    Q_ASSERT(qt_gl_texture_cache()->getTexture(cacheKey) == 0);
 }
 
 
@@ -2011,6 +2096,16 @@
 }
 #undef ctx
 
+#ifdef QT_NO_EGL
+void QGLContextPrivate::swapRegion(const QRegion *)
+{
+    static bool firstWarning = true;
+    if (firstWarning) {
+        qWarning() << "::swapRegion called but not supported!";
+        firstWarning = false;
+    }
+}
+#endif
 
 /*!
     \overload
@@ -2165,6 +2260,13 @@
     }
 }
 
+#if defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_WS_QWS)
+QGLExtensionFuncs& QGLContextPrivate::extensionFuncs(const QGLContext *)
+{
+    return qt_extensionFuncs;
+}
+#endif
+
 QImage QGLContextPrivate::convertToGLFormat(const QImage &image, bool force_premul,
                                             GLenum texture_format)
 {
@@ -2276,9 +2378,6 @@
         && target == GL_TEXTURE_2D
         && (options & QGLContext::MipmapBindOption))
     {
-#ifdef QGL_BIND_TEXTURE_DEBUG
-        printf(" - generating mipmaps (%d ms)\n", time.elapsed());
-#endif
 #if !defined(QT_OPENGL_ES_2)
         glHint(GL_GENERATE_MIPMAP_HINT_SGIS, GL_NICEST);
 #ifndef QT_OPENGL_ES
@@ -2292,6 +2391,9 @@
 #endif
         glTexParameterf(target, GL_TEXTURE_MIN_FILTER, options & QGLContext::LinearFilteringBindOption
                         ? GL_LINEAR_MIPMAP_LINEAR : GL_NEAREST_MIPMAP_NEAREST);
+#ifdef QGL_BIND_TEXTURE_DEBUG
+        printf(" - generating mipmaps (%d ms)\n", time.elapsed());
+#endif
     } else {
         glTexParameterf(target, GL_TEXTURE_MIN_FILTER, filtering);
     }
@@ -2316,7 +2418,7 @@
         if (premul) {
             img = img.convertToFormat(target_format = QImage::Format_ARGB32_Premultiplied);
 #ifdef QGL_BIND_TEXTURE_DEBUG
-            printf(" - converting ARGB32 -> ARGB32_Premultiplied (%d ms) \n", time.elapsed());
+            printf(" - converted ARGB32 -> ARGB32_Premultiplied (%d ms) \n", time.elapsed());
 #endif
         }
         break;
@@ -2324,7 +2426,7 @@
         if (!premul) {
             img = img.convertToFormat(target_format = QImage::Format_ARGB32);
 #ifdef QGL_BIND_TEXTURE_DEBUG
-            printf(" - converting ARGB32_Premultiplied -> ARGB32 (%d ms)\n", time.elapsed());
+            printf(" - converted ARGB32_Premultiplied -> ARGB32 (%d ms)\n", time.elapsed());
 #endif
         }
         break;
@@ -2341,20 +2443,17 @@
                                       ? QImage::Format_ARGB32_Premultiplied
                                       : QImage::Format_ARGB32);
 #ifdef QGL_BIND_TEXTURE_DEBUG
-            printf(" - converting to 32-bit alpha format (%d ms)\n", time.elapsed());
+            printf(" - converted to 32-bit alpha format (%d ms)\n", time.elapsed());
 #endif
         } else {
             img = img.convertToFormat(QImage::Format_RGB32);
 #ifdef QGL_BIND_TEXTURE_DEBUG
-            printf(" - converting to 32-bit (%d ms)\n", time.elapsed());
+            printf(" - converted to 32-bit (%d ms)\n", time.elapsed());
 #endif
         }
     }
 
     if (options & QGLContext::InvertedYBindOption) {
-#ifdef QGL_BIND_TEXTURE_DEBUG
-            printf(" - flipping bits over y (%d ms)\n", time.elapsed());
-#endif
         if (img.isDetached()) {
             int ipl = img.bytesPerLine() / 4;
             int h = img.height();
@@ -2371,17 +2470,20 @@
             // data twice.  This version should only do it once.
             img = img.mirrored();
         }
+#ifdef QGL_BIND_TEXTURE_DEBUG
+            printf(" - flipped bits over y (%d ms)\n", time.elapsed());
+#endif
     }
 
     if (externalFormat == GL_RGBA) {
-#ifdef QGL_BIND_TEXTURE_DEBUG
-            printf(" - doing byte swapping (%d ms)\n", time.elapsed());
-#endif
         // The only case where we end up with a depth different from
         // 32 in the switch above is for the RGB16 case, where we set
         // the format to GL_RGB
         Q_ASSERT(img.depth() == 32);
         qgl_byteSwapImage(img, pixel_type);
+#ifdef QGL_BIND_TEXTURE_DEBUG
+            printf(" - did byte swapping (%d ms)\n", time.elapsed());
+#endif
     }
 #ifdef QT_OPENGL_ES
     // OpenGL/ES requires that the internal and external formats be
@@ -2410,7 +2512,7 @@
 #ifdef QGL_BIND_TEXTURE_DEBUG
     static int totalUploadTime = 0;
     totalUploadTime += time.elapsed();
-    printf(" - upload done in (%d ms) time=%d\n", time.elapsed(), totalUploadTime);
+    printf(" - upload done in %d ms, (accumulated: %d ms)\n", time.elapsed(), totalUploadTime);
 #endif
 
 
@@ -2425,7 +2527,7 @@
 QGLTexture *QGLContextPrivate::textureCacheLookup(const qint64 key, GLenum target)
 {
     Q_Q(QGLContext);
-    QGLTexture *texture = QGLTextureCache::instance()->getTexture(key);
+    QGLTexture *texture = QGLTextureCache::instance()->getTexture(q, key);
     if (texture && texture->target == target
         && (texture->context == q || QGLContext::areSharing(q, texture->context)))
     {
@@ -3619,8 +3721,10 @@
     bool doRelease = (glcx && glcx->windowCreated());
 #endif
     delete d->glcx;
-#if defined(Q_WGL)
+    d->glcx = 0;
+#if defined(Q_WS_WIN)
     delete d->olcx;
+    d->olcx = 0;
 #endif
 #if defined(GLX_MESA_release_buffers) && defined(QGL_USE_MESA_EXT)
     if (doRelease)
@@ -4937,8 +5041,9 @@
 /*!
     \since 4.4
 
-    Calls the corresponding QGLContext::drawTexture() on
-    this widget's context.
+    Calls the corresponding QGLContext::drawTexture() with
+    \a target, \a textureId, and \a textureTarget for this
+    widget's context.
 */
 void QGLWidget::drawTexture(const QRectF &target, GLuint textureId, GLenum textureTarget)
 {
@@ -4958,8 +5063,9 @@
 /*!
     \since 4.4
 
-    Calls the corresponding QGLContext::drawTexture() on
-    this widget's context.
+    Calls the corresponding QGLContext::drawTexture() with
+    \a point, \a textureId, and \a textureTarget for this
+    widget's context.
 */
 void QGLWidget::drawTexture(const QPointF &point, GLuint textureId, GLenum textureTarget)
 {
@@ -5104,6 +5210,8 @@
         glExtensions |= NVFloatBuffer;
     if (extensions.match("GL_ARB_pixel_buffer_object"))
         glExtensions |= PixelBufferObject;
+    if (extensions.match("GL_IMG_texture_format_BGRA8888"))
+        glExtensions |= BGRATextureFormat;
 #if defined(QT_OPENGL_ES_2)
     glExtensions |= FramebufferObject;
     glExtensions |= GenerateMipmap;