[PATCH xserver] glamor: Use GL_MESA_tile_raster_order for overlapping blits.

Eric Anholt eric at anholt.net
Tue Oct 10 18:19:22 UTC 2017


Improves Raspberry Pi 3 x11perf -copywinwin100 from ~4700/sec to
~5130/sec.

Signed-off-by: Eric Anholt <eric at anholt.net>
---
 glamor/glamor.c      |  2 ++
 glamor/glamor_copy.c | 74 ++++++++++++++++++++++++++++++++++------------------
 glamor/glamor_priv.h |  1 +
 3 files changed, 52 insertions(+), 25 deletions(-)

diff --git a/glamor/glamor.c b/glamor/glamor.c
index 91236e29ce67..d06934595713 100644
--- a/glamor/glamor.c
+++ b/glamor/glamor.c
@@ -601,6 +601,8 @@ glamor_init(ScreenPtr screen, unsigned int flags)
         epoxy_has_gl_extension("GL_EXT_map_buffer_range");
     glamor_priv->has_buffer_storage =
         epoxy_has_gl_extension("GL_ARB_buffer_storage");
+    glamor_priv->has_mesa_tile_raster_order =
+        epoxy_has_gl_extension("GL_MESA_tile_raster_order");
     glamor_priv->has_nv_texture_barrier =
         epoxy_has_gl_extension("GL_NV_texture_barrier");
     glamor_priv->has_unpack_subimage =
diff --git a/glamor/glamor_copy.c b/glamor/glamor_copy.c
index cbaf06dddcd9..bd4a0e20f250 100644
--- a/glamor/glamor_copy.c
+++ b/glamor/glamor_copy.c
@@ -317,6 +317,13 @@ bail:
     return FALSE;
 }
 
+/* Include the enums here for the moment, to keep from needing to bump epoxy. */
+#ifndef GL_TILE_RASTER_ORDER_FIXED_MESA
+#define GL_TILE_RASTER_ORDER_FIXED_MESA          0x8BB8
+#define GL_TILE_RASTER_ORDER_INCREASING_X_MESA   0x8BB9
+#define GL_TILE_RASTER_ORDER_INCREASING_Y_MESA   0x8BBA
+#endif
+
 /*
  * Copy from GPU to GPU by using the source
  * as a texture and painting that into the destination
@@ -388,6 +395,18 @@ glamor_copy_fbo_fbo_draw(DrawablePtr src,
 
     v = glamor_get_vbo_space(dst->pScreen, nbox * 8 * sizeof (int16_t), &vbo_offset);
 
+    if (src_pixmap == dst_pixmap && glamor_priv->has_mesa_tile_raster_order) {
+        glEnable(GL_TILE_RASTER_ORDER_FIXED_MESA);
+        if (dx >= 0)
+            glEnable(GL_TILE_RASTER_ORDER_INCREASING_X_MESA);
+        else
+            glDisable(GL_TILE_RASTER_ORDER_INCREASING_X_MESA);
+        if (dy >= 0)
+            glEnable(GL_TILE_RASTER_ORDER_INCREASING_Y_MESA);
+        else
+            glDisable(GL_TILE_RASTER_ORDER_INCREASING_Y_MESA);
+    }
+
     glEnableVertexAttribArray(GLAMOR_VERTEX_POS);
     glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_SHORT, GL_FALSE,
                           2 * sizeof (GLshort), vbo_offset);
@@ -451,6 +470,9 @@ glamor_copy_fbo_fbo_draw(DrawablePtr src,
     ret = TRUE;
 
 bail_ctx:
+    if (src_pixmap == dst_pixmap && glamor_priv->has_mesa_tile_raster_order) {
+        glDisable(GL_TILE_RASTER_ORDER_FIXED_MESA);
+    }
     glDisable(GL_SCISSOR_TEST);
     glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
 
@@ -611,34 +633,36 @@ glamor_copy_needs_temp(DrawablePtr src,
     if (!glamor_priv->has_nv_texture_barrier)
         return TRUE;
 
-    glamor_get_drawable_deltas(src, src_pixmap, &src_off_x, &src_off_y);
-    glamor_get_drawable_deltas(dst, dst_pixmap, &dst_off_x, &dst_off_y);
-
-    bounds = box[0];
-    for (n = 1; n < nbox; n++) {
-        bounds.x1 = min(bounds.x1, box[n].x1);
-        bounds.y1 = min(bounds.y1, box[n].y1);
+    if (!glamor_priv->has_mesa_tile_raster_order) {
+        glamor_get_drawable_deltas(src, src_pixmap, &src_off_x, &src_off_y);
+        glamor_get_drawable_deltas(dst, dst_pixmap, &dst_off_x, &dst_off_y);
 
-        bounds.x2 = max(bounds.x2, box[n].x2);
-        bounds.y2 = max(bounds.y2, box[n].y2);
-    }
+        bounds = box[0];
+        for (n = 1; n < nbox; n++) {
+            bounds.x1 = min(bounds.x1, box[n].x1);
+            bounds.y1 = min(bounds.y1, box[n].y1);
 
-    /* Check to see if the pixmap-relative boxes overlap in both X and Y,
-     * in which case we can't rely on NV_texture_barrier and must
-     * make a temporary copy
-     *
-     *  dst.x1                     < src.x2 &&
-     *  src.x1                     < dst.x2 &&
-     *
-     *  dst.y1                     < src.y2 &&
-     *  src.y1                     < dst.y2
-     */
-    if (bounds.x1 + dst_off_x      < bounds.x2 + dx + src_off_x &&
-        bounds.x1 + dx + src_off_x < bounds.x2 + dst_off_x &&
+            bounds.x2 = max(bounds.x2, box[n].x2);
+            bounds.y2 = max(bounds.y2, box[n].y2);
+        }
 
-        bounds.y1 + dst_off_y      < bounds.y2 + dy + src_off_y &&
-        bounds.y1 + dy + src_off_y < bounds.y2 + dst_off_y) {
-        return TRUE;
+        /* Check to see if the pixmap-relative boxes overlap in both X and Y,
+         * in which case we can't rely on NV_texture_barrier and must
+         * make a temporary copy
+         *
+         *  dst.x1                     < src.x2 &&
+         *  src.x1                     < dst.x2 &&
+         *
+         *  dst.y1                     < src.y2 &&
+         *  src.y1                     < dst.y2
+         */
+        if (bounds.x1 + dst_off_x      < bounds.x2 + dx + src_off_x &&
+            bounds.x1 + dx + src_off_x < bounds.x2 + dst_off_x &&
+
+            bounds.y1 + dst_off_y      < bounds.y2 + dy + src_off_y &&
+            bounds.y1 + dy + src_off_y < bounds.y2 + dst_off_y) {
+            return TRUE;
+        }
     }
 
     glTextureBarrierNV();
diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h
index 07a98efeb467..7050df526203 100644
--- a/glamor/glamor_priv.h
+++ b/glamor/glamor_priv.h
@@ -192,6 +192,7 @@ typedef struct glamor_screen_private {
     Bool has_map_buffer_range;
     Bool has_buffer_storage;
     Bool has_khr_debug;
+    Bool has_mesa_tile_raster_order;
     Bool has_nv_texture_barrier;
     Bool has_pack_subimage;
     Bool has_unpack_subimage;
-- 
2.14.2



More information about the xorg-devel mailing list