Blur background of EffectFrames.

BUG: 241389
FIXED-IN: 4.6.0

svn path=/trunk/KDE/kdebase/workspace/; revision=1154132
This commit is contained in:
Martin Gräßlin 2010-07-24 20:48:19 +00:00
parent 89c0ea0c8d
commit 111db93e05
2 changed files with 83 additions and 66 deletions

View file

@ -230,72 +230,7 @@ void BlurEffect::drawWindow(EffectWindow *w, int mask, QRegion region, WindowPai
if (valid && !shape.isEmpty() && region.intersects(shape.boundingRect()))
{
const QRegion expanded = expand(shape) & screen;
const QRect r = expanded.boundingRect();
// Create a scratch texture and copy the area in the back buffer that we're
// going to blur into it
GLTexture scratch(r.width(), r.height());
scratch.setFilter(GL_LINEAR);
scratch.setWrapMode(GL_CLAMP_TO_EDGE);
scratch.bind();
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r.x(), displayHeight() - r.y() - r.height(),
r.width(), r.height());
// Draw the texture on the offscreen framebuffer object, while blurring it horizontally
effects->pushRenderTarget(target);
shader->bind();
shader->setDirection(Qt::Horizontal);
shader->setPixelDistance(1.0 / r.width());
// Set up the texture matrix to transform from screen coordinates
// to texture coordinates.
glMatrixMode(GL_TEXTURE);
glPushMatrix();
glLoadIdentity();
glScalef(1.0 / scratch.width(), -1.0 / scratch.height(), 1);
glTranslatef(-r.x(), -scratch.height() - r.y(), 0);
drawRegion(expanded);
effects->popRenderTarget();
scratch.unbind();
scratch.discard();
// Now draw the horizontally blurred area back to the backbuffer, while
// blurring it vertically and clipping it to the window shape.
tex->bind();
shader->setDirection(Qt::Vertical);
shader->setPixelDistance(1.0 / tex->height());
// Modulate the blurred texture with the window opacity if the window isn't opaque
const float opacity = data.opacity * data.contents_opacity;
if (opacity < 1.0) {
glPushAttrib(GL_COLOR_BUFFER_BIT);
glEnable(GL_BLEND);
glBlendColor(0, 0, 0, opacity);
glBlendFunc(GL_CONSTANT_ALPHA, GL_ONE_MINUS_CONSTANT_ALPHA);
}
// Set the up the texture matrix to transform from screen coordinates
// to texture coordinates.
glLoadIdentity();
glScalef(1.0 / tex->width(), -1.0 / tex->height(), 1);
glTranslatef(0, -tex->height(), 0);
drawRegion(shape);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
if (opacity < 1.0)
glPopAttrib();
tex->unbind();
shader->unbind();
doBlur(shape, screen, data.opacity * data.contents_opacity);
// Rebind the shader used for drawing the window if one was set
if (data.shader)
@ -306,5 +241,85 @@ void BlurEffect::drawWindow(EffectWindow *w, int mask, QRegion region, WindowPai
effects->drawWindow(w, mask, region, data);
}
void BlurEffect::paintEffectFrame(EffectFrame *frame, QRegion region, double opacity, double frameOpacity)
{
const QRect screen(0, 0, displayWidth(), displayHeight());
bool valid = target->valid() && shader->isValid();
QRegion shape = frame->geometry().adjusted( -5, -5, 5, 5 ) & screen;
if (valid && !shape.isEmpty() && region.intersects(shape.boundingRect())) {
doBlur(shape, screen, opacity * frameOpacity);
}
effects->paintEffectFrame(frame, region, opacity, frameOpacity);
}
void BlurEffect::doBlur(const QRegion& shape, const QRect& screen, const float opacity)
{
const QRegion expanded = expand(shape) & screen;
const QRect r = expanded.boundingRect();
// Create a scratch texture and copy the area in the back buffer that we're
// going to blur into it
GLTexture scratch(r.width(), r.height());
scratch.setFilter(GL_LINEAR);
scratch.setWrapMode(GL_CLAMP_TO_EDGE);
scratch.bind();
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r.x(), displayHeight() - r.y() - r.height(),
r.width(), r.height());
// Draw the texture on the offscreen framebuffer object, while blurring it horizontally
effects->pushRenderTarget(target);
shader->bind();
shader->setDirection(Qt::Horizontal);
shader->setPixelDistance(1.0 / r.width());
// Set up the texture matrix to transform from screen coordinates
// to texture coordinates.
glMatrixMode(GL_TEXTURE);
glPushMatrix();
glLoadIdentity();
glScalef(1.0 / scratch.width(), -1.0 / scratch.height(), 1);
glTranslatef(-r.x(), -scratch.height() - r.y(), 0);
drawRegion(expanded);
effects->popRenderTarget();
scratch.unbind();
scratch.discard();
// Now draw the horizontally blurred area back to the backbuffer, while
// blurring it vertically and clipping it to the window shape.
tex->bind();
shader->setDirection(Qt::Vertical);
shader->setPixelDistance(1.0 / tex->height());
// Modulate the blurred texture with the window opacity if the window isn't opaque
if (opacity < 1.0) {
glPushAttrib(GL_COLOR_BUFFER_BIT);
glEnable(GL_BLEND);
glBlendColor(0, 0, 0, opacity);
glBlendFunc(GL_CONSTANT_ALPHA, GL_ONE_MINUS_CONSTANT_ALPHA);
}
// Set the up the texture matrix to transform from screen coordinates
// to texture coordinates.
glLoadIdentity();
glScalef(1.0 / tex->width(), -1.0 / tex->height(), 1);
glTranslatef(0, -tex->height(), 0);
drawRegion(shape);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
if (opacity < 1.0)
glPopAttrib();
tex->unbind();
shader->unbind();
}
} // namespace KWin

View file

@ -44,6 +44,7 @@ public:
void propertyNotify(EffectWindow *w, long atom);
void paintScreen(int mask, QRegion region, ScreenPaintData &data);
void drawWindow(EffectWindow *w, int mask, QRegion region, WindowPaintData &data);
void paintEffectFrame(EffectFrame *frame, QRegion region, double opacity, double frameOpacity);
private:
QRect expand(const QRect &rect) const;
@ -51,6 +52,7 @@ private:
QRegion blurRegion(const EffectWindow *w) const;
void updateBlurRegion(EffectWindow *w) const;
void drawRegion(const QRegion &region);
void doBlur(const QRegion &shape, const QRect &screen, const float opacity);
private:
BlurShader *shader;