[glx] Make the wait_for_vblank function private

Nobody should be using the function to wait for the vblank outside
of the GLX backend.
This commit is contained in:
Emmanuele Bassi 2009-07-13 15:31:38 +01:00
parent 5425a6e311
commit 07453a5861
2 changed files with 63 additions and 67 deletions

View File

@ -476,6 +476,65 @@ clutter_backend_glx_ensure_context (ClutterBackend *backend,
} }
} }
static void
glx_wait_for_vblank (ClutterBackendGLX *backend_glx)
{
/* If we are going to wait for VBLANK manually, we not only need
* to flush out pending drawing to the GPU before we sleep, we
* need to wait for it to finish. Otherwise, we may end up with
* the situation:
*
* - We finish drawing - GPU drawing continues
* - We go to sleep - GPU drawing continues
* VBLANK - We call glXSwapBuffers - GPU drawing continues
* - GPU drawing continues
* - Swap buffers happens
*
* Producing a tear. Calling glFinish() first will cause us to properly
* wait for the next VBLANK before we swap. This obviously does not
* happen when we use GLX_SWAP and let the driver do the right thing
*/
switch (backend_glx->vblank_type)
{
case CLUTTER_VBLANK_GLX_SWAP:
/* Nothing */
break;
case CLUTTER_VBLANK_GLX:
{
unsigned int retraceCount;
glFinish ();
backend_glx->get_video_sync (&retraceCount);
backend_glx->wait_video_sync (2,
(retraceCount + 1) % 2,
&retraceCount);
}
break;
case CLUTTER_VBLANK_DRI:
#ifdef __linux__
{
drm_wait_vblank_t blank;
glFinish ();
blank.request.type = DRM_VBLANK_RELATIVE;
blank.request.sequence = 1;
blank.request.signal = 0;
drm_wait_vblank (backend_glx->dri_fd, &blank);
}
#endif
break;
case CLUTTER_VBLANK_NONE:
default:
break;
}
}
static void static void
clutter_backend_glx_redraw (ClutterBackend *backend, clutter_backend_glx_redraw (ClutterBackend *backend,
ClutterStage *stage) ClutterStage *stage)
@ -504,7 +563,7 @@ clutter_backend_glx_redraw (ClutterBackend *backend,
{ {
/* wait for the next vblank */ /* wait for the next vblank */
CLUTTER_NOTE (BACKEND, "Waiting for vblank"); CLUTTER_NOTE (BACKEND, "Waiting for vblank");
clutter_backend_glx_wait_for_vblank (CLUTTER_BACKEND_GLX (backend)); glx_wait_for_vblank (CLUTTER_BACKEND_GLX (backend));
/* push on the screen */ /* push on the screen */
CLUTTER_NOTE (BACKEND, "glXSwapBuffers (display: %p, window: 0x%lx)", CLUTTER_NOTE (BACKEND, "glXSwapBuffers (display: %p, window: 0x%lx)",
@ -633,62 +692,3 @@ _clutter_backend_impl_get_type (void)
{ {
return clutter_backend_glx_get_type (); return clutter_backend_glx_get_type ();
} }
void
clutter_backend_glx_wait_for_vblank (ClutterBackendGLX *backend_glx)
{
/* If we are going to wait for VBLANK manually, we not only need
* to flush out pending drawing to the GPU before we sleep, we
* need to wait for it to finish. Otherwise, we may end up with
* the situation:
*
* - We finish drawing - GPU drawing continues
* - We go to sleep - GPU drawing continues
* VBLANK - We call glXSwapBuffers - GPU drawing continues
* - GPU drawing continues
* - Swap buffers happens
*
* Producing a tear. Calling glFinish() first will cause us to properly
* wait for the next VBLANK before we swap. This obviously does not
* happen when we use GLX_SWAP and let the driver do the right thing
*/
switch (backend_glx->vblank_type)
{
case CLUTTER_VBLANK_GLX_SWAP:
/* Nothing */
break;
case CLUTTER_VBLANK_GLX:
{
unsigned int retraceCount;
glFinish ();
backend_glx->get_video_sync (&retraceCount);
backend_glx->wait_video_sync (2,
(retraceCount + 1) % 2,
&retraceCount);
}
break;
case CLUTTER_VBLANK_DRI:
#ifdef __linux__
{
drm_wait_vblank_t blank;
glFinish ();
blank.request.type = DRM_VBLANK_RELATIVE;
blank.request.sequence = 1;
blank.request.signal = 0;
drm_wait_vblank (backend_glx->dri_fd, &blank);
}
#endif
break;
case CLUTTER_VBLANK_NONE:
default:
break;
}
}

View File

@ -45,20 +45,18 @@ G_BEGIN_DECLS
typedef struct _ClutterBackendGLX ClutterBackendGLX; typedef struct _ClutterBackendGLX ClutterBackendGLX;
typedef struct _ClutterBackendGLXClass ClutterBackendGLXClass; typedef struct _ClutterBackendGLXClass ClutterBackendGLXClass;
typedef enum ClutterGLXVBlankType typedef enum ClutterGLXVBlankType {
{
CLUTTER_VBLANK_NONE = 0, CLUTTER_VBLANK_NONE = 0,
CLUTTER_VBLANK_GLX_SWAP, CLUTTER_VBLANK_GLX_SWAP,
CLUTTER_VBLANK_GLX, CLUTTER_VBLANK_GLX,
CLUTTER_VBLANK_DRI CLUTTER_VBLANK_DRI
} ClutterGLXVBlankType; } ClutterGLXVBlankType;
typedef int (*GetVideoSyncProc) (unsigned int *count); typedef int (*GetVideoSyncProc) (unsigned int *count);
typedef int (*WaitVideoSyncProc) (int divisor, typedef int (*WaitVideoSyncProc) (int divisor,
int remainder, int remainder,
unsigned int *count); unsigned int *count);
typedef int (*SwapIntervalProc) (int interval); typedef int (*SwapIntervalProc) (int interval);
struct _ClutterBackendGLX struct _ClutterBackendGLX
{ {
@ -84,8 +82,6 @@ struct _ClutterBackendGLXClass
ClutterBackendX11Class parent_class; ClutterBackendX11Class parent_class;
}; };
void clutter_backend_glx_wait_for_vblank (ClutterBackendGLX *backend_glx);
GType clutter_backend_glx_get_type (void) G_GNUC_CONST; GType clutter_backend_glx_get_type (void) G_GNUC_CONST;
G_END_DECLS G_END_DECLS