diff --git a/src/3rdparty/wayland/protocols/qt_attribution.json b/src/3rdparty/wayland/protocols/qt_attribution.json
index a9fddb84082..657c032827c 100644
--- a/src/3rdparty/wayland/protocols/qt_attribution.json
+++ b/src/3rdparty/wayland/protocols/qt_attribution.json
@@ -154,5 +154,20 @@ Copyright © 2015, 2016 Jan Arne Petersen"
"License": "MIT License",
"LicenseFile": "MIT_LICENSE.txt",
"Copyright": "Copyright © 2014, 2015 Collabora, Ltd."
- }
+ },
+
+ {
+ "Id": "wayland-eglstream-controller",
+ "Name": "Wayland EGLStream Controller Protocol",
+ "QDocModule": "qtwaylandcompositor",
+ "QtUsage": "Used in the Qt Wayland Compositor",
+ "Files": "wayland-eglstream-controller.xml",
+
+ "Description": "Allows clients to request that the compositor creates its EGLStream.",
+ "Homepage": "https://github.com/NVIDIA/egl-wayland",
+ "LicenseId": "MIT",
+ "License": "MIT License",
+ "LicenseFile": "MIT_LICENSE.txt",
+ "Copyright": "Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved."
+ }
]
diff --git a/src/3rdparty/wayland/protocols/wl-eglstream-controller.xml b/src/3rdparty/wayland/protocols/wl-eglstream-controller.xml
new file mode 100644
index 00000000000..dea072e64b5
--- /dev/null
+++ b/src/3rdparty/wayland/protocols/wl-eglstream-controller.xml
@@ -0,0 +1,37 @@
+
+
+
+ Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved.
+
+ Permission is hereby granted, free of charge, to any person obtaining a
+ copy of this software and associated documentation files (the "Software"),
+ to deal in the Software without restriction, including without limitation
+ the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ and/or sell copies of the Software, and to permit persons to whom the
+ Software is furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ DEALINGS IN THE SOFTWARE.
+
+
+
+
+ Creates the corresponding server side EGLStream from the given wl_buffer
+ and attaches a consumer to it.
+
+
+
+
+
+
diff --git a/src/plugins/platforms/wayland/qwaylandintegration.cpp b/src/plugins/platforms/wayland/qwaylandintegration.cpp
index 1ffaf3c8930..45957629f77 100644
--- a/src/plugins/platforms/wayland/qwaylandintegration.cpp
+++ b/src/plugins/platforms/wayland/qwaylandintegration.cpp
@@ -343,6 +343,7 @@ void QWaylandIntegration::initializeClientBufferIntegration()
if (targetKey.isEmpty()) {
if (mDisplay->hardwareIntegration()
+ && mDisplay->hardwareIntegration()->clientBufferIntegration() != QLatin1String("wayland-eglstream-controller")
&& mDisplay->hardwareIntegration()->clientBufferIntegration() != QLatin1String("linux-dmabuf-unstable-v1")) {
targetKey = mDisplay->hardwareIntegration()->clientBufferIntegration();
} else {
diff --git a/src/plugins/platforms/wayland/qwaylandwindow.cpp b/src/plugins/platforms/wayland/qwaylandwindow.cpp
index 2301875c912..e81221fb5dd 100644
--- a/src/plugins/platforms/wayland/qwaylandwindow.cpp
+++ b/src/plugins/platforms/wayland/qwaylandwindow.cpp
@@ -359,8 +359,6 @@ void QWaylandWindow::sendExposeEvent(const QRect &rect)
{
if (!(mShellSurface && mShellSurface->handleExpose(rect)))
QWindowSystemInterface::handleExposeEvent(window(), rect);
- else
- qCDebug(lcQpaWayland) << "sendExposeEvent: intercepted by shell extension, not sending";
mLastExposeGeometry = rect;
}
@@ -549,11 +547,18 @@ void QWaylandWindow::handleScreenRemoved(QScreen *qScreen)
void QWaylandWindow::attach(QWaylandBuffer *buffer, int x, int y)
{
Q_ASSERT(!buffer->committed());
+ if (mFrameCallback) {
+ wl_callback_destroy(mFrameCallback);
+ mFrameCallback = nullptr;
+ }
+
if (buffer) {
- handleUpdate();
+ mFrameCallback = frame();
+ wl_callback_add_listener(mFrameCallback, &QWaylandWindow::callbackListener, this);
+ mWaitingForFrameSync = true;
buffer->setBusy();
- QtWayland::wl_surface::attach(buffer->buffer(), x, y);
+ attach(buffer->buffer(), x, y);
} else {
QtWayland::wl_surface::attach(nullptr, 0, 0);
}
@@ -623,9 +628,11 @@ void QWaylandWindow::frameCallback(void *data, struct wl_callback *callback, uin
Q_UNUSED(callback);
QWaylandWindow *self = static_cast(data);
- self->mWaitingForFrameCallback = false;
- if (self->mUpdateRequested)
+ self->mWaitingForFrameSync = false;
+ if (self->mUpdateRequested) {
+ self->mUpdateRequested = false;
self->deliverUpdateRequest();
+ }
}
QMutex QWaylandWindow::mFrameSyncMutex;
@@ -633,10 +640,10 @@ QMutex QWaylandWindow::mFrameSyncMutex;
void QWaylandWindow::waitForFrameSync()
{
QMutexLocker locker(&mFrameSyncMutex);
- if (!mWaitingForFrameCallback)
+ if (!mWaitingForFrameSync)
return;
mDisplay->flushRequests();
- while (mWaitingForFrameCallback)
+ while (mWaitingForFrameSync)
mDisplay->blockingReadEvents();
}
@@ -1037,88 +1044,12 @@ QVariant QWaylandWindow::property(const QString &name, const QVariant &defaultVa
return m_properties.value(name, defaultValue);
}
-void QWaylandWindow::timerEvent(QTimerEvent *event)
-{
- if (event->timerId() == mFallbackUpdateTimerId) {
- killTimer(mFallbackUpdateTimerId);
- mFallbackUpdateTimerId = -1;
-
- if (!isExposed()) {
- qCDebug(lcWaylandBackingstore) << "Fallback update timer: Window not exposed,"
- << "not delivering update request.";
- return;
- }
-
- if (mWaitingForUpdate && mUpdateRequested && !mWaitingForFrameCallback) {
- qCWarning(lcWaylandBackingstore) << "Delivering update request through fallback timer,"
- << "may not be in sync with display";
- deliverUpdateRequest();
- }
- }
-}
-
void QWaylandWindow::requestUpdate()
{
- if (mUpdateRequested)
- return;
-
- mUpdateRequested = true;
-
- // If we have a frame callback all is good and will be taken care of there
- if (mWaitingForFrameCallback)
- 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;
- }
-
- // 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 (mUpdateRequested && !mWaitingForUpdate && !mWaitingForFrameCallback)
- deliverUpdateRequest();
- }, Qt::QueuedConnection);
-}
-
-// Should be called whenever we commit a buffer (directly through wl_surface.commit or indirectly
-// with eglSwapBuffers) to know when it's time to commit the next one.
-// Can be called from the render thread (without locking anything) so make sure to not make races in this method.
-void QWaylandWindow::handleUpdate()
-{
- // TODO: Should sync subsurfaces avoid requesting frame callbacks?
-
- if (mFrameCallback) {
- wl_callback_destroy(mFrameCallback);
- 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, [=] { killTimer(id); }, Qt::QueuedConnection);
- }
-
- mFrameCallback = frame();
- wl_callback_add_listener(mFrameCallback, &QWaylandWindow::callbackListener, this);
- mWaitingForFrameCallback = true;
- mWaitingForUpdate = false;
-}
-
-void QWaylandWindow::deliverUpdateRequest()
-{
- mUpdateRequested = false;
- mWaitingForUpdate = true;
- QPlatformWindow::deliverUpdateRequest();
+ if (!mWaitingForFrameSync)
+ QPlatformWindow::requestUpdate();
+ else
+ mUpdateRequested = true;
}
void QWaylandWindow::addAttachOffset(const QPoint point)
diff --git a/src/plugins/platforms/wayland/qwaylandwindow_p.h b/src/plugins/platforms/wayland/qwaylandwindow_p.h
index 52cbc3e5920..146767a1e76 100644
--- a/src/plugins/platforms/wayland/qwaylandwindow_p.h
+++ b/src/plugins/platforms/wayland/qwaylandwindow_p.h
@@ -193,10 +193,7 @@ public:
bool startSystemMove(const QPoint &pos) override;
- void timerEvent(QTimerEvent *event) override;
void requestUpdate() override;
- void handleUpdate();
- void deliverUpdateRequest() override;
public slots:
void applyConfigure();
@@ -216,14 +213,10 @@ protected:
Qt::MouseButtons mMousePressedInContentArea = Qt::NoButton;
WId mWindowId;
- bool mWaitingForFrameCallback = false;
+ bool mWaitingForFrameSync = false;
struct ::wl_callback *mFrameCallback = nullptr;
QWaitCondition mFrameSyncWait;
- // True when we have called deliverRequestUpdate, but the client has not yet attached a new buffer
- bool mWaitingForUpdate = false;
- int mFallbackUpdateTimerId = -1;
-
QMutex mResizeLock;
bool mWaitingToApplyConfigure = false;
bool mCanResize = true;