add vblank support to i915 driver
authorDave Airlie <airliedfreedesktop.org>
Mon, 6 Feb 2006 00:09:58 +0000 (00:09 +0000)
committerDave Airlie <airliedfreedesktop.org>
Mon, 6 Feb 2006 00:09:58 +0000 (00:09 +0000)
src/mesa/drivers/dri/i915/intel_batchbuffer.c
src/mesa/drivers/dri/i915/intel_context.c
src/mesa/drivers/dri/i915/intel_context.h
src/mesa/drivers/dri/i915/intel_ioctl.c
src/mesa/drivers/dri/i915/intel_ioctl.h
src/mesa/drivers/dri/i915/intel_screen.c

index 323d0b2..508900d 100644 (file)
@@ -32,6 +32,7 @@
 #include "mtypes.h"
 #include "context.h"
 #include "enums.h"
+#include "vblank.h"
 
 #include "intel_reg.h"
 #include "intel_batchbuffer.h"
@@ -329,6 +330,38 @@ GLuint *intelEmitInlinePrimitiveLocked(intelContextPtr intel,
 }
 
 
+static void intelWaitForFrameCompletion( intelContextPtr intel )
+{
+  drm_i915_sarea_t *sarea = (drm_i915_sarea_t *)intel->sarea;
+
+   if (intel->do_irqs) {
+      if (intelGetLastFrame(intel) < sarea->last_dispatch) {
+        if (!intel->irqsEmitted) {
+           while (intelGetLastFrame (intel) < sarea->last_dispatch)
+              ;
+        }
+        else {
+           UNLOCK_HARDWARE( intel ); 
+           intelWaitIrq( intel, intel->alloc.irq_emitted );    
+           LOCK_HARDWARE( intel ); 
+        }
+        intel->irqsEmitted = 10;
+      }
+
+      if (intel->irqsEmitted) {
+        intelEmitIrqLocked( intel );
+        intel->irqsEmitted--;
+      }
+   } 
+   else {
+      while (intelGetLastFrame (intel) < sarea->last_dispatch) {
+        UNLOCK_HARDWARE( intel ); 
+        if (intel->do_usleeps) 
+           DO_USLEEP( 1 );
+        LOCK_HARDWARE( intel ); 
+      }
+   }
+}
 
 /*
  * Copy the back buffer to the front buffer. 
@@ -336,6 +369,8 @@ GLuint *intelEmitInlinePrimitiveLocked(intelContextPtr intel,
 void intelCopyBuffer( const __DRIdrawablePrivate *dPriv ) 
 {
    intelContextPtr intel;
+   GLboolean   missed_target;
+   int64_t ust;
 
    if (0)
       fprintf(stderr, "%s\n", __FUNCTION__);
@@ -347,6 +382,12 @@ void intelCopyBuffer( const __DRIdrawablePrivate *dPriv )
    intel = (intelContextPtr) dPriv->driContextPriv->driverPrivate;
 
    intelFlush( &intel->ctx );
+   
+   LOCK_HARDWARE( intel );
+   intelWaitForFrameCompletion( intel );
+   UNLOCK_HARDWARE( intel );
+   driWaitForVBlank( dPriv, &intel->vbl_seq, intel->vblank_flags, & missed_target );
+
    LOCK_HARDWARE( intel );
    {
       const intelScreenPrivate *intelScreen = intel->intelScreen;
@@ -412,6 +453,15 @@ void intelCopyBuffer( const __DRIdrawablePrivate *dPriv )
    }
    intelFlushBatchLocked( intel, GL_TRUE, GL_TRUE, GL_TRUE );
    UNLOCK_HARDWARE( intel );
+
+   intel->swap_count++;
+   (*dri_interface->getUST)(&ust);
+   if (missed_target) {
+     intel->swap_missed_count++;
+     intel->swap_missed_ust = ust -  intel->swap_ust;
+   }
+   
+   intel->swap_ust = ust;
 }
 
 
index 60b588e..c79ce96 100644 (file)
@@ -55,7 +55,9 @@
 #include "intel_ioctl.h"
 #include "intel_batchbuffer.h"
 
+#include "vblank.h"
 #include "utils.h"
+#include "xmlpool.h" /* for symbolic values of enum-type options */
 #ifndef INTEL_DEBUG
 int INTEL_DEBUG = (0);
 #endif
@@ -303,6 +305,7 @@ GLboolean intelInitContext( intelContextPtr intel,
    intelScreenPrivate *intelScreen = (intelScreenPrivate *)sPriv->private;
    drmI830Sarea *saPriv = (drmI830Sarea *)
       (((GLubyte *)sPriv->pSAREA)+intelScreen->sarea_priv_offset);
+   int fthrottle_mode;
 
    if (!_mesa_initialize_context(&intel->ctx,
                                 mesaVis, shareCtx, 
@@ -319,6 +322,9 @@ GLboolean intelInitContext( intelContextPtr intel,
    (void) memset( intel->texture_heaps, 0, sizeof( intel->texture_heaps ) );
    make_empty_list( & intel->swapped );
 
+   driParseConfigFiles (&intel->optionCache, &intelScreen->optionCache,
+                       intel->driScreen->myNum, "i915");
+
    ctx->Const.MaxTextureMaxAnisotropy = 2.0;
 
    ctx->Const.MinLineWidth = 1.0;
@@ -382,9 +388,19 @@ GLboolean intelInitContext( intelContextPtr intel,
 
    intel->RenderIndex = ~0;
 
+   fthrottle_mode = driQueryOptioni(&intel->optionCache, "fthrottle_mode");
+   intel->iw.irq_seq = -1;
+   intel->irqsEmitted = 0;
+
    intel->do_irqs = (intel->intelScreen->irq_active &&
-                    !getenv("INTEL_NO_IRQS"));
+                    fthrottle_mode == DRI_CONF_FTHROTTLE_IRQS);
+
+   intel->do_usleeps = (fthrottle_mode == DRI_CONF_FTHROTTLE_USLEEPS);
+
+   intel->vblank_flags = (intel->intelScreen->irq_active != 0)
+       ? driGetDefaultVBlankFlags(&intelScreen->optionCache) : VBLANK_FLAG_NO_IRQ;
 
+   (*dri_interface->getUST)(&intel->swap_ust);
    _math_matrix_ctr (&intel->ViewportMatrix);
 
    driInitExtensions( ctx, card_extensions, GL_TRUE );
@@ -581,6 +597,8 @@ GLboolean intelMakeCurrent(__DRIcontextPrivate *driContextPriv,
 
       if ( intel->driDrawable != driDrawPriv ) {
         /* Shouldn't the readbuffer be stored also? */
+        driDrawableInitVBlank( driDrawPriv, intel->vblank_flags );
+
         intel->driDrawable = driDrawPriv;
         intelWindowMoved( intel );
       }
@@ -809,3 +827,5 @@ void intelInitState( GLcontext *ctx )
 
    ctx->Driver.DrawBuffer( ctx, ctx->Color.DrawBuffer[0] );
 }
+
+
index b1c1757..2f362f9 100644 (file)
@@ -36,6 +36,7 @@
 #include "texmem.h"
 
 #include "intel_screen.h"
+#include "i915_drm.h"
 #include "i830_common.h"
 #include "tnl/t_vertex.h"
 
@@ -227,7 +228,11 @@ struct intel_context
 
    int dirtyAge;
    int perf_boxes;
+
+   GLuint do_usleeps;
    int do_irqs;
+   GLuint irqsEmitted;
+   drm_i915_irq_wait_t iw;
 
    GLboolean scissor;
    drm_clip_rect_t draw_rect;
@@ -246,6 +251,17 @@ struct intel_context
     * Configuration cache
     */
    driOptionCache optionCache;
+
+   /* VBI
+    */
+   GLuint vbl_seq;
+   GLuint vblank_flags;
+
+   int64_t swap_ust;
+   int64_t swap_missed_ust;
+
+   GLuint swap_count;
+   GLuint swap_missed_count;
 };
 
 
index 8834f87..82ad14c 100644 (file)
 #include "intel_batchbuffer.h"
 #include "drm.h"
 
+u_int32_t intelGetLastFrame (intelContextPtr intel) 
+{
+   int ret;
+   u_int32_t frame;
+   drm_i915_getparam_t gp;
+   
+   gp.param = I915_PARAM_LAST_DISPATCH;
+   gp.value = (int *)&frame;
+   ret = drmCommandWriteRead( intel->driFd, DRM_I915_GETPARAM,
+                             &gp, sizeof(gp) );
+   return frame;
+}
 
-
-static int intelEmitIrqLocked( intelContextPtr intel )
+int intelEmitIrqLocked( intelContextPtr intel )
 {
    drmI830IrqEmit ie;
    int ret, seq;
@@ -65,18 +76,17 @@ static int intelEmitIrqLocked( intelContextPtr intel )
    return seq;
 }
 
-static void intelWaitIrq( intelContextPtr intel, int seq )
+void intelWaitIrq( intelContextPtr intel, int seq )
 {
-   drmI830IrqWait iw;
    int ret;
       
    if (0)
       fprintf(stderr, "%s %d\n", __FUNCTION__, seq );
 
-   iw.irq_seq = seq;
+   intel->iw.irq_seq = seq;
         
    do {
-      ret = drmCommandWrite( intel->driFd, DRM_I830_IRQ_WAIT, &iw, sizeof(iw) );
+     ret = drmCommandWrite( intel->driFd, DRM_I830_IRQ_WAIT, &intel->iw, sizeof(intel->iw) );
    } while (ret == -EAGAIN || ret == -EINTR);
 
    if ( ret ) {
index 07b8a9c..099a7e1 100644 (file)
@@ -67,5 +67,7 @@ extern GLboolean intelIsAgpMemory( intelContextPtr intel, const GLvoid *pointer,
 
 extern GLuint intelAgpOffsetFromVirtual( intelContextPtr intel, const GLvoid *p );
 
-
+extern void intelWaitIrq( intelContextPtr intel, int seq );
+extern u_int32_t intelGetLastFrame (intelContextPtr intel);
+extern int intelEmitIrqLocked( intelContextPtr intel );
 #endif
index 66dfe34..ed8038e 100644 (file)
@@ -32,6 +32,7 @@
 #include "renderbuffer.h"
 #include "simple_list.h"
 #include "utils.h"
+#include "vblank.h"
 #include "xmlpool.h"
 
 
 
 PUBLIC const char __driConfigOptions[] =
 DRI_CONF_BEGIN
-   DRI_CONF_SECTION_PERFORMANCE
-      DRI_CONF_FORCE_S3TC_ENABLE(false)
-      DRI_CONF_ALLOW_LARGE_TEXTURES(1)
-   DRI_CONF_SECTION_END
+    DRI_CONF_SECTION_PERFORMANCE
+       DRI_CONF_FTHROTTLE_MODE(DRI_CONF_FTHROTTLE_IRQS) 
+       DRI_CONF_VBLANK_MODE(DRI_CONF_VBLANK_DEF_INTERVAL_0)
+    DRI_CONF_SECTION_END
+    DRI_CONF_SECTION_QUALITY
+       DRI_CONF_FORCE_S3TC_ENABLE(false)
+       DRI_CONF_ALLOW_LARGE_TEXTURES(1)
+      DRI_CONF_SECTION_END
 DRI_CONF_END;
-const GLuint __driNConfigOptions = 2;
+const GLuint __driNConfigOptions = 4;
 
 #ifdef USE_NEW_INTERFACE
 static PFNGLXCREATECONTEXTMODES create_context_modes = NULL;
@@ -330,6 +335,10 @@ static GLboolean intelInitDriver(__DRIscreenPrivate *sPriv)
    }
 
    if (glx_enable_extension != NULL) {
+      (*glx_enable_extension)( psc, "GLX_SGI_swap_control" );
+      (*glx_enable_extension)( psc, "GLX_SGI_video_sync" );
+      (*glx_enable_extension)( psc, "GLX_MESA_swap_control" );
+      (*glx_enable_extension)( psc, "GLX_MESA_swap_frame_usage" );
       (*glx_enable_extension)( psc, "GLX_SGI_make_current_read" );
       (*glx_enable_extension)( psc, "GLX_MESA_allocate_memory" );
    }
@@ -440,6 +449,33 @@ static void intelDestroyBuffer(__DRIdrawablePrivate *driDrawPriv)
 }
 
 
+/**
+ * Get information about previous buffer swaps.
+ */
+static int
+intelGetSwapInfo( __DRIdrawablePrivate *dPriv, __DRIswapInfo * sInfo )
+{
+   intelContextPtr intel;
+
+   if ( (dPriv == NULL) || (dPriv->driContextPriv == NULL)
+       || (dPriv->driContextPriv->driverPrivate == NULL)
+       || (sInfo == NULL) ) {
+      return -1;
+   }
+
+   intel = dPriv->driContextPriv->driverPrivate;
+   sInfo->swap_count = intel->swap_count;
+   sInfo->swap_ust = intel->swap_ust;
+   sInfo->swap_missed_count = intel->swap_missed_count;
+
+   sInfo->swap_missed_usage = (sInfo->swap_missed_count != 0)
+       ? driCalculateSwapUsage( dPriv, 0, intel->swap_missed_ust )
+       : 0.0;
+
+   return 0;
+}
+
+
 /* There are probably better ways to do this, such as an
  * init-designated function to register chipids and createcontext
  * functions.
@@ -494,9 +530,9 @@ static const struct __DriverAPIRec intelAPI = {
    .SwapBuffers     = intelSwapBuffers,
    .MakeCurrent     = intelMakeCurrent,
    .UnbindContext   = intelUnbindContext,
-   .GetSwapInfo     = NULL,
-   .GetMSC          = NULL,
-   .WaitForMSC      = NULL,
+   .GetSwapInfo     = intelGetSwapInfo,
+   .GetMSC          = driGetMSC32,
+   .WaitForMSC      = driWaitForMSC32,
    .WaitForSBC      = NULL,
    .SwapBuffersMSC  = NULL
 };