summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGiulio Camuffo <giulio.camuffo@jollamobile.com>2015-03-19 10:52:03 +0200
committerGiulio Camuffo <giulio.camuffo@jollamobile.com>2015-07-15 07:09:55 +0000
commit6c47babc1a3566c7186e3196e7975df2be9b575b (patch)
tree9fce1d93e02d48346ffa1ecfeebbc8a6adf4ef62
parentab3b7de2405f92cd01efb8a7717a4924c7630d5f (diff)
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.cpp7
-rw-r--r--src/compositor/compositor_api/qwaylandbufferref.h3
-rw-r--r--src/compositor/compositor_api/qwaylandquicksurface.cpp22
-rw-r--r--src/compositor/compositor_api/qwaylandsurface.cpp26
-rw-r--r--src/compositor/compositor_api/qwaylandsurface.h12
-rw-r--r--src/compositor/compositor_api/qwaylandsurfaceitem.cpp4
-rw-r--r--src/compositor/wayland_wrapper/qwlsurface.cpp29
-rw-r--r--src/compositor/wayland_wrapper/qwlsurface_p.h6
-rw-r--r--tests/auto/compositor/tst_compositor.cpp3
9 files changed, 91 insertions, 21 deletions
diff --git a/examples/wayland/qwindow-compositor/qwindowcompositor.cpp b/examples/wayland/qwindow-compositor/qwindowcompositor.cpp
index 0b39f1102..5d338692f 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 213474fab..103a1b388 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 ef78c8849..c8edcb6bc 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 f71504c65..d1bcb6efb 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 653d74c1b..db1e1fb44 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 93cfaf008..0c48df382 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 a20e91142..9b3789087 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 a41d78880..d08fb4cd6 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 8932374ca..c30ebc02b 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
{