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.
master
Martin Gräßlin 9 years ago
parent 952122dbe1
commit ebbb82906d

@ -82,6 +82,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "thumbnailitem.h"
#include <KWayland/Server/buffer_interface.h>
#include <KWayland/Server/subcompositor_interface.h>
#include <KWayland/Server/surface_interface.h>
namespace KWin
@ -937,6 +938,15 @@ WindowPixmap::WindowPixmap(Scene::Window *window)
{
}
WindowPixmap::WindowPixmap(const QPointer<KWayland::Server::SubSurfaceInterface> &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<KWayland::Server::SubSurfaceInterface> &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<WindowPixmap*> oldTree = m_children;
QVector<WindowPixmap*> 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();
}
}
}

@ -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<WindowPixmap*> children() const {
return m_children;
}
/**
* @returns the subsurface this WindowPixmap is for if it is not for a root window
**/
QPointer<KWayland::Server::SubSurfaceInterface> subSurface() const {
return m_subSurface;
}
protected:
explicit WindowPixmap(Scene::Window *window);
explicit WindowPixmap(const QPointer<KWayland::Server::SubSurfaceInterface> &subSurface, WindowPixmap *parent);
virtual WindowPixmap *createChild(const QPointer<KWayland::Server::SubSurfaceInterface> &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<WindowPixmap*> &children) {
m_children = children;
}
private:
Scene::Window *m_window;
xcb_pixmap_t m_pixmap;
@ -412,6 +444,9 @@ private:
QRect m_contentsRect;
QPointer<KWayland::Server::BufferInterface> m_buffer;
QSharedPointer<QOpenGLFramebufferObject> m_fbo;
WindowPixmap *m_parent = nullptr;
QVector<WindowPixmap*> m_children;
QPointer<KWayland::Server::SubSurfaceInterface> m_subSurface;
};
class Scene::EffectFrame

Loading…
Cancel
Save