From 22bd8badbf72b19a9c3849e4df3e873c1e2c9c0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Gr=C3=A4=C3=9Flin?= Date: Wed, 27 Jan 2016 14:15:32 +0100 Subject: [PATCH] [effects] Add a simplified fullscreen blur If a window is fullscreen and wants fullscreen blur behind it, we use the blur from logout effect. This is mostly intended for the Application Dashboard which requires a fullscreen blur. The generic blur effect is not designed for such usage and is rather costly. This simplified blur just needs framebuffer blit and midmaps. This makes it rather cheap in usage and also doesn't need a cached texture. REVIEW: 126906 --- effects/blur/blur.cpp | 34 +++++++++++++++++++++++++++++++++- effects/blur/blur.h | 2 ++ 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/effects/blur/blur.cpp b/effects/blur/blur.cpp index a360f0301e..93a2af0396 100644 --- a/effects/blur/blur.cpp +++ b/effects/blur/blur.cpp @@ -40,6 +40,10 @@ static const QByteArray s_blurAtomName = QByteArrayLiteral("_KDE_NET_WM_BLUR_BEH BlurEffect::BlurEffect() { shader = BlurShader::create(); + m_simpleShader = ShaderManager::instance()->generateShaderFromResources(ShaderTrait::MapTexture, QString(), QStringLiteral("logout-blur.frag")); + if (!m_simpleShader->isValid()) { + qCDebug(KWINEFFECTS) << "Simple blur shader failed to load"; + } // Offscreen texture that's used as the target for the horizontal blur pass // and the source for the vertical pass. @@ -78,6 +82,7 @@ BlurEffect::~BlurEffect() { windows.clear(); + delete m_simpleShader; delete shader; delete target; } @@ -438,7 +443,9 @@ void BlurEffect::drawWindow(EffectWindow *w, int mask, QRegion region, WindowPai } if (!shape.isEmpty()) { - if (m_shouldCache && !translated && !w->isDeleted()) { + if (w->isFullScreen() && GLRenderTarget::blitSupported() && m_simpleShader->isValid() && shape.boundingRect() == w->geometry()) { + doSimpleBlur(w, data.opacity(), data.screenProjectionMatrix()); + } else if (m_shouldCache && !translated && !w->isDeleted()) { doCachedBlur(w, region, data.opacity(), data.screenProjectionMatrix()); } else { doBlur(shape, screen, data.opacity(), data.screenProjectionMatrix()); @@ -461,6 +468,31 @@ void BlurEffect::paintEffectFrame(EffectFrame *frame, QRegion region, double opa effects->paintEffectFrame(frame, region, opacity, frameOpacity); } +void BlurEffect::doSimpleBlur(EffectWindow *w, const float opacity, const QMatrix4x4 &screenProjection) +{ + // The fragment shader uses a LOD bias of 1.75, so we need 3 mipmap levels. + GLTexture blurTexture = GLTexture(GL_RGBA8, w->size(), 3); + blurTexture.setFilter(GL_LINEAR_MIPMAP_LINEAR); + blurTexture.setWrapMode(GL_CLAMP_TO_EDGE); + + target->attachTexture(blurTexture); + target->blitFromFramebuffer(w->geometry(), QRect(QPoint(0, 0), w->size())); + + // Unmodified base image + ShaderBinder binder(m_simpleShader); + QMatrix4x4 mvp = screenProjection; + mvp.translate(w->x(), w->y()); + m_simpleShader->setUniform(GLShader::ModelViewProjectionMatrix, mvp); + m_simpleShader->setUniform("u_alphaProgress", opacity); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + blurTexture.bind(); + blurTexture.generateMipmaps(); + blurTexture.render(infiniteRegion(), w->geometry()); + blurTexture.unbind(); + glDisable(GL_BLEND); +} + void BlurEffect::doBlur(const QRegion& shape, const QRect& screen, const float opacity, const QMatrix4x4 &screenProjection) { const QRegion expanded = expand(shape) & screen; diff --git a/effects/blur/blur.h b/effects/blur/blur.h index fd5a020688..e6f44946db 100644 --- a/effects/blur/blur.h +++ b/effects/blur/blur.h @@ -81,6 +81,7 @@ private: QRegion blurRegion(const EffectWindow *w) const; bool shouldBlur(const EffectWindow *w, int mask, const WindowPaintData &data) const; void updateBlurRegion(EffectWindow *w) const; + void doSimpleBlur(EffectWindow *w, const float opacity, const QMatrix4x4 &screenProjection); void doBlur(const QRegion &shape, const QRect &screen, const float opacity, const QMatrix4x4 &screenProjection); void doCachedBlur(EffectWindow *w, const QRegion& region, const float opacity, const QMatrix4x4 &screenProjection); void uploadRegion(QVector2D *&map, const QRegion ®ion); @@ -88,6 +89,7 @@ private: private: BlurShader *shader; + GLShader *m_simpleShader; GLRenderTarget *target; GLTexture tex; long net_wm_blur_region;