scene: Stop monitoring changes for unmapped surfaces

Once the main surface has been unmapped, we are no longer interested in
any changes that indicate that the window quads cache should be discarded

This also fixes a bug where the scene holds a subsurface monitor object
even after the associated window has been destroyed.
icc-effect-5.26.4
Vlad Zahorodnii 2020-11-03 13:18:09 +02:00
parent 3d43f8ad93
commit 47ea0c98b1
2 changed files with 55 additions and 31 deletions

View File

@ -422,30 +422,6 @@ void Scene::addToplevel(Toplevel *c)
m_windows[ c ] = w;
connect(c, &Toplevel::windowClosed, this, &Scene::windowClosed);
if (c->surface()) {
// We generate window quads for sub-surfaces so it's quite important to discard
// the pixmap tree and cached window quads when the sub-surface tree is changed.
SubSurfaceMonitor *monitor = new SubSurfaceMonitor(c->surface(), this);
// TODO(vlad): Is there a more efficient way to manage window pixmap trees?
connect(monitor, &SubSurfaceMonitor::subSurfaceAdded, w, &Window::discardPixmap);
connect(monitor, &SubSurfaceMonitor::subSurfaceRemoved, w, &Window::discardPixmap);
connect(monitor, &SubSurfaceMonitor::subSurfaceMapped, w, &Window::discardPixmap);
connect(monitor, &SubSurfaceMonitor::subSurfaceUnmapped, w, &Window::discardPixmap);
connect(monitor, &SubSurfaceMonitor::subSurfaceBufferSizeChanged, w, &Window::discardPixmap);
connect(monitor, &SubSurfaceMonitor::subSurfaceAdded, w, &Window::discardQuads);
connect(monitor, &SubSurfaceMonitor::subSurfaceRemoved, w, &Window::discardQuads);
connect(monitor, &SubSurfaceMonitor::subSurfaceMoved, w, &Window::discardQuads);
connect(monitor, &SubSurfaceMonitor::subSurfaceResized, w, &Window::discardQuads);
connect(monitor, &SubSurfaceMonitor::subSurfaceMapped, w, &Window::discardQuads);
connect(monitor, &SubSurfaceMonitor::subSurfaceUnmapped, w, &Window::discardQuads);
connect(monitor, &SubSurfaceMonitor::subSurfaceSurfaceToBufferMatrixChanged, w, &Window::discardQuads);
connect(c->surface(), &KWaylandServer::SurfaceInterface::bufferSizeChanged, w, &Window::discardPixmap);
connect(c->surface(), &KWaylandServer::SurfaceInterface::surfaceToBufferMatrixChanged, w, &Window::discardQuads);
}
connect(c, &Toplevel::screenScaleChanged, w, &Window::discardQuads);
connect(c, &Toplevel::shadowChanged, w, &Window::discardQuads);
connect(c, &Toplevel::geometryShapeChanged, w, &Window::discardShape);
@ -749,6 +725,45 @@ Scene::Window::Window(Toplevel *client, QObject *parent)
connect(screens(), &Screens::countChanged, this, &Window::reallocRepaints);
}
reallocRepaints();
KWaylandServer::SurfaceInterface *surface = toplevel->surface();
if (surface) {
// We generate window quads for sub-surfaces so it's quite important to discard
// the pixmap tree and cached window quads when the sub-surface tree is changed.
m_subsurfaceMonitor = new SubSurfaceMonitor(surface, this);
// TODO(vlad): Is there a more efficient way to manage window pixmap trees?
connect(m_subsurfaceMonitor, &SubSurfaceMonitor::subSurfaceAdded,
this, &Window::discardPixmap);
connect(m_subsurfaceMonitor, &SubSurfaceMonitor::subSurfaceRemoved,
this, &Window::discardPixmap);
connect(m_subsurfaceMonitor, &SubSurfaceMonitor::subSurfaceMapped,
this, &Window::discardPixmap);
connect(m_subsurfaceMonitor, &SubSurfaceMonitor::subSurfaceUnmapped,
this, &Window::discardPixmap);
connect(m_subsurfaceMonitor, &SubSurfaceMonitor::subSurfaceBufferSizeChanged,
this, &Window::discardPixmap);
connect(m_subsurfaceMonitor, &SubSurfaceMonitor::subSurfaceAdded,
this, &Window::discardQuads);
connect(m_subsurfaceMonitor, &SubSurfaceMonitor::subSurfaceRemoved,
this, &Window::discardQuads);
connect(m_subsurfaceMonitor, &SubSurfaceMonitor::subSurfaceMoved,
this, &Window::discardQuads);
connect(m_subsurfaceMonitor, &SubSurfaceMonitor::subSurfaceResized,
this, &Window::discardQuads);
connect(m_subsurfaceMonitor, &SubSurfaceMonitor::subSurfaceMapped,
this, &Window::discardQuads);
connect(m_subsurfaceMonitor, &SubSurfaceMonitor::subSurfaceUnmapped,
this, &Window::discardQuads);
connect(m_subsurfaceMonitor, &SubSurfaceMonitor::subSurfaceSurfaceToBufferMatrixChanged,
this, &Window::discardQuads);
connect(surface, &KWaylandServer::SurfaceInterface::bufferSizeChanged,
this, &Window::discardPixmap);
connect(surface, &KWaylandServer::SurfaceInterface::surfaceToBufferMatrixChanged,
this, &Window::discardQuads);
}
}
Scene::Window::~Window()
@ -763,6 +778,19 @@ Scene::Window::~Window()
delete m_shadow;
}
void Scene::Window::updateToplevel(Deleted *deleted)
{
delete m_subsurfaceMonitor;
m_subsurfaceMonitor = nullptr;
KWaylandServer::SurfaceInterface *surface = toplevel->surface();
if (surface) {
disconnect(surface, nullptr, this, nullptr);
}
toplevel = deleted;
}
void Scene::Window::referencePreviousPixmap()
{
if (!m_previousPixmap.isNull() && m_previousPixmap->isDiscarded()) {

10
scene.h
View File

@ -43,6 +43,7 @@ class Shadow;
class WindowPixmap;
class GLTexture;
class AbstractOutput;
class SubSurfaceMonitor;
// The base class for compositing backends.
class KWIN_EXPORT Scene : public QObject
@ -349,7 +350,7 @@ public:
QRegion decorationShape() const;
QPoint bufferOffset() const;
void discardShape();
void updateToplevel(Toplevel* c);
void updateToplevel(Deleted *deleted);
// creates initial quad list for the window
virtual WindowQuadList buildQuads(bool force = false) const;
void updateShadow(Shadow* shadow);
@ -407,6 +408,7 @@ private:
QScopedPointer<WindowPixmap> m_previousPixmap;
QVector<QRegion> m_repaints;
QVector<QRegion> m_layerRepaints;
SubSurfaceMonitor *m_subsurfaceMonitor = nullptr;
int m_referencePixmapCounter;
int disable_painting;
mutable QRegion m_bufferShape;
@ -677,12 +679,6 @@ Toplevel* Scene::Window::window() const
return toplevel;
}
inline
void Scene::Window::updateToplevel(Toplevel* c)
{
toplevel = c;
}
inline
const Shadow* Scene::Window::shadow() const
{