Move XRender based rendering of unstyled EffectFrame into scene_xrender
This follows how it is done for OpenGL where the renderRoundBox() got dropped some time ago. New implementation implements the box with round corners using xrender directly instead of using a QPainter on a QPixmap.icc-effect-5.14.5
parent
368de6842a
commit
a1ac6df20e
|
@ -73,64 +73,6 @@ XRenderPicture xRenderBlendPicture(double opacity)
|
||||||
return _blendPicture;
|
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
|
// XRenderFind(Standard)Format() is a roundtrip, so cache the results
|
||||||
static XRenderPictFormat* renderformats[ 33 ];
|
static XRenderPictFormat* renderformats[ 33 ];
|
||||||
|
|
||||||
|
|
|
@ -39,10 +39,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
namespace KWin
|
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
|
* dumps a QColor into a XRenderColor
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -37,6 +37,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#include <kxerrorhandler.h>
|
#include <kxerrorhandler.h>
|
||||||
|
|
||||||
#include <QtGui/QPainter>
|
#include <QtGui/QPainter>
|
||||||
|
#include <QtCore/qmath.h>
|
||||||
|
|
||||||
namespace KWin
|
namespace KWin
|
||||||
{
|
{
|
||||||
|
@ -93,6 +94,7 @@ SceneXrender::~SceneXrender()
|
||||||
m_overlayWindow->destroy();
|
m_overlayWindow->destroy();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
SceneXrender::EffectFrame::cleanup();
|
||||||
XRenderFreePicture(display(), front);
|
XRenderFreePicture(display(), front);
|
||||||
XRenderFreePicture(display(), buffer);
|
XRenderFreePicture(display(), buffer);
|
||||||
buffer = None;
|
buffer = None;
|
||||||
|
@ -727,6 +729,8 @@ void SceneXrender::screenGeometryChanged(const QSize &size)
|
||||||
// SceneXrender::EffectFrame
|
// SceneXrender::EffectFrame
|
||||||
//****************************************
|
//****************************************
|
||||||
|
|
||||||
|
XRenderPicture *SceneXrender::EffectFrame::s_effectFrameCircle = NULL;
|
||||||
|
|
||||||
SceneXrender::EffectFrame::EffectFrame(EffectFrameImpl* frame)
|
SceneXrender::EffectFrame::EffectFrame(EffectFrameImpl* frame)
|
||||||
: Scene::EffectFrame(frame)
|
: Scene::EffectFrame(frame)
|
||||||
{
|
{
|
||||||
|
@ -744,6 +748,12 @@ SceneXrender::EffectFrame::~EffectFrame()
|
||||||
delete m_selectionPicture;
|
delete m_selectionPicture;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SceneXrender::EffectFrame::cleanup()
|
||||||
|
{
|
||||||
|
delete s_effectFrameCircle;
|
||||||
|
s_effectFrameCircle = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
void SceneXrender::EffectFrame::free()
|
void SceneXrender::EffectFrame::free()
|
||||||
{
|
{
|
||||||
delete m_picture;
|
delete m_picture;
|
||||||
|
@ -792,10 +802,9 @@ void SceneXrender::EffectFrame::render(QRegion region, double opacity, double fr
|
||||||
}
|
}
|
||||||
|
|
||||||
// Render the actual frame
|
// Render the actual frame
|
||||||
if (m_effectFrame->style() == EffectFrameUnstyled)
|
if (m_effectFrame->style() == EffectFrameUnstyled) {
|
||||||
xRenderRoundBox(effects->xrenderBufferPicture(), m_effectFrame->geometry().adjusted(-5, -5, 5, 5),
|
renderUnstyled(effects->xrenderBufferPicture(), m_effectFrame->geometry(), opacity * frameOpacity);
|
||||||
5, QColor(0, 0, 0, int(opacity * frameOpacity * 255)));
|
} else if (m_effectFrame->style() == EffectFrameStyled) {
|
||||||
else if (m_effectFrame->style() == EffectFrameStyled) {
|
|
||||||
if (!m_picture) { // Lazy creation
|
if (!m_picture) { // Lazy creation
|
||||||
updatePicture();
|
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<xcb_render_pointfix_t> 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()
|
void SceneXrender::EffectFrame::updatePicture()
|
||||||
{
|
{
|
||||||
delete m_picture;
|
delete m_picture;
|
||||||
|
|
|
@ -113,15 +113,18 @@ public:
|
||||||
virtual void crossFadeIcon();
|
virtual void crossFadeIcon();
|
||||||
virtual void crossFadeText();
|
virtual void crossFadeText();
|
||||||
virtual void render(QRegion region, double opacity, double frameOpacity);
|
virtual void render(QRegion region, double opacity, double frameOpacity);
|
||||||
|
static void cleanup();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void updatePicture();
|
void updatePicture();
|
||||||
void updateTextPicture();
|
void updateTextPicture();
|
||||||
|
void renderUnstyled(xcb_render_picture_t pict, const QRect &rect, qreal opacity);
|
||||||
|
|
||||||
XRenderPicture* m_picture;
|
XRenderPicture* m_picture;
|
||||||
XRenderPicture* m_textPicture;
|
XRenderPicture* m_textPicture;
|
||||||
XRenderPicture* m_iconPicture;
|
XRenderPicture* m_iconPicture;
|
||||||
XRenderPicture* m_selectionPicture;
|
XRenderPicture* m_selectionPicture;
|
||||||
|
static XRenderPicture* s_effectFrameCircle;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline
|
inline
|
||||||
|
|
Loading…
Reference in New Issue