diff --git a/effects/shadow.cpp b/effects/shadow.cpp
index a9eb5ee94c..7277df2f57 100644
--- a/effects/shadow.cpp
+++ b/effects/shadow.cpp
@@ -28,12 +28,51 @@ along with this program. If not, see .
#include
#include
#include
+#ifdef KWIN_HAVE_XRENDER_COMPOSITING
+#include
+#endif
+
+#include
namespace KWin
{
KWIN_EFFECT( shadow, ShadowEffect )
+ShadowTiles::ShadowTiles(const QPixmap& shadow)
+ {
+ int w = shadow.width() / 2, h = shadow.height() / 2;
+ cornerSize = QSize(w, h);
+#define DUMP_CNR(_TILE_, _W_, _H_, _XOFF_, _YOFF_)\
+ dump = QPixmap(_W_, _H_);\
+ dump.fill(Qt::transparent);\
+ p.begin(&dump);\
+ p.drawPixmap( 0, 0, shadow, _XOFF_, _YOFF_, _W_, _H_ );\
+ p.end();\
+ _TILE_ = dump
+
+ QPixmap dump; QPainter p;
+ DUMP_CNR(topLeft, w, h, 0, 0);
+ DUMP_CNR(topRight, w, h, w, 0);
+ DUMP_CNR(btmLeft, w, h, 0, h);
+ DUMP_CNR(btmRight, w, h, w, h);
+
+ XRenderPictureAttributes pa; pa.repeat = True;
+#define DUMP_TILE(_TILE_, _W_, _H_, _XOFF_, _YOFF_)\
+ DUMP_CNR(_TILE_, _W_, _H_, _XOFF_, _YOFF_);\
+ XRenderChangePicture (display(), _TILE_, CPRepeat, &pa)
+
+ DUMP_TILE(top, 1, h, w, 0);
+ DUMP_TILE(btm, 1, h, w, h);
+ DUMP_TILE(left, w, 1, 0, h);
+ DUMP_TILE(right, w, 1, w, h);
+
+ DUMP_TILE(center, 1, 1, w, h);
+ }
+
+#undef DUMP_CNR
+#undef DUMP_TILE
+
ShadowEffect::ShadowEffect()
{
KConfigGroup conf = effects->effectConfig("Shadow");
@@ -43,9 +82,40 @@ ShadowEffect::ShadowEffect()
shadowFuzzyness = conf.readEntry( "Fuzzyness", 10 );
shadowSize = conf.readEntry( "Size", 5 );
intensifyActiveShadow = conf.readEntry( "IntensifyActiveShadow", true );
+#ifdef KWIN_HAVE_OPENGL_COMPOSITING
+ if ( effects->compositingType() == OpenGLCompositing)
+ {
+ QString shadowtexture = KGlobal::dirs()->findResource("data", "kwin/shadow-texture.png");
+ mShadowTexture = new GLTexture(shadowtexture);
+ }
+ else
+ mShadowTexture = NULL;
+#endif
+#ifdef KWIN_HAVE_XRENDER_COMPOSITING
+ if ( effects->compositingType() == XRenderCompositing)
+ {
+ qreal size = 2*(shadowFuzzyness+shadowSize)+1;
+ QPixmap *shadow = new QPixmap(size, size); shadow->fill(Qt::transparent);
+ size /= 2.0;
+ QRadialGradient rg(size, size, size);
+ QColor c(0,0,0,255);
+ rg.setColorAt(0, c);
+ c.setAlpha(0.3*c.alpha());
+ if (shadowSize > 0)
+ rg.setColorAt(((float)shadowSize)/(shadowFuzzyness+shadowSize), c);
+ c.setAlpha(0); rg.setColorAt(0.8, c);
+ QPainter p(shadow);
+ p.setRenderHint(QPainter::Antialiasing);
+ p.setPen(Qt::NoPen); p.setBrush(rg);
+ p.drawRect(shadow->rect());
+ p.end();
- QString shadowtexture = KGlobal::dirs()->findResource("data", "kwin/shadow-texture.png");
- mShadowTexture = new GLTexture(shadowtexture);
+ mShadowPics = new ShadowTiles(*shadow);
+ delete shadow;
+ }
+ else
+ mShadowPics = NULL;
+#endif
updateShadowColor();
connect(KGlobalSettings::self(), SIGNAL(kdisplayPaletteChanged()),
@@ -54,7 +124,12 @@ ShadowEffect::ShadowEffect()
ShadowEffect::~ShadowEffect()
{
+#ifdef KWIN_HAVE_OPENGL_COMPOSITING
delete mShadowTexture;
+#endif
+#ifdef KWIN_HAVE_XRENDER_COMPOSITING
+ delete mShadowPics;
+#endif
}
void ShadowEffect::updateShadowColor()
@@ -70,10 +145,23 @@ QRect ShadowEffect::shadowRectangle(const QRect& windowRectangle) const
shadowXOffset + shadowGrow, shadowYOffset + shadowGrow);
}
+#ifdef KWIN_HAVE_XRENDER_COMPOSITING
+static ScreenPaintData gScreenData;
+#endif
+
void ShadowEffect::paintScreen( int mask, QRegion region, ScreenPaintData& data )
{
shadowDatas.clear();
-
+#ifdef KWIN_HAVE_XRENDER_COMPOSITING
+ if ((mask & PAINT_SCREEN_TRANSFORMED) &&
+ (effects->compositingType() == XRenderCompositing)) // TODO: copy constructor?
+ {
+ gScreenData.xTranslate = data.xTranslate;
+ gScreenData.yTranslate = data.yTranslate;
+ gScreenData.xScale = data.xScale;
+ gScreenData.yScale = data.yScale;
+ }
+#endif
// Draw windows
effects->paintScreen( mask, region, data );
@@ -177,73 +265,149 @@ void ShadowEffect::drawQueuedShadows( EffectWindow* behindWindow )
void ShadowEffect::drawShadow( EffectWindow* window, int mask, QRegion region, WindowPaintData& data )
{
- glPushAttrib( GL_CURRENT_BIT | GL_ENABLE_BIT | GL_TEXTURE_BIT );
- glEnable( GL_BLEND );
- glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
+#ifdef KWIN_HAVE_OPENGL_COMPOSITING
+ if( effects->compositingType() == OpenGLCompositing)
+ {
+ glPushAttrib( GL_CURRENT_BIT | GL_ENABLE_BIT | GL_TEXTURE_BIT );
+ glEnable( GL_BLEND );
+ glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
- int fuzzy = shadowFuzzyness;
- // Shadow's size must be a least 2*fuzzy in both directions (or the corners will be broken)
- int w = qMax(fuzzy*2, window->width() + 2*shadowSize);
- int h = qMax(fuzzy*2, window->height() + 2*shadowSize);
+ int fuzzy = shadowFuzzyness;
+ // Shadow's size must be a least 2*fuzzy in both directions (or the corners will be broken)
+ int w = qMax(fuzzy*2, window->width() + 2*shadowSize);
+ int h = qMax(fuzzy*2, window->height() + 2*shadowSize);
- glPushMatrix();
- if( mask & PAINT_WINDOW_TRANSFORMED )
- glTranslatef( data.xTranslate, data.yTranslate, 0 );
- glTranslatef( window->x() + shadowXOffset - qMax(0, w - window->width()) / 2.0,
- window->y() + shadowYOffset - qMax(0, h - window->height()) / 2.0, 0 );
- if(( mask & PAINT_WINDOW_TRANSFORMED ) && ( data.xScale != 1 || data.yScale != 1 ))
- glScalef( data.xScale, data.yScale, 1 );
+ glPushMatrix();
+ if( mask & PAINT_WINDOW_TRANSFORMED )
+ glTranslatef( data.xTranslate, data.yTranslate, 0 );
+ glTranslatef( window->x() + shadowXOffset - qMax(0, w - window->width()) / 2.0,
+ window->y() + shadowYOffset - qMax(0, h - window->height()) / 2.0, 0 );
+ if(( mask & PAINT_WINDOW_TRANSFORMED ) && ( data.xScale != 1 || data.yScale != 1 ))
+ glScalef( data.xScale, data.yScale, 1 );
- QVector verts, texcoords;
- verts.reserve(80);
- texcoords.reserve(80);
- // center
- addQuadVertices(verts, 0 + fuzzy, 0 + fuzzy, w - fuzzy, h - fuzzy);
- addQuadVertices(texcoords, 0.5, 0.5, 0.5, 0.5);
- // sides
- // left
- addQuadVertices(verts, 0 - fuzzy, 0 + fuzzy, 0 + fuzzy, h - fuzzy);
- addQuadVertices(texcoords, 0.0, 0.5, 0.5, 0.5);
- // top
- addQuadVertices(verts, 0 + fuzzy, 0 - fuzzy, w - fuzzy, 0 + fuzzy);
- addQuadVertices(texcoords, 0.5, 0.0, 0.5, 0.5);
- // right
- addQuadVertices(verts, w - fuzzy, 0 + fuzzy, w + fuzzy, h - fuzzy);
- addQuadVertices(texcoords, 0.5, 0.5, 1.0, 0.5);
- // bottom
- addQuadVertices(verts, 0 + fuzzy, h - fuzzy, w - fuzzy, h + fuzzy);
- addQuadVertices(texcoords, 0.5, 0.5, 0.5, 1.0);
- // corners
- // top-left
- addQuadVertices(verts, 0 - fuzzy, 0 - fuzzy, 0 + fuzzy, 0 + fuzzy);
- addQuadVertices(texcoords, 0.0, 0.0, 0.5, 0.5);
- // top-right
- addQuadVertices(verts, w - fuzzy, 0 - fuzzy, w + fuzzy, 0 + fuzzy);
- addQuadVertices(texcoords, 0.5, 0.0, 1.0, 0.5);
- // bottom-left
- addQuadVertices(verts, 0 - fuzzy, h - fuzzy, 0 + fuzzy, h + fuzzy);
- addQuadVertices(texcoords, 0.0, 0.5, 0.5, 1.0);
- // bottom-right
- addQuadVertices(verts, w - fuzzy, h - fuzzy, w + fuzzy, h + fuzzy);
- addQuadVertices(texcoords, 0.5, 0.5, 1.0, 1.0);
+ QVector verts, texcoords;
+ verts.reserve(80);
+ texcoords.reserve(80);
+ // center
+ addQuadVertices(verts, 0 + fuzzy, 0 + fuzzy, w - fuzzy, h - fuzzy);
+ addQuadVertices(texcoords, 0.5, 0.5, 0.5, 0.5);
+ // sides
+ // left
+ addQuadVertices(verts, 0 - fuzzy, 0 + fuzzy, 0 + fuzzy, h - fuzzy);
+ addQuadVertices(texcoords, 0.0, 0.5, 0.5, 0.5);
+ // top
+ addQuadVertices(verts, 0 + fuzzy, 0 - fuzzy, w - fuzzy, 0 + fuzzy);
+ addQuadVertices(texcoords, 0.5, 0.0, 0.5, 0.5);
+ // right
+ addQuadVertices(verts, w - fuzzy, 0 + fuzzy, w + fuzzy, h - fuzzy);
+ addQuadVertices(texcoords, 0.5, 0.5, 1.0, 0.5);
+ // bottom
+ addQuadVertices(verts, 0 + fuzzy, h - fuzzy, w - fuzzy, h + fuzzy);
+ addQuadVertices(texcoords, 0.5, 0.5, 0.5, 1.0);
+ // corners
+ // top-left
+ addQuadVertices(verts, 0 - fuzzy, 0 - fuzzy, 0 + fuzzy, 0 + fuzzy);
+ addQuadVertices(texcoords, 0.0, 0.0, 0.5, 0.5);
+ // top-right
+ addQuadVertices(verts, w - fuzzy, 0 - fuzzy, w + fuzzy, 0 + fuzzy);
+ addQuadVertices(texcoords, 0.5, 0.0, 1.0, 0.5);
+ // bottom-left
+ addQuadVertices(verts, 0 - fuzzy, h - fuzzy, 0 + fuzzy, h + fuzzy);
+ addQuadVertices(texcoords, 0.0, 0.5, 0.5, 1.0);
+ // bottom-right
+ addQuadVertices(verts, w - fuzzy, h - fuzzy, w + fuzzy, h + fuzzy);
+ addQuadVertices(texcoords, 0.5, 0.5, 1.0, 1.0);
- mShadowTexture->bind();
- // Take the transparency settings and window's transparency into account.
- // Also make the shadow more transparent if we've made it bigger
- float opacity = shadowOpacity;
- if( intensifyActiveShadow && window == effects->activeWindow() )
- {
- opacity = 1 - (1 - shadowOpacity)*(1 - shadowOpacity);
- }
- glColor4f(shadowColor.redF(), shadowColor.greenF(), shadowColor.blueF(), opacity * data.opacity * (window->width() / (double)w) * (window->height() / (double)h));
- glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
- // We have two elements per vertex in the verts array
- int verticesCount = verts.count() / 2;
- renderGLGeometry( region, verticesCount, verts.data(), texcoords.data() );
- mShadowTexture->unbind();
+ mShadowTexture->bind();
+ // Take the transparency settings and window's transparency into account.
+ // Also make the shadow more transparent if we've made it bigger
+ float opacity = shadowOpacity;
+ if( intensifyActiveShadow && window == effects->activeWindow() )
+ {
+ opacity = 1 - (1 - shadowOpacity)*(1 - shadowOpacity);
+ }
+ glColor4f(shadowColor.redF(), shadowColor.greenF(), shadowColor.blueF(), opacity * data.opacity * (window->width() / (double)w) * (window->height() / (double)h));
+ glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+ // We have two elements per vertex in the verts array
+ int verticesCount = verts.count() / 2;
+ renderGLGeometry( region, verticesCount, verts.data(), texcoords.data() );
+ mShadowTexture->unbind();
- glPopMatrix();
- glPopAttrib();
+ glPopMatrix();
+ glPopAttrib();
+ }
+#endif
+#ifdef KWIN_HAVE_XRENDER_COMPOSITING
+ if( effects->compositingType() == XRenderCompositing)
+ {
+ // calculate opacity =================================================
+ float opacity;
+ if( intensifyActiveShadow && window == effects->activeWindow() )
+ {
+ opacity = (1 - (1 - shadowOpacity)*(1 - shadowOpacity)) * data.opacity;
+ }
+ else
+ {
+ opacity = data.opacity * shadowOpacity;
+ }
+
+ // query rect and translate in case (may have impact on opacity)===========================
+ QRect r = window->geometry();
+ if ( mask & (PAINT_WINDOW_TRANSFORMED | PAINT_SCREEN_TRANSFORMED))
+ {
+ float xScale = 1.0, yScale = 1.0, xTranslate = 0.0, yTranslate = 0.0;
+ if ( mask & PAINT_SCREEN_TRANSFORMED)
+ {
+ xScale = gScreenData.xScale; yScale = gScreenData.yScale;
+ xTranslate += (xScale-1.0)*r.x() + gScreenData.xTranslate;
+ yTranslate += (yScale-1.0)*r.y() + gScreenData.yTranslate;
+ }
+
+ if ( mask & PAINT_WINDOW_TRANSFORMED)
+ {
+ xTranslate += xScale*data.xTranslate;
+ yTranslate += yScale*data.yTranslate;
+ xScale *= data.xScale; yScale *= data.yScale;
+ }
+
+ r.translate(xTranslate, yTranslate);
+
+ if (xScale != 1.0 || yScale != 1.0)
+ {
+ r.setWidth(xScale * r.width());
+ r.setHeight(yScale * r.height());
+// opacity *= 2.0/(2 - (2 - (xScale + yScale))*(2 - (xScale + yScale)));
+ }
+ }
+ r = shadowRectangle(r);
+
+ // create render mask ==================================================================
+
+ XRenderColor xc = preMultiply(shadowColor, opacity);
+ XRenderPicture fill = xRenderFill(&xc);
+
+ // clip, then paint shadow tiles ========================================================
+ XRenderSetPictureClipRegion (display(), effects->xrenderBufferPicture(), region.handle());
+#define DRAW_CORNER(_CNR_, _X_, _Y_)\
+XRenderComposite( display(), PictOpOver, fill, mShadowPics->_CNR_, effects->xrenderBufferPicture(), 0, 0, 0, 0, _X_, _Y_, w, h )
+#define DRAW_TILE(_TILE_, _X_, _Y_, _W_, _H_)\
+XRenderComposite( display(), PictOpOver, fill, mShadowPics->_TILE_, effects->xrenderBufferPicture(), 0, 0, 0, 0, _X_, _Y_, _W_, _H_ )
+ int w = qMin(mShadowPics->cornerSize.width(), r.width()/2);
+ int h = qMin(mShadowPics->cornerSize.height(), r.height()/2);
+ DRAW_CORNER(topLeft, r.x(), r.y());
+ DRAW_CORNER(topRight, r.right()-w, r.y());
+ DRAW_CORNER(btmLeft, r.x(), r.bottom()-h);
+ DRAW_CORNER(btmRight, r.right()-w, r.bottom()-h);
+ int w2 = r.width()-2*w-1, h2 = r.height()-2*h-1;
+ DRAW_TILE(top, r.x()+w, r.y(), w2, h);
+ DRAW_TILE(btm, r.x()+w, r.bottom()-h, w2, h);
+ DRAW_TILE(left, r.x(), r.y()+h, w, h2);
+ DRAW_TILE(right, r.right()-w, r.y()+h, w, h2);
+ DRAW_TILE(center, r.x()+w, r.y()+h, w2, h2);
+#undef DRAW_CORNER
+#undef DRAW_TILE
+ }
+#endif
}
} // namespace
diff --git a/effects/shadow.h b/effects/shadow.h
index 32269a4b9d..4617a6b25f 100644
--- a/effects/shadow.h
+++ b/effects/shadow.h
@@ -22,13 +22,23 @@ along with this program. If not, see .
#define KWIN_SHADOW_H
#include
-
+#include
namespace KWin
{
class GLTexture;
+class ShadowTiles
+ {
+ public:
+ ShadowTiles(const QPixmap& shadow);
+ XRenderPicture topLeft, top, topRight,
+ left, center, right,
+ btmLeft, btm, btmRight;
+ QSize cornerSize;
+ };
+
class ShadowEffect
: public QObject, public Effect
{
@@ -60,6 +70,7 @@ class ShadowEffect
bool intensifyActiveShadow;
QColor shadowColor;
GLTexture* mShadowTexture;
+ ShadowTiles *mShadowPics;
struct ShadowData
{