From ebbb82906daa547258d97434bcd08e0ec1fde487 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Gr=C3=A4=C3=9Flin?= Date: Mon, 21 Mar 2016 16:37:45 +0100 Subject: [PATCH] Add support for SubSurface to WindowPixmap This change introduces a tree for WindowPixmap. A WindowPixmap can have a parent WindowPixmap and children. Each child represents a SubSurface and references the buffer of that SubSurface. The tree of WindowPixmaps is updated each time updateBuffer is called. If there are new SubSurfaces new WindowPixmaps are created, for removed SubSurfaces the old WindowPixmap gets removed. Also the ordering is updated to reflect the current state. This is currently rather expensive and should be changed to only rebuild the tree if it actually changed. --- scene.cpp | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++++-- scene.h | 37 ++++++++++++++++++++++++++++++- 2 files changed, 99 insertions(+), 3 deletions(-) diff --git a/scene.cpp b/scene.cpp index 27da36e893..89eeeb9bb0 100644 --- a/scene.cpp +++ b/scene.cpp @@ -82,6 +82,7 @@ along with this program. If not, see . #include "thumbnailitem.h" #include +#include #include namespace KWin @@ -937,6 +938,15 @@ WindowPixmap::WindowPixmap(Scene::Window *window) { } +WindowPixmap::WindowPixmap(const QPointer &subSurface, WindowPixmap *parent) + : m_window(parent->m_window) + , m_pixmap(XCB_PIXMAP_NONE) + , m_discarded(false) + , m_parent(parent) + , m_subSurface(subSurface) +{ +} + WindowPixmap::~WindowPixmap() { if (isValid() && !kwinApp()->shouldUseWaylandForCompositing()) { @@ -957,7 +967,7 @@ void WindowPixmap::create() if (kwinApp()->shouldUseWaylandForCompositing()) { // use Buffer updateBuffer(); - if (m_buffer || !m_fbo.isNull()) { + if ((m_buffer || !m_fbo.isNull()) && m_subSurface.isNull()) { m_window->unreferencePreviousPixmap(); } return; @@ -991,6 +1001,12 @@ void WindowPixmap::create() m_window->unreferencePreviousPixmap(); } +WindowPixmap *WindowPixmap::createChild(const QPointer &subSurface) +{ + Q_UNUSED(subSurface) + return nullptr; +} + bool WindowPixmap::isValid() const { if (kwinApp()->shouldUseWaylandForCompositing()) { @@ -1001,9 +1017,42 @@ bool WindowPixmap::isValid() const void WindowPixmap::updateBuffer() { - if (auto s = toplevel()->surface()) { + using namespace KWayland::Server; + SurfaceInterface *s = nullptr; + if (!m_subSurface.isNull()) { + s = m_subSurface->surface().data(); + } else { + s = toplevel()->surface(); + } + if (s) { + QVector oldTree = m_children; + QVector children; using namespace KWayland::Server; + const auto subSurfaces = s->childSubSurfaces(); + for (const auto &subSurface : subSurfaces) { + if (subSurface.isNull()) { + continue; + } + auto it = std::find_if(oldTree.begin(), oldTree.end(), [subSurface] (WindowPixmap *p) { return p->m_subSurface == subSurface; }); + if (it != oldTree.end()) { + children << *it; + (*it)->updateBuffer(); + oldTree.erase(it); + } else { + WindowPixmap *p = createChild(subSurface); + if (p) { + p->create(); + children << p; + } + } + } + setChildren(children); + qDeleteAll(oldTree); if (auto b = s->buffer()) { + if (b == m_buffer) { + // no change + return; + } if (m_buffer) { QObject::disconnect(m_buffer.data(), &BufferInterface::aboutToBeDestroyed, m_buffer.data(), &BufferInterface::unref); m_buffer->unref(); @@ -1011,6 +1060,12 @@ void WindowPixmap::updateBuffer() m_buffer = b; m_buffer->ref(); QObject::connect(m_buffer.data(), &BufferInterface::aboutToBeDestroyed, m_buffer.data(), &BufferInterface::unref); + } else if (m_subSurface) { + if (m_buffer) { + QObject::disconnect(m_buffer.data(), &BufferInterface::aboutToBeDestroyed, m_buffer.data(), &BufferInterface::unref); + m_buffer->unref(); + m_buffer.clear(); + } } else { // might be an internal window const auto &fbo = toplevel()->internalFramebufferObject(); @@ -1018,6 +1073,12 @@ void WindowPixmap::updateBuffer() m_fbo = fbo; } } + } else { + if (m_buffer) { + QObject::disconnect(m_buffer.data(), &BufferInterface::aboutToBeDestroyed, m_buffer.data(), &BufferInterface::unref); + m_buffer->unref(); + m_buffer.clear(); + } } } diff --git a/scene.h b/scene.h index 279f71394d..7eb1347da7 100644 --- a/scene.h +++ b/scene.h @@ -35,6 +35,7 @@ namespace KWayland namespace Server { class BufferInterface; +class SubSurfaceInterface; } } @@ -392,8 +393,31 @@ public: */ Toplevel *toplevel() const; + /** + * @returns the parent WindowPixmap in the sub-surface tree + **/ + WindowPixmap *parent() const { + return m_parent; + } + + /** + * @returns the current sub-surface tree + **/ + QVector children() const { + return m_children; + } + + /** + * @returns the subsurface this WindowPixmap is for if it is not for a root window + **/ + QPointer subSurface() const { + return m_subSurface; + } + protected: explicit WindowPixmap(Scene::Window *window); + explicit WindowPixmap(const QPointer &subSurface, WindowPixmap *parent); + virtual WindowPixmap *createChild(const QPointer &subSurface); /** * @return The Window this WindowPixmap belongs to */ @@ -403,7 +427,15 @@ protected: * Should be called by the implementing subclasses when the Wayland Buffer changed and needs * updating. **/ - void updateBuffer(); + virtual void updateBuffer(); + + /** + * Sets the sub-surface tree to @p children. + **/ + void setChildren(const QVector &children) { + m_children = children; + } + private: Scene::Window *m_window; xcb_pixmap_t m_pixmap; @@ -412,6 +444,9 @@ private: QRect m_contentsRect; QPointer m_buffer; QSharedPointer m_fbo; + WindowPixmap *m_parent = nullptr; + QVector m_children; + QPointer m_subSurface; }; class Scene::EffectFrame