diff options
Diffstat (limited to 'src/mesa/drivers/dri/common')
-rw-r--r-- | src/mesa/drivers/dri/common/dri_util.c | 14 | ||||
-rw-r--r-- | src/mesa/drivers/dri/common/dri_util.h | 34 | ||||
-rw-r--r-- | src/mesa/drivers/dri/common/vblank.c | 94 | ||||
-rw-r--r-- | src/mesa/drivers/dri/common/vblank.h | 6 |
4 files changed, 127 insertions, 21 deletions
diff --git a/src/mesa/drivers/dri/common/dri_util.c b/src/mesa/drivers/dri/common/dri_util.c index d59ea0ddad0..2e2e64c4d18 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,7 @@ static void *driCreateNewDrawable(__DRIscreen *screen, pdraw->private = pdp; pdraw->destroyDrawable = driDestroyDrawable; pdraw->swapBuffers = driSwapBuffers; /* called by glXSwapBuffers() */ + pdp->msc_base = 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 91992a9a242..def07758398 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,32 @@ struct __DRIdrawablePrivateRec { /*@}*/ /** + * \name Vertical blank tracking information + * Used for waiting on vertical blank events. + */ + /*@{*/ + unsigned int vblSeq; + unsigned int vblFlags; + /*@}*/ + + /** + * \name Monotonic MSC tracking + * + * Low level driver is responsible for updating msc_base and + * vblSeq values so that higher level code can calculate + * a new msc value or msc target for a WaitMSC call. The new value + * will be: + * msc = msc_base + get_vblank_count() - vblank_base; + * + * And for waiting on a value, core code will use: + * actual_target = target_msc - msc_base + vblank_base; + */ + /*@{*/ + int64_t vblank_base; + int64_t msc_base; + /*@}*/ + + /** * 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 3b5acfecb12..05964404632 100644 --- a/src/mesa/drivers/dri/common/vblank.c +++ b/src/mesa/drivers/dri/common/vblank.c @@ -35,6 +35,16 @@ #include "vblank.h" #include "xmlpool.h" +static unsigned int msc_to_vblank(__DRIdrawablePrivate * 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) +{ + return (int64_t)(vblank - dPriv->vblank_base + dPriv->msc_base); +} + /****************************************************************************/ /** @@ -42,7 +52,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 +60,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 +76,46 @@ 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) { + *count = vblank_to_msc(dPriv, vbl.reply.sequence); + } else { + /* Old driver (no knowledge of drawable MSC callback) */ + *count = vbl.reply.sequence; + } 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); +} /****************************************************************************/ /** @@ -123,7 +169,9 @@ int driWaitForMSC32( __DRIdrawablePrivate *priv, */ vbl.request.type = dont_wait ? DRM_VBLANK_RELATIVE : DRM_VBLANK_ABSOLUTE; - vbl.request.sequence = next; + vbl.request.sequence = next ? msc_to_vblank(priv, next) : 0; + 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. @@ -131,8 +179,10 @@ int driWaitForMSC32( __DRIdrawablePrivate *priv, return GLX_BAD_CONTEXT; } + *msc = vblank_to_msc(priv, vbl.reply.sequence); + dont_wait = 0; - if (target_msc != 0 && vbl.reply.sequence == target) + if (target_msc != 0 && *msc == target) break; /* Assuming the wait-done test fails, the next refresh to wait for @@ -142,9 +192,9 @@ 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 = (vbl.reply.sequence % (unsigned int)divisor); - next = (vbl.reply.sequence - r + (unsigned int)remainder); - if (next <= vbl.reply.sequence) next += (unsigned int)divisor; + r = (*msc % (unsigned int)divisor); + next = (*msc - r + (unsigned int)remainder); + if (next <= *msc) next += (unsigned int)divisor; } while ( r != (unsigned int)remainder ); } @@ -154,7 +204,10 @@ int driWaitForMSC32( __DRIdrawablePrivate *priv, */ vbl.request.type = DRM_VBLANK_ABSOLUTE; - vbl.request.sequence = target_msc; + vbl.request.sequence = target_msc ? msc_to_vblank(priv, target_msc) : 0; + + 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,8 +216,8 @@ int driWaitForMSC32( __DRIdrawablePrivate *priv, } } - *msc = (target_msc & 0xffffffff00000000LL); - *msc |= vbl.reply.sequence; + *msc = vblank_to_msc(priv, vbl.reply.sequence); + if ( *msc < target_msc ) { *msc += 0x0000000100000000LL; } @@ -252,16 +305,21 @@ 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->vblank_base = priv->vblSeq; + + 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 ec83adc78dd..e8550b28124 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, |