scene: Pad damage if scale factor is fractional
Floating point arithmetic and/or the use of GL_LINEAR in the pipeline, may result in visual glitches due to rounding (errors). As a short-term fix until a proper (more involved) solution is in place for Plasma 6, pad the damage slightly in all directions to alleviate those effects.
This commit is contained in:
parent
9ac6f71662
commit
56f6bab0c3
1 changed files with 26 additions and 5 deletions
|
@ -241,14 +241,29 @@ static void resetRepaintsHelper(Item *item, SceneDelegate *delegate)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void accumulateRepaints(Item *item, SceneDelegate *delegate, QRegion *repaints)
|
static void accumulateRepaints(Item *item, SceneDelegate *delegate, QRegion *repaints, const bool padDamage)
|
||||||
{
|
{
|
||||||
*repaints += item->repaints(delegate);
|
if (!padDamage) {
|
||||||
|
*repaints += item->repaints(delegate);
|
||||||
|
} else {
|
||||||
|
const auto padding = 1;
|
||||||
|
|
||||||
|
for (const QRect region : item->repaints(delegate)) {
|
||||||
|
if (region.isEmpty() || region == infiniteRegion()) {
|
||||||
|
*repaints += region;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
*repaints += QRect{region.x() - padding, region.y() - padding,
|
||||||
|
region.width() + 2 * padding, region.height() + 2 * padding};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
item->resetRepaints(delegate);
|
item->resetRepaints(delegate);
|
||||||
|
|
||||||
const auto childItems = item->childItems();
|
const auto childItems = item->childItems();
|
||||||
for (Item *childItem : childItems) {
|
for (Item *childItem : childItems) {
|
||||||
accumulateRepaints(childItem, delegate, repaints);
|
accumulateRepaints(childItem, delegate, repaints, padDamage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -275,11 +290,17 @@ void WorkspaceScene::preparePaintGenericScreen()
|
||||||
|
|
||||||
void WorkspaceScene::preparePaintSimpleScreen()
|
void WorkspaceScene::preparePaintSimpleScreen()
|
||||||
{
|
{
|
||||||
|
// if a fractional scale factor is used, pad the damage to avoid visual
|
||||||
|
// glitches due to rounding errors (floating point arithmetic) and/or the
|
||||||
|
// use of GL_LINEAR in the pipeline
|
||||||
|
const auto scale = painted_screen->scale();
|
||||||
|
const bool padDamage = std::trunc(scale) != scale;
|
||||||
|
|
||||||
for (WindowItem *windowItem : std::as_const(stacking_order)) {
|
for (WindowItem *windowItem : std::as_const(stacking_order)) {
|
||||||
Window *window = windowItem->window();
|
Window *window = windowItem->window();
|
||||||
WindowPrePaintData data;
|
WindowPrePaintData data;
|
||||||
data.mask = m_paintContext.mask;
|
data.mask = m_paintContext.mask;
|
||||||
accumulateRepaints(windowItem, painted_delegate, &data.paint);
|
accumulateRepaints(windowItem, painted_delegate, &data.paint, padDamage);
|
||||||
|
|
||||||
// Clip out the decoration for opaque windows; the decoration is drawn in the second pass.
|
// Clip out the decoration for opaque windows; the decoration is drawn in the second pass.
|
||||||
if (window->opacity() == 1.0) {
|
if (window->opacity() == 1.0) {
|
||||||
|
@ -314,7 +335,7 @@ void WorkspaceScene::preparePaintSimpleScreen()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_dndIcon) {
|
if (m_dndIcon) {
|
||||||
accumulateRepaints(m_dndIcon.get(), painted_delegate, &m_paintContext.damage);
|
accumulateRepaints(m_dndIcon.get(), painted_delegate, &m_paintContext.damage, padDamage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue