diff options
-rw-r--r-- | src/quick/designer/qquickdesignerwindowmanager.cpp | 3 | ||||
-rw-r--r-- | src/quick/items/qquickrendercontrol.cpp | 65 | ||||
-rw-r--r-- | src/quick/items/qquickrendercontrol.h | 1 | ||||
-rw-r--r-- | src/quick/items/qquickwindow.cpp | 33 | ||||
-rw-r--r-- | src/quick/scenegraph/qsgdefaultrendercontext.cpp | 50 | ||||
-rw-r--r-- | src/quick/scenegraph/qsgdefaultrendercontext_p.h | 1 | ||||
-rw-r--r-- | src/quick/scenegraph/qsgrenderloop.cpp | 125 | ||||
-rw-r--r-- | src/quick/scenegraph/qsgthreadedrenderloop.cpp | 181 | ||||
-rw-r--r-- | src/quick/scenegraph/qsgthreadedrenderloop_p.h | 3 | ||||
-rw-r--r-- | src/quickwidgets/qquickwidget.cpp | 11 |
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(¶ms); 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(¶ms); - } 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 |