From f52b53996c5bb98e25316e3716e49afb3f64b494 Mon Sep 17 00:00:00 2001 From: Elvis Lee Date: Fri, 29 Jan 2016 11:31:06 +0900 Subject: [PATCH 1/4] Fix crash for destroyed surface on touch event Change-Id: Ia3dd8627c1b96a88d308dc7fa85d936f809c7856 Reviewed-by: Elvis Lee Reviewed-by: Paul Olav Tvete --- src/plugins/platforms/wayland/qwaylandinputdevice.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/plugins/platforms/wayland/qwaylandinputdevice.cpp b/src/plugins/platforms/wayland/qwaylandinputdevice.cpp index 567620ba50d..e0a5ce9441a 100644 --- a/src/plugins/platforms/wayland/qwaylandinputdevice.cpp +++ b/src/plugins/platforms/wayland/qwaylandinputdevice.cpp @@ -253,6 +253,8 @@ void QWaylandInputDevice::handleWindowDestroyed(QWaylandWindow *window) mKeyboard->mFocus = 0; mKeyboard->stopRepeat(); } + if (mTouch && window == mTouch->mFocus) + mTouch->mFocus = 0; } void QWaylandInputDevice::setDataDevice(QWaylandDataDevice *device) @@ -739,6 +741,9 @@ void QWaylandInputDevice::Touch::touch_down(uint32_t serial, wl_fixed_t x, wl_fixed_t y) { + if (!surface) + return; + mParent->mTime = time; mParent->mSerial = serial; mFocus = QWaylandWindow::fromWlSurface(surface); From 9d119e5c963e467fd2e2dc425b03d7f46901712f Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Fri, 12 Feb 2016 16:50:44 +0100 Subject: [PATCH 2/4] consistently put {qt,qml}_{module,plugin} at the end of project files this fixes static builds by ensuring that all dependencies are exported. Task-number: QTBUG-51071 Change-Id: Ie9e89fa47696244e8ee478ed1a019765c835533e Reviewed-by: Paul Olav Tvete --- src/plugins/platforms/wayland/client.pro | 19 +++++++++---------- .../plugins/decorations/bradient/bradient.pro | 5 ++--- .../hardwareintegration/brcm-egl/brcm-egl.pro | 5 ++--- .../drm-egl-server/drm-egl-server.pro | 5 ++--- .../libhybris-egl-server.pro | 5 ++--- .../wayland-egl/wayland-egl.pro | 5 ++--- .../xcomposite-egl/xcomposite-egl.pro | 5 ++--- .../xcomposite-glx/xcomposite-glx.pro | 5 ++--- 8 files changed, 23 insertions(+), 31 deletions(-) diff --git a/src/plugins/platforms/wayland/client.pro b/src/plugins/platforms/wayland/client.pro index 8bd9e1dc83a..1a0779834fc 100644 --- a/src/plugins/platforms/wayland/client.pro +++ b/src/plugins/platforms/wayland/client.pro @@ -1,17 +1,9 @@ TARGET = QtWaylandClient +MODULE = waylandclient + QT += core-private gui-private QT_FOR_PRIVATE += platformsupport-private -MODULE=waylandclient -MODULE_PLUGIN_TYPES = \ - wayland-graphics-integration-client \ - wayland-inputdevice-integration \ - wayland-decoration-client - -CONFIG += generated_privates - -load(qt_module) - # We have a bunch of C code with casts, so we can't have this option QMAKE_CXXFLAGS_WARN_ON -= -Wcast-qual @@ -117,3 +109,10 @@ HEADERS += qwaylandintegration_p.h \ include(hardwareintegration/hardwareintegration.pri) include(shellintegration/shellintegration.pri) include(inputdeviceintegration/inputdeviceintegration.pri) + +CONFIG += generated_privates +MODULE_PLUGIN_TYPES = \ + wayland-graphics-integration-client \ + wayland-inputdevice-integration \ + wayland-decoration-client +load(qt_module) diff --git a/src/plugins/platforms/wayland/plugins/decorations/bradient/bradient.pro b/src/plugins/platforms/wayland/plugins/decorations/bradient/bradient.pro index fd376f4a985..0f62db9cc9d 100644 --- a/src/plugins/platforms/wayland/plugins/decorations/bradient/bradient.pro +++ b/src/plugins/platforms/wayland/plugins/decorations/bradient/bradient.pro @@ -1,6 +1,3 @@ -PLUGIN_TYPE = wayland-decoration-client -load(qt_plugin) - QT += waylandclient-private OTHER_FILES += \ @@ -15,3 +12,5 @@ contains(QT_CONFIG, no-pkg-config) { PKGCONFIG += wayland-client } +PLUGIN_TYPE = wayland-decoration-client +load(qt_plugin) diff --git a/src/plugins/platforms/wayland/plugins/hardwareintegration/brcm-egl/brcm-egl.pro b/src/plugins/platforms/wayland/plugins/hardwareintegration/brcm-egl/brcm-egl.pro index 6dbe53732ed..550343cfe99 100644 --- a/src/plugins/platforms/wayland/plugins/hardwareintegration/brcm-egl/brcm-egl.pro +++ b/src/plugins/platforms/wayland/plugins/hardwareintegration/brcm-egl/brcm-egl.pro @@ -1,6 +1,3 @@ -PLUGIN_TYPE = wayland-graphics-integration-client -load(qt_plugin) - QT += waylandclient-private include(../../../../hardwareintegration/client/brcm-egl/brcm-egl.pri) @@ -10,3 +7,5 @@ OTHER_FILES += \ SOURCES += main.cpp +PLUGIN_TYPE = wayland-graphics-integration-client +load(qt_plugin) diff --git a/src/plugins/platforms/wayland/plugins/hardwareintegration/drm-egl-server/drm-egl-server.pro b/src/plugins/platforms/wayland/plugins/hardwareintegration/drm-egl-server/drm-egl-server.pro index 827228d2bdd..29a48c9e6e7 100644 --- a/src/plugins/platforms/wayland/plugins/hardwareintegration/drm-egl-server/drm-egl-server.pro +++ b/src/plugins/platforms/wayland/plugins/hardwareintegration/drm-egl-server/drm-egl-server.pro @@ -1,6 +1,3 @@ -PLUGIN_TYPE = wayland-graphics-integration-client -load(qt_plugin) - # We have a bunch of C code with casts, so we can't have this option QMAKE_CXXFLAGS_WARN_ON -= -Wcast-qual @@ -13,3 +10,5 @@ OTHER_FILES += \ SOURCES += main.cpp +PLUGIN_TYPE = wayland-graphics-integration-client +load(qt_plugin) diff --git a/src/plugins/platforms/wayland/plugins/hardwareintegration/libhybris-egl-server/libhybris-egl-server.pro b/src/plugins/platforms/wayland/plugins/hardwareintegration/libhybris-egl-server/libhybris-egl-server.pro index 55f98415d58..d7bf03705ce 100644 --- a/src/plugins/platforms/wayland/plugins/hardwareintegration/libhybris-egl-server/libhybris-egl-server.pro +++ b/src/plugins/platforms/wayland/plugins/hardwareintegration/libhybris-egl-server/libhybris-egl-server.pro @@ -1,6 +1,3 @@ -PLUGIN_TYPE = wayland-graphics-integration-client -load(qt_plugin) - QT += waylandclient-private include(../../../../hardwareintegration/client/libhybris-egl-server/libhybris-egl-server.pri) @@ -10,3 +7,5 @@ OTHER_FILES += \ SOURCES += main.cpp +PLUGIN_TYPE = wayland-graphics-integration-client +load(qt_plugin) diff --git a/src/plugins/platforms/wayland/plugins/hardwareintegration/wayland-egl/wayland-egl.pro b/src/plugins/platforms/wayland/plugins/hardwareintegration/wayland-egl/wayland-egl.pro index 38989628886..076b6af2c34 100644 --- a/src/plugins/platforms/wayland/plugins/hardwareintegration/wayland-egl/wayland-egl.pro +++ b/src/plugins/platforms/wayland/plugins/hardwareintegration/wayland-egl/wayland-egl.pro @@ -1,6 +1,3 @@ -PLUGIN_TYPE = wayland-graphics-integration-client -load(qt_plugin) - QT += waylandclient-private include(../../../../hardwareintegration/client/wayland-egl/wayland-egl.pri) @@ -10,3 +7,5 @@ OTHER_FILES += \ SOURCES += main.cpp +PLUGIN_TYPE = wayland-graphics-integration-client +load(qt_plugin) diff --git a/src/plugins/platforms/wayland/plugins/hardwareintegration/xcomposite-egl/xcomposite-egl.pro b/src/plugins/platforms/wayland/plugins/hardwareintegration/xcomposite-egl/xcomposite-egl.pro index 1af1786695f..031d2812ad9 100644 --- a/src/plugins/platforms/wayland/plugins/hardwareintegration/xcomposite-egl/xcomposite-egl.pro +++ b/src/plugins/platforms/wayland/plugins/hardwareintegration/xcomposite-egl/xcomposite-egl.pro @@ -1,6 +1,3 @@ -PLUGIN_TYPE = wayland-graphics-integration-client -load(qt_plugin) - # We have a bunch of C code with casts, so we can't have this option QMAKE_CXXFLAGS_WARN_ON -= -Wcast-qual @@ -13,3 +10,5 @@ OTHER_FILES += xcomposite-egl.json SOURCES += \ main.cpp +PLUGIN_TYPE = wayland-graphics-integration-client +load(qt_plugin) diff --git a/src/plugins/platforms/wayland/plugins/hardwareintegration/xcomposite-glx/xcomposite-glx.pro b/src/plugins/platforms/wayland/plugins/hardwareintegration/xcomposite-glx/xcomposite-glx.pro index 0080150ccd1..eb8e03c7f33 100644 --- a/src/plugins/platforms/wayland/plugins/hardwareintegration/xcomposite-glx/xcomposite-glx.pro +++ b/src/plugins/platforms/wayland/plugins/hardwareintegration/xcomposite-glx/xcomposite-glx.pro @@ -1,6 +1,3 @@ -PLUGIN_TYPE = wayland-graphics-integration-client -load(qt_plugin) - QT += waylandclient-private include(../../../../hardwareintegration/client/xcomposite-glx/xcomposite-glx.pri) @@ -10,3 +7,5 @@ OTHER_FILES += xcomposite-glx.json SOURCES += \ main.cpp +PLUGIN_TYPE = wayland-graphics-integration-client +load(qt_plugin) From d9e3842afda97b4ac31c7d562c7923c65cb98b33 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Fri, 12 Feb 2016 16:51:28 +0100 Subject: [PATCH 3/4] don't over-expose private dependencies Change-Id: If46406b4129b464e8ccfa0b4cf6ff2989402ca74 Reviewed-by: Paul Olav Tvete --- src/plugins/platforms/wayland/client.pro | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/plugins/platforms/wayland/client.pro b/src/plugins/platforms/wayland/client.pro index 1a0779834fc..2895e19d759 100644 --- a/src/plugins/platforms/wayland/client.pro +++ b/src/plugins/platforms/wayland/client.pro @@ -16,19 +16,19 @@ CONFIG += link_pkgconfig qpa/genericunixfontdatabase wayland-scanner config_xkbcommon { !contains(QT_CONFIG, no-pkg-config) { - PKGCONFIG += xkbcommon + PKGCONFIG_PRIVATE += xkbcommon } else { - LIBS += -lxkbcommon + LIBS_PRIVATE += -lxkbcommon } } else { DEFINES += QT_NO_WAYLAND_XKB } !contains(QT_CONFIG, no-pkg-config) { - PKGCONFIG += wayland-client wayland-cursor + PKGCONFIG_PRIVATE += wayland-client wayland-cursor contains(QT_CONFIG, glib): PKGCONFIG_PRIVATE += glib-2.0 } else { - LIBS += -lwayland-client -lwayland-cursor $$QT_LIBS_GLIB + LIBS_PRIVATE += -lwayland-client -lwayland-cursor $$QT_LIBS_GLIB } INCLUDEPATH += $$PWD/../shared From 330e3a78695bbe7f439676831b2336f3e5e26521 Mon Sep 17 00:00:00 2001 From: Giulio Camuffo Date: Fri, 11 Dec 2015 22:27:49 +0200 Subject: [PATCH 4/4] Fix SHM drawing logic The old logic didn't care to listen for wl_buffer.release events so it always drew in the same buffer, potentially resulting in tearing if the compositor was scanning out the buffer at the same time. Instead properly cycle between a few buffers and don't reuse the same one until the release event was received. The old code also used to throttle the redraws, unless the buffer was changing, that is unless the window was getting resized. This is now lost, and no throttling is ever done. Doing it properly, by waiting for the frame callback before committing the new buffer shows very noticeable lags with many applications when resizing, because they paint many times per resize event, so they fall behind the cursor. A proper fix will be to implement the support for requestUpdate(), and using it in the applications. Change-Id: I02732c34769a5c75a6ad68c095bae916e4b274d3 Reviewed-by: Robin Burchell --- src/plugins/platforms/wayland/client.pro | 1 + .../platforms/wayland/qwaylandbuffer.cpp | 72 +++++++++ .../platforms/wayland/qwaylandbuffer_p.h | 18 ++- .../wayland/qwaylandshmbackingstore.cpp | 150 ++++++++---------- .../wayland/qwaylandshmbackingstore_p.h | 10 +- .../platforms/wayland/qwaylandwindow.cpp | 15 +- .../platforms/wayland/qwaylandwindow_p.h | 1 - 7 files changed, 157 insertions(+), 110 deletions(-) create mode 100644 src/plugins/platforms/wayland/qwaylandbuffer.cpp diff --git a/src/plugins/platforms/wayland/client.pro b/src/plugins/platforms/wayland/client.pro index 2895e19d759..59234b14e74 100644 --- a/src/plugins/platforms/wayland/client.pro +++ b/src/plugins/platforms/wayland/client.pro @@ -73,6 +73,7 @@ SOURCES += qwaylandintegration.cpp \ qwaylandwindowmanagerintegration.cpp \ qwaylandinputcontext.cpp \ qwaylanddatadevice.cpp \ + qwaylandbuffer.cpp \ HEADERS += qwaylandintegration_p.h \ qwaylandnativeinterface_p.h \ diff --git a/src/plugins/platforms/wayland/qwaylandbuffer.cpp b/src/plugins/platforms/wayland/qwaylandbuffer.cpp new file mode 100644 index 00000000000..c6aace2c7ce --- /dev/null +++ b/src/plugins/platforms/wayland/qwaylandbuffer.cpp @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Copyright (C) 2015 Giulio Camuffo. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qwaylandbuffer_p.h" + +#include + +QT_BEGIN_NAMESPACE + +namespace QtWaylandClient { + +QWaylandBuffer::QWaylandBuffer() + : mBuffer(0) + , mBusy(false) +{ +} + +QWaylandBuffer::~QWaylandBuffer() +{ + if (mBuffer) + wl_buffer_destroy(mBuffer); +} + +void QWaylandBuffer::init(wl_buffer *buf) +{ + mBuffer = buf; + wl_buffer_add_listener(buf, &listener, this); +} + +void QWaylandBuffer::release(void *data, wl_buffer *) +{ + static_cast(data)->mBusy = false; +} + +const wl_buffer_listener QWaylandBuffer::listener = { + QWaylandBuffer::release +}; + +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/wayland/qwaylandbuffer_p.h b/src/plugins/platforms/wayland/qwaylandbuffer_p.h index 6f8f7b269a9..7db6cfefec9 100644 --- a/src/plugins/platforms/wayland/qwaylandbuffer_p.h +++ b/src/plugins/platforms/wayland/qwaylandbuffer_p.h @@ -59,17 +59,25 @@ namespace QtWaylandClient { class Q_WAYLAND_CLIENT_EXPORT QWaylandBuffer { public: - QWaylandBuffer() - : mBuffer(0) - { - } - virtual ~QWaylandBuffer() { } + QWaylandBuffer(); + virtual ~QWaylandBuffer(); + void init(wl_buffer *buf); + wl_buffer *buffer() {return mBuffer;} virtual QSize size() const = 0; virtual int scale() const { return 1; } + void setBusy() { mBusy = true; } + bool busy() const { return mBusy; } + protected: struct wl_buffer *mBuffer; + +private: + bool mBusy; + + static void release(void *data, wl_buffer *); + static const wl_buffer_listener listener; }; } diff --git a/src/plugins/platforms/wayland/qwaylandshmbackingstore.cpp b/src/plugins/platforms/wayland/qwaylandshmbackingstore.cpp index f009e08116b..3bbe24c318c 100644 --- a/src/plugins/platforms/wayland/qwaylandshmbackingstore.cpp +++ b/src/plugins/platforms/wayland/qwaylandshmbackingstore.cpp @@ -39,6 +39,7 @@ #include #include #include +#include #include #include @@ -53,9 +54,14 @@ QT_BEGIN_NAMESPACE namespace QtWaylandClient { +Q_DECLARE_LOGGING_CATEGORY(logCategory) + +Q_LOGGING_CATEGORY(logCategory, "qt.qpa.wayland.backingstore") + QWaylandShmBuffer::QWaylandShmBuffer(QWaylandDisplay *display, const QSize &size, QImage::Format format, int scale) - : mShmPool(0) + : QWaylandBuffer() + , mShmPool(0) , mMarginsImage(0) { int stride = size.width() * 4; @@ -90,8 +96,8 @@ QWaylandShmBuffer::QWaylandShmBuffer(QWaylandDisplay *display, mImage.setDevicePixelRatio(qreal(scale)); mShmPool = wl_shm_create_pool(display->shm(), fd, alloc); - mBuffer = wl_shm_pool_create_buffer(mShmPool,0, size.width(), size.height(), - stride, wl_format); + init(wl_shm_pool_create_buffer(mShmPool,0, size.width(), size.height(), + stride, wl_format)); close(fd); } @@ -100,8 +106,6 @@ QWaylandShmBuffer::~QWaylandShmBuffer(void) delete mMarginsImage; if (mImage.constBits()) munmap((void *) mImage.constBits(), mImage.byteCount()); - if (mBuffer) - wl_buffer_destroy(mBuffer); if (mShmPool) wl_shm_pool_destroy(mShmPool); } @@ -139,9 +143,7 @@ QWaylandShmBackingStore::QWaylandShmBackingStore(QWindow *window) , mDisplay(QWaylandScreen::waylandScreenFromWindow(window)->display()) , mFrontBuffer(0) , mBackBuffer(0) - , mFrontBufferIsDirty(false) , mPainting(false) - , mFrameCallback(0) { } @@ -151,16 +153,10 @@ QWaylandShmBackingStore::~QWaylandShmBackingStore() if (QWaylandWindow *w = waylandWindow()) w->setBackingStore(Q_NULLPTR); - if (mFrameCallback) - wl_callback_destroy(mFrameCallback); - // if (mFrontBuffer == waylandWindow()->attached()) // waylandWindow()->attach(0); - if (mFrontBuffer != mBackBuffer) - delete mFrontBuffer; - - delete mBackBuffer; + qDeleteAll(mBuffers); } QPaintDevice *QWaylandShmBackingStore::paintDevice() @@ -173,11 +169,7 @@ void QWaylandShmBackingStore::beginPaint(const QRegion &) mPainting = true; ensureSize(); - QWaylandWindow *window = waylandWindow(); - if (window->attached() && mBackBuffer == window->attached() && mFrameCallback) - window->waitForFrameSync(); - - window->setCanResize(false); + waylandWindow()->setCanResize(false); } void QWaylandShmBackingStore::endPaint() @@ -188,11 +180,6 @@ void QWaylandShmBackingStore::endPaint() void QWaylandShmBackingStore::hidden() { - QMutexLocker lock(&mMutex); - if (mFrameCallback) { - wl_callback_destroy(mFrameCallback); - mFrameCallback = Q_NULLPTR; - } } void QWaylandShmBackingStore::ensureSize() @@ -219,35 +206,15 @@ void QWaylandShmBackingStore::flush(QWindow *window, const QRegion ®ion, cons mFrontBuffer = mBackBuffer; - if (mFrameCallback) { - mFrontBufferIsDirty = true; - return; - } - - mFrameCallback = waylandWindow()->frame(); - wl_callback_add_listener(mFrameCallback,&frameCallbackListener,this); QMargins margins = windowDecorationMargins(); - bool damageAll = false; - if (waylandWindow()->attached() != mFrontBuffer) { - delete waylandWindow()->attached(); - damageAll = true; - } waylandWindow()->attachOffset(mFrontBuffer); + mFrontBuffer->setBusy(); - if (damageAll) { - //need to damage it all, otherwise the attach offset may screw up - waylandWindow()->damage(QRect(QPoint(0,0), window->size())); - } else { - QVector rects = region.rects(); - for (int i = 0; i < rects.size(); i++) { - QRect rect = rects.at(i); - rect.translate(margins.left(),margins.top()); - waylandWindow()->damage(rect); - } - } + QVector rects = region.rects(); + foreach (const QRect &rect, rects) + waylandWindow()->damage(rect.translated(margins.left(), margins.top())); waylandWindow()->commit(); - mFrontBufferIsDirty = false; } void QWaylandShmBackingStore::resize(const QSize &size, const QRegion &) @@ -255,22 +222,65 @@ void QWaylandShmBackingStore::resize(const QSize &size, const QRegion &) mRequestedSize = size; } +QWaylandShmBuffer *QWaylandShmBackingStore::getBuffer(const QSize &size) +{ + foreach (QWaylandShmBuffer *b, mBuffers) { + if (!b->busy()) { + if (b->size() == size) { + return b; + } else { + mBuffers.removeOne(b); + if (mBackBuffer == b) + mBackBuffer = 0; + delete b; + } + } + } + + static const int MAX_BUFFERS = 5; + if (mBuffers.count() < MAX_BUFFERS) { + QImage::Format format = QPlatformScreen::platformScreenForWindow(window())->format(); + QWaylandShmBuffer *b = new QWaylandShmBuffer(mDisplay, size, format, waylandWindow()->scale()); + mBuffers.prepend(b); + return b; + } + return 0; +} + void QWaylandShmBackingStore::resize(const QSize &size) { QMargins margins = windowDecorationMargins(); int scale = waylandWindow()->scale(); QSize sizeWithMargins = (size + QSize(margins.left()+margins.right(),margins.top()+margins.bottom())) * scale; - QImage::Format format = QPlatformScreen::platformScreenForWindow(window())->format(); + // We look for a free buffer to draw into. If the buffer is not the last buffer we used, + // that is mBackBuffer, and the size is the same we memcpy the old content into the new + // buffer so that QPainter is happy to find the stuff it had drawn before. If the new + // buffer has a different size it needs to be redrawn completely anyway, and if the buffer + // is the same the stuff is there already. + // You can exercise the different codepaths with weston, switching between the gl and the + // pixman renderer. With the gl renderer release events are sent early so we can effectively + // run single buffered, while with the pixman renderer we have to use two. + QWaylandShmBuffer *buffer = getBuffer(sizeWithMargins); + while (!buffer) { + qCDebug(logCategory, "QWaylandShmBackingStore: stalling waiting for a buffer to be released from the compositor..."); - if (mBackBuffer != NULL && mBackBuffer->size() == sizeWithMargins) - return; - - if (mBackBuffer != mFrontBuffer) { - delete mBackBuffer; //we delete the attached buffer when we flush + mDisplay->blockingReadEvents(); + buffer = getBuffer(sizeWithMargins); } - mBackBuffer = new QWaylandShmBuffer(mDisplay, sizeWithMargins, format, scale); + int oldSize = mBackBuffer ? mBackBuffer->image()->byteCount() : 0; + // mBackBuffer may have been deleted here but if so it means its size was different so we wouldn't copy it anyway + if (mBackBuffer != buffer && oldSize == buffer->image()->byteCount()) { + memcpy(buffer->image()->bits(), mBackBuffer->image()->constBits(), buffer->image()->byteCount()); + } + mBackBuffer = buffer; + // ensure the new buffer is at the beginning of the list so next time getBuffer() will pick + // it if possible + if (mBuffers.first() != buffer) { + mBuffers.removeOne(buffer); + mBuffers.prepend(buffer); + } if (windowDecoration() && window()->isVisible()) windowDecoration()->update(); @@ -344,36 +354,6 @@ QImage QWaylandShmBackingStore::toImage() const } #endif // QT_NO_OPENGL -void QWaylandShmBackingStore::done(void *data, wl_callback *callback, uint32_t time) -{ - Q_UNUSED(time); - QWaylandShmBackingStore *self = - static_cast(data); - if (callback != self->mFrameCallback) // others, like QWaylandWindow, may trigger callbacks too - return; - QMutexLocker lock(&self->mMutex); - QWaylandWindow *window = self->waylandWindow(); - wl_callback_destroy(self->mFrameCallback); - self->mFrameCallback = 0; - - - if (self->mFrontBufferIsDirty && !self->mPainting) { - self->mFrontBufferIsDirty = false; - self->mFrameCallback = wl_surface_frame(window->object()); - wl_callback_add_listener(self->mFrameCallback,&self->frameCallbackListener,self); - if (self->mFrontBuffer != window->attached()) { - delete window->attached(); - } - window->attachOffset(self->mFrontBuffer); - window->damage(QRect(QPoint(0,0),window->geometry().size())); - window->commit(); - } -} - -const struct wl_callback_listener QWaylandShmBackingStore::frameCallbackListener = { - QWaylandShmBackingStore::done -}; - } QT_END_NAMESPACE diff --git a/src/plugins/platforms/wayland/qwaylandshmbackingstore_p.h b/src/plugins/platforms/wayland/qwaylandshmbackingstore_p.h index a1a6e19c3ce..8b58c0b5eda 100644 --- a/src/plugins/platforms/wayland/qwaylandshmbackingstore_p.h +++ b/src/plugins/platforms/wayland/qwaylandshmbackingstore_p.h @@ -51,6 +51,7 @@ #include #include #include +#include QT_BEGIN_NAMESPACE @@ -107,22 +108,17 @@ public: private: void updateDecorations(); + QWaylandShmBuffer *getBuffer(const QSize &size); QWaylandDisplay *mDisplay; + QLinkedList mBuffers; QWaylandShmBuffer *mFrontBuffer; QWaylandShmBuffer *mBackBuffer; - bool mFrontBufferIsDirty; bool mPainting; QMutex mMutex; QSize mRequestedSize; Qt::WindowFlags mCurrentWindowFlags; - - static const struct wl_callback_listener frameCallbackListener; - static void done(void *data, - struct wl_callback *callback, - uint32_t time); - struct wl_callback *mFrameCallback; }; } diff --git a/src/plugins/platforms/wayland/qwaylandwindow.cpp b/src/plugins/platforms/wayland/qwaylandwindow.cpp index fa4e20f948b..caf24c0aab9 100644 --- a/src/plugins/platforms/wayland/qwaylandwindow.cpp +++ b/src/plugins/platforms/wayland/qwaylandwindow.cpp @@ -74,7 +74,6 @@ QWaylandWindow::QWaylandWindow(QWindow *window) , mMouseEventsInContentArea(false) , mMousePressedInContentArea(Qt::NoButton) , m_cursorShape(Qt::ArrowCursor) - , mBuffer(0) , mWaitingForFrameSync(false) , mFrameCallback(0) , mRequestResizeSent(false) @@ -412,9 +411,8 @@ void QWaylandWindow::requestResize() void QWaylandWindow::attach(QWaylandBuffer *buffer, int x, int y) { - mBuffer = buffer; - if (mBuffer) - attach(mBuffer->buffer(), x, y); + if (buffer) + attach(buffer->buffer(), x, y); else QtWayland::wl_surface::attach(0, 0, 0); } @@ -425,11 +423,6 @@ void QWaylandWindow::attachOffset(QWaylandBuffer *buffer) mOffset = QPoint(); } -QWaylandBuffer *QWaylandWindow::attached() const -{ - return mBuffer; -} - void QWaylandWindow::damage(const QRect &rect) { //We have to do sync stuff before calling damage, or we might @@ -439,9 +432,7 @@ void QWaylandWindow::damage(const QRect &rect) wl_callback_add_listener(mFrameCallback,&QWaylandWindow::callbackListener,this); mWaitingForFrameSync = true; } - if (mBuffer) { - damage(rect.x(), rect.y(), rect.width(), rect.height()); - } + damage(rect.x(), rect.y(), rect.width(), rect.height()); } const wl_callback_listener QWaylandWindow::callbackListener = { diff --git a/src/plugins/platforms/wayland/qwaylandwindow_p.h b/src/plugins/platforms/wayland/qwaylandwindow_p.h index be8f53088dd..701a9cdf6d0 100644 --- a/src/plugins/platforms/wayland/qwaylandwindow_p.h +++ b/src/plugins/platforms/wayland/qwaylandwindow_p.h @@ -208,7 +208,6 @@ protected: Qt::MouseButtons mMousePressedInContentArea; Qt::CursorShape m_cursorShape; - QWaylandBuffer *mBuffer; WId mWindowId; bool mWaitingForFrameSync; struct wl_callback *mFrameCallback;