From 8f8c1d31ba9f8a3f32a49b9911e514b2c0d5c52e Mon Sep 17 00:00:00 2001 From: Lucas Murray Date: Sun, 8 Feb 2009 14:07:00 +0000 Subject: [PATCH] Added blurring during the logout effect. As this is done entirely using mipmaps the quality isn't the best. Might add a shader later that will generate the final image so it uses mipmaps for realtime blurring while using a high quality blur at the end. svn path=/trunk/KDE/kdebase/workspace/; revision=923246 --- effects/logout/logout.cpp | 85 +++++++++++++++++++++++++++++++++++++++ effects/logout/logout.h | 12 ++++++ 2 files changed, 97 insertions(+) diff --git a/effects/logout/logout.cpp b/effects/logout/logout.cpp index 7d0c3e4228..6fe089b9db 100644 --- a/effects/logout/logout.cpp +++ b/effects/logout/logout.cpp @@ -3,6 +3,7 @@ This file is part of the KDE project. Copyright (C) 2007 Lubos Lunak +Copyright (C) 2009 Lucas Murray This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -40,6 +41,38 @@ LogoutEffect::LogoutEffect() Atom hack = XInternAtom( display(), "_KWIN_LOGOUT_EFFECT", False ); XChangeProperty( display(), sel, hack, hack, 8, PropModeReplace, (unsigned char*)&hack, 1 ); // the atom is not removed when effect is destroyed, this is temporary anyway + +#ifdef KWIN_HAVE_OPENGL_COMPOSITING + blurSupported = false; + + // If NPOT textures are not supported use the nearest power-of-two sized + // texture. It wastes memory, but it's possible to support systems without + // NPOT textures this way. + int texw = displayWidth(); + int texh = displayHeight(); + if( !GLTexture::NPOTTextureSupported() ) + { + kWarning( 1212 ) << "NPOT textures not supported, wasting some memory"; + texw = nearestPowerOfTwo( texw ); + texh = nearestPowerOfTwo( texh ); + } + // Create texture and render target + blurTexture = new GLTexture( texw, texh ); + blurTexture->setFilter( GL_LINEAR_MIPMAP_LINEAR ); + blurTexture->setWrapMode( GL_CLAMP_TO_EDGE ); + + blurTarget = new GLRenderTarget( blurTexture ); + if( blurTarget->valid() ) + blurSupported = true; +#endif + } + +LogoutEffect::~LogoutEffect() + { +#ifdef KWIN_HAVE_OPENGL_COMPOSITING + delete blurTexture; + delete blurTarget; +#endif } void LogoutEffect::prePaintScreen( ScreenPrePaintData& data, int time ) @@ -48,9 +81,27 @@ void LogoutEffect::prePaintScreen( ScreenPrePaintData& data, int time ) progress = qBound( 0., progress + time / animationTime( 2000. ), 1. ); else if( progress != 0 ) progress = qBound( 0., progress - time / animationTime( 500. ), 1. ); + +#ifdef KWIN_HAVE_OPENGL_COMPOSITING + if( blurSupported && progress > 0.0 ) + { + data.mask |= PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS; + effects->pushRenderTarget( blurTarget ); + } +#endif + effects->prePaintScreen( data, time ); } +void LogoutEffect::prePaintWindow( EffectWindow* w, WindowPrePaintData& data, int time ) + { +#ifdef KWIN_HAVE_OPENGL_COMPOSITING + if( blurSupported && progress > 0.0 && w == logout_window ) + w->disablePainting( EffectWindow::PAINT_DISABLED ); +#endif + effects->prePaintWindow( w, data, time ); + } + void LogoutEffect::paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data ) { if( w != logout_window && progress != 0 ) @@ -73,6 +124,40 @@ void LogoutEffect::postPaintScreen() if( progress != 0 && progress != 1 ) effects->addRepaintFull(); effects->postPaintScreen(); + +#ifdef KWIN_HAVE_OPENGL_COMPOSITING + if( blurSupported && progress > 0.0 ) + { + assert( effects->popRenderTarget() == blurTarget ); + + // Render the blurred scene + blurTexture->bind(); + GLfloat bias[1]; + glGetTexEnvfv( GL_TEXTURE_FILTER_CONTROL, GL_TEXTURE_LOD_BIAS, bias ); + glTexEnvf( GL_TEXTURE_FILTER_CONTROL, GL_TEXTURE_LOD_BIAS, progress * 2.75 ); + glBegin(GL_QUADS); + glTexCoord2f( 0.0, 0.0 ); + glVertex2f( 0.0, displayHeight() ); + glTexCoord2f( 1.0, 0.0 ); + glVertex2f( displayWidth(), displayHeight() ); + glTexCoord2f( 1.0, 1.0 ); + glVertex2f( displayWidth(), 0.0 ); + glTexCoord2f( 0.0, 1.0 ); + glVertex2f( 0.0, 0.0 ); + glEnd(); + glTexEnvf( GL_TEXTURE_FILTER_CONTROL, GL_TEXTURE_LOD_BIAS, bias[0] ); + blurTexture->unbind(); + + // Render the logout window + if( logout_window ) + { + int mask = PAINT_WINDOW_OPAQUE; // TODO: Can we have a translucent logout window? + QRect region = infiniteRegion(); + WindowPaintData data( logout_window ); + effects->drawWindow( logout_window, mask, region, data ); + } + } +#endif } void LogoutEffect::windowAdded( EffectWindow* w ) diff --git a/effects/logout/logout.h b/effects/logout/logout.h index 0179942568..d71b529806 100644 --- a/effects/logout/logout.h +++ b/effects/logout/logout.h @@ -3,6 +3,7 @@ This file is part of the KDE project. Copyright (C) 2007 Lubos Lunak +Copyright (C) 2009 Lucas Murray This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -27,13 +28,18 @@ along with this program. If not, see . namespace KWin { +class GLRenderTarget; +class GLTexture; + class LogoutEffect : public Effect { public: LogoutEffect(); + ~LogoutEffect(); virtual void prePaintScreen( ScreenPrePaintData& data, int time ); virtual void postPaintScreen(); + virtual void prePaintWindow( EffectWindow* w, WindowPrePaintData& data, int time ); virtual void paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data ); virtual void windowAdded( EffectWindow* w ); virtual void windowClosed( EffectWindow* w ); @@ -41,6 +47,12 @@ class LogoutEffect bool isLogoutDialog( EffectWindow* w ); double progress; // 0-1 EffectWindow* logout_window; + +#ifdef KWIN_HAVE_OPENGL_COMPOSITING + bool blurSupported; + GLTexture* blurTexture; + GLRenderTarget* blurTarget; +#endif }; } // namespace