diff options
author | Samuel Rødal <samuel.rodal@nokia.com> | 2011-06-07 17:25:22 +0200 |
---|---|---|
committer | Samuel Rødal <samuel.rodal@nokia.com> | 2011-06-10 09:24:56 +0200 |
commit | 4a189c188ccd2fb5f8d1d5ddadf06cbd6bc0916f (patch) | |
tree | 99bff9f015e869b5521836ea5667590939b22a53 /src/opengl/qgl_qpa.cpp | |
parent | 4d10e64f2a78e32418a98e1c80c6579ae0779dfc (diff) |
QWindowContext / QWindowFormat refactor.
To enable having a single GL context used for multiple drawables we need
to de-couple the context class a bit more from the window class in the
plugin API. Now contexts are created stand-alone based on a GL format
and a share context, and when calling makeCurrent() a desired surface
is specified. This maps well to GLX, EGL, Cocoa, AGL, and WGL, which all
support this use case.
QWindowContext is renamed to QGuiGLContext, and QWindowFormat is renamed
to QGuiGLFormat. We have the ability to introduce a pbuffer or similar
other offscreen GL drawable abstraction in the future.
Diffstat (limited to 'src/opengl/qgl_qpa.cpp')
-rw-r--r-- | src/opengl/qgl_qpa.cpp | 123 |
1 files changed, 69 insertions, 54 deletions
diff --git a/src/opengl/qgl_qpa.cpp b/src/opengl/qgl_qpa.cpp index 57c87d1238..cb3032bd59 100644 --- a/src/opengl/qgl_qpa.cpp +++ b/src/opengl/qgl_qpa.cpp @@ -47,7 +47,7 @@ #include <private/qapplication_p.h> #include <QtGui/QPlatformGLContext> #include <QtGui/QPlatformWindow> -#include <QtGui/QWindowContext> +#include <QtGui/QGuiGLFormat> #include "qgl.h" #include "qgl_p.h" @@ -57,7 +57,7 @@ QT_BEGIN_NAMESPACE /*! Returns an OpenGL format for the window format specified by \a format. */ -QGLFormat QGLFormat::fromWindowFormat(const QWindowFormat &format) +QGLFormat QGLFormat::fromGuiGLFormat(const QGuiGLFormat &format) { QGLFormat retFormat; if (format.alphaBufferSize() >= 0) @@ -78,7 +78,7 @@ QGLFormat QGLFormat::fromWindowFormat(const QWindowFormat &format) retFormat.setStencil(true); retFormat.setStencilBufferSize(format.stencilBufferSize()); } - retFormat.setDoubleBuffer(format.swapBehavior() != QWindowFormat::SingleBuffer); + retFormat.setDoubleBuffer(format.swapBehavior() != QGuiGLFormat::SingleBuffer); retFormat.setStereo(format.stereo()); return retFormat; } @@ -86,9 +86,9 @@ QGLFormat QGLFormat::fromWindowFormat(const QWindowFormat &format) /*! Returns a window format for the OpenGL format specified by \a format. */ -QWindowFormat QGLFormat::toWindowFormat(const QGLFormat &format) +QGuiGLFormat QGLFormat::toGuiGLFormat(const QGLFormat &format) { - QWindowFormat retFormat; + QGuiGLFormat retFormat; if (format.alpha()) retFormat.setAlphaBufferSize(format.alphaBufferSize() == -1 ? 1 : format.alphaBufferSize()); if (format.blueBufferSize() >= 0) @@ -99,7 +99,7 @@ QWindowFormat QGLFormat::toWindowFormat(const QGLFormat &format) retFormat.setRedBufferSize(format.redBufferSize()); if (format.depth()) retFormat.setDepthBufferSize(format.depthBufferSize() == -1 ? 1 : format.depthBufferSize()); - retFormat.setSwapBehavior(format.doubleBuffer() ? QWindowFormat::DoubleBuffer : QWindowFormat::DefaultSwapBehavior); + retFormat.setSwapBehavior(format.doubleBuffer() ? QGuiGLFormat::DoubleBuffer : QGuiGLFormat::DefaultSwapBehavior); if (format.sampleBuffers()) retFormat.setSamples(format.samples() == -1 ? 4 : format.samples()); if (format.stencil()) @@ -110,11 +110,11 @@ QWindowFormat QGLFormat::toWindowFormat(const QGLFormat &format) void QGLContextPrivate::setupSharing() { Q_Q(QGLContext); - QWindowContext *sharedContext = windowContext->handle()->windowFormat().sharedContext(); + QGuiGLContext *sharedContext = guiGlContext->shareContext(); if (sharedContext) { - QGLContext *actualSharedContext = QGLContext::fromWindowContext(sharedContext); + QGLContext *actualSharedContext = QGLContext::fromGuiGLContext(sharedContext); sharing = true; - QGLContextGroup::addShare(q,actualSharedContext); + QGLContextGroup::addShare(q, actualSharedContext); } } @@ -137,25 +137,26 @@ bool QGLContext::chooseContext(const QGLContext* shareContext) d->valid = false; }else { QWidget *widget = static_cast<QWidget *>(d->paintDevice); + QGLFormat glformat = format(); + QGuiGLFormat winFormat = QGLFormat::toGuiGLFormat(glformat); + if (widget->testAttribute(Qt::WA_TranslucentBackground)) + winFormat.setAlphaBufferSize(qMax(winFormat.alphaBufferSize(), 8)); + winFormat.setWindowSurface(false); + if (!widget->windowHandle()->handle()) { - QGLFormat glformat = format(); - QWindowFormat winFormat = QGLFormat::toWindowFormat(glformat); - if (shareContext) { - winFormat.setSharedContext(shareContext->d_func()->windowContext); - } widget->windowHandle()->setSurfaceType(QWindow::OpenGLSurface); - if (widget->testAttribute(Qt::WA_TranslucentBackground)) - winFormat.setAlphaBufferSize(qMax(winFormat.alphaBufferSize(), 8)); - winFormat.setWindowSurface(false); - widget->windowHandle()->setWindowFormat(winFormat); + widget->windowHandle()->setGLFormat(winFormat); widget->winId();//make window } - d->windowContext = widget->windowHandle()->glContext(); - Q_ASSERT(d->windowContext); - d->glFormat = QGLFormat::fromWindowFormat(d->windowContext->handle()->windowFormat()); - d->valid =(bool) d->windowContext; + + delete d->guiGlContext; + QGuiGLContext *shareGlContext = shareContext ? shareContext->d_func()->guiGlContext : 0; + d->guiGlContext = new QGuiGLContext(winFormat, shareGlContext); + + d->glFormat = QGLFormat::fromGuiGLFormat(d->guiGlContext->format()); + d->valid = d->guiGlContext->isValid(); if (d->valid) { - d->windowContext->setQGLContextHandle(this,qDeleteQGLContext); + d->guiGlContext->setQGLContextHandle(this,qDeleteQGLContext); } d->setupSharing(); } @@ -177,42 +178,55 @@ void QGLContext::reset() d->transpColor = QColor(); d->initDone = false; QGLContextGroup::removeShare(this); - if (d->windowContext) { - d->windowContext->setQGLContextHandle(0,0); + if (d->guiGlContext) { + d->guiGlContext->setQGLContextHandle(0,0); } } void QGLContext::makeCurrent() { Q_D(QGLContext); - d->windowContext->makeCurrent(); + if (!d->paintDevice || d->paintDevice->devType() != QInternal::Widget) + return; + + QWidget *widget = static_cast<QWidget *>(d->paintDevice); + if (!widget->windowHandle()) + return; - 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; + if (d->guiGlContext->makeCurrent(widget->windowHandle()->glSurface())) { + 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->windowContext->doneCurrent(); + d->guiGlContext->doneCurrent(); } void QGLContext::swapBuffers() const { Q_D(const QGLContext); - d->windowContext->swapBuffers(); + if (!d->paintDevice || d->paintDevice->devType() != QInternal::Widget) + return; + + QWidget *widget = static_cast<QWidget *>(d->paintDevice); + if (!widget->windowHandle()) + return; + + d->guiGlContext->swapBuffers(widget->windowHandle()->glSurface()); } void *QGLContext::getProcAddress(const QString &procName) const { Q_D(const QGLContext); - return (void *)d->windowContext->getProcAddress(procName.toAscii()); + return (void *)d->guiGlContext->getProcAddress(procName.toAscii()); } void QGLWidget::setContext(QGLContext *context, @@ -271,30 +285,31 @@ class QGLTemporaryContextPrivate { public: QWindow *window; - QWindowContext *context; + QGuiGLContext *context; + + QGLContext *oldContext; }; QGLTemporaryContext::QGLTemporaryContext(bool, QWidget *) : d(new QGLTemporaryContextPrivate) { - d->context = const_cast<QWindowContext *>(QWindowContext::currentContext()); - if (d->context) - d->context->doneCurrent(); + d->oldContext = const_cast<QGLContext *>(QGLContext::currentContext()); d->window = new QWindow; d->window->setGeometry(QRect(0, 0, 3, 3)); d->window->setSurfaceType(QWindow::OpenGLSurface); d->window->create(); - d->window->glContext()->makeCurrent(); + d->context = new QGuiGLContext; + d->context->makeCurrent(d->window->glSurface()); } QGLTemporaryContext::~QGLTemporaryContext() { - if (d->context) - d->context->makeCurrent(); - else - d->window->glContext()->doneCurrent(); + if (d->oldContext) + d->oldContext->makeCurrent(); + + delete d->context; delete d->window; } @@ -361,28 +376,28 @@ void QGLWidget::setColormap(const QGLColormap & c) Q_UNUSED(c); } -QGLContext::QGLContext(QWindowContext *windowContext) +QGLContext::QGLContext(QGuiGLContext *context) : d_ptr(new QGLContextPrivate(this)) { Q_D(QGLContext); - d->init(0,QGLFormat::fromWindowFormat(windowContext->handle()->windowFormat())); - d->windowContext = windowContext; - d->windowContext->setQGLContextHandle(this,qDeleteQGLContext); - d->valid = true; + d->init(0,QGLFormat::fromGuiGLFormat(context->format())); + d->guiGlContext = context; + d->guiGlContext->setQGLContextHandle(this,qDeleteQGLContext); + d->valid = context->isValid(); d->setupSharing(); } /*! Returns a OpenGL context for the window context specified by \a windowContext */ -QGLContext *QGLContext::fromWindowContext(QWindowContext *windowContext) +QGLContext *QGLContext::fromGuiGLContext(QGuiGLContext *context) { - if (!windowContext) + if (!context) return 0; - if (windowContext->qGLContextHandle()) { - return reinterpret_cast<QGLContext *>(windowContext->qGLContextHandle()); + if (context->qGLContextHandle()) { + return reinterpret_cast<QGLContext *>(context->qGLContextHandle()); } - QGLContext *glContext = new QGLContext(windowContext); + QGLContext *glContext = new QGLContext(context); //Dont call create on context. This can cause the platformFormat to be set on the widget, which //will cause the platformWindow to be recreated. return glContext; |