On Tuesday, October 23, 2007 10:32 am Jesse Barnes wrote:
> On Tuesday, October 23, 2007 10:03 am Jesse Barnes wrote:
> > On Tuesday, October 23, 2007 7:32 am Michel Dänzer wrote:
> > > > Thinking about this more, I think we can make the counter not
> > > > decrease, but I don't think we can avoid bad behavior.
> > >
> > > Why not, with something like the scheme Ian outlined above?
> >
> > You snipped out the reasons:  we'll get bad behavior of one sort or
> > another no matter what, unless we have genlocked displays.
>
> Ok, you guys banged this into my head on IRC.  So the calculation
> will be:
>       msc += last_pipe_vblank_count - cur_pipeX_vblank_count
> like Ian said (where last_pipeX_vblank_count is updated everytime the
> drawable moves onto pipe X).  This gets a little ugly since I'll need
> to track both a per-drawable MSC count as well as per-pipe
> last_pipeX_vblank_count values.  And unfortunately, since the
> drawable movement is tracked in per-driver SAREA fields, this code
> can't be generic.  Ugg.

Well at least some of the code can be generic, fortunately.  Here's what 
I have.  The extension support seems to have changed a bit since my 
last patch (this one is against Mesa HEAD as of yesterday), and I'm no 
longer sure about the compatibility issues with the patch.

It still has some bugs.  When moving windows between screens, Mesa seems 
to lose track of the right vblank count to sync against sometimes, so 
my test app's calls to glXWaitVideoSyncSGI return immediately.  Moving 
the window back and forth between the screens a few times fixes this 
problem though, maybe there's a race in the update of base_msc and 
which pipe to sync against?

On the plus side, I never see the MSC count decrease, so at least that 
part is working I think.

Jesse
diff --git a/configs/default b/configs/default
index 620445f..3874dc7 100644
--- a/configs/default
+++ b/configs/default
@@ -79,8 +79,8 @@ APP_LIB_DEPS = -L$(TOP)/$(LIB_DIR) -l$(GLUT_LIB) -l$(GLU_LIB) -l$(GL_LIB) -lm
 
 
 # Installation directories (for make install)
-INSTALL_DIR = /usr/local
-DRI_DRIVER_INSTALL_DIR = /usr/X11R6/lib/modules/dri
+INSTALL_DIR = /usr
+DRI_DRIVER_INSTALL_DIR = /usr/lib64/dri
 
 # Where libGL will look for DRI hardware drivers
 DRI_DRIVER_SEARCH_DIR = $(DRI_DRIVER_INSTALL_DIR)
diff --git a/configs/linux b/configs/linux
index 0d455ff..1d1e962 100644
--- a/configs/linux
+++ b/configs/linux
@@ -20,7 +20,7 @@ DEFINES = -D_POSIX_SOURCE -D_POSIX_C_SOURCE=199309L -D_SVID_SOURCE \
 	-D_BSD_SOURCE -D_GNU_SOURCE \
 	-DPTHREADS -DUSE_XSHM -DHAVE_POSIX_MEMALIGN
 
-X11_INCLUDES = -I/usr/X11R6/include
+X11_INCLUDES = -I/usr/include/X11
 
 CFLAGS = -Wall -Wmissing-prototypes $(OPT_FLAGS) $(PIC_FLAGS) $(ARCH_FLAGS) \
 	$(DEFINES) $(ASM_FLAGS) $(X11_INCLUDES) -std=c99 -ffast-math 
@@ -30,4 +30,4 @@ CXXFLAGS = -Wall $(OPT_FLAGS) $(PIC_FLAGS) $(ARCH_FLAGS) $(DEFINES) \
 
 GLUT_CFLAGS = -fexceptions
 
-EXTRA_LIB_PATH = -L/usr/X11R6/lib
+EXTRA_LIB_PATH = -L/usr/lib64
diff --git a/configs/linux-dri-x86-64 b/configs/linux-dri-x86-64
index 821ab3e..ca7e67c 100644
--- a/configs/linux-dri-x86-64
+++ b/configs/linux-dri-x86-64
@@ -20,5 +20,5 @@ EXTRA_LIB_PATH=-L/usr/X11R6/lib64
 # the new interface.  i810 are missing because there is no x86-64
 # system where they could *ever* be used.
 #
-DRI_DIRS = i915tex i915 i965 mach64 mga r128 r200 radeon tdfx unichrome savage r300
+DRI_DIRS = i915 i965 mach64 mga r128 r200 radeon tdfx unichrome savage r300
 
diff --git a/include/GL/internal/dri_interface.h b/include/GL/internal/dri_interface.h
index e7fbf8e..f1d236a 100644
--- a/include/GL/internal/dri_interface.h
+++ b/include/GL/internal/dri_interface.h
@@ -189,6 +189,18 @@ struct __DRImediaStreamCounterExtensionRec {
     int (*waitForMSC)(__DRIdrawable *drawable,
 		      int64_t target_msc, int64_t divisor, int64_t remainder,
 		      int64_t * msc, int64_t * sbc);
+
+    /**
+     * Like the screen version of getMSC, but also takes a drawable so that
+     * the appropriate pipe's counter can be retrieved.
+     *
+     * Get the number of vertical refreshes since some point in time before
+     * this function was first called (i.e., system start up).
+     *
+     * \since Internal API version 20070925.
+     */
+    int (*getDrawableMSC)(__DRIscreen *screen, void *drawablePrivate,
+			  int64_t *msc);
 };
 
 
diff --git a/src/glx/x11/glxcmds.c b/src/glx/x11/glxcmds.c
index 707e398..cbc498a 100644
--- a/src/glx/x11/glxcmds.c
+++ b/src/glx/x11/glxcmds.c
@@ -1941,13 +1941,24 @@ static int __glXGetVideoSyncSGI(unsigned int *count)
    if ( (gc != NULL) && gc->isDirect ) {
       __GLXscreenConfigs * const psc = GetGLXScreenConfigs( gc->currentDpy,
 							    gc->screen );
-      if (psc->msc != NULL && psc->driScreen.private != NULL) {
-	 int       ret;
-	 int64_t   temp;
-
-	 ret = psc->msc->getMSC(&psc->driScreen, &temp);
-	 *count = (unsigned) temp;
-	 return (ret == 0) ? 0 : GLX_BAD_CONTEXT;
+      if ( psc->driScreen.private ) {
+          __DRIdrawable * const pdraw = 
+              GetDRIDrawable(gc->currentDpy, gc->currentDrawable, NULL);
+	  int64_t temp; 
+	  int ret;
+ 
+ 	  /*
+ 	   * Try to use getDrawableMSC first so we get the right
+ 	   * counter...
+ 	   */
+	  if (psc->msc->getDrawableMSC)
+	      ret = (*psc->msc->getDrawableMSC)( &psc->driScreen,
+						 pdraw->private,
+						 & temp);
+	  else
+	      ret = (*psc->msc->getMSC)( &psc->driScreen, & temp);
+	  *count = (unsigned) temp;
+	  return (ret == 0) ? 0 : GLX_BAD_CONTEXT;
       }
    }
 #else
@@ -1970,16 +1981,14 @@ static int __glXWaitVideoSyncSGI(int divisor, int remainder, unsigned int *count
       if (psc->msc != NULL && psc->driScreen.private ) {
 	 __DRIdrawable * const pdraw = 
 	     GetDRIDrawable(gc->currentDpy, gc->currentDrawable, NULL);
-	 if (pdraw != NULL) {
-	    int       ret;
-	    int64_t   msc;
-	    int64_t   sbc;
-
-	    ret = (*psc->msc->waitForMSC)(pdraw, 0,
-					  divisor, remainder, &msc, &sbc);
-	    *count = (unsigned) msc;
-	    return (ret == 0) ? 0 : GLX_BAD_CONTEXT;
-	 }
+	 int       ret;
+	 int64_t   msc;
+	 int64_t   sbc;
+
+	 ret = (*psc->msc->waitForMSC)(pdraw, 0, divisor, remainder, &msc,
+				       &sbc);
+	 *count = (unsigned) msc;
+	 return (ret == 0) ? 0 : GLX_BAD_CONTEXT;
       }
    }
 #else
@@ -2919,8 +2928,10 @@ int __glXGetInternalVersion(void)
      *            any DRI driver built to any previous version.
      * 20060314 - Added support for GLX_MESA_copy_sub_buffer.
      * 20070105 - Added support for damage reporting.
+     * 20070925 - Added support for per-drawable getMSC callbacks, which
+     *            allows the core to support vblank events on multiple pipes.
      */
-    return 20070105;
+    return 20070925;
 }
 
 
diff --git a/src/mesa/drivers/dri/common/dri_util.c b/src/mesa/drivers/dri/common/dri_util.c
index d59ea0d..d023231 100644
--- a/src/mesa/drivers/dri/common/dri_util.c
+++ b/src/mesa/drivers/dri/common/dri_util.c
@@ -356,10 +356,18 @@ static void driSwapBuffers(__DRIdrawable *drawable)
 				   &rect, 1, GL_TRUE);
 }
 
+static int driDrawableGetMSC( __DRIscreen *screen, void *drawablePrivate,
+			      int64_t *msc )
+{
+    __DRIscreenPrivate *sPriv = screen->private;
+
+    return sPriv->DriverAPI.GetDrawableMSC( sPriv, drawablePrivate, msc );
+}
+
 /**
  * Called directly from a number of higher-level GLX functions.
  */
-static int driGetMSC( __DRIscreen *screen, int64_t *msc )
+static int driGetMSC( __DRIscreen *screen, void *drawablePrivate, int64_t *msc )
 {
     __DRIscreenPrivate *sPriv = screen->private;
 
@@ -396,6 +404,7 @@ const __DRImediaStreamCounterExtension driMediaStreamCounterExtension = {
     { __DRI_MEDIA_STREAM_COUNTER, __DRI_MEDIA_STREAM_COUNTER_VERSION },
     driGetMSC,
     driWaitForMSC,
+    driDrawableGetMSC,
 };
 
 static void driCopySubBuffer(__DRIdrawable *drawable,
@@ -471,6 +480,8 @@ static void *driCreateNewDrawable(__DRIscreen *screen,
     pdp->numBackClipRects = 0;
     pdp->pClipRects = NULL;
     pdp->pBackClipRects = NULL;
+    pdp->vblSeq = 0;
+    pdp->vblFlags = 0;
 
     psp = (__DRIscreenPrivate *)screen->private;
     pdp->driScreenPriv = psp;
@@ -485,6 +496,11 @@ static void *driCreateNewDrawable(__DRIscreen *screen,
     pdraw->private = pdp;
     pdraw->destroyDrawable = driDestroyDrawable;
     pdraw->swapBuffers = driSwapBuffers;  /* called by glXSwapBuffers() */
+    if (driCompareGLXAPIVersion(20070925) >= 0) {
+	pdp->msc = 0;
+	pdp->base_msc = 0;
+    }
+
 
     /* This special default value is replaced with the configured
      * default value when the drawable is first bound to a direct
diff --git a/src/mesa/drivers/dri/common/dri_util.h b/src/mesa/drivers/dri/common/dri_util.h
index 91992a9..5c2a9e4 100644
--- a/src/mesa/drivers/dri/common/dri_util.h
+++ b/src/mesa/drivers/dri/common/dri_util.h
@@ -206,6 +206,14 @@ struct __DriverAPIRec {
      */
     void (*setTexOffset)(__DRIcontext *pDRICtx, GLint texname,
 			 unsigned long long offset, GLint depth, GLuint pitch);
+
+    /**
+     * New version of GetMSC so we can pass drawable data to the low level
+     * DRM driver (e.g. pipe info).
+     */
+    int (*GetDrawableMSC) ( __DRIscreenPrivate * priv,
+			    __DRIdrawablePrivate *drawablePrivate,
+			    int64_t *count);
 };
 
 
@@ -318,6 +326,38 @@ struct __DRIdrawablePrivateRec {
     /[EMAIL PROTECTED]/
 
     /**
+     * \name Vertical blank tracking information
+     * Used for waiting on vertical blank events.
+     */
+    /[EMAIL PROTECTED]/
+    unsigned int vblSeq;
+    unsigned int vblFlags;
+    /[EMAIL PROTECTED]/
+
+    /**
+     * \name Monotonic MSC tracking
+     *
+     * Low level driver is responsible for updating base_msc, primary and
+     * secondary_vblank_base values so that higher level code can calculate
+     * a new msc value or msc target for a WaitMSC call.  The new value will
+     * be:
+     *   if (pipe == primary)
+     *     msc += get_vblank_count(primary) - primary_vblank_base;
+     *   else
+     *     msc += get_vblank_count(secondary) - secondary_vblank_base;
+     *
+     * And for waiting on a value, core code will use:
+     *   actual_target = target_msc - base_msc +
+     *     (primary|secondary)_vblank_base;
+     */
+    /[EMAIL PROTECTED]/
+    int64_t msc;
+    int64_t base_msc;
+    int64_t primary_vblank_base;
+    int64_t secondary_vblank_base;
+    /[EMAIL PROTECTED]/
+
+    /**
      * Pointer to context to which this drawable is currently bound.
      */
     __DRIcontextPrivate *driContextPriv;
diff --git a/src/mesa/drivers/dri/common/vblank.c b/src/mesa/drivers/dri/common/vblank.c
index 3b5acfe..3ad7bec 100644
--- a/src/mesa/drivers/dri/common/vblank.c
+++ b/src/mesa/drivers/dri/common/vblank.c
@@ -42,7 +42,7 @@
  *
  * 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.
+ * may, it will never decrease for a given drawable.
  *
  * \warning This function is called from \c glXGetVideoSyncSGI, which expects
  * a \c count of type \c unsigned (32-bit), and \c glXGetSyncValuesOML, which 
@@ -50,11 +50,14 @@
  * currently always returns a \c sequence of type \c unsigned.
  *
  * \param priv   Pointer to the DRI screen private struct.
+ * \param dPriv  Pointer to the DRI drawable 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 )
+int driDrawableGetMSC32( __DRIscreenPrivate * priv,
+			 __DRIdrawablePrivate * dPriv,
+			 int64_t * count)
 {
    drmVBlank vbl;
    int ret;
@@ -63,13 +66,52 @@ int driGetMSC32( __DRIscreenPrivate * priv, int64_t * count )
 
    vbl.request.type = DRM_VBLANK_RELATIVE;
    vbl.request.sequence = 0;
+   if ( dPriv && dPriv->vblFlags & VBLANK_FLAG_SECONDARY )
+      vbl.request.type |= DRM_VBLANK_SECONDARY;
 
    ret = drmWaitVBlank( priv->fd, &vbl );
-   *count = (int64_t)vbl.reply.sequence;
+
+   if ( dPriv && !(dPriv->vblFlags & VBLANK_FLAG_SECONDARY) ) {
+      /* Primary pipe */
+      dPriv->msc += vbl.reply.sequence - dPriv->primary_vblank_base;
+   } else if (dPriv && (dPriv->vblFlags & VBLANK_FLAG_SECONDARY) ) {
+      /* Secondary pipe */
+      dPriv->msc += vbl.reply.sequence - dPriv->secondary_vblank_base;
+   } else {
+      /* Old driver (no knowledge of per-drawable MSC callback) */
+      dPriv->msc += vbl.reply.sequence;
+   }
+
+   *count = dPriv->msc;
 
    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);
+}
 
 /****************************************************************************/
 /**
@@ -109,13 +151,23 @@ int driWaitForMSC32( __DRIdrawablePrivate *priv,
 {
    drmVBlank vbl;
 
+   /* Convert to actual DRM counter value */
+   if (target_msc) {
+      target_msc -= priv->base_msc;
+      if (!(priv->vblFlags & VBLANK_FLAG_SECONDARY))
+	 target_msc += priv->primary_vblank_base;
+      else
+	 target_msc += priv->secondary_vblank_base;
+   }
 
    if ( divisor != 0 ) {
       unsigned int target = (unsigned int)target_msc;
-      unsigned int next = target;
+      unsigned int next;
       unsigned int r;
       int dont_wait = (target_msc == 0);
 
+      next = target;
+
       do {
          /* dont_wait means we're using the glXWaitVideoSyncSGI() behavior.
           * The first time around, just get the current count and proceed 
@@ -124,6 +176,8 @@ int driWaitForMSC32( __DRIdrawablePrivate *priv,
          vbl.request.type = dont_wait ? DRM_VBLANK_RELATIVE :
                                         DRM_VBLANK_ABSOLUTE;
          vbl.request.sequence = next;
+	 if ( priv->vblFlags & VBLANK_FLAG_SECONDARY )
+	    vbl.request.type |= DRM_VBLANK_SECONDARY;
 
 	 if ( drmWaitVBlank( priv->driScreenPriv->fd, &vbl ) != 0 ) {
 	    /* FIXME: This doesn't seem like the right thing to return here.
@@ -156,6 +210,9 @@ int driWaitForMSC32( __DRIdrawablePrivate *priv,
       vbl.request.type = DRM_VBLANK_ABSOLUTE;
       vbl.request.sequence = target_msc;
 
+      if ( priv->vblFlags & VBLANK_FLAG_SECONDARY )
+	 vbl.request.type |= DRM_VBLANK_SECONDARY;
+
       if ( drmWaitVBlank( priv->driScreenPriv->fd, &vbl ) != 0 ) {
 	 /* FIXME: This doesn't seem like the right thing to return here.
 	  */
@@ -163,12 +220,22 @@ int driWaitForMSC32( __DRIdrawablePrivate *priv,
       }
    }
 
-   *msc  = (target_msc & 0xffffffff00000000LL);
-   *msc |= vbl.reply.sequence;
-   if ( *msc < target_msc ) {
-      *msc += 0x0000000100000000LL;
+   if ( !(priv->vblFlags & VBLANK_FLAG_SECONDARY) ) {
+      /* Primary pipe */
+      priv->msc = priv->base_msc + vbl.reply.sequence -
+	 priv->primary_vblank_base;
+   } else {
+      /* Secondary pipe */
+      priv->msc = priv->base_msc + vbl.reply.sequence -
+	 priv->secondary_vblank_base;
    }
 
+   if ( priv->msc < target_msc ) {
+      priv->msc += 0x0000000100000000LL;
+   }
+
+   *msc = priv->msc;
+
    return 0;
 }
 
@@ -252,16 +319,20 @@ static int do_wait( drmVBlank * vbl, GLuint * vbl_seq, int fd )
  * direct rendering context.
  */
 
-void driDrawableInitVBlank( __DRIdrawablePrivate *priv, GLuint flags,
-			    GLuint *vbl_seq )
+void driDrawableInitVBlank( __DRIdrawablePrivate *priv )
 {
    if ( priv->swap_interval == (unsigned)-1 ) {
       /* Get current vertical blank sequence */
-      drmVBlank vbl = { .request={ .type = DRM_VBLANK_RELATIVE, .sequence = 0 } };
-      do_wait( &vbl, vbl_seq, priv->driScreenPriv->fd );
-
-      priv->swap_interval = (flags & (VBLANK_FLAG_THROTTLE |
-				      VBLANK_FLAG_SYNC)) != 0 ? 1 : 0;
+      drmVBlank vbl;
+ 
+      vbl.request.type = DRM_VBLANK_RELATIVE;
+      if ( priv->vblFlags & VBLANK_FLAG_SECONDARY )
+ 	 vbl.request.type |= DRM_VBLANK_SECONDARY;
+      vbl.request.sequence = 0;
+      do_wait( &vbl, &priv->vblSeq, priv->driScreenPriv->fd );
+
+      priv->swap_interval =
+ 	 (priv->vblFlags & (VBLANK_FLAG_THROTTLE | VBLANK_FLAG_SYNC)) ? 1 : 0;
    }
 }
 
diff --git a/src/mesa/drivers/dri/common/vblank.h b/src/mesa/drivers/dri/common/vblank.h
index ec83adc..e8550b2 100644
--- a/src/mesa/drivers/dri/common/vblank.h
+++ b/src/mesa/drivers/dri/common/vblank.h
@@ -46,11 +46,13 @@
 					  */
 
 extern int driGetMSC32( __DRIscreenPrivate * priv, int64_t * count );
+extern int driDrawableGetMSC32( __DRIscreenPrivate * priv,
+				__DRIdrawablePrivate * drawablePrivate,
+				int64_t * count);
 extern int driWaitForMSC32( __DRIdrawablePrivate *priv,
     int64_t target_msc, int64_t divisor, int64_t remainder, int64_t * msc );
 extern GLuint driGetDefaultVBlankFlags( const driOptionCache *optionCache );
-extern void driDrawableInitVBlank ( __DRIdrawablePrivate *priv, GLuint flags,
-				    GLuint *vbl_seq );
+extern void driDrawableInitVBlank ( __DRIdrawablePrivate *priv );
 extern unsigned driGetVBlankInterval( const  __DRIdrawablePrivate *priv,
 				      GLuint flags );
 extern void driGetCurrentVBlank( const  __DRIdrawablePrivate *priv,
diff --git a/src/mesa/drivers/dri/ffb/ffb_xmesa.c b/src/mesa/drivers/dri/ffb/ffb_xmesa.c
index 3a5551e..173c5fa 100644
--- a/src/mesa/drivers/dri/ffb/ffb_xmesa.c
+++ b/src/mesa/drivers/dri/ffb/ffb_xmesa.c
@@ -615,6 +615,7 @@ static const struct __DriverAPIRec ffbAPI = {
    .UnbindContext   = ffbUnbindContext,
    .GetSwapInfo     = NULL,
    .GetMSC          = NULL,
+   .GetDrawableMSC  = NULL,
    .WaitForMSC      = NULL,
    .WaitForSBC      = NULL,
    .SwapBuffersMSC  = NULL
diff --git a/src/mesa/drivers/dri/i810/i810screen.c b/src/mesa/drivers/dri/i810/i810screen.c
index 3c7ec96..1a0d3c3 100644
--- a/src/mesa/drivers/dri/i810/i810screen.c
+++ b/src/mesa/drivers/dri/i810/i810screen.c
@@ -413,6 +413,7 @@ static const struct __DriverAPIRec i810API = {
    .UnbindContext   = i810UnbindContext,
    .GetSwapInfo     = NULL,
    .GetMSC          = NULL,
+   .GetDrawableMSC  = NULL,
    .WaitForMSC      = NULL,
    .WaitForSBC      = NULL,
    .SwapBuffersMSC  = NULL
diff --git a/src/mesa/drivers/dri/i915/intel_context.c b/src/mesa/drivers/dri/i915/intel_context.c
index d7af432..85d2d9e 100644
--- a/src/mesa/drivers/dri/i915/intel_context.c
+++ b/src/mesa/drivers/dri/i915/intel_context.c
@@ -621,8 +621,7 @@ intelMakeCurrent(__DRIcontextPrivate * driContextPriv,
 		 : VBLANK_FLAG_NO_IRQ;
 
 	       (*dri_interface->getUST) (&intel_fb->swap_ust);
-	       driDrawableInitVBlank(driDrawPriv, intel_fb->vblank_flags,
-				     &intel_fb->vbl_seq);
+	       driDrawableInitVBlank(driDrawPriv);
 	       intel_fb->vbl_waited = intel_fb->vbl_seq;
 
 	       for (i = 0; i < (intel->intelScreen->third.handle ? 3 : 2); i++) {
diff --git a/src/mesa/drivers/dri/i915/intel_screen.c b/src/mesa/drivers/dri/i915/intel_screen.c
index 8be5d91..25f5efa 100644
--- a/src/mesa/drivers/dri/i915/intel_screen.c
+++ b/src/mesa/drivers/dri/i915/intel_screen.c
@@ -790,6 +790,7 @@ static const struct __DriverAPIRec intelAPI = {
    .UnbindContext = intelUnbindContext,
    .GetSwapInfo = intelGetSwapInfo,
    .GetMSC = driGetMSC32,
+   .GetDrawableMSC = driDrawableGetMSC32,
    .WaitForMSC = driWaitForMSC32,
    .WaitForSBC = NULL,
    .SwapBuffersMSC = NULL,
diff --git a/src/mesa/drivers/dri/i965/intel_blit.c b/src/mesa/drivers/dri/i965/intel_blit.c
index d1c1c8a..6343f61 100644
--- a/src/mesa/drivers/dri/i965/intel_blit.c
+++ b/src/mesa/drivers/dri/i965/intel_blit.c
@@ -76,7 +76,8 @@ void intelCopyBuffer( const __DRIdrawablePrivate *dPriv,
    if (!rect)
    {
        UNLOCK_HARDWARE( intel );
-       driWaitForVBlank( dPriv, &intel->vbl_seq, intel->vblank_flags, & missed_target );
+       driWaitForVBlank( dPriv, &dPriv->vblSeq, dPriv->vblFlags,
+			 &missed_target );
        LOCK_HARDWARE( intel );
    }
 
diff --git a/src/mesa/drivers/dri/i965/intel_buffers.c b/src/mesa/drivers/dri/i965/intel_buffers.c
index 6c8b073..dd0fd74 100644
--- a/src/mesa/drivers/dri/i965/intel_buffers.c
+++ b/src/mesa/drivers/dri/i965/intel_buffers.c
@@ -33,6 +33,8 @@
 #include "context.h"
 #include "framebuffer.h"
 #include "macros.h"
+#include "utils.h"
+#include "vblank.h"
 #include "swrast/swrast.h"
 
 GLboolean intel_intersect_cliprects( drm_clip_rect_t *dst,
@@ -190,6 +192,48 @@ void intelWindowMoved( struct intel_context *intel )
       }
    }
 
+   /* Get updated plane info so we sync against the right vblank counter */
+   if (intel->intelScreen->driScrnPriv->ddx_version.minor >= 7) {
+      drmI830Sarea *sarea = intel->sarea;
+      drm_clip_rect_t drw_rect = { .x1 = dPriv->x, .x2 = dPriv->x + dPriv->w,
+				   .y1 = dPriv->y, .y2 = dPriv->y + dPriv->h };
+      drm_clip_rect_t planeA_rect = { .x1 = sarea->planeA_x, .y1 = sarea->planeA_y,
+				     .x2 = sarea->planeA_x + sarea->planeA_w,
+				     .y2 = sarea->planeA_y + sarea->planeA_h };
+      drm_clip_rect_t planeB_rect = { .x1 = sarea->planeB_x, .y1 = sarea->planeB_y,
+				     .x2 = sarea->planeB_x + sarea->planeB_w,
+				     .y2 = sarea->planeB_y + sarea->planeB_h };
+      GLint areaA = driIntersectArea( drw_rect, planeA_rect );
+      GLint areaB = driIntersectArea( drw_rect, planeB_rect );
+      GLuint flags = dPriv->vblFlags;
+
+      /* Update vblank info
+       */
+      if (areaB > areaA || (areaA == areaB && areaB > 0)) {
+	 flags = dPriv->vblFlags | VBLANK_FLAG_SECONDARY;
+      } else {
+	 flags = dPriv->vblFlags & ~VBLANK_FLAG_SECONDARY;
+      }
+
+      /* Check to see if we changed pipes */
+      if (flags != dPriv->vblFlags && dPriv->vblFlags &&
+	  !(dPriv->vblFlags & VBLANK_FLAG_NO_IRQ)) {
+	 /*
+	  * Update monotonic MSC fields for new pipe
+	  */
+	 dPriv->vblFlags = flags;
+	 driGetCurrentVBlank(dPriv, dPriv->vblFlags, &dPriv->vblSeq);
+	 driDrawableGetMSC32(dPriv->driScreenPriv, dPriv, &dPriv->msc);
+	 dPriv->base_msc = dPriv->msc;
+	 if ( !(dPriv->vblFlags & VBLANK_FLAG_SECONDARY) )
+	     dPriv->primary_vblank_base = dPriv->vblSeq;
+	 else
+	     dPriv->secondary_vblank_base = dPriv->vblSeq;
+      }
+   } else {
+      dPriv->vblFlags &= ~VBLANK_FLAG_SECONDARY;
+   }
+
    _mesa_resize_framebuffer(&intel->ctx,
 			    (GLframebuffer*)dPriv->driverPrivate,
 			    dPriv->w, dPriv->h);
diff --git a/src/mesa/drivers/dri/i965/intel_context.c b/src/mesa/drivers/dri/i965/intel_context.c
index 7ec316a..aa066ae 100644
--- a/src/mesa/drivers/dri/i965/intel_context.c
+++ b/src/mesa/drivers/dri/i965/intel_context.c
@@ -330,8 +330,8 @@ GLboolean intelInitContext( struct intel_context *intel,
    GLcontext *shareCtx = (GLcontext *) sharedContextPrivate;
    __DRIscreenPrivate *sPriv = driContextPriv->driScreenPriv;
    intelScreenPrivate *intelScreen = (intelScreenPrivate *)sPriv->private;
-   volatile drmI830Sarea *saPriv = (volatile drmI830Sarea *)
-      (((GLubyte *)sPriv->pSAREA)+intelScreen->sarea_priv_offset);
+   volatile drmI830Sarea *saPriv = (drmI830Sarea *)
+     (((GLubyte *)sPriv->pSAREA)+intelScreen->sarea_priv_offset);
 
    if (!_mesa_initialize_context(&intel->ctx,
 				 mesaVis, shareCtx, 
@@ -349,9 +349,6 @@ GLboolean intelInitContext( struct intel_context *intel,
    driParseConfigFiles (&intel->optionCache, &intelScreen->optionCache,
 		   intel->driScreen->myNum, "i965");
 
-   intel->vblank_flags = (intel->intelScreen->irq_active != 0)
-	   ? driGetDefaultVBlankFlags(&intel->optionCache) : VBLANK_FLAG_NO_IRQ;
-
    ctx->Const.MaxTextureMaxAnisotropy = 2.0;
 
    if (getenv("INTEL_STRICT_CONFORMANCE")) {
@@ -578,17 +575,19 @@ GLboolean intelMakeCurrent(__DRIcontextPrivate *driContextPriv,
    if (driContextPriv) {
       struct intel_context *intel = (struct intel_context *) driContextPriv->driverPrivate;
 
+      driDrawPriv->vblFlags = (intel->intelScreen->irq_active != 0)
+	  ? driGetDefaultVBlankFlags(&intel->optionCache) : VBLANK_FLAG_NO_IRQ;
+
+
       if (intel->driReadDrawable != driReadPriv) {
           intel->driReadDrawable = driReadPriv;
       }
 
       if ( intel->driDrawable != driDrawPriv ) {
-	 /* Shouldn't the readbuffer be stored also? */
-	 driDrawableInitVBlank( driDrawPriv, intel->vblank_flags,
-		      &intel->vbl_seq );
-
 	 intel->driDrawable = driDrawPriv;
 	 intelWindowMoved( intel );
+	 /* Shouldn't the readbuffer be stored also? */
+	 driDrawableInitVBlank( driDrawPriv );
       }
 
       _mesa_make_current(&intel->ctx,
diff --git a/src/mesa/drivers/dri/i965/intel_context.h b/src/mesa/drivers/dri/i965/intel_context.h
index 65898ca..5848d0c 100644
--- a/src/mesa/drivers/dri/i965/intel_context.h
+++ b/src/mesa/drivers/dri/i965/intel_context.h
@@ -231,11 +231,6 @@ struct intel_context
     */
    driOptionCache optionCache;
 
-   /* VBI
-    */
-   GLuint vbl_seq;
-   GLuint vblank_flags;
-
    int64_t swap_ust;
    int64_t swap_missed_ust;
 
diff --git a/src/mesa/drivers/dri/i965/intel_screen.c b/src/mesa/drivers/dri/i965/intel_screen.c
index e35f7da..2527300 100644
--- a/src/mesa/drivers/dri/i965/intel_screen.c
+++ b/src/mesa/drivers/dri/i965/intel_screen.c
@@ -449,6 +449,10 @@ static GLboolean intelCreateBuffer( __DRIscreenPrivate *driScrnPriv,
                                    GL_FALSE /* aux */);
       driDrawPriv->driverPrivate = (void *) fb;
 
+      driGetCurrentVBlank(driDrawPriv, 0, &driDrawPriv->primary_vblank_base);
+      driGetCurrentVBlank(driDrawPriv, VBLANK_FLAG_SECONDARY,
+			  &driDrawPriv->secondary_vblank_base);
+
       return (driDrawPriv->driverPrivate != NULL);
    }
 }
@@ -549,6 +553,7 @@ static const struct __DriverAPIRec intelAPI = {
    .UnbindContext   = intelUnbindContext,
    .GetSwapInfo     = intelGetSwapInfo,
    .GetMSC          = driGetMSC32,
+   .GetDrawableMSC  = driDrawableGetMSC32,
    .WaitForMSC      = driWaitForMSC32,
    .WaitForSBC      = NULL,
    .SwapBuffersMSC  = NULL,
diff --git a/src/mesa/drivers/dri/mach64/mach64_context.c b/src/mesa/drivers/dri/mach64/mach64_context.c
index ad661e1..138e84d 100644
--- a/src/mesa/drivers/dri/mach64/mach64_context.c
+++ b/src/mesa/drivers/dri/mach64/mach64_context.c
@@ -100,6 +100,7 @@ GLboolean mach64CreateContext( const __GLcontextModes *glVisual,
 {
    GLcontext *ctx, *shareCtx;
    __DRIscreenPrivate *driScreen = driContextPriv->driScreenPriv;
+   __DRIdrawablePrivate *dPriv = driContextPriv->driDrawablePriv;
    struct dd_function_table functions;
    mach64ContextPtr mmesa;
    mach64ScreenPtr mach64Screen;
@@ -253,7 +254,7 @@ GLboolean mach64CreateContext( const __GLcontextModes *glVisual,
 
    mmesa->do_irqs = (mmesa->mach64Screen->irq && !getenv("MACH64_NO_IRQS"));
 
-   mmesa->vblank_flags = (mmesa->do_irqs)
+   dPriv->vblFlags = (mmesa->do_irqs)
       ? driGetDefaultVBlankFlags(&mmesa->optionCache) : VBLANK_FLAG_NO_IRQ;
 
    driContextPriv->driverPrivate = (void *)mmesa;
@@ -330,8 +331,7 @@ mach64MakeCurrent( __DRIcontextPrivate *driContextPriv,
       }
 
       
-      driDrawableInitVBlank( driDrawPriv, newMach64Ctx->vblank_flags,
-			     &newMach64Ctx->vbl_seq );
+      driDrawableInitVBlank( driDrawPriv );
 
       if ( newMach64Ctx->driDrawable != driDrawPriv ) {
 	 newMach64Ctx->driDrawable = driDrawPriv;
diff --git a/src/mesa/drivers/dri/mach64/mach64_context.h b/src/mesa/drivers/dri/mach64/mach64_context.h
index 8d89452..c602333 100644
--- a/src/mesa/drivers/dri/mach64/mach64_context.h
+++ b/src/mesa/drivers/dri/mach64/mach64_context.h
@@ -263,8 +263,6 @@ struct mach64_context {
 
    /* VBI
     */
-   GLuint vbl_seq;
-   GLuint vblank_flags;
    GLuint do_irqs;
 
    /* Configuration cache
diff --git a/src/mesa/drivers/dri/mach64/mach64_ioctl.c b/src/mesa/drivers/dri/mach64/mach64_ioctl.c
index 36e7d3c..7405a27 100644
--- a/src/mesa/drivers/dri/mach64/mach64_ioctl.c
+++ b/src/mesa/drivers/dri/mach64/mach64_ioctl.c
@@ -279,7 +279,7 @@ static int mach64WaitForFrameCompletion( mach64ContextPtr mmesa )
 
 /* Copy the back color buffer to the front color buffer.
  */
-void mach64CopyBuffer( const __DRIdrawablePrivate *dPriv )
+void mach64CopyBuffer( __DRIdrawablePrivate *dPriv )
 {
    mach64ContextPtr mmesa;
    GLint nbox, i, ret;
@@ -320,7 +320,7 @@ void mach64CopyBuffer( const __DRIdrawablePrivate *dPriv )
 #endif
 
    UNLOCK_HARDWARE( mmesa );
-   driWaitForVBlank( dPriv, &mmesa->vbl_seq, mmesa->vblank_flags, &missed_target );
+   driWaitForVBlank( dPriv, &dPriv->vblSeq, dPriv->vblFlags, &missed_target );
    LOCK_HARDWARE( mmesa );
 
    /* use front buffer cliprects */
diff --git a/src/mesa/drivers/dri/mach64/mach64_ioctl.h b/src/mesa/drivers/dri/mach64/mach64_ioctl.h
index 52fe863..c28bf31 100644
--- a/src/mesa/drivers/dri/mach64/mach64_ioctl.h
+++ b/src/mesa/drivers/dri/mach64/mach64_ioctl.h
@@ -78,7 +78,7 @@ extern void mach64FireBlitLocked( mach64ContextPtr mmesa, void *buffer,
 				  GLint offset, GLint pitch, GLint format,
 				  GLint x, GLint y, GLint width, GLint height );
 
-extern void mach64CopyBuffer( const __DRIdrawablePrivate *dPriv );
+extern void mach64CopyBuffer( __DRIdrawablePrivate *dPriv );
 #if ENABLE_PERF_BOXES
 extern void mach64PerformanceCounters( mach64ContextPtr mmesa );
 extern void mach64PerformanceBoxesLocked( mach64ContextPtr mmesa );
diff --git a/src/mesa/drivers/dri/mach64/mach64_screen.c b/src/mesa/drivers/dri/mach64/mach64_screen.c
index 04eb081..a04b775 100644
--- a/src/mesa/drivers/dri/mach64/mach64_screen.c
+++ b/src/mesa/drivers/dri/mach64/mach64_screen.c
@@ -484,6 +484,7 @@ static struct __DriverAPIRec mach64API = {
    .UnbindContext   = mach64UnbindContext,
    .GetSwapInfo     = NULL,
    .GetMSC          = driGetMSC32,
+   .GetDrawableMSC  = driDrawableGetMSC32,
    .WaitForMSC      = driWaitForMSC32,
    .WaitForSBC      = NULL,
    .SwapBuffersMSC  = NULL
diff --git a/src/mesa/drivers/dri/mga/mga_xmesa.c b/src/mesa/drivers/dri/mga/mga_xmesa.c
index 2f3516f..31042f9 100644
--- a/src/mesa/drivers/dri/mga/mga_xmesa.c
+++ b/src/mesa/drivers/dri/mga/mga_xmesa.c
@@ -452,6 +452,7 @@ mgaCreateContext( const __GLcontextModes *mesaVis,
    GLcontext *ctx, *shareCtx;
    mgaContextPtr mmesa;
    __DRIscreenPrivate *sPriv = driContextPriv->driScreenPriv;
+   __DRIdrawablePrivate *dPriv = driContextPriv->driDrawablePriv;
    mgaScreenPrivate *mgaScreen = (mgaScreenPrivate *)sPriv->private;
    drm_mga_sarea_t *saPriv = (drm_mga_sarea_t *)(((char*)sPriv->pSAREA)+
 					      mgaScreen->sarea_priv_offset);
@@ -650,7 +651,7 @@ mgaCreateContext( const __GLcontextModes *mesaVis,
 				    debug_control );
 #endif
 
-   mmesa->vblank_flags = (mmesa->mgaScreen->irq == 0)
+   dPriv->vblFlags = (mmesa->mgaScreen->irq == 0)
        ? VBLANK_FLAG_NO_IRQ : driGetDefaultVBlankFlags(&mmesa->optionCache);
 
    (*dri_interface->getUST)( & mmesa->swap_ust );
@@ -882,8 +883,8 @@ mgaMakeCurrent(__DRIcontextPrivate *driContextPriv,
       mgaContextPtr mmesa = (mgaContextPtr) driContextPriv->driverPrivate;
 
       if (mmesa->driDrawable != driDrawPriv) {
-	 driDrawableInitVBlank( driDrawPriv, mmesa->vblank_flags,
-				&mmesa->vbl_seq );
+	 driDrawableInitVBlank( driDrawPriv );
+
 	 mmesa->driDrawable = driDrawPriv;
 	 mmesa->dirty = ~0; 
 	 mmesa->dirty_cliprects = (MGA_FRONT|MGA_BACK); 
@@ -948,6 +949,7 @@ static const struct __DriverAPIRec mgaAPI = {
    .UnbindContext   = mgaUnbindContext,
    .GetSwapInfo     = getSwapInfo,
    .GetMSC          = driGetMSC32,
+   .GetDrawableMSC  = driDrawableGetMSC32,
    .WaitForMSC      = driWaitForMSC32,
    .WaitForSBC      = NULL,
    .SwapBuffersMSC  = NULL
diff --git a/src/mesa/drivers/dri/mga/mgacontext.h b/src/mesa/drivers/dri/mga/mgacontext.h
index 2124006..2681976 100644
--- a/src/mesa/drivers/dri/mga/mgacontext.h
+++ b/src/mesa/drivers/dri/mga/mgacontext.h
@@ -258,11 +258,6 @@ struct mga_context_t {
    drmBufPtr  vertex_dma_buffer;
    drmBufPtr  iload_buffer;
 
-   /* VBI
-    */
-   GLuint vbl_seq;
-   GLuint vblank_flags;
-
    int64_t swap_ust;
    int64_t swap_missed_ust;
 
diff --git a/src/mesa/drivers/dri/mga/mgaioctl.c b/src/mesa/drivers/dri/mga/mgaioctl.c
index 679d688..94126a3 100644
--- a/src/mesa/drivers/dri/mga/mgaioctl.c
+++ b/src/mesa/drivers/dri/mga/mgaioctl.c
@@ -428,8 +428,7 @@ void mgaCopyBuffer( const __DRIdrawablePrivate *dPriv )
    FLUSH_BATCH( mmesa );
 
    mgaWaitForFrameCompletion( mmesa );
-   driWaitForVBlank( dPriv, & mmesa->vbl_seq, mmesa->vblank_flags,
-		     & missed_target );
+   driWaitForVBlank( dPriv, & dPriv->vblSeq, dPriv->vblFlags, & missed_target );
    if ( missed_target ) {
       mmesa->swap_missed_count++;
       (void) (*dri_interface->getUST)( & mmesa->swap_missed_ust );
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_context.c b/src/mesa/drivers/dri/nouveau/nouveau_context.c
index a8569a9..5ef24d8 100644
--- a/src/mesa/drivers/dri/nouveau/nouveau_context.c
+++ b/src/mesa/drivers/dri/nouveau/nouveau_context.c
@@ -283,7 +283,7 @@ GLboolean nouveauMakeCurrent( __DRIcontextPrivate *driContextPriv,
 		struct gl_framebuffer *read_fb =
 			(struct gl_framebuffer*)driReadPriv->driverPrivate;
 
-		driDrawableInitVBlank(driDrawPriv, nmesa->vblank_flags, &nmesa->vblank_seq );
+		driDrawableInitVBlank(driDrawPriv);
 		nmesa->driDrawable = driDrawPriv;
 
 		_mesa_resize_framebuffer(nmesa->glCtx, draw_fb,
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_context.h b/src/mesa/drivers/dri/nouveau/nouveau_context.h
index 9aff0ee..a617dd6 100644
--- a/src/mesa/drivers/dri/nouveau/nouveau_context.h
+++ b/src/mesa/drivers/dri/nouveau/nouveau_context.h
@@ -182,10 +182,6 @@ typedef struct nouveau_context {
 	/* Configuration cache */
 	driOptionCache optionCache;
 
-	/* vblank stuff */
-	uint32_t vblank_flags;
-	uint32_t vblank_seq;
-
 	GLuint new_state;
 	GLuint new_render_state;
 	GLuint render_index;
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_screen.c b/src/mesa/drivers/dri/nouveau/nouveau_screen.c
index 3e7bab6..533b4b1 100644
--- a/src/mesa/drivers/dri/nouveau/nouveau_screen.c
+++ b/src/mesa/drivers/dri/nouveau/nouveau_screen.c
@@ -205,6 +205,7 @@ static const struct __DriverAPIRec nouveauAPI = {
 	.UnbindContext   = nouveauUnbindContext,
 	.GetSwapInfo     = nouveauGetSwapInfo,
 	.GetMSC          = driGetMSC32,
+	.GetDrawableMSC  = driDrawableGetMSC32,
 	.WaitForMSC      = driWaitForMSC32,
 	.WaitForSBC      = NULL,
 	.SwapBuffersMSC  = NULL,
diff --git a/src/mesa/drivers/dri/r128/r128_context.c b/src/mesa/drivers/dri/r128/r128_context.c
index c9fe11f..25efe5e 100644
--- a/src/mesa/drivers/dri/r128/r128_context.c
+++ b/src/mesa/drivers/dri/r128/r128_context.c
@@ -113,6 +113,7 @@ GLboolean r128CreateContext( const __GLcontextModes *glVisual,
 {
    GLcontext *ctx, *shareCtx;
    __DRIscreenPrivate *sPriv = driContextPriv->driScreenPriv;
+   __DRIdrawablePrivate *dPriv = driContextPriv->driDrawablePriv;
    struct dd_function_table functions;
    r128ContextPtr rmesa;
    r128ScreenPtr r128scrn;
@@ -262,7 +263,7 @@ GLboolean r128CreateContext( const __GLcontextModes *glVisual,
    r128DDInitSpanFuncs( ctx );
    r128DDInitState( rmesa );
 
-   rmesa->vblank_flags = (rmesa->r128Screen->irq != 0)
+   dPriv->vblFlags = (rmesa->r128Screen->irq != 0)
        ? driGetDefaultVBlankFlags(&rmesa->optionCache) : VBLANK_FLAG_NO_IRQ;
 
    driContextPriv->driverPrivate = (void *)rmesa;
@@ -347,8 +348,7 @@ r128MakeCurrent( __DRIcontextPrivate *driContextPriv,
 	 newR128Ctx->dirty = R128_UPLOAD_ALL;
       }
 
-      driDrawableInitVBlank( driDrawPriv, newR128Ctx->vblank_flags,
-			     &newR128Ctx->vbl_seq );
+      driDrawableInitVBlank( driDrawPriv );
       newR128Ctx->driDrawable = driDrawPriv;
 
       _mesa_make_current( newR128Ctx->glCtx,
diff --git a/src/mesa/drivers/dri/r128/r128_context.h b/src/mesa/drivers/dri/r128/r128_context.h
index c51dd7f..3f7416e 100644
--- a/src/mesa/drivers/dri/r128/r128_context.h
+++ b/src/mesa/drivers/dri/r128/r128_context.h
@@ -210,11 +210,6 @@ struct r128_context {
    GLuint c_textureBytes;
    GLuint c_vertexBuffers;
 
-   /* VBI
-    */
-   GLuint vbl_seq;
-   GLuint vblank_flags;
-
    /* Configuration cache
     */
    driOptionCache optionCache;
diff --git a/src/mesa/drivers/dri/r128/r128_ioctl.c b/src/mesa/drivers/dri/r128/r128_ioctl.c
index b0dba7d..e04c087 100644
--- a/src/mesa/drivers/dri/r128/r128_ioctl.c
+++ b/src/mesa/drivers/dri/r128/r128_ioctl.c
@@ -249,7 +249,7 @@ static int r128WaitForFrameCompletion( r128ContextPtr rmesa )
 
 /* Copy the back color buffer to the front color buffer.
  */
-void r128CopyBuffer( const __DRIdrawablePrivate *dPriv )
+void r128CopyBuffer( __DRIdrawablePrivate *dPriv )
 {
    r128ContextPtr rmesa;
    GLint nbox, i, ret;
@@ -282,7 +282,7 @@ void r128CopyBuffer( const __DRIdrawablePrivate *dPriv )
    }
 
    UNLOCK_HARDWARE( rmesa );
-   driWaitForVBlank( dPriv, &rmesa->vbl_seq, rmesa->vblank_flags, &missed_target );
+   driWaitForVBlank( dPriv, &dPriv->vblSeq, dPriv->vblFlags, &missed_target );
    LOCK_HARDWARE( rmesa );
 
    nbox = dPriv->numClipRects;	/* must be in locked region */
@@ -328,7 +328,7 @@ void r128CopyBuffer( const __DRIdrawablePrivate *dPriv )
 #endif
 }
 
-void r128PageFlip( const __DRIdrawablePrivate *dPriv )
+void r128PageFlip( __DRIdrawablePrivate *dPriv )
 {
    r128ContextPtr rmesa;
    GLint ret;
@@ -359,7 +359,7 @@ void r128PageFlip( const __DRIdrawablePrivate *dPriv )
    }
 
    UNLOCK_HARDWARE( rmesa );
-   driWaitForVBlank( dPriv, &rmesa->vbl_seq, rmesa->vblank_flags, &missed_target );
+   driWaitForVBlank( dPriv, &dPriv->vblSeq, dPriv->vblFlags, &missed_target );
    LOCK_HARDWARE( rmesa );
 
    /* The kernel will have been initialized to perform page flipping
diff --git a/src/mesa/drivers/dri/r128/r128_ioctl.h b/src/mesa/drivers/dri/r128/r128_ioctl.h
index 95779f0..0f9d11f 100644
--- a/src/mesa/drivers/dri/r128/r128_ioctl.h
+++ b/src/mesa/drivers/dri/r128/r128_ioctl.h
@@ -86,8 +86,8 @@ extern void r128ReadDepthSpanLocked( r128ContextPtr rmesa,
 extern void r128ReadDepthPixelsLocked( r128ContextPtr rmesa, GLuint n,
 				       const GLint x[], const GLint y[] );
 
-extern void r128CopyBuffer( const __DRIdrawablePrivate *dPriv );
-extern void r128PageFlip( const __DRIdrawablePrivate *dPriv );
+extern void r128CopyBuffer( __DRIdrawablePrivate *dPriv );
+extern void r128PageFlip( __DRIdrawablePrivate *dPriv );
 void r128WaitForVBlank( r128ContextPtr rmesa );
 
 extern void r128WaitForIdleLocked( r128ContextPtr rmesa );
diff --git a/src/mesa/drivers/dri/r128/r128_screen.c b/src/mesa/drivers/dri/r128/r128_screen.c
index 9d65ebd..719f936 100644
--- a/src/mesa/drivers/dri/r128/r128_screen.c
+++ b/src/mesa/drivers/dri/r128/r128_screen.c
@@ -411,6 +411,7 @@ static struct __DriverAPIRec r128API = {
    .UnbindContext   = r128UnbindContext,
    .GetSwapInfo     = NULL,
    .GetMSC          = driGetMSC32,
+   .GetDrawableMSC  = driDrawableGetMSC32,
    .WaitForMSC      = driWaitForMSC32,
    .WaitForSBC      = NULL,
    .SwapBuffersMSC  = NULL
diff --git a/src/mesa/drivers/dri/r200/r200_context.c b/src/mesa/drivers/dri/r200/r200_context.c
index 8f43a2f..2b18889 100644
--- a/src/mesa/drivers/dri/r200/r200_context.c
+++ b/src/mesa/drivers/dri/r200/r200_context.c
@@ -248,6 +248,7 @@ GLboolean r200CreateContext( const __GLcontextModes *glVisual,
 			     void *sharedContextPrivate)
 {
    __DRIscreenPrivate *sPriv = driContextPriv->driScreenPriv;
+   __DRIdrawablePrivate *dPriv = driContextPriv->driDrawablePriv;
    radeonScreenPtr screen = (radeonScreenPtr)(sPriv->private);
    struct dd_function_table functions;
    r200ContextPtr rmesa;
@@ -499,7 +500,7 @@ GLboolean r200CreateContext( const __GLcontextModes *glVisual,
 	      fthrottle_mode,
 	      rmesa->r200Screen->irq);
 
-   rmesa->vblank_flags = (rmesa->r200Screen->irq != 0)
+   dPriv->vblFlags = (rmesa->r200Screen->irq != 0)
        ? driGetDefaultVBlankFlags(&rmesa->optionCache) : VBLANK_FLAG_NO_IRQ;
 
    rmesa->prefer_gart_client_texturing = 
@@ -667,8 +668,7 @@ r200MakeCurrent( __DRIcontextPrivate *driContextPriv,
 	 fprintf(stderr, "%s ctx %p\n", __FUNCTION__, (void *)newCtx->glCtx);
 
       if ( newCtx->dri.drawable != driDrawPriv ) {
-	 driDrawableInitVBlank( driDrawPriv, newCtx->vblank_flags,
-				&newCtx->vbl_seq );
+	  driDrawableInitVBlank( driDrawPriv );
       }
 
       newCtx->dri.readable = driReadPriv;
diff --git a/src/mesa/drivers/dri/r200/r200_context.h b/src/mesa/drivers/dri/r200/r200_context.h
index c80180b..be73507 100644
--- a/src/mesa/drivers/dri/r200/r200_context.h
+++ b/src/mesa/drivers/dri/r200/r200_context.h
@@ -893,11 +893,8 @@ struct r200_context {
    GLuint TexGenCompSel;
    GLmatrix tmpmat;
 
-   /* VBI / buffer swap
+   /* buffer swap
     */
-   GLuint vbl_seq;
-   GLuint vblank_flags;
-
    int64_t swap_ust;
    int64_t swap_missed_ust;
 
diff --git a/src/mesa/drivers/dri/r200/r200_ioctl.c b/src/mesa/drivers/dri/r200/r200_ioctl.c
index c9c5a86..2ab9ff8 100644
--- a/src/mesa/drivers/dri/r200/r200_ioctl.c
+++ b/src/mesa/drivers/dri/r200/r200_ioctl.c
@@ -419,7 +419,7 @@ static void r200WaitForFrameCompletion( r200ContextPtr rmesa )
 
 /* Copy the back color buffer to the front color buffer.
  */
-void r200CopyBuffer( const __DRIdrawablePrivate *dPriv,
+void r200CopyBuffer( __DRIdrawablePrivate *dPriv,
 		      const drm_clip_rect_t	 *rect)
 {
    r200ContextPtr rmesa;
@@ -449,7 +449,7 @@ void r200CopyBuffer( const __DRIdrawablePrivate *dPriv,
    if (!rect)
    {
        UNLOCK_HARDWARE( rmesa );
-       driWaitForVBlank( dPriv, & rmesa->vbl_seq, rmesa->vblank_flags, & missed_target );
+       driWaitForVBlank( dPriv, & dPriv->vblSeq, dPriv->vblFlags, & missed_target );
        LOCK_HARDWARE( rmesa );
    }
 
@@ -513,7 +513,7 @@ void r200CopyBuffer( const __DRIdrawablePrivate *dPriv,
    }
 }
 
-void r200PageFlip( const __DRIdrawablePrivate *dPriv )
+void r200PageFlip( __DRIdrawablePrivate *dPriv )
 {
    r200ContextPtr rmesa;
    GLint ret;
@@ -553,7 +553,7 @@ void r200PageFlip( const __DRIdrawablePrivate *dPriv )
     */
    r200WaitForFrameCompletion( rmesa );
    UNLOCK_HARDWARE( rmesa );
-   driWaitForVBlank( dPriv, & rmesa->vbl_seq, rmesa->vblank_flags, & missed_target );
+   driWaitForVBlank( dPriv, & dPriv->vblSeq, dPriv->vblFlags, & missed_target );
    if ( missed_target ) {
       rmesa->swap_missed_count++;
       (void) (*dri_interface->getUST)( & rmesa->swap_missed_ust );
diff --git a/src/mesa/drivers/dri/r200/r200_ioctl.h b/src/mesa/drivers/dri/r200/r200_ioctl.h
index bf12679..4521fba 100644
--- a/src/mesa/drivers/dri/r200/r200_ioctl.h
+++ b/src/mesa/drivers/dri/r200/r200_ioctl.h
@@ -89,9 +89,9 @@ extern void r200ReleaseDmaRegion( r200ContextPtr rmesa,
 				    struct r200_dma_region *region,
 				    const char *caller );
 
-extern void r200CopyBuffer( const __DRIdrawablePrivate *drawable,
+extern void r200CopyBuffer( __DRIdrawablePrivate *drawable,
 			    const drm_clip_rect_t      *rect);
-extern void r200PageFlip( const __DRIdrawablePrivate *drawable );
+extern void r200PageFlip( __DRIdrawablePrivate *drawable );
 extern void r200Flush( GLcontext *ctx );
 extern void r200Finish( GLcontext *ctx );
 extern void r200WaitForIdleLocked( r200ContextPtr rmesa );
diff --git a/src/mesa/drivers/dri/r300/radeon_context.c b/src/mesa/drivers/dri/r300/radeon_context.c
index 6dfaf3c..8316b74 100644
--- a/src/mesa/drivers/dri/r300/radeon_context.c
+++ b/src/mesa/drivers/dri/r300/radeon_context.c
@@ -127,6 +127,7 @@ GLboolean radeonInitContext(radeonContextPtr radeon,
 			    void *sharedContextPrivate)
 {
 	__DRIscreenPrivate *sPriv = driContextPriv->driScreenPriv;
+	__DRIdrawablePrivate *dPriv = driContextPriv->driDrawablePriv;
 	radeonScreenPtr screen = (radeonScreenPtr) (sPriv->private);
 	GLcontext* ctx;
 	GLcontext* shareCtx;
@@ -177,7 +178,7 @@ GLboolean radeonInitContext(radeonContextPtr radeon,
 			radeon->do_usleeps ? "usleeps" : "busy waits",
 			fthrottle_mode, radeon->radeonScreen->irq);
 
-	radeon->vblank_flags = (radeon->radeonScreen->irq != 0)
+	dPriv->vblFlags = (radeon->radeonScreen->irq != 0)
 	    ? driGetDefaultVBlankFlags(&radeon->optionCache) : VBLANK_FLAG_NO_IRQ;
 
 	(*dri_interface->getUST) (&radeon->swap_ust);
@@ -277,9 +278,7 @@ GLboolean radeonMakeCurrent(__DRIcontextPrivate * driContextPriv,
 				radeon->glCtx);
 
 		if (radeon->dri.drawable != driDrawPriv) {
-			driDrawableInitVBlank(driDrawPriv,
-					      radeon->vblank_flags,
-					      &radeon->vbl_seq);
+		    driDrawableInitVBlank(driDrawPriv);
 		}
 
 		radeon->dri.readable = driReadPriv;
diff --git a/src/mesa/drivers/dri/r300/radeon_context.h b/src/mesa/drivers/dri/r300/radeon_context.h
index 2f23941..38d8930 100644
--- a/src/mesa/drivers/dri/r300/radeon_context.h
+++ b/src/mesa/drivers/dri/r300/radeon_context.h
@@ -182,10 +182,7 @@ struct radeon_context {
 	GLuint irqsEmitted;
 	drm_radeon_irq_wait_t iw;
 
-	/* VBI / buffer swap */
-	GLuint vbl_seq;
-	GLuint vblank_flags;
-
+	/* buffer swap */
 	int64_t swap_ust;
 	int64_t swap_missed_ust;
 
diff --git a/src/mesa/drivers/dri/r300/radeon_ioctl.c b/src/mesa/drivers/dri/r300/radeon_ioctl.c
index 0b8656b..eeef71a 100644
--- a/src/mesa/drivers/dri/r300/radeon_ioctl.c
+++ b/src/mesa/drivers/dri/r300/radeon_ioctl.c
@@ -157,7 +157,7 @@ static void radeonWaitForFrameCompletion(radeonContextPtr radeon)
 
 /* Copy the back color buffer to the front color buffer.
  */
-void radeonCopyBuffer(const __DRIdrawablePrivate * dPriv,
+void radeonCopyBuffer(__DRIdrawablePrivate * dPriv,
 		      const drm_clip_rect_t	 * rect)
 {
 	radeonContextPtr radeon;
@@ -187,7 +187,7 @@ void radeonCopyBuffer(const __DRIdrawablePrivate * dPriv,
 	if (!rect)
 	{
 	    UNLOCK_HARDWARE(radeon);
-	    driWaitForVBlank(dPriv, &radeon->vbl_seq, radeon->vblank_flags,
+	    driWaitForVBlank(dPriv, &dPriv->vblSeq, dPriv->vblFlags,
 			     &missed_target);
 	    LOCK_HARDWARE(radeon);
 	}
@@ -253,7 +253,7 @@ void radeonCopyBuffer(const __DRIdrawablePrivate * dPriv,
 	}
 }
 
-void radeonPageFlip(const __DRIdrawablePrivate * dPriv)
+void radeonPageFlip(__DRIdrawablePrivate * dPriv)
 {
 	radeonContextPtr radeon;
 	GLint ret;
@@ -293,7 +293,7 @@ void radeonPageFlip(const __DRIdrawablePrivate * dPriv)
 	 */
 	radeonWaitForFrameCompletion(radeon);
 	UNLOCK_HARDWARE(radeon);
-	driWaitForVBlank(dPriv, &radeon->vbl_seq, radeon->vblank_flags,
+	driWaitForVBlank(dPriv, &dPriv->vblSeq, dPriv->vblFlags,
 			 &missed_target);
 	if (missed_target) {
 		radeon->swap_missed_count++;
diff --git a/src/mesa/drivers/dri/r300/radeon_ioctl.h b/src/mesa/drivers/dri/r300/radeon_ioctl.h
index 3a80d36..210001e 100644
--- a/src/mesa/drivers/dri/r300/radeon_ioctl.h
+++ b/src/mesa/drivers/dri/r300/radeon_ioctl.h
@@ -46,9 +46,9 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #endif
 #include "radeon_drm.h"
 
-extern void radeonCopyBuffer(const __DRIdrawablePrivate * drawable,
+extern void radeonCopyBuffer(__DRIdrawablePrivate * drawable,
 			     const drm_clip_rect_t	* rect);
-extern void radeonPageFlip(const __DRIdrawablePrivate * drawable);
+extern void radeonPageFlip(__DRIdrawablePrivate * drawable);
 extern void radeonFlush(GLcontext * ctx);
 extern void radeonFinish(GLcontext * ctx);
 extern void radeonWaitForIdleLocked(radeonContextPtr radeon);
diff --git a/src/mesa/drivers/dri/radeon/radeon_context.c b/src/mesa/drivers/dri/radeon/radeon_context.c
index defc82f..fe6d3c2 100644
--- a/src/mesa/drivers/dri/radeon/radeon_context.c
+++ b/src/mesa/drivers/dri/radeon/radeon_context.c
@@ -594,8 +594,7 @@ radeonMakeCurrent( __DRIcontextPrivate *driContextPriv,
 
       if ( newCtx->dri.drawable != driDrawPriv ) {
          /* XXX we may need to validate the drawable here!!! */
-	 driDrawableInitVBlank( driDrawPriv, newCtx->vblank_flags,
-				&newCtx->vbl_seq );
+	  driDrawableInitVBlank( driDrawPriv );
       }
 
       newCtx->dri.readable = driReadPriv;
diff --git a/src/mesa/drivers/dri/radeon/radeon_screen.c b/src/mesa/drivers/dri/radeon/radeon_screen.c
index 10d3c2b..4cc87a9 100644
--- a/src/mesa/drivers/dri/radeon/radeon_screen.c
+++ b/src/mesa/drivers/dri/radeon/radeon_screen.c
@@ -961,6 +961,7 @@ static struct __DriverAPIRec radeonAPI = {
    .UnbindContext   = radeonUnbindContext,
    .GetSwapInfo     = getSwapInfo,
    .GetMSC          = driGetMSC32,
+   .GetDrawableMSC  = driDrawableGetMSC32,
    .WaitForMSC      = driWaitForMSC32,
    .WaitForSBC      = NULL,
    .SwapBuffersMSC  = NULL,
@@ -978,6 +979,7 @@ static const struct __DriverAPIRec r200API = {
    .UnbindContext   = r200UnbindContext,
    .GetSwapInfo     = getSwapInfo,
    .GetMSC          = driGetMSC32,
+   .GetDrawableMSC  = driDrawableGetMSC32,
    .WaitForMSC      = driWaitForMSC32,
    .WaitForSBC      = NULL,
    .SwapBuffersMSC  = NULL,
diff --git a/src/mesa/drivers/dri/sis/sis_screen.c b/src/mesa/drivers/dri/sis/sis_screen.c
index 79682a7..6711935 100644
--- a/src/mesa/drivers/dri/sis/sis_screen.c
+++ b/src/mesa/drivers/dri/sis/sis_screen.c
@@ -314,6 +314,7 @@ static struct __DriverAPIRec sisAPI = {
    .UnbindContext   = sisUnbindContext,
    .GetSwapInfo     = NULL,
    .GetMSC          = NULL,
+   .GetDrawableMSC  = NULL,
    .WaitForMSC      = NULL,
    .WaitForSBC      = NULL,
    .SwapBuffersMSC  = NULL
diff --git a/src/mesa/drivers/dri/tdfx/tdfx_screen.c b/src/mesa/drivers/dri/tdfx/tdfx_screen.c
index 5bdb446..6298de8 100644
--- a/src/mesa/drivers/dri/tdfx/tdfx_screen.c
+++ b/src/mesa/drivers/dri/tdfx/tdfx_screen.c
@@ -355,6 +355,7 @@ static const struct __DriverAPIRec tdfxAPI = {
    .UnbindContext   = tdfxUnbindContext,
    .GetSwapInfo     = NULL,
    .GetMSC          = NULL,
+   .GetDrawableMSC  = NULL,
    .WaitForMSC      = NULL,
    .WaitForSBC      = NULL,
    .SwapBuffersMSC  = NULL
diff --git a/src/mesa/drivers/dri/unichrome/via_context.c b/src/mesa/drivers/dri/unichrome/via_context.c
index 66e92cc..5d95d97 100644
--- a/src/mesa/drivers/dri/unichrome/via_context.c
+++ b/src/mesa/drivers/dri/unichrome/via_context.c
@@ -465,6 +465,7 @@ viaCreateContext(const __GLcontextModes *visual,
     GLcontext *ctx, *shareCtx;
     struct via_context *vmesa;
     __DRIscreenPrivate *sPriv = driContextPriv->driScreenPriv;
+    __DRIdrawablePrivate *dPriv = driContextPriv->driDrawablePriv;
     viaScreenPrivate *viaScreen = (viaScreenPrivate *)sPriv->private;
     drm_via_sarea_t *saPriv = (drm_via_sarea_t *)
         (((GLubyte *)sPriv->pSAREA) + viaScreen->sareaPrivOffset);
@@ -658,7 +659,7 @@ viaCreateContext(const __GLcontextModes *visual,
         driQueryOptionb(&vmesa->optionCache, "no_rast"))
        FALLBACK(vmesa, VIA_FALLBACK_USER_DISABLE, 1);
 
-    vmesa->vblank_flags =
+    dPriv->vblFlags =
        vmesa->viaScreen->irqEnabled ?
         driGetDefaultVBlankFlags(&vmesa->optionCache) : VBLANK_FLAG_NO_IRQ;
 
@@ -838,8 +839,7 @@ viaMakeCurrent(__DRIcontextPrivate *driContextPriv,
         readBuffer = (GLframebuffer *)driReadPriv->driverPrivate;
 
 	if (vmesa->driDrawable != driDrawPriv) {
-	   driDrawableInitVBlank(driDrawPriv, vmesa->vblank_flags,
-				 &vmesa->vbl_seq);
+	    driDrawableInitVBlank(driDrawPriv);
 	}
 
        if ((vmesa->driDrawable != driDrawPriv)
diff --git a/src/mesa/drivers/dri/unichrome/via_context.h b/src/mesa/drivers/dri/unichrome/via_context.h
index 6321713..acd6f2e 100644
--- a/src/mesa/drivers/dri/unichrome/via_context.h
+++ b/src/mesa/drivers/dri/unichrome/via_context.h
@@ -321,9 +321,6 @@ struct via_context {
     */
    driOptionCache optionCache;
 
-   GLuint vblank_flags;
-   GLuint vbl_seq;
-
    int64_t swap_ust;
    int64_t swap_missed_ust;
 
diff --git a/src/mesa/drivers/dri/unichrome/via_ioctl.c b/src/mesa/drivers/dri/unichrome/via_ioctl.c
index 4a733fb..3c7dafd 100644
--- a/src/mesa/drivers/dri/unichrome/via_ioctl.c
+++ b/src/mesa/drivers/dri/unichrome/via_ioctl.c
@@ -507,7 +507,7 @@ void viaWaitIdleLocked( struct via_context *vmesa, GLboolean light )
  * except that WAIT_IDLE() will spin the CPU polling, while this is
  * IRQ driven.
  */
-static void viaWaitIdleVBlank( const __DRIdrawablePrivate *dPriv, 
+static void viaWaitIdleVBlank(  __DRIdrawablePrivate *dPriv, 
 			       struct via_context *vmesa,
 			       GLuint value )
 {
@@ -523,8 +523,8 @@ static void viaWaitIdleVBlank( const __DRIdrawablePrivate *dPriv,
 	  vmesa->thrashing)
 	 viaSwapOutWork(vmesa);
 
-      driWaitForVBlank( dPriv, & vmesa->vbl_seq, 
-			vmesa->vblank_flags, & missed_target );
+      driWaitForVBlank( dPriv, & dPriv->vblSeq, dPriv->vblFlags,
+			& missed_target );
       if ( missed_target ) {
 	 vmesa->swap_missed_count++;
 	 (*dri_interface->getUST)( &vmesa->swap_missed_ust );
@@ -591,7 +591,7 @@ void viaResetPageFlippingLocked(struct via_context *vmesa)
 /*
  * Copy the back buffer to the front buffer. 
  */
-void viaCopyBuffer(const __DRIdrawablePrivate *dPriv)
+void viaCopyBuffer(__DRIdrawablePrivate *dPriv)
 {
    struct via_context *vmesa = 
       (struct via_context *)dPriv->driContextPriv->driverPrivate;
@@ -607,7 +607,7 @@ void viaCopyBuffer(const __DRIdrawablePrivate *dPriv)
 
    VIA_FLUSH_DMA(vmesa);
 
-   if (vmesa->vblank_flags == VBLANK_FLAG_SYNC &&
+   if (dPriv->vblFlags == VBLANK_FLAG_SYNC &&
        vmesa->lastBreadcrumbWrite > 1)
       viaWaitIdleVBlank(dPriv, vmesa, vmesa->lastBreadcrumbWrite-1);
    else
@@ -634,14 +634,14 @@ void viaCopyBuffer(const __DRIdrawablePrivate *dPriv)
 }
 
 
-void viaPageFlip(const __DRIdrawablePrivate *dPriv)
+void viaPageFlip(__DRIdrawablePrivate *dPriv)
 {
     struct via_context *vmesa = 
        (struct via_context *)dPriv->driContextPriv->driverPrivate;
     struct via_renderbuffer buffer_tmp;
 
     VIA_FLUSH_DMA(vmesa);
-   if (vmesa->vblank_flags == VBLANK_FLAG_SYNC &&
+   if (dPriv->vblFlags == VBLANK_FLAG_SYNC &&
        vmesa->lastBreadcrumbWrite > 1)
       viaWaitIdleVBlank(dPriv, vmesa, vmesa->lastBreadcrumbWrite - 1);
    else
diff --git a/src/mesa/drivers/dri/unichrome/via_ioctl.h b/src/mesa/drivers/dri/unichrome/via_ioctl.h
index a81b427..44fc439 100644
--- a/src/mesa/drivers/dri/unichrome/via_ioctl.h
+++ b/src/mesa/drivers/dri/unichrome/via_ioctl.h
@@ -33,8 +33,8 @@ void viaFlushDma(struct via_context *vmesa);
 void viaFlushDmaLocked(struct via_context *vmesa, GLuint flags);
 
 void viaInitIoctlFuncs(GLcontext *ctx);
-void viaCopyBuffer(const __DRIdrawablePrivate *dpriv);
-void viaPageFlip(const __DRIdrawablePrivate *dpriv);
+void viaCopyBuffer(__DRIdrawablePrivate *dpriv);
+void viaPageFlip(__DRIdrawablePrivate *dpriv);
 void viaCheckDma(struct via_context *vmesa, GLuint bytes);
 void viaResetPageFlippingLocked(struct via_context *vmesa);
 void viaWaitIdle(struct via_context *vmesa, GLboolean light);
diff --git a/src/mesa/drivers/dri/unichrome/via_screen.c b/src/mesa/drivers/dri/unichrome/via_screen.c
index f3912ac..0ad18b4 100644
--- a/src/mesa/drivers/dri/unichrome/via_screen.c
+++ b/src/mesa/drivers/dri/unichrome/via_screen.c
@@ -334,6 +334,7 @@ static struct __DriverAPIRec viaAPI = {
    .UnbindContext   = viaUnbindContext,
    .GetSwapInfo     = getSwapInfo,
    .GetMSC          = driGetMSC32,
+   .GetDrawableMSC  = driDrawableGetMSC32,
    .WaitForMSC      = driWaitForMSC32,
    .WaitForSBC      = NULL,
    .SwapBuffersMSC  = NULL
-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems?  Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >> http://get.splunk.com/
--
_______________________________________________
Dri-devel mailing list
Dri-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/dri-devel

Reply via email to