Index: trunk/src/opengl/qgl_p.h
===================================================================
--- trunk/src/opengl/qgl_p.h	(revision 561)
+++ trunk/src/opengl/qgl_p.h	(revision 651)
@@ -1,5 +1,5 @@
 /****************************************************************************
 **
-** 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)
@@ -223,7 +223,6 @@
 
 // QGLContextPrivate has the responsibility of creating context groups.
-// QGLContextPrivate and QGLShareRegister will both maintain the reference counter and destroy
+// QGLContextPrivate maintains the reference counter and destroys
 // context groups when needed.
-// QGLShareRegister has the responsibility of keeping the context pointer up to date.
 class QGLContextGroup
 {
@@ -234,7 +233,11 @@
     const QGLContext *context() const {return m_context;}
     bool isSharing() const { return m_shares.size() >= 2; }
+    QList<const QGLContext *> shares() const { return m_shares; }
 
     void addGuard(QGLSharedResourceGuard *guard);
     void removeGuard(QGLSharedResourceGuard *guard);
+
+    static void addShare(const QGLContext *context, const QGLContext *share);
+    static void removeShare(const QGLContext *context);
 private:
     QGLContextGroup(const QGLContext *context) : m_context(context), m_guards(0), m_refs(1) { }
@@ -250,5 +253,4 @@
     void cleanupResources(const QGLContext *ctx);
 
-    friend class QGLShareRegister;
     friend class QGLContext;
     friend class QGLContextPrivate;
@@ -256,108 +258,7 @@
 };
 
-class QGLTexture;
-
-class QGLContextPrivate
-{
-    Q_DECLARE_PUBLIC(QGLContext)
-public:
-    explicit QGLContextPrivate(QGLContext *context) : internal_context(false), q_ptr(context) {group = new QGLContextGroup(context);}
-    ~QGLContextPrivate();
-    QGLTexture *bindTexture(const QImage &image, GLenum target, GLint format,
-                            QGLContext::BindOptions options);
-    QGLTexture *bindTexture(const QImage &image, GLenum target, GLint format, const qint64 key,
-                            QGLContext::BindOptions options);
-    QGLTexture *bindTexture(const QPixmap &pixmap, GLenum target, GLint format,
-                            QGLContext::BindOptions options);
-    QGLTexture *textureCacheLookup(const qint64 key, GLenum target);
-    void init(QPaintDevice *dev, const QGLFormat &format);
-    QImage convertToGLFormat(const QImage &image, bool force_premul, GLenum texture_format);
-    int maxTextureSize();
-
-    void cleanup();
-
-#if defined(Q_WS_WIN)
-    HGLRC rc;
-    HDC dc;
-    WId        win;
-    int pixelFormatId;
-    QGLCmap* cmap;
-    HBITMAP hbitmap;
-    HDC hbitmap_hdc;
-#endif
-#if defined(QT_OPENGL_ES)
-    QEglContext *eglContext;
-    EGLSurface eglSurface;
-    void destroyEglSurfaceForDevice();
-#elif defined(Q_WS_X11) || defined(Q_WS_MAC)
-    void* cx;
-#endif
-#if defined(Q_WS_X11) || defined(Q_WS_MAC)
-    void* vi;
-#endif
-#if defined(Q_WS_X11)
-    void* pbuf;
-    quint32 gpm;
-    int screen;
-    QHash<QPixmapData*, QPixmap> boundPixmaps;
-    QGLTexture *bindTextureFromNativePixmap(QPixmapData*, const qint64 key,
-                                            QGLContext::BindOptions options);
-    static void destroyGlSurfaceForPixmap(QPixmapData*);
-    static void unbindPixmapFromTexture(QPixmapData*);
-#endif
-#if defined(Q_WS_MAC)
-    bool update;
-    void *tryFormat(const QGLFormat &format);
-    void clearDrawable();
-#endif
-    QGLFormat glFormat;
-    QGLFormat reqFormat;
-    GLuint fbo;
-
-    uint valid : 1;
-    uint sharing : 1;
-    uint initDone : 1;
-    uint crWin : 1;
-    uint internal_context : 1;
-    uint version_flags_cached : 1;
-    QPaintDevice *paintDevice;
-    QColor transpColor;
-    QGLContext *q_ptr;
-    QGLFormat::OpenGLVersionFlags version_flags;
-
-    QGLContextGroup *group;
-    GLint max_texture_size;
-
-    GLuint current_fbo;
-    GLuint default_fbo;
-    QPaintEngine *active_engine;
-
-    static inline QGLContextGroup *contextGroup(const QGLContext *ctx) { return ctx->d_ptr->group; }
-
-#ifdef Q_WS_WIN
-    static inline QGLExtensionFuncs& extensionFuncs(const QGLContext *ctx) { return ctx->d_ptr->group->extensionFuncs(); }
-#endif
-
-#if defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_WS_QWS)
-    static QGLExtensionFuncs qt_extensionFuncs;
-    static inline QGLExtensionFuncs& extensionFuncs(const QGLContext *) { return qt_extensionFuncs; }
-#endif
-
-    static void setCurrentContext(QGLContext *context);
-};
-
-// ### make QGLContext a QObject in 5.0 and remove the proxy stuff
-class Q_OPENGL_EXPORT QGLSignalProxy : public QObject
-{
-    Q_OBJECT
-public:
-    QGLSignalProxy() : QObject() {}
-    void emitAboutToDestroyContext(const QGLContext *context) {
-        emit aboutToDestroyContext(context);
-    }
-    static QGLSignalProxy *instance();
-Q_SIGNALS:
-    void aboutToDestroyContext(const QGLContext *context);
-};
+// Get the context that resources for "ctx" will transfer to once
+// "ctx" is destroyed.  Returns null if nothing is sharing with ctx.
+Q_OPENGL_EXPORT const QGLContext *qt_gl_transfer_context(const QGLContext *);
 
 // GL extension definitions
@@ -387,25 +288,149 @@
     Q_DECLARE_FLAGS(Extensions, Extension)
 
-    static Extensions glExtensions;
-    static bool nvidiaFboNeedsFinish;
-    static void init(); // sys dependent
-    static void init_extensions(); // general: called by init()
+    static Extensions glExtensions();
+
+private:
+    static Extensions currentContextExtensions();
+};
+
+/*
+    QGLTemporaryContext - the main objective of this class is to have a way of
+    creating a GL context and making it current, without going via QGLWidget
+    and friends. At certain points during GL initialization we need a current
+    context in order decide what GL features are available, and to resolve GL
+    extensions. Having a light-weight way of creating such a context saves
+    initial application startup time, and it doesn't wind up creating recursive
+    conflicts.
+    The class currently uses a private d pointer to hide the platform specific
+    types. This could possibly been done inline with #ifdef'ery, but it causes
+    major headaches on e.g. X11 due to namespace pollution.
+*/
+class QGLTemporaryContextPrivate;
+class QGLTemporaryContext {
+public:
+    QGLTemporaryContext(bool directRendering = true, QWidget *parent = 0);
+    ~QGLTemporaryContext();
+
+private:
+    QScopedPointer<QGLTemporaryContextPrivate> d;
+};
+
+class QGLTexture;
+
+// This probably needs to grow to GL_MAX_VERTEX_ATTRIBS, but 3 is ok for now as that's
+// all the GL2 engine uses:
+#define QT_GL_VERTEX_ARRAY_TRACKED_COUNT 3
+
+class QGLContextPrivate
+{
+    Q_DECLARE_PUBLIC(QGLContext)
+public:
+    explicit QGLContextPrivate(QGLContext *context) : internal_context(false), q_ptr(context) {group = new QGLContextGroup(context);}
+    ~QGLContextPrivate();
+    QGLTexture *bindTexture(const QImage &image, GLenum target, GLint format,
+                            QGLContext::BindOptions options);
+    QGLTexture *bindTexture(const QImage &image, GLenum target, GLint format, const qint64 key,
+                            QGLContext::BindOptions options);
+    QGLTexture *bindTexture(const QPixmap &pixmap, GLenum target, GLint format,
+                            QGLContext::BindOptions options);
+    QGLTexture *textureCacheLookup(const qint64 key, GLenum target);
+    void init(QPaintDevice *dev, const QGLFormat &format);
+    QImage convertToGLFormat(const QImage &image, bool force_premul, GLenum texture_format);
+    int maxTextureSize();
+
+    void cleanup();
+
+    void setVertexAttribArrayEnabled(int arrayIndex, bool enabled = true);
+    void syncGlState(); // Makes sure the GL context's state is what we think it is
+
+#if defined(Q_WS_WIN)
+    HGLRC rc;
+    HDC dc;
+    WId        win;
+    int pixelFormatId;
+    QGLCmap* cmap;
+    HBITMAP hbitmap;
+    HDC hbitmap_hdc;
+#endif
+#if defined(QT_OPENGL_ES)
+    QEglContext *eglContext;
+    EGLSurface eglSurface;
+    void destroyEglSurfaceForDevice();
+#elif defined(Q_WS_X11) || defined(Q_WS_MAC)
+    void* cx;
+#endif
+#if defined(Q_WS_X11) || defined(Q_WS_MAC)
+    void* vi;
+#endif
+#if defined(Q_WS_X11)
+    void* pbuf;
+    quint32 gpm;
+    int screen;
+    QHash<QPixmapData*, QPixmap> boundPixmaps;
+    QGLTexture *bindTextureFromNativePixmap(QPixmapData*, const qint64 key,
+                                            QGLContext::BindOptions options);
+    static void destroyGlSurfaceForPixmap(QPixmapData*);
+    static void unbindPixmapFromTexture(QPixmapData*);
+#endif
+#if defined(Q_WS_MAC)
+    bool update;
+    void *tryFormat(const QGLFormat &format);
+    void clearDrawable();
+#endif
+    QGLFormat glFormat;
+    QGLFormat reqFormat;
+    GLuint fbo;
+
+    uint valid : 1;
+    uint sharing : 1;
+    uint initDone : 1;
+    uint crWin : 1;
+    uint internal_context : 1;
+    uint version_flags_cached : 1;
+    uint extension_flags_cached : 1;
+    QPaintDevice *paintDevice;
+    QColor transpColor;
+    QGLContext *q_ptr;
+    QGLFormat::OpenGLVersionFlags version_flags;
+    QGLExtensions::Extensions extension_flags;
+
+    QGLContextGroup *group;
+    GLint max_texture_size;
+
+    GLuint current_fbo;
+    GLuint default_fbo;
+    QPaintEngine *active_engine;
+
+    bool vertexAttributeArraysEnabledState[QT_GL_VERTEX_ARRAY_TRACKED_COUNT];
+
+    static inline QGLContextGroup *contextGroup(const QGLContext *ctx) { return ctx->d_ptr->group; }
+
+#ifdef Q_WS_WIN
+    static inline QGLExtensionFuncs& extensionFuncs(const QGLContext *ctx) { return ctx->d_ptr->group->extensionFuncs(); }
+#endif
+
+#if defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_WS_QWS)
+    static QGLExtensionFuncs qt_extensionFuncs;
+    static inline QGLExtensionFuncs& extensionFuncs(const QGLContext *) { return qt_extensionFuncs; }
+#endif
+
+    static void setCurrentContext(QGLContext *context);
+};
+
+// ### make QGLContext a QObject in 5.0 and remove the proxy stuff
+class Q_OPENGL_EXPORT QGLSignalProxy : public QObject
+{
+    Q_OBJECT
+public:
+    QGLSignalProxy() : QObject() {}
+    void emitAboutToDestroyContext(const QGLContext *context) {
+        emit aboutToDestroyContext(context);
+    }
+    static QGLSignalProxy *instance();
+Q_SIGNALS:
+    void aboutToDestroyContext(const QGLContext *context);
 };
 
 Q_DECLARE_OPERATORS_FOR_FLAGS(QGLExtensions::Extensions)
-
-
-class Q_OPENGL_EXPORT QGLShareRegister
-{
-public:
-    QGLShareRegister() {}
-    ~QGLShareRegister() {}
-
-    void addShare(const QGLContext *context, const QGLContext *share);
-    QList<const QGLContext *> shares(const QGLContext *context);
-    void removeShare(const QGLContext *context);
-};
-
-extern Q_OPENGL_EXPORT QGLShareRegister* qgl_share_reg();
 
 // Temporarily make a context current if not already current or
@@ -498,5 +523,5 @@
 };
 
-class QGLTextureCache {
+class Q_AUTOTEST_EXPORT QGLTextureCache {
 public:
     QGLTextureCache();
@@ -515,9 +540,6 @@
     static void deleteIfEmpty();
     static void imageCleanupHook(qint64 cacheKey);
-    static void cleanupTextures(QPixmap* pixmap);
-#ifdef Q_WS_X11
-    // X11 needs to catch pixmap data destruction to delete EGL/GLX pixmap surfaces
-    static void cleanupPixmapSurfaces(QPixmap* pixmap);
-#endif
+    static void cleanupTextures(QPixmapData* pixmap);
+    static void cleanupBeforePixmapDestruction(QPixmapData* pixmap);
 
 private:
@@ -532,5 +554,5 @@
 inline GLenum qt_gl_preferredTextureFormat()
 {
-    return (QGLExtensions::glExtensions & QGLExtensions::BGRATextureFormat) && QSysInfo::ByteOrder == QSysInfo::LittleEndian
+    return (QGLExtensions::glExtensions() & QGLExtensions::BGRATextureFormat) && QSysInfo::ByteOrder == QSysInfo::LittleEndian
         ? GL_BGRA : GL_RGBA;
 }
@@ -541,5 +563,5 @@
     return GL_TEXTURE_2D;
 #else
-    return (QGLExtensions::glExtensions & QGLExtensions::TextureRectangle)
+    return (QGLExtensions::glExtensions() & QGLExtensions::TextureRectangle)
            && !qt_gl_preferGL2Engine()
            ? GL_TEXTURE_RECTANGLE_NV
@@ -613,5 +635,5 @@
 
 
-// This class can be used to match GL extensions with doing any mallocs. The
+// This class can be used to match GL extensions without doing any mallocs. The
 // class assumes that the GL extension string ends with a space character,
 // which it should do on all conformant platforms. Create the object and pass
