[PATCH xserver 1/3] glamor: Scissor rectangle drawing to the bounds of the rects.

Eric Anholt eric at anholt.net
Thu Aug 3 19:23:48 UTC 2017


Scissors provide a critical hint to tiled renderers as to what tiles
need to be load/stored because they could be modified by the
rendering.

The bounds calculation here is limited to when we have a small number
of rects (large enough to cover rounded window corners, but probably
not xeyes) to avoid overhead on desktop GL.

No performance difference on i965 with x11perf -rect1 -repeat 1 -reps
10000 (n=50)

v2: Clamp rectangle bounds addition.

Signed-off-by: Eric Anholt <eric at anholt.net>
---
 glamor/glamor_rects.c | 26 ++++++++++++++++++++++----
 glamor/glamor_utils.h | 35 +++++++++++++++++++++++++++++++++++
 2 files changed, 57 insertions(+), 4 deletions(-)

diff --git a/glamor/glamor_rects.c b/glamor/glamor_rects.c
index cc029c8c04a6..6cbb040c18ea 100644
--- a/glamor/glamor_rects.c
+++ b/glamor/glamor_rects.c
@@ -53,6 +53,7 @@ glamor_poly_fill_rect_gl(DrawablePtr drawable,
     char *vbo_offset;
     int box_index;
     Bool ret = FALSE;
+    BoxRec bounds = glamor_no_rendering_bounds();
 
     pixmap_priv = glamor_get_pixmap_private(pixmap);
     if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv))
@@ -60,6 +61,12 @@ glamor_poly_fill_rect_gl(DrawablePtr drawable,
 
     glamor_make_current(glamor_priv);
 
+    if (nrect < 100) {
+        bounds = glamor_start_rendering_bounds();
+        for (int i = 0; i < nrect; i++)
+            glamor_bounds_union_rect(&bounds, &prect[i]);
+    }
+
     if (glamor_priv->glsl_version >= 130) {
         prog = glamor_use_program_fill(pixmap, gc,
                                        &glamor_priv->poly_fill_rect_program,
@@ -121,11 +128,22 @@ glamor_poly_fill_rect_gl(DrawablePtr drawable,
             goto bail;
 
         while (nbox--) {
-            glScissor(box->x1 + off_x,
-                      box->y1 + off_y,
-                      box->x2 - box->x1,
-                      box->y2 - box->y1);
+            BoxRec scissor = {
+                .x1 = max(box->x1, bounds.x1 + drawable->x),
+                .y1 = max(box->y1, bounds.y1 + drawable->y),
+                .x2 = min(box->x2, bounds.x2 + drawable->x),
+                .y2 = min(box->y2, bounds.y2 + drawable->y),
+            };
+
             box++;
+
+            if (scissor.x1 >= scissor.x2 || scissor.y1 >= scissor.y2)
+                continue;
+
+            glScissor(scissor.x1 + off_x,
+                      scissor.y1 + off_y,
+                      scissor.x2 - scissor.x1,
+                      scissor.y2 - scissor.y1);
             if (glamor_priv->glsl_version >= 130)
                 glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, nrect);
             else {
diff --git a/glamor/glamor_utils.h b/glamor/glamor_utils.h
index a35917c37a16..f1f8f5633a1a 100644
--- a/glamor/glamor_utils.h
+++ b/glamor/glamor_utils.h
@@ -729,6 +729,41 @@ glamor_make_current(glamor_screen_private *glamor_priv)
     }
 }
 
+static inline BoxRec
+glamor_no_rendering_bounds(void)
+{
+    BoxRec bounds = {
+        .x1 = 0,
+        .y1 = 0,
+        .x2 = MAXSHORT,
+        .y2 = MAXSHORT,
+    };
+
+    return bounds;
+}
+
+static inline BoxRec
+glamor_start_rendering_bounds(void)
+{
+    BoxRec bounds = {
+        .x1 = MAXSHORT,
+        .y1 = MAXSHORT,
+        .x2 = 0,
+        .y2 = 0,
+    };
+
+    return bounds;
+}
+
+static inline void
+glamor_bounds_union_rect(BoxPtr bounds, xRectangle *rect)
+{
+    bounds->x1 = min(bounds->x1, rect->x);
+    bounds->y1 = min(bounds->y1, rect->y);
+    bounds->x2 = min(SHRT_MAX, max(bounds->x2, rect->x + rect->width));
+    bounds->y2 = min(SHRT_MAX, max(bounds->y2, rect->y + rect->height));
+}
+
 /**
  * Helper function for implementing draws with GL_QUADS on GLES2,
  * where we don't have them.
-- 
2.13.3



More information about the xorg-devel mailing list