Funny how awesome ideas are often so awfully simple. Test whether compositing

really works by simply trying to do it and test the result - create a small
testing window with known content, do the same with it like with normal
windows, grab the screen contents, compare with the original, doesn't match? -> fail.
It still would be nice to have something similar for performance.


svn path=/trunk/KDE/kdebase/workspace/; revision=854549
master
Luboš Luňák 16 years ago
parent 8e5f95a9d6
commit fd2e9b54cb

@ -152,6 +152,8 @@ XRender TODO
in window's pre-paint - see the transformedShape() comment
- and currently seems to be generally broken
+ implement self-check (SceneOpenGL::selfCheckSetup() etc.) also for XRender, possibly share some code
Effects framework TODO
==============================

@ -84,6 +84,10 @@ Sources and other compositing managers:
#ifdef KWIN_HAVE_OPENGL_COMPOSITING
#include <X11/extensions/Xcomposite.h>
#include <qpainter.h>
namespace KWin
{
@ -113,6 +117,7 @@ XShmSegmentInfo SceneOpenGL::shm;
SceneOpenGL::SceneOpenGL( Workspace* ws )
: Scene( ws )
, init_ok( false )
, selfCheckDone( false )
{
if( !Extensions::glxAvailable())
{
@ -615,6 +620,61 @@ bool SceneOpenGL::initDrawableConfigs()
return true;
}
// Test if compositing actually _really_ works, by creating a texture from a testing
// 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 )
{
QImage img( 5, 1, QImage::Format_RGB32 );
img.setPixel( 0, 0, QColor( Qt::red ).rgb());
img.setPixel( 1, 0, QColor( Qt::green ).rgb());
img.setPixel( 2, 0, QColor( Qt::blue ).rgb());
img.setPixel( 3, 0, QColor( Qt::white ).rgb());
img.setPixel( 4, 0, QColor( Qt::black ).rgb());
XSetWindowAttributes wa;
wa.override_redirect = True;
::Window window = XCreateWindow( display(), rootWindow(), 0, 0, 5, 1, 0, QX11Info::appDepth(),
CopyFromParent, CopyFromParent, CWOverrideRedirect, &wa );
QPixmap pix = QPixmap::fromImage( img );
XSetWindowBackgroundPixmap( display(), window, pix.handle());
XClearWindow( display(), window );
XMapWindow( display(), window );
XSync( display(), False );
Pixmap wpix = XCompositeNameWindowPixmap( display(), window );
XDestroyWindow( display(), window );
glXWaitX();
Texture texture;
texture.load( wpix, QSize( 5, 1 ), QX11Info::appDepth());
texture.bind();
QRect rect( 0, 0, 5, 1 );
texture.render( rect, rect );
Workspace::self()->addRepaint( rect );
texture.unbind();
texture.discard();
XFreePixmap( display(), wpix );
damage |= rect;
}
void SceneOpenGL::selfCheckFinish()
{
glXWaitGL();
selfCheckDone = true;
QPixmap pix = QPixmap::grabWindow( rootWindow(), 0, 0, 5, 1 );
QImage img = pix.toImage();
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()
|| img.pixel( 3, 0 ) != QColor( Qt::white ).rgb()
|| img.pixel( 4, 0 ) != QColor( Qt::black ).rgb())
{
kError( 1212 ) << "Compositing self-check failed, disabling compositing.";
QTimer::singleShot( 0, Workspace::self(), SLOT( finishCompositing()));
}
else
kDebug( 1212 ) << "Compositing self-check passed.";
}
// the entry function for painting
void SceneOpenGL::paint( QRegion damage, ToplevelList toplevels )
{
@ -636,7 +696,13 @@ void SceneOpenGL::paint( QRegion damage, ToplevelList toplevels )
#endif
glPopMatrix();
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" );
@ -658,8 +724,6 @@ void SceneOpenGL::waitSync()
// actually paint to the screen (double-buffer swap or copy from pixmap buffer)
void SceneOpenGL::flushBuffer( int mask, QRegion damage )
{
if( wspace->overlayWindow()) // show the window only after the first pass, since
wspace->showOverlay(); // that pass may take long
if( db )
{
if( mask & PAINT_SCREEN_REGION )

@ -64,6 +64,8 @@ class SceneOpenGL
bool initDrawableConfigs();
void waitSync();
void flushBuffer( int mask, QRegion damage );
void selfCheckSetup( QRegion& damage );
void selfCheckFinish();
GC gcroot;
class FBConfigInfo
{
@ -90,6 +92,7 @@ class SceneOpenGL
static XShmSegmentInfo shm;
#endif
bool init_ok;
bool selfCheckDone;
};
class SceneOpenGL::Texture

@ -488,6 +488,7 @@ class Workspace : public QObject, public KDecorationDefines
void slotReloadConfig();
void setPopupClientOpacity( QAction* action );
void setupCompositing();
void finishCompositing();
void performCompositing();
void lostCMSelection();
void updateElectricBorders();
@ -571,7 +572,6 @@ class Workspace : public QObject, public KDecorationDefines
void updateClientArea( bool force );
void finishCompositing();
bool windowRepaintsPending() const;
int current_desktop;

Loading…
Cancel
Save