Reworked shadow effect which should bring nice speedup (especially on cards where fill
rate is expensive). It optimizes shadow rendering a lot by eliminating tons of overdraw: - Windows are not forced to be drawn bottom-to-top anymore. - For opaque windows, shadows are drawn only to where they will actually be visible, not under the whole window. svn path=/trunk/KDE/kdebase/workspace/; revision=746296
This commit is contained in:
parent
881fd48854
commit
864dea425e
2 changed files with 86 additions and 28 deletions
|
@ -52,38 +52,63 @@ QRect ShadowEffect::shadowRectangle(const QRect& windowRectangle) const
|
||||||
shadowXOffset + shadowGrow, shadowYOffset + shadowGrow);
|
shadowXOffset + shadowGrow, shadowYOffset + shadowGrow);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ShadowEffect::paintScreen( int mask, QRegion region, ScreenPaintData& data )
|
||||||
|
{
|
||||||
|
shadowDatas.clear();
|
||||||
|
|
||||||
|
// Draw windows
|
||||||
|
effects->paintScreen( mask, region, data );
|
||||||
|
|
||||||
|
// Draw shadows
|
||||||
|
drawQueuedShadows( 0 );
|
||||||
|
}
|
||||||
|
|
||||||
void ShadowEffect::prePaintWindow( EffectWindow* w, WindowPrePaintData& data, int time )
|
void ShadowEffect::prePaintWindow( EffectWindow* w, WindowPrePaintData& data, int time )
|
||||||
{
|
{
|
||||||
if( useShadow( w ))
|
if( useShadow( w ))
|
||||||
{
|
{
|
||||||
data.mask |= PAINT_WINDOW_TRANSLUCENT;
|
data.paint |= shadowRectangle( data.paint.boundingRect() );
|
||||||
QRect r = ( QRegion( w->geometry()) & data.paint ).boundingRect();
|
|
||||||
if( !r.isEmpty())
|
|
||||||
data.paint |= shadowRectangle( r );
|
|
||||||
}
|
}
|
||||||
effects->prePaintWindow( w, data, time );
|
effects->prePaintWindow( w, data, time );
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShadowEffect::paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data )
|
void ShadowEffect::drawWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data )
|
||||||
{
|
{
|
||||||
|
// Whether the shadow drawing can be delayed or not.
|
||||||
|
bool optimize = !( mask & ( PAINT_WINDOW_TRANSFORMED | PAINT_SCREEN_TRANSFORMED |
|
||||||
|
PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS | PAINT_WINDOW_TRANSLUCENT ));
|
||||||
|
if( !optimize )
|
||||||
|
{
|
||||||
|
// Transformed or translucent windows are drawn bottom-to-top, so
|
||||||
|
// first we need to draw all queued shadows.
|
||||||
|
drawQueuedShadows( w );
|
||||||
|
}
|
||||||
if( useShadow( w ))
|
if( useShadow( w ))
|
||||||
drawShadow( w, mask, region, data );
|
{
|
||||||
effects->paintWindow( w, mask, region, data );
|
if( !optimize )
|
||||||
|
{
|
||||||
|
// For translucent windows, shadow needs to be drawn before the
|
||||||
|
// window itself.
|
||||||
|
drawShadow( w, mask, region, data, false );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// For opaque windows, just schedule the shadow to be drawn later
|
||||||
|
ShadowData d(w, data);
|
||||||
|
d.clip = w->shape().translated( w->x(), w->y());
|
||||||
|
if( !shadowDatas.isEmpty())
|
||||||
|
d.clip |= shadowDatas.last().clip;
|
||||||
|
d.mask = mask;
|
||||||
|
foreach(QRect r, region.rects())
|
||||||
|
d.region |= shadowRectangle(r);
|
||||||
|
d.region &= region;
|
||||||
|
shadowDatas.append(d);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
effects->drawWindow( w, mask, region, data );
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShadowEffect::postPaintWindow( EffectWindow* w )
|
|
||||||
{
|
|
||||||
effects->postPaintWindow( w );
|
|
||||||
}
|
|
||||||
|
|
||||||
QRect ShadowEffect::transformWindowDamage( EffectWindow* w, const QRect& r )
|
|
||||||
{
|
|
||||||
if( !useShadow( w ))
|
|
||||||
return effects->transformWindowDamage( w, r );
|
|
||||||
QRect r2 = r | shadowRectangle( r );
|
|
||||||
return effects->transformWindowDamage( w, r2 );
|
|
||||||
}
|
|
||||||
|
|
||||||
void ShadowEffect::windowClosed( EffectWindow* c )
|
void ShadowEffect::windowClosed( EffectWindow* c )
|
||||||
{
|
{
|
||||||
effects->addRepaint( shadowRectangle( c->geometry() ));
|
effects->addRepaint( shadowRectangle( c->geometry() ));
|
||||||
|
@ -102,10 +127,28 @@ void ShadowEffect::addQuadVertices(QVector<float>& verts, float x1, float y1, fl
|
||||||
verts << x2 << y1;
|
verts << x2 << y1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShadowEffect::drawShadow( EffectWindow* window, int mask, QRegion region, WindowPaintData& data )
|
void ShadowEffect::drawQueuedShadows( EffectWindow* behindWindow )
|
||||||
|
{
|
||||||
|
QList<ShadowData> newShadowDatas;
|
||||||
|
EffectWindowList stack = effects->stackingOrder();
|
||||||
|
foreach( ShadowData d, shadowDatas )
|
||||||
|
{
|
||||||
|
// If behindWindow is given then only render shadows of the windows
|
||||||
|
// that are behind that window.
|
||||||
|
if( !behindWindow || stack.indexOf(d.w) < stack.indexOf(behindWindow))
|
||||||
|
{
|
||||||
|
drawShadow( d.w, d.mask, d.region.subtracted( d.clip ), d.data, true );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
newShadowDatas.append(d);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
shadowDatas = newShadowDatas;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShadowEffect::drawShadow( EffectWindow* window, int mask, QRegion region, WindowPaintData& data, bool clip )
|
||||||
{
|
{
|
||||||
if(( mask & PAINT_WINDOW_TRANSLUCENT ) == 0 )
|
|
||||||
return;
|
|
||||||
glPushAttrib( GL_CURRENT_BIT | GL_ENABLE_BIT | GL_TEXTURE_BIT );
|
glPushAttrib( GL_CURRENT_BIT | GL_ENABLE_BIT | GL_TEXTURE_BIT );
|
||||||
glEnable( GL_BLEND );
|
glEnable( GL_BLEND );
|
||||||
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
|
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
|
||||||
|
@ -168,7 +211,10 @@ void ShadowEffect::drawShadow( EffectWindow* window, int mask, QRegion region, W
|
||||||
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
|
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
|
||||||
// We have two elements per vertex in the verts array
|
// We have two elements per vertex in the verts array
|
||||||
int verticesCount = verts.count() / 2;
|
int verticesCount = verts.count() / 2;
|
||||||
renderGLGeometry( mask, region, verticesCount, verts.data(), texcoords.data() );
|
if( clip )
|
||||||
|
renderGLGeometry( true, region, verticesCount, verts.data(), texcoords.data() );
|
||||||
|
else
|
||||||
|
renderGLGeometry( mask, region, verticesCount, verts.data(), texcoords.data() );
|
||||||
mShadowTexture->unbind();
|
mShadowTexture->unbind();
|
||||||
|
|
||||||
glPopMatrix();
|
glPopMatrix();
|
||||||
|
|
|
@ -35,16 +35,16 @@ class ShadowEffect
|
||||||
public:
|
public:
|
||||||
ShadowEffect();
|
ShadowEffect();
|
||||||
virtual void prePaintWindow( EffectWindow* w, WindowPrePaintData& data, int time );
|
virtual void prePaintWindow( EffectWindow* w, WindowPrePaintData& data, int time );
|
||||||
virtual void paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data );
|
virtual void drawWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data );
|
||||||
virtual void postPaintWindow( EffectWindow* w );
|
virtual void paintScreen( int mask, QRegion region, ScreenPaintData& data );
|
||||||
virtual QRect transformWindowDamage( EffectWindow* w, const QRect& r );
|
|
||||||
virtual void windowClosed( EffectWindow* c );
|
virtual void windowClosed( EffectWindow* c );
|
||||||
private:
|
private:
|
||||||
void drawShadow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data );
|
void drawShadow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data, bool clip );
|
||||||
void addQuadVertices(QVector<float>& verts, float x1, float y1, float x2, float y2) const;
|
void addQuadVertices(QVector<float>& verts, float x1, float y1, float x2, float y2) const;
|
||||||
// transforms window rect -> shadow rect
|
// transforms window rect -> shadow rect
|
||||||
QRect shadowRectangle(const QRect& windowRectangle) const;
|
QRect shadowRectangle(const QRect& windowRectangle) const;
|
||||||
bool useShadow( EffectWindow* w ) const;
|
bool useShadow( EffectWindow* w ) const;
|
||||||
|
void drawQueuedShadows( EffectWindow* behindWindow );
|
||||||
|
|
||||||
int shadowXOffset, shadowYOffset;
|
int shadowXOffset, shadowYOffset;
|
||||||
double shadowOpacity;
|
double shadowOpacity;
|
||||||
|
@ -52,6 +52,18 @@ class ShadowEffect
|
||||||
int shadowSize;
|
int shadowSize;
|
||||||
bool intensifyActiveShadow;
|
bool intensifyActiveShadow;
|
||||||
GLTexture* mShadowTexture;
|
GLTexture* mShadowTexture;
|
||||||
|
|
||||||
|
struct ShadowData
|
||||||
|
{
|
||||||
|
ShadowData(EffectWindow* _w, WindowPaintData& _data) : w(_w), data(_data) {}
|
||||||
|
EffectWindow* w;
|
||||||
|
QRegion clip;
|
||||||
|
int mask;
|
||||||
|
QRegion region;
|
||||||
|
WindowPaintData data;
|
||||||
|
};
|
||||||
|
|
||||||
|
QList<ShadowData> shadowDatas;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
Loading…
Reference in a new issue