static void wait_for_vblank (ClutterBackendGLX *backend_glx) { if (backend_glx->vblank_type == CLUTTER_VBLANK_NONE) return; if (backend_glx->wait_video_sync) { unsigned int retraceCount; CLUTTER_NOTE (BACKEND, "Waiting for vblank (wait_video_sync)"); backend_glx->get_video_sync (&retraceCount); backend_glx->wait_video_sync (2, (retraceCount + 1) % 2, &retraceCount); } else { #ifdef HAVE_DRM drm_wait_vblank_t blank; CLUTTER_NOTE (BACKEND, "Waiting for vblank (drm)"); blank.request.type = _DRM_VBLANK_RELATIVE; blank.request.sequence = 1; blank.request.signal = 0; drm_wait_vblank (backend_glx->dri_fd, &blank); #else CLUTTER_NOTE (BACKEND, "No vblank mechanism found"); #endif /* HAVE_DRM */ } }
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; } }