summaryrefslogtreecommitdiffstats
path: root/src/mesa/drivers/dri/common/vblank.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mesa/drivers/dri/common/vblank.c')
-rw-r--r--src/mesa/drivers/dri/common/vblank.c159
1 files changed, 59 insertions, 100 deletions
diff --git a/src/mesa/drivers/dri/common/vblank.c b/src/mesa/drivers/dri/common/vblank.c
index 0008ab1c34a..094950d3626 100644
--- a/src/mesa/drivers/dri/common/vblank.c
+++ b/src/mesa/drivers/dri/common/vblank.c
@@ -34,16 +34,6 @@
#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);
-}
-
/****************************************************************************/
/**
@@ -51,7 +41,7 @@ static int64_t vblank_to_msc(__DRIdrawablePrivate * dPriv, unsigned int vblank)
*
* 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 for a given drawable.
+ * 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
@@ -59,14 +49,11 @@ static int64_t vblank_to_msc(__DRIdrawablePrivate * dPriv, unsigned int vblank)
* 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 driDrawableGetMSC32( __DRIscreenPrivate * priv,
- __DRIdrawablePrivate * dPriv,
- int64_t * count)
+int driGetMSC32( __DRIscreenPrivate * priv, int64_t * count )
{
drmVBlank vbl;
int ret;
@@ -75,21 +62,14 @@ int driDrawableGetMSC32( __DRIscreenPrivate * priv,
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 );
-
- if (dPriv) {
- *count = vblank_to_msc(dPriv, vbl.reply.sequence);
- } else {
- /* Old driver (no knowledge of drawable MSC callback) */
- *count = vbl.reply.sequence;
- }
+ *count = (int64_t)vbl.reply.sequence;
return ret;
}
+
/****************************************************************************/
/**
* Wait for a specified refresh count. This implements most of the
@@ -142,9 +122,7 @@ int driWaitForMSC32( __DRIdrawablePrivate *priv,
*/
vbl.request.type = dont_wait ? DRM_VBLANK_RELATIVE :
DRM_VBLANK_ABSOLUTE;
- vbl.request.sequence = next ? msc_to_vblank(priv, next) : 0;
- if ( priv->vblFlags & VBLANK_FLAG_SECONDARY )
- vbl.request.type |= DRM_VBLANK_SECONDARY;
+ vbl.request.sequence = next;
if ( drmWaitVBlank( priv->driScreenPriv->fd, &vbl ) != 0 ) {
/* FIXME: This doesn't seem like the right thing to return here.
@@ -152,10 +130,8 @@ int driWaitForMSC32( __DRIdrawablePrivate *priv,
return GLX_BAD_CONTEXT;
}
- *msc = vblank_to_msc(priv, vbl.reply.sequence);
-
dont_wait = 0;
- if (target_msc != 0 && *msc == target)
+ if (target_msc != 0 && vbl.reply.sequence == target)
break;
/* Assuming the wait-done test fails, the next refresh to wait for
@@ -165,9 +141,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 = (*msc % (unsigned int)divisor);
- next = (*msc - r + (unsigned int)remainder);
- if (next <= *msc) next += (unsigned int)divisor;
+ r = (vbl.reply.sequence % (unsigned int)divisor);
+ next = (vbl.reply.sequence - r + (unsigned int)remainder);
+ if (next <= vbl.reply.sequence) next += (unsigned int)divisor;
} while ( r != (unsigned int)remainder );
}
@@ -177,10 +153,7 @@ int driWaitForMSC32( __DRIdrawablePrivate *priv,
*/
vbl.request.type = DRM_VBLANK_ABSOLUTE;
- vbl.request.sequence = target_msc ? msc_to_vblank(priv, target_msc) : 0;
-
- if ( priv->vblFlags & VBLANK_FLAG_SECONDARY )
- vbl.request.type |= DRM_VBLANK_SECONDARY;
+ vbl.request.sequence = target_msc;
if ( drmWaitVBlank( priv->driScreenPriv->fd, &vbl ) != 0 ) {
/* FIXME: This doesn't seem like the right thing to return here.
@@ -189,8 +162,8 @@ int driWaitForMSC32( __DRIdrawablePrivate *priv,
}
}
- *msc = vblank_to_msc(priv, vbl.reply.sequence);
-
+ *msc = (target_msc & 0xffffffff00000000LL);
+ *msc |= vbl.reply.sequence;
if ( *msc < target_msc ) {
*msc += 0x0000000100000000LL;
}
@@ -259,8 +232,8 @@ static int do_wait( drmVBlank * vbl, GLuint * vbl_seq, int fd )
if ( first_time ) {
fprintf(stderr,
"%s: drmWaitVBlank returned %d, IRQs don't seem to be"
- " working correctly.\nTry adjusting the vblank_mode"
- " configuration parameter.\n", __FUNCTION__, ret);
+ " working correctly.\nTry running with LIBGL_THROTTLE_REFRESH"
+ " and LIBL_SYNC_REFRESH unset.\n", __FUNCTION__, ret);
first_time = GL_FALSE;
}
@@ -274,42 +247,20 @@ static int do_wait( drmVBlank * vbl, GLuint * vbl_seq, int fd )
/****************************************************************************/
/**
- * Returns the default swap interval of the given drawable.
- */
-
-static unsigned
-driGetDefaultVBlankInterval( const __DRIdrawablePrivate *priv )
-{
- if ( (priv->vblFlags & (VBLANK_FLAG_THROTTLE | VBLANK_FLAG_SYNC)) != 0 ) {
- return 1;
- }
- else {
- return 0;
- }
-}
-
-
-/****************************************************************************/
-/**
* Sets the default swap interval when the drawable is first bound to a
* direct rendering context.
*/
-void driDrawableInitVBlank( __DRIdrawablePrivate *priv )
+void driDrawableInitVBlank( __DRIdrawablePrivate *priv, GLuint flags,
+ GLuint *vbl_seq )
{
- if ( priv->swap_interval == (unsigned)-1 &&
- !( priv->vblFlags & VBLANK_FLAG_NO_IRQ ) ) {
+ if ( priv->pdraw->swap_interval == (unsigned)-1 ) {
/* Get current vertical blank sequence */
- 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 = driGetDefaultVBlankInterval( priv );
+ drmVBlank vbl = { .request={ .type = DRM_VBLANK_RELATIVE, .sequence = 0 } };
+ do_wait( &vbl, vbl_seq, priv->driScreenPriv->fd );
+
+ priv->pdraw->swap_interval = (flags & (VBLANK_FLAG_THROTTLE |
+ VBLANK_FLAG_SYNC)) != 0 ? 1 : 0;
}
}
@@ -320,17 +271,21 @@ void driDrawableInitVBlank( __DRIdrawablePrivate *priv )
*/
unsigned
-driGetVBlankInterval( const __DRIdrawablePrivate *priv )
+driGetVBlankInterval( const __DRIdrawablePrivate *priv, GLuint flags )
{
- if ( (priv->vblFlags & VBLANK_FLAG_INTERVAL) != 0 ) {
+ if ( (flags & VBLANK_FLAG_INTERVAL) != 0 ) {
/* this must have been initialized when the drawable was first bound
* to a direct rendering context. */
- assert ( priv->swap_interval != (unsigned)-1 );
+ assert ( priv->pdraw->swap_interval != (unsigned)-1 );
- return priv->swap_interval;
+ return priv->pdraw->swap_interval;
+ }
+ else if ( (flags & (VBLANK_FLAG_THROTTLE | VBLANK_FLAG_SYNC)) != 0 ) {
+ return 1;
+ }
+ else {
+ return 0;
}
- else
- return driGetDefaultVBlankInterval( priv );
}
@@ -340,17 +295,18 @@ driGetVBlankInterval( const __DRIdrawablePrivate *priv )
*/
void
-driGetCurrentVBlank( __DRIdrawablePrivate *priv )
+driGetCurrentVBlank( const __DRIdrawablePrivate *priv, GLuint flags,
+ GLuint *vbl_seq )
{
drmVBlank vbl;
vbl.request.type = DRM_VBLANK_RELATIVE;
- if ( priv->vblFlags & VBLANK_FLAG_SECONDARY ) {
+ if ( flags & VBLANK_FLAG_SECONDARY ) {
vbl.request.type |= DRM_VBLANK_SECONDARY;
}
vbl.request.sequence = 0;
- (void) do_wait( &vbl, &priv->vblSeq, priv->driScreenPriv->fd );
+ (void) do_wait( &vbl, vbl_seq, priv->driScreenPriv->fd );
}
@@ -358,15 +314,19 @@ driGetCurrentVBlank( __DRIdrawablePrivate *priv )
/**
* Waits for the vertical blank for use with glXSwapBuffers.
*
+ * \param vbl_seq Vertical blank sequence number (MSC) after the last buffer
+ * swap. Updated after this wait.
+ * \param flags \c VBLANK_FLAG bits that control how long to wait.
* \param missed_deadline Set to \c GL_TRUE if the MSC after waiting is later
- * than the "target" based on \c priv->vblFlags. The idea is
- * that if \c missed_deadline is set, then the application is
- * not achieving its desired framerate.
+ * than the "target" based on \c flags. The idea is that if
+ * \c missed_deadline is set, then the application is not
+ * achieving its desired framerate.
* \return Zero on success, -1 on error.
*/
int
-driWaitForVBlank( __DRIdrawablePrivate *priv, GLboolean * missed_deadline )
+driWaitForVBlank( const __DRIdrawablePrivate *priv, GLuint * vbl_seq,
+ GLuint flags, GLboolean * missed_deadline )
{
drmVBlank vbl;
unsigned original_seq;
@@ -375,10 +335,10 @@ driWaitForVBlank( __DRIdrawablePrivate *priv, GLboolean * missed_deadline )
unsigned diff;
*missed_deadline = GL_FALSE;
- if ( (priv->vblFlags & (VBLANK_FLAG_INTERVAL |
- VBLANK_FLAG_THROTTLE |
- VBLANK_FLAG_SYNC)) == 0 ||
- (priv->vblFlags & VBLANK_FLAG_NO_IRQ) != 0 ) {
+ if ( (flags & (VBLANK_FLAG_INTERVAL |
+ VBLANK_FLAG_THROTTLE |
+ VBLANK_FLAG_SYNC)) == 0 ||
+ (flags & VBLANK_FLAG_NO_IRQ) != 0 ) {
return 0;
}
@@ -389,45 +349,44 @@ driWaitForVBlank( __DRIdrawablePrivate *priv, GLboolean * missed_deadline )
*
* VBLANK_FLAG_INTERVAL and VBLANK_FLAG_THROTTLE mean to wait for at
* least one vertical blank since the last wait. Since do_wait modifies
- * priv->vblSeq, we have to save the original value of priv->vblSeq for the
+ * vbl_seq, we have to save the original value of vbl_seq for the
* VBLANK_FLAG_INTERVAL / VBLANK_FLAG_THROTTLE calculation later.
*/
- original_seq = priv->vblSeq;
- interval = driGetVBlankInterval(priv);
+ original_seq = *vbl_seq;
+ interval = driGetVBlankInterval(priv, flags);
deadline = original_seq + interval;
vbl.request.type = DRM_VBLANK_RELATIVE;
- if ( priv->vblFlags & VBLANK_FLAG_SECONDARY ) {
+ if ( flags & VBLANK_FLAG_SECONDARY ) {
vbl.request.type |= DRM_VBLANK_SECONDARY;
}
- vbl.request.sequence = ((priv->vblFlags & VBLANK_FLAG_SYNC) != 0) ? 1 : 0;
+ vbl.request.sequence = ((flags & VBLANK_FLAG_SYNC) != 0) ? 1 : 0;
- if ( do_wait( & vbl, &priv->vblSeq, priv->driScreenPriv->fd ) != 0 ) {
+ if ( do_wait( & vbl, vbl_seq, priv->driScreenPriv->fd ) != 0 ) {
return -1;
}
- diff = priv->vblSeq - deadline;
+ diff = *vbl_seq - deadline;
/* No need to wait again if we've already reached the target */
if (diff <= (1 << 23)) {
- *missed_deadline = (priv->vblFlags & VBLANK_FLAG_SYNC) ? (diff > 0) :
- GL_TRUE;
+ *missed_deadline = (flags & VBLANK_FLAG_SYNC) ? (diff > 0) : GL_TRUE;
return 0;
}
/* Wait until the target vertical blank. */
vbl.request.type = DRM_VBLANK_ABSOLUTE;
- if ( priv->vblFlags & VBLANK_FLAG_SECONDARY ) {
+ if ( flags & VBLANK_FLAG_SECONDARY ) {
vbl.request.type |= DRM_VBLANK_SECONDARY;
}
vbl.request.sequence = deadline;
- if ( do_wait( & vbl, &priv->vblSeq, priv->driScreenPriv->fd ) != 0 ) {
+ if ( do_wait( & vbl, vbl_seq, priv->driScreenPriv->fd ) != 0 ) {
return -1;
}
- diff = priv->vblSeq - deadline;
+ diff = *vbl_seq - deadline;
*missed_deadline = diff > 0 && diff <= (1 << 23);
return 0;