diff options
author | Giulio Camuffo <giulio.camuffo@jollamobile.com> | 2015-03-19 10:52:03 +0200 |
---|---|---|
committer | Giulio Camuffo <giulio.camuffo@jollamobile.com> | 2015-07-15 07:09:55 +0000 |
commit | 6c47babc1a3566c7186e3196e7975df2be9b575b (patch) | |
tree | 9fce1d93e02d48346ffa1ecfeebbc8a6adf4ef62 | |
parent | ab3b7de2405f92cd01efb8a7717a4924c7630d5f (diff) | |
download | qtwayland-6c47babc1a3566c7186e3196e7975df2be9b575b.tar.gz |
Add a mechanism to delay unmapping of surfaces
When a client attachs a NULL buffer on a surface we may want to hang on
to the old buffer for a bit, e.g. to do a hide animation.
Add the QWaylandUnmapLock class to keep a surface mapped after an attach(0)
request.
Change-Id: I5d5be0b36410a76a58d2b68c1b2ac5e3b875a801
Reviewed-by: Robin Burchell <robin.burchell@viroteck.net>
-rw-r--r-- | examples/wayland/qwindow-compositor/qwindowcompositor.cpp | 7 | ||||
-rw-r--r-- | src/compositor/compositor_api/qwaylandbufferref.h | 3 | ||||
-rw-r--r-- | src/compositor/compositor_api/qwaylandquicksurface.cpp | 22 | ||||
-rw-r--r-- | src/compositor/compositor_api/qwaylandsurface.cpp | 26 | ||||
-rw-r--r-- | src/compositor/compositor_api/qwaylandsurface.h | 12 | ||||
-rw-r--r-- | src/compositor/compositor_api/qwaylandsurfaceitem.cpp | 4 | ||||
-rw-r--r-- | src/compositor/wayland_wrapper/qwlsurface.cpp | 29 | ||||
-rw-r--r-- | src/compositor/wayland_wrapper/qwlsurface_p.h | 6 | ||||
-rw-r--r-- | tests/auto/compositor/tst_compositor.cpp | 3 |
9 files changed, 91 insertions, 21 deletions
diff --git a/examples/wayland/qwindow-compositor/qwindowcompositor.cpp b/examples/wayland/qwindow-compositor/qwindowcompositor.cpp index 0b39f110..5d338692 100644 --- a/examples/wayland/qwindow-compositor/qwindowcompositor.cpp +++ b/examples/wayland/qwindow-compositor/qwindowcompositor.cpp @@ -98,6 +98,13 @@ public: } } + void unmap() + { + delete shmTex; + shmTex = 0; + bufferRef = QWaylandBufferRef(); + } + QImage image() const { if (!bufferRef || !bufferRef.isShm()) diff --git a/src/compositor/compositor_api/qwaylandbufferref.h b/src/compositor/compositor_api/qwaylandbufferref.h index 213474fa..103a1b38 100644 --- a/src/compositor/compositor_api/qwaylandbufferref.h +++ b/src/compositor/compositor_api/qwaylandbufferref.h @@ -65,7 +65,8 @@ public: #ifdef QT_COMPOSITOR_WAYLAND_GL /** * There must be a GL context bound when calling this function. - * It is responsibility of the caller to call destroyTexture() later. + * The texture will be automatically destroyed when the last QWaylandBufferRef + * referring to the same underlying buffer will be destroyed or reset. */ GLuint createTexture(); void destroyTexture(); diff --git a/src/compositor/compositor_api/qwaylandquicksurface.cpp b/src/compositor/compositor_api/qwaylandquicksurface.cpp index ef78c884..c8edcb6b 100644 --- a/src/compositor/compositor_api/qwaylandquicksurface.cpp +++ b/src/compositor/compositor_api/qwaylandquicksurface.cpp @@ -73,19 +73,12 @@ public: void createTexture() { - if (bufferRef) - bufferRef.destroyTexture(); bufferRef = nextBuffer; + delete texture; + texture = 0; QQuickWindow *window = static_cast<QQuickWindow *>(surface->mainOutput()->window()); - - // If the next buffer is NULL do not delete the current texture. If the client called - // attach(0) the surface is going to be unmapped anyway, if instead the client attached - // a valid buffer but died before we got here we want to keep the old buffer around - // in case some destroy animation is run. - if (bufferRef) { - delete texture; - + if (nextBuffer) { if (bufferRef.isShm()) { texture = window->createTextureFromImage(bufferRef.image()); } else { @@ -101,6 +94,12 @@ public: update = false; } + void unmap() Q_DECL_OVERRIDE + { + nextBuffer = QWaylandBufferRef(); + update = true; + } + void invalidateTexture() { if (bufferRef) @@ -141,9 +140,6 @@ public: void surface_commit(Resource *resource) Q_DECL_OVERRIDE { - if (m_pending.newlyAttached) { - buffer->update = true; - } QWaylandSurfacePrivate::surface_commit(resource); Q_FOREACH (QtWayland::Output *output, outputs()) diff --git a/src/compositor/compositor_api/qwaylandsurface.cpp b/src/compositor/compositor_api/qwaylandsurface.cpp index f71504c6..d1bcb6ef 100644 --- a/src/compositor/compositor_api/qwaylandsurface.cpp +++ b/src/compositor/compositor_api/qwaylandsurface.cpp @@ -511,4 +511,30 @@ void QWaylandSurfacePrivate::setType(QWaylandSurface::WindowType type) } } +class QWaylandUnmapLockPrivate +{ +public: + QWaylandSurface *surface; +}; + +/*! + Constructs a QWaylandUnmapLock object. + + The lock will act on the \a surface parameter, and will prevent the surface to + be unmapped, retaining the last valid buffer when the client attachs a NULL buffer. + The lock will be automatically released when deleted. +*/ +QWaylandUnmapLock::QWaylandUnmapLock(QWaylandSurface *surface) + : d(new QWaylandUnmapLockPrivate) +{ + d->surface = surface; + surface->handle()->addUnmapLock(this); +} + +QWaylandUnmapLock::~QWaylandUnmapLock() +{ + d->surface->handle()->removeUnmapLock(this); + delete d; +} + QT_END_NAMESPACE diff --git a/src/compositor/compositor_api/qwaylandsurface.h b/src/compositor/compositor_api/qwaylandsurface.h index 653d74c1..db1e1fb4 100644 --- a/src/compositor/compositor_api/qwaylandsurface.h +++ b/src/compositor/compositor_api/qwaylandsurface.h @@ -77,6 +77,7 @@ public: protected: virtual void attach(const QWaylandBufferRef &ref) = 0; + virtual void unmap() = 0; friend class QtWayland::Surface; }; @@ -261,6 +262,17 @@ Q_SIGNALS: friend class QtWayland::Surface; }; +class QWaylandUnmapLockPrivate; +class Q_COMPOSITOR_EXPORT QWaylandUnmapLock +{ +public: + QWaylandUnmapLock(QWaylandSurface *surface); + ~QWaylandUnmapLock(); + +private: + QWaylandUnmapLockPrivate *const d; +}; + QT_END_NAMESPACE #endif // QWAYLANDSURFACE_H diff --git a/src/compositor/compositor_api/qwaylandsurfaceitem.cpp b/src/compositor/compositor_api/qwaylandsurfaceitem.cpp index 93cfaf00..0c48df38 100644 --- a/src/compositor/compositor_api/qwaylandsurfaceitem.cpp +++ b/src/compositor/compositor_api/qwaylandsurfaceitem.cpp @@ -364,9 +364,7 @@ void QWaylandSurfaceItem::updateTexture(bool changed) if (!m_provider) m_provider = new QWaylandSurfaceTextureProvider(); - bool mapped = surface() && surface()->isMapped(); - if (mapped) - m_provider->t = static_cast<QWaylandQuickSurface *>(surface())->texture(); + m_provider->t = static_cast<QWaylandQuickSurface *>(surface())->texture(); m_provider->smooth = smooth(); if (m_newTexture || changed) emit m_provider->textureChanged(); diff --git a/src/compositor/wayland_wrapper/qwlsurface.cpp b/src/compositor/wayland_wrapper/qwlsurface.cpp index a20e9114..9b378908 100644 --- a/src/compositor/wayland_wrapper/qwlsurface.cpp +++ b/src/compositor/wayland_wrapper/qwlsurface.cpp @@ -200,7 +200,7 @@ bool Surface::isYInverted() const bool Surface::mapped() const { - return m_buffer ? bool(m_buffer->waylandBufferHandle()) : false; + return !m_unmapLocks.isEmpty() || (m_buffer && bool(m_buffer->waylandBufferHandle())); } QSize Surface::size() const @@ -366,7 +366,8 @@ void Surface::setBackBuffer(SurfaceBuffer *buffer) if (m_buffer) { bool valid = m_buffer->waylandBufferHandle() != 0; - setSize(valid ? m_buffer->size() : QSize()); + if (valid) + setSize(m_buffer->size()); m_damage = m_damage.intersected(QRect(QPoint(), m_size)); emit m_waylandSurface->damaged(m_damage); @@ -387,6 +388,20 @@ void Surface::setMapped(bool mapped) } } +void Surface::addUnmapLock(QWaylandUnmapLock *l) +{ + m_unmapLocks << l; +} + +void Surface::removeUnmapLock(QWaylandUnmapLock *l) +{ + m_unmapLocks.removeOne(l); + if (!mapped() && m_attacher) { + setSize(QSize()); + m_attacher->unmap(); + } +} + SurfaceBuffer *Surface::createSurfaceBuffer(struct ::wl_resource *buffer) { SurfaceBuffer *newBuffer = 0; @@ -473,8 +488,14 @@ void Surface::surface_commit(Resource *) setBackBuffer(m_pending.buffer); m_bufferRef = QWaylandBufferRef(m_buffer); - if (m_attacher) - m_attacher->attach(m_bufferRef); + if (m_attacher) { + if (m_bufferRef) { + m_attacher->attach(m_bufferRef); + } else if (!mapped()) { + setSize(QSize()); + m_attacher->unmap(); + } + } emit m_waylandSurface->configure(m_bufferRef); if (m_roleHandler) m_roleHandler->configure(m_pending.offset.x(), m_pending.offset.y()); diff --git a/src/compositor/wayland_wrapper/qwlsurface_p.h b/src/compositor/wayland_wrapper/qwlsurface_p.h index a41d7888..d08fb4cd 100644 --- a/src/compositor/wayland_wrapper/qwlsurface_p.h +++ b/src/compositor/wayland_wrapper/qwlsurface_p.h @@ -65,6 +65,8 @@ QT_BEGIN_NAMESPACE class QTouchEvent; +class QWaylandUnmapLock; + namespace QtWayland { class Compositor; @@ -149,6 +151,9 @@ public: void releaseSurfaces(); void frameStarted(); + void addUnmapLock(QWaylandUnmapLock *l); + void removeUnmapLock(QWaylandUnmapLock *l); + void setMapped(bool mapped); void setVisibility(QWindow::Visibility visibility) { m_visibility = visibility; } @@ -185,6 +190,7 @@ protected: QWaylandBufferRef m_bufferRef; bool m_surfaceMapped; QWaylandBufferAttacher *m_attacher; + QVector<QWaylandUnmapLock *> m_unmapLocks; struct { SurfaceBuffer *buffer; diff --git a/tests/auto/compositor/tst_compositor.cpp b/tests/auto/compositor/tst_compositor.cpp index 8932374c..c30ebc02 100644 --- a/tests/auto/compositor/tst_compositor.cpp +++ b/tests/auto/compositor/tst_compositor.cpp @@ -251,6 +251,9 @@ void tst_WaylandCompositor::frameCallback() { bufferRef = ref; } + void unmap() Q_DECL_OVERRIDE + { + } QImage image() const { |