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) one for the root window (or for the window used in the XComposite overlay)
and the best one for every depth of drawables 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 - currently the compositing code is run with 20ms timer, i.e. constant 50fps
- the GLX_SGI_video_sync extension should be used - 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 + GL_ARB_texture_rectangle vs GL_ARB_texture_non_power_of_two
- code currently uses GL_ARB_texture_rectangle (GL_TEXTURE_RECTANGLE_ARB), using - code currently uses GL_ARB_texture_rectangle (GL_TEXTURE_RECTANGLE_ARB), using

View file

@ -33,6 +33,9 @@ glXBindTexImageEXT_func glXBindTexImageEXT;
glActiveTexture_func glActiveTexture; glActiveTexture_func glActiveTexture;
// glXCopySubBufferMESA // glXCopySubBufferMESA
glXCopySubBuffer_func glXCopySubBuffer; glXCopySubBuffer_func glXCopySubBuffer;
// video_sync extension functions
glXGetVideoSync_func glXGetVideoSync;
glXWaitVideoSync_func glXWaitVideoSync;
// Functions // Functions
@ -74,6 +77,16 @@ void initGLX()
glXCopySubBuffer = (glXCopySubBuffer_func) getProcAddress( "glXCopySubBufferMESA" ); glXCopySubBuffer = (glXCopySubBuffer_func) getProcAddress( "glXCopySubBufferMESA" );
else else
glXCopySubBuffer = NULL; 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() void initGL()

View file

@ -85,6 +85,11 @@ extern glActiveTexture_func glActiveTexture;
// glXCopySubBufferMESA // glXCopySubBufferMESA
typedef void (*glXCopySubBuffer_func) ( Display* , GLXDrawable, int, int, int, int ); typedef void (*glXCopySubBuffer_func) ( Display* , GLXDrawable, int, int, int, int );
extern glXCopySubBuffer_func glXCopySubBuffer; 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 } // namespace

View file

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

View file

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

View file

@ -450,6 +450,22 @@ void SceneOpenGL::paint( QRegion damage, ToplevelList toplevels )
ungrabXServer(); 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) // actually paint to the screen (double-buffer swap or copy from pixmap buffer)
void SceneOpenGL::flushBuffer( int mask, const QRegion& damage ) 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 ) if( mask & PAINT_SCREEN_REGION )
{ {
waitSync();
if( glXCopySubBuffer ) if( glXCopySubBuffer )
{ {
foreach( QRect r, damage.rects()) foreach( QRect r, damage.rects())
@ -483,7 +500,10 @@ void SceneOpenGL::flushBuffer( int mask, const QRegion& damage )
} }
} }
else else
{
waitSync();
glXSwapBuffers( display(), glxbuffer ); glXSwapBuffers( display(), glxbuffer );
}
glXWaitGL(); glXWaitGL();
XFlush( display()); XFlush( display());
} }
@ -491,6 +511,7 @@ void SceneOpenGL::flushBuffer( int mask, const QRegion& damage )
{ {
glFlush(); glFlush();
glXWaitGL(); glXWaitGL();
waitSync();
if( mask & PAINT_SCREEN_REGION ) if( mask & PAINT_SCREEN_REGION )
foreach( QRect r, damage.rects()) foreach( QRect r, damage.rects())
XCopyArea( display(), buffer, rootWindow(), gcroot, r.x(), r.y(), r.width(), r.height(), r.x(), r.y()); 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 initBuffer();
void initRenderingContext(); void initRenderingContext();
bool findConfig( const int* attrs, GLXFBConfig* config, VisualID visual = None ); bool findConfig( const int* attrs, GLXFBConfig* config, VisualID visual = None );
void waitSync();
void flushBuffer( int mask, const QRegion& damage ); void flushBuffer( int mask, const QRegion& damage );
typedef GLuint Texture; typedef GLuint Texture;
GC gcroot; GC gcroot;