diff options
Diffstat (limited to 'src/mesa/drivers')
-rw-r--r-- | src/mesa/drivers/dri/common/vblank.c | 50 |
1 files changed, 27 insertions, 23 deletions
diff --git a/src/mesa/drivers/dri/common/vblank.c b/src/mesa/drivers/dri/common/vblank.c index 25b912e8242..c7c7b8296ec 100644 --- a/src/mesa/drivers/dri/common/vblank.c +++ b/src/mesa/drivers/dri/common/vblank.c @@ -260,7 +260,8 @@ void driDrawableInitVBlank( __DRIdrawablePrivate *priv, GLuint flags, drmVBlank vbl = { .request={ .type = DRM_VBLANK_RELATIVE, .sequence = 0 } }; do_wait( &vbl, vbl_seq, priv->driScreenPriv->fd ); - priv->pdraw->swap_interval = (flags & VBLANK_FLAG_THROTTLE) != 0 ? 1 : 0; + priv->pdraw->swap_interval = (flags & (VBLANK_FLAG_THROTTLE | + VBLANK_FLAG_SYNC)) != 0 ? 1 : 0; } } @@ -287,7 +288,7 @@ driWaitForVBlank( const __DRIdrawablePrivate *priv, GLuint * vbl_seq, unsigned original_seq; unsigned deadline; unsigned interval; - + unsigned diff; *missed_deadline = GL_FALSE; if ( (flags & (VBLANK_FLAG_INTERVAL | @@ -310,43 +311,46 @@ driWaitForVBlank( const __DRIdrawablePrivate *priv, GLuint * vbl_seq, original_seq = *vbl_seq; - vbl.request.sequence = ((flags & VBLANK_FLAG_SYNC) != 0) ? 1 : 0; - vbl.request.type = DRM_VBLANK_RELATIVE; - - if ( do_wait( & vbl, vbl_seq, priv->driScreenPriv->fd ) != 0 ) { - return -1; - } - - - vbl.request.type = DRM_VBLANK_ABSOLUTE; - if ( (flags & VBLANK_FLAG_INTERVAL) != 0 ) { interval = priv->pdraw->swap_interval; /* this must have been initialized when the drawable was first bound * to a direct rendering context. */ assert ( interval != (unsigned)-1 ); } - else if ( (flags & VBLANK_FLAG_THROTTLE) != 0 ) { + else if ( (flags & (VBLANK_FLAG_THROTTLE | VBLANK_FLAG_SYNC)) != 0 ) { interval = 1; } else { interval = 0; } + deadline = original_seq + interval; - /* Wait until the next vertical blank. If the interval is zero, then - * the deadline is one vertical blank after the previous wait. - */ + vbl.request.sequence = ((flags & VBLANK_FLAG_SYNC) != 0) ? 1 : 0; + vbl.request.type = DRM_VBLANK_RELATIVE; + + if ( do_wait( & vbl, vbl_seq, priv->driScreenPriv->fd ) != 0 ) { + return -1; + } - vbl.request.sequence = original_seq + interval; - if ( *vbl_seq < vbl.request.sequence ) { - if ( do_wait( & vbl, vbl_seq, priv->driScreenPriv->fd ) != 0 ) { - return -1; - } + diff = *vbl_seq - deadline; + + /* No need to wait again if we've already reached the target */ + if (diff <= (1 << 23)) { + *missed_deadline = (flags & VBLANK_FLAG_SYNC) ? (diff > 0) : GL_TRUE; + return 0; + } + + /* Wait until the target vertical blank. */ + vbl.request.type = DRM_VBLANK_ABSOLUTE; + vbl.request.sequence = deadline; + + if ( do_wait( & vbl, vbl_seq, priv->driScreenPriv->fd ) != 0 ) { + return -1; } - deadline = original_seq + ((interval == 0) ? 1 : interval); - *missed_deadline = ( *vbl_seq > deadline ); + diff = *vbl_seq - deadline; + *missed_deadline = diff > 0 && diff <= (1 << 23); return 0; } |