From 08c4a88a77563e50860c34164414fe014271ccc2 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs <laszlo.agocs@digia.com> Date: Wed, 19 Feb 2014 13:31:51 +0100 Subject: [PATCH] Avoid extra platformwindows with QQuickWidget QQuickWidget is nice but does not work on platforms like eglfs because it always creates a (hidden) platform window for the QQuickWindow. This is now fixed by avoiding calling create() on the window and using the toplevel window of the QQuickWidget instead. Change-Id: Ia552f7a16d8b913fb798fde04b9304c6d037a46c Reviewed-by: Paul Olav Tvete <paul.tvete@digia.com> --- src/quick/items/qquickrendercontrol.cpp | 10 +++++--- src/quick/items/qquickwindow.cpp | 3 +++ src/quickwidgets/qquickwidget.cpp | 32 ++++++++++++++++++------- 3 files changed, 34 insertions(+), 11 deletions(-) diff --git a/src/quick/items/qquickrendercontrol.cpp b/src/quick/items/qquickrendercontrol.cpp index 7e4335ba63..faee1358ae 100644 --- a/src/quick/items/qquickrendercontrol.cpp +++ b/src/quick/items/qquickrendercontrol.cpp @@ -114,9 +114,13 @@ void QQuickRenderControl::initialize(QOpenGLContext *gl) Q_D(QQuickRenderControl); if (!d->window) return; - bool current = gl->makeCurrent(d->window); - if (current) - QQuickWindowPrivate::get(d->window)->context->initialize(gl); + + // It is the caller's responsiblity to make a context/surface current. + // It cannot be done here since the surface to use may not be the + // surface belonging to window. In fact window may not have a native + // window/surface at all. + + QQuickWindowPrivate::get(d->window)->context->initialize(gl); } void QQuickRenderControl::invalidate() diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp index 7f62267859..588120a51a 100644 --- a/src/quick/items/qquickwindow.cpp +++ b/src/quick/items/qquickwindow.cpp @@ -361,6 +361,9 @@ void QQuickWindowPrivate::renderSceneGraph(const QSize &size) { QML_MEMORY_SCOPE_STRING("SceneGraph"); Q_Q(QQuickWindow); + if (!renderer) + return; + animationController->advance(); emit q->beforeRendering(); int fboId = 0; diff --git a/src/quickwidgets/qquickwidget.cpp b/src/quickwidgets/qquickwidget.cpp index ec4ce2f314..e8dec60bc4 100644 --- a/src/quickwidgets/qquickwidget.cpp +++ b/src/quickwidgets/qquickwidget.cpp @@ -95,7 +95,7 @@ QQuickWidgetPrivate::QQuickWidgetPrivate() renderControl = new QQuickRenderControl; offscreenWindow = new QQuickWindow(renderControl); offscreenWindow->setTitle(QString::fromLatin1("Offscreen")); - offscreenWindow->create(); + // Do not call create() on offscreenWindow. } QQuickWidgetPrivate::~QQuickWidgetPrivate() @@ -155,7 +155,9 @@ void QQuickWidgetPrivate::renderSceneGraph() qWarning("QQuickWidget: render scenegraph with no context"); return; } - context->makeCurrent(offscreenWindow); + + Q_ASSERT(q->window()->windowHandle()->handle()); + context->makeCurrent(q->window()->windowHandle()); renderControl->polishItems(); renderControl->sync(); renderControl->render(); @@ -493,20 +495,25 @@ QSize QQuickWidgetPrivate::rootObjectSize() const void QQuickWidgetPrivate::createContext() { + Q_Q(QQuickWidget); if (context) return; context = new QOpenGLContext(); - context->setFormat(offscreenWindow->requestedFormat()); + context->setFormat(q->window()->windowHandle()->requestedFormat()); if (QSGContext::sharedOpenGLContext()) context->setShareContext(QSGContext::sharedOpenGLContext()); // ??? is this correct if (!context->create()) { - qWarning("QtQuick: failed to create OpenGL context"); + qWarning("QQuickWidget: failed to create OpenGL context"); delete context; context = 0; } - renderControl->initialize(context); + Q_ASSERT(q->window()->windowHandle()->handle()); + if (context->makeCurrent(q->window()->windowHandle())) + renderControl->initialize(context); + else + qWarning("QQuickWidget: failed to make window surface current"); } void QQuickWidget::createFramebufferObject() @@ -518,7 +525,7 @@ void QQuickWidget::createFramebufferObject() QOpenGLContext *context = d->offscreenWindow->openglContext(); if (!context) { - qWarning("createFBO with no context"); + qWarning("QQuickWidget: Attempted to create FBO with no context"); return; } @@ -526,10 +533,17 @@ void QQuickWidget::createFramebufferObject() context->setShareContext(QWidgetPrivate::get(window())->shareContext()); context->create(); } - context->makeCurrent(d->offscreenWindow); + + Q_ASSERT(window()->windowHandle()->handle()); + context->makeCurrent(window()->windowHandle()); d->fbo = new QOpenGLFramebufferObject(size()); d->fbo->setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil); d->offscreenWindow->setRenderTarget(d->fbo); + + // Sanity check: The window must not have an underlying platform window. + // Having one would mean create() was called and platforms that only support + // a single native window were in trouble. + Q_ASSERT(!d->offscreenWindow->handle()); } void QQuickWidget::destroyFramebufferObject() @@ -690,7 +704,9 @@ void QQuickWidget::resizeEvent(QResizeEvent *e) qWarning("QQuickWidget::resizeEvent() no OpenGL context"); return; } - context->makeCurrent(d->offscreenWindow); + + Q_ASSERT(window()->windowHandle()->handle()); + context->makeCurrent(window()->windowHandle()); d->renderControl->render(); glFlush(); context->doneCurrent(); -- GitLab