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
This commit is contained in:
Luboš Luňák 2008-09-11 16:37:26 +00:00
parent cfb0a0584d
commit 8eedfa3456
4 changed files with 70 additions and 31 deletions

View file

@ -433,10 +433,7 @@ void Workspace::setupOverlay( Window w )
assert( overlay != None ); assert( overlay != None );
assert( Extensions::shapeInputAvailable()); assert( Extensions::shapeInputAvailable());
XSetWindowBackgroundPixmap( display(), overlay, None ); XSetWindowBackgroundPixmap( display(), overlay, None );
XRectangle rec = { 0, 0, displayWidth(), displayHeight() }; setOverlayShape( QRect( 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());
if( w != None ) if( w != None )
{ {
XSetWindowBackgroundPixmap( display(), w, None ); XSetWindowBackgroundPixmap( display(), w, None );
@ -455,6 +452,34 @@ void Workspace::showOverlay()
overlay_shown = true; 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() void Workspace::destroyOverlay()
{ {
if( overlay == None ) if( overlay == None )

View file

@ -118,7 +118,6 @@ XShmSegmentInfo SceneOpenGL::shm;
SceneOpenGL::SceneOpenGL( Workspace* ws ) SceneOpenGL::SceneOpenGL( Workspace* ws )
: Scene( ws ) : Scene( ws )
, init_ok( false ) , init_ok( false )
, selfCheckDone( false )
{ {
if( !Extensions::glxAvailable()) if( !Extensions::glxAvailable())
{ {
@ -177,17 +176,19 @@ SceneOpenGL::SceneOpenGL( Workspace* ws )
glFrustum( xmin, xmax, ymin, ymax, zNear, zFar ); glFrustum( xmin, xmax, ymin, ymax, zNear, zFar );
glMatrixMode( GL_MODELVIEW ); glMatrixMode( GL_MODELVIEW );
glLoadIdentity(); 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" )) if( checkGLError( "Init" ))
{ {
kError( 1212 ) << "OpenGL compositing setup failed"; kError( 1212 ) << "OpenGL compositing setup failed";
return; // error return; // error
} }
if( !selfCheck())
return;
kDebug( 1212 ) << "DB:" << db << ", TFP:" << tfp_mode << ", SHM:" << shm_mode kDebug( 1212 ) << "DB:" << db << ", TFP:" << tfp_mode << ", SHM:" << shm_mode
<< ", Direct:" << bool( glXIsDirect( display(), ctxbuffer )) << endl; << ", Direct:" << bool( glXIsDirect( display(), ctxbuffer )) << endl;
init_ok = true; 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() SceneOpenGL::~SceneOpenGL()
@ -625,7 +626,7 @@ bool SceneOpenGL::initDrawableConfigs()
// window, drawing it on the screen, reading the contents back and comparing. This // window, drawing it on the screen, reading the contents back and comparing. This
// should test whether compositing really works. // should test whether compositing really works.
// It would be still nice to check somehow if compositing is not awfully slow. // 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 ); QImage img( 5, 1, QImage::Format_RGB32 );
img.setPixel( 0, 0, QColor( Qt::red ).rgb()); 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( 3, 0, QColor( Qt::white ).rgb());
img.setPixel( 4, 0, QColor( Qt::black ).rgb()); img.setPixel( 4, 0, QColor( Qt::black ).rgb());
QPixmap pix = QPixmap::fromImage( img ); 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; XSetWindowAttributes wa;
wa.override_redirect = True; wa.override_redirect = True;
@ -643,7 +653,10 @@ void SceneOpenGL::selfCheckSetup( QRegion& damage )
XSetWindowBackgroundPixmap( display(), window, pix.handle()); XSetWindowBackgroundPixmap( display(), window, pix.handle());
XClearWindow( display(), window ); XClearWindow( display(), window );
XMapWindow( 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 ); Pixmap wpix = XCompositeNameWindowPixmap( display(), window );
glXWaitX(); glXWaitX();
Texture texture; Texture texture;
@ -651,23 +664,23 @@ void SceneOpenGL::selfCheckSetup( QRegion& damage )
texture.bind(); texture.bind();
QRect rect( p.x(), p.y(), 5, 1 ); QRect rect( p.x(), p.y(), 5, 1 );
texture.render( infiniteRegion(), rect ); texture.render( infiniteRegion(), rect );
Workspace::self()->addRepaint( rect );
texture.unbind(); texture.unbind();
glXWaitGL(); glXWaitGL();
XFreePixmap( display(), wpix ); XFreePixmap( display(), wpix );
damage |= rect;
XDestroyWindow( display(), window ); XDestroyWindow( display(), window );
} }
} flushBuffer( PAINT_SCREEN_REGION, reg );
void SceneOpenGL::selfCheckFinish()
{
glXWaitGL(); glXWaitGL();
selfCheckDone = true; bool ok = true;
foreach( const QPoint& p, selfCheckPoints()) foreach( const QPoint& p, points )
{ {
QPixmap pix = QPixmap::grabWindow( rootWindow(), p.x(), p.y(), 5, 1 ); QPixmap pix = QPixmap::grabWindow( rootWindow(), p.x(), p.y(), 5, 1 );
QImage img = pix.toImage(); 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() if( img.pixel( 0, 0 ) != QColor( Qt::red ).rgb()
|| img.pixel( 1, 0 ) != QColor( Qt::green ).rgb() || img.pixel( 1, 0 ) != QColor( Qt::green ).rgb()
|| img.pixel( 2, 0 ) != QColor( Qt::blue ).rgb() || img.pixel( 2, 0 ) != QColor( Qt::blue ).rgb()
@ -675,11 +688,15 @@ void SceneOpenGL::selfCheckFinish()
|| img.pixel( 4, 0 ) != QColor( Qt::black ).rgb()) || img.pixel( 4, 0 ) != QColor( Qt::black ).rgb())
{ {
kError( 1212 ) << "Compositing self-check failed, disabling compositing."; kError( 1212 ) << "Compositing self-check failed, disabling compositing.";
QTimer::singleShot( 0, Workspace::self(), SLOT( finishCompositing())); ok = false;
return; 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 QList< QPoint > SceneOpenGL::selfCheckPoints() const
@ -691,7 +708,8 @@ QList< QPoint > SceneOpenGL::selfCheckPoints() const
++screen ) ++screen )
{ // test top-left and bottom-right of every screen { // test top-left and bottom-right of every screen
ret.append( qApp->desktop()->screenGeometry( screen ).topLeft()); 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; return ret;
} }
@ -719,11 +737,7 @@ void SceneOpenGL::paint( QRegion damage, ToplevelList toplevels )
ungrabXServer(); // ungrab before flushBuffer(), it may wait for vsync ungrabXServer(); // ungrab before flushBuffer(), it may wait for vsync
if( wspace->overlayWindow()) // show the window only after the first pass, since if( wspace->overlayWindow()) // show the window only after the first pass, since
wspace->showOverlay(); // that pass may take long wspace->showOverlay(); // that pass may take long
if( !selfCheckDone )
selfCheckSetup( damage );
flushBuffer( mask, damage ); flushBuffer( mask, damage );
if( !selfCheckDone )
selfCheckFinish();
// do cleanup // do cleanup
stacking_order.clear(); stacking_order.clear();
checkGLError( "PostPaint" ); checkGLError( "PostPaint" );

View file

@ -64,8 +64,7 @@ class SceneOpenGL
bool initDrawableConfigs(); bool initDrawableConfigs();
void waitSync(); void waitSync();
void flushBuffer( int mask, QRegion damage ); void flushBuffer( int mask, QRegion damage );
void selfCheckSetup( QRegion& damage ); bool selfCheck();
void selfCheckFinish();
QList< QPoint > selfCheckPoints() const; QList< QPoint > selfCheckPoints() const;
GC gcroot; GC gcroot;
class FBConfigInfo class FBConfigInfo
@ -93,7 +92,6 @@ class SceneOpenGL
static XShmSegmentInfo shm; static XShmSegmentInfo shm;
#endif #endif
bool init_ok; bool init_ok;
bool selfCheckDone;
}; };
class SceneOpenGL::Texture class SceneOpenGL::Texture

View file

@ -327,6 +327,8 @@ class Workspace : public QObject, public KDecorationDefines
// init overlay and the destination window in it // init overlay and the destination window in it
void setupOverlay( Window window ); void setupOverlay( Window window );
void showOverlay(); void showOverlay();
void hideOverlay(); // hides and resets overlay window
void setOverlayShape( const QRegion& reg );
// destroys XComposite overlay window // destroys XComposite overlay window
void destroyOverlay(); void destroyOverlay();
Window overlayWindow(); Window overlayWindow();
@ -489,7 +491,6 @@ class Workspace : public QObject, public KDecorationDefines
void slotReloadConfig(); void slotReloadConfig();
void setPopupClientOpacity( QAction* action ); void setPopupClientOpacity( QAction* action );
void setupCompositing(); void setupCompositing();
void finishCompositing();
void performCompositing(); void performCompositing();
void lostCMSelection(); void lostCMSelection();
void updateElectricBorders(); void updateElectricBorders();
@ -573,6 +574,7 @@ class Workspace : public QObject, public KDecorationDefines
void updateClientArea( bool force ); void updateClientArea( bool force );
void finishCompositing();
bool windowRepaintsPending() const; bool windowRepaintsPending() const;
void setCompositeTimer(); void setCompositeTimer();