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.
This commit is contained in:
parent
8f9c6ce92f
commit
976981349b
2 changed files with 62 additions and 9 deletions
|
@ -30,6 +30,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
#include "abstract_backend.h"
|
||||
#include "wayland_server.h"
|
||||
#include <KWayland/Server/buffer_interface.h>
|
||||
#include <KWayland/Server/subcompositor_interface.h>
|
||||
#include <KWayland/Server/surface_interface.h>
|
||||
#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<QPainterWindowPixmap*>(*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<QPainterWindowPixmap*>(pixmap));
|
||||
}
|
||||
|
||||
if (!opaque) {
|
||||
tempPainter.restore();
|
||||
tempPainter.setCompositionMode(QPainter::CompositionMode_DestinationIn);
|
||||
|
@ -406,6 +433,11 @@ QPainterWindowPixmap::QPainterWindowPixmap(Scene::Window *window)
|
|||
{
|
||||
}
|
||||
|
||||
QPainterWindowPixmap::QPainterWindowPixmap(const QPointer<KWayland::Server::SubSurfaceInterface> &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<KWayland::Server::SubSurfaceInterface> &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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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<KWayland::Server::SubSurfaceInterface> &subSurface) override;
|
||||
void updateBuffer() override;
|
||||
private:
|
||||
explicit QPainterWindowPixmap(const QPointer<KWayland::Server::SubSurfaceInterface> &subSurface, WindowPixmap *parent);
|
||||
QImage m_image;
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue