From 8eedfa3456d53725b3b722e2c97c9bfc5c07903e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lubo=C5=A1=20Lu=C5=88=C3=A1k?= Date: Thu, 11 Sep 2008 16:37:26 +0000 Subject: [PATCH] Another attempt at self-check, this time done directly during setup (so that it can fail immediately). svn path=/trunk/KDE/kdebase/workspace/; revision=859960 --- composite.cpp | 33 ++++++++++++++++++++++---- scene_opengl.cpp | 60 +++++++++++++++++++++++++++++------------------- scene_opengl.h | 4 +--- workspace.h | 4 +++- 4 files changed, 70 insertions(+), 31 deletions(-) diff --git a/composite.cpp b/composite.cpp index a931f4ba52..e964950281 100644 --- a/composite.cpp +++ b/composite.cpp @@ -433,10 +433,7 @@ void Workspace::setupOverlay( Window w ) assert( overlay != None ); assert( Extensions::shapeInputAvailable()); XSetWindowBackgroundPixmap( display(), overlay, None ); - XRectangle rec = { 0, 0, displayWidth(), displayHeight() }; - XShapeCombineRectangles( display(), overlay, ShapeBounding, 0, 0, &rec, 1, ShapeSet, Unsorted ); - XShapeCombineRectangles( display(), overlay, ShapeInput, 0, 0, NULL, 0, ShapeSet, Unsorted ); - overlay_shape = QRegion( 0, 0, displayWidth(), displayHeight()); + setOverlayShape( QRect( 0, 0, displayWidth(), displayHeight())); if( w != None ) { XSetWindowBackgroundPixmap( display(), w, None ); @@ -455,6 +452,34 @@ void Workspace::showOverlay() overlay_shown = true; } +void Workspace::hideOverlay() + { + assert( overlay != None ); + XUnmapWindow( display(), overlay ); + overlay_shown = false; + setOverlayShape( QRect( 0, 0, displayWidth(), displayHeight())); + } + +void Workspace::setOverlayShape( const QRegion& reg ) + { + QVector< QRect > rects = reg.rects(); + XRectangle* xrects = new XRectangle[ rects.count() ]; + for( int i = 0; + i < rects.count(); + ++i ) + { + xrects[ i ].x = rects[ i ].x(); + xrects[ i ].y = rects[ i ].y(); + xrects[ i ].width = rects[ i ].width(); + xrects[ i ].height = rects[ i ].height(); + } + XShapeCombineRectangles( display(), overlay, ShapeBounding, 0, 0, + xrects, rects.count(), ShapeSet, Unsorted ); + delete[] xrects; + XShapeCombineRectangles( display(), overlay, ShapeInput, 0, 0, NULL, 0, ShapeSet, Unsorted ); + overlay_shape = reg; + } + void Workspace::destroyOverlay() { if( overlay == None ) diff --git a/scene_opengl.cpp b/scene_opengl.cpp index 721886024c..0c2de9c42d 100644 --- a/scene_opengl.cpp +++ b/scene_opengl.cpp @@ -118,7 +118,6 @@ XShmSegmentInfo SceneOpenGL::shm; SceneOpenGL::SceneOpenGL( Workspace* ws ) : Scene( ws ) , init_ok( false ) - , selfCheckDone( false ) { if( !Extensions::glxAvailable()) { @@ -177,17 +176,19 @@ SceneOpenGL::SceneOpenGL( Workspace* ws ) glFrustum( xmin, xmax, ymin, ymax, zNear, zFar ); glMatrixMode( GL_MODELVIEW ); glLoadIdentity(); + float scaleFactor = 1.1 * tan( fovy * M_PI / 360.0f )/ymax; + glTranslatef( xmin*scaleFactor, ymax*scaleFactor, -1.1 ); + glScalef( (xmax-xmin)*scaleFactor/displayWidth(), -(ymax-ymin)*scaleFactor/displayHeight(), 0.001 ); if( checkGLError( "Init" )) { kError( 1212 ) << "OpenGL compositing setup failed"; return; // error } + if( !selfCheck()) + return; kDebug( 1212 ) << "DB:" << db << ", TFP:" << tfp_mode << ", SHM:" << shm_mode << ", Direct:" << bool( glXIsDirect( display(), ctxbuffer )) << endl; init_ok = true; - float scaleFactor = 1.1 * tan( fovy * M_PI / 360.0f )/ymax; - glTranslatef( xmin*scaleFactor, ymax*scaleFactor, -1.1 ); - glScalef( (xmax-xmin)*scaleFactor/displayWidth(), -(ymax-ymin)*scaleFactor/displayHeight(), 0.001 ); } SceneOpenGL::~SceneOpenGL() @@ -625,7 +626,7 @@ bool SceneOpenGL::initDrawableConfigs() // window, drawing it on the screen, reading the contents back and comparing. This // should test whether compositing really works. // It would be still nice to check somehow if compositing is not awfully slow. -void SceneOpenGL::selfCheckSetup( QRegion& damage ) +bool SceneOpenGL::selfCheck() { QImage img( 5, 1, QImage::Format_RGB32 ); img.setPixel( 0, 0, QColor( Qt::red ).rgb()); @@ -634,7 +635,16 @@ void SceneOpenGL::selfCheckSetup( QRegion& damage ) img.setPixel( 3, 0, QColor( Qt::white ).rgb()); img.setPixel( 4, 0, QColor( Qt::black ).rgb()); QPixmap pix = QPixmap::fromImage( img ); - foreach( const QPoint& p, selfCheckPoints()) + QList< QPoint > points = selfCheckPoints(); + QRegion reg; + foreach( const QPoint& p, points ) + reg |= QRect( p, pix.size()); + if( wspace->overlayWindow()) + { // avoid covering the whole screen too soon + wspace->setOverlayShape( reg ); + wspace->showOverlay(); + } + foreach( const QPoint& p, points ) { XSetWindowAttributes wa; wa.override_redirect = True; @@ -643,7 +653,10 @@ void SceneOpenGL::selfCheckSetup( QRegion& damage ) XSetWindowBackgroundPixmap( display(), window, pix.handle()); XClearWindow( display(), window ); XMapWindow( display(), window ); - XMoveWindow( display(), window, p.x(), p.y()); + // move the window one down to where the result will be rendered too, just in case + // the render would fail completely and eventual check would try to read this window's contents + XMoveWindow( display(), window, p.x() + 1, p.y()); + XCompositeRedirectWindow( display(), window, CompositeRedirectManual ); Pixmap wpix = XCompositeNameWindowPixmap( display(), window ); glXWaitX(); Texture texture; @@ -651,23 +664,23 @@ void SceneOpenGL::selfCheckSetup( QRegion& damage ) texture.bind(); QRect rect( p.x(), p.y(), 5, 1 ); texture.render( infiniteRegion(), rect ); - Workspace::self()->addRepaint( rect ); texture.unbind(); glXWaitGL(); XFreePixmap( display(), wpix ); - damage |= rect; XDestroyWindow( display(), window ); } - } - -void SceneOpenGL::selfCheckFinish() - { + flushBuffer( PAINT_SCREEN_REGION, reg ); glXWaitGL(); - selfCheckDone = true; - foreach( const QPoint& p, selfCheckPoints()) + bool ok = true; + foreach( const QPoint& p, points ) { QPixmap pix = QPixmap::grabWindow( rootWindow(), p.x(), p.y(), 5, 1 ); QImage img = pix.toImage(); +// kdDebug() << "P:" << QColor( img.pixel( 0, 0 )).name(); +// kdDebug() << "P:" << QColor( img.pixel( 1, 0 )).name(); +// kdDebug() << "P:" << QColor( img.pixel( 2, 0 )).name(); +// kdDebug() << "P:" << QColor( img.pixel( 3, 0 )).name(); +// kdDebug() << "P:" << QColor( img.pixel( 4, 0 )).name(); if( img.pixel( 0, 0 ) != QColor( Qt::red ).rgb() || img.pixel( 1, 0 ) != QColor( Qt::green ).rgb() || img.pixel( 2, 0 ) != QColor( Qt::blue ).rgb() @@ -675,11 +688,15 @@ void SceneOpenGL::selfCheckFinish() || img.pixel( 4, 0 ) != QColor( Qt::black ).rgb()) { kError( 1212 ) << "Compositing self-check failed, disabling compositing."; - QTimer::singleShot( 0, Workspace::self(), SLOT( finishCompositing())); - return; + ok = false; + break; } } - kDebug( 1212 ) << "Compositing self-check passed."; + if( wspace->overlayWindow()) + wspace->hideOverlay(); + if( ok ) + kDebug( 1212 ) << "Compositing self-check passed."; + return ok; } QList< QPoint > SceneOpenGL::selfCheckPoints() const @@ -691,7 +708,8 @@ QList< QPoint > SceneOpenGL::selfCheckPoints() const ++screen ) { // test top-left and bottom-right of every screen ret.append( qApp->desktop()->screenGeometry( screen ).topLeft()); - ret.append( qApp->desktop()->screenGeometry( screen ).bottomRight() + QPoint( -5 + 1, -1 + 1 )); + ret.append( qApp->desktop()->screenGeometry( screen ).bottomRight() + QPoint( -5 + 1, -1 + 1 ) + + QPoint( -1, 0 )); // intentionally moved one up, since the source windows will be one down } return ret; } @@ -719,11 +737,7 @@ void SceneOpenGL::paint( QRegion damage, ToplevelList toplevels ) ungrabXServer(); // ungrab before flushBuffer(), it may wait for vsync if( wspace->overlayWindow()) // show the window only after the first pass, since wspace->showOverlay(); // that pass may take long - if( !selfCheckDone ) - selfCheckSetup( damage ); flushBuffer( mask, damage ); - if( !selfCheckDone ) - selfCheckFinish(); // do cleanup stacking_order.clear(); checkGLError( "PostPaint" ); diff --git a/scene_opengl.h b/scene_opengl.h index 9558bc8e78..af6eab01e3 100644 --- a/scene_opengl.h +++ b/scene_opengl.h @@ -64,8 +64,7 @@ class SceneOpenGL bool initDrawableConfigs(); void waitSync(); void flushBuffer( int mask, QRegion damage ); - void selfCheckSetup( QRegion& damage ); - void selfCheckFinish(); + bool selfCheck(); QList< QPoint > selfCheckPoints() const; GC gcroot; class FBConfigInfo @@ -93,7 +92,6 @@ class SceneOpenGL static XShmSegmentInfo shm; #endif bool init_ok; - bool selfCheckDone; }; class SceneOpenGL::Texture diff --git a/workspace.h b/workspace.h index f45079def4..9ee48985ea 100644 --- a/workspace.h +++ b/workspace.h @@ -327,6 +327,8 @@ class Workspace : public QObject, public KDecorationDefines // init overlay and the destination window in it void setupOverlay( Window window ); void showOverlay(); + void hideOverlay(); // hides and resets overlay window + void setOverlayShape( const QRegion& reg ); // destroys XComposite overlay window void destroyOverlay(); Window overlayWindow(); @@ -489,7 +491,6 @@ class Workspace : public QObject, public KDecorationDefines void slotReloadConfig(); void setPopupClientOpacity( QAction* action ); void setupCompositing(); - void finishCompositing(); void performCompositing(); void lostCMSelection(); void updateElectricBorders(); @@ -573,6 +574,7 @@ class Workspace : public QObject, public KDecorationDefines void updateClientArea( bool force ); + void finishCompositing(); bool windowRepaintsPending() const; void setCompositeTimer();