Some restructuring of the driWaitForVBlank() code.
authorMichel Dänzer <michel@daenzer.net>
Thu, 28 Sep 2006 14:03:02 +0000 (14:03 +0000)
committerMichel Dänzer <michel@daenzer.net>
Thu, 28 Sep 2006 14:03:02 +0000 (14:03 +0000)
Also some minor fixes for detecting when the deadline is met or missed, in
particular wrt wraparounds of the sequence number.

src/mesa/drivers/dri/common/vblank.c

index 25b912e82427b15dd4735a3a12450cb58a66be7b..c7c7b8296ec7ac2e416625f1a585c01f1c046d58 100644 (file)
@@ -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;
 }