diff --git a/libkwineffects/kwinxrenderutils.cpp b/libkwineffects/kwinxrenderutils.cpp index 2ea6b9dc1d..41a864163b 100644 --- a/libkwineffects/kwinxrenderutils.cpp +++ b/libkwineffects/kwinxrenderutils.cpp @@ -73,64 +73,6 @@ XRenderPicture xRenderBlendPicture(double opacity) return _blendPicture; } - -static XRenderPicture *_circle[4] = {NULL, NULL, NULL, NULL}; - -#define DUMP_CNR(_SECT_, _W_, _H_, _XOFF_, _YOFF_)\ - dump = QPixmap(_W_, _H_);\ - dump.fill(Qt::transparent);\ - p.begin(&dump);\ - p.drawPixmap( 0, 0, tmp, _XOFF_, _YOFF_, _W_, _H_ );\ - p.end();\ - _circle[_SECT_] = new XRenderPicture(dump); - -#define CS 8 - -static XRenderPicture *circle(int i) -{ - if (!_circle[0]) { - QPixmap tmp(2 * CS, 2 * CS); - tmp.fill(Qt::transparent); - QPainter p(&tmp); - p.setRenderHint(QPainter::Antialiasing); - p.setPen(Qt::NoPen); p.setBrush(Qt::black); - p.drawEllipse(tmp.rect()); - p.end(); - QPixmap dump; - DUMP_CNR(0, CS, CS, 0, 0); - DUMP_CNR(1, CS, CS, CS, 0); - DUMP_CNR(2, CS, CS, CS, CS); - DUMP_CNR(3, CS, CS, 0, CS); - } - return _circle[i]; -} - -void xRenderRoundBox(Picture pict, const QRect &rect, int , const QColor &c) -{ - XRenderPicture fill = xRenderFill(c); - int op = c.alpha() == 255 ? PictOpSrc : PictOpOver; - // TODO: implement second paramenter "roundness" - // so rather use ?? XRenderCompositeTriFan (dpy, op, src, dst, maskFormat, xSrc, ySrc, - //XPointFixed *points, npoint); - // this will require "points on a circle" calculation, however... - - int s = qMin(CS, qMin(rect.height() / 2, rect.width() / 2)); - int x, y, b, r; - rect.getCoords(&x, &y, &r, &b); - r -= (s - 1); - b -= (s - 1); - XRenderComposite(display(), PictOpOver, fill, *circle(0), pict, 0, 0, 0, 0, x, y, CS, CS); - XRenderComposite(display(), PictOpOver, fill, *circle(1), pict, 0, 0, CS - s, 0, r, y, s, s); - XRenderComposite(display(), PictOpOver, fill, *circle(2), pict, 0, 0, CS - s, CS - s, r, b, s, s); - XRenderComposite(display(), PictOpOver, fill, *circle(3), pict, 0, 0, 0, CS - s, x, b, s, s); - XRenderComposite(display(), op, fill, 0, pict, 0, 0, 0, 0, x + s, y, rect.width() - 2 * s, s); - XRenderComposite(display(), op, fill, 0, pict, 0, 0, 0, 0, x, y + s, rect.width(), rect.height() - 2 * s); - XRenderComposite(display(), op, fill, 0, pict, 0, 0, 0, 0, x + s, b, rect.width() - 2 * s, s); -} - -#undef CS -#undef DUMP_CNR - // XRenderFind(Standard)Format() is a roundtrip, so cache the results static XRenderPictFormat* renderformats[ 33 ]; diff --git a/libkwineffects/kwinxrenderutils.h b/libkwineffects/kwinxrenderutils.h index 4218f8ba81..7069e8201f 100644 --- a/libkwineffects/kwinxrenderutils.h +++ b/libkwineffects/kwinxrenderutils.h @@ -39,10 +39,6 @@ along with this program. If not, see . namespace KWin { -/** - * draws a round box on the renderscene - */ -KWIN_EXPORT void xRenderRoundBox(Picture pict, const QRect &rect, int round, const QColor &c); /** * dumps a QColor into a XRenderColor */ diff --git a/scene_xrender.cpp b/scene_xrender.cpp index 140470a168..dc40f66137 100644 --- a/scene_xrender.cpp +++ b/scene_xrender.cpp @@ -37,6 +37,7 @@ along with this program. If not, see . #include #include +#include namespace KWin { @@ -93,6 +94,7 @@ SceneXrender::~SceneXrender() m_overlayWindow->destroy(); return; } + SceneXrender::EffectFrame::cleanup(); XRenderFreePicture(display(), front); XRenderFreePicture(display(), buffer); buffer = None; @@ -727,6 +729,8 @@ void SceneXrender::screenGeometryChanged(const QSize &size) // SceneXrender::EffectFrame //**************************************** +XRenderPicture *SceneXrender::EffectFrame::s_effectFrameCircle = NULL; + SceneXrender::EffectFrame::EffectFrame(EffectFrameImpl* frame) : Scene::EffectFrame(frame) { @@ -744,6 +748,12 @@ SceneXrender::EffectFrame::~EffectFrame() delete m_selectionPicture; } +void SceneXrender::EffectFrame::cleanup() +{ + delete s_effectFrameCircle; + s_effectFrameCircle = NULL; +} + void SceneXrender::EffectFrame::free() { delete m_picture; @@ -792,10 +802,9 @@ void SceneXrender::EffectFrame::render(QRegion region, double opacity, double fr } // Render the actual frame - if (m_effectFrame->style() == EffectFrameUnstyled) - xRenderRoundBox(effects->xrenderBufferPicture(), m_effectFrame->geometry().adjusted(-5, -5, 5, 5), - 5, QColor(0, 0, 0, int(opacity * frameOpacity * 255))); - else if (m_effectFrame->style() == EffectFrameStyled) { + if (m_effectFrame->style() == EffectFrameUnstyled) { + renderUnstyled(effects->xrenderBufferPicture(), m_effectFrame->geometry(), opacity * frameOpacity); + } else if (m_effectFrame->style() == EffectFrameStyled) { if (!m_picture) { // Lazy creation updatePicture(); } @@ -844,6 +853,95 @@ void SceneXrender::EffectFrame::render(QRegion region, double opacity, double fr } } +void SceneXrender::EffectFrame::renderUnstyled(xcb_render_picture_t pict, const QRect &rect, qreal opacity) +{ + const int roundness = 5; + const QRect area = rect.adjusted(-roundness, -roundness, roundness, roundness); + xcb_rectangle_t rects[3]; + // center + rects[0].x = area.left(); + rects[0].y = area.top() + roundness; + rects[0].width = area.width(); + rects[0].height = area.height() - roundness * 2; + // top + rects[1].x = area.left() + roundness; + rects[1].y = area.top(); + rects[1].width = area.width() - roundness * 2; + rects[1].height = roundness; + // bottom + rects[2].x = area.left() + roundness; + rects[2].y = area.top() + area.height() - roundness; + rects[2].width = area.width() - roundness * 2; + rects[2].height = roundness; + xcb_render_color_t color = {0, 0, 0, uint16_t(opacity * 0xffff)}; + xcb_render_fill_rectangles(connection(), XCB_RENDER_PICT_OP_OVER, pict, color, 3, rects); + + if (!s_effectFrameCircle) { + // create the circle + const int diameter = roundness * 2; + xcb_pixmap_t pix = xcb_generate_id(connection()); + xcb_create_pixmap(connection(), 32, pix, rootWindow(), diameter, diameter); + s_effectFrameCircle = new XRenderPicture(pix, 32); + xcb_free_pixmap(connection(), pix); + + // clear it with transparent + xcb_rectangle_t xrect = {0, 0, diameter, diameter}; + xcb_render_color_t tranparent = {0, 0, 0, 0}; + xcb_render_fill_rectangles(connection(), XCB_RENDER_PICT_OP_SRC, *s_effectFrameCircle, tranparent, 1, &xrect); + + static int num_segments = 80; + static qreal theta = 2 * M_PI / qreal(num_segments); + static qreal c = qCos(theta); //precalculate the sine and cosine + static qreal s = qSin(theta); + qreal t; + + qreal x = roundness;//we start at angle = 0 + qreal y = 0; + #define DOUBLE_TO_FIXED(d) ((xcb_render_fixed_t) ((d) * 65536)) + QVector points; + xcb_render_pointfix_t point; + point.x = DOUBLE_TO_FIXED(roundness); + point.y = DOUBLE_TO_FIXED(roundness); + points << point; + for (int ii = 0; ii <= num_segments; ++ii) { + point.x = DOUBLE_TO_FIXED(x + roundness); + point.y = DOUBLE_TO_FIXED(y + roundness); + points << point; + //apply the rotation matrix + t = x; + x = c * x - s * y; + y = s * t + c * y; + } + XRenderPicture fill = xRenderFill(Qt::black); + xcb_render_tri_fan(connection(), XCB_RENDER_PICT_OP_OVER, fill, *s_effectFrameCircle, + 0, 0, 0, points.count(), points.constData()); + #undef DOUBLE_TO_FIXED + } + // TODO: merge alpha mask with SceneXrender::Window::alphaMask + // alpha mask + xcb_pixmap_t pix = xcb_generate_id(connection()); + xcb_create_pixmap(connection(), 8, pix, rootWindow(), 1, 1); + XRenderPicture alphaMask(pix, 8); + xcb_free_pixmap(connection(), pix); + const uint32_t values[] = {true}; + xcb_render_change_picture(connection(), alphaMask, XCB_RENDER_CP_REPEAT, values); + color.alpha = int(opacity * 0xffff); + xcb_rectangle_t xrect = {0, 0, 1, 1}; + xcb_render_fill_rectangles(connection(), XCB_RENDER_PICT_OP_SRC, alphaMask, color, 1, &xrect); + + // TODO: replace by lambda +#define RENDER_CIRCLE(srcX, srcY, destX, destY) \ +xcb_render_composite(connection(), XCB_RENDER_PICT_OP_OVER, *s_effectFrameCircle, alphaMask, \ + pict, srcX, srcY, 0, 0, destX, destY, roundness, roundness) + + RENDER_CIRCLE(0, 0, area.left(), area.top()); + RENDER_CIRCLE(0, roundness, area.left(), area.top() + area.height() - roundness); + RENDER_CIRCLE(roundness, 0, area.left() + area.width() - roundness, area.top()); + RENDER_CIRCLE(roundness, roundness, + area.left() + area.width() - roundness, area.top() + area.height() - roundness); +#undef RENDER_CIRCLE +} + void SceneXrender::EffectFrame::updatePicture() { delete m_picture; diff --git a/scene_xrender.h b/scene_xrender.h index cfcb81416c..9f55ebd834 100644 --- a/scene_xrender.h +++ b/scene_xrender.h @@ -113,15 +113,18 @@ public: virtual void crossFadeIcon(); virtual void crossFadeText(); virtual void render(QRegion region, double opacity, double frameOpacity); + static void cleanup(); private: void updatePicture(); void updateTextPicture(); + void renderUnstyled(xcb_render_picture_t pict, const QRect &rect, qreal opacity); XRenderPicture* m_picture; XRenderPicture* m_textPicture; XRenderPicture* m_iconPicture; XRenderPicture* m_selectionPicture; + static XRenderPicture* s_effectFrameCircle; }; inline