aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLaszlo Agocs <laszlo.agocs@qt.io>2020-06-05 12:10:06 +0200
committerLaszlo Agocs <laszlo.agocs@qt.io>2020-06-08 14:10:45 +0200
commit433dc99229c7c980f410b6692c1df17734c95385 (patch)
tree876adc33c9240e4ef782057c07c192543bc9ae3d
parent3f5e21a0cc9f41f1747e5c431695e7798ee489db (diff)
Make render loops OpenGL clean
Task-number: QTBUG-84718 Task-number: QTBUG-84623 Change-Id: I14392c365a52ecc410362500bbe29b4dd7953007 Reviewed-by: Andy Nichols <andy.nichols@qt.io>
-rw-r--r--src/quick/designer/qquickdesignerwindowmanager.cpp3
-rw-r--r--src/quick/items/qquickrendercontrol.cpp65
-rw-r--r--src/quick/items/qquickrendercontrol.h1
-rw-r--r--src/quick/items/qquickwindow.cpp33
-rw-r--r--src/quick/scenegraph/qsgdefaultrendercontext.cpp50
-rw-r--r--src/quick/scenegraph/qsgdefaultrendercontext_p.h1
-rw-r--r--src/quick/scenegraph/qsgrenderloop.cpp125
-rw-r--r--src/quick/scenegraph/qsgthreadedrenderloop.cpp181
-rw-r--r--src/quick/scenegraph/qsgthreadedrenderloop_p.h3
-rw-r--r--src/quickwidgets/qquickwidget.cpp11
10 files changed, 73 insertions, 400 deletions
diff --git a/src/quick/designer/qquickdesignerwindowmanager.cpp b/src/quick/designer/qquickdesignerwindowmanager.cpp
index bca89f3e14..04df6b2832 100644
--- a/src/quick/designer/qquickdesignerwindowmanager.cpp
+++ b/src/quick/designer/qquickdesignerwindowmanager.cpp
@@ -77,7 +77,8 @@ void QQuickDesignerWindowManager::makeOpenGLContext(QQuickWindow *window)
qWarning("QQuickWindow: makeCurrent() failed...");
QSGDefaultRenderContext::InitParams params;
params.sampleCount = qMax(1, m_openGlContext->format().samples());
- params.openGLContext = m_openGlContext.data();
+ // ### glpurge Designer's RHI migration is left as a future exercise (QTBUG-78598)
+ //params.openGLContext = m_openGlContext.data();
params.initialSurfacePixelSize = window->size() * window->effectiveDevicePixelRatio();
params.maybeSurface = window;
m_renderContext->initialize(&params);
diff --git a/src/quick/items/qquickrendercontrol.cpp b/src/quick/items/qquickrendercontrol.cpp
index 6a84f55578..f8d2d14fcb 100644
--- a/src/quick/items/qquickrendercontrol.cpp
+++ b/src/quick/items/qquickrendercontrol.cpp
@@ -48,9 +48,6 @@
#include <private/qsgrhishadereffectnode_p.h>
-#if QT_CONFIG(opengl)
-# include <QOpenGLContext>
-#endif
#include <QtGui/private/qguiapplication_p.h>
#include <qpa/qplatformintegration.h>
#include <QtGui/qoffscreensurface.h>
@@ -68,9 +65,6 @@
#include <QtGui/private/qrhi_p.h>
QT_BEGIN_NAMESPACE
-#if QT_CONFIG(opengl)
-extern Q_GUI_EXPORT QImage qt_gl_read_framebuffer(const QSize &size, bool alpha_format, bool include_alpha);
-#endif
/*!
\class QQuickRenderControl
@@ -313,52 +307,6 @@ bool QQuickRenderControl::initialize()
}
/*!
- Initializes the scene graph resources. The context \a gl has to be the
- current OpenGL context or null if it is not relevant because a Qt Quick
- backend other than OpenGL is in use.
-
- \note Qt Quick does not take ownership of the context. It is up to the
- application to destroy it after a call to invalidate() or after the
- QQuickRenderControl instance is destroyed.
- */
-void QQuickRenderControl::initialize(QOpenGLContext *gl)
-{
-
- Q_D(QQuickRenderControl);
-#if QT_CONFIG(opengl)
- if (!d->window) {
- qWarning("QQuickRenderControl::initialize called with no associated window");
- return;
- }
-
- if (QOpenGLContext::currentContext() != gl) {
- qWarning("QQuickRenderControl::initialize called with incorrect current context");
- return;
- }
-
- // 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.
- QSGDefaultRenderContext *rc = qobject_cast<QSGDefaultRenderContext *>(d->rc);
- if (rc) {
- QSGDefaultRenderContext::InitParams params;
- params.sampleCount = qMax(1, gl->format().samples());
- params.openGLContext = gl;
- params.initialSurfacePixelSize = d->window->size() * d->window->effectiveDevicePixelRatio();
- params.maybeSurface = d->window;
- rc->initialize(&params);
- } else {
- // can this happen?
- d->rc->initialize(nullptr);
- }
-#else
- Q_UNUSED(gl)
-#endif
- d->initialized = true;
-}
-
-/*!
This function should be called as late as possible before
sync(). In a threaded scenario, rendering can happen in parallel
with this function.
@@ -513,19 +461,6 @@ QImage QQuickRenderControlPrivate::grab()
// does not support custom render targets, so the grab implementation
// here is still valuable)
- } else if (window->rendererInterface()->graphicsApi() == QSGRendererInterface::OpenGL) {
-#if QT_CONFIG(opengl)
- QQuickWindowPrivate *cd = QQuickWindowPrivate::get(window);
- cd->polishItems();
- cd->syncSceneGraph();
- rc->endSync();
- q->render();
- const bool alpha = window->format().alphaBufferSize() > 0 && window->color().alpha() < 255;
- grabContent = qt_gl_read_framebuffer(window->size() * window->effectiveDevicePixelRatio(), alpha, alpha);
- if (QQuickRenderControl::renderWindowFor(window)) {
- grabContent.setDevicePixelRatio(window->effectiveDevicePixelRatio());
- }
-#endif
#if QT_CONFIG(thread)
} else if (window->rendererInterface()->graphicsApi() == QSGRendererInterface::Software) {
QQuickWindowPrivate *cd = QQuickWindowPrivate::get(window);
diff --git a/src/quick/items/qquickrendercontrol.h b/src/quick/items/qquickrendercontrol.h
index cdcad589f6..6284203be3 100644
--- a/src/quick/items/qquickrendercontrol.h
+++ b/src/quick/items/qquickrendercontrol.h
@@ -64,7 +64,6 @@ public:
int samples() const;
bool initialize();
- void initialize(QOpenGLContext *gl); // ### Qt 6 remove
void invalidate();
diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp
index 7cdfde44de..aac5a0c527 100644
--- a/src/quick/items/qquickwindow.cpp
+++ b/src/quick/items/qquickwindow.cpp
@@ -4282,39 +4282,6 @@ QImage QQuickWindow::grabWindow()
Q_ASSERT(!d->rhi);
return QSGRhiSupport::instance()->grabOffscreen(this);
}
-
- // ### Qt 6 remove
-#if QT_CONFIG(opengl)
- auto openglRenderContext = static_cast<QSGDefaultRenderContext *>(d->context);
- if (!openglRenderContext->openglContext()) {
- if (!handle() || !size().isValid()) {
- qWarning("QQuickWindow::grabWindow: window must be created and have a valid size");
- return QImage();
- }
-
- QOpenGLContext context;
- context.setFormat(requestedFormat());
- context.setShareContext(qt_gl_global_share_context());
- context.create();
- context.makeCurrent(this);
- QSGDefaultRenderContext::InitParams rcParams;
- rcParams.openGLContext = &context;
- d->context->initialize(&rcParams);
-
- d->polishItems();
- d->syncSceneGraph();
- d->renderSceneGraph(size());
-
- bool alpha = format().alphaBufferSize() > 0 && color().alpha() < 255;
- QImage image = qt_gl_read_framebuffer(size() * effectiveDevicePixelRatio(), alpha, alpha);
- image.setDevicePixelRatio(effectiveDevicePixelRatio());
- d->cleanupNodesOnShutdown();
- d->context->invalidate();
- context.doneCurrent();
-
- return image;
- }
-#endif
}
// The common case: we have an exposed window with an initialized
diff --git a/src/quick/scenegraph/qsgdefaultrendercontext.cpp b/src/quick/scenegraph/qsgdefaultrendercontext.cpp
index 5dc73fa3ad..59e4b5e3bb 100644
--- a/src/quick/scenegraph/qsgdefaultrendercontext.cpp
+++ b/src/quick/scenegraph/qsgdefaultrendercontext.cpp
@@ -86,51 +86,11 @@ void QSGDefaultRenderContext::initialize(const QSGRenderContext::InitParams *par
m_initParams = *initParams;
m_rhi = m_initParams.rhi;
- if (m_rhi) {
- m_maxTextureSize = m_rhi->resourceLimit(QRhi::TextureSizeMax);
- if (!m_rhiAtlasManager)
- m_rhiAtlasManager = new QSGRhiAtlasTexture::Manager(this, m_initParams.initialSurfacePixelSize, m_initParams.maybeSurface);
- // unlike OpenGL (and like WebGL), QRhi does not guarantee buffer usage types can be mixed
- m_separateIndexBuffer = true;
- } else {
- QOpenGLFunctions *funcs = m_rhi ? nullptr : QOpenGLContext::currentContext()->functions();
- funcs->glGetIntegerv(GL_MAX_TEXTURE_SIZE, &m_maxTextureSize);
-
- // Sanity check the surface format, in case it was overridden by the application
- QSurfaceFormat requested = m_sg->defaultSurfaceFormat();
- QSurfaceFormat actual = m_initParams.openGLContext->format();
- if (requested.depthBufferSize() > 0 && actual.depthBufferSize() <= 0)
- qWarning("QSGContext::initialize: depth buffer support missing, expect rendering errors");
- if (requested.stencilBufferSize() > 0 && actual.stencilBufferSize() <= 0)
- qWarning("QSGContext::initialize: stencil buffer support missing, expect rendering errors");
-
-#ifdef Q_OS_LINUX
- const char *vendor = (const char *) funcs->glGetString(GL_VENDOR);
- if (vendor && strstr(vendor, "nouveau"))
- m_brokenIBOs = true;
- const char *renderer = (const char *) funcs->glGetString(GL_RENDERER);
- if (renderer && strstr(renderer, "llvmpipe"))
- m_serializedRender = true;
- if (vendor && renderer && strstr(vendor, "Hisilicon Technologies") && strstr(renderer, "Immersion.16"))
- m_brokenIBOs = true;
-#endif
-
- Q_ASSERT_X(!m_gl, "QSGRenderContext::initialize", "already initialized!");
- m_gl = m_initParams.openGLContext;
- if (m_attachToGLContext) {
- Q_ASSERT(!m_gl->property(QSG_RENDERCONTEXT_PROPERTY).isValid());
- m_gl->setProperty(QSG_RENDERCONTEXT_PROPERTY, QVariant::fromValue(this));
- }
-
- // WebGL: A given WebGLBuffer object may only be bound to one of
- // the ARRAY_BUFFER or ELEMENT_ARRAY_BUFFER target in its
- // lifetime. An attempt to bind a buffer object to the other
- // target will generate an INVALID_OPERATION error, and the
- // current binding will remain untouched.
- const bool isWebGL = (qGuiApp->platformName().compare(QLatin1String("webgl")) == 0
- || qGuiApp->platformName().compare(QLatin1String("wasm")) == 0);
- m_separateIndexBuffer = isWebGL;
- }
+ m_maxTextureSize = m_rhi->resourceLimit(QRhi::TextureSizeMax);
+ if (!m_rhiAtlasManager)
+ m_rhiAtlasManager = new QSGRhiAtlasTexture::Manager(this, m_initParams.initialSurfacePixelSize, m_initParams.maybeSurface);
+ // unlike OpenGL (and like WebGL), QRhi does not guarantee buffer usage types can be mixed
+ m_separateIndexBuffer = true;
m_sg->renderContextInitialized(this);
diff --git a/src/quick/scenegraph/qsgdefaultrendercontext_p.h b/src/quick/scenegraph/qsgdefaultrendercontext_p.h
index 4cf989b345..2f97b16131 100644
--- a/src/quick/scenegraph/qsgdefaultrendercontext_p.h
+++ b/src/quick/scenegraph/qsgdefaultrendercontext_p.h
@@ -93,7 +93,6 @@ public:
int sType = INIT_PARAMS_MAGIC; // help discovering broken code passing something else as 'context'
QRhi *rhi = nullptr;
int sampleCount = 1; // 1, 4, 8, ...
- QOpenGLContext *openGLContext = nullptr; // ### Qt 6: remove
// only used as a hint f.ex. in the texture atlas init
QSize initialSurfacePixelSize;
// The first window that will be used with this rc, if available.
diff --git a/src/quick/scenegraph/qsgrenderloop.cpp b/src/quick/scenegraph/qsgrenderloop.cpp
index c2b1550689..c37ab04438 100644
--- a/src/quick/scenegraph/qsgrenderloop.cpp
+++ b/src/quick/scenegraph/qsgrenderloop.cpp
@@ -65,7 +65,6 @@
#include <private/qsgrhishadereffectnode_p.h>
#if QT_CONFIG(opengl)
-#include <QOpenGLContext>
#include <private/qsgdefaultrendercontext_p.h>
#endif
@@ -89,12 +88,10 @@ extern Q_GUI_EXPORT QImage qt_gl_read_framebuffer(const QSize &size, bool alpha_
#define ENABLE_DEFAULT_BACKEND
/*
- expectations for this manager to work:
- - one opengl context to render multiple windows
- - OpenGL pipeline will not block for vsync in swap
- - OpenGL pipeline will block based on a full buffer queue.
- - Multiple screens can share the OpenGL context
- - Animations are advanced for all windows once per swap
+ - Uses one QRhi (and so OpenGL Context, Vulkan device, etc.) to render multiple windows.
+ - This assumes multiple screens can use the OpenGL context.
+ - Animations are advanced using the standard timer, so QML animations run as expected even when
+ vsync throttling is broken.
*/
DEFINE_BOOL_CONFIG_OPTION(qmlNoThreadedRenderer, QML_BAD_GUI_RENDER_LOOP);
@@ -141,17 +138,10 @@ void QSGRenderLoop::postJob(QQuickWindow *window, QRunnable *job)
Q_ASSERT(job);
#ifdef ENABLE_DEFAULT_BACKEND
Q_ASSERT(window);
- if (!QSGRhiSupport::instance()->isRhiEnabled()) {
- if (window->openglContext()) {
- window->openglContext()->makeCurrent(window);
- job->run();
- }
- } else {
- QQuickWindowPrivate *cd = QQuickWindowPrivate::get(window);
- if (cd->rhi)
- cd->rhi->makeThreadLocalNativeContextCurrent();
- job->run();
- }
+ QQuickWindowPrivate *cd = QQuickWindowPrivate::get(window);
+ if (cd->rhi)
+ cd->rhi->makeThreadLocalNativeContextCurrent();
+ job->run();
#else
Q_UNUSED(window)
job->run();
@@ -207,7 +197,6 @@ public:
QHash<QQuickWindow *, WindowData> m_windows;
- QOpenGLContext *gl = nullptr;
QOffscreenSurface *offscreenSurface = nullptr;
QRhi *rhi = nullptr;
QSGContext *sg;
@@ -382,23 +371,11 @@ void QSGGuiThreadRenderLoop::windowDestroyed(QQuickWindow *window)
hide(window);
QQuickWindowPrivate *d = QQuickWindowPrivate::get(window);
- bool current = false;
- if (gl || rhi) {
- if (rhi) {
- // Direct OpenGL calls in user code need a current context, like
- // when rendering; ensure this (no-op when not running on GL).
- // Also works when there is no handle() anymore.
- rhi->makeThreadLocalNativeContextCurrent();
- current = true;
- } else {
- QSurface *surface = window;
- // There may be no platform window if the window got closed.
- if (!window->handle())
- surface = offscreenSurface;
- current = gl->makeCurrent(surface);
- }
- if (Q_UNLIKELY(!current))
- qCDebug(QSG_LOG_RENDERLOOP, "cleanup without an OpenGL context");
+ if (rhi) {
+ // Direct OpenGL calls in user code need a current context, like
+ // when rendering; ensure this (no-op when not running on GL).
+ // Also works when there is no handle() anymore.
+ rhi->makeThreadLocalNativeContextCurrent();
}
#if QT_CONFIG(quick_shadereffect)
@@ -422,13 +399,8 @@ void QSGGuiThreadRenderLoop::windowDestroyed(QQuickWindow *window)
d->rhi = nullptr;
delete rhi;
rhi = nullptr;
- delete gl;
- gl = nullptr;
delete offscreenSurface;
offscreenSurface = nullptr;
- } else if (gl && window == gl->surface() && current) {
- if (!rhi)
- gl->doneCurrent();
}
d->animationController.reset();
@@ -513,9 +485,8 @@ void QSGGuiThreadRenderLoop::renderWindow(QQuickWindow *window)
bool current = false;
QSGRhiSupport *rhiSupport = QSGRhiSupport::instance();
int rhiSampleCount = 1;
- const bool enableRhi = rhiSupport->isRhiEnabled();
- if (enableRhi && !rhi) {
+ if (!rhi) {
// This block below handles both the initial QRhi initialization and
// also the subsequent reinitialization attempts after a device lost
// (reset) situation.
@@ -556,48 +527,17 @@ void QSGGuiThreadRenderLoop::renderWindow(QQuickWindow *window)
}
// otherwise no error, will retry on a subsequent rendering attempt
}
- } else if (!enableRhi && !gl) {
- gl = new QOpenGLContext();
- gl->setFormat(window->requestedFormat());
- gl->setScreen(window->screen());
- if (qt_gl_global_share_context())
- gl->setShareContext(qt_gl_global_share_context());
- if (!gl->create()) {
- delete gl;
- gl = nullptr;
- handleContextCreationFailure(window);
- } else {
- if (!offscreenSurface) {
- offscreenSurface = new QOffscreenSurface;
- offscreenSurface->setFormat(gl->format());
- offscreenSurface->create();
- }
- cd->fireOpenGLContextCreated(gl);
- current = gl->makeCurrent(window);
- }
- if (current) {
- QSGDefaultRenderContext::InitParams rcParams;
- rcParams.sampleCount = qMax(1, gl->format().samples());
- rcParams.openGLContext = gl;
- rcParams.initialSurfacePixelSize = window->size() * window->effectiveDevicePixelRatio();
- rcParams.maybeSurface = window;
- cd->context->initialize(&rcParams);
- }
} else {
- if (rhi) {
- current = true;
- // With the rhi making the (OpenGL) context current serves only one
- // purpose: to enable external OpenGL rendering connected to one of
- // the QQuickWindow signals (beforeSynchronizing, beforeRendering,
- // etc.) to function like it did on the direct OpenGL path. For our
- // own rendering this call would not be necessary.
- rhi->makeThreadLocalNativeContextCurrent();
- } else {
- current = gl->makeCurrent(window);
- }
+ current = true;
+ // With the rhi making the (OpenGL) context current serves only one
+ // purpose: to enable external OpenGL rendering connected to one of
+ // the QQuickWindow signals (beforeSynchronizing, beforeRendering,
+ // etc.) to function like it did on the direct OpenGL path. For our
+ // own rendering this call would not be necessary.
+ rhi->makeThreadLocalNativeContextCurrent();
}
- if (enableRhi && rhi && !cd->swapchain) {
+ if (rhi && !cd->swapchain) {
// if it's not the first window then the rhi is not yet stored to
// QQuickWindowPrivate, do it now
cd->rhi = rhi;
@@ -639,24 +579,6 @@ void QSGGuiThreadRenderLoop::renderWindow(QQuickWindow *window)
i++;
}
- // Check for context loss. (legacy GL only)
- if (!current && !rhi && !gl->isValid()) {
- for (auto it = m_windows.constBegin() ; it != m_windows.constEnd(); it++) {
- QQuickWindowPrivate *windowPrivate = QQuickWindowPrivate::get(it.key());
- windowPrivate->cleanupNodesOnShutdown();
- }
- rc->invalidate();
- current = gl->create() && gl->makeCurrent(window);
- if (current) {
- QSGDefaultRenderContext::InitParams rcParams;
- rcParams.sampleCount = qMax(1, gl->format().samples());
- rcParams.openGLContext = gl;
- rcParams.initialSurfacePixelSize = window->size() * window->effectiveDevicePixelRatio();
- rcParams.maybeSurface = window;
- rc->initialize(&rcParams);
- }
- }
-
if (!current)
return;
@@ -789,9 +711,6 @@ void QSGGuiThreadRenderLoop::renderWindow(QQuickWindow *window)
else if (frameResult == QRhi::FrameOpError)
qWarning("Failed to end frame");
}
- } else if (needsPresent) {
- if (!cd->customRenderStage || !cd->customRenderStage->swap())
- gl->swapBuffers(window);
}
if (needsPresent)
cd->fireFrameSwapped();
diff --git a/src/quick/scenegraph/qsgthreadedrenderloop.cpp b/src/quick/scenegraph/qsgthreadedrenderloop.cpp
index 04df601b28..736ab5cfb9 100644
--- a/src/quick/scenegraph/qsgthreadedrenderloop.cpp
+++ b/src/quick/scenegraph/qsgthreadedrenderloop.cpp
@@ -95,7 +95,7 @@
---
- There is one thread per window and one opengl context per thread.
+ There is one thread per window and one QRhi instance per thread.
---
@@ -280,8 +280,6 @@ class QSGRenderThread : public QThread
public:
QSGRenderThread(QSGThreadedRenderLoop *w, QSGRenderContext *renderContext)
: wm(w)
- , gl(nullptr)
- , enableRhi(false)
, rhi(nullptr)
, offscreenSurface(nullptr)
, animatorDriver(nullptr)
@@ -306,7 +304,7 @@ public:
delete offscreenSurface;
}
- void invalidateGraphics(QQuickWindow *window, bool inDestructor, QOffscreenSurface *backupSurface);
+ void invalidateGraphics(QQuickWindow *window, bool inDestructor);
bool event(QEvent *) override;
void run() override;
@@ -343,8 +341,6 @@ public:
void handleDeviceLoss();
QSGThreadedRenderLoop *wm;
- QOpenGLContext *gl;
- bool enableRhi;
QRhi *rhi;
QSGDefaultRenderContext *sgrc;
QOffscreenSurface *offscreenSurface;
@@ -423,9 +419,9 @@ bool QSGRenderThread::event(QEvent *e)
wm->m_lockedForSync = true;
WMTryReleaseEvent *wme = static_cast<WMTryReleaseEvent *>(e);
if (!window || wme->inDestructor) {
- qCDebug(QSG_LOG_RENDERLOOP, QSG_RT_PAD, "- setting exit flag and invalidating OpenGL");
- invalidateGraphics(wme->window, wme->inDestructor, wme->needsFallback ? offscreenSurface : nullptr);
- active = gl || rhi;
+ qCDebug(QSG_LOG_RENDERLOOP, QSG_RT_PAD, "- setting exit flag and invalidating");
+ invalidateGraphics(wme->window, wme->inDestructor);
+ active = rhi != nullptr;
Q_ASSERT_X(!wme->inDestructor || !active, "QSGRenderThread::invalidateGraphics()", "Thread's active state is not set to false when shutting down");
if (sleeping)
stopEventProcessing = true;
@@ -452,24 +448,9 @@ bool QSGRenderThread::event(QEvent *e)
Q_ASSERT(ce->window == window || !window);
mutex.lock();
if (ce->window) {
- const bool alpha = ce->window->format().alphaBufferSize() > 0 && ce->window->color().alpha() != 255;
- const QSize readbackSize = windowSize * ce->window->effectiveDevicePixelRatio();
if (rhi) {
rhi->makeThreadLocalNativeContextCurrent();
syncAndRender(ce->image);
- } else {
- gl->makeCurrent(ce->window);
-
- qCDebug(QSG_LOG_RENDERLOOP, QSG_RT_PAD, "- sync scene graph");
- QQuickWindowPrivate *d = QQuickWindowPrivate::get(ce->window);
- d->syncSceneGraph();
- sgrc->endSync();
-
- qCDebug(QSG_LOG_RENDERLOOP, QSG_RT_PAD, "- rendering scene graph");
- QQuickWindowPrivate::get(ce->window)->renderSceneGraph(ce->window->size());
-
- qCDebug(QSG_LOG_RENDERLOOP, QSG_RT_PAD, "- grabbing result");
- *ce->image = qt_gl_read_framebuffer(readbackSize, alpha, alpha);
}
ce->image->setDevicePixelRatio(ce->window->effectiveDevicePixelRatio());
}
@@ -486,8 +467,6 @@ bool QSGRenderThread::event(QEvent *e)
if (window) {
if (rhi)
rhi->makeThreadLocalNativeContextCurrent();
- else
- gl->makeCurrent(window);
ce->job->run();
delete ce->job;
ce->job = nullptr;
@@ -517,11 +496,11 @@ bool QSGRenderThread::event(QEvent *e)
return QThread::event(e);
}
-void QSGRenderThread::invalidateGraphics(QQuickWindow *window, bool inDestructor, QOffscreenSurface *fallback)
+void QSGRenderThread::invalidateGraphics(QQuickWindow *window, bool inDestructor)
{
qCDebug(QSG_LOG_RENDERLOOP, QSG_RT_PAD, "invalidateGraphics()");
- if (!gl && !rhi)
+ if (!rhi)
return;
if (!window) {
@@ -531,12 +510,10 @@ void QSGRenderThread::invalidateGraphics(QQuickWindow *window, bool inDestructor
bool wipeSG = inDestructor || !window->isPersistentSceneGraph();
- bool wipeGL = inDestructor || (wipeSG && !window->isPersistentOpenGLContext());
+ bool wipeGraphics = inDestructor || (wipeSG && !window->isPersistentOpenGLContext());
bool current = true;
- if (gl)
- current = gl->makeCurrent(fallback ? static_cast<QSurface *>(fallback) : static_cast<QSurface *>(window));
- else if (rhi)
+ if (rhi)
rhi->makeThreadLocalNativeContextCurrent();
if (Q_UNLIKELY(!current)) {
@@ -554,8 +531,6 @@ void QSGRenderThread::invalidateGraphics(QQuickWindow *window, bool inDestructor
dd->cleanupNodesOnShutdown();
} else {
qCDebug(QSG_LOG_RENDERLOOP, QSG_RT_PAD, "- persistent SG, avoiding cleanup");
- if (current && gl)
- gl->doneCurrent();
return;
}
@@ -564,11 +539,10 @@ void QSGRenderThread::invalidateGraphics(QQuickWindow *window, bool inDestructor
QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete);
if (inDestructor)
dd->animationController.reset();
- if (current && gl)
- gl->doneCurrent();
+
qCDebug(QSG_LOG_RENDERLOOP, QSG_RT_PAD, "- invalidating scene graph");
- if (wipeGL) {
+ if (wipeGraphics) {
if (dd->swapchain) {
if (window->handle()) {
// We get here when exiting via QCoreApplication::quit() instead of
@@ -579,11 +553,9 @@ void QSGRenderThread::invalidateGraphics(QQuickWindow *window, bool inDestructor
window, dd->swapchain);
}
}
- delete gl;
- gl = nullptr;
delete rhi;
rhi = nullptr;
- qCDebug(QSG_LOG_RENDERLOOP, QSG_RT_PAD, "- invalidated OpenGL");
+ qCDebug(QSG_LOG_RENDERLOOP, QSG_RT_PAD, "- QRhi destroyed");
} else {
qCDebug(QSG_LOG_RENDERLOOP, QSG_RT_PAD, "- persistent GL, avoiding cleanup");
}
@@ -602,26 +574,7 @@ void QSGRenderThread::sync(bool inExpose, bool inGrab)
Q_ASSERT_X(wm->m_lockedForSync, "QSGRenderThread::sync()", "sync triggered on bad terms as gui is not already locked...");
bool current = true;
- if (gl) {
- if (windowSize.width() > 0 && windowSize.height() > 0)
- current = gl->makeCurrent(window);
- else
- current = false;
- // Check for context loss.
- if (!current && !gl->isValid()) {
- QQuickWindowPrivate::get(window)->cleanupNodesOnShutdown();
- sgrc->invalidate();
- current = gl->create() && gl->makeCurrent(window);
- if (current) {
- QSGDefaultRenderContext::InitParams rcParams;
- rcParams.sampleCount = qMax(1, gl->format().samples());
- rcParams.openGLContext = gl;
- rcParams.initialSurfacePixelSize = windowSize * qreal(dpr);
- rcParams.maybeSurface = window;
- sgrc->initialize(&rcParams);
- }
- }
- } else if (rhi) {
+ if (rhi) {
if (windowSize.width() > 0 && windowSize.height() > 0) {
// With the rhi making the (OpenGL) context current serves only one
// purpose: to enable external OpenGL rendering connected to one of
@@ -792,7 +745,7 @@ void QSGRenderThread::syncAndRender(QImage *grabImage)
&& !(pendingUpdate & RepaintRequest) // may have been set in sync()
&& sgrc->isValid()
&& !grabRequested
- && (gl || rhi))
+ && rhi)
{
qCDebug(QSG_LOG_RENDERLOOP, QSG_RT_PAD, "- no changes, render aborted");
if (rhi && rhi->isRecordingFrame())
@@ -823,24 +776,13 @@ void QSGRenderThread::syncAndRender(QImage *grabImage)
}
bool current = true;
- if (d->renderer && windowSize.width() > 0 && windowSize.height() > 0 && (gl || rhi)) {
- if (gl)
- current = gl->makeCurrent(window);
- else
- rhi->makeThreadLocalNativeContextCurrent();
- } else {
- // Zero size windows do not initialize a swapchain and
- // rendercontext. So no sync or render can be done then.
+ // Zero size windows do not initialize a swapchain and
+ // rendercontext. So no sync or render can be done then.
+ if (d->renderer && windowSize.width() > 0 && windowSize.height() > 0 && rhi)
+ rhi->makeThreadLocalNativeContextCurrent();
+ else
current = false;
- }
- // Check for context loss (GL, RHI case handled after the beginFrame() above)
- if (gl) {
- if (!current && !gl->isValid()) {
- // Cannot do anything here because gui is not locked. Request a new
- // sync+render round on the gui thread and let the sync handle it.
- QCoreApplication::postEvent(window, new QEvent(QEvent::Type(QQuickWindowPrivate::FullUpdateRequest)));
- }
- }
+
if (current) {
d->renderSceneGraph(windowSize, rhi ? cd->swapchain->currentPixelSize() : QSize());
@@ -856,7 +798,7 @@ void QSGRenderThread::syncAndRender(QImage *grabImage)
// grabs as it rather invokes sync/render directly without going
// through syncAndRender().
if (grabRequested) {
- Q_ASSERT(rhi && !gl && cd->swapchain);
+ Q_ASSERT(rhi && cd->swapchain);
*grabImage = QSGRhiSupport::instance()->grabAndBlockInCurrentFrame(rhi, cd->swapchain->currentFrameCommandBuffer());
}
@@ -873,9 +815,6 @@ void QSGRenderThread::syncAndRender(QImage *grabImage)
if (frameResult == QRhi::FrameOpDeviceLost || frameResult == QRhi::FrameOpSwapChainOutOfDate)
QCoreApplication::postEvent(window, new QEvent(QEvent::Type(QQuickWindowPrivate::FullUpdateRequest)));
}
- } else {
- if (!cd->customRenderStage || !cd->customRenderStage->swap())
- gl->swapBuffers(window);
}
if (!grabRequested)
@@ -976,7 +915,6 @@ void QSGRenderThread::ensureRhi()
QSGDefaultRenderContext::InitParams rcParams;
rcParams.rhi = rhi;
rcParams.sampleCount = rhiSampleCount;
- rcParams.openGLContext = nullptr;
rcParams.initialSurfacePixelSize = windowSize * qreal(dpr);
rcParams.maybeSurface = window;
sgrc->initialize(&rcParams);
@@ -1022,35 +960,21 @@ void QSGRenderThread::run()
#endif
if (window) {
- if (enableRhi) {
-
- ensureRhi();
+ ensureRhi();
- // We absolutely have to syncAndRender() here, even when QRhi
- // failed to initialize otherwise the gui thread will be left
- // in a blocked state. It is up to syncAndRender() to
- // gracefully skip all graphics stuff when rhi is null.
+ // We absolutely have to syncAndRender() here, even when QRhi
+ // failed to initialize otherwise the gui thread will be left
+ // in a blocked state. It is up to syncAndRender() to
+ // gracefully skip all graphics stuff when rhi is null.
- syncAndRender();
+ syncAndRender();
- // Now we can do something about rhi init failures. (reinit
- // failure after device reset does not count)
- if (rhiDoomed && !guiNotifiedAboutRhiFailure) {
- guiNotifiedAboutRhiFailure = true;
- QEvent *e = new QEvent(QEvent::Type(QQuickWindowPrivate::TriggerContextCreationFailure));
- QCoreApplication::postEvent(window, e);
- }
-
- } else {
- if (!sgrc->openglContext() && windowSize.width() > 0 && windowSize.height() > 0 && gl->makeCurrent(window)) {
- QSGDefaultRenderContext::InitParams rcParams;
- rcParams.sampleCount = qMax(1, gl->format().samples());
- rcParams.openGLContext = gl;
- rcParams.initialSurfacePixelSize = windowSize * qreal(dpr);
- rcParams.maybeSurface = window;
- sgrc->initialize(&rcParams);
- }
- syncAndRender();
+ // Now we can do something about rhi init failures. (reinit
+ // failure after device reset does not count)
+ if (rhiDoomed && !guiNotifiedAboutRhiFailure) {
+ guiNotifiedAboutRhiFailure = true;
+ QEvent *e = new QEvent(QEvent::Type(QQuickWindowPrivate::TriggerContextCreationFailure));
+ QCoreApplication::postEvent(window, e);
}
}
@@ -1065,7 +989,7 @@ void QSGRenderThread::run()
}
}
- Q_ASSERT_X(!gl && !rhi, "QSGRenderThread::run()", "The graphics context should be cleaned up before exiting the render thread...");
+ Q_ASSERT_X(!rhi, "QSGRenderThread::run()", "The graphics context should be cleaned up before exiting the render thread...");
qCDebug(QSG_LOG_RENDERLOOP, QSG_RT_PAD, "run() completed");
@@ -1344,36 +1268,10 @@ void QSGThreadedRenderLoop::handleExposure(QQuickWindow *window)
if (!w->thread->isRunning()) {
qCDebug(QSG_LOG_RENDERLOOP, "- starting render thread");
- w->thread->enableRhi = QSGRhiSupport::instance()->isRhiEnabled();
- if (w->thread->enableRhi) {
- if (!w->thread->rhi) {
- QSGRhiSupport *rhiSupport = QSGRhiSupport::instance();
- w->thread->offscreenSurface = rhiSupport->maybeCreateOffscreenSurface(window);
- window->installEventFilter(this);
- }
- } else {
- if (!w->thread->gl) {
- w->thread->gl = new QOpenGLContext();
- if (qt_gl_global_share_context())
- w->thread->gl->setShareContext(qt_gl_global_share_context());
- w->thread->gl->setFormat(w->window->requestedFormat());
- w->thread->gl->setScreen(w->window->screen());
- if (!w->thread->gl->create()) {
- delete w->thread->gl;
- w->thread->gl = nullptr;
- handleContextCreationFailure(w->window);
- return;
- }
-
- QQuickWindowPrivate::get(w->window)->fireOpenGLContextCreated(w->thread->gl);
-
- w->thread->gl->moveToThread(w->thread);
- qCDebug(QSG_LOG_RENDERLOOP, "- OpenGL context created");
-
- w->thread->offscreenSurface = new QOffscreenSurface();
- w->thread->offscreenSurface->setFormat(w->actualWindowFormat);
- w->thread->offscreenSurface->create();
- }
+ if (!w->thread->rhi) {
+ QSGRhiSupport *rhiSupport = QSGRhiSupport::instance();
+ w->thread->offscreenSurface = rhiSupport->maybeCreateOffscreenSurface(window);
+ window->installEventFilter(this);
}
QQuickAnimatorController *controller
@@ -1540,8 +1438,7 @@ void QSGThreadedRenderLoop::releaseResources(Window *w, bool inDestructor)
// The platform window might have been destroyed before
// hide/release/windowDestroyed is called, so we may need to have a
// fallback surface to perform the cleanup of the scene graph and the
- // OpenGL resources. QOffscreenSurface must be created on the GUI
- // thread so that is done for us already.
+ // RHI resources.
qCDebug(QSG_LOG_RENDERLOOP, "- posting release request to render thread");
w->thread->postEvent(new WMTryReleaseEvent(window, inDestructor, window->handle() == nullptr));
diff --git a/src/quick/scenegraph/qsgthreadedrenderloop_p.h b/src/quick/scenegraph/qsgthreadedrenderloop_p.h
index d805c91d79..f8075d9791 100644
--- a/src/quick/scenegraph/qsgthreadedrenderloop_p.h
+++ b/src/quick/scenegraph/qsgthreadedrenderloop_p.h
@@ -52,7 +52,6 @@
//
#include <QtCore/QThread>
-#include <QOpenGLContext>
#include <private/qsgcontext_p.h>
#include "qsgrenderloop_p.h"
@@ -137,8 +136,6 @@ private:
bool m_lockedForSync;
};
-
-
QT_END_NAMESPACE
#endif // QSGTHREADEDRENDERLOOP_P_H
diff --git a/src/quickwidgets/qquickwidget.cpp b/src/quickwidgets/qquickwidget.cpp
index 6bcbb0722c..440da6b461 100644
--- a/src/quickwidgets/qquickwidget.cpp
+++ b/src/quickwidgets/qquickwidget.cpp
@@ -315,8 +315,10 @@ void QQuickWidgetPrivate::render(bool needsSync)
if (!current && !context->isValid()) {
renderControl->invalidate();
current = context->create() && context->makeCurrent(offscreenSurface);
- if (current)
- renderControl->initialize(context);
+ if (current) {
+ offscreenWindow->setGraphicsDevice(QQuickGraphicsDevice::fromOpenGLContext(context));
+ renderControl->initialize();
+ }
}
if (!current) {
@@ -970,10 +972,7 @@ void QQuickWidgetPrivate::createContext()
if (context->makeCurrent(offscreenSurface)) {
if (!offscreenWindow->isSceneGraphInitialized()) {
offscreenWindow->setGraphicsDevice(QQuickGraphicsDevice::fromOpenGLContext(context));
- if (QSGRhiSupport::instance()->isRhiEnabled())
- renderControl->initialize();
- else
- renderControl->initialize(context);
+ renderControl->initialize();
}
} else
#endif