Make QQuickWidget play nicer with the software backend

Launching with QT_QUICK_BACKEND=software should never lead to doing
anything QRhi-related, neither in Qt Quick, neither on the Widgets side.

Fixes: QTBUG-101884
Change-Id: I0dc47e04a0d32904db04f32a1db109029f8f4b44
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Andy Nichols <andy.nichols@qt.io>
This commit is contained in:
Laszlo Agocs 2022-03-21 15:28:02 +01:00
parent 1430cc7739
commit a7d3ac7c2d
4 changed files with 27 additions and 22 deletions

View File

@ -211,7 +211,12 @@ QQuickRenderControl::~QQuickRenderControl()
delete d->rc; delete d->rc;
d->resetRhi(); // Only call rhi related cleanup when we actually got to initialize() and
// managed to get a QRhi. The software backend for instance would mean
// using the rendercontrol without ever calling initialize() - it is then
// important to completely skip calling any QSGRhiSupport functions.
if (d->rhi)
d->resetRhi();
} }
void QQuickRenderControlPrivate::windowDestroyed() void QQuickRenderControlPrivate::windowDestroyed()

View File

@ -179,7 +179,8 @@ QWindow *QQuickWidgetRenderControl::renderWindow(QPoint *offset)
void QQuickWidgetPrivate::initOffscreenWindow() void QQuickWidgetPrivate::initOffscreenWindow()
{ {
Q_Q(QQuickWidget); Q_Q(QQuickWidget);
offscreenWindow = new QQuickWidgetOffscreenWindow(*new QQuickWidgetOffscreenWindowPrivate(), renderControl);
ensureBackingScene();
offscreenWindow->setScreen(q->screen()); offscreenWindow->setScreen(q->screen());
// Do not call create() on offscreenWindow. // Do not call create() on offscreenWindow.
@ -192,17 +193,30 @@ void QQuickWidgetPrivate::initOffscreenWindow()
#endif #endif
} }
void QQuickWidgetPrivate::init(QQmlEngine* e) void QQuickWidgetPrivate::ensureBackingScene()
{ {
Q_Q(QQuickWidget); // This should initialize, if not already done, the absolute minimum set of
// mandatory backing resources, meaning the QQuickWindow and its
// QQuickRenderControl. This function may be called very early on upon
// construction, including before init() even.
renderControl = new QQuickWidgetRenderControl(q); Q_Q(QQuickWidget);
initOffscreenWindow(); if (!renderControl)
renderControl = new QQuickWidgetRenderControl(q);
if (!offscreenWindow)
offscreenWindow = new QQuickWidgetOffscreenWindow(*new QQuickWidgetOffscreenWindowPrivate(), renderControl);
// Check if the Software Adaptation is being used // Check if the Software Adaptation is being used
auto sgRendererInterface = offscreenWindow->rendererInterface(); auto sgRendererInterface = offscreenWindow->rendererInterface();
if (sgRendererInterface && sgRendererInterface->graphicsApi() == QSGRendererInterface::Software) if (sgRendererInterface && sgRendererInterface->graphicsApi() == QSGRendererInterface::Software)
useSoftwareRenderer = true; useSoftwareRenderer = true;
}
void QQuickWidgetPrivate::init(QQmlEngine* e)
{
Q_Q(QQuickWidget);
initOffscreenWindow();
if (!useSoftwareRenderer) { if (!useSoftwareRenderer) {
if (QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::RhiBasedRendering)) if (QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::RhiBasedRendering))
@ -1280,6 +1294,7 @@ void QQuickWidgetPrivate::setRootObject(QObject *obj)
QPlatformBackingStoreRhiConfig QQuickWidgetPrivate::rhiConfig() const QPlatformBackingStoreRhiConfig QQuickWidgetPrivate::rhiConfig() const
{ {
const_cast<QQuickWidgetPrivate *>(this)->ensureBackingScene();
if (useSoftwareRenderer) if (useSoftwareRenderer)
return {}; return {};

View File

@ -104,6 +104,7 @@ public:
QImage grabFramebuffer() override; QImage grabFramebuffer() override;
void init(QQmlEngine* e = 0); void init(QQmlEngine* e = 0);
void ensureBackingScene();
void initOffscreenWindow(); void initOffscreenWindow();
void ensureEngine() const; void ensureEngine() const;
void handleWindowChange(); void handleWindowChange();

View File

@ -127,7 +127,6 @@ public:
tst_qquickwidget(); tst_qquickwidget();
private slots: private slots:
void initTestCase();
void showHide(); void showHide();
void reparentAfterShow(); void reparentAfterShow();
void changeGeometry(); void changeGeometry();
@ -163,21 +162,6 @@ private:
tst_qquickwidget::tst_qquickwidget() tst_qquickwidget::tst_qquickwidget()
: QQmlDataTest(QT_QMLTEST_DATADIR) : QQmlDataTest(QT_QMLTEST_DATADIR)
{ {
QQuickWindow::setGraphicsApi(QSGRendererInterface::OpenGLRhi);
}
void tst_qquickwidget::initTestCase()
{
QQmlDataTest::initTestCase();
// ### QTBUG-101884 Skip this test in the QEMU configs in the CI. That runs
// with the offscreen plugin and the software backend of Qt Quick. Until
// some of the test cases are investigated, skip the whole test.
if ((QGuiApplication::platformName() == QLatin1String("offscreen"))
|| (QGuiApplication::platformName() == QLatin1String("minimal")))
{
QSKIP("Skipping due to using a an offscreen platform / software rendering");
}
} }
void tst_qquickwidget::showHide() void tst_qquickwidget::showHide()