wayland: Schedule repaints even on empty commits

If only frame callbacks have been committed, the compositor must still
schedule compositing.

BUG: 428499
This commit is contained in:
Vlad Zahorodnii 2021-02-02 15:16:33 +02:00
parent e30b1a0f92
commit 72fda78cf6
6 changed files with 43 additions and 20 deletions

View file

@ -778,6 +778,13 @@ Scene::Window::Window(Toplevel *client, QObject *parent)
this, &Window::discardPixmap); this, &Window::discardPixmap);
connect(surface, &KWaylandServer::SurfaceInterface::surfaceToBufferMatrixChanged, connect(surface, &KWaylandServer::SurfaceInterface::surfaceToBufferMatrixChanged,
this, &Window::discardQuads); this, &Window::discardQuads);
connect(m_subsurfaceMonitor, &SubSurfaceMonitor::subSurfaceCommitted, this, [this](KWaylandServer::SubSurfaceInterface *subsurface) {
handleSurfaceCommitted(subsurface->surface());
});
connect(surface, &KWaylandServer::SurfaceInterface::committed, this, [this, surface]() {
handleSurfaceCommitted(surface);
});
} }
connect(toplevel, &Toplevel::screenScaleChanged, this, &Window::discardQuads); connect(toplevel, &Toplevel::screenScaleChanged, this, &Window::discardQuads);
@ -1218,6 +1225,27 @@ void Scene::Window::reallocRepaints()
m_repaints.fill(infiniteRegion()); m_repaints.fill(infiniteRegion());
} }
void Scene::Window::scheduleRepaint()
{
if (kwinApp()->platform()->isPerScreenRenderingEnabled()) {
const QVector<AbstractOutput *> outputs = kwinApp()->platform()->enabledOutputs();
for (AbstractOutput *output : outputs) {
if (window()->isOnOutput(output)) {
output->renderLoop()->scheduleRepaint();
}
}
} else {
kwinApp()->platform()->renderLoop()->scheduleRepaint();
}
}
void Scene::Window::handleSurfaceCommitted(KWaylandServer::SurfaceInterface *surface)
{
if (surface->hasFrameCallbacks()) {
scheduleRepaint();
}
}
//**************************************** //****************************************
// WindowPixmap // WindowPixmap
//**************************************** //****************************************

View file

@ -400,6 +400,8 @@ protected:
ImageFilterType filter; ImageFilterType filter;
Shadow *m_shadow; Shadow *m_shadow;
private: private:
void scheduleRepaint();
void handleSurfaceCommitted(KWaylandServer::SurfaceInterface *surface);
void reallocRepaints(); void reallocRepaints();
QScopedPointer<WindowPixmap> m_currentPixmap; QScopedPointer<WindowPixmap> m_currentPixmap;

View file

@ -39,6 +39,8 @@ void SubSurfaceMonitor::registerSubSurface(SubSurfaceInterface *subSurface)
this, &SubSurfaceMonitor::subSurfaceSurfaceToBufferMatrixChanged); this, &SubSurfaceMonitor::subSurfaceSurfaceToBufferMatrixChanged);
connect(surface, &SurfaceInterface::bufferSizeChanged, connect(surface, &SurfaceInterface::bufferSizeChanged,
this, &SubSurfaceMonitor::subSurfaceBufferSizeChanged); this, &SubSurfaceMonitor::subSurfaceBufferSizeChanged);
connect(surface, &SurfaceInterface::committed,
this, [this, subSurface]() { emit subSurfaceCommitted(subSurface); });
registerSurface(surface); registerSurface(surface);
} }
@ -49,18 +51,7 @@ void SubSurfaceMonitor::unregisterSubSurface(SubSurfaceInterface *subSurface)
if (!surface) if (!surface)
return; return;
disconnect(subSurface, &SubSurfaceInterface::positionChanged, disconnect(subSurface, nullptr, this, nullptr);
this, &SubSurfaceMonitor::subSurfaceMoved);
disconnect(surface, &SurfaceInterface::sizeChanged,
this, &SubSurfaceMonitor::subSurfaceResized);
disconnect(surface, &SurfaceInterface::mapped,
this, &SubSurfaceMonitor::subSurfaceMapped);
disconnect(surface, &SurfaceInterface::unmapped,
this, &SubSurfaceMonitor::subSurfaceUnmapped);
disconnect(surface, &SurfaceInterface::surfaceToBufferMatrixChanged,
this, &SubSurfaceMonitor::subSurfaceSurfaceToBufferMatrixChanged);
disconnect(surface, &SurfaceInterface::bufferSizeChanged,
this, &SubSurfaceMonitor::subSurfaceBufferSizeChanged);
unregisterSurface(surface); unregisterSurface(surface);
} }
@ -79,14 +70,7 @@ void SubSurfaceMonitor::registerSurface(SurfaceInterface *surface)
void SubSurfaceMonitor::unregisterSurface(SurfaceInterface *surface) void SubSurfaceMonitor::unregisterSurface(SurfaceInterface *surface)
{ {
disconnect(surface, &SurfaceInterface::childSubSurfaceAdded, disconnect(surface, nullptr, this, nullptr);
this, &SubSurfaceMonitor::subSurfaceAdded);
disconnect(surface, &SurfaceInterface::childSubSurfaceRemoved,
this, &SubSurfaceMonitor::subSurfaceRemoved);
disconnect(surface, &SurfaceInterface::childSubSurfaceAdded,
this, &SubSurfaceMonitor::registerSubSurface);
disconnect(surface, &SurfaceInterface::childSubSurfaceRemoved,
this, &SubSurfaceMonitor::unregisterSubSurface);
} }
} // namespace KWin } // namespace KWin

View file

@ -68,6 +68,7 @@ Q_SIGNALS:
* This signal is emitted when the buffer size of a subsurface has changed. * This signal is emitted when the buffer size of a subsurface has changed.
*/ */
void subSurfaceBufferSizeChanged(); void subSurfaceBufferSizeChanged();
void subSurfaceCommitted(KWaylandServer::SubSurfaceInterface *subSurface);
private: private:
void registerSubSurface(KWaylandServer::SubSurfaceInterface *subSurface); void registerSubSurface(KWaylandServer::SubSurfaceInterface *subSurface);

View file

@ -9,6 +9,7 @@
#include "toplevel.h" #include "toplevel.h"
#include "abstract_client.h" #include "abstract_client.h"
#include "abstract_output.h"
#ifdef KWIN_BUILD_ACTIVITIES #ifdef KWIN_BUILD_ACTIVITIES
#include "activities.h" #include "activities.h"
#endif #endif
@ -563,6 +564,11 @@ bool Toplevel::isOnActiveScreen() const
return isOnScreen(screens()->current()); return isOnScreen(screens()->current());
} }
bool Toplevel::isOnOutput(AbstractOutput *output) const
{
return output->geometry().intersects(frameGeometry());
}
void Toplevel::updateShadow() void Toplevel::updateShadow()
{ {
QRect dirtyRect; // old & new shadow region QRect dirtyRect; // old & new shadow region

View file

@ -37,6 +37,7 @@ class SurfaceInterface;
namespace KWin namespace KWin
{ {
class AbstractOutput;
class ClientMachine; class ClientMachine;
class Deleted; class Deleted;
class EffectWindowImpl; class EffectWindowImpl;
@ -347,6 +348,7 @@ public:
int width() const; int width() const;
int height() const; int height() const;
bool isOnScreen(int screen) const; // true if it's at least partially there bool isOnScreen(int screen) const; // true if it's at least partially there
bool isOnOutput(AbstractOutput *output) const;
bool isOnActiveScreen() const; bool isOnActiveScreen() const;
int screen() const; // the screen where the center is int screen() const; // the screen where the center is
/** /**