00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "kwinxrenderutils.h"
00022
00023 #ifdef KWIN_HAVE_XRENDER_COMPOSITING
00024
00025 #include <QVector>
00026 #include <QPixmap>
00027 #include <QPainter>
00028 #include <kdebug.h>
00029
00030 namespace KWin
00031 {
00032
00033
00034
00035
00036 XserverRegion toXserverRegion( QRegion region )
00037 {
00038 QVector< QRect > rects = region.rects();
00039 XRectangle* xr = new XRectangle[ rects.count() ];
00040 for( int i = 0;
00041 i < rects.count();
00042 ++i )
00043 {
00044 xr[ i ].x = rects[ i ].x();
00045 xr[ i ].y = rects[ i ].y();
00046 xr[ i ].width = rects[ i ].width();
00047 xr[ i ].height = rects[ i ].height();
00048 }
00049 XserverRegion ret = XFixesCreateRegion( display(), xr, rects.count());
00050 delete[] xr;
00051 return ret;
00052 }
00053
00054
00055 XRenderColor preMultiply(const QColor &c, float opacity)
00056 {
00057 XRenderColor color;
00058 const uint A = c.alpha() * opacity,
00059 R = c.red(),
00060 G = c.green(),
00061 B = c.blue();
00062 color.alpha = (A | A << 8);
00063 color.red = (R | R << 8) * color.alpha / 0x10000;
00064 color.green = (G | G << 8) * color.alpha / 0x10000;
00065 color.blue = (B | B << 8) * color.alpha / 0x10000;
00066 return color;
00067 }
00068
00069 XRenderPicture xRenderFill( const XRenderColor *xc )
00070 {
00071 Pixmap pixmap = XCreatePixmap( display(), rootWindow(), 1, 1, 32 );
00072 XRenderPictureAttributes pa; pa.repeat = True;
00073 XRenderPicture fill( pixmap, 32 );
00074 XFreePixmap( display(), pixmap );
00075 XRenderChangePicture (display(), fill, CPRepeat, &pa);
00076 XRenderFillRectangle( display(), PictOpSrc, fill, xc, 0, 0, 1, 1 );
00077 return fill;
00078 }
00079
00080 XRenderPicture xRenderFill( const QColor &c )
00081 {
00082 XRenderColor xc = preMultiply(c);
00083 return xRenderFill( &xc );
00084 }
00085
00086
00087 static XRenderPicture *_circle[4] = {NULL, NULL, NULL, NULL};
00088
00089 #define DUMP_CNR(_SECT_, _W_, _H_, _XOFF_, _YOFF_)\
00090 dump = QPixmap(_W_, _H_);\
00091 dump.fill(Qt::transparent);\
00092 p.begin(&dump);\
00093 p.drawPixmap( 0, 0, tmp, _XOFF_, _YOFF_, _W_, _H_ );\
00094 p.end();\
00095 _circle[_SECT_] = new XRenderPicture(dump);
00096
00097 #define CS 8
00098
00099 static XRenderPicture *circle(int i)
00100 {
00101 if (!_circle[0])
00102 {
00103 QPixmap tmp(2*CS, 2*CS);
00104 tmp.fill(Qt::transparent);
00105 QPainter p(&tmp);
00106 p.setRenderHint(QPainter::Antialiasing);
00107 p.setPen(Qt::NoPen); p.setBrush(Qt::black);
00108 p.drawEllipse(tmp.rect());
00109 p.end();
00110 QPixmap dump;
00111 DUMP_CNR(0, CS, CS, 0, 0);
00112 DUMP_CNR(1, CS, CS, CS, 0);
00113 DUMP_CNR(2, CS, CS, CS, CS);
00114 DUMP_CNR(3, CS, CS, 0, CS);
00115 }
00116 return _circle[i];
00117 }
00118
00119 void xRenderRoundBox( Picture pict, const QRect &rect, int , const QColor &c )
00120 {
00121 XRenderPicture fill = xRenderFill(c);
00122 int op = c.alpha() == 255 ? PictOpSrc : PictOpOver;
00123
00124
00125
00126
00127
00128 int s = qMin(CS, qMin(rect.height()/2, rect.width()/2));
00129 int x,y,b,r;
00130 rect.getCoords(&x,&y,&r,&b);
00131 r -= (s - 1);
00132 b -= (s - 1);
00133 XRenderComposite( display(), PictOpOver, fill, *circle(0), pict, 0, 0, 0, 0, x, y, CS, CS );
00134 XRenderComposite( display(), PictOpOver, fill, *circle(1), pict, 0, 0, CS-s, 0, r, y, s, s );
00135 XRenderComposite( display(), PictOpOver, fill, *circle(2), pict, 0, 0, CS-s, CS-s, r, b, s, s );
00136 XRenderComposite( display(), PictOpOver, fill, *circle(3), pict, 0, 0, 0, CS-s, x, b, s, s );
00137 XRenderComposite( display(), op, fill, 0, pict, 0, 0, 0, 0, x+s, y, rect.width()-2*s, s);
00138 XRenderComposite( display(), op, fill, 0, pict, 0, 0, 0, 0, x, y+s, rect.width(), rect.height()-2*s);
00139 XRenderComposite( display(), op, fill, 0, pict, 0, 0, 0, 0, x+s, b, rect.width()-2*s, s);
00140 }
00141
00142 #undef CS
00143 #undef DUMP_CNR
00144
00145
00146 static XRenderPictFormat* renderformats[ 33 ];
00147
00148 static Picture createPicture( Pixmap pix, int depth )
00149 {
00150 if( pix == None )
00151 return None;
00152 if( renderformats[ depth ] == NULL )
00153 {
00154 switch( depth)
00155 {
00156 case 1:
00157 renderformats[ 1 ] = XRenderFindStandardFormat( display(), PictStandardA1 );
00158 break;
00159 case 8:
00160 renderformats[ 8 ] = XRenderFindStandardFormat( display(), PictStandardA8 );
00161 break;
00162 case 24:
00163 renderformats[ 24 ] = XRenderFindStandardFormat( display(), PictStandardRGB24 );
00164 break;
00165 case 32:
00166 renderformats[ 32 ] = XRenderFindStandardFormat( display(), PictStandardARGB32 );
00167 break;
00168 default:
00169 {
00170 XRenderPictFormat req;
00171 long mask = PictFormatType | PictFormatDepth;
00172 req.type = PictTypeDirect;
00173 req.depth = depth;
00174 renderformats[ depth ] = XRenderFindFormat( display(), mask, &req, 0 );
00175 break;
00176 }
00177 }
00178 if( renderformats[ depth ] == NULL )
00179 {
00180 kWarning( 1212 ) << "Could not find XRender format for depth" << depth;
00181 return None;
00182 }
00183 }
00184 return XRenderCreatePicture( display(), pix, renderformats[ depth ], 0, NULL );
00185 }
00186
00187 XRenderPicture::XRenderPicture( QPixmap pix )
00188 : d( new XRenderPictureData( createPicture( pix.handle(), pix.depth())))
00189 {
00190 }
00191
00192 XRenderPicture::XRenderPicture( Pixmap pix, int depth )
00193 : d( new XRenderPictureData( createPicture( pix, depth )))
00194 {
00195 }
00196
00197 }
00198
00199 #endif