diff options
Diffstat (limited to 'src/opengl')
-rw-r--r-- | src/opengl/qgl.h | 1 | ||||
-rw-r--r-- | src/opengl/qpixmapdata_x11gl_egl.cpp | 241 | ||||
-rw-r--r-- | src/opengl/qpixmapdata_x11gl_p.h | 7 |
3 files changed, 148 insertions, 101 deletions
diff --git a/src/opengl/qgl.h b/src/opengl/qgl.h index b1e2ede..92a064f 100644 --- a/src/opengl/qgl.h +++ b/src/opengl/qgl.h @@ -432,6 +432,7 @@ private: friend class QGLFBOGLPaintDevice; friend class QGLPaintDevice; friend class QX11GLPixmapData; + friend class QX11GLSharedContexts; private: Q_DISABLE_COPY(QGLContext) }; diff --git a/src/opengl/qpixmapdata_x11gl_egl.cpp b/src/opengl/qpixmapdata_x11gl_egl.cpp index 3b11749..58d34fc 100644 --- a/src/opengl/qpixmapdata_x11gl_egl.cpp +++ b/src/opengl/qpixmapdata_x11gl_egl.cpp @@ -62,123 +62,170 @@ QT_BEGIN_NAMESPACE -// On 16bpp systems, RGB & ARGB pixmaps are different bit-depths and therefore need -// different contexts: - -Q_GLOBAL_STATIC(QEglContext, qt_x11gl_rgbContext); -Q_GLOBAL_STATIC(QEglContext, qt_x11gl_argbContext); -Q_GLOBAL_STATIC_WITH_ARGS(QGLContext, qt_x11gl_fake_shared_context, (QX11GLPixmapData::glFormat())); +class QX11GLSharedContexts +{ +public: + QX11GLSharedContexts() + : rgbContext(0) + , argbContext(0) + , sharedQGLContext(0) + , sharePixmap(0) + { + EGLint rgbConfigId; + EGLint argbConfigId; + + + do { + EGLConfig rgbConfig = QEgl::defaultConfig(QInternal::Pixmap, QEgl::OpenGL, QEgl::Renderable); + EGLConfig argbConfig = QEgl::defaultConfig(QInternal::Pixmap, QEgl::OpenGL, + QEgl::Renderable | QEgl::Translucent); + + eglGetConfigAttrib(QEgl::display(), rgbConfig, EGL_CONFIG_ID, &rgbConfigId); + eglGetConfigAttrib(QEgl::display(), argbConfig, EGL_CONFIG_ID, &argbConfigId); + + rgbContext = new QEglContext; + rgbContext->setConfig(rgbConfig); + rgbContext->createContext(); -QEglContext* QX11GLPixmapData::rgbContext = 0; -QEglContext* QX11GLPixmapData::argbContext = 0; + if (!rgbContext->isValid()) + break; + // If the RGB & ARGB configs are the same, use the same egl context for both: + if (rgbConfig == argbConfig) + argbContext = rgbContext; + + // Otherwise, create a seperate context to be used for ARGB pixmaps: + if (!argbContext) { + argbContext = new QEglContext; + argbContext->setConfig(argbConfig); + bool success = argbContext->createContext(rgbContext); + if (!success) { + qWarning("QX11GLPixmapData - RGB & ARGB contexts aren't shared"); + success = argbContext->createContext(); + if (!success) + argbContext = rgbContext; // Might work, worth a shot at least. + } + } -bool QX11GLPixmapData::hasX11GLPixmaps() -{ - static bool checkedForX11Pixmaps = false; - static bool haveX11Pixmaps = false; + if (!argbContext->isValid()) + break; - if (checkedForX11Pixmaps) - return haveX11Pixmaps; + // Create the pixmap which will be used to create the egl surface for the share QGLContext + QX11PixmapData *rgbPixmapData = new QX11PixmapData(QPixmapData::PixmapType); + rgbPixmapData->resize(8, 8); + rgbPixmapData->fill(Qt::red); + sharePixmap = new QPixmap(rgbPixmapData); + EGLSurface sharePixmapSurface = QEgl::createSurface(sharePixmap, rgbConfig); + rgbPixmapData->gl_surface = (void*)sharePixmapSurface; + + // Create the actual QGLContext which will be used for sharing + sharedQGLContext = new QGLContext(QX11GLPixmapData::glFormat()); + sharedQGLContext->d_func()->eglContext = rgbContext; + sharedQGLContext->d_func()->eglSurface = sharePixmapSurface; + sharedQGLContext->d_func()->valid = true; + qt_glformat_from_eglconfig(sharedQGLContext->d_func()->glFormat, rgbConfig); + + + valid = rgbContext->makeCurrent(sharePixmapSurface); + + // If the ARGB & RGB configs are different, check ARGB works too: + if (argbConfig != rgbConfig) { + QX11PixmapData *argbPixmapData = new QX11PixmapData(QPixmapData::PixmapType); + argbPixmapData->resize(8, 8); + argbPixmapData->fill(Qt::transparent); // Force ARGB + QPixmap argbPixmap(argbPixmapData); // destroys pixmap data when goes out of scope + EGLSurface argbPixmapSurface = QEgl::createSurface(&argbPixmap, argbConfig); + valid = argbContext->makeCurrent(argbPixmapSurface); + argbContext->doneCurrent(); + eglDestroySurface(QEgl::display(), argbPixmapSurface); + } - checkedForX11Pixmaps = true; + if (!valid) { + qWarning() << "Unable to make pixmap surface current:" << QEgl::errorString(); + break; + } - EGLint rgbConfigId; - EGLint argbConfigId; + // The pixmap surface destruction hooks are installed by QGLTextureCache, so we + // must make sure this is instanciated: + QGLTextureCache::instance(); + } while(0); - do { - if (qgetenv("QT_USE_X11GL_PIXMAPS").isEmpty()) - break; - EGLConfig rgbConfig = QEgl::defaultConfig(QInternal::Pixmap, QEgl::OpenGL, QEgl::Renderable); - EGLConfig argbConfig = QEgl::defaultConfig(QInternal::Pixmap, QEgl::OpenGL, - QEgl::Renderable | QEgl::Translucent); + if (!valid) + cleanup(); + else + qDebug("Using QX11GLPixmapData with EGL config %d for ARGB and config %d for RGB", argbConfigId, rgbConfigId); - eglGetConfigAttrib(QEgl::display(), rgbConfig, EGL_CONFIG_ID, &rgbConfigId); - eglGetConfigAttrib(QEgl::display(), argbConfig, EGL_CONFIG_ID, &argbConfigId); + } - if (!rgbContext) { - rgbContext = qt_x11gl_rgbContext(); - rgbContext->setConfig(rgbConfig); - rgbContext->createContext(); + void cleanup() { + if (sharedQGLContext) { + delete sharedQGLContext; + sharedQGLContext = 0; } + if (argbContext && argbContext != rgbContext) + delete argbContext; + argbContext = 0; - if (!rgbContext->isValid()) - break; - - // If the configs are the same, use the same egl contexts: - if (rgbConfig == argbConfig) - argbContext = rgbContext; - - if (!argbContext) { - argbContext = qt_x11gl_argbContext(); - argbContext->setConfig(argbConfig); - bool success = argbContext->createContext(rgbContext); - if (!success) { - qWarning("QX11GLPixmapData - RGB & ARGB contexts aren't shared"); - success = argbContext->createContext(); - if (!success) - argbContext = rgbContext; // Might work, worth a shot at least. - } + if (rgbContext) { + delete rgbContext; + rgbContext = 0; } - if (!argbContext->isValid()) - break; - - { - QX11PixmapData *argbPixmapData = new QX11PixmapData(QPixmapData::PixmapType); - argbPixmapData->resize(100, 100); - argbPixmapData->fill(Qt::transparent); // Force ARGB - QPixmap argbPixmap(argbPixmapData); - EGLSurface argbPixmapSurface = QEgl::createSurface(&argbPixmap, argbConfig); - haveX11Pixmaps = argbContext->makeCurrent(argbPixmapSurface); - argbContext->doneCurrent(); - eglDestroySurface(QEgl::display(), argbPixmapSurface); + // Deleting the QPixmap will fire the pixmap destruction cleanup hooks which in turn + // will destroy the egl surface: + if (sharePixmap) { + delete sharePixmap; + sharePixmap = 0; } + } - if (!haveX11Pixmaps) { - qWarning() << "Unable to make pixmap surface current:" << QEgl::errorString(); - break; - } + bool isValid() { return valid;} - // If the ARGB & RGB configs are different, check RGB too: - if (argbConfig != rgbConfig) { - QX11PixmapData *rgbPixmapData = new QX11PixmapData(QPixmapData::PixmapType); - rgbPixmapData->resize(100, 100); - rgbPixmapData->fill(Qt::red); + // On 16bpp systems, RGB & ARGB pixmaps are different bit-depths and therefore need + // different contexts: + QEglContext *rgbContext; + QEglContext *argbContext; - QPixmap rgbPixmap(rgbPixmapData); - EGLSurface rgbPixmapSurface = QEgl::createSurface(&rgbPixmap, rgbConfig); - haveX11Pixmaps = rgbContext->makeCurrent(rgbPixmapSurface); - rgbContext->doneCurrent(); - eglDestroySurface(QEgl::display(), rgbPixmapSurface); + // The share context wraps the rgbContext and is used as the master of the context share + // group. As all other contexts will have the same egl context (or a shared one if rgb != argb) + // all QGLContexts will actually be sharing and can be in the same context group. + QGLContext *sharedQGLContext; +private: + QPixmap *sharePixmap; + bool valid; +}; - if (!haveX11Pixmaps) { - qWarning() << "Unable to make pixmap config current:" << QEgl::errorString(); - break; - } - } +static void qt_cleanup_x11gl_share_contexts(); - // The pixmap surface destruction hooks are installed by QGLTextureCache, so we - // must make sure this is instanciated: - QGLTextureCache::instance(); - } while (0); +Q_GLOBAL_STATIC_WITH_INITIALIZER(QX11GLSharedContexts, qt_x11gl_share_contexts, + { + qAddPostRoutine(qt_cleanup_x11gl_share_contexts); + }) - if (!haveX11Pixmaps) { - if (argbContext && (argbContext != rgbContext)) { - delete argbContext; - argbContext = 0; - } - if (rgbContext) { - delete rgbContext; - rgbContext = 0; - } - } +static void qt_cleanup_x11gl_share_contexts() +{ + qt_x11gl_share_contexts()->cleanup(); +} - if (haveX11Pixmaps) - qDebug("Using QX11GLPixmapData with EGL config %d for ARGB and config %d for RGB", argbConfigId, rgbConfigId); - else - qDebug("QX11GLPixmapData is *NOT* being used"); + +QX11GLSharedContexts* QX11GLPixmapData::sharedContexts() +{ + return qt_x11gl_share_contexts(); +} + +bool QX11GLPixmapData::hasX11GLPixmaps() +{ + static bool checkedForX11Pixmaps = false; + static bool haveX11Pixmaps = false; + + if (checkedForX11Pixmaps) + return haveX11Pixmaps; + + checkedForX11Pixmaps = true; + + if (!qgetenv("QT_USE_X11GL_PIXMAPS").isEmpty() && sharedContexts()->isValid()) + haveX11Pixmaps = true; return haveX11Pixmaps; } @@ -264,14 +311,14 @@ QPaintEngine* QX11GLPixmapData::paintEngine() const if (!ctx) { ctx = new QGLContext(glFormat()); Q_ASSERT(ctx->d_func()->eglContext == 0); - ctx->d_func()->eglContext = hasAlphaChannel() ? argbContext : rgbContext; + ctx->d_func()->eglContext = hasAlphaChannel() ? sharedContexts()->argbContext : sharedContexts()->rgbContext; // While we use a seperate QGLContext for each pixmap, the underlying QEglContext is // the same. So we must use a "fake" QGLContext and fool the texture cache into thinking // each pixmap's QGLContext is sharing with this central one. The only place this is // going to fail is where we the underlying EGL RGB and ARGB contexts aren't sharing. ctx->d_func()->sharing = true; - QGLContextGroup::addShare(ctx, qt_x11gl_fake_shared_context()); + QGLContextGroup::addShare(ctx, sharedContexts()->sharedQGLContext); // Update the glFormat for the QGLContext: qt_glformat_from_eglconfig(ctx->d_func()->glFormat, ctx->d_func()->eglContext->config()); diff --git a/src/opengl/qpixmapdata_x11gl_p.h b/src/opengl/qpixmapdata_x11gl_p.h index b613eba..2d1336b 100644 --- a/src/opengl/qpixmapdata_x11gl_p.h +++ b/src/opengl/qpixmapdata_x11gl_p.h @@ -65,6 +65,8 @@ QT_BEGIN_NAMESPACE +class QX11GLSharedContexts; + class QX11GLPixmapData : public QX11PixmapData, public QGLPaintDevice { public: @@ -84,11 +86,8 @@ public: static bool hasX11GLPixmaps(); static QGLFormat glFormat(); + static QX11GLSharedContexts* sharedContexts(); -#ifndef QT_NO_EGL - static QEglContext* rgbContext; - static QEglContext* argbContext; -#endif private: mutable QGLContext* ctx; }; |