kwin: move/resize events shall not force a repaint of all layers
This patch adds a new function Toplevel::addLayerRepaint, that in contrast to addWorkspaceRepaint does not invalidate every blur texture cache that overlaps with that region. As the name suggests it rather invalidates the to the window associated layer at that position. This is especially useful in the case of move/resize events in combination with oxygen-transparent, where the altered window is almost always the topmost window and the blur texture cache of the windows underneath are unchanged. For the case of fully opaque windows the behaviour of addLayerRepaint and addWorkspaceRepaint should be same. REVIEW: 103906
This commit is contained in:
parent
85635dd485
commit
239d5757f2
8 changed files with 76 additions and 43 deletions
|
@ -735,24 +735,48 @@ void Toplevel::resetDamage(const QRect& r)
|
|||
|
||||
void Toplevel::addRepaint(const QRect& r)
|
||||
{
|
||||
addRepaint(r.x(), r.y(), r.width(), r.height());
|
||||
}
|
||||
|
||||
void Toplevel::addRepaint(int x, int y, int w, int h)
|
||||
{
|
||||
if (!compositing())
|
||||
if (!compositing()) {
|
||||
return;
|
||||
QRect r(x, y, w, h);
|
||||
r &= rect();
|
||||
}
|
||||
repaints_region += r;
|
||||
workspace()->checkCompositeTimer();
|
||||
}
|
||||
|
||||
void Toplevel::addRepaint(int x, int y, int w, int h)
|
||||
{
|
||||
QRect r(x, y, w, h);
|
||||
addRepaint(r);
|
||||
}
|
||||
|
||||
void Toplevel::addRepaint(const QRegion& r)
|
||||
{
|
||||
if (!compositing()) {
|
||||
return;
|
||||
}
|
||||
repaints_region += r;
|
||||
workspace()->checkCompositeTimer();
|
||||
}
|
||||
|
||||
void Toplevel::addLayerRepaint(const QRect& r)
|
||||
{
|
||||
if (!compositing()) {
|
||||
return;
|
||||
}
|
||||
layer_repaints_region += r;
|
||||
workspace()->checkCompositeTimer();
|
||||
}
|
||||
|
||||
void Toplevel::addLayerRepaint(int x, int y, int w, int h)
|
||||
{
|
||||
QRect r(x, y, w, h);
|
||||
addLayerRepaint(r);
|
||||
}
|
||||
|
||||
void Toplevel::addLayerRepaint(const QRegion& r)
|
||||
{
|
||||
if (!compositing())
|
||||
return;
|
||||
repaints_region += r;
|
||||
layer_repaints_region += r;
|
||||
workspace()->checkCompositeTimer();
|
||||
}
|
||||
|
||||
|
@ -762,9 +786,10 @@ void Toplevel::addRepaintFull()
|
|||
workspace()->checkCompositeTimer();
|
||||
}
|
||||
|
||||
void Toplevel::resetRepaints(const QRect& r)
|
||||
void Toplevel::resetRepaints()
|
||||
{
|
||||
repaints_region -= r;
|
||||
repaints_region = QRegion();
|
||||
layer_repaints_region = QRegion();
|
||||
}
|
||||
|
||||
void Toplevel::addWorkspaceRepaint(int x, int y, int w, int h)
|
||||
|
|
|
@ -290,7 +290,7 @@ void BlurEffect::prePaintWindow(EffectWindow* w, WindowPrePaintData& data, int t
|
|||
// if a window underneath the blurred area is damaged we have to
|
||||
// update the cached texture
|
||||
QRegion damagedCache;
|
||||
if (windows.contains(w) && !windows[w].dropCache) {
|
||||
if (windows.contains(w) && !windows.value(w).dropCache) {
|
||||
damagedCache = expand(expandedBlur & m_damagedArea) & expandedBlur;
|
||||
} else {
|
||||
damagedCache = expandedBlur;
|
||||
|
@ -504,13 +504,17 @@ void BlurEffect::doCachedBlur(EffectWindow *w, const QRegion& region, const floa
|
|||
bwi.blurredBackground = GLTexture(r.width(),r.height());
|
||||
bwi.damagedRegion = expanded;
|
||||
bwi.dropCache = false;
|
||||
windows[w] = bwi;
|
||||
}
|
||||
|
||||
if (windows[w].blurredBackground.size() != r.size()) {
|
||||
bwi.windowPos = w->pos();
|
||||
windows.insert(w, bwi);
|
||||
} else if (windows.value(w).blurredBackground.size() != r.size()) {
|
||||
windows[w].blurredBackground = GLTexture(r.width(),r.height());
|
||||
windows[w].damagedRegion = expanded;
|
||||
windows[w].dropCache = false;
|
||||
windows[w].windowPos = w->pos();
|
||||
} else if (windows.value(w).windowPos != w->pos()) {
|
||||
windows[w].damagedRegion = expanded;
|
||||
windows[w].dropCache = false;
|
||||
windows[w].windowPos = w->pos();
|
||||
}
|
||||
|
||||
GLTexture targetTexture = windows[w].blurredBackground;
|
||||
|
@ -530,7 +534,7 @@ void BlurEffect::doCachedBlur(EffectWindow *w, const QRegion& region, const floa
|
|||
#endif
|
||||
|
||||
// We only update that part of the background texture that is visible and marked as dirty.
|
||||
const QRegion updateBackground = windows[w].damagedRegion & region;
|
||||
const QRegion updateBackground = windows.value(w).damagedRegion & region;
|
||||
|
||||
if (!updateBackground.isEmpty()) {
|
||||
const QRect updateRect = (expand(updateBackground) & expanded).boundingRect();
|
||||
|
|
|
@ -78,6 +78,7 @@ private:
|
|||
struct BlurWindowInfo {
|
||||
GLTexture blurredBackground; // keeps the horizontally blurred background
|
||||
QRegion damagedRegion;
|
||||
QPoint windowPos;
|
||||
bool dropCache;
|
||||
};
|
||||
|
||||
|
|
12
geometry.cpp
12
geometry.cpp
|
@ -1913,8 +1913,8 @@ void Client::setGeometry(int x, int y, int w, int h, ForceGeometry_t force)
|
|||
emit geometryShapeChanged(this, geom_before_block);
|
||||
}
|
||||
const QRect deco_rect = decorationRect().translated(geom.x(), geom.y());
|
||||
addWorkspaceRepaint(deco_rect_before_block);
|
||||
addWorkspaceRepaint(deco_rect);
|
||||
addLayerRepaint(deco_rect_before_block);
|
||||
addLayerRepaint(deco_rect);
|
||||
geom_before_block = geom;
|
||||
deco_rect_before_block = deco_rect;
|
||||
|
||||
|
@ -1980,8 +1980,8 @@ void Client::plainResize(int w, int h, ForceGeometry_t force)
|
|||
discardWindowPixmap();
|
||||
emit geometryShapeChanged(this, geom_before_block);
|
||||
const QRect deco_rect = decorationRect().translated(geom.x(), geom.y());
|
||||
addWorkspaceRepaint(deco_rect_before_block);
|
||||
addWorkspaceRepaint(deco_rect);
|
||||
addLayerRepaint(deco_rect_before_block);
|
||||
addLayerRepaint(deco_rect);
|
||||
geom_before_block = geom;
|
||||
deco_rect_before_block = deco_rect;
|
||||
|
||||
|
@ -2027,8 +2027,8 @@ void Client::move(int x, int y, ForceGeometry_t force)
|
|||
#endif
|
||||
// client itself is not damaged
|
||||
const QRect deco_rect = decorationRect().translated(geom.x(), geom.y());
|
||||
addWorkspaceRepaint(deco_rect_before_block);
|
||||
addWorkspaceRepaint(deco_rect); // trigger repaint of window's new location
|
||||
addLayerRepaint(deco_rect_before_block);
|
||||
addLayerRepaint(deco_rect); // trigger repaint of window's new location
|
||||
geom_before_block = geom;
|
||||
deco_rect_before_block = deco_rect;
|
||||
|
||||
|
|
|
@ -418,6 +418,16 @@ void EffectWindow::addRepaintFull()
|
|||
QMetaObject::invokeMethod(parent(), "addRepaintFull");
|
||||
}
|
||||
|
||||
void EffectWindow::addLayerRepaint(int x, int y, int w, int h)
|
||||
{
|
||||
QMetaObject::invokeMethod(parent(), "addLayerRepaint", Q_ARG(int, x), Q_ARG(int, y), Q_ARG(int, w), Q_ARG(int, h));
|
||||
}
|
||||
|
||||
void EffectWindow::addLayerRepaint(const QRect &r)
|
||||
{
|
||||
QMetaObject::invokeMethod(parent(), "addLayerRepaint", Q_ARG(const QRect&, r));
|
||||
}
|
||||
|
||||
bool EffectWindow::isOnCurrentActivity() const
|
||||
{
|
||||
return isOnActivity(effects->currentActivity());
|
||||
|
|
|
@ -1088,6 +1088,8 @@ public:
|
|||
void addRepaint(const QRect& r);
|
||||
void addRepaint(int x, int y, int w, int h);
|
||||
void addRepaintFull();
|
||||
void addLayerRepaint(const QRect& r);
|
||||
void addLayerRepaint(int x, int y, int w, int h);
|
||||
|
||||
virtual void refWindow() = 0;
|
||||
virtual void unrefWindow() = 0;
|
||||
|
|
23
scene.cpp
23
scene.cpp
|
@ -202,10 +202,7 @@ void Scene::paintGenericScreen(int orig_mask, ScreenPaintData)
|
|||
// Reset the repaint_region.
|
||||
// This has to be done here because many effects schedule a repaint for
|
||||
// the next frame within Effects::prePaintWindow.
|
||||
topw->resetRepaints(topw->decorationRect());
|
||||
if (topw->hasShadow()) {
|
||||
topw->resetRepaints(topw->shadow()->shadowRegion().boundingRect());
|
||||
}
|
||||
topw->resetRepaints();
|
||||
|
||||
WindowPrePaintData data;
|
||||
data.mask = orig_mask | (w->isOpaque() ? PAINT_WINDOW_OPAQUE : PAINT_WINDOW_TRANSLUCENT);
|
||||
|
@ -253,16 +250,13 @@ void Scene::paintSimpleScreen(int orig_mask, QRegion region)
|
|||
data.mask = orig_mask | (w->isOpaque() ? PAINT_WINDOW_OPAQUE : PAINT_WINDOW_TRANSLUCENT);
|
||||
w->resetPaintingEnabled();
|
||||
data.paint = region;
|
||||
data.paint |= topw->repaints().translated(topw->pos());
|
||||
data.paint |= topw->repaints();
|
||||
data.paint |= topw->decorationPendingRegion();
|
||||
|
||||
// Reset the repaint_region.
|
||||
// This has to be done here because many effects schedule a repaint for
|
||||
// the next frame within Effects::prePaintWindow.
|
||||
topw->resetRepaints(topw->decorationRect());
|
||||
if (topw->hasShadow()) {
|
||||
topw->resetRepaints(topw->shadow()->shadowRegion().boundingRect());
|
||||
}
|
||||
topw->resetRepaints();
|
||||
// Clip out the decoration for opaque windows; the decoration is drawn in the second pass
|
||||
if (w->isOpaque()) {
|
||||
// the window is fully opaque
|
||||
|
@ -299,15 +293,8 @@ void Scene::paintSimpleScreen(int orig_mask, QRegion region)
|
|||
QPair< Window*, Phase2Data > *entry = &phase2data[i];
|
||||
Phase2Data *data = &entry->second;
|
||||
|
||||
Toplevel *tlw = entry->first->window();
|
||||
// In case there is a window with a higher stackposition which has translucent regions
|
||||
// (e.g. decorations) that still have to be drawn, we also have to repaint the current window
|
||||
// in these particular regions
|
||||
if (!(data->mask & PAINT_WINDOW_TRANSFORMED)) {
|
||||
data->region |= (upperTranslucentDamage & tlw->decorationRect().translated(tlw->pos()));
|
||||
} else {
|
||||
data->region |= upperTranslucentDamage;
|
||||
}
|
||||
data->region |= upperTranslucentDamage;
|
||||
|
||||
// subtract the parts which will possibly been drawn as part of
|
||||
// a higher opaque window
|
||||
data->region -= allclips;
|
||||
|
|
|
@ -235,12 +235,15 @@ public:
|
|||
Q_INVOKABLE void addRepaint(const QRect& r);
|
||||
Q_INVOKABLE void addRepaint(const QRegion& r);
|
||||
Q_INVOKABLE void addRepaint(int x, int y, int w, int h);
|
||||
Q_INVOKABLE void addLayerRepaint(const QRect& r);
|
||||
Q_INVOKABLE void addLayerRepaint(const QRegion& r);
|
||||
Q_INVOKABLE void addLayerRepaint(int x, int y, int w, int h);
|
||||
Q_INVOKABLE virtual void addRepaintFull();
|
||||
// these call workspace->addRepaint(), but first transform the damage if needed
|
||||
void addWorkspaceRepaint(const QRect& r);
|
||||
void addWorkspaceRepaint(int x, int y, int w, int h);
|
||||
QRegion repaints() const;
|
||||
void resetRepaints(const QRect& r);
|
||||
void resetRepaints();
|
||||
QRegion damage() const;
|
||||
void resetDamage(const QRect& r);
|
||||
EffectWindowImpl* effectWindow();
|
||||
|
@ -324,6 +327,7 @@ protected:
|
|||
NETWinInfo2* info;
|
||||
bool ready_for_painting;
|
||||
QRegion repaints_region; // updating, repaint just requires repaint of that area
|
||||
QRegion layer_repaints_region;
|
||||
private:
|
||||
static QByteArray staticWindowRole(WId);
|
||||
static QByteArray staticSessionId(WId);
|
||||
|
@ -513,7 +517,7 @@ inline QRegion Toplevel::damage() const
|
|||
|
||||
inline QRegion Toplevel::repaints() const
|
||||
{
|
||||
return repaints_region;
|
||||
return repaints_region.translated(pos()) | layer_repaints_region;
|
||||
}
|
||||
|
||||
inline bool Toplevel::shape() const
|
||||
|
|
Loading…
Reference in a new issue