From 71abe300263d9f6bcd6e061e889a58111c48f92a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Lind?= Date: Fri, 26 Nov 2010 15:59:30 +0100 Subject: Make QtOpenGL use shared contextexts on Lighthouse --- src/gui/kernel/qplatformglcontext_qpa.cpp | 6 ++++- src/gui/kernel/qwidget_qpa.cpp | 24 ++++++++++---------- src/opengl/qgl.cpp | 24 +++++++++++--------- src/opengl/qgl_qpa.cpp | 33 +++++++++++++++++++++------- src/opengl/qglpixmapfilter.cpp | 2 +- src/opengl/qpixmapdata_gl.cpp | 30 ++++++++++++------------- src/opengl/qwindowsurface_gl.cpp | 32 +++++++++++++++++++++++++-- src/opengl/qwindowsurface_gl_p.h | 4 ++++ src/plugins/platforms/eglfs/qeglfsscreen.cpp | 4 +++- 9 files changed, 110 insertions(+), 49 deletions(-) diff --git a/src/gui/kernel/qplatformglcontext_qpa.cpp b/src/gui/kernel/qplatformglcontext_qpa.cpp index 5d2faf1..14bd718 100644 --- a/src/gui/kernel/qplatformglcontext_qpa.cpp +++ b/src/gui/kernel/qplatformglcontext_qpa.cpp @@ -180,7 +180,11 @@ void QPlatformGLContext::setQGLContextHandle(void *handle,void (*qGLContextDelet void QPlatformGLContext::deleteQGLContext() { Q_D(QPlatformGLContext); - d->qGLContextDeleteFunction(d->qGLContextHandle); + if (d->qGLContextDeleteFunction && d->qGLContextHandle) { + d->qGLContextDeleteFunction(d->qGLContextHandle); + d->qGLContextDeleteFunction = 0; + d->qGLContextHandle = 0; + } } /*! diff --git a/src/gui/kernel/qwidget_qpa.cpp b/src/gui/kernel/qwidget_qpa.cpp index aa6b3f8..1f2a764 100644 --- a/src/gui/kernel/qwidget_qpa.cpp +++ b/src/gui/kernel/qwidget_qpa.cpp @@ -98,10 +98,12 @@ void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyO } Q_ASSERT(platformWindow); - if (!surface && platformWindow && q->platformWindowFormat().hasWindowSurface()) { - surface = QApplicationPrivate::platformIntegration()->createWindowSurface(q,platformWindow->winId()); - } else { - q->setAttribute(Qt::WA_PaintOnScreen,true); + if (!surface ) { + if (platformWindow && q->platformWindowFormat().hasWindowSurface()) { + surface = QApplicationPrivate::platformIntegration()->createWindowSurface(q,platformWindow->winId()); + } else { + q->setAttribute(Qt::WA_PaintOnScreen,true); + } } data.window_flags = q->platformWindow()->setWindowFlags(data.window_flags); @@ -787,13 +789,13 @@ void QWidgetPrivate::createTLSysExtra() void QWidgetPrivate::deleteTLSysExtra() { if (extra && extra->topextra) { - if (extra->topextra->platformWindowFormat.windowApi() == QPlatformWindowFormat::OpenGL) { - //the toplevel might have a context with a "qglcontext assosiated with it. We need to - //delete the qglcontext before we delete the qplatformglcontext. - if (extra->topextra->platformWindow) { - if (QPlatformGLContext *context = extra->topextra->platformWindow->glContext()) { - context->deleteQGLContext(); - } + //the toplevel might have a context with a "qglcontext assosiated with it. We need to + //delete the qglcontext before we delete the qplatformglcontext. + //One unfortunate thing about this is that we potentially create a glContext just to + //delete it straight afterwards. + if (extra->topextra->platformWindow) { + if (QPlatformGLContext *context = extra->topextra->platformWindow->glContext()) { + context->deleteQGLContext(); } } delete extra->topextra->platformWindow; diff --git a/src/opengl/qgl.cpp b/src/opengl/qgl.cpp index 111a3e4..dc7a333 100644 --- a/src/opengl/qgl.cpp +++ b/src/opengl/qgl.cpp @@ -2095,14 +2095,6 @@ QGLContext::QGLContext(const QGLFormat &format) d->init(0, format); } -QGLContext::QGLContext(QPlatformGLContext *platformContext) - : d_ptr(new QGLContextPrivate(this)) -{ - Q_D(QGLContext); - d->init(0,QGLFormat::fromPlatformWindowFormat(platformContext->platformWindowFormat())); - d->platformContext = platformContext; -} - /*! Destroys the OpenGL context and frees its resources. */ @@ -3788,7 +3780,13 @@ QGLWidget::QGLWidget(QWidget *parent, const QGLWidget* shareWidget, Qt::WindowFl setAttribute(Qt::WA_NoSystemBackground); setAutoFillBackground(true); // for compatibility #ifdef Q_WS_QPA - setPlatformWindowFormat(QGLFormat::toPlatformWindowFormat(QGLFormat::defaultFormat())); + QPlatformWindowFormat platformFormat = QGLFormat::toPlatformWindowFormat(QGLFormat::defaultFormat()); + platformFormat.setUseDefaultSharedContext(false); + if (shareWidget && shareWidget->d_func()->glcx) { + QPlatformGLContext *sharedPlatformContext = shareWidget->d_func()->glcx->d_func()->platformContext; + platformFormat.setSharedContext(sharedPlatformContext); + } + setPlatformWindowFormat(platformFormat); winId(); // create window; QGLContext *glContext = 0; if (platformWindow()) @@ -3839,7 +3837,13 @@ QGLWidget::QGLWidget(const QGLFormat &format, QWidget *parent, const QGLWidget* setAttribute(Qt::WA_NoSystemBackground); setAutoFillBackground(true); // for compatibility #ifdef Q_WS_QPA - setPlatformWindowFormat(QGLFormat::toPlatformWindowFormat(QGLFormat::defaultFormat())); + QPlatformWindowFormat platformFormat = QGLFormat::toPlatformWindowFormat(format); + platformFormat.setUseDefaultSharedContext(false); + if (shareWidget && shareWidget->d_func()->glcx) { + QPlatformGLContext *sharedPlatformContext = shareWidget->d_func()->glcx->d_func()->platformContext; + platformFormat.setSharedContext(sharedPlatformContext); + } + setPlatformWindowFormat(platformFormat); winId(); // create window; QGLContext *glContext = 0; if (platformWindow()) diff --git a/src/opengl/qgl_qpa.cpp b/src/opengl/qgl_qpa.cpp index d45f246..415e915 100644 --- a/src/opengl/qgl_qpa.cpp +++ b/src/opengl/qgl_qpa.cpp @@ -129,11 +129,7 @@ void qDeleteQGLContext(void *handle) bool QGLContext::chooseContext(const QGLContext* shareContext) { Q_D(QGLContext); - if (d->platformContext && !d->platformContext->qGLContextHandle()) { - d->platformContext->setQGLContextHandle(this,qDeleteQGLContext); - d->glFormat = QGLFormat::fromPlatformWindowFormat(d->platformContext->platformWindowFormat()); - d->valid = true; - }else if(!d->paintDevice || d->paintDevice->devType() != QInternal::Widget) { + if(!d->paintDevice || d->paintDevice->devType() != QInternal::Widget) { d->valid = false; }else { QWidget *widget = static_cast(d->paintDevice); @@ -157,6 +153,18 @@ bool QGLContext::chooseContext(const QGLContext* shareContext) } } + if (d->valid) { + QPlatformGLContext *sharedPlatformGLContext = d->platformContext->platformWindowFormat().sharedGLContext(); + if (sharedPlatformGLContext) { + QGLContext *actualSharedContext = QGLContext::fromPlatformGLContext(sharedPlatformGLContext); + if (actualSharedContext == shareContext) { + d->sharing = true;//Will add combination in QGLContext::create + }else { + QGLContextGroup::addShare(this,actualSharedContext); + } + } + } + return d->valid; } @@ -173,13 +181,15 @@ void QGLContext::reset() d->transpColor = QColor(); d->initDone = false; QGLContextGroup::removeShare(this); + if (d->platformContext) { + d->platformContext->setQGLContextHandle(0,0); + } } void QGLContext::makeCurrent() { Q_D(QGLContext); d->platformContext->makeCurrent(); - QGLContextPrivate::setCurrentContext(this); if (!d->workaroundsCached) { d->workaroundsCached = true; @@ -195,7 +205,6 @@ void QGLContext::doneCurrent() { Q_D(QGLContext); d->platformContext->doneCurrent(); - QGLContextPrivate::setCurrentContext(0); } void QGLContext::swapBuffers() const @@ -279,6 +288,8 @@ QGLTemporaryContext::QGLTemporaryContext(bool, QWidget *) d->widget->setGeometry(0,0,3,3); QPlatformWindowFormat format = d->widget->platformWindowFormat(); format.setWindowApi(QPlatformWindowFormat::OpenGL); + format.setWindowSurface(false); + d->widget->setPlatformWindowFormat(format); d->widget->winId(); d->widget->platformWindow()->glContext()->makeCurrent(); @@ -360,6 +371,13 @@ void QGLWidget::setColormap(const QGLColormap & c) Q_UNUSED(c); } +QGLContext::QGLContext(QPlatformGLContext *platformContext) + : d_ptr(new QGLContextPrivate(this)) +{ + Q_D(QGLContext); + d->init(0,QGLFormat::fromPlatformWindowFormat(platformContext->platformWindowFormat())); + d->platformContext = platformContext; +} QGLContext *QGLContext::fromPlatformGLContext(QPlatformGLContext *platformContext) { @@ -379,5 +397,4 @@ QGLContext *QGLContext::fromPlatformGLContext(QPlatformGLContext *platformContex return glContext; } - QT_END_NAMESPACE diff --git a/src/opengl/qglpixmapfilter.cpp b/src/opengl/qglpixmapfilter.cpp index 73d698c..6c20aae 100644 --- a/src/opengl/qglpixmapfilter.cpp +++ b/src/opengl/qglpixmapfilter.cpp @@ -125,7 +125,7 @@ protected: bool processGL(QPainter *painter, const QPointF &pos, const QPixmap &src, const QRectF &srcRect) const; }; -extern QGLWidget *qt_gl_share_widget(); +extern const QGLContext *qt_gl_share_context(); QPixmapFilter *QGL2PaintEngineEx::pixmapFilter(int type, const QPixmapFilter *prototype) { diff --git a/src/opengl/qpixmapdata_gl.cpp b/src/opengl/qpixmapdata_gl.cpp index cd7f0c2..1cf5bd7 100644 --- a/src/opengl/qpixmapdata_gl.cpp +++ b/src/opengl/qpixmapdata_gl.cpp @@ -58,7 +58,7 @@ QT_BEGIN_NAMESPACE -extern QGLWidget* qt_gl_share_widget(); +extern const QGLContext* qt_gl_share_context(); /*! \class QGLFramebufferObjectPool @@ -261,14 +261,14 @@ QGLPixmapData::QGLPixmapData(PixelType type) QGLPixmapData::~QGLPixmapData() { - QGLWidget *shareWidget = qt_gl_share_widget(); - if (!shareWidget) + const QGLContext *shareContext = qt_gl_share_context(); + if (!shareContext) return; delete m_engine; if (m_texture.id) { - QGLShareContextScope ctx(shareWidget->context()); + QGLShareContextScope ctx(shareContext); glDeleteTextures(1, &m_texture.id); } } @@ -288,7 +288,7 @@ bool QGLPixmapData::isValidContext(const QGLContext *ctx) const if (ctx == m_ctx) return true; - const QGLContext *share_ctx = qt_gl_share_widget()->context(); + const QGLContext *share_ctx = qt_gl_share_context(); return ctx == share_ctx || QGLContext::areSharing(ctx, share_ctx); } @@ -308,7 +308,7 @@ void QGLPixmapData::resize(int width, int height) d = pixelType() == QPixmapData::PixmapType ? 32 : 1; if (m_texture.id) { - QGLShareContextScope ctx(qt_gl_share_widget()->context()); + QGLShareContextScope ctx(qt_gl_share_context()); glDeleteTextures(1, &m_texture.id); m_texture.id = 0; } @@ -325,7 +325,7 @@ void QGLPixmapData::ensureCreated() const m_dirty = false; - QGLShareContextScope ctx(qt_gl_share_widget()->context()); + QGLShareContextScope ctx(qt_gl_share_context()); m_ctx = ctx; const GLenum internal_format = m_hasAlpha ? GL_RGBA : GL_RGB; @@ -399,7 +399,7 @@ void QGLPixmapData::fromImage(const QImage &image, d = m_source.depth(); if (m_texture.id) { - QGLShareContextScope ctx(qt_gl_share_widget()->context()); + QGLShareContextScope ctx(qt_gl_share_context()); glDeleteTextures(1, &m_texture.id); m_texture.id = 0; } @@ -420,7 +420,7 @@ bool QGLPixmapData::fromFile(const QString &filename, const char *format, resize(0, 0); data = file.readAll(); file.close(); - QGLShareContextScope ctx(qt_gl_share_widget()->context()); + QGLShareContextScope ctx(qt_gl_share_context()); QSize size = m_texture.bindCompressedTexture (data.constData(), data.size(), format); if (!size.isEmpty()) { @@ -446,7 +446,7 @@ bool QGLPixmapData::fromData(const uchar *buffer, uint len, const char *format, const char *buf = reinterpret_cast(buffer); if (m_texture.canBindCompressedTexture(buf, int(len), format, &alpha)) { resize(0, 0); - QGLShareContextScope ctx(qt_gl_share_widget()->context()); + QGLShareContextScope ctx(qt_gl_share_context()); QSize size = m_texture.bindCompressedTexture(buf, int(len), format); if (!size.isEmpty()) { w = size.width(); @@ -479,7 +479,7 @@ void QGLPixmapData::copy(const QPixmapData *data, const QRect &rect) const QGLPixmapData *other = static_cast(data); if (other->m_renderFbo) { - QGLShareContextScope ctx(qt_gl_share_widget()->context()); + QGLShareContextScope ctx(qt_gl_share_context()); resize(rect.width(), rect.height()); m_hasAlpha = other->m_hasAlpha; @@ -593,7 +593,7 @@ QImage QGLPixmapData::toImage() const ensureCreated(); } - QGLShareContextScope ctx(qt_gl_share_widget()->context()); + QGLShareContextScope ctx(qt_gl_share_context()); glBindTexture(GL_TEXTURE_2D, m_texture.id); return qt_gl_read_texture(QSize(w, h), true, true); } @@ -617,7 +617,7 @@ void QGLPixmapData::copyBackFromRenderFbo(bool keepCurrentFboBound) const m_hasFillColor = false; - const QGLContext *share_ctx = qt_gl_share_widget()->context(); + const QGLContext *share_ctx = qt_gl_share_context(); QGLShareContextScope ctx(share_ctx); ensureCreated(); @@ -672,8 +672,8 @@ QPaintEngine* QGLPixmapData::paintEngine() const extern QGLWidget* qt_gl_share_widget(); if (!QGLContext::currentContext()) - qt_gl_share_widget()->makeCurrent(); - QGLShareContextScope ctx(qt_gl_share_widget()->context()); + const_cast(qt_gl_share_context())->makeCurrent(); + QGLShareContextScope ctx(qt_gl_share_context()); QGLFramebufferObjectFormat format; format.setAttachment(QGLFramebufferObject::CombinedDepthStencil); diff --git a/src/opengl/qwindowsurface_gl.cpp b/src/opengl/qwindowsurface_gl.cpp index 47f36dd..cd7558c 100644 --- a/src/opengl/qwindowsurface_gl.cpp +++ b/src/opengl/qwindowsurface_gl.cpp @@ -182,6 +182,7 @@ QGLGraphicsSystem::QGLGraphicsSystem(bool useX11GL) // QGLWindowSurface // +#ifndef Q_WS_QPA class QGLGlobalShareWidget { public: @@ -255,6 +256,23 @@ void qt_destroy_gl_share_widget() { _qt_gl_share_widget()->destroy(); } +#endif//Q_WS_QPA + +const QGLContext *qt_gl_share_context() +{ +#ifdef Q_WS_QPA + //make it possible to have an assesor to defaultSharedGLContext. + const QPlatformGLContext *platformContext = QPlatformGLContext::defaultSharedContext(); + if (!platformContext) + qDebug() << "Please implement a defaultSharedContext for your platformplugin"; + return QGLContext::fromPlatformGLContext(const_cast(platformContext)); +#else + QGLWidget *widget = qt_gl_share_widget(); + if (widget) + return widget->context(); + return 0; +#endif +} struct QGLWindowSurfacePrivate { @@ -336,10 +354,12 @@ QGLWindowSurface::~QGLWindowSurface() { if (d_ptr->ctx) glDeleteTextures(1, &d_ptr->tex_id); +#ifndef Q_WS_QPA // Dont delete the contexts. Destroying the window does that for us foreach(QGLContext **ctx, d_ptr->contexts) { delete *ctx; *ctx = 0; } +#endif delete d_ptr->pb; delete d_ptr->fbo; @@ -356,6 +376,7 @@ void QGLWindowSurface::deleted(QObject *object) d_ptr->fbo = 0; } +#ifndef Q_WS_QPA //no need to specifically delete the QGLContext as it will be deleted by QWidget QWidgetPrivate *widgetPrivate = widget->d_func(); if (widgetPrivate->extraData()) { union { QGLContext **ctxPtrPtr; void **voidPtrPtr; }; @@ -367,6 +388,7 @@ void QGLWindowSurface::deleted(QObject *object) d_ptr->contexts.removeAt(index); } } +#endif } } @@ -377,8 +399,14 @@ void QGLWindowSurface::hijackWindow(QWidget *widget) if (widgetPrivate->extraData()->glContext) return; +#ifdef Q_WS_QPA + QGLContext *ctx = QGLContext::fromPlatformGLContext(widget->platformWindow()->glContext()); + if (!d_ptr->fbo && d_ptr->tried_fbo) + d_ptr->ctx = ctx; +#else QGLContext *ctx = new QGLContext(surfaceFormat, widget); ctx->create(qt_gl_share_widget()->context()); +#endif #ifndef QT_NO_EGL static bool checkedForNOKSwapRegion = false; @@ -816,7 +844,7 @@ void QGLWindowSurface::updateGeometry() { } } -#if !defined(QT_OPENGL_ES_2) +#if !defined(QT_OPENGL_ES_2) && !defined(Q_WS_QPA) //QPA doesn't support pixelbuffers if (d_ptr->destructive_swap_buffers && (d_ptr->pb || !d_ptr->tried_pb)) { d_ptr->tried_pb = true; @@ -855,7 +883,7 @@ void QGLWindowSurface::updateGeometry() { d_ptr->pb = 0; } } -#endif // !defined(QT_OPENGL_ES_2) +#endif // !defined(QT_OPENGL_ES_2) !defined(Q_WS_QPA) ctx->makeCurrent(); diff --git a/src/opengl/qwindowsurface_gl_p.h b/src/opengl/qwindowsurface_gl_p.h index 4f4ec92..22bd5f0 100644 --- a/src/opengl/qwindowsurface_gl_p.h +++ b/src/opengl/qwindowsurface_gl_p.h @@ -66,8 +66,12 @@ class QRegion; class QWidget; struct QGLWindowSurfacePrivate; +#ifdef Q_WS_QPA +Q_OPENGL_EXPORT const QGLContext* qt_gl_share_context(); +#else Q_OPENGL_EXPORT QGLWidget* qt_gl_share_widget(); Q_OPENGL_EXPORT void qt_destroy_gl_share_widget(); +#endif class QGLWindowSurfaceGLPaintDevice : public QGLPaintDevice { diff --git a/src/plugins/platforms/eglfs/qeglfsscreen.cpp b/src/plugins/platforms/eglfs/qeglfsscreen.cpp index 7abc492..cbe6210 100644 --- a/src/plugins/platforms/eglfs/qeglfsscreen.cpp +++ b/src/plugins/platforms/eglfs/qeglfsscreen.cpp @@ -202,7 +202,9 @@ void QEglFSScreen::createAndSetPlatformContext() attribList[temp++] = 2; // GLES version 2 attribList[temp++] = EGL_NONE; - m_platformContext = new QEGLPlatformContext(m_dpy,config,attribList,m_surface,EGL_OPENGL_ES_API); + QEGLPlatformContext *platformContext = new QEGLPlatformContext(m_dpy,config,attribList,m_surface,EGL_OPENGL_ES_API); + platformContext->makeDefaultSaredContext(); + m_platformContext = platformContext; EGLint w,h; // screen size detection eglQuerySurface(m_dpy, m_surface, EGL_WIDTH, &w); -- cgit v0.12