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:
parent
cfb0a0584d
commit
8eedfa3456
4 changed files with 70 additions and 31 deletions
|
@ -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 )
|
||||
|
|
|
@ -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" );
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
Loading…
Reference in a new issue