diff --git a/effects.cpp b/effects.cpp index 2762cd2e88..3bbb687f94 100644 --- a/effects.cpp +++ b/effects.cpp @@ -99,6 +99,7 @@ EffectsHandlerImpl::EffectsHandlerImpl(CompositingType type) , fullscreen_effect( 0 ) , next_window_quad_type( EFFECT_QUAD_TYPE_START ) , mouse_poll_ref_count( 0 ) + , current_paint_effectframe( 0 ) { reconfigure(); } @@ -203,6 +204,20 @@ void EffectsHandlerImpl::paintWindow( EffectWindow* w, int mask, QRegion region, scene->finalPaintWindow( static_cast( w ), mask, region, data ); } +void EffectsHandlerImpl::paintEffectFrame( EffectFrame* frame, QRegion region, double opacity, double frameOpacity ) + { + if( current_paint_effectframe < loaded_effects.size()) + { + loaded_effects[current_paint_effectframe++].second->paintEffectFrame( frame, region, opacity, frameOpacity ); + --current_paint_effectframe; + } + else + { + const EffectFrameImpl* frameImpl = static_cast( frame ); + frameImpl->finalRender( region, opacity, frameOpacity ); + } + } + void EffectsHandlerImpl::postPaintWindow( EffectWindow* w ) { if( current_paint_window < loaded_effects.size()) @@ -1647,6 +1662,7 @@ EffectFrameImpl::EffectFrameImpl( EffectFrameStyle style, bool staticSize, QPoin , m_static( staticSize ) , m_point( position ) , m_alignment( alignment ) + , m_shader( NULL ) { if( m_style == Styled ) { @@ -1775,10 +1791,14 @@ void EffectFrameImpl::render( QRegion region, double opacity, double frameOpacit { return; // Nothing to display } + m_shader = NULL; + effects->paintEffectFrame( this, region, opacity, frameOpacity ); + } +void EffectFrameImpl::finalRender( QRegion region, double opacity, double frameOpacity ) const + { region = infiniteRegion(); // TODO: Old region doesn't seem to work with OpenGL - // TODO: pass through all effects m_sceneFrame->render( region, opacity, frameOpacity ); } diff --git a/effects.h b/effects.h index c5c413d5c5..de21c0738d 100644 --- a/effects.h +++ b/effects.h @@ -46,6 +46,7 @@ class EffectsHandlerImpl : public EffectsHandler virtual void prePaintWindow( EffectWindow* w, WindowPrePaintData& data, int time ); virtual void paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data ); virtual void postPaintWindow( EffectWindow* w ); + virtual void paintEffectFrame( EffectFrame* frame, QRegion region, double opacity, double frameOpacity ); bool providesResizeEffect(); @@ -198,6 +199,7 @@ class EffectsHandlerImpl : public EffectsHandler QHash< long, int > registered_atoms; int next_window_quad_type; int mouse_poll_ref_count; + int current_paint_effectframe; }; class EffectWindowImpl : public EffectWindow @@ -345,6 +347,15 @@ class EffectFrameImpl { return m_static; }; + void finalRender( QRegion region, double opacity, double frameOpacity ) const; + virtual void setShader( GLShader* shader ) + { + m_shader = shader; + } + virtual GLShader* shader() const + { + return m_shader; + } private Q_SLOTS: void plasmaThemeChanged(); @@ -370,6 +381,7 @@ class EffectFrameImpl QSize m_iconSize; Scene::EffectFrame* m_sceneFrame; + GLShader* m_shader; }; inline diff --git a/effects/invert/invert.cpp b/effects/invert/invert.cpp index 7a8815b8ab..fd076e3859 100644 --- a/effects/invert/invert.cpp +++ b/effects/invert/invert.cpp @@ -118,6 +118,19 @@ void InvertEffect::drawWindow( EffectWindow* w, int mask, QRegion region, Window m_shader->unbind(); } +void InvertEffect::paintEffectFrame( KWin::EffectFrame* frame, QRegion region, double opacity, double frameOpacity ) + { + if( m_valid && m_allWindows ) + { + frame->setShader( m_shader ); + effects->paintEffectFrame( frame, region, opacity, frameOpacity ); + } + else + { + effects->paintEffectFrame( frame, region, opacity, frameOpacity ); + } + } + void InvertEffect::windowClosed( EffectWindow* w ) { m_windows.removeOne( w ); diff --git a/effects/invert/invert.h b/effects/invert/invert.h index 2ce9b4302b..461487f3e2 100644 --- a/effects/invert/invert.h +++ b/effects/invert/invert.h @@ -41,6 +41,7 @@ class InvertEffect ~InvertEffect(); virtual void drawWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data ); + virtual void paintEffectFrame( KWin::EffectFrame* frame, QRegion region, double opacity, double frameOpacity ); virtual void windowClosed( EffectWindow* w ); public slots: diff --git a/lib/kwineffects.cpp b/lib/kwineffects.cpp index 7a287d820b..f97c251bbf 100644 --- a/lib/kwineffects.cpp +++ b/lib/kwineffects.cpp @@ -247,6 +247,11 @@ void Effect::postPaintWindow( EffectWindow* w ) effects->postPaintWindow( w ); } +void Effect::paintEffectFrame( KWin::EffectFrame* frame, QRegion region, double opacity, double frameOpacity ) + { + effects->paintEffectFrame( frame, region, opacity, frameOpacity ); + } + void Effect::drawWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data ) { effects->drawWindow( w, mask, region, data ); diff --git a/lib/kwineffects.h b/lib/kwineffects.h index 3b69f73cea..f816546c13 100644 --- a/lib/kwineffects.h +++ b/lib/kwineffects.h @@ -170,7 +170,7 @@ X-KDE-Library=kwin4_effect_cooleffect #define KWIN_EFFECT_API_MAKE_VERSION( major, minor ) (( major ) << 8 | ( minor )) #define KWIN_EFFECT_API_VERSION_MAJOR 0 -#define KWIN_EFFECT_API_VERSION_MINOR 153 +#define KWIN_EFFECT_API_VERSION_MINOR 154 #define KWIN_EFFECT_API_VERSION KWIN_EFFECT_API_MAKE_VERSION( \ KWIN_EFFECT_API_VERSION_MAJOR, KWIN_EFFECT_API_VERSION_MINOR ) @@ -392,6 +392,18 @@ class KWIN_EXPORT Effect **/ virtual void postPaintWindow( EffectWindow* w ); + /** + * This method is called directly before painting an @ref EffectFrame. + * You can implement this method if you need to bind a shader or perform + * other operations before the frame is rendered. + * @param frame The EffectFrame which will be rendered + * @param region Region to restrict painting to + * @param opacity Opacity of text/icon + * @param frameOpacity Opacity of background + * @since 4.6 + **/ + virtual void paintEffectFrame( EffectFrame* frame, QRegion region, double opacity, double frameOpacity ); + /** * Called on Transparent resizes. * return true if your effect substitutes the XOR rubberband @@ -573,6 +585,7 @@ class KWIN_EXPORT EffectsHandler virtual void prePaintWindow( EffectWindow* w, WindowPrePaintData& data, int time ) = 0; virtual void paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data ) = 0; virtual void postPaintWindow( EffectWindow* w ) = 0; + virtual void paintEffectFrame( EffectFrame* frame, QRegion region, double opacity, double frameOpacity ) = 0; virtual void drawWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data ) = 0; virtual void buildQuads( EffectWindow* w, WindowQuadList& quadList ) = 0; virtual QRect transformWindowDamage( EffectWindow* w, const QRect& r ); @@ -1724,6 +1737,15 @@ class KWIN_EXPORT EffectFrame virtual void setIconSize( const QSize& size ) = 0; virtual const QSize& iconSize() const = 0; + /** + * @param shader The GLShader for rendering. + **/ + virtual void setShader( GLShader* shader ) = 0; + /** + * @returns The GLShader used for rendering or null if none. + **/ + virtual GLShader* shader() const = 0; + /** * The foreground text color as specified by the default Plasma theme. */ diff --git a/scene_opengl.cpp b/scene_opengl.cpp index 4130407ac8..7af4440da9 100644 --- a/scene_opengl.cpp +++ b/scene_opengl.cpp @@ -1968,10 +1968,22 @@ void SceneOpenGL::EffectFrame::render( QRegion region, double opacity, double fr region = infiniteRegion(); // TODO: Old region doesn't seem to work with OpenGL + GLShader* shader = m_effectFrame->shader(); + if( shader ) + { + shader->bind(); + shader->setUniform("saturation", 1.0f); + shader->setUniform("brightness", 1.0f); + + shader->setUniform("textureWidth", 1.0f); + shader->setUniform("textureHeight", 1.0f); + } + glPushAttrib( GL_CURRENT_BIT | GL_ENABLE_BIT | GL_TEXTURE_BIT ); glEnable( GL_BLEND ); glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); - glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); + if( !shader ) + glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); glPushMatrix(); @@ -2082,7 +2094,10 @@ void SceneOpenGL::EffectFrame::render( QRegion region, double opacity, double fr m_unstyledVBO->setData( verts.count() / 2, 2, verts.data(), texCoords.data() ); } - glColor4f( 0.0, 0.0, 0.0, opacity * frameOpacity ); + if( shader ) + shader->setUniform( "opacity", (float)(opacity * frameOpacity) ); + else + glColor4f( 0.0, 0.0, 0.0, opacity * frameOpacity ); m_unstyledTexture->bind(); m_unstyledVBO->render( region, GL_TRIANGLES ); @@ -2093,7 +2108,10 @@ void SceneOpenGL::EffectFrame::render( QRegion region, double opacity, double fr if( !m_texture ) // Lazy creation updateTexture(); - glColor4f( 1.0, 1.0, 1.0, opacity * frameOpacity ); + if( shader ) + shader->setUniform( "opacity", (float)(opacity * frameOpacity) ); + else + glColor4f( 1.0, 1.0, 1.0, opacity * frameOpacity ); m_texture->bind(); qreal left, top, right, bottom; @@ -2102,7 +2120,10 @@ void SceneOpenGL::EffectFrame::render( QRegion region, double opacity, double fr m_texture->unbind(); } - glColor4f( 1.0, 1.0, 1.0, opacity ); + if( shader ) + shader->setUniform( "opacity", (float)opacity ); + else + glColor4f( 1.0, 1.0, 1.0, opacity ); // Render icon if( !m_effectFrame->icon().isNull() && !m_effectFrame->iconSize().isEmpty() ) @@ -2131,6 +2152,9 @@ void SceneOpenGL::EffectFrame::render( QRegion region, double opacity, double fr m_textTexture->unbind(); } + if( shader ) + shader->unbind(); + glPopMatrix(); glPopAttrib(); }