diff options
Diffstat (limited to 'src/opengl')
-rw-r--r-- | src/opengl/qgl.cpp | 58 | ||||
-rw-r--r-- | src/opengl/qgl.h | 15 | ||||
-rw-r--r-- | src/opengl/qgl_qpa.cpp | 93 | ||||
-rw-r--r-- | src/opengl/qglpixmapfilter.cpp | 2 | ||||
-rw-r--r-- | src/opengl/qpixmapdata_gl.cpp | 30 | ||||
-rw-r--r-- | src/opengl/qwindowsurface_gl.cpp | 32 | ||||
-rw-r--r-- | src/opengl/qwindowsurface_gl_p.h | 4 |
7 files changed, 196 insertions, 38 deletions
diff --git a/src/opengl/qgl.cpp b/src/opengl/qgl.cpp index cf45239..dc7a333 100644 --- a/src/opengl/qgl.cpp +++ b/src/opengl/qgl.cpp @@ -79,6 +79,10 @@ #include <private/qglwindowsurface_qws_p.h> #endif +#ifdef Q_WS_QPA +#include <QtGui/QPlatformGLContext> +#endif + #include <qglpixelbuffer.h> #include <qglframebufferobject.h> @@ -117,7 +121,9 @@ struct QGLThreadContext { QGLContext *context; }; +#ifndef Q_WS_QPA static QThreadStorage<QGLThreadContext *> qgl_context_storage; +#endif Q_GLOBAL_STATIC(QGLFormat, qgl_default_format) @@ -3298,11 +3304,16 @@ bool QGLContext::areSharing(const QGLContext *context1, const QGLContext *contex bool QGLContext::create(const QGLContext* shareContext) { Q_D(QGLContext); +#ifdef Q_WS_QPA + if (!d->paintDevice && !d->platformContext) +#else if (!d->paintDevice) +#endif return false; + reset(); d->valid = chooseContext(shareContext); - if (d->valid && d->paintDevice->devType() == QInternal::Widget) { + if (d->valid && d->paintDevice && d->paintDevice->devType() == QInternal::Widget) { QWidgetPrivate *wd = qt_widget_private(static_cast<QWidget *>(d->paintDevice)); wd->usesDoubleBufferedGLContext = d->glFormat.doubleBuffer(); } @@ -3381,14 +3392,24 @@ void QGLContext::setInitialized(bool on) const QGLContext* QGLContext::currentContext() { +#ifdef Q_WS_QPA + if (const QPlatformGLContext *threadContext = QPlatformGLContext::currentContext()) { + return QGLContext::fromPlatformGLContext(const_cast<QPlatformGLContext *>(threadContext)); + } + return 0; +#else QGLThreadContext *threadContext = qgl_context_storage.localData(); if (threadContext) return threadContext->context; return 0; +#endif //Q_WS_QPA } void QGLContextPrivate::setCurrentContext(QGLContext *context) { +#ifdef Q_WS_QPA + Q_UNUSED(context); +#else QGLThreadContext *threadContext = qgl_context_storage.localData(); if (!threadContext) { if (!QThread::currentThread()) { @@ -3401,6 +3422,7 @@ void QGLContextPrivate::setCurrentContext(QGLContext *context) } threadContext->context = context; QGLContext::currentCtx = context; // XXX: backwards-compat, not thread-safe +#endif } /*! @@ -3757,7 +3779,24 @@ QGLWidget::QGLWidget(QWidget *parent, const QGLWidget* shareWidget, Qt::WindowFl setAttribute(Qt::WA_PaintOnScreen); setAttribute(Qt::WA_NoSystemBackground); setAutoFillBackground(true); // for compatibility +#ifdef Q_WS_QPA + 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()) + glContext = QGLContext::fromPlatformGLContext(platformWindow()->glContext()); + if (glContext){ + d->init(glContext,shareWidget); + } +#else d->init(new QGLContext(QGLFormat::defaultFormat(), this), shareWidget); +#endif } @@ -3797,7 +3836,24 @@ QGLWidget::QGLWidget(const QGLFormat &format, QWidget *parent, const QGLWidget* setAttribute(Qt::WA_PaintOnScreen); setAttribute(Qt::WA_NoSystemBackground); setAutoFillBackground(true); // for compatibility +#ifdef Q_WS_QPA + 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()) + glContext = QGLContext::fromPlatformGLContext(platformWindow()->glContext()); + if (glContext){ + d->init(glContext,shareWidget); + } +#else d->init(new QGLContext(format, this), shareWidget); +#endif } /*! diff --git a/src/opengl/qgl.h b/src/opengl/qgl.h index 4f10e5c..ff135fa 100644 --- a/src/opengl/qgl.h +++ b/src/opengl/qgl.h @@ -48,6 +48,10 @@ #include <QtCore/qmap.h> #include <QtCore/qscopedpointer.h> +#ifdef Q_WS_QPA +#include <QtGui/QPlatformWindowFormat> +#endif + QT_BEGIN_HEADER #if defined(Q_WS_WIN) @@ -270,6 +274,10 @@ public: static OpenGLVersionFlags openGLVersionFlags(); +#if defined(Q_WS_QPA) + static QGLFormat fromPlatformWindowFormat(const QPlatformWindowFormat &format); + static QPlatformWindowFormat toPlatformWindowFormat(const QGLFormat &format); +#endif private: QGLFormatPrivate *d; @@ -375,6 +383,9 @@ public: static const QGLContext* currentContext(); +#ifdef Q_WS_QPA + static QGLContext *fromPlatformGLContext(QPlatformGLContext *platformContext); +#endif protected: virtual bool chooseContext(const QGLContext* shareContext = 0); @@ -404,6 +415,10 @@ protected: static QGLContext* currentCtx; private: +#ifdef Q_WS_QPA + QGLContext(QPlatformGLContext *platformContext); +#endif + QScopedPointer<QGLContextPrivate> d_ptr; friend class QGLPixelBuffer; diff --git a/src/opengl/qgl_qpa.cpp b/src/opengl/qgl_qpa.cpp index 49c0860..415e915 100644 --- a/src/opengl/qgl_qpa.cpp +++ b/src/opengl/qgl_qpa.cpp @@ -52,7 +52,7 @@ QT_BEGIN_NAMESPACE -static QGLFormat qt_platformwindowformat_to_glformat(const QPlatformWindowFormat &format) +QGLFormat QGLFormat::fromPlatformWindowFormat(const QPlatformWindowFormat &format) { QGLFormat retFormat; retFormat.setAccum(format.accum()); @@ -83,7 +83,7 @@ static QGLFormat qt_platformwindowformat_to_glformat(const QPlatformWindowFormat return retFormat; } -static QPlatformWindowFormat qt_glformat_to_platformwindowformat(const QGLFormat &format) +QPlatformWindowFormat QGLFormat::toPlatformWindowFormat(const QGLFormat &format) { QPlatformWindowFormat retFormat; retFormat.setAccum(format.accum()); @@ -120,27 +120,49 @@ bool QGLFormat::hasOpenGL() return QApplicationPrivate::platformIntegration()->hasOpenGL(); } +void qDeleteQGLContext(void *handle) +{ + QGLContext *context = static_cast<QGLContext *>(handle); + delete context; +} + bool QGLContext::chooseContext(const QGLContext* shareContext) { Q_D(QGLContext); - if (!d->paintDevice || d->paintDevice->devType() != QInternal::Widget) { + if(!d->paintDevice || d->paintDevice->devType() != QInternal::Widget) { d->valid = false; }else { QWidget *widget = static_cast<QWidget *>(d->paintDevice); if (!widget->platformWindow()){ QGLFormat glformat = format(); - QPlatformWindowFormat winFormat = qt_glformat_to_platformwindowformat(glformat); + QPlatformWindowFormat winFormat = QGLFormat::toPlatformWindowFormat(glformat); if (shareContext) { winFormat.setSharedContext(shareContext->d_func()->platformContext); } winFormat.setWindowApi(QPlatformWindowFormat::OpenGL); + winFormat.setWindowSurface(false); widget->setPlatformWindowFormat(winFormat); widget->winId();//make window } d->platformContext = widget->platformWindow()->glContext(); Q_ASSERT(d->platformContext); - d->glFormat = qt_platformwindowformat_to_glformat(d->platformContext->platformWindowFormat()); + d->glFormat = QGLFormat::fromPlatformWindowFormat(d->platformContext->platformWindowFormat()); d->valid =(bool) d->platformContext; + if (d->valid) { + d->platformContext->setQGLContextHandle(this,qDeleteQGLContext); + } + } + + 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; @@ -159,20 +181,30 @@ 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; + const char *renderer = reinterpret_cast<const char *>(glGetString(GL_RENDERER)); + if (renderer && strstr(renderer, "Mali")) { + d->workaround_brokenFBOReadBack = true; + } + } + } void QGLContext::doneCurrent() { Q_D(QGLContext); d->platformContext->doneCurrent(); - QGLContextPrivate::setCurrentContext(0); } void QGLContext::swapBuffers() const @@ -196,10 +228,9 @@ void QGLWidget::setContext(QGLContext *context, qWarning("QGLWidget::setContext: Cannot set null context"); return; } - if (!context->deviceIsPixmap() && context->device() != this) { - qWarning("QGLWidget::setContext: Context must refer to this widget"); - return; - } + + if (context->device() == 0) // a context may refere to more than 1 window. + context->setDevice(this); //but its better to point to 1 of them than none of them. QGLContext* oldcx = d->glcx; d->glcx = context; @@ -244,22 +275,23 @@ class QGLTemporaryContextPrivate { public: QWidget *widget; - QGLContext *context; + QPlatformGLContext *context; }; QGLTemporaryContext::QGLTemporaryContext(bool, QWidget *) : d(new QGLTemporaryContextPrivate) { - d->context = const_cast<QGLContext *>(QGLContext::currentContext()); + d->context = const_cast<QPlatformGLContext *>(QPlatformGLContext::currentContext()); if (d->context) d->context->doneCurrent(); d->widget = new 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(); } @@ -294,11 +326,8 @@ bool QGLWidget::event(QEvent *e) { Q_D(QGLWidget); if (e->type() == QEvent::WinIdChange) { - if (d->glcx->isValid()) { - if (QGLContext::currentContext() == d->glcx) - QGLContextPrivate::setCurrentContext(0); //Its not valid anymore - setContext(new QGLContext(d->glcx->requestedFormat(), this)); - + if (platformWindow()) { + d->glcx = QGLContext::fromPlatformGLContext(platformWindow()->glContext()); } } return QWidget::event(e); @@ -342,4 +371,30 @@ 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) +{ + if (!platformContext) + return 0; + if (platformContext->qGLContextHandle()) { + return reinterpret_cast<QGLContext *>(platformContext->qGLContextHandle()); + } + QGLContext *glContext = new QGLContext(platformContext); + //Dont call create on context. This can cause the platformFormat to be set on the widget, which + //will cause the platformWindow to be recreated. + glContext->d_func()->platformContext->setQGLContextHandle(glContext,qDeleteQGLContext); + QGLFormat format = QGLFormat::fromPlatformWindowFormat(platformContext->platformWindowFormat()); + glContext->d_func()->glFormat = format; + glContext->d_func()->valid = true; + + 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<const char *>(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<const QGLPixmapData *>(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<QGLContext *>(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<QPlatformGLContext *>(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 { |