From b12279b6edc4e87f585d819c8015727fcd453629 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20L=C3=BCbking?= Date: Thu, 19 Apr 2012 20:25:27 +0200 Subject: [PATCH] implement mousemark effect for xrender BUG: 298338 FIXED-IN: 4.8.3 REVIEW: 104674 --- effects/mousemark/mousemark.cpp | 117 ++++++++++++++++++++++++-------- effects/mousemark/mousemark.h | 4 ++ 2 files changed, 91 insertions(+), 30 deletions(-) diff --git a/effects/mousemark/mousemark.cpp b/effects/mousemark/mousemark.cpp index e41ea82723..fa50822eb7 100644 --- a/effects/mousemark/mousemark.cpp +++ b/effects/mousemark/mousemark.cpp @@ -65,55 +65,112 @@ MouseMarkEffect::~MouseMarkEffect() effects->stopMousePolling(); } +static int width_2 = 1; void MouseMarkEffect::reconfigure(ReconfigureFlags) { KConfigGroup conf = EffectsHandler::effectConfig("MouseMark"); width = conf.readEntry("LineWidth", 3); + width_2 = width / 2; color = conf.readEntry("Color", QColor(Qt::red)); color.setAlphaF(1.0); } +#ifdef KWIN_HAVE_XRENDER_COMPOSITING +void MouseMarkEffect::addRect(const QPoint &p1, const QPoint &p2, XRectangle *r, XRenderColor *c) +{ + r->x = qMin(p1.x(), p2.x()) - width_2; + r->y = qMin(p1.y(), p2.y()) - width_2; + r->width = qAbs(p1.x()-p2.x()) + 1 + width_2; + r->height = qAbs(p1.y()-p2.y()) + 1 + width_2; + // fast move -> large rect, tess... interpolate a line + if (r->width > 3*width/2 && r->height > 3*width/2) { + const int n = sqrt(r->width*r->width + r->height*r->height) / width; + XRectangle *rects = new XRectangle[n-1]; + const int w = p1.x() < p2.x() ? r->width : -r->width; + const int h = p1.y() < p2.y() ? r->height : -r->height; + for (int i = 1; i < n; ++i) { + rects[i-1].x = p1.x() + i*w/n; + rects[i-1].y = p1.y() + i*h/n; + rects[i-1].width = rects[i-1].height = width; + } + XRenderFillRectangles(display(), PictOpSrc, effects->xrenderBufferPicture(), c, rects, n - 1); + delete [] rects; + r->x = p1.x(); + r->y = p1.y(); + r->width = r->height = width; + } +} +#endif + void MouseMarkEffect::paintScreen(int mask, QRegion region, ScreenPaintData& data) { effects->paintScreen(mask, region, data); // paint normal screen if (marks.isEmpty() && drawing.isEmpty()) return; +#ifdef KWIN_HAVE_OPENGL + if ( effects->compositingType() == OpenGLCompositing) { #ifndef KWIN_HAVE_OPENGLES - glEnable(GL_LINE_SMOOTH); + glEnable(GL_LINE_SMOOTH); #endif - glLineWidth(width); - GLVertexBuffer *vbo = GLVertexBuffer::streamingBuffer(); - vbo->reset(); - vbo->setUseColor(true); - vbo->setColor(color); - if (ShaderManager::instance()->isValid()) { - ShaderManager::instance()->pushShader(ShaderManager::ColorShader); - } - QVector verts; - foreach (const Mark & mark, marks) { - verts.clear(); - verts.reserve(mark.size() * 2); - foreach (const QPoint & p, mark) { - verts << p.x() << p.y(); + glLineWidth(width); + GLVertexBuffer *vbo = GLVertexBuffer::streamingBuffer(); + vbo->reset(); + vbo->setUseColor(true); + vbo->setColor(color); + if (ShaderManager::instance()->isValid()) { + ShaderManager::instance()->pushShader(ShaderManager::ColorShader); } - vbo->setData(verts.size() / 2, 2, verts.data(), NULL); - vbo->render(GL_LINE_STRIP); - } - if (!drawing.isEmpty()) { - verts.clear(); - verts.reserve(drawing.size() * 2); - foreach (const QPoint & p, drawing) { - verts << p.x() << p.y(); + QVector verts; + foreach (const Mark & mark, marks) { + verts.clear(); + verts.reserve(mark.size() * 2); + foreach (const QPoint & p, mark) { + verts << p.x() << p.y(); + } + vbo->setData(verts.size() / 2, 2, verts.data(), NULL); + vbo->render(GL_LINE_STRIP); } - vbo->setData(verts.size() / 2, 2, verts.data(), NULL); - vbo->render(GL_LINE_STRIP); + if (!drawing.isEmpty()) { + verts.clear(); + verts.reserve(drawing.size() * 2); + foreach (const QPoint & p, drawing) { + verts << p.x() << p.y(); + } + vbo->setData(verts.size() / 2, 2, verts.data(), NULL); + vbo->render(GL_LINE_STRIP); + } + if (ShaderManager::instance()->isValid()) { + ShaderManager::instance()->popShader(); + } + glLineWidth(1.0); + #ifndef KWIN_HAVE_OPENGLES + glDisable(GL_LINE_SMOOTH); + #endif } - if (ShaderManager::instance()->isValid()) { - ShaderManager::instance()->popShader(); +#endif +#ifdef KWIN_HAVE_XRENDER_COMPOSITING + if ( effects->compositingType() == XRenderCompositing) { + XRenderColor c = preMultiply(color); + for (int i = 0; i < marks.count(); ++i) { + const int n = marks[i].count() - 1; + if (n > 0) { + XRectangle *rects = new XRectangle[n]; + for (int j = 0; j < marks[i].count()-1; ++j) { + addRect(marks[i][j], marks[i][j+1], &rects[j], &c); + } + XRenderFillRectangles(display(), PictOpSrc, effects->xrenderBufferPicture(), &c, rects, n); + delete [] rects; + } + } + const int n = drawing.count() - 1; + if (n > 0) { + XRectangle *rects = new XRectangle[n]; + for (int i = 0; i < n; ++i) + addRect(drawing[i], drawing[i+1], &rects[i], &c); + XRenderFillRectangles(display(), PictOpSrc, effects->xrenderBufferPicture(), &c, rects, n); + delete [] rects; + } } - glLineWidth(1.0); -#ifndef KWIN_HAVE_OPENGLES - glDisable(GL_LINE_SMOOTH); #endif } diff --git a/effects/mousemark/mousemark.h b/effects/mousemark/mousemark.h index 845586ad65..ccf551d846 100644 --- a/effects/mousemark/mousemark.h +++ b/effects/mousemark/mousemark.h @@ -23,6 +23,7 @@ along with this program. If not, see . #include #include +#include namespace KWin { @@ -46,6 +47,9 @@ private slots: private: typedef QVector< QPoint > Mark; static Mark createArrow(QPoint arrow_start, QPoint arrow_end); +#ifdef KWIN_HAVE_XRENDER_COMPOSITING + void addRect(const QPoint &p1, const QPoint &p2, XRectangle *r, XRenderColor *c); +#endif QVector< Mark > marks; Mark drawing; QPoint arrow_start;