diff options
author | Peter Yard <peter.yard@nokia.com> | 2009-07-24 04:20:16 (GMT) |
---|---|---|
committer | Peter Yard <peter.yard@nokia.com> | 2009-07-24 04:20:16 (GMT) |
commit | ed159f974aa99e2ba3cc3112f7e3a1ced26b14b1 (patch) | |
tree | a0fbfb009316f8fb9b2600db7a86fadbeef966e4 /src/opengl/qgl_p.h | |
parent | 3d272951dc9f055e9fc5064098f6a165a8c3e623 (diff) | |
parent | 9ec431c161202d9f06f3a7c59181cb0ab523958a (diff) | |
download | Qt-ed159f974aa99e2ba3cc3112f7e3a1ced26b14b1.zip Qt-ed159f974aa99e2ba3cc3112f7e3a1ced26b14b1.tar.gz Qt-ed159f974aa99e2ba3cc3112f7e3a1ced26b14b1.tar.bz2 |
Merge branch 'master' of git@scm.dev.nokia.troll.no:qt/qt
Diffstat (limited to 'src/opengl/qgl_p.h')
-rw-r--r-- | src/opengl/qgl_p.h | 171 |
1 files changed, 114 insertions, 57 deletions
diff --git a/src/opengl/qgl_p.h b/src/opengl/qgl_p.h index ac19d64..85dae0d 100644 --- a/src/opengl/qgl_p.h +++ b/src/opengl/qgl_p.h @@ -60,10 +60,7 @@ #include "QtCore/qthreadstorage.h" #include "QtCore/qhash.h" #include "private/qwidget_p.h" - -#if !defined(QT_OPENGL_ES_1) && !defined(QT_OPENGL_ES_1_CL) -#include "private/qpixmapdata_gl_p.h" -#endif +#include "qcache.h" #ifndef QT_OPENGL_ES_1_CL #define q_vertexType float @@ -196,17 +193,26 @@ public: #endif }; +struct QGLContextGroupResources +{ + QGLContextGroupResources() : refs(1) { } + QGLExtensionFuncs extensionFuncs; + QAtomicInt refs; +}; + +class QGLTexture; + class QGLContextPrivate { Q_DECLARE_PUBLIC(QGLContext) public: - explicit QGLContextPrivate(QGLContext *context) : internal_context(false), q_ptr(context) {} - ~QGLContextPrivate() {} - GLuint bindTexture(const QImage &image, GLenum target, GLint format, const qint64 key, + explicit QGLContextPrivate(QGLContext *context) : internal_context(false), q_ptr(context) {groupResources = new QGLContextGroupResources;} + ~QGLContextPrivate() {if (!groupResources->refs.deref()) delete groupResources;} + QGLTexture *bindTexture(const QImage &image, GLenum target, GLint format, bool clean); + QGLTexture *bindTexture(const QImage &image, GLenum target, GLint format, const qint64 key, bool clean = false); - GLuint bindTexture(const QPixmap &pixmap, GLenum target, GLint format, bool clean); - GLuint bindTexture(const QImage &image, GLenum target, GLint format, bool clean); - bool textureCacheLookup(const qint64 key, GLenum target, GLuint *id); + QGLTexture *bindTexture(const QPixmap &pixmap, GLenum target, GLint format, bool clean, bool canInvert = false); + 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(); @@ -234,6 +240,8 @@ public: void* pbuf; quint32 gpm; int screen; + QHash<QPixmapData*, QPixmap> boundPixmaps; + QGLTexture *bindTextureFromNativePixmap(QPixmap *pm, const qint64 key, bool internal); #endif #if defined(Q_WS_MAC) bool update; @@ -257,14 +265,14 @@ public: QGLContext *q_ptr; QGLFormat::OpenGLVersionFlags version_flags; - QGLExtensionFuncs extensionFuncs; + QGLContextGroupResources *groupResources; GLint max_texture_size; GLuint current_fbo; QPaintEngine *active_engine; #ifdef Q_WS_WIN - static inline QGLExtensionFuncs& qt_get_extension_funcs(const QGLContext *ctx) { return ctx->d_ptr->extensionFuncs; } + static inline QGLExtensionFuncs& qt_get_extension_funcs(const QGLContext *ctx) { return ctx->d_ptr->groupResources->extensionFuncs; } #endif #if defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_WS_QWS) @@ -293,6 +301,7 @@ class QGLPixelBuffer; class QGLFramebufferObject; class QWSGLWindowSurface; class QGLWindowSurface; +class QGLPixmapData; class QGLDrawable { public: QGLDrawable() : widget(0), buffer(0), fbo(0) @@ -353,7 +362,8 @@ public: PackedDepthStencil = 0x00000200, NVFloatBuffer = 0x00000400, PixelBufferObject = 0x00000800, - FramebufferBlit = 0x00001000 + FramebufferBlit = 0x00001000, + NPOTTextures = 0x00002000 }; Q_DECLARE_FLAGS(Extensions, Extension) @@ -371,65 +381,89 @@ struct QGLThreadContext { }; extern QThreadStorage<QGLThreadContext *> qgl_context_storage; -typedef QMultiHash<const QGLContext *, const QGLContext *> QGLSharingHash; class QGLShareRegister { public: QGLShareRegister() {} ~QGLShareRegister() { reg.clear(); } - bool checkSharing(const QGLContext *context1, const QGLContext *context2, const QGLContext * skip=0) { - if (context1 == context2) - return true; - QList<const QGLContext *> shares = reg.values(context1); - for (int k=0; k<shares.size(); ++k) { - const QGLContext *ctx = shares.at(k); - if (ctx == skip) // avoid an indirect circular loop (infinite recursion) - continue; - if (ctx == context2) - return true; - if (checkSharing(ctx, context2, context1)) - return true; - } - return false; - } + bool checkSharing(const QGLContext *context1, const QGLContext *context2); + void addShare(const QGLContext *context, const QGLContext *share); + QList<const QGLContext *> shares(const QGLContext *context); + void removeShare(const QGLContext *context); +private: + // Use a context's 'groupResources' pointer to uniquely identify a group. + typedef QList<const QGLContext *> ContextList; + typedef QHash<const QGLContextGroupResources *, ContextList> SharingHash; + SharingHash reg; +}; - void addShare(const QGLContext *context, const QGLContext *share) { - reg.insert(context, share); // context sharing works both ways - reg.insert(share, context); - } +extern Q_OPENGL_EXPORT QGLShareRegister* qgl_share_reg(); - void removeShare(const QGLContext *context) { - QGLSharingHash::iterator it = reg.begin(); - while (it != reg.end()) { - if (it.key() == context || it.value() == context) - it = reg.erase(it); - else - ++it; +class QGLTexture { +public: + QGLTexture(QGLContext *ctx = 0, GLuint tx_id = 0, GLenum tx_target = GL_TEXTURE_2D, + bool _clean = false, bool _yInverted = false) + : context(ctx), id(tx_id), target(tx_target), clean(_clean), yInverted(_yInverted) +#if defined(Q_WS_X11) + , boundPixmap(0) +#endif + {} + + ~QGLTexture() { + if (clean) { + QGLContext *current = const_cast<QGLContext *>(QGLContext::currentContext()); + QGLContext *ctx = const_cast<QGLContext *>(context); + Q_ASSERT(ctx); + bool switch_context = current != ctx && !qgl_share_reg()->checkSharing(current, ctx); + if (switch_context) + ctx->makeCurrent(); +#if defined(Q_WS_X11) + // Although glXReleaseTexImage is a glX call, it must be called while there + // is a current context - the context the pixmap was bound to a texture in. + // Otherwise the release doesn't do anything and you get BadDrawable errors + // when you come to delete the context. + deleteBoundPixmap(); +#endif + glDeleteTextures(1, &id); + if (switch_context && current) + current->makeCurrent(); } - } + } - void replaceShare(const QGLContext *oldContext, const QGLContext *newContext) { - QGLSharingHash::iterator it = reg.begin(); - while (it != reg.end()) { - if (it.key() == oldContext) - reg.insert(newContext, it.value()); - else if (it.value() == oldContext) - reg.insert(it.key(), newContext); - ++it; - } - removeShare(oldContext); - } + QGLContext *context; + GLuint id; + GLenum target; + bool clean; + bool yInverted; // NOTE: Y-Inverted textures are for internal use only! +#if defined(Q_WS_X11) + Qt::HANDLE boundPixmap; + void deleteBoundPixmap(); // in qgl_x11.cpp/qgl_x11egl.cpp +#endif +}; - QList<const QGLContext *> shares(const QGLContext *context) { - return reg.values(context); - } +class QGLTextureCache { +public: + QGLTextureCache(); + ~QGLTextureCache(); + + void insert(QGLContext *ctx, qint64 key, QGLTexture *texture, int cost); + void remove(quint64 key) { m_cache.remove(key); } + bool remove(QGLContext *ctx, GLuint textureId); + void removeContextTextures(QGLContext *ctx); + int size() { return m_cache.size(); } + void setMaxCost(int newMax) { m_cache.setMaxCost(newMax); } + int maxCost() {return m_cache.maxCost(); } + QGLTexture* getTexture(quint64 key) { return m_cache.object(key); } + + static QGLTextureCache *instance(); + static void deleteIfEmpty(); + static void cleanupHook(qint64 cacheKey); private: - QGLSharingHash reg; + QCache<qint64, QGLTexture> m_cache; }; -extern Q_OPENGL_EXPORT QGLShareRegister* qgl_share_reg(); #ifdef Q_WS_QWS extern QPaintEngine* qt_qgl_paint_engine(); @@ -464,6 +498,29 @@ inline GLenum qt_gl_preferredTextureTarget() #endif } +// One resource per group of shared contexts. +class QGLContextResource : public QObject +{ + Q_OBJECT +public: + typedef void (*FreeFunc)(void *); + QGLContextResource(FreeFunc f, QObject *parent = 0); + ~QGLContextResource(); + // Set resource 'value' for 'key' and all its shared contexts. + void insert(const QGLContext *key, void *value); + // Return resource for 'key' or a shared context. + void *value(const QGLContext *key); + // Free resource for 'key' and all its shared contexts. + void remove(const QGLContext *key); +private slots: + // Remove entry 'key' from cache and delete resource if there are no shared contexts. + void aboutToDestroyContext(const QGLContext *key); +private: + typedef QHash<const QGLContext *, void *> ResourceHash; + ResourceHash m_resources; + FreeFunc free; +}; + QT_END_NAMESPACE #endif // QGL_P_H |