XRender implementation for ScreenEdges Glow Effect
More or less straight forward port from OpenGL to XRender. There is one small difference: the corners are not upscaled. REVIEW: 108939
This commit is contained in:
parent
25bb1482e3
commit
3d5f962566
2 changed files with 94 additions and 17 deletions
|
@ -21,11 +21,16 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
// KWin
|
||||
#include <kwinglutils.h>
|
||||
#include <kwingltexture.h>
|
||||
#include <kwinxrenderutils.h>
|
||||
// KDE
|
||||
#include <Plasma/Svg>
|
||||
// Qt
|
||||
#include <QTimer>
|
||||
#include <QPainter>
|
||||
// xcb
|
||||
#ifdef KWIN_HAVE_XRENDER_COMPOSITING
|
||||
#include <xcb/render.h>
|
||||
#endif
|
||||
|
||||
namespace KWin {
|
||||
|
||||
|
@ -101,6 +106,33 @@ void ScreenEdgeEffect::paintScreen(int mask, QRegion region, ScreenPaintData &da
|
|||
}
|
||||
texture->unbind();
|
||||
glDisable(GL_BLEND);
|
||||
} else if (effects->compositingType() == XRenderCompositing) {
|
||||
#ifdef KWIN_HAVE_XRENDER_COMPOSITING
|
||||
const QRect &rect = (*it)->geometry;
|
||||
const QSize &size = (*it)->pictureSize;
|
||||
int x = rect.x();
|
||||
int y = rect.y();
|
||||
int width = rect.width();
|
||||
int height = rect.height();
|
||||
switch ((*it)->border) {
|
||||
case ElectricTopRight:
|
||||
x = rect.x() + rect.width() - size.width();
|
||||
break;
|
||||
case ElectricBottomRight:
|
||||
x = rect.x() + rect.width() - size.width();
|
||||
y = rect.y() + rect.height() - size.height();
|
||||
break;
|
||||
case ElectricBottomLeft:
|
||||
y = rect.y() + rect.height() - size.height();
|
||||
break;
|
||||
default:
|
||||
// nothing
|
||||
break;
|
||||
}
|
||||
xcb_render_composite(connection(), XCB_RENDER_PICT_OP_OVER, *(*it)->picture.data(),
|
||||
xRenderBlendPicture(opacity), effects->xrenderBufferPicture(),
|
||||
0, 0, 0, 0, x, y, width, height);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -116,7 +148,13 @@ void ScreenEdgeEffect::edgeApproaching(ElectricBorder border, qreal factor, cons
|
|||
(*it)->geometry = geometry;
|
||||
effects->addRepaint((*it)->geometry);
|
||||
if (border == ElectricLeft || border == ElectricRight || border == ElectricTop || border == ElectricBottom) {
|
||||
(*it)->texture.reset(createEdgeGlow(border, geometry.size()));
|
||||
if (effects->isOpenGLCompositing()) {
|
||||
(*it)->texture.reset(createEdgeGlow<GLTexture>(border, geometry.size()));
|
||||
} else if (effects->compositingType() == XRenderCompositing) {
|
||||
#ifdef KWIN_HAVE_XRENDER_COMPOSITING
|
||||
(*it)->picture.reset(createEdgeGlow<XRenderPicture>(border, geometry.size()));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
if (factor == 0.0) {
|
||||
|
@ -137,41 +175,74 @@ void ScreenEdgeEffect::edgeApproaching(ElectricBorder border, qreal factor, cons
|
|||
Glow *ScreenEdgeEffect::createGlow(ElectricBorder border, qreal factor, const QRect &geometry)
|
||||
{
|
||||
Glow *glow = new Glow();
|
||||
glow->border = border;
|
||||
glow->strength = factor;
|
||||
glow->geometry = geometry;
|
||||
|
||||
// render the glow image
|
||||
if (border == ElectricTopLeft || border == ElectricTopRight || border == ElectricBottomRight || border == ElectricBottomLeft) {
|
||||
glow->texture.reset(createCornerGlow(border));
|
||||
} else {
|
||||
glow->texture.reset(createEdgeGlow(border, geometry.size()));
|
||||
if (effects->isOpenGLCompositing()) {
|
||||
if (border == ElectricTopLeft || border == ElectricTopRight || border == ElectricBottomRight || border == ElectricBottomLeft) {
|
||||
glow->texture.reset(createCornerGlow<GLTexture>(border));
|
||||
} else {
|
||||
glow->texture.reset(createEdgeGlow<GLTexture>(border, geometry.size()));
|
||||
}
|
||||
if (!glow->texture.isNull()) {
|
||||
glow->texture->setWrapMode(GL_CLAMP_TO_EDGE);
|
||||
}
|
||||
} else if (effects->compositingType() == XRenderCompositing) {
|
||||
#ifdef KWIN_HAVE_XRENDER_COMPOSITING
|
||||
if (border == ElectricTopLeft || border == ElectricTopRight || border == ElectricBottomRight || border == ElectricBottomLeft) {
|
||||
glow->pictureSize = cornerGlowSize(border);
|
||||
glow->picture.reset(createCornerGlow<XRenderPicture>(border));
|
||||
} else {
|
||||
glow->pictureSize = geometry.size();
|
||||
glow->picture.reset(createEdgeGlow<XRenderPicture>(border, geometry.size()));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
if (glow->texture.isNull()) {
|
||||
if (glow->texture.isNull() && glow->picture.isNull()) {
|
||||
delete glow;
|
||||
return NULL;
|
||||
}
|
||||
glow->texture->setWrapMode(GL_CLAMP_TO_EDGE);
|
||||
|
||||
return glow;
|
||||
}
|
||||
|
||||
GLTexture *ScreenEdgeEffect::createCornerGlow(ElectricBorder border)
|
||||
template <typename T>
|
||||
T *ScreenEdgeEffect::createCornerGlow(ElectricBorder border)
|
||||
{
|
||||
switch (border) {
|
||||
case ElectricTopLeft:
|
||||
return new GLTexture(m_glow->pixmap("bottomright"));
|
||||
return new T(m_glow->pixmap("bottomright"));
|
||||
case ElectricTopRight:
|
||||
return new GLTexture(m_glow->pixmap("bottomleft"));
|
||||
return new T(m_glow->pixmap("bottomleft"));
|
||||
case ElectricBottomRight:
|
||||
return new GLTexture(m_glow->pixmap("topleft"));
|
||||
return new T(m_glow->pixmap("topleft"));
|
||||
case ElectricBottomLeft:
|
||||
return new GLTexture(m_glow->pixmap("topright"));
|
||||
return new T(m_glow->pixmap("topright"));
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
GLTexture *ScreenEdgeEffect::createEdgeGlow(ElectricBorder border, const QSize &size)
|
||||
QSize ScreenEdgeEffect::cornerGlowSize(ElectricBorder border) const
|
||||
{
|
||||
switch (border) {
|
||||
case ElectricTopLeft:
|
||||
return m_glow->elementSize("bottomright");
|
||||
case ElectricTopRight:
|
||||
return m_glow->elementSize("bottomleft");
|
||||
case ElectricBottomRight:
|
||||
return m_glow->elementSize("topleft");
|
||||
case ElectricBottomLeft:
|
||||
return m_glow->elementSize("topright");
|
||||
default:
|
||||
return QSize();
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T *ScreenEdgeEffect::createEdgeGlow(ElectricBorder border, const QSize &size)
|
||||
{
|
||||
QPoint pixmapPosition(0, 0);
|
||||
QPixmap l, r, c;
|
||||
|
@ -201,7 +272,7 @@ GLTexture *ScreenEdgeEffect::createEdgeGlow(ElectricBorder border, const QSize &
|
|||
default:
|
||||
return NULL;
|
||||
}
|
||||
QImage image(size, QImage::Format_ARGB32);
|
||||
QPixmap image(size);
|
||||
image.fill(Qt::transparent);
|
||||
QPainter p;
|
||||
p.begin(&image);
|
||||
|
@ -215,7 +286,7 @@ GLTexture *ScreenEdgeEffect::createEdgeGlow(ElectricBorder border, const QSize &
|
|||
p.drawPixmap(QPoint(pixmapPosition.x(), size.height() - r.height()), r);
|
||||
}
|
||||
p.end();
|
||||
return new GLTexture(image);
|
||||
return new T(image);
|
||||
}
|
||||
|
||||
bool ScreenEdgeEffect::isActive() const
|
||||
|
|
|
@ -44,8 +44,11 @@ private Q_SLOTS:
|
|||
void cleanup();
|
||||
private:
|
||||
Glow *createGlow(ElectricBorder border, qreal factor, const QRect &geometry);
|
||||
GLTexture *createCornerGlow(ElectricBorder border);
|
||||
GLTexture *createEdgeGlow(ElectricBorder border, const QSize &size);
|
||||
template <typename T>
|
||||
T *createCornerGlow(ElectricBorder border);
|
||||
template <typename T>
|
||||
T *createEdgeGlow(ElectricBorder border, const QSize &size);
|
||||
QSize cornerGlowSize(ElectricBorder border) const;
|
||||
Plasma::Svg *m_glow;
|
||||
QHash<ElectricBorder, Glow*> m_borders;
|
||||
QTimer *m_cleanupTimer;
|
||||
|
@ -55,8 +58,11 @@ class Glow
|
|||
{
|
||||
public:
|
||||
QScopedPointer<GLTexture> texture;
|
||||
QScopedPointer<XRenderPicture> picture;
|
||||
qreal strength;
|
||||
QRect geometry;
|
||||
QSize pictureSize;
|
||||
ElectricBorder border;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue