From 4c4537d63a62d5ba0a2d8ddbc04026f81399268f Mon Sep 17 00:00:00 2001 From: Tom Cooksey Date: Fri, 5 Mar 2010 16:57:46 +0100 Subject: Make QEgl::ConfigOptions use QFlags Reviewed-By: Trustme --- src/gui/egl/qegl_p.h | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/gui/egl/qegl_p.h b/src/gui/egl/qegl_p.h index ffb45aa..f500bd4 100644 --- a/src/gui/egl/qegl_p.h +++ b/src/gui/egl/qegl_p.h @@ -97,10 +97,14 @@ QT_END_INCLUDE_NAMESPACE #include +#include + QT_BEGIN_NAMESPACE #define QEGL_NO_CONFIG ((EGLConfig)-1) + + class QEglProperties; namespace QEgl { @@ -116,12 +120,14 @@ namespace QEgl { BestPixelFormat }; - enum ConfigOptions + enum ConfigOption { NoOptions = 0, Translucent = 0x01, Renderable = 0x02 // Config will be compatable with the paint engines (VG or GL) }; + Q_DECLARE_FLAGS(ConfigOptions, ConfigOption); + // Most of the time we use the same config for things like widgets & pixmaps, so rather than // go through the eglChooseConfig loop every time, we use defaultConfig, which will return @@ -153,6 +159,7 @@ namespace QEgl { #endif }; +Q_DECLARE_OPERATORS_FOR_FLAGS(QEgl::ConfigOptions); QT_END_NAMESPACE -- cgit v0.12 From ee07fff45d49e69d9a4f4474861a219af8d557f2 Mon Sep 17 00:00:00 2001 From: Tom Cooksey Date: Fri, 5 Mar 2010 16:59:06 +0100 Subject: Make QEgl::createSurface store the surface in the pixmapdata too This means the same surface can then later be used to bind the pixmap as a texture using eglBindTexImage2D. Reviewed-By: TrustMe --- src/gui/egl/qegl_x11.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/gui/egl/qegl_x11.cpp b/src/gui/egl/qegl_x11.cpp index 483c01d..8608523 100644 --- a/src/gui/egl/qegl_x11.cpp +++ b/src/gui/egl/qegl_x11.cpp @@ -404,9 +404,11 @@ EGLSurface QEgl::createSurface(QPaintDevice *device, EGLConfig config, const QEg else surfaceAttribs.setValue(EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGB); - return eglCreatePixmapSurface(QEgl::display(), config, - (EGLNativePixmapType) x11PixmapData->handle(), - surfaceAttribs.properties()); + EGLSurface surf = eglCreatePixmapSurface(QEgl::display(), config, + (EGLNativePixmapType) x11PixmapData->handle(), + surfaceAttribs.properties()); + x11PixmapData->gl_surface = (Qt::HANDLE)surf; + return surf; } return EGL_NO_SURFACE; -- cgit v0.12 From 7d587efef35b3adbb3433a4baec1c5ee7105cf0b Mon Sep 17 00:00:00 2001 From: Tom Cooksey Date: Fri, 5 Mar 2010 17:29:53 +0100 Subject: Port QX11GLPixmapData & QX11GLWindowSurface to new QEgl API It's still just as buggy, but at least it allows us to remove a lot of crud from qgl_x11egl.cpp. Reviewed-By: TrustMe --- src/opengl/qgl_egl.cpp | 15 ++-- src/opengl/qgl_x11egl.cpp | 107 --------------------------- src/opengl/qgraphicssystem_gl.cpp | 1 - src/opengl/qpixmapdata_x11gl_egl.cpp | 138 ++++++++++++++--------------------- src/opengl/qpixmapdata_x11gl_p.h | 9 +++ 5 files changed, 74 insertions(+), 196 deletions(-) diff --git a/src/opengl/qgl_egl.cpp b/src/opengl/qgl_egl.cpp index 7bfcf27..91b271b 100644 --- a/src/opengl/qgl_egl.cpp +++ b/src/opengl/qgl_egl.cpp @@ -210,23 +210,26 @@ void QGLContextPrivate::destroyEglSurfaceForDevice() EGLSurface QGLContextPrivate::eglSurfaceForDevice() const { - if (paintDevice->devType() == QInternal::Widget) + // If a QPixmapData had to create the QGLContext, we don't have a paintDevice + if (!paintDevice) return eglSurface; - if (paintDevice->devType() == QInternal::Pixmap) { + #ifdef Q_WS_X11 + if (paintDevice->devType() == QInternal::Pixmap) { QPixmapData *pmd = static_cast(paintDevice)->data_ptr().data(); if (pmd->classId() == QPixmapData::X11Class) { QX11PixmapData* x11PixmapData = static_cast(pmd); return (EGLSurface)x11PixmapData->gl_surface; - } else -#endif - return eglSurface; + } } +#endif + if (paintDevice->devType() == QInternal::Pbuffer) { QGLPixelBuffer* pbuf = static_cast(paintDevice); return pbuf->d_func()->pbuf; } - return EGL_NO_SURFACE; + + return eglSurface; } void QGLWidget::setMouseTracking(bool enable) diff --git a/src/opengl/qgl_x11egl.cpp b/src/opengl/qgl_x11egl.cpp index 123bbdd..5ffecc5 100644 --- a/src/opengl/qgl_x11egl.cpp +++ b/src/opengl/qgl_x11egl.cpp @@ -358,113 +358,6 @@ void QGLWidgetPrivate::recreateEglSurface(bool force) } } -// Selects which configs should be used -EGLConfig Q_OPENGL_EXPORT qt_chooseEGLConfigForPixmap(bool hasAlpha, bool readOnly) -{ - // Cache the configs we select as they wont change: - static EGLConfig roPixmapRGBConfig = 0; - static EGLConfig roPixmapRGBAConfig = 0; - static EGLConfig rwPixmapRGBConfig = 0; - static EGLConfig rwPixmapRGBAConfig = 0; - - EGLConfig* targetConfig; - - if (hasAlpha) { - if (readOnly) - targetConfig = &roPixmapRGBAConfig; - else - targetConfig = &rwPixmapRGBAConfig; - } - else { - if (readOnly) - targetConfig = &roPixmapRGBConfig; - else - targetConfig = &rwPixmapRGBConfig; - } - - if (*targetConfig == 0) { - QEglProperties configAttribs; - configAttribs.setValue(EGL_SURFACE_TYPE, EGL_PIXMAP_BIT); - configAttribs.setRenderableType(QEgl::OpenGL); - if (hasAlpha) - configAttribs.setValue(EGL_BIND_TO_TEXTURE_RGBA, EGL_TRUE); - else - configAttribs.setValue(EGL_BIND_TO_TEXTURE_RGB, EGL_TRUE); - - // If this is going to be a render target, it needs to have a depth, stencil & sample buffer - if (!readOnly) { - configAttribs.setValue(EGL_DEPTH_SIZE, 1); - configAttribs.setValue(EGL_STENCIL_SIZE, 1); - configAttribs.setValue(EGL_SAMPLE_BUFFERS, 1); - } - - EGLint configCount = 0; - do { - eglChooseConfig(QEgl::display(), configAttribs.properties(), targetConfig, 1, &configCount); - if (configCount > 0) { - // Got one - qDebug() << "Found an" << (hasAlpha ? "ARGB" : "RGB") << (readOnly ? "readonly" : "target" ) - << "config to create a pixmap surface:"; - -// QEglProperties configProps(*targetConfig); -// qDebug() << configProps.toString(); - break; - } - qWarning("choosePixmapConfig() - No suitible config found, reducing requirements"); - } while (configAttribs.reduceConfiguration()); - } - - if (*targetConfig == 0) - qWarning("choosePixmapConfig() - Couldn't find a suitable config"); - - return *targetConfig; -} - -bool Q_OPENGL_EXPORT qt_createEGLSurfaceForPixmap(QPixmapData* pmd, bool readOnly) -{ - Q_ASSERT(pmd->classId() == QPixmapData::X11Class); - QX11PixmapData* pixmapData = static_cast(pmd); - - bool hasAlpha = pixmapData->hasAlphaChannel(); - - EGLConfig pixmapConfig = qt_chooseEGLConfigForPixmap(hasAlpha, readOnly); - - QEglProperties pixmapAttribs; - - // If the pixmap can't be bound to a texture, it's pretty useless - pixmapAttribs.setValue(EGL_TEXTURE_TARGET, EGL_TEXTURE_2D); - if (hasAlpha) - pixmapAttribs.setValue(EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGBA); - else - pixmapAttribs.setValue(EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGB); - - EGLSurface pixmapSurface; - pixmapSurface = eglCreatePixmapSurface(QEgl::display(), - pixmapConfig, - (EGLNativePixmapType) pixmapData->handle(), - pixmapAttribs.properties()); -// qDebug("qt_createEGLSurfaceForPixmap() created surface 0x%x for pixmap 0x%x", -// pixmapSurface, pixmapData->handle()); - if (pixmapSurface == EGL_NO_SURFACE) { - qWarning() << "Failed to create a pixmap surface:" << QEgl::errorString(); - return false; - } - - static bool doneOnce = false; - if (!doneOnce) { - // Make sure QGLTextureCache is instanciated so it can install cleanup hooks - // which cleanup the EGL surface. - QGLTextureCache::instance(); - doneOnce = true; - } - - Q_ASSERT(sizeof(Qt::HANDLE) >= sizeof(EGLSurface)); // Just to make totally sure! - pixmapData->gl_surface = (Qt::HANDLE)pixmapSurface; - QImagePixmapCleanupHooks::enableCleanupHooks(pixmapData); // Make sure the cleanup hook gets called - - return true; -} - QGLTexture *QGLContextPrivate::bindTextureFromNativePixmap(QPixmapData* pd, const qint64 key, QGLContext::BindOptions options) diff --git a/src/opengl/qgraphicssystem_gl.cpp b/src/opengl/qgraphicssystem_gl.cpp index 3a399ae..a282e4c 100644 --- a/src/opengl/qgraphicssystem_gl.cpp +++ b/src/opengl/qgraphicssystem_gl.cpp @@ -62,7 +62,6 @@ QPixmapData *QGLGraphicsSystem::createPixmapData(QPixmapData::PixelType type) co if (type == QPixmapData::PixmapType && QX11GLPixmapData::hasX11GLPixmaps()) return new QX11GLPixmapData(); #endif - return new QGLPixmapData(type); } diff --git a/src/opengl/qpixmapdata_x11gl_egl.cpp b/src/opengl/qpixmapdata_x11gl_egl.cpp index 811e554..34915f5 100644 --- a/src/opengl/qpixmapdata_x11gl_egl.cpp +++ b/src/opengl/qpixmapdata_x11gl_egl.cpp @@ -58,13 +58,12 @@ QT_BEGIN_NAMESPACE -extern EGLConfig qt_chooseEGLConfigForPixmap(bool hasAlpha, bool readOnly); // in qgl_x11egl.cpp -extern bool qt_createEGLSurfaceForPixmap(QPixmapData* pmd, bool readOnly); // in qgl_x11egl.cpp // On 16bpp systems, RGB & ARGB pixmaps are different bit-depths and therefore need // different contexts: -static EGLContext qPixmapARGBSharedEglContext = EGL_NO_CONTEXT; -static EGLContext qPixmapRGBSharedEglContext = EGL_NO_CONTEXT; +QEglContext* QX11GLPixmapData::rgbContext = 0; +QEglContext* QX11GLPixmapData::argbContext = 0; + bool QX11GLPixmapData::hasX11GLPixmaps() { @@ -76,68 +75,64 @@ bool QX11GLPixmapData::hasX11GLPixmaps() checkedForX11Pixmaps = true; - QX11PixmapData *argbPixmapData = 0; - QX11PixmapData *rgbPixmapData = 0; do { if (qgetenv("QT_USE_X11GL_PIXMAPS").isEmpty()) break; - // Check we actually have EGL configs which support pixmaps - EGLConfig argbConfig = qt_chooseEGLConfigForPixmap(true, false); - EGLConfig rgbConfig = qt_chooseEGLConfigForPixmap(false, false); + EGLConfig rgbConfig = QEgl::defaultConfig(QInternal::Pixmap, QEgl::OpenGL, QEgl::Renderable); + EGLConfig argbConfig = QEgl::defaultConfig(QInternal::Pixmap, QEgl::OpenGL, + QEgl::Renderable | QEgl::Translucent); + + if (!rgbContext) { + rgbContext = new QEglContext; + rgbContext->setConfig(rgbConfig); + rgbContext->createContext(); + } - if (argbConfig == 0 || rgbConfig == 0) + if (!rgbContext->isValid()) break; - // Create the shared contexts: - eglBindAPI(EGL_OPENGL_ES_API); - EGLint contextAttribs[] = { -#if defined(QT_OPENGL_ES_2) - EGL_CONTEXT_CLIENT_VERSION, 2, -#endif - EGL_NONE - }; - qPixmapARGBSharedEglContext = eglCreateContext(QEgl::display(), - argbConfig, 0, contextAttribs); - - if (argbConfig == rgbConfig) { - // If the configs are the same, we can re-use the same context. - qPixmapRGBSharedEglContext = qPixmapARGBSharedEglContext; - } else { - qPixmapRGBSharedEglContext = eglCreateContext(QEgl::display(), - rgbConfig, 0, contextAttribs); - } + // If the configs are the same, use the same egl contexts: + if (rgbConfig == argbConfig) + argbContext = rgbContext; - argbPixmapData = new QX11PixmapData(QPixmapData::PixmapType); - argbPixmapData->resize(100, 100); - argbPixmapData->fill(Qt::transparent); // Force ARGB + if (!argbContext) { + argbContext = new QEglContext; + argbContext->setConfig(argbConfig); + argbContext->createContext(); + } - if (!qt_createEGLSurfaceForPixmap(argbPixmapData, false)) + if (!argbContext->isValid()) break; - haveX11Pixmaps = eglMakeCurrent(QEgl::display(), - (EGLSurface)argbPixmapData->gl_surface, - (EGLSurface)argbPixmapData->gl_surface, - qPixmapARGBSharedEglContext); + { + 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); + } + if (!haveX11Pixmaps) { - qWarning() << "Unable to make pixmap config current:" << QEgl::errorString(); + qWarning() << "Unable to make pixmap surface current:" << QEgl::errorString(); break; } - // If the ARGB & RGB configs are the same, we don't need to check RGB too - if (haveX11Pixmaps && (argbConfig != rgbConfig)) { - rgbPixmapData = new QX11PixmapData(QPixmapData::PixmapType); + // 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); - // Try to actually create an EGL pixmap surface - if (!qt_createEGLSurfaceForPixmap(rgbPixmapData, false)) - break; + QPixmap rgbPixmap(rgbPixmapData); + EGLSurface rgbPixmapSurface = QEgl::createSurface(&rgbPixmap, rgbConfig); + haveX11Pixmaps = rgbContext->makeCurrent(rgbPixmapSurface); + rgbContext->doneCurrent(); + eglDestroySurface(QEgl::display(), rgbPixmapSurface); - haveX11Pixmaps = eglMakeCurrent(QEgl::display(), - (EGLSurface)rgbPixmapData->gl_surface, - (EGLSurface)rgbPixmapData->gl_surface, - qPixmapRGBSharedEglContext); if (!haveX11Pixmaps) { qWarning() << "Unable to make pixmap config current:" << QEgl::errorString(); break; @@ -145,36 +140,15 @@ bool QX11GLPixmapData::hasX11GLPixmaps() } } while (0); - if (qPixmapARGBSharedEglContext || qPixmapRGBSharedEglContext) { - eglMakeCurrent(QEgl::display(), - EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); - } - - if (argbPixmapData) { - if (argbPixmapData->gl_surface) - QGLContextPrivate::destroyGlSurfaceForPixmap(argbPixmapData); - delete argbPixmapData; - argbPixmapData = 0; - } - if (rgbPixmapData) { - if (rgbPixmapData->gl_surface) - QGLContextPrivate::destroyGlSurfaceForPixmap(rgbPixmapData); - delete rgbPixmapData; - rgbPixmapData = 0; - } - if (!haveX11Pixmaps) { - // Clean up the context(s) if we can't use X11GL pixmaps - if (qPixmapARGBSharedEglContext != EGL_NO_CONTEXT) - eglDestroyContext(QEgl::display(), qPixmapARGBSharedEglContext); - - if (qPixmapRGBSharedEglContext != qPixmapARGBSharedEglContext && - qPixmapRGBSharedEglContext != EGL_NO_CONTEXT) - { - eglDestroyContext(QEgl::display(), qPixmapRGBSharedEglContext); + if (argbContext && (argbContext != rgbContext)) { + delete argbContext; + argbContext = 0; + } + if (rgbContext) { + delete rgbContext; + rgbContext = 0; } - qPixmapRGBSharedEglContext = EGL_NO_CONTEXT; - qPixmapARGBSharedEglContext = EGL_NO_CONTEXT; } if (haveX11Pixmaps) @@ -209,11 +183,8 @@ QPaintEngine* QX11GLPixmapData::paintEngine() const // We need to create the context before beginPaint - do it here: if (!ctx) { ctx = new QGLContext(glFormat()); - if (ctx->d_func()->eglContext == 0) - ctx->d_func()->eglContext = new QEglContext(); - ctx->d_func()->eglContext->setApi(QEgl::OpenGL); - ctx->d_func()->eglContext->setContext(hasAlphaChannel() ? qPixmapARGBSharedEglContext - : qPixmapRGBSharedEglContext); + Q_ASSERT(ctx->d_func()->eglContext == 0); + ctx->d_func()->eglContext = hasAlphaChannel() ? argbContext : rgbContext; } QPaintEngine* engine; @@ -256,10 +227,13 @@ QPaintEngine* QX11GLPixmapData::paintEngine() const void QX11GLPixmapData::beginPaint() { // qDebug("QX11GLPixmapData::beginPaint()"); + // TODO: Check to see if the surface is renderable if ((EGLSurface)gl_surface == EGL_NO_SURFACE) { - qt_createEGLSurfaceForPixmap(this, false); + QPixmap tmpPixmap(this); + EGLConfig cfg = ctx->d_func()->eglContext->config(); + gl_surface = (Qt::HANDLE)QEgl::createSurface(&tmpPixmap, cfg); ctx->d_func()->eglSurface = (EGLSurface)gl_surface; - ctx->d_func()->valid = true; // ;-) + ctx->d_func()->valid = true; } QGLPaintDevice::beginPaint(); } diff --git a/src/opengl/qpixmapdata_x11gl_p.h b/src/opengl/qpixmapdata_x11gl_p.h index c9f4f56..83cd780 100644 --- a/src/opengl/qpixmapdata_x11gl_p.h +++ b/src/opengl/qpixmapdata_x11gl_p.h @@ -59,6 +59,10 @@ #include +#ifndef QT_NO_EGL +#include +#endif + QT_BEGIN_NAMESPACE class QX11GLPixmapData : public QX11PixmapData, public QGLPaintDevice @@ -76,6 +80,11 @@ public: static bool hasX11GLPixmaps(); static QGLFormat glFormat(); + +#ifndef QT_NO_EGL + static QEglContext* rgbContext; + static QEglContext* argbContext; +#endif private: mutable QGLContext* ctx; }; -- cgit v0.12