intel: Use the new DRI2 flush invalidate entrypoint to signal frame done.
authorEric Anholt <eric@anholt.net>
Tue, 19 Jan 2010 18:55:21 +0000 (10:55 -0800)
committerEric Anholt <eric@anholt.net>
Tue, 19 Jan 2010 19:07:51 +0000 (11:07 -0800)
Previously for frame throttling we would wait on the first batch after
a swap before emitting another swap, because we had no hook after a
swap was emitted.  This meant that if an app managed to squeeze
everything it for a frame had into one batch, it would lock-step with
the GPU.  With the swapbuffers changes, we now have the entrypoint we
want.

This takes the WoW intro screen from 25% GPU idle and visibly jerky to
4-5% GPU idle and rather smooth.  Other apps such as OpenArena have
run into this problem as well.

src/mesa/drivers/dri/intel/intel_context.c
src/mesa/drivers/dri/intel/intel_screen.c

index 3f6634c..d52fe2e 100644 (file)
@@ -506,27 +506,7 @@ intelFlush(GLcontext * ctx)
 static void
 intel_glFlush(GLcontext *ctx)
 {
-   struct intel_context *intel = intel_context(ctx);
-
    intel_flush(ctx, GL_TRUE);
-
-   /* We're using glFlush as an indicator that a frame is done, which is
-    * what DRI2 does before calling SwapBuffers (and means we should catch
-    * people doing front-buffer rendering, as well)..
-    *
-    * Wait for the swapbuffers before the one we just emitted, so we don't
-    * get too many swaps outstanding for apps that are GPU-heavy but not
-    * CPU-heavy.
-    *
-    * Unfortunately, we don't have a handle to the batch containing the swap,
-    * and getting our hands on that doesn't seem worth it, so we just us the
-    * first batch we emitted after the last swap.
-    */
-   if (intel->first_post_swapbuffers_batch != NULL) {
-      drm_intel_bo_wait_rendering(intel->first_post_swapbuffers_batch);
-      drm_intel_bo_unreference(intel->first_post_swapbuffers_batch);
-      intel->first_post_swapbuffers_batch = NULL;
-   }
 }
 
 void
index e240957..6c2cb3b 100644 (file)
@@ -128,8 +128,29 @@ intelDRI2Flush(__DRIdrawable *drawable)
 static void
 intelDRI2FlushInvalidate(__DRIdrawable *drawable)
 {
+   struct intel_context *intel = drawable->driContextPriv->driverPrivate;
+
    intelDRI2Flush(drawable);
    drawable->validBuffers = GL_FALSE;
+
+   /* We're using FlushInvalidate as an indicator that a frame is
+    * done.  It's only called immediately after SwapBuffers, so it
+    * won't affect front-buffer rendering or applications explicitly
+    * managing swap regions using MESA_copy_buffer.
+    *
+    * Wait for the swapbuffers before the one we just emitted, so we don't
+    * get too many swaps outstanding for apps that are GPU-heavy but not
+    * CPU-heavy.
+    *
+    * Unfortunately, we don't have a handle to the batch containing the swap,
+    * and getting our hands on that doesn't seem worth it, so we just use the
+    * first batch we emitted after the last swap.
+    */
+   if (intel->first_post_swapbuffers_batch != NULL) {
+      drm_intel_bo_wait_rendering(intel->first_post_swapbuffers_batch);
+      drm_intel_bo_unreference(intel->first_post_swapbuffers_batch);
+      intel->first_post_swapbuffers_batch = NULL;
+   }
 }
 
 static const struct __DRI2flushExtensionRec intelFlushExtension = {