On Wednesday, September 26, 2007 9:39 am Michel Dänzer wrote:
> > Err yeah I was describing it backwards.  The __DRIscreen hooks for
> > the MSC stuff all point to dri_util.c wrapper functions that end up
> > calling the driver hooks.  However, drivers always set their hooks
> > to either NULL or to the routines in vblank.c.  So we could just
> > set the __DRIscreen hooks to point to vblank.c directly since none
> > of the drivers appear to have custom hooks for these calls...
>
> I see, thanks for clarifying. Ian Romanick can probably tell us more
> about this.

And for reference, here's the updated patch.

Jesse
diff --git a/include/GL/internal/dri_interface.h b/include/GL/internal/dri_interface.h
index 8d24e31..bd898d2 100644
--- a/include/GL/internal/dri_interface.h
+++ b/include/GL/internal/dri_interface.h
@@ -512,6 +512,17 @@ struct __DRIdrawableRec {
      */
     void (*copySubBuffer)(__DRInativeDisplay *dpy, void *drawablePrivate,
 			  int x, int y, int w, int h);
+
+    /**
+     * 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 (*getMSC)(__DRInativeDisplay *dpy, void *drawablePrivate, int64_t *msc);
 };
 
 #endif
diff --git a/src/glx/x11/glxcmds.c b/src/glx/x11/glxcmds.c
index f52b71f..134afac 100644
--- a/src/glx/x11/glxcmds.c
+++ b/src/glx/x11/glxcmds.c
@@ -1889,14 +1889,32 @@ static int __glXGetVideoSyncSGI(unsigned int *count)
    if ( (gc != NULL) && gc->isDirect ) {
       __GLXscreenConfigs * const psc = GetGLXScreenConfigs( gc->currentDpy,
 							    gc->screen );
-      if ( __glXExtensionBitIsEnabled( psc, SGI_video_sync_bit )
-	   && psc->driScreen.private && psc->driScreen.getMSC) {
-	 int       ret;
-	 int64_t   temp;
-
-	 ret = psc->driScreen.getMSC( psc->driScreen.private, & temp );
-	 *count = (unsigned) temp;
-	 return (ret == 0) ? 0 : GLX_BAD_CONTEXT;
+      if ( __glXExtensionBitIsEnabled( psc, SGI_video_sync_bit ) 
+	   && psc->driScreen.private ) {
+	  __DRIdrawable * const pdraw = 
+	      (*psc->driScreen.getDrawable)(gc->currentDpy,
+					    gc->currentDrawable,
+					    psc->driScreen.private);
+	  /*
+	   * Try to use the drawable's getMSC first so we get the right
+	   * counter
+	   */
+	  if ( (pdraw != NULL) && (pdraw->getMSC != NULL) ) {
+	      int       ret;
+	      int64_t	temp;
+
+	      ret = (*pdraw->getMSC)( psc->driScreen.private, pdraw->private,
+				      & temp);
+	      *count = (unsigned) temp;
+	      return (ret == 0) ? 0 : GLX_BAD_CONTEXT;
+	  } else if ( psc->driScreen.getMSC ) { /* fallback to screen */
+	      int       ret;
+	      int64_t   temp;
+
+	      ret = psc->driScreen.getMSC( psc->driScreen.private, & temp );
+	      *count = (unsigned) temp;
+	      return (ret == 0) ? 0 : GLX_BAD_CONTEXT;
+	  }
       }
    }
 #else
diff --git a/src/mesa/drivers/dri/common/dri_util.c b/src/mesa/drivers/dri/common/dri_util.c
index c30e66f..ae2db0a 100644
--- a/src/mesa/drivers/dri/common/dri_util.c
+++ b/src/mesa/drivers/dri/common/dri_util.c
@@ -31,6 +31,7 @@
 
 #include "dri_util.h"
 #include "drm_sarea.h"
+#include "vblank.h"
 
 #ifndef GLX_OML_sync_control
 typedef GLboolean ( * PFNGLXGETMSCRATEOMLPROC) (__DRInativeDisplay *dpy, __DRIid drawable, int32_t *numerator, int32_t *denominator);
@@ -639,6 +640,8 @@ static void *driCreateNewDrawable(__DRInativeDisplay *dpy,
     pdp->numBackClipRects = 0;
     pdp->pClipRects = NULL;
     pdp->pBackClipRects = NULL;
+    pdp->vblSeq = 0;
+    pdp->vblFlags = 0;
     pdp->display = dpy;
     pdp->screen = modes->screen;
 
@@ -663,6 +666,7 @@ static void *driCreateNewDrawable(__DRInativeDisplay *dpy,
     pdraw->swapBuffersMSC = driSwapBuffersMSC;
     pdraw->frameTracking = NULL;
     pdraw->queryFrameTracking = driQueryFrameTracking;
+    pdraw->getMSC = driDrawableGetMSC;
 
     if (driCompareGLXAPIVersion (20060314) >= 0)
 	pdraw->copySubBuffer = driCopySubBuffer;
diff --git a/src/mesa/drivers/dri/common/dri_util.h b/src/mesa/drivers/dri/common/dri_util.h
index 539d28d..cb3c5d3 100644
--- a/src/mesa/drivers/dri/common/dri_util.h
+++ b/src/mesa/drivers/dri/common/dri_util.h
@@ -308,6 +308,15 @@ 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]/
+
+    /**
      * 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 e7ed545..6ab72b3 100644
--- a/src/mesa/drivers/dri/common/vblank.c
+++ b/src/mesa/drivers/dri/common/vblank.c
@@ -50,19 +50,24 @@
  * currently always returns a \c sequence of type \c unsigned.
  *
  * \param priv   Pointer to the DRI screen private struct.
+ * \param drawablePrivate 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 driDrawableGetMSC(__DRIscreenPrivate * priv, void *drawablePrivate,
+		      int64_t * count)
 {
    drmVBlank vbl;
    int ret;
+   __DRIdrawablePrivate *dPriv = drawablePrivate;
 
    /* Don't wait for anything.  Just get the current refresh count. */
 
    vbl.request.type = DRM_VBLANK_RELATIVE;
    vbl.request.sequence = 0;
+   if ( dPriv->vblFlags & VBLANK_FLAG_SECONDARY )
+      vbl.request.type |= DRM_VBLANK_SECONDARY;
 
    ret = drmWaitVBlank( priv->fd, &vbl );
    *count = (int64_t)vbl.reply.sequence;
@@ -70,6 +75,27 @@ int driGetMSC32( __DRIscreenPrivate * priv, int64_t * count )
    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.
+ *
+ * \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);
+}
 
 /****************************************************************************/
 /**
@@ -124,6 +150,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.
@@ -257,7 +285,12 @@ void driDrawableInitVBlank( __DRIdrawablePrivate *priv, GLuint flags,
 {
    if ( priv->pdraw->swap_interval == (unsigned)-1 ) {
       /* Get current vertical blank sequence */
-      drmVBlank vbl = { .request={ .type = DRM_VBLANK_RELATIVE, .sequence = 0 } };
+      drmVBlank vbl;
+
+      vbl.request.type = DRM_VBLANK_RELATIVE;
+      if ( flags & VBLANK_FLAG_SECONDARY )
+	 vbl.request.type |= DRM_VBLANK_SECONDARY;
+      vbl.request.sequence = 0;
       do_wait( &vbl, vbl_seq, priv->driScreenPriv->fd );
 
       priv->pdraw->swap_interval = (flags & (VBLANK_FLAG_THROTTLE |
diff --git a/src/mesa/drivers/dri/common/vblank.h b/src/mesa/drivers/dri/common/vblank.h
index ec83adc..a9d720d 100644
--- a/src/mesa/drivers/dri/common/vblank.h
+++ b/src/mesa/drivers/dri/common/vblank.h
@@ -45,6 +45,8 @@
 #define VBLANK_FLAG_SECONDARY (1U << 8)  /* Wait for secondary vblank.
 					  */
 
+extern int driDrawableGetMSC(__DRIscreenPrivate * priv, void *drawablePrivate,
+			     int64_t * count);
 extern int driGetMSC32( __DRIscreenPrivate * priv, int64_t * count );
 extern int driWaitForMSC32( __DRIdrawablePrivate *priv,
     int64_t target_msc, int64_t divisor, int64_t remainder, int64_t * msc );
diff --git a/src/mesa/drivers/dri/i965/intel_blit.c b/src/mesa/drivers/dri/i965/intel_blit.c
index f88cbb2..a7604b9 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 d155c03..2b2bac0 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,45 @@ void intelWindowMoved( struct intel_context *intel )
       }
    }
 
+   /* Get updated plane info so we sync against the right vblank counter */
+   if (intel->intelScreen->driScrnPriv->ddxMinor >= 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;
+      }
+
+      if (flags != dPriv->vblFlags && dPriv->vblFlags &&
+	  !(dPriv->vblFlags & VBLANK_FLAG_NO_IRQ)) {
+	 drmVBlank vbl;
+
+	 vbl.request.type = DRM_VBLANK_ABSOLUTE;
+
+	 if ( dPriv->vblFlags & VBLANK_FLAG_SECONDARY )
+	    vbl.request.type |= DRM_VBLANK_SECONDARY;
+
+	 dPriv->vblFlags = flags;
+	 driGetCurrentVBlank(dPriv, dPriv->vblFlags, &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 1fbf571..05a9aec 100644
--- a/src/mesa/drivers/dri/i965/intel_context.c
+++ b/src/mesa/drivers/dri/i965/intel_context.c
@@ -327,9 +327,10 @@ GLboolean intelInitContext( struct intel_context *intel,
    GLcontext *ctx = &intel->ctx;
    GLcontext *shareCtx = (GLcontext *) sharedContextPrivate;
    __DRIscreenPrivate *sPriv = driContextPriv->driScreenPriv;
+   __DRIdrawablePrivate *dPriv = driContextPriv->driDrawablePriv;
    intelScreenPrivate *intelScreen = (intelScreenPrivate *)sPriv->private;
-   volatile drmI830Sarea *saPriv = (volatile drmI830Sarea *)
-      (((GLubyte *)sPriv->pSAREA)+intelScreen->sarea_priv_offset);
+   drmI830Sarea *saPriv = (drmI830Sarea *)
+       (((GLubyte *)sPriv->pSAREA)+intelScreen->sarea_priv_offset);
 
    if (!_mesa_initialize_context(&intel->ctx,
 				 mesaVis, shareCtx, 
@@ -347,8 +348,8 @@ 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;
+   dPriv->vblFlags = (intel->intelScreen->irq_active != 0)
+       ? driGetDefaultVBlankFlags(&intel->optionCache) : VBLANK_FLAG_NO_IRQ;
 
    ctx->Const.MaxTextureMaxAnisotropy = 2.0;
 
@@ -582,8 +583,9 @@ GLboolean intelMakeCurrent(__DRIcontextPrivate *driContextPriv,
 
       if ( intel->driDrawable != driDrawPriv ) {
 	 /* Shouldn't the readbuffer be stored also? */
-	 driDrawableInitVBlank( driDrawPriv, intel->vblank_flags,
-		      &intel->vbl_seq );
+	  driDrawableInitVBlank( driDrawPriv,
+				 driDrawPriv->vblFlags,
+				 &driDrawPriv->vblSeq);
 
 	 intel->driDrawable = driDrawPriv;
 	 intelWindowMoved( intel );
diff --git a/src/mesa/drivers/dri/i965/intel_context.h b/src/mesa/drivers/dri/i965/intel_context.h
index 053d93a..26d6923 100644
--- a/src/mesa/drivers/dri/i965/intel_context.h
+++ b/src/mesa/drivers/dri/i965/intel_context.h
@@ -237,7 +237,7 @@ struct intel_context
    __DRIdrawablePrivate *driReadDrawable;
    __DRIscreenPrivate *driScreen;
    intelScreenPrivate *intelScreen; 
-   volatile drmI830Sarea *sarea; 
+   drmI830Sarea *sarea; 
    
    FILE *aub_file;
 
@@ -248,11 +248,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/server/i830_common.h b/src/mesa/drivers/dri/i965/server/i830_common.h
index f320378..452c400 100644
--- a/src/mesa/drivers/dri/i965/server/i830_common.h
+++ b/src/mesa/drivers/dri/i965/server/i830_common.h
@@ -119,6 +119,15 @@ typedef struct {
         unsigned int depth_tiled;
         unsigned int rotated_tiled;
         unsigned int rotated2_tiled;
+
+	int planeA_x;
+	int planeA_y;
+	int planeA_w;
+	int planeA_h;
+	int planeB_x;
+	int planeB_y;
+	int planeB_w;
+	int planeB_h;
 } drmI830Sarea;
 
 /* Flags for perf_boxes
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
--
_______________________________________________
Dri-devel mailing list
Dri-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/dri-devel

Reply via email to