src/opengl/qgl_p.h
branchRCL_3
changeset 4 3b1da2848fc7
parent 3 41300fa6a67c
child 8 3f74d0d4af4c
equal deleted inserted replaced
3:41300fa6a67c 4:3b1da2848fc7
     1 /****************************************************************************
     1 /****************************************************************************
     2 **
     2 **
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
     3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     4 ** All rights reserved.
     4 ** All rights reserved.
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
     6 **
     6 **
     7 ** This file is part of the QtOpenGL module of the Qt Toolkit.
     7 ** This file is part of the QtOpenGL module of the Qt Toolkit.
     8 **
     8 **
   220 class QGLSharedResourceGuard;
   220 class QGLSharedResourceGuard;
   221 
   221 
   222 typedef QHash<QString, GLuint> QGLDDSCache;
   222 typedef QHash<QString, GLuint> QGLDDSCache;
   223 
   223 
   224 // QGLContextPrivate has the responsibility of creating context groups.
   224 // QGLContextPrivate has the responsibility of creating context groups.
   225 // QGLContextPrivate and QGLShareRegister will both maintain the reference counter and destroy
   225 // QGLContextPrivate maintains the reference counter and destroys
   226 // context groups when needed.
   226 // context groups when needed.
   227 // QGLShareRegister has the responsibility of keeping the context pointer up to date.
       
   228 class QGLContextGroup
   227 class QGLContextGroup
   229 {
   228 {
   230 public:
   229 public:
   231     ~QGLContextGroup();
   230     ~QGLContextGroup();
   232 
   231 
   233     QGLExtensionFuncs &extensionFuncs() {return m_extensionFuncs;}
   232     QGLExtensionFuncs &extensionFuncs() {return m_extensionFuncs;}
   234     const QGLContext *context() const {return m_context;}
   233     const QGLContext *context() const {return m_context;}
   235     bool isSharing() const { return m_shares.size() >= 2; }
   234     bool isSharing() const { return m_shares.size() >= 2; }
       
   235     QList<const QGLContext *> shares() const { return m_shares; }
   236 
   236 
   237     void addGuard(QGLSharedResourceGuard *guard);
   237     void addGuard(QGLSharedResourceGuard *guard);
   238     void removeGuard(QGLSharedResourceGuard *guard);
   238     void removeGuard(QGLSharedResourceGuard *guard);
       
   239 
       
   240     static void addShare(const QGLContext *context, const QGLContext *share);
       
   241     static void removeShare(const QGLContext *context);
   239 private:
   242 private:
   240     QGLContextGroup(const QGLContext *context) : m_context(context), m_guards(0), m_refs(1) { }
   243     QGLContextGroup(const QGLContext *context) : m_context(context), m_guards(0), m_refs(1) { }
   241 
   244 
   242     QGLExtensionFuncs m_extensionFuncs;
   245     QGLExtensionFuncs m_extensionFuncs;
   243     const QGLContext *m_context; // context group's representative
   246     const QGLContext *m_context; // context group's representative
   247     QAtomicInt m_refs;
   250     QAtomicInt m_refs;
   248     QGLDDSCache m_dds_cache;
   251     QGLDDSCache m_dds_cache;
   249 
   252 
   250     void cleanupResources(const QGLContext *ctx);
   253     void cleanupResources(const QGLContext *ctx);
   251 
   254 
   252     friend class QGLShareRegister;
       
   253     friend class QGLContext;
   255     friend class QGLContext;
   254     friend class QGLContextPrivate;
   256     friend class QGLContextPrivate;
   255     friend class QGLContextResource;
   257     friend class QGLContextResource;
   256 };
   258 };
   257 
   259 
   258 class QGLTexture;
   260 // Get the context that resources for "ctx" will transfer to once
   259 
   261 // "ctx" is destroyed.  Returns null if nothing is sharing with ctx.
   260 class QGLContextPrivate
   262 Q_OPENGL_EXPORT const QGLContext *qt_gl_transfer_context(const QGLContext *);
   261 {
       
   262     Q_DECLARE_PUBLIC(QGLContext)
       
   263 public:
       
   264     explicit QGLContextPrivate(QGLContext *context) : internal_context(false), q_ptr(context) {group = new QGLContextGroup(context);}
       
   265     ~QGLContextPrivate();
       
   266     QGLTexture *bindTexture(const QImage &image, GLenum target, GLint format,
       
   267                             QGLContext::BindOptions options);
       
   268     QGLTexture *bindTexture(const QImage &image, GLenum target, GLint format, const qint64 key,
       
   269                             QGLContext::BindOptions options);
       
   270     QGLTexture *bindTexture(const QPixmap &pixmap, GLenum target, GLint format,
       
   271                             QGLContext::BindOptions options);
       
   272     QGLTexture *textureCacheLookup(const qint64 key, GLenum target);
       
   273     void init(QPaintDevice *dev, const QGLFormat &format);
       
   274     QImage convertToGLFormat(const QImage &image, bool force_premul, GLenum texture_format);
       
   275     int maxTextureSize();
       
   276 
       
   277     void cleanup();
       
   278 
       
   279 #if defined(Q_WS_WIN)
       
   280     HGLRC rc;
       
   281     HDC dc;
       
   282     WId        win;
       
   283     int pixelFormatId;
       
   284     QGLCmap* cmap;
       
   285     HBITMAP hbitmap;
       
   286     HDC hbitmap_hdc;
       
   287 #endif
       
   288 #if defined(QT_OPENGL_ES)
       
   289     QEglContext *eglContext;
       
   290     EGLSurface eglSurface;
       
   291     void destroyEglSurfaceForDevice();
       
   292 #elif defined(Q_WS_X11) || defined(Q_WS_MAC)
       
   293     void* cx;
       
   294 #endif
       
   295 #if defined(Q_WS_X11) || defined(Q_WS_MAC)
       
   296     void* vi;
       
   297 #endif
       
   298 #if defined(Q_WS_X11)
       
   299     void* pbuf;
       
   300     quint32 gpm;
       
   301     int screen;
       
   302     QHash<QPixmapData*, QPixmap> boundPixmaps;
       
   303     QGLTexture *bindTextureFromNativePixmap(QPixmapData*, const qint64 key,
       
   304                                             QGLContext::BindOptions options);
       
   305     static void destroyGlSurfaceForPixmap(QPixmapData*);
       
   306     static void unbindPixmapFromTexture(QPixmapData*);
       
   307 #endif
       
   308 #if defined(Q_WS_MAC)
       
   309     bool update;
       
   310     void *tryFormat(const QGLFormat &format);
       
   311     void clearDrawable();
       
   312 #endif
       
   313     QGLFormat glFormat;
       
   314     QGLFormat reqFormat;
       
   315     GLuint fbo;
       
   316 
       
   317     uint valid : 1;
       
   318     uint sharing : 1;
       
   319     uint initDone : 1;
       
   320     uint crWin : 1;
       
   321     uint internal_context : 1;
       
   322     uint version_flags_cached : 1;
       
   323     QPaintDevice *paintDevice;
       
   324     QColor transpColor;
       
   325     QGLContext *q_ptr;
       
   326     QGLFormat::OpenGLVersionFlags version_flags;
       
   327 
       
   328     QGLContextGroup *group;
       
   329     GLint max_texture_size;
       
   330 
       
   331     GLuint current_fbo;
       
   332     GLuint default_fbo;
       
   333     QPaintEngine *active_engine;
       
   334 
       
   335     static inline QGLContextGroup *contextGroup(const QGLContext *ctx) { return ctx->d_ptr->group; }
       
   336 
       
   337 #ifdef Q_WS_WIN
       
   338     static inline QGLExtensionFuncs& extensionFuncs(const QGLContext *ctx) { return ctx->d_ptr->group->extensionFuncs(); }
       
   339 #endif
       
   340 
       
   341 #if defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_WS_QWS)
       
   342     static QGLExtensionFuncs qt_extensionFuncs;
       
   343     static inline QGLExtensionFuncs& extensionFuncs(const QGLContext *) { return qt_extensionFuncs; }
       
   344 #endif
       
   345 
       
   346     static void setCurrentContext(QGLContext *context);
       
   347 };
       
   348 
       
   349 // ### make QGLContext a QObject in 5.0 and remove the proxy stuff
       
   350 class Q_OPENGL_EXPORT QGLSignalProxy : public QObject
       
   351 {
       
   352     Q_OBJECT
       
   353 public:
       
   354     QGLSignalProxy() : QObject() {}
       
   355     void emitAboutToDestroyContext(const QGLContext *context) {
       
   356         emit aboutToDestroyContext(context);
       
   357     }
       
   358     static QGLSignalProxy *instance();
       
   359 Q_SIGNALS:
       
   360     void aboutToDestroyContext(const QGLContext *context);
       
   361 };
       
   362 
   263 
   363 // GL extension definitions
   264 // GL extension definitions
   364 class QGLExtensions {
   265 class QGLExtensions {
   365 public:
   266 public:
   366     enum Extension {
   267     enum Extension {
   384         PVRTCTextureCompression = 0x00020000,
   285         PVRTCTextureCompression = 0x00020000,
   385         FragmentShader          = 0x00040000
   286         FragmentShader          = 0x00040000
   386     };
   287     };
   387     Q_DECLARE_FLAGS(Extensions, Extension)
   288     Q_DECLARE_FLAGS(Extensions, Extension)
   388 
   289 
   389     static Extensions glExtensions;
   290     static Extensions glExtensions();
   390     static bool nvidiaFboNeedsFinish;
   291 
   391     static void init(); // sys dependent
   292 private:
   392     static void init_extensions(); // general: called by init()
   293     static Extensions currentContextExtensions();
       
   294 };
       
   295 
       
   296 /*
       
   297     QGLTemporaryContext - the main objective of this class is to have a way of
       
   298     creating a GL context and making it current, without going via QGLWidget
       
   299     and friends. At certain points during GL initialization we need a current
       
   300     context in order decide what GL features are available, and to resolve GL
       
   301     extensions. Having a light-weight way of creating such a context saves
       
   302     initial application startup time, and it doesn't wind up creating recursive
       
   303     conflicts.
       
   304     The class currently uses a private d pointer to hide the platform specific
       
   305     types. This could possibly been done inline with #ifdef'ery, but it causes
       
   306     major headaches on e.g. X11 due to namespace pollution.
       
   307 */
       
   308 class QGLTemporaryContextPrivate;
       
   309 class QGLTemporaryContext {
       
   310 public:
       
   311     QGLTemporaryContext(bool directRendering = true, QWidget *parent = 0);
       
   312     ~QGLTemporaryContext();
       
   313 
       
   314 private:
       
   315     QScopedPointer<QGLTemporaryContextPrivate> d;
       
   316 };
       
   317 
       
   318 class QGLTexture;
       
   319 
       
   320 // This probably needs to grow to GL_MAX_VERTEX_ATTRIBS, but 3 is ok for now as that's
       
   321 // all the GL2 engine uses:
       
   322 #define QT_GL_VERTEX_ARRAY_TRACKED_COUNT 3
       
   323 
       
   324 class QGLContextPrivate
       
   325 {
       
   326     Q_DECLARE_PUBLIC(QGLContext)
       
   327 public:
       
   328     explicit QGLContextPrivate(QGLContext *context) : internal_context(false), q_ptr(context) {group = new QGLContextGroup(context);}
       
   329     ~QGLContextPrivate();
       
   330     QGLTexture *bindTexture(const QImage &image, GLenum target, GLint format,
       
   331                             QGLContext::BindOptions options);
       
   332     QGLTexture *bindTexture(const QImage &image, GLenum target, GLint format, const qint64 key,
       
   333                             QGLContext::BindOptions options);
       
   334     QGLTexture *bindTexture(const QPixmap &pixmap, GLenum target, GLint format,
       
   335                             QGLContext::BindOptions options);
       
   336     QGLTexture *textureCacheLookup(const qint64 key, GLenum target);
       
   337     void init(QPaintDevice *dev, const QGLFormat &format);
       
   338     QImage convertToGLFormat(const QImage &image, bool force_premul, GLenum texture_format);
       
   339     int maxTextureSize();
       
   340 
       
   341     void cleanup();
       
   342 
       
   343     void setVertexAttribArrayEnabled(int arrayIndex, bool enabled = true);
       
   344     void syncGlState(); // Makes sure the GL context's state is what we think it is
       
   345 
       
   346 #if defined(Q_WS_WIN)
       
   347     HGLRC rc;
       
   348     HDC dc;
       
   349     WId        win;
       
   350     int pixelFormatId;
       
   351     QGLCmap* cmap;
       
   352     HBITMAP hbitmap;
       
   353     HDC hbitmap_hdc;
       
   354 #endif
       
   355 #if defined(QT_OPENGL_ES)
       
   356     QEglContext *eglContext;
       
   357     EGLSurface eglSurface;
       
   358     void destroyEglSurfaceForDevice();
       
   359 #elif defined(Q_WS_X11) || defined(Q_WS_MAC)
       
   360     void* cx;
       
   361 #endif
       
   362 #if defined(Q_WS_X11) || defined(Q_WS_MAC)
       
   363     void* vi;
       
   364 #endif
       
   365 #if defined(Q_WS_X11)
       
   366     void* pbuf;
       
   367     quint32 gpm;
       
   368     int screen;
       
   369     QHash<QPixmapData*, QPixmap> boundPixmaps;
       
   370     QGLTexture *bindTextureFromNativePixmap(QPixmapData*, const qint64 key,
       
   371                                             QGLContext::BindOptions options);
       
   372     static void destroyGlSurfaceForPixmap(QPixmapData*);
       
   373     static void unbindPixmapFromTexture(QPixmapData*);
       
   374 #endif
       
   375 #if defined(Q_WS_MAC)
       
   376     bool update;
       
   377     void *tryFormat(const QGLFormat &format);
       
   378     void clearDrawable();
       
   379 #endif
       
   380     QGLFormat glFormat;
       
   381     QGLFormat reqFormat;
       
   382     GLuint fbo;
       
   383 
       
   384     uint valid : 1;
       
   385     uint sharing : 1;
       
   386     uint initDone : 1;
       
   387     uint crWin : 1;
       
   388     uint internal_context : 1;
       
   389     uint version_flags_cached : 1;
       
   390     uint extension_flags_cached : 1;
       
   391     QPaintDevice *paintDevice;
       
   392     QColor transpColor;
       
   393     QGLContext *q_ptr;
       
   394     QGLFormat::OpenGLVersionFlags version_flags;
       
   395     QGLExtensions::Extensions extension_flags;
       
   396 
       
   397     QGLContextGroup *group;
       
   398     GLint max_texture_size;
       
   399 
       
   400     GLuint current_fbo;
       
   401     GLuint default_fbo;
       
   402     QPaintEngine *active_engine;
       
   403 
       
   404     bool vertexAttributeArraysEnabledState[QT_GL_VERTEX_ARRAY_TRACKED_COUNT];
       
   405 
       
   406     static inline QGLContextGroup *contextGroup(const QGLContext *ctx) { return ctx->d_ptr->group; }
       
   407 
       
   408 #ifdef Q_WS_WIN
       
   409     static inline QGLExtensionFuncs& extensionFuncs(const QGLContext *ctx) { return ctx->d_ptr->group->extensionFuncs(); }
       
   410 #endif
       
   411 
       
   412 #if defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_WS_QWS)
       
   413     static QGLExtensionFuncs qt_extensionFuncs;
       
   414     static inline QGLExtensionFuncs& extensionFuncs(const QGLContext *) { return qt_extensionFuncs; }
       
   415 #endif
       
   416 
       
   417     static void setCurrentContext(QGLContext *context);
       
   418 };
       
   419 
       
   420 // ### make QGLContext a QObject in 5.0 and remove the proxy stuff
       
   421 class Q_OPENGL_EXPORT QGLSignalProxy : public QObject
       
   422 {
       
   423     Q_OBJECT
       
   424 public:
       
   425     QGLSignalProxy() : QObject() {}
       
   426     void emitAboutToDestroyContext(const QGLContext *context) {
       
   427         emit aboutToDestroyContext(context);
       
   428     }
       
   429     static QGLSignalProxy *instance();
       
   430 Q_SIGNALS:
       
   431     void aboutToDestroyContext(const QGLContext *context);
   393 };
   432 };
   394 
   433 
   395 Q_DECLARE_OPERATORS_FOR_FLAGS(QGLExtensions::Extensions)
   434 Q_DECLARE_OPERATORS_FOR_FLAGS(QGLExtensions::Extensions)
   396 
       
   397 
       
   398 class Q_OPENGL_EXPORT QGLShareRegister
       
   399 {
       
   400 public:
       
   401     QGLShareRegister() {}
       
   402     ~QGLShareRegister() {}
       
   403 
       
   404     void addShare(const QGLContext *context, const QGLContext *share);
       
   405     QList<const QGLContext *> shares(const QGLContext *context);
       
   406     void removeShare(const QGLContext *context);
       
   407 };
       
   408 
       
   409 extern Q_OPENGL_EXPORT QGLShareRegister* qgl_share_reg();
       
   410 
   435 
   411 // Temporarily make a context current if not already current or
   436 // Temporarily make a context current if not already current or
   412 // shared with the current contex.  The previous context is made
   437 // shared with the current contex.  The previous context is made
   413 // current when the object goes out of scope.
   438 // current when the object goes out of scope.
   414 class Q_OPENGL_EXPORT QGLShareContextScope
   439 class Q_OPENGL_EXPORT QGLShareContextScope
   529 
   554 
   530 bool qt_gl_preferGL2Engine();
   555 bool qt_gl_preferGL2Engine();
   531 
   556 
   532 inline GLenum qt_gl_preferredTextureFormat()
   557 inline GLenum qt_gl_preferredTextureFormat()
   533 {
   558 {
   534     return (QGLExtensions::glExtensions & QGLExtensions::BGRATextureFormat) && QSysInfo::ByteOrder == QSysInfo::LittleEndian
   559     return (QGLExtensions::glExtensions() & QGLExtensions::BGRATextureFormat) && QSysInfo::ByteOrder == QSysInfo::LittleEndian
   535         ? GL_BGRA : GL_RGBA;
   560         ? GL_BGRA : GL_RGBA;
   536 }
   561 }
   537 
   562 
   538 inline GLenum qt_gl_preferredTextureTarget()
   563 inline GLenum qt_gl_preferredTextureTarget()
   539 {
   564 {
   540 #if defined(QT_OPENGL_ES_2)
   565 #if defined(QT_OPENGL_ES_2)
   541     return GL_TEXTURE_2D;
   566     return GL_TEXTURE_2D;
   542 #else
   567 #else
   543     return (QGLExtensions::glExtensions & QGLExtensions::TextureRectangle)
   568     return (QGLExtensions::glExtensions() & QGLExtensions::TextureRectangle)
   544            && !qt_gl_preferGL2Engine()
   569            && !qt_gl_preferGL2Engine()
   545            ? GL_TEXTURE_RECTANGLE_NV
   570            ? GL_TEXTURE_RECTANGLE_NV
   546            : GL_TEXTURE_2D;
   571            : GL_TEXTURE_2D;
   547 #endif
   572 #endif
   548 }
   573 }
   610 
   635 
   611     friend class QGLContextGroup;
   636     friend class QGLContextGroup;
   612 };
   637 };
   613 
   638 
   614 
   639 
   615 // This class can be used to match GL extensions with doing any mallocs. The
   640 // This class can be used to match GL extensions without doing any mallocs. The
   616 // class assumes that the GL extension string ends with a space character,
   641 // class assumes that the GL extension string ends with a space character,
   617 // which it should do on all conformant platforms. Create the object and pass
   642 // which it should do on all conformant platforms. Create the object and pass
   618 // in a pointer to the extension string, then call match() on each extension
   643 // in a pointer to the extension string, then call match() on each extension
   619 // that should be matched. The match() function takes the extension name
   644 // that should be matched. The match() function takes the extension name
   620 // *without* the terminating space character as input.
   645 // *without* the terminating space character as input.