[gtk/wip/otte/diff: 2/2] rendernode: Limit diff region




commit 20dcc31d19fcb544b4d830c2c99ced6828888a86
Author: Benjamin Otte <otte redhat com>
Date:   Mon Dec 20 18:40:02 2021 +0100

    rendernode: Limit diff region
    
    Limit the diff region to 30 rectangles (randomly chosen because it
    looked big enough to not trigger by accident and small enough to not
    cause performance issues).
    
    If the diff region gets more complicated, we abort to the parent node
    and use its bounds as the diff region instead and then continue diffing
    the rest of the node tree.
    
    Fixes: #4560
    Fixes: #2396

 gsk/gskrendernodeimpl.c | 10 ++++++++++
 1 file changed, 10 insertions(+)
---
diff --git a/gsk/gskrendernodeimpl.c b/gsk/gskrendernodeimpl.c
index 24bf09baac..dca0bbe585 100644
--- a/gsk/gskrendernodeimpl.c
+++ b/gsk/gskrendernodeimpl.c
@@ -33,6 +33,12 @@
 
 #include <hb-ot.h>
 
+/* maximal number of rectangles we keep in a diff region before we throw
+ * the towel and just use the bounding box of the parent node.
+ * Meant to avoid performance corner cases.
+ */
+#define MAX_RECTS_IN_DIFF 30
+
 static inline void
 gsk_cairo_rectangle (cairo_t               *cr,
                      const graphene_rect_t *rect)
@@ -2611,6 +2617,8 @@ static GskDiffResult
 gsk_container_node_keep_func (gconstpointer elem1, gconstpointer elem2, gpointer data)
 {
   gsk_render_node_diff ((GskRenderNode *) elem1, (GskRenderNode *) elem2, data);
+  if (cairo_region_num_rectangles (data) > MAX_RECTS_IN_DIFF)
+    return GSK_DIFF_ABORTED;
 
   return GSK_DIFF_OK;
 }
@@ -2624,6 +2632,8 @@ gsk_container_node_change_func (gconstpointer elem, gsize idx, gpointer data)
 
   rectangle_init_from_graphene (&rect, &node->bounds);
   cairo_region_union_rectangle (region, &rect);
+  if (cairo_region_num_rectangles (region) > MAX_RECTS_IN_DIFF)
+    return GSK_DIFF_ABORTED;
 
   return GSK_DIFF_OK;
 }


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]