Blur background of EffectFrames.
BUG: 241389 FIXED-IN: 4.6.0 svn path=/trunk/KDE/kdebase/workspace/; revision=1154132
This commit is contained in:
parent
89c0ea0c8d
commit
111db93e05
2 changed files with 83 additions and 66 deletions
|
@ -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
|
||||
|
||||
|
|
|
@ -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 ®ion);
|
||||
void doBlur(const QRegion &shape, const QRect &screen, const float opacity);
|
||||
|
||||
private:
|
||||
BlurShader *shader;
|
||||
|
|
Loading…
Reference in a new issue