summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/gallium/state_trackers/glx/xlib/xm_api.c32
-rw-r--r--src/gallium/state_trackers/glx/xlib/xm_api.h2
-rw-r--r--src/gallium/state_trackers/glx/xlib/xm_st.c12
3 files changed, 42 insertions, 4 deletions
diff --git a/src/gallium/state_trackers/glx/xlib/xm_api.c b/src/gallium/state_trackers/glx/xlib/xm_api.c
index 2fc400b3fc..894ed548ee 100644
--- a/src/gallium/state_trackers/glx/xlib/xm_api.c
+++ b/src/gallium/state_trackers/glx/xlib/xm_api.c
@@ -72,10 +72,35 @@
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
diff --git a/src/gallium/state_trackers/glx/xlib/xm_api.h b/src/gallium/state_trackers/glx/xlib/xm_api.h
index 4f2c8a6e6a..934c749450 100644
--- a/src/gallium/state_trackers/glx/xlib/xm_api.h
+++ b/src/gallium/state_trackers/glx/xlib/xm_api.h
@@ -378,6 +378,6 @@ xmesa_buffer_height(XMesaBuffer b)
return b->height;
}
-
+extern boolean xmesa_strict_invalidate;
#endif
diff --git a/src/gallium/state_trackers/glx/xlib/xm_st.c b/src/gallium/state_trackers/glx/xlib/xm_st.c
index 9cd744c3a6..873d5b6603 100644
--- a/src/gallium/state_trackers/glx/xlib/xm_st.c
+++ b/src/gallium/state_trackers/glx/xlib/xm_st.c
@@ -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);
}
}