From 976981349beeb6ac5cf39b64602b896368c5b1f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Gr=C3=A4=C3=9Flin?= Date: Mon, 21 Mar 2016 16:42:30 +0100 Subject: [PATCH] Render child WindowPixmap in SceneQPainter The rendering is done in a recursive way. For updating the buffer an important change is done: the buffer is copied into a new QImage on each change and the differences are no longer painted. This is due to damage region in a sub-surface tree being basically unknown. --- scene_qpainter.cpp | 64 ++++++++++++++++++++++++++++++++++++++++------ scene_qpainter.h | 7 ++++- 2 files changed, 62 insertions(+), 9 deletions(-) diff --git a/scene_qpainter.cpp b/scene_qpainter.cpp index cdaede1429..1b5965315a 100644 --- a/scene_qpainter.cpp +++ b/scene_qpainter.cpp @@ -30,6 +30,7 @@ along with this program. If not, see . #include "abstract_backend.h" #include "wayland_server.h" #include +#include #include #include "decorations/decoratedclient.h" // Qt @@ -235,6 +236,23 @@ SceneQPainter::Window::~Window() discardShape(); } +static void paintSubSurface(QPainter *painter, const QPoint &pos, QPainterWindowPixmap *pixmap) +{ + QPoint p = pos; + if (!pixmap->subSurface().isNull()) { + p += pixmap->subSurface()->position(); + } + painter->drawImage(p, pixmap->image()); + const auto &children = pixmap->children(); + for (auto it = children.begin(); it != children.end(); ++it) { + auto pixmap = static_cast(*it); + if (pixmap->subSurface().isNull() || pixmap->subSurface()->surface().isNull() || !pixmap->subSurface()->surface()->isMapped()) { + continue; + } + paintSubSurface(painter, p, pixmap); + } +} + void SceneQPainter::Window::performPaint(int mask, QRegion region, WindowPaintData data) { if (!(mask & (PAINT_WINDOW_TRANSFORMED | PAINT_SCREEN_TRANSFORMED))) @@ -247,7 +265,7 @@ void SceneQPainter::Window::performPaint(int mask, QRegion region, WindowPaintDa return; } if (!toplevel->damage().isEmpty()) { - pixmap->update(toplevel->damage()); + pixmap->update(); toplevel->resetDamage(); } @@ -282,6 +300,15 @@ void SceneQPainter::Window::performPaint(int mask, QRegion region, WindowPaintDa const QRect src = QRect(toplevel->clientPos() + toplevel->clientContentPos(), toplevel->clientSize()); painter->drawImage(toplevel->clientPos(), pixmap->image(), src); + // render subsurfaces + const auto &children = pixmap->children(); + for (auto pixmap : children) { + if (pixmap->subSurface().isNull() || pixmap->subSurface()->surface().isNull() || !pixmap->subSurface()->surface()->isMapped()) { + continue; + } + paintSubSurface(painter, toplevel->clientPos(), static_cast(pixmap)); + } + if (!opaque) { tempPainter.restore(); tempPainter.setCompositionMode(QPainter::CompositionMode_DestinationIn); @@ -406,6 +433,11 @@ QPainterWindowPixmap::QPainterWindowPixmap(Scene::Window *window) { } +QPainterWindowPixmap::QPainterWindowPixmap(const QPointer &subSurface, WindowPixmap *parent) + : WindowPixmap(subSurface, parent) +{ +} + QPainterWindowPixmap::~QPainterWindowPixmap() { } @@ -423,20 +455,36 @@ void QPainterWindowPixmap::create() m_image = buffer()->data().copy(); } -bool QPainterWindowPixmap::update(const QRegion &damage) +WindowPixmap *QPainterWindowPixmap::createChild(const QPointer &subSurface) { + return new QPainterWindowPixmap(subSurface, this); +} + +void QPainterWindowPixmap::updateBuffer() +{ + const auto oldBuffer = buffer(); + WindowPixmap::updateBuffer(); + const auto &b = buffer(); + if (b.isNull()) { + m_image = QImage(); + return; + } + if (b == oldBuffer) { + return; + } + // perform deep copy + m_image = b->data().copy(); +} + +bool QPainterWindowPixmap::update() +{ + // TODO: there is lots of things which can be removed here const auto oldBuffer = buffer(); updateBuffer(); const auto &b = buffer(); if (b == oldBuffer || b.isNull()) { return false; } - QPainter p(&m_image); - const QImage &data = b->data(); - p.setCompositionMode(QPainter::CompositionMode_Source); - for (const QRect &rect : damage.rects()) { - p.drawImage(rect, data, rect); - } return true; } diff --git a/scene_qpainter.h b/scene_qpainter.h index 8a9cfa16e2..c23ecc3963 100644 --- a/scene_qpainter.h +++ b/scene_qpainter.h @@ -156,9 +156,14 @@ public: virtual ~QPainterWindowPixmap(); virtual void create() override; - bool update(const QRegion &damage); + bool update(); const QImage &image(); + +protected: + WindowPixmap *createChild(const QPointer &subSurface) override; + void updateBuffer() override; private: + explicit QPainterWindowPixmap(const QPointer &subSurface, WindowPixmap *parent); QImage m_image; };