Drop GLcontext typedef and use struct gl_context instead
[mesa.git] / src / mesa / drivers / dri / common / vblank.c
index 059644046329fcd936025e604e314a2425d719f3..cb98dd0b3a38a8396cb64b0d6652e610c55e700d 100644 (file)
  * Authors:
  *    Ian Romanick <idr@us.ibm.com>
  */
-/* $XFree86:$ */
 
-#include "glheader.h"
+#include "main/glheader.h"
 #include "xf86drm.h"
-#include "mtypes.h"
-#include "macros.h"
-#include "dd.h"
+#include "main/mtypes.h"
+#include "main/macros.h"
+#include "main/dd.h"
 #include "vblank.h"
 #include "xmlpool.h"
 
-static unsigned int msc_to_vblank(__DRIdrawablePrivate * dPriv, int64_t msc)
+static unsigned int msc_to_vblank(__DRIdrawable * dPriv, int64_t msc)
 {
    return (unsigned int)(msc - dPriv->msc_base + dPriv->vblank_base);
 }
 
-static int64_t vblank_to_msc(__DRIdrawablePrivate * dPriv, unsigned int vblank)
+static int64_t vblank_to_msc(__DRIdrawable * dPriv, unsigned int vblank)
 {
    return (int64_t)(vblank - dPriv->vblank_base + dPriv->msc_base);
 }
@@ -65,8 +64,8 @@ static int64_t vblank_to_msc(__DRIdrawablePrivate * dPriv, unsigned int vblank)
  * \return       Zero is returned on success.  A negative errno value
  *               is returned on failure.
  */
-int driDrawableGetMSC32( __DRIscreenPrivate * priv,
-                        __DRIdrawablePrivate * dPriv,
+int driDrawableGetMSC32( __DRIscreen * priv,
+                        __DRIdrawable * dPriv,
                         int64_t * count)
 {
    drmVBlank vbl;
@@ -91,32 +90,6 @@ int driDrawableGetMSC32( __DRIscreenPrivate * priv,
    return ret;
 }
 
-/**
- * Get the current MSC refresh counter.
- *
- * Stores the 64-bit count of vertical refreshes since some (arbitrary)
- * point in time in \c count.  Unless the value wraps around, which it
- * may, it will never decrease.
- *
- * \warning This function is called from \c glXGetVideoSyncSGI, which expects
- * a \c count of type \c unsigned (32-bit), and \c glXGetSyncValuesOML, which 
- * expects a \c count of type \c int64_t (signed 64-bit).  The kernel ioctl 
- * currently always returns a \c sequence of type \c unsigned.
- *
- * Since this function doesn't take a drawable, it may end up getting the MSC
- * value from a pipe not associated with the caller's context, resuling in
- * undesired behavior.
- *
- * \param priv   Pointer to the DRI screen private struct.
- * \param count  Storage to hold MSC counter.
- * \return       Zero is returned on success.  A negative errno value
- *               is returned on failure.
- */
-int driGetMSC32( __DRIscreenPrivate * priv, int64_t * count )
-{
-   return driDrawableGetMSC32(priv, NULL, count);
-}
-
 /****************************************************************************/
 /**
  * Wait for a specified refresh count.  This implements most of the
@@ -149,7 +122,7 @@ int driGetMSC32( __DRIscreenPrivate * priv, int64_t * count )
  * \return            Zero on success or \c GLX_BAD_CONTEXT on failure.
  */
 
-int driWaitForMSC32( __DRIdrawablePrivate *priv,
+int driWaitForMSC32( __DRIdrawable *priv,
                     int64_t target_msc, int64_t divisor, int64_t remainder,
                     int64_t * msc )
 {
@@ -157,9 +130,8 @@ int driWaitForMSC32( __DRIdrawablePrivate *priv,
 
 
    if ( divisor != 0 ) {
-      unsigned int target = (unsigned int)target_msc;
-      unsigned int next = target;
-      unsigned int r;
+      int64_t next = target_msc;
+      int64_t r;
       int dont_wait = (target_msc == 0);
 
       do {
@@ -181,9 +153,9 @@ int driWaitForMSC32( __DRIdrawablePrivate *priv,
 
         *msc = vblank_to_msc(priv, vbl.reply.sequence);
 
-         dont_wait = 0;
-         if (target_msc != 0 && *msc == target)
+         if (!dont_wait && *msc == next)
             break;
+         dont_wait = 0;
 
          /* Assuming the wait-done test fails, the next refresh to wait for
           * will be one that satisfies (MSC % divisor) == remainder.  The
@@ -192,11 +164,12 @@ int driWaitForMSC32( __DRIdrawablePrivate *priv,
           * If this refresh has already happened, we add divisor to obtain 
           * the next refresh after the current one that will satisfy it.
           */
-         r = (*msc % (unsigned int)divisor);
-         next = (*msc - r + (unsigned int)remainder);
-         if (next <= *msc) next += (unsigned int)divisor;
+         r = ((uint64_t)*msc % divisor);
+         next = (*msc - r + remainder);
+         if (next <= *msc)
+           next += divisor;
 
-      } while ( r != (unsigned int)remainder );
+      } while (r != remainder);
    }
    else {
       /* If the \c divisor is zero, just wait until the MSC is greater
@@ -268,7 +241,7 @@ GLuint driGetDefaultVBlankFlags( const driOptionCache *optionCache )
  * the first time the \c drmWaitVBlank fails.  If \c drmWaitVBlank is
  * successful, \c vbl_seq will be set the sequence value in the reply.
  *
- * \param vbl      Pointer to drmVBlank packet desribing how to wait.
+ * \param vbl      Pointer to drmVBlank packet describing how to wait.
  * \param vbl_seq  Location to store the current refresh counter.
  * \param fd       File descriptor use to call into the DRM.
  * \return         Zero on success or -1 on failure.
@@ -286,8 +259,8 @@ static int do_wait( drmVBlank * vbl, GLuint * vbl_seq, int fd )
       if ( first_time ) {
         fprintf(stderr, 
                 "%s: drmWaitVBlank returned %d, IRQs don't seem to be"
-                " working correctly.\nTry running with LIBGL_THROTTLE_REFRESH"
-                " and LIBL_SYNC_REFRESH unset.\n", __FUNCTION__, ret);
+                " working correctly.\nTry adjusting the vblank_mode"
+                " configuration parameter.\n", __FUNCTION__, ret);
         first_time = GL_FALSE;
       }
 
@@ -299,15 +272,33 @@ static int do_wait( drmVBlank * vbl, GLuint * vbl_seq, int fd )
 }
 
 
+/****************************************************************************/
+/**
+ * Returns the default swap interval of the given drawable.
+ */
+
+static unsigned
+driGetDefaultVBlankInterval( const  __DRIdrawable *priv )
+{
+   if ( (priv->vblFlags & (VBLANK_FLAG_THROTTLE | VBLANK_FLAG_SYNC)) != 0 ) {
+      return 1;
+   }
+   else {
+      return 0;
+   }
+}
+
+
 /****************************************************************************/
 /**
  * Sets the default swap interval when the drawable is first bound to a
  * direct rendering context.
  */
 
-void driDrawableInitVBlank( __DRIdrawablePrivate *priv )
+void driDrawableInitVBlank( __DRIdrawable *priv )
 {
-   if ( priv->swap_interval == (unsigned)-1 ) {
+   if ( priv->swap_interval == (unsigned)-1 &&
+       !( priv->vblFlags & VBLANK_FLAG_NO_IRQ ) ) {
       /* Get current vertical blank sequence */
       drmVBlank vbl;
  
@@ -318,8 +309,7 @@ void driDrawableInitVBlank( __DRIdrawablePrivate *priv )
       do_wait( &vbl, &priv->vblSeq, priv->driScreenPriv->fd );
       priv->vblank_base = priv->vblSeq;
 
-      priv->swap_interval =
-        (priv->vblFlags & (VBLANK_FLAG_THROTTLE | VBLANK_FLAG_SYNC)) ? 1 : 0;
+      priv->swap_interval = driGetDefaultVBlankInterval( priv );
    }
 }
 
@@ -330,21 +320,17 @@ void driDrawableInitVBlank( __DRIdrawablePrivate *priv )
  */
 
 unsigned
-driGetVBlankInterval( const  __DRIdrawablePrivate *priv, GLuint flags )
+driGetVBlankInterval( const  __DRIdrawable *priv )
 {
-   if ( (flags & VBLANK_FLAG_INTERVAL) != 0 ) {
+   if ( (priv->vblFlags & VBLANK_FLAG_INTERVAL) != 0 ) {
       /* this must have been initialized when the drawable was first bound
        * to a direct rendering context. */
       assert ( priv->swap_interval != (unsigned)-1 );
 
       return priv->swap_interval;
    }
-   else if ( (flags & (VBLANK_FLAG_THROTTLE | VBLANK_FLAG_SYNC)) != 0 ) {
-      return 1;
-   }
-   else {
-      return 0;
-   }
+   else 
+      return driGetDefaultVBlankInterval( priv );
 }
 
 
@@ -354,18 +340,17 @@ driGetVBlankInterval( const  __DRIdrawablePrivate *priv, GLuint flags )
  */
 
 void
-driGetCurrentVBlank( const  __DRIdrawablePrivate *priv, GLuint flags,
-                    GLuint *vbl_seq )
+driGetCurrentVBlank( __DRIdrawable *priv )
 {
    drmVBlank vbl;
 
    vbl.request.type = DRM_VBLANK_RELATIVE;
-   if ( flags & VBLANK_FLAG_SECONDARY ) {
+   if ( priv->vblFlags & VBLANK_FLAG_SECONDARY ) {
       vbl.request.type |= DRM_VBLANK_SECONDARY;
    }
    vbl.request.sequence = 0;
 
-   (void) do_wait( &vbl, vbl_seq, priv->driScreenPriv->fd );
+   (void) do_wait( &vbl, &priv->vblSeq, priv->driScreenPriv->fd );
 }
 
 
@@ -373,19 +358,15 @@ driGetCurrentVBlank( const  __DRIdrawablePrivate *priv, GLuint flags,
 /**
  * Waits for the vertical blank for use with glXSwapBuffers.
  * 
- * \param vbl_seq  Vertical blank sequence number (MSC) after the last buffer
- *                 swap.  Updated after this wait.
- * \param flags    \c VBLANK_FLAG bits that control how long to wait.
  * \param missed_deadline  Set to \c GL_TRUE if the MSC after waiting is later
- *                 than the "target" based on \c flags.  The idea is that if
- *                 \c missed_deadline is set, then the application is not 
- *                 achieving its desired framerate.
+ *                 than the "target" based on \c priv->vblFlags.  The idea is
+ *                 that if \c missed_deadline is set, then the application is
+ *                 not achieving its desired framerate.
  * \return         Zero on success, -1 on error.
  */
 
 int
-driWaitForVBlank( const  __DRIdrawablePrivate *priv, GLuint * vbl_seq,
-                 GLuint flags, GLboolean * missed_deadline )
+driWaitForVBlank( __DRIdrawable *priv, GLboolean * missed_deadline )
 {
    drmVBlank vbl;
    unsigned   original_seq;
@@ -394,10 +375,10 @@ driWaitForVBlank( const  __DRIdrawablePrivate *priv, GLuint * vbl_seq,
    unsigned   diff;
 
    *missed_deadline = GL_FALSE;
-   if ( (flags & (VBLANK_FLAG_INTERVAL |
-                 VBLANK_FLAG_THROTTLE |
-                 VBLANK_FLAG_SYNC)) == 0 ||
-       (flags & VBLANK_FLAG_NO_IRQ) != 0 ) {
+   if ( (priv->vblFlags & (VBLANK_FLAG_INTERVAL |
+                          VBLANK_FLAG_THROTTLE |
+                          VBLANK_FLAG_SYNC)) == 0 ||
+       (priv->vblFlags & VBLANK_FLAG_NO_IRQ) != 0 ) {
       return 0;
    }
 
@@ -408,44 +389,45 @@ driWaitForVBlank( const  __DRIdrawablePrivate *priv, GLuint * vbl_seq,
     *
     * VBLANK_FLAG_INTERVAL and VBLANK_FLAG_THROTTLE mean to wait for at
     * least one vertical blank since the last wait.  Since do_wait modifies
-    * vbl_seq, we have to save the original value of vbl_seq for the
+    * priv->vblSeq, we have to save the original value of priv->vblSeq for the
     * VBLANK_FLAG_INTERVAL / VBLANK_FLAG_THROTTLE calculation later.
     */
 
-   original_seq = *vbl_seq;
-   interval = driGetVBlankInterval(priv, flags);
+   original_seq = priv->vblSeq;
+   interval = driGetVBlankInterval(priv);
    deadline = original_seq + interval;
 
    vbl.request.type = DRM_VBLANK_RELATIVE;
-   if ( flags & VBLANK_FLAG_SECONDARY ) {
+   if ( priv->vblFlags & VBLANK_FLAG_SECONDARY ) {
       vbl.request.type |= DRM_VBLANK_SECONDARY;
    }
-   vbl.request.sequence = ((flags & VBLANK_FLAG_SYNC) != 0) ? 1 : 0;
+   vbl.request.sequence = ((priv->vblFlags & VBLANK_FLAG_SYNC) != 0) ? 1 : 0;
 
-   if ( do_wait( & vbl, vbl_seq, priv->driScreenPriv->fd ) != 0 ) {
+   if ( do_wait( & vbl, &priv->vblSeq, priv->driScreenPriv->fd ) != 0 ) {
       return -1;
    }
 
-   diff = *vbl_seq - deadline;
+   diff = priv->vblSeq - 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;
+      *missed_deadline = (priv->vblFlags & VBLANK_FLAG_SYNC) ? (diff > 0) :
+                        GL_TRUE;
       return 0;
    }
 
    /* Wait until the target vertical blank. */
    vbl.request.type = DRM_VBLANK_ABSOLUTE;
-   if ( flags & VBLANK_FLAG_SECONDARY ) {
+   if ( priv->vblFlags & VBLANK_FLAG_SECONDARY ) {
       vbl.request.type |= DRM_VBLANK_SECONDARY;
    }
    vbl.request.sequence = deadline;
 
-   if ( do_wait( & vbl, vbl_seq, priv->driScreenPriv->fd ) != 0 ) {
+   if ( do_wait( & vbl, &priv->vblSeq, priv->driScreenPriv->fd ) != 0 ) {
       return -1;
    }
 
-   diff = *vbl_seq - deadline;
+   diff = priv->vblSeq - deadline;
    *missed_deadline = diff > 0 && diff <= (1 << 23);
 
    return 0;