plugins/blur: Fix blurred region sticking outside panel popups
The blur geometry is scaled in the global coordinate space, while it works fine with integer scale factors, it's not okay with fractional scale factors as it doesn't match how the ItemRenderer snaps quads to the pixel grid. Note that blur behind apps can be still off by one pixel, but it should be harder to notice it. In order to fix it, it would be great to apply effects behind Items, which is on my todo list.
This commit is contained in:
parent
2ca1d3fd4c
commit
9abf7a9d61
1 changed files with 29 additions and 13 deletions
|
@ -10,6 +10,7 @@
|
|||
// KConfigSkeleton
|
||||
#include "blurconfig.h"
|
||||
|
||||
#include "core/pixelgrid.h"
|
||||
#include "core/rendertarget.h"
|
||||
#include "core/renderviewport.h"
|
||||
#include "effect/effecthandler.h"
|
||||
|
@ -559,8 +560,29 @@ void BlurEffect::blur(const RenderTarget &renderTarget, const RenderViewport &vi
|
|||
blurShape = translated;
|
||||
}
|
||||
|
||||
const QRect backgroundRect = blurShape.boundingRect();
|
||||
const QRect deviceBackgroundRect = snapToPixelGrid(scaledRect(backgroundRect, viewport.scale()));
|
||||
const auto opacity = w->opacity() * data.opacity();
|
||||
|
||||
// Get the effective shape that will be actually blurred. It's possible that all of it will be clipped.
|
||||
const QRegion effectiveShape = blurShape & region;
|
||||
QList<QRectF> effectiveShape;
|
||||
effectiveShape.reserve(blurShape.rectCount());
|
||||
if (region != infiniteRegion()) {
|
||||
for (const QRect &clipRect : region) {
|
||||
const QRectF deviceClipRect = snapToPixelGridF(scaledRect(clipRect, viewport.scale()))
|
||||
.translated(-deviceBackgroundRect.topLeft());
|
||||
for (const QRect &shapeRect : blurShape) {
|
||||
const QRectF deviceShapeRect = snapToPixelGridF(scaledRect(shapeRect.translated(-backgroundRect.topLeft()), viewport.scale()));
|
||||
if (const QRectF intersected = deviceClipRect.intersected(deviceShapeRect); !intersected.isEmpty()) {
|
||||
effectiveShape.append(intersected);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (const QRect &rect : blurShape) {
|
||||
effectiveShape.append(snapToPixelGridF(scaledRect(rect.translated(-backgroundRect.topLeft()), viewport.scale())));
|
||||
}
|
||||
}
|
||||
if (effectiveShape.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
@ -572,10 +594,6 @@ void BlurEffect::blur(const RenderTarget &renderTarget, const RenderViewport &vi
|
|||
textureFormat = renderTarget.texture()->internalFormat();
|
||||
}
|
||||
|
||||
const QRect backgroundRect = blurShape.boundingRect();
|
||||
const QRect deviceBackgroundRect = scaledRect(backgroundRect, viewport.scale()).toRect();
|
||||
const auto opacity = w->opacity() * data.opacity();
|
||||
|
||||
if (renderInfo.framebuffers.size() != (m_iterationCount + 1) || renderInfo.textures[0]->size() != backgroundRect.size() || renderInfo.textures[0]->internalFormat() != textureFormat) {
|
||||
renderInfo.framebuffers.clear();
|
||||
renderInfo.textures.clear();
|
||||
|
@ -611,7 +629,7 @@ void BlurEffect::blur(const RenderTarget &renderTarget, const RenderViewport &vi
|
|||
vbo->reset();
|
||||
vbo->setAttribLayout(std::span(GLVertexBuffer::GLVertex2DLayout), sizeof(GLVertex2D));
|
||||
|
||||
const int vertexCount = effectiveShape.rectCount() * 6;
|
||||
const int vertexCount = effectiveShape.size() * 6;
|
||||
if (auto result = vbo->map<GLVertex2D>(6 + vertexCount)) {
|
||||
auto map = *result;
|
||||
|
||||
|
@ -661,13 +679,11 @@ void BlurEffect::blur(const RenderTarget &renderTarget, const RenderViewport &vi
|
|||
}
|
||||
|
||||
// The geometry that will be painted on screen, in device pixels.
|
||||
for (const QRect &rect : effectiveShape) {
|
||||
const QRectF localRect = scaledRect(rect, viewport.scale()).translated(-deviceBackgroundRect.topLeft());
|
||||
|
||||
const float x0 = std::round(localRect.left());
|
||||
const float y0 = std::round(localRect.top());
|
||||
const float x1 = std::round(localRect.right());
|
||||
const float y1 = std::round(localRect.bottom());
|
||||
for (const QRectF &rect : effectiveShape) {
|
||||
const float x0 = rect.left();
|
||||
const float y0 = rect.top();
|
||||
const float x1 = rect.right();
|
||||
const float y1 = rect.bottom();
|
||||
|
||||
const float u0 = x0 / deviceBackgroundRect.width();
|
||||
const float v0 = 1.0f - y0 / deviceBackgroundRect.height();
|
||||
|
|
Loading…
Reference in a new issue