Merge remote-tracking branch 'origin/5.12' into dev

Conflicts:
	.qmake.conf
	src/3rdparty/protocol/qt_attribution.json
	src/client/qwaylandintegration.cpp

Change-Id: I475889f2817c7094b68a2948fdd34ddf8b0c486f
This commit is contained in:
Liang Qi 2019-01-22 11:52:51 +01:00
commit 35463d211f
5 changed files with 74 additions and 97 deletions

View File

@ -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."
}
]

View File

@ -0,0 +1,37 @@
<?xml version="1.0" encoding="UTF-8"?>
<protocol name="wl_eglstream_controller">
<copyright>
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.
</copyright>
<interface name="wl_eglstream_controller" version="1">
<request name="attach_eglstream_consumer">
<description summary="Create server stream and attach consumer">
Creates the corresponding server side EGLStream from the given wl_buffer
and attaches a consumer to it.
</description>
<arg name="wl_surface" type="object" interface="wl_surface"
summary="wl_surface corresponds to the client surface associated with
newly created eglstream"/>
<arg name="wl_resource" type="object" interface="wl_buffer"
summary="wl_resource corresponding to an EGLStream"/>
</request>
</interface>
</protocol>

View File

@ -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 {

View File

@ -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<QWaylandWindow*>(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)

View File

@ -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;