intel: Throttle after doing copyregion/swapbuffers round trip
authorKristian Høgsberg <krh@bitplanet.net>
Wed, 19 May 2010 01:50:44 +0000 (21:50 -0400)
committerKristian Høgsberg <krh@bitplanet.net>
Thu, 20 May 2010 15:39:28 +0000 (11:39 -0400)
Before we would throttle in the flush callback prior to round-tripping
to the server to do copyregion or swapbuffer.  Now, instead just note
that we need to throttle and do it in intel_prepare_render(), which
will be called after receiving the response from the server but before
we start rendering the next frame.  Even if the server also throttles
us in swapbuffer, this just makes the throttling a no-op when we hit
intel_prepare_render().  With that we can drop the
using_dri2_swapbuffers hack and just always throttle.

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

index 9768b0deee77891b062ef3aae47377cce4a26b05..ca8e34483685dcf6992741371845ddaa23cffe48 100644 (file)
@@ -130,8 +130,7 @@ _intel_batchbuffer_flush(struct intel_batchbuffer *batch, const char *file,
    struct intel_context *intel = batch->intel;
    GLuint used = batch->ptr - batch->map;
 
-   if (!intel->using_dri2_swapbuffers &&
-       intel->first_post_swapbuffers_batch == NULL) {
+   if (intel->first_post_swapbuffers_batch == NULL) {
       intel->first_post_swapbuffers_batch = intel->batch->buf;
       drm_intel_bo_reference(intel->first_post_swapbuffers_batch);
    }
index a94f6886f981969c84c6d988cfc2dc5d8d3e1922..05d49986546727381de55163066e33bfc7343071 100644 (file)
@@ -440,6 +440,28 @@ intel_prepare_render(struct intel_context *intel)
     */
    if (intel->is_front_buffer_rendering)
       intel->front_buffer_dirty = GL_TRUE;
+
+   /* 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.
+    *
+    * We're using intelDRI2Flush (called from the loader before
+    * swapbuffer) and glFlush (for front buffer rendering) as the
+    * indicator that a frame is done and then throttle when we get
+    * here as we prepare to render the next frame.  At this point for
+    * round trips for swap/copy and getting new buffers are done and
+    * we'll spend less time waiting on the GPU.
+    *
+    * 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->need_throttle && intel->first_post_swapbuffers_batch) {
+      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;
+      intel->need_throttle = GL_FALSE;
+   }
 }
 
 static void
@@ -451,8 +473,7 @@ intel_viewport(GLcontext *ctx, GLint x, GLint y, GLsizei w, GLsizei h)
     if (intel->saved_viewport)
        intel->saved_viewport(ctx, x, y, w, h);
 
-    if (!intel->using_dri2_swapbuffers &&
-       !intel->meta.internal_viewport_call && ctx->DrawBuffer->Name == 0) {
+    if (!intel->meta.internal_viewport_call && ctx->DrawBuffer->Name == 0) {
        dri2InvalidateDrawable(driContext->driDrawablePriv);
        dri2InvalidateDrawable(driContext->driReadablePriv);
     }
@@ -530,27 +551,8 @@ intel_glFlush(GLcontext *ctx)
    struct intel_context *intel = intel_context(ctx);
 
    intel_flush(ctx);
-
    intel_flush_front(ctx);
-
-   /* 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->using_dri2_swapbuffers &&
-       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;
-   }
+   intel->need_throttle = GL_TRUE;
 }
 
 void
index dae5896a5cda65482fe64480201641bbe0ce1fd2..04d5fc92a251af35ac14dcefef0d1bf58dbcb038 100644 (file)
@@ -150,8 +150,8 @@ struct intel_context
 
    struct intel_batchbuffer *batch;
    drm_intel_bo *first_post_swapbuffers_batch;
+   GLboolean need_throttle;
    GLboolean no_batch_wrap;
-   GLboolean using_dri2_swapbuffers;
 
    struct
    {
index 3aed253e2407aa2a7b435ab4970386aec5bf7279..15a465c6402ae9b4bdb47a565251d554fd55e1fb 100644 (file)
@@ -110,23 +110,16 @@ intelDRI2Flush(__DRIdrawable *drawable)
    if (intel->gen < 4)
       INTEL_FIREVERTICES(intel);
 
+   intel->need_throttle = GL_TRUE;
+
    if (intel->batch->map != intel->batch->ptr)
       intel_batchbuffer_flush(intel->batch);
 }
 
-static void
-intelDRI2Invalidate(__DRIdrawable *drawable)
-{
-   struct intel_context *intel = drawable->driContextPriv->driverPrivate;
-
-   intel->using_dri2_swapbuffers = GL_TRUE;
-   dri2InvalidateDrawable(drawable);
-}
-
 static const struct __DRI2flushExtensionRec intelFlushExtension = {
     { __DRI2_FLUSH, __DRI2_FLUSH_VERSION },
     intelDRI2Flush,
-    intelDRI2Invalidate,
+    dri2InvalidateDrawable,
 };
 
 static __DRIimage *