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;
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()

View File

@ -179,7 +179,8 @@ QWindow *QQuickWidgetRenderControl::renderWindow(QPoint *offset)
void QQuickWidgetPrivate::initOffscreenWindow()
{
Q_Q(QQuickWidget);
offscreenWindow = new QQuickWidgetOffscreenWindow(*new QQuickWidgetOffscreenWindowPrivate(), renderControl);
ensureBackingScene();
offscreenWindow->setScreen(q->screen());
// Do not call create() on offscreenWindow.
@ -192,17 +193,30 @@ void QQuickWidgetPrivate::initOffscreenWindow()
#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);
initOffscreenWindow();
Q_Q(QQuickWidget);
if (!renderControl)
renderControl = new QQuickWidgetRenderControl(q);
if (!offscreenWindow)
offscreenWindow = new QQuickWidgetOffscreenWindow(*new QQuickWidgetOffscreenWindowPrivate(), renderControl);
// Check if the Software Adaptation is being used
auto sgRendererInterface = offscreenWindow->rendererInterface();
if (sgRendererInterface && sgRendererInterface->graphicsApi() == QSGRendererInterface::Software)
useSoftwareRenderer = true;
}
void QQuickWidgetPrivate::init(QQmlEngine* e)
{
Q_Q(QQuickWidget);
initOffscreenWindow();
if (!useSoftwareRenderer) {
if (QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::RhiBasedRendering))
@ -1280,6 +1294,7 @@ void QQuickWidgetPrivate::setRootObject(QObject *obj)
QPlatformBackingStoreRhiConfig QQuickWidgetPrivate::rhiConfig() const
{
const_cast<QQuickWidgetPrivate *>(this)->ensureBackingScene();
if (useSoftwareRenderer)
return {};

View File

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

View File

@ -127,7 +127,6 @@ public:
tst_qquickwidget();
private slots:
void initTestCase();
void showHide();
void reparentAfterShow();
void changeGeometry();
@ -163,21 +162,6 @@ private:
tst_qquickwidget::tst_qquickwidget()
: 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()