From bd6eb42fa31919aff1906aa60036aa33fd3edaa4 Mon Sep 17 00:00:00 2001 From: Johan Klokkhammer Helsing Date: Mon, 14 Oct 2019 11:10:42 +0200 Subject: Fix build: Use temporary directories for tests' XDG_RUNTIME_DIR Using XDG_RUNTIME_DIR="." does not work after qtbase 5542785, and it was a rather brittle solution anyway. Fixes: QTBUG-79185 Change-Id: Iaf9ced66709cc6cbac8a2d54efc64e1a8c528561 Reviewed-by: Paul Olav Tvete --- tests/auto/client/client/tst_client.cpp | 3 ++- tests/auto/client/inputcontext/tst_inputcontext.cpp | 3 ++- tests/auto/client/shared/mockcompositor.h | 3 ++- tests/auto/compositor/compositor/tst_compositor.cpp | 7 ++++++- 4 files changed, 12 insertions(+), 4 deletions(-) diff --git a/tests/auto/client/client/tst_client.cpp b/tests/auto/client/client/tst_client.cpp index 83b9e6ce0..e7729ce8b 100644 --- a/tests/auto/client/client/tst_client.cpp +++ b/tests/auto/client/client/tst_client.cpp @@ -507,7 +507,8 @@ void tst_WaylandClient::longWindowTitleWithUtf16Characters() int main(int argc, char **argv) { - setenv("XDG_RUNTIME_DIR", ".", 1); + QTemporaryDir tmpRuntimeDir; + setenv("XDG_RUNTIME_DIR", tmpRuntimeDir.path().toLocal8Bit(), 1); setenv("QT_QPA_PLATFORM", "wayland", 1); // force QGuiApplication to use wayland plugin MockCompositor compositor; diff --git a/tests/auto/client/inputcontext/tst_inputcontext.cpp b/tests/auto/client/inputcontext/tst_inputcontext.cpp index b1a5a7f17..3e6de4a08 100644 --- a/tests/auto/client/inputcontext/tst_inputcontext.cpp +++ b/tests/auto/client/inputcontext/tst_inputcontext.cpp @@ -173,7 +173,8 @@ void tst_inputcontext::inputContextReconfigurationWhenTogglingTextInputExtension int main(int argc, char *argv[]) { - qputenv("XDG_RUNTIME_DIR", "."); + QTemporaryDir tmpRuntimeDir; + qputenv("XDG_RUNTIME_DIR", tmpRuntimeDir.path().toLocal8Bit()); qputenv("QT_QPA_PLATFORM", "wayland"); tst_inputcontext tc; diff --git a/tests/auto/client/shared/mockcompositor.h b/tests/auto/client/shared/mockcompositor.h index 05bf32c8d..f5264ccf6 100644 --- a/tests/auto/client/shared/mockcompositor.h +++ b/tests/auto/client/shared/mockcompositor.h @@ -77,7 +77,8 @@ public: #define QCOMPOSITOR_TEST_MAIN(test) \ int main(int argc, char **argv) \ { \ - setenv("XDG_RUNTIME_DIR", ".", 1); \ + QTemporaryDir tmpRuntimeDir; \ + setenv("XDG_RUNTIME_DIR", tmpRuntimeDir.path().toLocal8Bit(), 1); \ setenv("XDG_CURRENT_DESKTOP", "qtwaylandtests", 1); \ setenv("QT_QPA_PLATFORM", "wayland", 1); \ test tc; \ diff --git a/tests/auto/compositor/compositor/tst_compositor.cpp b/tests/auto/compositor/compositor/tst_compositor.cpp index c425f2ba1..c286aae70 100644 --- a/tests/auto/compositor/compositor/tst_compositor.cpp +++ b/tests/auto/compositor/compositor/tst_compositor.cpp @@ -110,10 +110,15 @@ private slots: void viewportDestinationNoSurfaceError(); void viewportSourceNoSurfaceError(); void viewportHiDpi(); + +private: + QTemporaryDir m_tmpRuntimeDir; }; void tst_WaylandCompositor::init() { - qputenv("XDG_RUNTIME_DIR", "."); + // We need to set a test specific runtime dir so we don't conflict with other tests' + // compositors by accident. + qputenv("XDG_RUNTIME_DIR", m_tmpRuntimeDir.path().toLocal8Bit()); } void tst_WaylandCompositor::singleClient() -- cgit v1.2.3 From 9f5b96225885f927727a57b6123d8550d6c373bb Mon Sep 17 00:00:00 2001 From: Johan Klokkhammer Helsing Date: Tue, 15 Oct 2019 09:51:43 +0200 Subject: Client: Fix 100ms freeze when applications do not swap after deliverUpdateRequest [ChangeLog][QPA plugin] Fixed a 100 ms freeze that would occur if applications did not draw after receiving a deliverUpdateRequest(). QtQuick does this at the start of animations. This should get rid of those backingstore warnings (and also remove a 100ms freeze before animations start in those instances). Fixes: QTBUG-76813 Change-Id: Id366bf4a14f402fa44530ae46e7b66d9988c14f6 Reviewed-by: Paul Olav Tvete Reviewed-by: John Brooks --- src/client/qwaylandwindow.cpp | 46 +++++++++---------------------------------- src/client/qwaylandwindow_p.h | 1 - 2 files changed, 9 insertions(+), 38 deletions(-) diff --git a/src/client/qwaylandwindow.cpp b/src/client/qwaylandwindow.cpp index ae26ba049..8d34afd1f 100644 --- a/src/client/qwaylandwindow.cpp +++ b/src/client/qwaylandwindow.cpp @@ -1105,25 +1105,6 @@ QVariant QWaylandWindow::property(const QString &name, const QVariant &defaultVa void QWaylandWindow::timerEvent(QTimerEvent *event) { - if (event->timerId() == mFallbackUpdateTimerId) { - killTimer(mFallbackUpdateTimerId); - mFallbackUpdateTimerId = -1; - qCDebug(lcWaylandBackingstore) << "mFallbackUpdateTimer timed out"; - - if (!isExposed()) { - qCDebug(lcWaylandBackingstore) << "Fallback update timer: Window not exposed," - << "not delivering update request."; - return; - } - - if (mWaitingForUpdate && hasPendingUpdateRequest() && !mWaitingForFrameCallback) { - qCWarning(lcWaylandBackingstore) << "Delivering update request through fallback timer," - << "may not be in sync with display"; - deliverUpdateRequest(); - } - } - - if (mFrameCallbackTimerId.testAndSetOrdered(event->timerId(), -1)) { killTimer(event->timerId()); qCDebug(lcWaylandBackingstore) << "Didn't receive frame callback in time, window should now be inexposed"; @@ -1135,6 +1116,7 @@ void QWaylandWindow::timerEvent(QTimerEvent *event) void QWaylandWindow::requestUpdate() { + qCDebug(lcWaylandBackingstore) << "requestUpdate"; Q_ASSERT(hasPendingUpdateRequest()); // should be set by QPA // If we have a frame callback all is good and will be taken care of there @@ -1142,20 +1124,17 @@ void QWaylandWindow::requestUpdate() return; // If we've already called deliverUpdateRequest(), but haven't seen any attach+commit/swap yet - if (mWaitingForUpdate) { - // Ideally, we should just have returned here, but we're not guaranteed that the client - // will actually update, so start this timer to deliver another request update after a while - // *IF* the client doesn't update. - int fallbackTimeout = 100; - mFallbackUpdateTimerId = startTimer(fallbackTimeout); - return; - } + // This is a somewhat redundant behavior and might indicate a bug in the calling code, so log + // here so we can get this information when debugging update/frame callback issues. + // Continue as nothing happened, though. + if (mWaitingForUpdate) + qCDebug(lcWaylandBackingstore) << "requestUpdate called twice without committing anything"; // Some applications (such as Qt Quick) depend on updates being delivered asynchronously, // so use invokeMethod to delay the delivery a bit. QMetaObject::invokeMethod(this, [this] { // Things might have changed in the meantime - if (hasPendingUpdateRequest() && !mWaitingForUpdate && !mWaitingForFrameCallback) + if (hasPendingUpdateRequest() && !mWaitingForFrameCallback) deliverUpdateRequest(); }, Qt::QueuedConnection); } @@ -1165,6 +1144,7 @@ void QWaylandWindow::requestUpdate() // Can be called from the render thread (without locking anything) so make sure to not make races in this method. void QWaylandWindow::handleUpdate() { + qCDebug(lcWaylandBackingstore) << "handleUpdate" << QThread::currentThread(); // TODO: Should sync subsurfaces avoid requesting frame callbacks? QReadLocker lock(&mSurfaceLock); if (!isInitialized()) @@ -1175,15 +1155,6 @@ void QWaylandWindow::handleUpdate() mFrameCallback = nullptr; } - if (mFallbackUpdateTimerId != -1) { - // Ideally, we would stop the fallback timer here, but since we're on another thread, - // it's not allowed. Instead we set mFallbackUpdateTimer to -1 here, so we'll just - // ignore it if it times out before it's cleaned up by the invokeMethod call. - int id = mFallbackUpdateTimerId; - mFallbackUpdateTimerId = -1; - QMetaObject::invokeMethod(this, [this, id] { killTimer(id); }, Qt::QueuedConnection); - } - mFrameCallback = frame(); wl_callback_add_listener(mFrameCallback, &QWaylandWindow::callbackListener, this); mWaitingForFrameCallback = true; @@ -1203,6 +1174,7 @@ void QWaylandWindow::handleUpdate() void QWaylandWindow::deliverUpdateRequest() { + qCDebug(lcWaylandBackingstore) << "deliverUpdateRequest"; mWaitingForUpdate = true; QPlatformWindow::deliverUpdateRequest(); } diff --git a/src/client/qwaylandwindow_p.h b/src/client/qwaylandwindow_p.h index b03d92e56..e4a1124e7 100644 --- a/src/client/qwaylandwindow_p.h +++ b/src/client/qwaylandwindow_p.h @@ -232,7 +232,6 @@ protected: // True when we have called deliverRequestUpdate, but the client has not yet attached a new buffer bool mWaitingForUpdate = false; - int mFallbackUpdateTimerId = -1; // Started when waiting for app to commit QMutex mResizeLock; bool mWaitingToApplyConfigure = false; -- cgit v1.2.3 From 507c4f275b6f1a1e9b1269d9002db4cd762053ca Mon Sep 17 00:00:00 2001 From: Johan Klokkhammer Helsing Date: Fri, 18 Oct 2019 14:22:28 +0200 Subject: Client: Print a warning when trying to set clipboard without a seat This warning can save some time when trying to understand why some qtbase auto tests are failing on headless Weston (which doesn't have seats at the moment). Change-Id: I361546611d12bff8a465af5bb103f61e80d73a15 Reviewed-by: Pier Luigi Fiorini --- src/client/qwaylandclipboard.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/client/qwaylandclipboard.cpp b/src/client/qwaylandclipboard.cpp index 369c6ec07..c3a526ddc 100644 --- a/src/client/qwaylandclipboard.cpp +++ b/src/client/qwaylandclipboard.cpp @@ -93,8 +93,10 @@ QMimeData *QWaylandClipboard::mimeData(QClipboard::Mode mode) void QWaylandClipboard::setMimeData(QMimeData *data, QClipboard::Mode mode) { auto *seat = mDisplay->currentInputDevice(); - if (!seat) + if (!seat) { + qCWarning(lcQpaWayland) << "Can't set clipboard contents with no wl_seats available"; return; + } static const QString plain = QStringLiteral("text/plain"); static const QString utf8 = QStringLiteral("text/plain;charset=utf-8"); -- cgit v1.2.3 From 48b1acd2ae088bf6d7ce17c779e5f309759da15b Mon Sep 17 00:00:00 2001 From: Pekka Vuorela Date: Mon, 14 Oct 2019 17:20:59 +0300 Subject: Fix url getting broken on openUrl UTF-8 byte array cannot be split in random position and assume getting valid content on resulting parts. Switched chunk size to be based on characters, encoded size will vary but don't think that should matter. Change-Id: Ic41ea16d2111b1620993b60fdbc6e739929f25d7 Reviewed-by: Paul Olav Tvete --- src/client/qwaylandwindowmanagerintegration.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/client/qwaylandwindowmanagerintegration.cpp b/src/client/qwaylandwindowmanagerintegration.cpp index 17ae8a5ae..dd1acaf72 100644 --- a/src/client/qwaylandwindowmanagerintegration.cpp +++ b/src/client/qwaylandwindowmanagerintegration.cpp @@ -110,13 +110,17 @@ void QWaylandWindowManagerIntegration::windowmanager_quit() void QWaylandWindowManagerIntegration::openUrl_helper(const QUrl &url) { Q_ASSERT(isInitialized()); - QByteArray data = url.toString().toUtf8(); + QString data = url.toString(); static const int chunkSize = 128; while (!data.isEmpty()) { - QByteArray chunk = data.left(chunkSize); + QString chunk = data.left(chunkSize); data = data.mid(chunkSize); - open_url(!data.isEmpty(), QString::fromUtf8(chunk)); + if (chunk.at(chunk.size() - 1).isHighSurrogate() && !data.isEmpty()) { + chunk.append(data.at(0)); + data = data.mid(1); + } + open_url(!data.isEmpty(), chunk); } } -- cgit v1.2.3 From b108d7a88d23a17d1cc94ecdc69b360dae11afa5 Mon Sep 17 00:00:00 2001 From: Pekka Vuorela Date: Thu, 17 Oct 2019 12:18:16 +0300 Subject: Signal clipboard change when focus lost clears the selection offer Change-Id: I311a5d422f31347029795dbd2479a771ae93c01f Reviewed-by: Johan Helsing --- src/client/qwaylanddatadevice.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/client/qwaylanddatadevice.cpp b/src/client/qwaylanddatadevice.cpp index fc3c7077a..f7d135e49 100644 --- a/src/client/qwaylanddatadevice.cpp +++ b/src/client/qwaylanddatadevice.cpp @@ -81,7 +81,14 @@ QWaylandDataOffer *QWaylandDataDevice::selectionOffer() const void QWaylandDataDevice::invalidateSelectionOffer() { + if (m_selectionOffer.isNull()) + return; + m_selectionOffer.reset(); + +#if QT_CONFIG(clipboard) + QGuiApplicationPrivate::platformIntegration()->clipboard()->emitChanged(QClipboard::Clipboard); +#endif } QWaylandDataSource *QWaylandDataDevice::selectionSource() const -- cgit v1.2.3 From e306847cd46e68d86b1d5478c0c05b9a5acb026c Mon Sep 17 00:00:00 2001 From: Johan Klokkhammer Helsing Date: Tue, 22 Oct 2019 12:30:09 +0200 Subject: Add client test for clipboard when losing keyboard focus Also, verifies that we fixed a recent bug about QClipboard::dataChanged not being emitted when the clipboard is invalidated due to losing focus. Change-Id: Ie92b618a4f673c21d6582979249700aef8785536 Reviewed-by: Pekka Vuorela --- .../auto/client/datadevicev1/tst_datadevicev1.cpp | 30 ++++++++++++++++++++++ tests/auto/client/shared/datadevice.h | 1 - 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/tests/auto/client/datadevicev1/tst_datadevicev1.cpp b/tests/auto/client/datadevicev1/tst_datadevicev1.cpp index e3babceb5..1568b3b96 100644 --- a/tests/auto/client/datadevicev1/tst_datadevicev1.cpp +++ b/tests/auto/client/datadevicev1/tst_datadevicev1.cpp @@ -59,6 +59,7 @@ private slots: void pasteUtf8(); void destroysPreviousSelection(); void destroysSelectionWithSurface(); + void destroysSelectionOnLeave(); void dragWithoutFocus(); }; @@ -215,6 +216,35 @@ void tst_datadevicev1::destroysSelectionWithSurface() QCOMPOSITOR_TRY_COMPARE(dataDevice()->m_sentSelectionOffers.size(), 0); } +void tst_datadevicev1::destroysSelectionOnLeave() +{ + QRasterWindow window; + window.resize(64, 64); + window.show(); + QCOMPOSITOR_TRY_VERIFY(xdgSurface() && xdgSurface()->m_committedConfigureSerial); + + exec([&] { + auto *offer = dataDevice()->sendDataOffer(client(), {"text/plain"}); + dataDevice()->sendSelection(offer); + + auto *surface = xdgSurface()->m_surface; + keyboard()->sendEnter(surface); // Need to set keyboard focus according to protocol + }); + + QTRY_VERIFY(QGuiApplication::clipboard()->mimeData(QClipboard::Clipboard)); + QTRY_VERIFY(QGuiApplication::clipboard()->mimeData(QClipboard::Clipboard)->hasText()); + + QSignalSpy dataChangedSpy(QGuiApplication::clipboard(), &QClipboard::dataChanged); + + exec([&] { + auto *surface = xdgSurface()->m_surface; + keyboard()->sendLeave(surface); + }); + + QTRY_COMPARE(dataChangedSpy.count(), 1); + QVERIFY(!QGuiApplication::clipboard()->mimeData(QClipboard::Clipboard)->hasText()); +} + // The application should not crash if it attempts to start a drag operation // when it doesn't have input focus (QTBUG-76368) void tst_datadevicev1::dragWithoutFocus() diff --git a/tests/auto/client/shared/datadevice.h b/tests/auto/client/shared/datadevice.h index a96da86f0..98e780b22 100644 --- a/tests/auto/client/shared/datadevice.h +++ b/tests/auto/client/shared/datadevice.h @@ -65,7 +65,6 @@ public: ~DataDevice() override; void send_data_offer(::wl_resource *resource) = delete; DataOffer *sendDataOffer(::wl_client *client, const QStringList &mimeTypes = {}); - DataOffer *sendDataOffer(const QStringList &mimeTypes = {}); void send_selection(::wl_resource *resource) = delete; void sendSelection(DataOffer *offer); -- cgit v1.2.3 From 1c67c2e281f8a5e1af5ae2ef697e570bdd50514b Mon Sep 17 00:00:00 2001 From: Johan Klokkhammer Helsing Date: Tue, 22 Oct 2019 10:17:56 +0200 Subject: Fix missing emission of QClipboard::selectionChanged And add a test to verify we've fixed it. Change-Id: Ic6d5e64b3000444465935f7caf7e32ec9c4f1012 Reviewed-by: Paul Olav Tvete --- src/client/qwaylandprimaryselectionv1.cpp | 9 +++++++ src/client/qwaylandprimaryselectionv1_p.h | 2 +- .../primaryselectionv1/tst_primaryselectionv1.cpp | 30 ++++++++++++++++++++++ 3 files changed, 40 insertions(+), 1 deletion(-) diff --git a/src/client/qwaylandprimaryselectionv1.cpp b/src/client/qwaylandprimaryselectionv1.cpp index 3ddf6dac3..832f96780 100644 --- a/src/client/qwaylandprimaryselectionv1.cpp +++ b/src/client/qwaylandprimaryselectionv1.cpp @@ -96,6 +96,15 @@ QWaylandPrimarySelectionDeviceV1::~QWaylandPrimarySelectionDeviceV1() destroy(); } +void QWaylandPrimarySelectionDeviceV1::invalidateSelectionOffer() +{ + if (!m_selectionOffer) + return; + + m_selectionOffer.reset(); + QGuiApplicationPrivate::platformIntegration()->clipboard()->emitChanged(QClipboard::Selection); +} + void QWaylandPrimarySelectionDeviceV1::setSelectionSource(QWaylandPrimarySelectionSourceV1 *source) { if (source) { diff --git a/src/client/qwaylandprimaryselectionv1_p.h b/src/client/qwaylandprimaryselectionv1_p.h index b165c51b8..3f0a42a67 100644 --- a/src/client/qwaylandprimaryselectionv1_p.h +++ b/src/client/qwaylandprimaryselectionv1_p.h @@ -125,7 +125,7 @@ class QWaylandPrimarySelectionDeviceV1 : public QObject, public QtWayland::zwp_p public: ~QWaylandPrimarySelectionDeviceV1() override; QWaylandPrimarySelectionOfferV1 *selectionOffer() const { return m_selectionOffer.data(); } - void invalidateSelectionOffer() { m_selectionOffer.reset(); } + void invalidateSelectionOffer(); QWaylandPrimarySelectionSourceV1 *selectionSource() const { return m_selectionSource.data(); } void setSelectionSource(QWaylandPrimarySelectionSourceV1 *source); diff --git a/tests/auto/client/primaryselectionv1/tst_primaryselectionv1.cpp b/tests/auto/client/primaryselectionv1/tst_primaryselectionv1.cpp index 216db85cd..b3fa2b13c 100644 --- a/tests/auto/client/primaryselectionv1/tst_primaryselectionv1.cpp +++ b/tests/auto/client/primaryselectionv1/tst_primaryselectionv1.cpp @@ -261,6 +261,7 @@ private slots: void pasteAscii(); void pasteUtf8(); void destroysPreviousSelection(); + void destroysSelectionOnLeave(); void copy(); }; @@ -411,6 +412,35 @@ void tst_primaryselectionv1::destroysPreviousSelection() QCOMPOSITOR_TRY_COMPARE(primarySelectionDevice()->m_sentSelectionOffers.size(), 1); } +void tst_primaryselectionv1::destroysSelectionOnLeave() +{ + QRasterWindow window; + window.resize(64, 64); + window.show(); + QCOMPOSITOR_TRY_VERIFY(xdgSurface() && xdgSurface()->m_committedConfigureSerial); + + exec([&] { + auto *surface = xdgSurface()->m_surface; + keyboard()->sendEnter(surface); // Need to set keyboard focus according to protocol + + auto *offer = primarySelectionDevice()->sendDataOffer({"text/plain"}); + primarySelectionDevice()->sendSelection(offer); + }); + + QTRY_VERIFY(QGuiApplication::clipboard()->mimeData(QClipboard::Selection)); + QTRY_VERIFY(QGuiApplication::clipboard()->mimeData(QClipboard::Selection)->hasText()); + + QSignalSpy selectionChangedSpy(QGuiApplication::clipboard(), &QClipboard::selectionChanged); + + exec([&] { + auto *surface = xdgSurface()->m_surface; + keyboard()->sendLeave(surface); + }); + + QTRY_COMPARE(selectionChangedSpy.count(), 1); + QVERIFY(!QGuiApplication::clipboard()->mimeData(QClipboard::Selection)->hasText()); +} + void tst_primaryselectionv1::copy() { class Window : public QRasterWindow { -- cgit v1.2.3 From a3ab80f3463ce4f2e8c973e3f1048cc133fdba35 Mon Sep 17 00:00:00 2001 From: Johan Klokkhammer Helsing Date: Tue, 22 Oct 2019 12:02:23 +0200 Subject: Fix QClipboard::ownSelection always returning false It would return false regardless of whether we owned the selection. Change-Id: I6df394d8dbceeccb6eb6d0670b4351af1a158491 Reviewed-by: Paul Olav Tvete --- src/client/qwaylandclipboard.cpp | 16 +++++++++++----- .../client/primaryselectionv1/tst_primaryselectionv1.cpp | 1 + 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/src/client/qwaylandclipboard.cpp b/src/client/qwaylandclipboard.cpp index c3a526ddc..81f48e05e 100644 --- a/src/client/qwaylandclipboard.cpp +++ b/src/client/qwaylandclipboard.cpp @@ -137,14 +137,20 @@ bool QWaylandClipboard::supportsMode(QClipboard::Mode mode) const bool QWaylandClipboard::ownsMode(QClipboard::Mode mode) const { - if (mode != QClipboard::Clipboard) + QWaylandInputDevice *seat = mDisplay->currentInputDevice(); + if (!seat) return false; - QWaylandInputDevice *inputDevice = mDisplay->currentInputDevice(); - if (!inputDevice || !inputDevice->dataDevice()) + switch (mode) { + case QClipboard::Clipboard: + return seat->dataDevice() && seat->dataDevice()->selectionSource() != nullptr; +#if QT_CONFIG(wayland_client_primary_selection) + case QClipboard::Selection: + return seat->primarySelectionDevice() && seat->primarySelectionDevice()->selectionSource() != nullptr; +#endif + default: return false; - - return inputDevice->dataDevice()->selectionSource() != nullptr; + } } } diff --git a/tests/auto/client/primaryselectionv1/tst_primaryselectionv1.cpp b/tests/auto/client/primaryselectionv1/tst_primaryselectionv1.cpp index b3fa2b13c..ee9fa110e 100644 --- a/tests/auto/client/primaryselectionv1/tst_primaryselectionv1.cpp +++ b/tests/auto/client/primaryselectionv1/tst_primaryselectionv1.cpp @@ -472,6 +472,7 @@ void tst_primaryselectionv1::copy() }); QCOMPOSITOR_TRY_VERIFY(primarySelectionDevice()->m_selectionSource); QCOMPOSITOR_TRY_VERIFY(mouseSerials.contains(primarySelectionDevice()->m_serial)); + QVERIFY(QGuiApplication::clipboard()->ownsSelection()); QByteArray pastedBuf; exec([&](){ auto *source = primarySelectionDevice()->m_selectionSource; -- cgit v1.2.3 From 137966a6293b50f6b248d130a2e36e67df49335e Mon Sep 17 00:00:00 2001 From: Johan Klokkhammer Helsing Date: Tue, 22 Oct 2019 13:41:49 +0200 Subject: Compositor: Warn and clean up when client hardware buffer integrations fail We've recently seen a number of performance issues on bugreports and on the mailing list. The problem in many of these cases, is that no client hardware buffer plugin is used. I.e. it's just due to our fallback to CPU buffers when the compositor is configured incorrectly or run in a setup where hardware buffers are not available. This patch detects when client hardware buffer plugins fail and prints a warning explaining the issue to the console. This will make it easier to differentiate between expected and unexpected drops in performance and will hopefully also guide users in the right direction to fix their setup (set the right environment variables and perhaps recompile Qt with a supported OpenGL version). QtWayland::ClientBufferIntegration now returns a bool indicating success or failure. The integration is now destroyed immediately if it failed, instead of leaving it lying around until the compositor shuts down. There has been some slight changes in the xcomposite plugins as well, turning some qFatals into qCWarnings and failing more softly (with the warning mentioned above). Task-number: QTBUG-78483 Change-Id: I55293dbb3cf72768f3982c075fcf63e79329ada1 Reviewed-by: Paul Olav Tvete --- .../compositor_api/qwaylandcompositor.cpp | 28 +++++++++-- .../qwlclientbufferintegration_p.h | 2 +- .../compositor/brcm-egl/brcmeglintegration.cpp | 56 +++++++++++----------- .../compositor/brcm-egl/brcmeglintegration.h | 2 +- .../linuxdmabufclientbufferintegration.cpp | 17 +++---- .../linuxdmabufclientbufferintegration.h | 2 +- .../waylandeglclientbufferintegration.cpp | 17 +++---- .../waylandeglclientbufferintegration.h | 2 +- .../waylandeglstreamintegration.cpp | 20 +++++--- .../waylandeglstreamintegration.h | 2 +- .../xcomposite-egl/xcompositeeglintegration.cpp | 18 ++++--- .../xcomposite-egl/xcompositeeglintegration.h | 2 +- .../xcomposite-glx/xcompositeglxintegration.cpp | 15 ++++-- .../xcomposite-glx/xcompositeglxintegration.h | 2 +- 14 files changed, 112 insertions(+), 73 deletions(-) diff --git a/src/compositor/compositor_api/qwaylandcompositor.cpp b/src/compositor/compositor_api/qwaylandcompositor.cpp index 7c3750207..52a6614bc 100644 --- a/src/compositor/compositor_api/qwaylandcompositor.cpp +++ b/src/compositor/compositor_api/qwaylandcompositor.cpp @@ -366,8 +366,6 @@ void QWaylandCompositorPrivate::initializeHardwareIntegration() loadClientBufferIntegration(); loadServerBufferIntegration(); - if (client_buffer_integration) - client_buffer_integration->initializeHardware(display); if (server_buffer_integration) server_buffer_integration->initializeHardware(q); #endif @@ -399,12 +397,32 @@ void QWaylandCompositorPrivate::loadClientBufferIntegration() if (!targetKey.isEmpty()) { client_buffer_integration.reset(QtWayland::ClientBufferIntegrationFactory::create(targetKey, QStringList())); if (client_buffer_integration) { + qCDebug(qLcWaylandCompositorHardwareIntegration) << "Loaded client buffer integration:" << targetKey; client_buffer_integration->setCompositor(q); - if (hw_integration) - hw_integration->setClientBufferIntegration(targetKey); + if (!client_buffer_integration->initializeHardware(display)) { + qCWarning(qLcWaylandCompositorHardwareIntegration) + << "Failed to initialize hardware for client buffer integration:" << targetKey; + client_buffer_integration.reset(); + } + } else { + qCWarning(qLcWaylandCompositorHardwareIntegration) + << "Failed to load client buffer integration:" << targetKey; } } - //BUG: if there is no client buffer integration, bad things will happen when opengl is used + + if (!client_buffer_integration) { + qCWarning(qLcWaylandCompositorHardwareIntegration) + << "No client buffer integration was loaded, this means that clients will fall back" + << "to use CPU buffers (wl_shm) for transmitting buffers instead of using zero-copy" + << "GPU buffer handles. Expect serious performance impact with OpenGL clients due" + << "to potentially multiple copies between CPU and GPU memory per buffer.\n" + << "See the QtWayland readme for more info about how to build and configure Qt for" + << "your device."; + return; + } + + if (client_buffer_integration && hw_integration) + hw_integration->setClientBufferIntegration(targetKey); #endif } diff --git a/src/compositor/hardware_integration/qwlclientbufferintegration_p.h b/src/compositor/hardware_integration/qwlclientbufferintegration_p.h index 0195f3d4b..2e962273f 100644 --- a/src/compositor/hardware_integration/qwlclientbufferintegration_p.h +++ b/src/compositor/hardware_integration/qwlclientbufferintegration_p.h @@ -64,7 +64,7 @@ public: void setCompositor(QWaylandCompositor *compositor) { m_compositor = compositor; } QWaylandCompositor *compositor() const { return m_compositor; } - virtual void initializeHardware(struct ::wl_display *display) = 0; + virtual bool initializeHardware(struct ::wl_display *display) = 0; virtual ClientBuffer *createBufferFor(struct ::wl_resource *buffer) = 0; diff --git a/src/hardwareintegration/compositor/brcm-egl/brcmeglintegration.cpp b/src/hardwareintegration/compositor/brcm-egl/brcmeglintegration.cpp index de39ff1d2..8ddb4f951 100644 --- a/src/hardwareintegration/compositor/brcm-egl/brcmeglintegration.cpp +++ b/src/hardwareintegration/compositor/brcm-egl/brcmeglintegration.cpp @@ -67,46 +67,48 @@ BrcmEglIntegration::BrcmEglIntegration() { } -void BrcmEglIntegration::initializeHardware(struct ::wl_display *display) +bool BrcmEglIntegration::initializeHardware(struct ::wl_display *display) { Q_D(BrcmEglIntegration); QPlatformNativeInterface *nativeInterface = QGuiApplication::platformNativeInterface(); - if (nativeInterface) { - d->egl_display = nativeInterface->nativeResourceForIntegration("EglDisplay"); - if (!d->egl_display) - qWarning("Failed to acquire EGL display from platform integration"); + if (!nativeInterface) + return false; - d->eglQueryGlobalImageBRCM = (PFNEGLQUERYGLOBALIMAGEBRCMPROC) eglGetProcAddress("eglQueryGlobalImageBRCM"); + d->egl_display = nativeInterface->nativeResourceForIntegration("EglDisplay"); + if (!d->egl_display) + qWarning("Failed to acquire EGL display from platform integration"); - if (!d->eglQueryGlobalImageBRCM) { - qWarning("Failed to resolve eglQueryGlobalImageBRCM"); - return; - } + d->eglQueryGlobalImageBRCM = (PFNEGLQUERYGLOBALIMAGEBRCMPROC) eglGetProcAddress("eglQueryGlobalImageBRCM"); - d->glEGLImageTargetTexture2DOES = (PFNGLEGLIMAGETARGETTEXTURE2DOESPROC)eglGetProcAddress("glEGLImageTargetTexture2DOES"); + if (!d->eglQueryGlobalImageBRCM) { + qWarning("Failed to resolve eglQueryGlobalImageBRCM"); + return false; + } + + d->glEGLImageTargetTexture2DOES = (PFNGLEGLIMAGETARGETTEXTURE2DOESPROC)eglGetProcAddress("glEGLImageTargetTexture2DOES"); - if (!d->glEGLImageTargetTexture2DOES) { - qWarning("Failed to resolve glEGLImageTargetTexture2DOES"); - return; - } + if (!d->glEGLImageTargetTexture2DOES) { + qWarning("Failed to resolve glEGLImageTargetTexture2DOES"); + return false; + } - d->eglCreateImageKHR = (PFNEGLCREATEIMAGEKHRPROC)eglGetProcAddress("eglCreateImageKHR"); + d->eglCreateImageKHR = (PFNEGLCREATEIMAGEKHRPROC)eglGetProcAddress("eglCreateImageKHR"); - if (!d->eglCreateImageKHR) { - qWarning("Failed to resolve eglCreateImageKHR"); - return; - } + if (!d->eglCreateImageKHR) { + qWarning("Failed to resolve eglCreateImageKHR"); + return false; + } - d->eglDestroyImageKHR = (PFNEGLDESTROYIMAGEKHRPROC)eglGetProcAddress("eglDestroyImageKHR"); + d->eglDestroyImageKHR = (PFNEGLDESTROYIMAGEKHRPROC)eglGetProcAddress("eglDestroyImageKHR"); - if (!d->eglDestroyImageKHR) { - qWarning("Failed to resolve eglDestroyImageKHR"); - return; - } - d->valid = true; - init(display, 1); + if (!d->eglDestroyImageKHR) { + qWarning("Failed to resolve eglDestroyImageKHR"); + return false; } + d->valid = true; + init(display, 1); + return true; } QtWayland::ClientBuffer *BrcmEglIntegration::createBufferFor(wl_resource *buffer) diff --git a/src/hardwareintegration/compositor/brcm-egl/brcmeglintegration.h b/src/hardwareintegration/compositor/brcm-egl/brcmeglintegration.h index 3728da7bc..4bc98e8c5 100644 --- a/src/hardwareintegration/compositor/brcm-egl/brcmeglintegration.h +++ b/src/hardwareintegration/compositor/brcm-egl/brcmeglintegration.h @@ -47,7 +47,7 @@ class BrcmEglIntegration : public QtWayland::ClientBufferIntegration, public QtW public: BrcmEglIntegration(); - void initializeHardware(struct ::wl_display *display) override; + bool initializeHardware(struct ::wl_display *display) override; QtWayland::ClientBuffer *createBufferFor(wl_resource *buffer) override; protected: diff --git a/src/hardwareintegration/compositor/linux-dmabuf-unstable-v1/linuxdmabufclientbufferintegration.cpp b/src/hardwareintegration/compositor/linux-dmabuf-unstable-v1/linuxdmabufclientbufferintegration.cpp index 101e29891..4f01f855e 100644 --- a/src/hardwareintegration/compositor/linux-dmabuf-unstable-v1/linuxdmabufclientbufferintegration.cpp +++ b/src/hardwareintegration/compositor/linux-dmabuf-unstable-v1/linuxdmabufclientbufferintegration.cpp @@ -275,7 +275,7 @@ LinuxDmabufClientBufferIntegration::~LinuxDmabufClientBufferIntegration() m_importedBuffers.clear(); } -void LinuxDmabufClientBufferIntegration::initializeHardware(struct ::wl_display *display) +bool LinuxDmabufClientBufferIntegration::initializeHardware(struct ::wl_display *display) { m_linuxDmabuf.reset(new LinuxDmabuf(display, this)); @@ -286,40 +286,40 @@ void LinuxDmabufClientBufferIntegration::initializeHardware(struct ::wl_display egl_query_dmabuf_formats_ext = reinterpret_cast(eglGetProcAddress("eglQueryDmaBufFormatsEXT")); if (!egl_query_dmabuf_modifiers_ext || !egl_query_dmabuf_formats_ext) { qCWarning(qLcWaylandCompositorHardwareIntegration) << "Failed to initialize EGL display. Could not find eglQueryDmaBufModifiersEXT and eglQueryDmaBufFormatsEXT."; - return; + return false; } egl_bind_wayland_display = reinterpret_cast(eglGetProcAddress("eglBindWaylandDisplayWL")); egl_unbind_wayland_display = reinterpret_cast(eglGetProcAddress("eglUnbindWaylandDisplayWL")); if ((!egl_bind_wayland_display || !egl_unbind_wayland_display) && !ignoreBindDisplay) { qCWarning(qLcWaylandCompositorHardwareIntegration) << "Failed to initialize EGL display. Could not find eglBindWaylandDisplayWL and eglUnbindWaylandDisplayWL."; - return; + return false; } egl_create_image = reinterpret_cast(eglGetProcAddress("eglCreateImageKHR")); egl_destroy_image = reinterpret_cast(eglGetProcAddress("eglDestroyImageKHR")); if (!egl_create_image || !egl_destroy_image) { qCWarning(qLcWaylandCompositorHardwareIntegration) << "Failed to initialize EGL display. Could not find eglCreateImageKHR and eglDestroyImageKHR."; - return; + return false; } // initialize EGL display QPlatformNativeInterface *nativeInterface = QGuiApplication::platformNativeInterface(); if (!nativeInterface) { qCWarning(qLcWaylandCompositorHardwareIntegration) << "Failed to initialize EGL display. No native platform interface available."; - return; + return false; } m_eglDisplay = nativeInterface->nativeResourceForIntegration("EglDisplay"); if (!m_eglDisplay) { qCWarning(qLcWaylandCompositorHardwareIntegration) << "Failed to initialize EGL display. Could not get EglDisplay for window."; - return; + return false; } const char *extensionString = eglQueryString(m_eglDisplay, EGL_EXTENSIONS); if (!extensionString || !strstr(extensionString, "EGL_EXT_image_dma_buf_import")) { qCWarning(qLcWaylandCompositorHardwareIntegration) << "Failed to initialize EGL display. There is no EGL_EXT_image_dma_buf_import extension."; - return; + return false; } if (strstr(extensionString, "EGL_EXT_image_dma_buf_import_modifiers")) m_supportsDmabufModifiers = true; @@ -331,7 +331,7 @@ void LinuxDmabufClientBufferIntegration::initializeHardware(struct ::wl_display qCWarning(qLcWaylandCompositorHardwareIntegration) << "Could not bind Wayland display. Ignoring."; } else { qCWarning(qLcWaylandCompositorHardwareIntegration) << "Failed to initialize EGL display. Could not bind Wayland display."; - return; + return false; } } } @@ -342,6 +342,7 @@ void LinuxDmabufClientBufferIntegration::initializeHardware(struct ::wl_display modifiers[format] = supportedDrmModifiers(format); } m_linuxDmabuf->setSupportedModifiers(modifiers); + return true; } QVector LinuxDmabufClientBufferIntegration::supportedDrmFormats() diff --git a/src/hardwareintegration/compositor/linux-dmabuf-unstable-v1/linuxdmabufclientbufferintegration.h b/src/hardwareintegration/compositor/linux-dmabuf-unstable-v1/linuxdmabufclientbufferintegration.h index cbbd4d9ba..8909fa89f 100644 --- a/src/hardwareintegration/compositor/linux-dmabuf-unstable-v1/linuxdmabufclientbufferintegration.h +++ b/src/hardwareintegration/compositor/linux-dmabuf-unstable-v1/linuxdmabufclientbufferintegration.h @@ -67,7 +67,7 @@ public: LinuxDmabufClientBufferIntegration(); ~LinuxDmabufClientBufferIntegration() override; - void initializeHardware(struct ::wl_display *display) override; + bool initializeHardware(struct ::wl_display *display) override; QtWayland::ClientBuffer *createBufferFor(wl_resource *resource) override; bool importBuffer(wl_resource *resource, LinuxDmabufWlBuffer *linuxDmabufBuffer); void removeBuffer(wl_resource *resource); diff --git a/src/hardwareintegration/compositor/wayland-egl/waylandeglclientbufferintegration.cpp b/src/hardwareintegration/compositor/wayland-egl/waylandeglclientbufferintegration.cpp index cbbe397f8..fe35b92cd 100644 --- a/src/hardwareintegration/compositor/wayland-egl/waylandeglclientbufferintegration.cpp +++ b/src/hardwareintegration/compositor/wayland-egl/waylandeglclientbufferintegration.cpp @@ -393,7 +393,7 @@ WaylandEglClientBufferIntegration::~WaylandEglClientBufferIntegration() } } -void WaylandEglClientBufferIntegration::initializeHardware(struct wl_display *display) +bool WaylandEglClientBufferIntegration::initializeHardware(struct wl_display *display) { Q_D(WaylandEglClientBufferIntegration); @@ -402,39 +402,39 @@ void WaylandEglClientBufferIntegration::initializeHardware(struct wl_display *di QPlatformNativeInterface *nativeInterface = QGuiApplication::platformNativeInterface(); if (!nativeInterface) { qWarning("QtCompositor: Failed to initialize EGL display. No native platform interface available."); - return; + return false; } d->egl_display = nativeInterface->nativeResourceForIntegration("EglDisplay"); if (!d->egl_display) { qWarning("QtCompositor: Failed to initialize EGL display. Could not get EglDisplay for window."); - return; + return false; } const char *extensionString = eglQueryString(d->egl_display, EGL_EXTENSIONS); if ((!extensionString || !strstr(extensionString, "EGL_WL_bind_wayland_display")) && !ignoreBindDisplay) { qWarning("QtCompositor: Failed to initialize EGL display. There is no EGL_WL_bind_wayland_display extension."); - return; + return false; } d->egl_bind_wayland_display = reinterpret_cast(eglGetProcAddress("eglBindWaylandDisplayWL")); d->egl_unbind_wayland_display = reinterpret_cast(eglGetProcAddress("eglUnbindWaylandDisplayWL")); if ((!d->egl_bind_wayland_display || !d->egl_unbind_wayland_display) && !ignoreBindDisplay) { qWarning("QtCompositor: Failed to initialize EGL display. Could not find eglBindWaylandDisplayWL and eglUnbindWaylandDisplayWL."); - return; + return false; } d->egl_query_wayland_buffer = reinterpret_cast(eglGetProcAddress("eglQueryWaylandBufferWL")); if (!d->egl_query_wayland_buffer) { qWarning("QtCompositor: Failed to initialize EGL display. Could not find eglQueryWaylandBufferWL."); - return; + return false; } d->egl_create_image = reinterpret_cast(eglGetProcAddress("eglCreateImageKHR")); d->egl_destroy_image = reinterpret_cast(eglGetProcAddress("eglDestroyImageKHR")); if (!d->egl_create_image || !d->egl_destroy_image) { qWarning("QtCompositor: Failed to initialize EGL display. Could not find eglCreateImageKHR and eglDestroyImageKHR."); - return; + return false; } if (d->egl_bind_wayland_display && d->egl_unbind_wayland_display) { @@ -442,7 +442,7 @@ void WaylandEglClientBufferIntegration::initializeHardware(struct wl_display *di if (!d->display_bound) { if (!ignoreBindDisplay) { qWarning("QtCompositor: Failed to initialize EGL display. Could not bind Wayland display."); - return; + return false; } else { qWarning("QtCompositor: Could not bind Wayland display. Ignoring."); } @@ -454,6 +454,7 @@ void WaylandEglClientBufferIntegration::initializeHardware(struct wl_display *di d->funcs->initialize(d->egl_display); d->valid = true; + return true; } QtWayland::ClientBuffer *WaylandEglClientBufferIntegration::createBufferFor(wl_resource *buffer) diff --git a/src/hardwareintegration/compositor/wayland-egl/waylandeglclientbufferintegration.h b/src/hardwareintegration/compositor/wayland-egl/waylandeglclientbufferintegration.h index bbc0eafef..3b9959e2f 100644 --- a/src/hardwareintegration/compositor/wayland-egl/waylandeglclientbufferintegration.h +++ b/src/hardwareintegration/compositor/wayland-egl/waylandeglclientbufferintegration.h @@ -45,7 +45,7 @@ public: WaylandEglClientBufferIntegration(); ~WaylandEglClientBufferIntegration() override; - void initializeHardware(struct ::wl_display *display) override; + bool initializeHardware(struct ::wl_display *display) override; QtWayland::ClientBuffer *createBufferFor(wl_resource *buffer) override; diff --git a/src/hardwareintegration/compositor/wayland-eglstream-controller/waylandeglstreamintegration.cpp b/src/hardwareintegration/compositor/wayland-eglstream-controller/waylandeglstreamintegration.cpp index 8285e18d4..6c031aa89 100644 --- a/src/hardwareintegration/compositor/wayland-eglstream-controller/waylandeglstreamintegration.cpp +++ b/src/hardwareintegration/compositor/wayland-eglstream-controller/waylandeglstreamintegration.cpp @@ -298,7 +298,7 @@ void WaylandEglStreamClientBufferIntegration::attachEglStreamConsumer(struct ::w d->initEglStream(clientBuffer, wl_buffer); } -void WaylandEglStreamClientBufferIntegration::initializeHardware(struct wl_display *display) +bool WaylandEglStreamClientBufferIntegration::initializeHardware(struct wl_display *display) { Q_D(WaylandEglStreamClientBufferIntegration); @@ -307,32 +307,32 @@ void WaylandEglStreamClientBufferIntegration::initializeHardware(struct wl_displ QPlatformNativeInterface *nativeInterface = QGuiApplication::platformNativeInterface(); if (!nativeInterface) { qWarning("QtCompositor: Failed to initialize EGL display. No native platform interface available."); - return; + return false; } d->egl_display = nativeInterface->nativeResourceForIntegration("EglDisplay"); if (!d->egl_display) { qWarning("QtCompositor: Failed to initialize EGL display. Could not get EglDisplay for window."); - return; + return false; } const char *extensionString = eglQueryString(d->egl_display, EGL_EXTENSIONS); if ((!extensionString || !strstr(extensionString, "EGL_WL_bind_wayland_display")) && !ignoreBindDisplay) { qWarning("QtCompositor: Failed to initialize EGL display. There is no EGL_WL_bind_wayland_display extension."); - return; + return false; } d->egl_bind_wayland_display = reinterpret_cast(eglGetProcAddress("eglBindWaylandDisplayWL")); d->egl_unbind_wayland_display = reinterpret_cast(eglGetProcAddress("eglUnbindWaylandDisplayWL")); if ((!d->egl_bind_wayland_display || !d->egl_unbind_wayland_display) && !ignoreBindDisplay) { qWarning("QtCompositor: Failed to initialize EGL display. Could not find eglBindWaylandDisplayWL and eglUnbindWaylandDisplayWL."); - return; + return false; } d->egl_query_wayland_buffer = reinterpret_cast(eglGetProcAddress("eglQueryWaylandBufferWL")); if (!d->egl_query_wayland_buffer) { qWarning("QtCompositor: Failed to initialize EGL display. Could not find eglQueryWaylandBufferWL."); - return; + return false; } if (d->egl_bind_wayland_display && d->egl_unbind_wayland_display) { @@ -340,7 +340,7 @@ void WaylandEglStreamClientBufferIntegration::initializeHardware(struct wl_displ if (!d->display_bound) { if (!ignoreBindDisplay) { qWarning("QtCompositor: Failed to initialize EGL display. Could not bind Wayland display."); - return; + return false; } else { qWarning("QtCompositor: Could not bind Wayland display. Ignoring."); } @@ -351,6 +351,12 @@ void WaylandEglStreamClientBufferIntegration::initializeHardware(struct wl_displ d->funcs = new QEGLStreamConvenience; d->funcs->initialize(d->egl_display); + if (!d->funcs->initialized) { + qWarning(qLcWaylandCompositorHardwareIntegration) << "Failed to initialize eglstreams API"; + return false; + } + + return true; } QtWayland::ClientBuffer *WaylandEglStreamClientBufferIntegration::createBufferFor(wl_resource *buffer) diff --git a/src/hardwareintegration/compositor/wayland-eglstream-controller/waylandeglstreamintegration.h b/src/hardwareintegration/compositor/wayland-eglstream-controller/waylandeglstreamintegration.h index 4c4cce257..35d2c80d3 100644 --- a/src/hardwareintegration/compositor/wayland-eglstream-controller/waylandeglstreamintegration.h +++ b/src/hardwareintegration/compositor/wayland-eglstream-controller/waylandeglstreamintegration.h @@ -44,7 +44,7 @@ public: WaylandEglStreamClientBufferIntegration(); ~WaylandEglStreamClientBufferIntegration() override; - void initializeHardware(struct ::wl_display *display) override; + bool initializeHardware(struct ::wl_display *display) override; QtWayland::ClientBuffer *createBufferFor(wl_resource *buffer) override; diff --git a/src/hardwareintegration/compositor/xcomposite-egl/xcompositeeglintegration.cpp b/src/hardwareintegration/compositor/xcomposite-egl/xcompositeeglintegration.cpp index 3cf51a8de..3c302c7f6 100644 --- a/src/hardwareintegration/compositor/xcomposite-egl/xcompositeeglintegration.cpp +++ b/src/hardwareintegration/compositor/xcomposite-egl/xcompositeeglintegration.cpp @@ -62,20 +62,26 @@ XCompositeEglClientBufferIntegration::XCompositeEglClientBufferIntegration() } -void XCompositeEglClientBufferIntegration::initializeHardware(struct ::wl_display *) +bool XCompositeEglClientBufferIntegration::initializeHardware(struct ::wl_display *) { QPlatformNativeInterface *nativeInterface = QGuiApplication::platformNativeInterface(); if (nativeInterface) { mDisplay = static_cast(nativeInterface->nativeResourceForIntegration("Display")); - if (!mDisplay) - qFatal("could not retrieve Display from platform integration"); + if (!mDisplay) { + qCWarning(qLcWaylandCompositorHardwareIntegration) << "could not retrieve Display from platform integration"; + return false; + } mEglDisplay = static_cast(nativeInterface->nativeResourceForIntegration("EGLDisplay")); - if (!mEglDisplay) - qFatal("could not retrieve EGLDisplay from platform integration"); + if (!mEglDisplay) { + qCWarning(qLcWaylandCompositorHardwareIntegration) << "could not retrieve EGLDisplay from platform integration"; + return false; + } } else { - qFatal("Platform integration doesn't have native interface"); + qCWarning(qLcWaylandCompositorHardwareIntegration) << "Platform integration doesn't have native interface"; + return false; } new XCompositeHandler(m_compositor, mDisplay); + return true; } QtWayland::ClientBuffer *XCompositeEglClientBufferIntegration::createBufferFor(wl_resource *buffer) diff --git a/src/hardwareintegration/compositor/xcomposite-egl/xcompositeeglintegration.h b/src/hardwareintegration/compositor/xcomposite-egl/xcompositeeglintegration.h index 80ce88b5f..2c3116df1 100644 --- a/src/hardwareintegration/compositor/xcomposite-egl/xcompositeeglintegration.h +++ b/src/hardwareintegration/compositor/xcomposite-egl/xcompositeeglintegration.h @@ -45,7 +45,7 @@ class XCompositeEglClientBufferIntegration : public QtWayland::ClientBufferInteg public: XCompositeEglClientBufferIntegration(); - void initializeHardware(struct ::wl_display *display) override; + bool initializeHardware(struct ::wl_display *display) override; QtWayland::ClientBuffer *createBufferFor(wl_resource *buffer) override; inline Display *xDisplay() const { return mDisplay; } inline EGLDisplay eglDisplay() const { return mEglDisplay; } diff --git a/src/hardwareintegration/compositor/xcomposite-glx/xcompositeglxintegration.cpp b/src/hardwareintegration/compositor/xcomposite-glx/xcompositeglxintegration.cpp index 3c8fc9d04..db4390252 100644 --- a/src/hardwareintegration/compositor/xcomposite-glx/xcompositeglxintegration.cpp +++ b/src/hardwareintegration/compositor/xcomposite-glx/xcompositeglxintegration.cpp @@ -70,16 +70,19 @@ XCompositeGLXClientBufferIntegration::~XCompositeGLXClientBufferIntegration() delete mHandler; } -void XCompositeGLXClientBufferIntegration::initializeHardware(struct ::wl_display *) +bool XCompositeGLXClientBufferIntegration::initializeHardware(struct ::wl_display *) { qDebug() << "Initializing GLX integration"; QPlatformNativeInterface *nativeInterface = QGuiApplicationPrivate::platformIntegration()->nativeInterface(); if (nativeInterface) { mDisplay = static_cast(nativeInterface->nativeResourceForIntegration("Display")); - if (!mDisplay) - qFatal("could not retrieve Display from platform integration"); + if (!mDisplay) { + qCWarning(qLcWaylandCompositorHardwareIntegration) << "could not retrieve Display from platform integration"; + return false; + } } else { - qFatal("Platform integration doesn't have native interface"); + qCWarning(qLcWaylandCompositorHardwareIntegration) << "Platform integration doesn't have native interface"; + return false; } mScreen = XDefaultScreen(mDisplay); @@ -90,7 +93,8 @@ void XCompositeGLXClientBufferIntegration::initializeHardware(struct ::wl_displa m_glxBindTexImageEXT = reinterpret_cast(glContext->getProcAddress("glXBindTexImageEXT")); if (!m_glxBindTexImageEXT) { - qDebug() << "Did not find glxBindTexImageExt, everything will FAIL!"; + qCWarning(qLcWaylandCompositorHardwareIntegration) << "Did not find glxBindTexImageExt, everything will FAIL!"; + return false; } m_glxReleaseTexImageEXT = reinterpret_cast(glContext->getProcAddress("glXReleaseTexImageEXT")); if (!m_glxReleaseTexImageEXT) { @@ -98,6 +102,7 @@ void XCompositeGLXClientBufferIntegration::initializeHardware(struct ::wl_displa } delete glContext; + return true; } QtWayland::ClientBuffer *XCompositeGLXClientBufferIntegration::createBufferFor(wl_resource *buffer) diff --git a/src/hardwareintegration/compositor/xcomposite-glx/xcompositeglxintegration.h b/src/hardwareintegration/compositor/xcomposite-glx/xcompositeglxintegration.h index e783d41bf..6763d5916 100644 --- a/src/hardwareintegration/compositor/xcomposite-glx/xcompositeglxintegration.h +++ b/src/hardwareintegration/compositor/xcomposite-glx/xcompositeglxintegration.h @@ -48,7 +48,7 @@ public: XCompositeGLXClientBufferIntegration(); ~XCompositeGLXClientBufferIntegration() override; - void initializeHardware(struct ::wl_display *display) override; + bool initializeHardware(struct ::wl_display *display) override; QtWayland::ClientBuffer *createBufferFor(wl_resource *buffer) override; inline Display *xDisplay() const { return mDisplay; } -- cgit v1.2.3