not quite so much needs to be delayed to the init() function
[personal-kdebase.git] / workspace / kwin / lib / kwinxrenderutils.cpp
blob585f2deea29664f47c09882621d56ee9b12beea3
1 /********************************************************************
2 KWin - the KDE window manager
3 This file is part of the KDE project.
5 Copyright (C) 2008 Lubos Lunak <l.lunak@kde.org>
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
19 *********************************************************************/
21 #include "kwinxrenderutils.h"
23 #ifdef KWIN_HAVE_XRENDER_COMPOSITING
25 #include <QVector>
26 #include <QPixmap>
27 #include <QPainter>
28 #include <kdebug.h>
30 namespace KWin
33 // Convert QRegion to XserverRegion. All code uses XserverRegion
34 // only when really necessary as the shared implementation uses
35 // QRegion.
36 XserverRegion toXserverRegion( QRegion region )
38 QVector< QRect > rects = region.rects();
39 XRectangle* xr = new XRectangle[ rects.count() ];
40 for( int i = 0;
41 i < rects.count();
42 ++i )
44 xr[ i ].x = rects[ i ].x();
45 xr[ i ].y = rects[ i ].y();
46 xr[ i ].width = rects[ i ].width();
47 xr[ i ].height = rects[ i ].height();
49 XserverRegion ret = XFixesCreateRegion( display(), xr, rects.count());
50 delete[] xr;
51 return ret;
54 // adapted from Qt, because this really sucks ;)
55 XRenderColor preMultiply(const QColor &c, float opacity)
57 XRenderColor color;
58 const uint A = c.alpha() * opacity,
59 R = c.red(),
60 G = c.green(),
61 B = c.blue();
62 color.alpha = (A | A << 8);
63 color.red = (R | R << 8) * color.alpha / 0x10000;
64 color.green = (G | G << 8) * color.alpha / 0x10000;
65 color.blue = (B | B << 8) * color.alpha / 0x10000;
66 return color;
69 XRenderPicture xRenderFill( const XRenderColor *xc )
71 Pixmap pixmap = XCreatePixmap( display(), rootWindow(), 1, 1, 32 );
72 XRenderPictureAttributes pa; pa.repeat = True;
73 XRenderPicture fill( pixmap, 32 );
74 XFreePixmap( display(), pixmap );
75 XRenderChangePicture (display(), fill, CPRepeat, &pa);
76 XRenderFillRectangle( display(), PictOpSrc, fill, xc, 0, 0, 1, 1 );
77 return fill;
80 XRenderPicture xRenderFill( const QColor &c )
82 XRenderColor xc = preMultiply(c);
83 return xRenderFill( &xc );
87 static XRenderPicture *_circle[4] = {NULL, NULL, NULL, NULL};
89 #define DUMP_CNR(_SECT_, _W_, _H_, _XOFF_, _YOFF_)\
90 dump = QPixmap(_W_, _H_);\
91 dump.fill(Qt::transparent);\
92 p.begin(&dump);\
93 p.drawPixmap( 0, 0, tmp, _XOFF_, _YOFF_, _W_, _H_ );\
94 p.end();\
95 _circle[_SECT_] = new XRenderPicture(dump);
97 #define CS 8
99 static XRenderPicture *circle(int i)
101 if (!_circle[0])
103 QPixmap tmp(2*CS, 2*CS);
104 tmp.fill(Qt::transparent);
105 QPainter p(&tmp);
106 p.setRenderHint(QPainter::Antialiasing);
107 p.setPen(Qt::NoPen); p.setBrush(Qt::black);
108 p.drawEllipse(tmp.rect());
109 p.end();
110 QPixmap dump;
111 DUMP_CNR(0, CS, CS, 0, 0);
112 DUMP_CNR(1, CS, CS, CS, 0);
113 DUMP_CNR(2, CS, CS, CS, CS);
114 DUMP_CNR(3, CS, CS, 0, CS);
116 return _circle[i];
119 void xRenderRoundBox( Picture pict, const QRect &rect, int , const QColor &c )
121 XRenderPicture fill = xRenderFill(c);
122 int op = c.alpha() == 255 ? PictOpSrc : PictOpOver;
123 // TODO: implement second paramenter "roundness"
124 // so rather use ?? XRenderCompositeTriFan (dpy, op, src, dst, maskFormat, xSrc, ySrc,
125 //XPointFixed *points, npoint);
126 // this will require "points on a circle" calculation, however...
128 int s = qMin(CS, qMin(rect.height()/2, rect.width()/2));
129 int x,y,b,r;
130 rect.getCoords(&x,&y,&r,&b);
131 r -= (s - 1);
132 b -= (s - 1);
133 XRenderComposite( display(), PictOpOver, fill, *circle(0), pict, 0, 0, 0, 0, x, y, CS, CS );
134 XRenderComposite( display(), PictOpOver, fill, *circle(1), pict, 0, 0, CS-s, 0, r, y, s, s );
135 XRenderComposite( display(), PictOpOver, fill, *circle(2), pict, 0, 0, CS-s, CS-s, r, b, s, s );
136 XRenderComposite( display(), PictOpOver, fill, *circle(3), pict, 0, 0, 0, CS-s, x, b, s, s );
137 XRenderComposite( display(), op, fill, 0, pict, 0, 0, 0, 0, x+s, y, rect.width()-2*s, s);
138 XRenderComposite( display(), op, fill, 0, pict, 0, 0, 0, 0, x, y+s, rect.width(), rect.height()-2*s);
139 XRenderComposite( display(), op, fill, 0, pict, 0, 0, 0, 0, x+s, b, rect.width()-2*s, s);
142 #undef CS
143 #undef DUMP_CNR
145 // XRenderFind(Standard)Format() is a roundtrip, so cache the results
146 static XRenderPictFormat* renderformats[ 33 ];
148 static Picture createPicture( Pixmap pix, int depth )
150 if( pix == None )
151 return None;
152 if( renderformats[ depth ] == NULL )
154 switch( depth)
156 case 1:
157 renderformats[ 1 ] = XRenderFindStandardFormat( display(), PictStandardA1 );
158 break;
159 case 8:
160 renderformats[ 8 ] = XRenderFindStandardFormat( display(), PictStandardA8 );
161 break;
162 case 24:
163 renderformats[ 24 ] = XRenderFindStandardFormat( display(), PictStandardRGB24 );
164 break;
165 case 32:
166 renderformats[ 32 ] = XRenderFindStandardFormat( display(), PictStandardARGB32 );
167 break;
168 default:
170 XRenderPictFormat req;
171 long mask = PictFormatType | PictFormatDepth;
172 req.type = PictTypeDirect;
173 req.depth = depth;
174 renderformats[ depth ] = XRenderFindFormat( display(), mask, &req, 0 );
175 break;
178 if( renderformats[ depth ] == NULL )
180 kWarning( 1212 ) << "Could not find XRender format for depth" << depth;
181 return None;
184 return XRenderCreatePicture( display(), pix, renderformats[ depth ], 0, NULL );
187 XRenderPicture::XRenderPicture( QPixmap pix )
188 : d( new XRenderPictureData( createPicture( pix.handle(), pix.depth())))
192 XRenderPicture::XRenderPicture( Pixmap pix, int depth )
193 : d( new XRenderPictureData( createPicture( pix, depth )))
197 } // namespace
199 #endif