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
icc-effect-5.14.5
Philipp Knechtges 2012-02-07 17:01:41 +01:00
parent 85635dd485
commit 239d5757f2
8 changed files with 76 additions and 43 deletions

View File

@ -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)

View File

@ -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();

View File

@ -78,6 +78,7 @@ private:
struct BlurWindowInfo {
GLTexture blurredBackground; // keeps the horizontally blurred background
QRegion damagedRegion;
QPoint windowPos;
bool dropCache;
};

View File

@ -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;

View File

@ -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());

View File

@ -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;

View File

@ -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;

View File

@ -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