kwin: Implement shadows in XRender compositor

There are still some glitches to be fixed, but
it works well for most use-cases.
This commit is contained in:
Jacopo De Simoi 2011-04-28 11:22:17 -04:00
parent ecf9d6e989
commit e688058235
3 changed files with 157 additions and 0 deletions

View file

@ -419,6 +419,9 @@ void SceneXrender::windowClosed(Toplevel* c, Deleted* deleted)
// replace c with deleted
Window* w = windows.take(c);
w->updateToplevel(deleted);
if (w->shadow()) {
w->shadow()->setToplevel(deleted);
}
windows[ deleted ] = w;
} else {
delete windows.take(c);
@ -438,6 +441,8 @@ void SceneXrender::windowAdded(Toplevel* c)
assert(!windows.contains(c));
windows[ c ] = new Window(c);
c->effectWindow()->setSceneWindow(windows[ c ]);
c->getShadow();
windows[ c ]->updateShadow(c->shadow());
}
//****************************************
@ -719,6 +724,38 @@ void SceneXrender::Window::performPaint(int mask, QRegion region, WindowPaintDat
XRenderChangePicture(display(), pic, CPRepeat, &attr);
}
}
//shadow
if (m_shadow) {
QRect stlr, str, strr, srr, sbrr, sbr, sblr, slr;
SceneXRenderShadow* m_xrenderShadow = static_cast<SceneXRenderShadow*>(m_shadow);
m_xrenderShadow->layoutShadowRects(str, strr, srr, sbrr, sbr, sblr, slr, stlr);
if (!scaled) {
stlr = mapToScreen(mask, data, stlr);
str = mapToScreen(mask, data, str);
strr = mapToScreen(mask, data, strr);
srr = mapToScreen(mask, data, srr);
sbrr = mapToScreen(mask, data, sbrr);
sbr = mapToScreen(mask, data, sbr);
sblr = mapToScreen(mask, data, sblr);
slr = mapToScreen(mask, data, slr);
Picture alpha = alphaMask(data.opacity);
XRenderComposite(display(), PictOpOver, m_xrenderShadow->x11ShadowPictureHandle(WindowQuadShadowTopLeft), alpha, buffer, 0, 0, 0, 0, stlr.x(), stlr.y(), stlr.width(), stlr.height());
XRenderComposite(display(), PictOpOver, m_xrenderShadow->x11ShadowPictureHandle(WindowQuadShadowTop), alpha, buffer, 0, 0, 0, 0, str.x(), str.y(), str.width(), str.height());
XRenderComposite(display(), PictOpOver, m_xrenderShadow->x11ShadowPictureHandle(WindowQuadShadowTopRight), alpha, buffer, 0, 0, 0, 0, strr.x(), strr.y(), strr.width(), strr.height());
XRenderComposite(display(), PictOpOver, m_xrenderShadow->x11ShadowPictureHandle(WindowQuadShadowLeft), alpha, buffer, 0, 0, 0, 0, slr.x(), slr.y(), slr.width(), slr.height());
XRenderComposite(display(), PictOpOver, m_xrenderShadow->x11ShadowPictureHandle(WindowQuadShadowRight), alpha, buffer, 0, 0, 0, 0, srr.x(), srr.y(), srr.width(), srr.height());
XRenderComposite(display(), PictOpOver, m_xrenderShadow->x11ShadowPictureHandle(WindowQuadShadowBottomLeft), alpha, buffer, 0, 0, 0, 0, sblr.x(), sblr.y(), sblr.width(), sblr.height());
XRenderComposite(display(), PictOpOver, m_xrenderShadow->x11ShadowPictureHandle(WindowQuadShadowBottom), alpha, buffer, 0, 0, 0, 0, sbr.x(), sbr.y(), sbr.width(), sbr.height());
XRenderComposite(display(), PictOpOver, m_xrenderShadow->x11ShadowPictureHandle(WindowQuadShadowBottomRight), alpha, buffer, 0, 0, 0, 0, sbrr.x(), sbrr.y(), sbrr.width(), sbrr.height());
} else {
//FIXME: At the moment shadows are not painted for scaled windows
}
}
for (PaintClipper::Iterator iterator;
!iterator.isDone();
iterator.next()) {
@ -982,5 +1019,85 @@ void SceneXrender::EffectFrame::updateTextPicture()
m_textPicture = new XRenderPicture(pixmap);
}
SceneXRenderShadow::SceneXRenderShadow(Toplevel *toplevel)
:Shadow(toplevel)
{
}
SceneXRenderShadow::~SceneXRenderShadow()
{
}
Qt::HANDLE SceneXRenderShadow::x11ShadowPictureHandle(WindowQuadType type)
{
switch (type) {
case WindowQuadShadowTopRight:
return resizedShadowPixmap(ShadowElementTopRight).x11PictureHandle();
case WindowQuadShadowTop:
return resizedShadowPixmap(ShadowElementTop).x11PictureHandle();
case WindowQuadShadowTopLeft:
return resizedShadowPixmap(ShadowElementTopLeft).x11PictureHandle();
case WindowQuadShadowLeft:
return resizedShadowPixmap(ShadowElementLeft).x11PictureHandle();
case WindowQuadShadowBottomLeft:
return resizedShadowPixmap(ShadowElementBottomLeft).x11PictureHandle();
case WindowQuadShadowBottom:
return resizedShadowPixmap(ShadowElementBottom).x11PictureHandle();
case WindowQuadShadowBottomRight:
return resizedShadowPixmap(ShadowElementBottomRight).x11PictureHandle();
case WindowQuadShadowRight:
return resizedShadowPixmap(ShadowElementRight).x11PictureHandle();
default:
return 0;
}
}
void SceneXRenderShadow::layoutShadowRects(QRect& top, QRect& topRight,
QRect& right, QRect& bottomRight,
QRect& bottom, QRect& bottomLeft,
QRect& left, QRect& topLeft)
{
WindowQuadList quads = shadowQuads();
if (quads.count() == 0) {
return;
}
WindowQuad topQuad = quads.select(WindowQuadShadowTop)[0];
WindowQuad topRightQuad = quads.select(WindowQuadShadowTopRight)[0];
WindowQuad topLeftQuad = quads.select(WindowQuadShadowTopLeft)[0];
WindowQuad leftQuad = quads.select(WindowQuadShadowLeft)[0];
WindowQuad rightQuad = quads.select(WindowQuadShadowRight)[0];
WindowQuad bottomQuad = quads.select(WindowQuadShadowBottom)[0];
WindowQuad bottomRightQuad = quads.select(WindowQuadShadowBottomRight)[0];
WindowQuad bottomLeftQuad = quads.select(WindowQuadShadowBottomLeft)[0];
top = QRect(topQuad.left(), topQuad.top(), (topQuad.right()-topQuad.left()), (topQuad.bottom()-topQuad.top()));
topLeft = QRect(topLeftQuad.left(), topLeftQuad.top(), (topLeftQuad.right()-topLeftQuad.left()), (topLeftQuad.bottom()-topLeftQuad.top()));
topRight = QRect(topRightQuad.left(), topRightQuad.top(), (topRightQuad.right()-topRightQuad.left()), (topRightQuad.bottom()-topRightQuad.top()));
left = QRect(leftQuad.left(), leftQuad.top(), (leftQuad.right()-leftQuad.left()), (leftQuad.bottom()-leftQuad.top()));
right = QRect(rightQuad.left(), rightQuad.top(), (rightQuad.right()-rightQuad.left()), (rightQuad.bottom()-rightQuad.top()));
bottom = QRect(bottomQuad.left(), bottomQuad.top(), (bottomQuad.right()-bottomQuad.left()), (bottomQuad.bottom()-bottomQuad.top()));
bottomLeft = QRect(bottomLeftQuad.left(), bottomLeftQuad.top(), (bottomLeftQuad.right()-bottomLeftQuad.left()), (bottomLeftQuad.bottom()-bottomLeftQuad.top()));
bottomRight = QRect(bottomRightQuad.left(), bottomRightQuad.top(), (bottomRightQuad.right()-bottomRightQuad.left()), (bottomRightQuad.bottom()-bottomRightQuad.top()));
}
void SceneXRenderShadow::buildQuads()
{
Shadow::buildQuads();
QRect stlr, str, strr, srr, sbrr, sbr, sblr, slr;
layoutShadowRects(str, strr, srr, sbrr, sbr, sblr, slr, stlr);
m_resizedElements[ShadowElementTop] = shadowPixmap(ShadowElementTop).scaled(str.size());
m_resizedElements[ShadowElementTopLeft] = shadowPixmap(ShadowElementTopLeft).scaled(stlr.size());
m_resizedElements[ShadowElementTopRight] = shadowPixmap(ShadowElementTopRight).scaled(strr.size());
m_resizedElements[ShadowElementLeft] = shadowPixmap(ShadowElementLeft).scaled(slr.size());
m_resizedElements[ShadowElementRight] = shadowPixmap(ShadowElementRight).scaled(srr.size());
m_resizedElements[ShadowElementBottom] = shadowPixmap(ShadowElementBottom).scaled(sbr.size());
m_resizedElements[ShadowElementBottomLeft] = shadowPixmap(ShadowElementBottomLeft).scaled(sblr.size());
m_resizedElements[ShadowElementBottomRight] = shadowPixmap(ShadowElementBottomRight).scaled(sbrr.size());
}
} // namespace
#endif

View file

@ -24,6 +24,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <config-workspace.h>
#include "scene.h"
#include "shadow.h"
#ifdef KWIN_HAVE_XRENDER_COMPOSITING
#include <X11/extensions/Xrender.h>
@ -138,6 +139,37 @@ void SceneXrender::Window::setTransformedShape(const QRegion& shape)
transformed_shape = shape;
}
/**
* @short XRender implementation of Shadow.
*
* This class extends Shadow by the elements required for XRender rendering.
* @author Jacopo De Simoi <wilderkde@gmail.org>
**/
class SceneXRenderShadow
: public Shadow
{
public:
SceneXRenderShadow(Toplevel *toplevel);
virtual ~SceneXRenderShadow();
Qt::HANDLE x11ShadowPictureHandle(WindowQuadType);
void layoutShadowRects(QRect& top, QRect& topRight,
QRect& right, QRect& bottomRight,
QRect& bottom, QRect& bottomLeft,
QRect& Left, QRect& topLeft);
const QPixmap &resizedShadowPixmap(ShadowElements element) const {
return m_resizedElements[element];
};
protected:
virtual void buildQuads();
private:
QPixmap m_resizedElements[ShadowElementsCount];
};
} // namespace
#endif

View file

@ -25,6 +25,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifdef KWIN_HAVE_OPENGL_COMPOSITING
#include "scene_opengl.h"
#endif
#ifdef KWIN_HAVE_XRENDER_COMPOSITING
#include "scene_xrender.h"
#endif
namespace KWin
{
@ -51,8 +54,13 @@ Shadow *Shadow::createShadow(Toplevel *toplevel)
if (effects->compositingType() == OpenGLCompositing) {
#ifdef KWIN_HAVE_OPENGL_COMPOSITING
shadow = new SceneOpenGLShadow(toplevel);
#endif
} else if (effects->compositingType() == XRenderCompositing) {
#ifdef KWIN_HAVE_XRENDER_COMPOSITING
shadow = new SceneXRenderShadow(toplevel);
#endif
}
if (shadow) {
if (!shadow->init(data)) {
delete shadow;