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