glx/xlib: configurable strict/non-strict buffer size invalidate
authorKeith Whitwell <keithw@vmware.com>
Sun, 22 Aug 2010 13:14:55 +0000 (14:14 +0100)
committerKeith Whitwell <keithw@vmware.com>
Sun, 22 Aug 2010 13:49:17 +0000 (14:49 +0100)
Introduce a new configuration option XMESA_STRICT_INVALIDATE to switch
between swapbuffers-based and glViewport-based buffer invalidation.

Default strict invalidate to false, ie glViewport-based invalidation,
aka ST_MANAGER_BROKEN_INVALIDATE.

This means we will not call XGetGeometry after every swapbuffers,
which allows swapbuffers to remain asynchronous.  For apps running at
100fps with synchronous swapping, a 10% boost is typical.  For gears,
I see closer to 20% speedup.

Note that the work of copying data on swapbuffers doesn't disappear -
this change just allows the X server to execute the PutImage
asynchronously without us effectively blocked until its completion.

This applies even to llvmpipe's threaded rasterization as the
swapbuffers operation was a large part of the serial component of an
llvmpipe frame.

The downside of this is correctness - applications which don't call
glViewport on window resizes will get incorrect rendering, unless
XMESA_STRICT_INVALIDATE is set.

The ultimate solution would be to have per-frame but asynchronous
invalidation.  Xcb almost looks as if it could provide this, but the
API doesn't seem to quite be there.

src/gallium/state_trackers/glx/xlib/xm_api.c
src/gallium/state_trackers/glx/xlib/xm_api.h
src/gallium/state_trackers/glx/xlib/xm_st.c

index 2fc400b..894ed54 100644 (file)
 static struct xm_driver driver;
 static struct st_api *stapi;
 
+/* Default strict invalidate to false.  This means we will not call
+ * XGetGeometry after every swapbuffers, which allows swapbuffers to
+ * remain asynchronous.  For apps running at 100fps with synchronous
+ * swapping, a 10% boost is typical.  For gears, I see closer to 20%
+ * speedup.
+ *
+ * Note that the work of copying data on swapbuffers doesn't disappear
+ * - this change just allows the X server to execute the PutImage
+ * asynchronously without us effectively blocked until its completion.
+ *
+ * This speeds up even llvmpipe's threaded rasterization as the
+ * swapbuffers operation was a large part of the serial component of
+ * an llvmpipe frame.
+ *
+ * The downside of this is correctness - applications which don't call
+ * glViewport on window resizes will get incorrect rendering.  A
+ * better solution would be to have per-frame but asynchronous
+ * invalidation.  Xcb almost looks as if it could provide this, but
+ * the API doesn't seem to quite be there.
+ */
+boolean xmesa_strict_invalidate = FALSE;
+
 void xmesa_set_driver( const struct xm_driver *templ )
 {
    driver = *templ;
    stapi = driver.create_st_api();
+
+   xmesa_strict_invalidate =
+      debug_get_bool_option("XMESA_STRICT_INVALIDATE", FALSE);
 }
 
 
@@ -91,7 +116,12 @@ static int
 xmesa_get_param(struct st_manager *smapi,
                 enum st_manager_param param)
 {
-   return 0;
+   switch(param) {
+   case ST_MANAGER_BROKEN_INVALIDATE:
+      return !xmesa_strict_invalidate;
+   default:
+      return 0;
+   }
 }
 
 static XMesaDisplay
index 4f2c8a6..934c749 100644 (file)
@@ -378,6 +378,6 @@ xmesa_buffer_height(XMesaBuffer b)
    return b->height;
 }
 
-
+extern boolean xmesa_strict_invalidate;
 
 #endif
index 9cd744c..873d5b6 100644 (file)
@@ -211,6 +211,12 @@ xmesa_st_framebuffer_validate(struct st_framebuffer_iface *stfbi,
    /* record newly allocated textures */
    new_mask = statt_mask & ~xstfb->texture_mask;
 
+   /* If xmesa_strict_invalidate is not set, we will not yet have
+    * called XGetGeometry().  Do so here:
+    */
+   if (!xmesa_strict_invalidate)
+      xmesa_check_buffer_size(xstfb->buffer);
+
    resized = (xstfb->buffer->width != xstfb->texture_width ||
               xstfb->buffer->height != xstfb->texture_height);
 
@@ -252,7 +258,8 @@ xmesa_st_framebuffer_flush_front(struct st_framebuffer_iface *stfbi,
    boolean ret;
 
    ret = xmesa_st_framebuffer_display(stfbi, statt);
-   if (ret)
+
+   if (ret && xmesa_strict_invalidate)
       xmesa_check_buffer_size(xstfb->buffer);
 
    return ret;
@@ -327,7 +334,8 @@ xmesa_swap_st_framebuffer(struct st_framebuffer_iface *stfbi)
          *back = tmp;
       }
 
-      xmesa_check_buffer_size(xstfb->buffer);
+      if (xmesa_strict_invalidate)
+        xmesa_check_buffer_size(xstfb->buffer);
    }
 }