Sync to vblank, patch by Philip Falkner.

svn path=/branches/work/kwin_composite/; revision=606795
This commit is contained in:
Luboš Luňák 2006-11-21 20:59:59 +00:00
parent 55015eb927
commit 9c4218d4bf
7 changed files with 43 additions and 2 deletions

View file

@ -96,10 +96,9 @@ OpenGL TODO
one for the root window (or for the window used in the XComposite overlay)
and the best one for every depth of drawables
+ sync to vblank
/ sync to vblank
- currently the compositing code is run with 20ms timer, i.e. constant 50fps
- the GLX_SGI_video_sync extension should be used
- compiz uses this, no idea about it though
+ GL_ARB_texture_rectangle vs GL_ARB_texture_non_power_of_two
- code currently uses GL_ARB_texture_rectangle (GL_TEXTURE_RECTANGLE_ARB), using

View file

@ -33,6 +33,9 @@ glXBindTexImageEXT_func glXBindTexImageEXT;
glActiveTexture_func glActiveTexture;
// glXCopySubBufferMESA
glXCopySubBuffer_func glXCopySubBuffer;
// video_sync extension functions
glXGetVideoSync_func glXGetVideoSync;
glXWaitVideoSync_func glXWaitVideoSync;
// Functions
@ -74,6 +77,16 @@ void initGLX()
glXCopySubBuffer = (glXCopySubBuffer_func) getProcAddress( "glXCopySubBufferMESA" );
else
glXCopySubBuffer = NULL;
if( hasGLExtension( "GLX_SGI_video_sync" ))
{
glXGetVideoSync = (glXGetVideoSync_func) getProcAddress( "glXGetVideoSyncSGI" );
glXWaitVideoSync = (glXWaitVideoSync_func) getProcAddress( "glXWaitVideoSyncSGI" );
}
else
{
glXGetVideoSync = NULL;
glXWaitVideoSync = NULL;
}
}
void initGL()

View file

@ -85,6 +85,11 @@ extern glActiveTexture_func glActiveTexture;
// glXCopySubBufferMESA
typedef void (*glXCopySubBuffer_func) ( Display* , GLXDrawable, int, int, int, int );
extern glXCopySubBuffer_func glXCopySubBuffer;
// video_sync extension functions
typedef void (*glXGetVideoSync_func)( unsigned int *count );
typedef void (*glXWaitVideoSync_func)( int divisor, int remainder, unsigned int *count );
extern glXGetVideoSync_func glXGetVideoSync;
extern glXWaitVideoSync_func glXWaitVideoSync;
} // namespace

View file

@ -203,6 +203,7 @@ unsigned long Options::updateSettings()
glMode = GLFallback;
glAlwaysRebind = config->readEntry("GLAlwaysRebind", false );
glDirect = config->readEntry("GLDirect", true );
glVSync = config->readEntry("GLVSync", true );
config->setGroup( "EffectShowFps" );
effectShowFpsAlpha = config->readEntry( "Alpha", 0.5 );

View file

@ -304,6 +304,7 @@ class Options : public KDecorationOptions
GLMode glMode;
bool glAlwaysRebind;
bool glDirect;
bool glVSync;
double effectShowFpsAlpha;
int effectShowFpsX;

View file

@ -450,6 +450,22 @@ void SceneOpenGL::paint( QRegion damage, ToplevelList toplevels )
ungrabXServer();
}
// wait for vblank signal before painting
void SceneOpenGL::waitSync()
{ // NOTE that vsync has no effect with indirect rendering
bool vsync = options->glVSync;
unsigned int sync;
if( !vsync )
return;
if( glXGetVideoSync )
{
glFlush();
glXGetVideoSync( &sync );
glXWaitVideoSync( 2, ( sync + 1 ) % 2, &sync );
}
}
// actually paint to the screen (double-buffer swap or copy from pixmap buffer)
void SceneOpenGL::flushBuffer( int mask, const QRegion& damage )
{
@ -457,6 +473,7 @@ void SceneOpenGL::flushBuffer( int mask, const QRegion& damage )
{
if( mask & PAINT_SCREEN_REGION )
{
waitSync();
if( glXCopySubBuffer )
{
foreach( QRect r, damage.rects())
@ -483,7 +500,10 @@ void SceneOpenGL::flushBuffer( int mask, const QRegion& damage )
}
}
else
{
waitSync();
glXSwapBuffers( display(), glxbuffer );
}
glXWaitGL();
XFlush( display());
}
@ -491,6 +511,7 @@ void SceneOpenGL::flushBuffer( int mask, const QRegion& damage )
{
glFlush();
glXWaitGL();
waitSync();
if( mask & PAINT_SCREEN_REGION )
foreach( QRect r, damage.rects())
XCopyArea( display(), buffer, rootWindow(), gcroot, r.x(), r.y(), r.width(), r.height(), r.x(), r.y());

View file

@ -44,6 +44,7 @@ class SceneOpenGL
void initBuffer();
void initRenderingContext();
bool findConfig( const int* attrs, GLXFBConfig* config, VisualID visual = None );
void waitSync();
void flushBuffer( int mask, const QRegion& damage );
typedef GLuint Texture;
GC gcroot;