• Skip to content
  • Skip to link menu
KDE 4.2 API Reference
  • KDE API Reference
  • API Reference
  • Sitemap
  • Contact Us
 

KWin

scene_xrender.cpp

Go to the documentation of this file.
00001 /********************************************************************
00002  KWin - the KDE window manager
00003  This file is part of the KDE project.
00004 
00005 Copyright (C) 2006 Lubos Lunak <l.lunak@kde.org>
00006 
00007 This program is free software; you can redistribute it and/or modify
00008 it under the terms of the GNU General Public License as published by
00009 the Free Software Foundation; either version 2 of the License, or
00010 (at your option) any later version.
00011 
00012 This program is distributed in the hope that it will be useful,
00013 but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 GNU General Public License for more details.
00016 
00017 You should have received a copy of the GNU General Public License
00018 along with this program.  If not, see <http://www.gnu.org/licenses/>.
00019 *********************************************************************/
00020 
00021 /*
00022  This is the XRender-based compositing code. The primary compositing
00023  backend is the OpenGL-based one, which should be more powerful
00024  and also possibly better documented. This backend is mostly for cases
00025  when the OpenGL backend cannot be used for some reason (insufficient
00026  performance, no usable OpenGL support at all, etc.)
00027  The plan is to keep it around as long as needed/possible, but if it
00028  proves to be too much hassle it will be dropped in the future.
00029  
00030  Docs:
00031  
00032  XRender (the protocol, but the function calls map to it):
00033  http://gitweb.freedesktop.org/?p=xorg/proto/renderproto.git;a=blob_plain;hb=HEAD;f=renderproto.txt
00034  
00035  XFixes (again, the protocol):
00036  http://gitweb.freedesktop.org/?p=xorg/proto/fixesproto.git;a=blob_plain;hb=HEAD;f=fixesproto.txt
00037 
00038 */
00039 
00040 #include "scene_xrender.h"
00041 
00042 #ifdef KWIN_HAVE_XRENDER_COMPOSITING
00043 
00044 #include "toplevel.h"
00045 #include "client.h"
00046 #include "deleted.h"
00047 #include "effects.h"
00048 #include "kwinxrenderutils.h"
00049 
00050 #include <X11/extensions/Xcomposite.h>
00051 
00052 #include <kxerrorhandler.h>
00053 
00054 namespace KWin
00055 {
00056 
00057 //****************************************
00058 // SceneXrender
00059 //****************************************
00060 
00061 // kDebug() support for the XserverRegion type
00062 struct RegionDebug
00063    {   
00064    RegionDebug( XserverRegion r ) : rr( r ) {}   
00065    XserverRegion rr;   
00066    };   
00067 
00068 kdbgstream& operator<<( kdbgstream& stream, RegionDebug r )
00069     {       
00070     if( r.rr == None )
00071         return stream << "EMPTY";
00072     int num;
00073     XRectangle* rects = XFixesFetchRegion( display(), r.rr, &num );
00074     if( rects == NULL || num == 0 )
00075         return stream << "EMPTY";
00076     for( int i = 0;
00077          i < num;
00078          ++i )
00079        stream << "[" << rects[ i ].x << "+" << rects[ i ].y << " " << rects[ i ].width << "x" << rects[ i ].height << "]";
00080     return stream;
00081     }
00082 
00083 Picture SceneXrender::buffer = None;
00084 ScreenPaintData SceneXrender::screen_paint;
00085 
00086 SceneXrender::SceneXrender( Workspace* ws )
00087     : Scene( ws )
00088     , front( None )
00089     , init_ok( false )
00090     {
00091     if( !Extensions::renderAvailable())
00092         {
00093         kError( 1212 ) << "No XRender extension available";
00094         return;
00095         }
00096     if( !Extensions::fixesRegionAvailable())
00097         {
00098         kError( 1212 ) << "No XFixes v3+ extension available";
00099         return;
00100         }
00101     KXErrorHandler xerr;
00102     if( wspace->createOverlay())
00103         {
00104         wspace->setupOverlay( None );
00105         XWindowAttributes attrs;
00106         XGetWindowAttributes( display(), wspace->overlayWindow(), &attrs );
00107         format = XRenderFindVisualFormat( display(), attrs.visual );
00108         if( format == NULL )
00109             {
00110             kError( 1212 ) << "Failed to find XRender format for overlay window";
00111             return;
00112             }
00113         front = XRenderCreatePicture( display(), wspace->overlayWindow(), format, 0, NULL );
00114         }
00115     else
00116         {
00117         // create XRender picture for the root window
00118         format = XRenderFindVisualFormat( display(), DefaultVisual( display(), DefaultScreen( display())));
00119         if( format == NULL )
00120             {
00121             kError( 1212 ) << "Failed to find XRender format for root window";
00122             return; // error
00123             }
00124         XRenderPictureAttributes pa;
00125         pa.subwindow_mode = IncludeInferiors;
00126         front = XRenderCreatePicture( display(), rootWindow(), format, CPSubwindowMode, &pa );
00127         }
00128     createBuffer();
00129     if( xerr.error( true ))
00130         {
00131         kError( 1212 ) << "XRender compositing setup failed";
00132         return;
00133         }
00134     if( !selfCheck())
00135         return;
00136     init_ok = true;
00137     }
00138 
00139 SceneXrender::~SceneXrender()
00140     {
00141     if( !init_ok )
00142         {
00143         // TODO this probably needs to clean up whatever has been created until the failure
00144         wspace->destroyOverlay();
00145         return;
00146         }
00147     XRenderFreePicture( display(), front );
00148     XRenderFreePicture( display(), buffer );
00149     buffer = None;
00150     wspace->destroyOverlay();
00151     foreach( Window* w, windows )
00152         delete w;
00153     }
00154 
00155 bool SceneXrender::initFailed() const
00156     {
00157     return !init_ok;
00158     }
00159 
00160 // Create the compositing buffer. The root window is not double-buffered,
00161 // so it is done manually using this buffer,
00162 void SceneXrender::createBuffer()
00163     {
00164     Pixmap pixmap = XCreatePixmap( display(), rootWindow(), displayWidth(), displayHeight(), DefaultDepth( display(), DefaultScreen( display())));
00165     buffer = XRenderCreatePicture( display(), pixmap, format, 0, 0 );
00166     XFreePixmap( display(), pixmap ); // The picture owns the pixmap now
00167     }
00168 
00169 // Just like SceneOpenGL::selfCheck()
00170 bool SceneXrender::selfCheck()
00171     {
00172     QImage img( 3, 2, QImage::Format_RGB32 );
00173     img.setPixel( 0, 0, QColor( Qt::red ).rgb());
00174     img.setPixel( 1, 0, QColor( Qt::green ).rgb());
00175     img.setPixel( 2, 0, QColor( Qt::blue ).rgb());
00176     img.setPixel( 0, 1, QColor( Qt::white ).rgb());
00177     img.setPixel( 1, 1, QColor( Qt::black ).rgb());
00178     img.setPixel( 2, 1, QColor( Qt::white ).rgb());
00179     QPixmap pix = QPixmap::fromImage( img );
00180     QList< QPoint > points = selfCheckPoints();
00181     QRegion reg;
00182     foreach( const QPoint& p, points )
00183         reg |= QRect( p, pix.size());
00184     if( wspace->overlayWindow())
00185         { // avoid covering the whole screen too soon
00186         wspace->setOverlayShape( reg );
00187         wspace->showOverlay();
00188         }
00189     foreach( const QPoint& p, points )
00190         {
00191         XSetWindowAttributes wa;
00192         wa.override_redirect = True;
00193         ::Window window = XCreateWindow( display(), rootWindow(), 0, 0, 3, 2, 0, QX11Info::appDepth(),
00194             CopyFromParent, CopyFromParent, CWOverrideRedirect, &wa );
00195         XSetWindowBackgroundPixmap( display(), window, pix.handle());
00196         XClearWindow( display(), window );
00197         XMapWindow( display(), window );
00198         // move the window one down to where the result will be rendered too, just in case
00199         // the render would fail completely and eventual check would try to read this window's contents
00200         XMoveWindow( display(), window, p.x() + 1, p.y());
00201         XCompositeRedirectWindow( display(), window, CompositeRedirectManual );
00202         Pixmap wpix = XCompositeNameWindowPixmap( display(), window );
00203         XWindowAttributes attrs;
00204         XGetWindowAttributes( display(), window, &attrs );
00205         XRenderPictFormat* format = XRenderFindVisualFormat( display(), attrs.visual );
00206         Picture pic = XRenderCreatePicture( display(), wpix, format, 0, 0 );
00207         QRect rect( p.x(), p.y(), 3, 2 );
00208         XRenderComposite( display(), PictOpSrc, pic, None, buffer, 0, 0, 0, 0,
00209             rect.x(), rect.y(), rect.width(), rect.height());
00210         XFreePixmap( display(), wpix );
00211         XDestroyWindow( display(), window );
00212         }
00213     flushBuffer( PAINT_SCREEN_REGION, reg );
00214     bool ok = true;
00215     foreach( const QPoint& p, points )
00216         {
00217         QPixmap pix = QPixmap::grabWindow( rootWindow(), p.x(), p.y(), 3, 2 );
00218         QImage img = pix.toImage();
00219 //        kDebug(1212) << "P:" << QColor( img.pixel( 0, 0 )).name();
00220 //        kDebug(1212) << "P:" << QColor( img.pixel( 1, 0 )).name();
00221 //        kDebug(1212) << "P:" << QColor( img.pixel( 2, 0 )).name();
00222 //        kDebug(1212) << "P:" << QColor( img.pixel( 0, 1 )).name();
00223 //        kDebug(1212) << "P:" << QColor( img.pixel( 1, 1 )).name();
00224 //        kDebug(1212) << "P:" << QColor( img.pixel( 2, 1 )).name();
00225         if( img.pixel( 0, 0 ) != QColor( Qt::red ).rgb()
00226             || img.pixel( 1, 0 ) != QColor( Qt::green ).rgb()
00227             || img.pixel( 2, 0 ) != QColor( Qt::blue ).rgb()
00228             || img.pixel( 0, 1 ) != QColor( Qt::white ).rgb()
00229             || img.pixel( 1, 1 ) != QColor( Qt::black ).rgb()
00230             || img.pixel( 2, 1 ) != QColor( Qt::white ).rgb())
00231             {
00232             kError( 1212 ) << "Compositing self-check failed, disabling compositing.";
00233             ok = false;
00234             break;
00235             }
00236         }
00237     if( wspace->overlayWindow())
00238         wspace->hideOverlay();
00239     if( ok )
00240         kDebug( 1212 ) << "Compositing self-check passed.";
00241     if( !ok && options->disableCompositingChecks )
00242         {
00243         kWarning( 1212 ) << "Compositing checks disabled, proceeding regardless of self-check failure.";
00244         return true;
00245         }
00246     return ok;
00247     }
00248 
00249 
00250 // the entry point for painting
00251 void SceneXrender::paint( QRegion damage, ToplevelList toplevels )
00252     {
00253     foreach( Toplevel* c, toplevels )
00254         {
00255         assert( windows.contains( c ));
00256         stacking_order.append( windows[ c ] );
00257         }
00258     int mask = 0;
00259     paintScreen( &mask, &damage );
00260     if( wspace->overlayWindow()) // show the window only after the first pass, since
00261         wspace->showOverlay();   // that pass may take long
00262     flushBuffer( mask, damage );
00263     // do cleanup
00264     stacking_order.clear();
00265     }
00266 
00267 void SceneXrender::flushBuffer( int mask, QRegion damage )
00268     {
00269     if( mask & PAINT_SCREEN_REGION )
00270         {
00271         // Use the damage region as the clip region for the root window
00272         XserverRegion front_region = toXserverRegion( damage );
00273         XFixesSetPictureClipRegion( display(), front, 0, 0, front_region );
00274         XFixesDestroyRegion( display(), front_region );
00275         // copy composed buffer to the root window
00276         XFixesSetPictureClipRegion( display(), buffer, 0, 0, None );
00277         XRenderComposite( display(), PictOpSrc, buffer, None, front, 0, 0, 0, 0, 0, 0, displayWidth(), displayHeight());
00278         XFixesSetPictureClipRegion( display(), front, 0, 0, None );
00279         XFlush( display());
00280         }
00281     else
00282         {
00283         // copy composed buffer to the root window
00284         XRenderComposite( display(), PictOpSrc, buffer, None, front, 0, 0, 0, 0, 0, 0, displayWidth(), displayHeight());
00285         XFlush( display());
00286         }
00287     }
00288 
00289 void SceneXrender::paintGenericScreen( int mask, ScreenPaintData data )
00290     {
00291     screen_paint = data; // save, transformations will be done when painting windows
00292     if( true ) // as long as paintTransformedScreen() doesn't work properly
00293         Scene::paintGenericScreen( mask, data );
00294     else
00295         paintTransformedScreen( mask );
00296     }
00297 
00298 /*
00299  TODO currently broken
00300  Try to do optimized painting even with transformations. Since only scaling
00301  and translation are supported by the painting code, clipping can be done
00302  manually to avoid having to paint everything in every pass. Whole screen
00303  still need to be painted but e.g. obscured windows don't. So this below
00304  is basically paintSimpleScreen() with extra code to compute clipping correctly.
00305  
00306  This code assumes that the only transformations possible with XRender are those
00307  provided by Window/ScreenPaintData, In the (very unlikely?) case more is needed
00308  then paintGenericScreen() needs to be used.
00309 */
00310 void SceneXrender::paintTransformedScreen( int orig_mask )
00311     {
00312     QRegion region( 0, 0, displayWidth(), displayHeight());
00313     QList< Phase2Data > phase2;
00314     QRegion allclips;
00315     // Draw each opaque window top to bottom, subtracting the bounding rect of
00316     // each window from the clip region after it's been drawn.
00317     for( int i = stacking_order.count() - 1; // top to bottom
00318          i >= 0;
00319          --i )
00320         {
00321         Window* w = static_cast< Window* >( stacking_order[ i ] );
00322         WindowPrePaintData data;
00323         data.mask = orig_mask | ( w->isOpaque() ? PAINT_WINDOW_OPAQUE : PAINT_WINDOW_TRANSLUCENT );
00324         w->resetPaintingEnabled();
00325         data.paint = region;
00326         // TODO this is wrong, transformedShape() should be used here, but is not known yet
00327         data.clip = w->isOpaque() ? region : QRegion();
00328         data.quads = w->buildQuads();
00329         // preparation step
00330         effects->prePaintWindow( effectWindow( w ), data, time_diff );
00331 #ifndef NDEBUG
00332         foreach( const WindowQuad &q, data.quads )
00333             if( q.isTransformed())
00334                 kFatal( 1212 ) << "Pre-paint calls are not allowed to transform quads!" ;
00335 #endif
00336         if( !w->isPaintingEnabled())
00337             continue;
00338         data.paint -= allclips; // make sure to avoid already clipped areas
00339         if( data.paint.isEmpty()) // completely clipped
00340             continue;
00341         if( data.paint != region ) // prepaint added area to draw
00342             {
00343             region |= data.paint; // make sure other windows in that area get painted too
00344             painted_region |= data.paint; // make sure it makes it to the screen
00345             }
00346         // If the window is transparent, the transparent part will be done
00347         // in the 2nd pass.
00348         if( data.mask & PAINT_WINDOW_TRANSLUCENT )
00349             phase2.prepend( Phase2Data( w, data.paint, data.clip, data.mask, data.quads ));
00350         if( data.mask & PAINT_WINDOW_OPAQUE )
00351             {
00352             w->setTransformedShape( QRegion());
00353             paintWindow( w, data.mask, data.paint, data.quads );
00354             // The window can clip by its opaque parts the windows below.
00355             region -= w->transformedShape();
00356             }
00357         // translucency or window transformed require window pixmap
00358         w->suspendUnredirect( data.mask & ( PAINT_WINDOW_TRANSLUCENT | PAINT_WINDOW_TRANSFORMED )); 
00359         }
00360     if( !( orig_mask & PAINT_SCREEN_BACKGROUND_FIRST ))
00361         paintBackground( region ); // Fill any areas of the root window not covered by windows
00362     // Now walk the list bottom to top, drawing translucent windows.
00363     // That we draw bottom to top is important now since we're drawing translucent objects
00364     // and also are clipping only by opaque windows.
00365     QRegion add_paint;
00366     foreach( const Phase2Data &d, phase2 )
00367         {
00368         Scene::Window* w = d.window;
00369         paintWindow( w, d.mask, d.region | add_paint, d.quads );
00370         // It is necessary to also add paint regions of windows below, because their
00371         // pre-paint's might have extended the paint area, so those areas need to be painted too.
00372         add_paint |= d.region;
00373         }
00374     }
00375 
00376 // fill the screen background
00377 void SceneXrender::paintBackground( QRegion region )
00378     {
00379     PaintClipper pc( region );
00380     for( PaintClipper::Iterator iterator;
00381          !iterator.isDone();
00382          iterator.next())
00383         {
00384         XRenderColor col = { 0, 0, 0, 0xffff }; // black
00385         XRenderFillRectangle( display(), PictOpSrc, buffer, &col, 0, 0, displayWidth(), displayHeight());
00386         }
00387     }
00388 
00389 void SceneXrender::windowGeometryShapeChanged( Toplevel* c )
00390     {
00391     if( !windows.contains( c )) // this is ok, shape is not valid by default
00392         return;
00393     Window* w = windows[ c ];
00394     w->discardPicture();
00395     w->discardShape();
00396     w->discardAlpha();
00397     }
00398     
00399 void SceneXrender::windowOpacityChanged( Toplevel* c )
00400     {
00401     if( !windows.contains( c )) // this is ok, alpha is created on demand
00402         return;
00403     Window* w = windows[ c ];
00404     w->discardAlpha();
00405     }
00406 
00407 void SceneXrender::windowClosed( Toplevel* c, Deleted* deleted )
00408     {
00409     assert( windows.contains( c ));
00410     if( deleted != NULL )
00411         { // replace c with deleted
00412         Window* w = windows.take( c );
00413         w->updateToplevel( deleted );
00414         windows[ deleted ] = w;
00415         }
00416     else
00417         {
00418         delete windows.take( c );
00419         c->effectWindow()->setSceneWindow( NULL );
00420         }
00421     }
00422 
00423 void SceneXrender::windowDeleted( Deleted* c )
00424     {
00425     assert( windows.contains( c ));
00426     delete windows.take( c );
00427     c->effectWindow()->setSceneWindow( NULL );
00428     }
00429 
00430 void SceneXrender::windowAdded( Toplevel* c )
00431     {
00432     assert( !windows.contains( c ));
00433     windows[ c ] = new Window( c );
00434     c->effectWindow()->setSceneWindow( windows[ c ]);
00435     }
00436 
00437 //****************************************
00438 // SceneXrender::Window
00439 //****************************************
00440 
00441 SceneXrender::Window::Window( Toplevel* c )
00442     : Scene::Window( c )
00443     , _picture( None )
00444     , format( XRenderFindVisualFormat( display(), c->visual()))
00445     , alpha( None )
00446     {
00447     }
00448 
00449 SceneXrender::Window::~Window()
00450     {
00451     discardPicture();
00452     discardAlpha();
00453     discardShape();
00454     }
00455 
00456 // Create XRender picture for the pixmap with the window contents.
00457 Picture SceneXrender::Window::picture()
00458     {
00459     if( !toplevel->damage().isEmpty() && _picture != None )
00460         {
00461         XRenderFreePicture( display(), _picture );
00462         _picture = None;
00463         }
00464     if( _picture == None && format != NULL )
00465         {
00466         // Get the pixmap with the window contents.
00467         Pixmap pix = toplevel->windowPixmap();
00468         if( pix == None )
00469             return None;
00470         _picture = XRenderCreatePicture( display(), pix, format, 0, 0 );
00471         toplevel->resetDamage( toplevel->rect());
00472         }
00473     return _picture;
00474     }
00475 
00476 
00477 void SceneXrender::Window::discardPicture()
00478     {
00479     if( _picture != None )
00480         XRenderFreePicture( display(), _picture );
00481     _picture = None;
00482     }
00483 
00484 void SceneXrender::Window::discardAlpha()
00485     {
00486     if( alpha != None )
00487         XRenderFreePicture( display(), alpha );
00488     alpha = None;
00489     }
00490 
00491 // Create XRender picture for the alpha mask.
00492 Picture SceneXrender::Window::alphaMask( double opacity )
00493     {
00494     if( isOpaque() && opacity == 1.0 )
00495         return None;
00496     if( alpha != None && alpha_cached_opacity != opacity )
00497         {
00498         if( alpha != None )
00499             XRenderFreePicture( display(), alpha );
00500         alpha = None;
00501         }
00502     if( alpha != None )
00503         return alpha;
00504     if( opacity == 1.0 )
00505         { // no need to create alpha mask
00506         alpha_cached_opacity = 1.0;
00507         return None;
00508         }
00509     // Create a 1x1 8bpp pixmap containing the given opacity in the alpha channel.
00510     Pixmap pixmap = XCreatePixmap( display(), rootWindow(), 1, 1, 8 );
00511     XRenderPictFormat* format = XRenderFindStandardFormat( display(), PictStandardA8 );
00512     XRenderPictureAttributes pa;
00513     pa.repeat = True;
00514     alpha = XRenderCreatePicture( display(), pixmap, format, CPRepeat, &pa );
00515     XFreePixmap( display(), pixmap );
00516     XRenderColor col;
00517     col.alpha = int( opacity * 0xffff );
00518     alpha_cached_opacity = opacity;
00519     XRenderFillRectangle( display(), PictOpSrc, alpha, &col, 0, 0, 1, 1 );
00520     return alpha;
00521     }
00522 
00523 // paint the window
00524 void SceneXrender::Window::performPaint( int mask, QRegion region, WindowPaintData data )
00525     {
00526     setTransformedShape( QRegion()); // maybe nothing will be painted
00527     // check if there is something to paint
00528     bool opaque = isOpaque() && data.opacity == 1.0;
00529     /* HACK: It seems this causes painting glitches, disable temporarily
00530     if(( mask & PAINT_WINDOW_OPAQUE ) ^ ( mask & PAINT_WINDOW_TRANSLUCENT ))
00531         { // We are only painting either opaque OR translucent windows, not both
00532         if( mask & PAINT_WINDOW_OPAQUE && !opaque )
00533             return; // Only painting opaque and window is translucent
00534         if( mask & PAINT_WINDOW_TRANSLUCENT && opaque )
00535             return; // Only painting translucent and window is opaque
00536         }*/
00537     Picture pic = picture(); // get XRender picture
00538     if( pic == None ) // The render format can be null for GL and/or Xv visuals
00539         return;
00540     // set picture filter
00541     if( options->xrenderSmoothScale ) // only when forced, it's slow
00542         {
00543         if( mask & PAINT_WINDOW_TRANSFORMED )
00544             filter = ImageFilterGood;
00545         else if( mask & PAINT_SCREEN_TRANSFORMED )
00546             filter = ImageFilterGood;
00547         else
00548             filter = ImageFilterFast;
00549         }
00550     else
00551         filter = ImageFilterFast;
00552     // do required transformations
00553     int x = toplevel->x();
00554     int y = toplevel->y();
00555     int width = toplevel->width();
00556     int height = toplevel->height();
00557     double xscale = 1;
00558     double yscale = 1;
00559     transformed_shape = shape();
00560     if( mask & PAINT_WINDOW_TRANSFORMED )
00561         {
00562         xscale *= data.xScale;
00563         yscale *= data.yScale;
00564         x += data.xTranslate;
00565         y += data.yTranslate;
00566         }
00567     if( mask & PAINT_SCREEN_TRANSFORMED )
00568         {
00569         xscale *= screen_paint.xScale;
00570         yscale *= screen_paint.yScale;
00571         x = int( x * screen_paint.xScale );
00572         y = int( y * screen_paint.yScale );
00573         x += screen_paint.xTranslate;
00574         y += screen_paint.yTranslate;
00575         }
00576     if( yscale != 1 || xscale != 1 )
00577         {
00578         XTransform xform = {{
00579             { XDoubleToFixed( 1 / xscale ), XDoubleToFixed( 0 ), XDoubleToFixed( 0 ) },
00580             { XDoubleToFixed( 0 ), XDoubleToFixed( 1 / yscale ), XDoubleToFixed( 0 ) },
00581             { XDoubleToFixed( 0 ), XDoubleToFixed( 0 ), XDoubleToFixed( 1 ) }
00582         }};
00583         XRenderSetPictureTransform( display(), pic, &xform );
00584         width = (int)(width * xscale);
00585         height = (int)(height * yscale);
00586         if( filter == ImageFilterGood )
00587             XRenderSetPictureFilter( display(), pic, const_cast< char* >( "good" ), NULL, 0 );
00588         // transform the shape for clipping in paintTransformedScreen()
00589         QVector< QRect > rects = transformed_shape.rects();
00590         for( int i = 0;
00591              i < rects.count();
00592              ++i )
00593             {
00594             QRect& r = rects[ i ];
00595             r = QRect( int( r.x() * xscale ), int( r.y() * yscale ),
00596                 int( r.width() * xscale ), int( r.height() * xscale ));
00597             }
00598         transformed_shape.setRects( rects.constData(), rects.count());
00599         }
00600     transformed_shape.translate( x, y );
00601     PaintClipper pcreg( region ); // clip by the region to paint
00602     PaintClipper pc( transformed_shape ); // clip by window's shape
00603     for( PaintClipper::Iterator iterator;
00604          !iterator.isDone();
00605          iterator.next())
00606         {
00607         if( opaque )
00608             {
00609             XRenderComposite( display(), PictOpSrc, pic, None, buffer, 0, 0, 0, 0,
00610                 x, y, width, height);
00611             // fake brightness change by overlaying black
00612             XRenderColor col = { 0, 0, 0, 0xffff * ( 1 - data.brightness ) };
00613             XRenderFillRectangle( display(), PictOpOver, buffer, &col, x, y, width, height );
00614             }
00615         else
00616             {
00617             Picture alpha = alphaMask( data.opacity );
00618             XRenderComposite( display(), PictOpOver, pic, alpha, buffer, 0, 0, 0, 0,
00619                 x, y, width, height);
00620             // fake brightness change by overlaying black
00621             XRenderColor col = { 0, 0, 0, 0xffff * ( 1 - data.brightness ) * data.opacity };
00622             XRenderFillRectangle( display(), PictOpOver, buffer, &col, x, y, width, height );
00623             transformed_shape = QRegion();
00624             }
00625         }
00626     if( xscale != 1 || yscale != 1 )
00627         {
00628         XTransform xform = {{
00629             { XDoubleToFixed( 1 ), XDoubleToFixed( 0 ), XDoubleToFixed( 0 ) },
00630             { XDoubleToFixed( 0 ), XDoubleToFixed( 1 ), XDoubleToFixed( 0 ) },
00631             { XDoubleToFixed( 0 ), XDoubleToFixed( 0 ), XDoubleToFixed( 1 ) }
00632         }};
00633         XRenderSetPictureTransform( display(), pic, &xform );
00634         if( filter == ImageFilterGood )
00635             XRenderSetPictureFilter( display(), pic, const_cast< char* >( "fast" ), NULL, 0 );
00636         }
00637     }
00638 
00639 } // namespace
00640 #endif

KWin

Skip menu "KWin"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

API Reference

Skip menu "API Reference"
  • KWin
  •   KWin Libraries
  • Libraries
  •   libkworkspace
  •   libsolidcontrol
  •   libtaskmanager
  • Plasma
  •   Animators
  •   Applets
  •   Engines
  • Solid Modules
Generated for API Reference by doxygen 1.5.7
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal