[Pixman] [PATCH 3/4] Speed up pixman_region{, 32}_contains_rectangle()
Søren Sandmann
sandmann at cs.au.dk
Wed Aug 3 19:21:19 PDT 2011
From: Søren Sandmann Pedersen <ssp at redhat.com>
When someone selects some text in Firefox under a non-composited X
server and initiates a drag, a shaped window is created with a complex
shape corresponding to the outline of the text. Then, on every mouse
movement pixman_region_contains_rectangle() is called many times on
that complicated region. And pixman_region_contains_rectangle() is
doing a linear scan through the rectangles in the region, although the
scan does does when it finds the first box that can't possibly
intersect the passed-in rectangle.
This patch changes the loop so that it begins with a binary search for
the first box that could possibly overlap the passed-in rectangle.
The performance improvement for the text dragging case is easily
noticable.
---
pixman/pixman-region.c | 44 +++++++++++++++++++++++++++++++++++++++-----
1 files changed, 39 insertions(+), 5 deletions(-)
diff --git a/pixman/pixman-region.c b/pixman/pixman-region.c
index 142493b..a199405 100644
--- a/pixman/pixman-region.c
+++ b/pixman/pixman-region.c
@@ -2086,6 +2086,40 @@ PIXMAN_EXPORT PREFIX (_inverse) (region_type_t *new_reg, /* Destination region
return TRUE;
}
+/* In time O(log n), locate the first box whose y2 is greater than y.
+ * Return @end if no such box exists.
+ */
+static box_type_t *
+find_box_for_y (box_type_t *begin, box_type_t *end, int y)
+{
+ box_type_t *mid;
+
+ if (end == begin)
+ return end;
+
+ if (end - begin == 1)
+ {
+ if (begin->y2 > y)
+ return begin;
+ else
+ return end;
+ }
+
+ mid = begin + (end - begin) / 2;
+ if (mid->y2 > y)
+ {
+ /* If no box is found in [begin, mid], the function
+ * will return @mid, which is then known to be the
+ * correct answer.
+ */
+ return find_box_for_y (begin, mid, y);
+ }
+ else
+ {
+ return find_box_for_y (mid, end, y);
+ }
+}
+
/*
* rect_in(region, rect)
* This routine takes a pointer to a region and a pointer to a box
@@ -2102,7 +2136,6 @@ PIXMAN_EXPORT PREFIX (_inverse) (region_type_t *new_reg, /* Destination region
* partially in the region) or is outside the region (we reached a band
* that doesn't overlap the box at all and part_in is false)
*/
-
pixman_region_overlap_t
PIXMAN_EXPORT PREFIX (_contains_rectangle) (region_type_t * region,
box_type_t * prect)
@@ -2137,12 +2170,13 @@ PIXMAN_EXPORT PREFIX (_contains_rectangle) (region_type_t * region,
x = prect->x1;
y = prect->y1;
+ pbox = PIXREGION_BOXPTR (region);
+ pbox_end = pbox + numRects;
+
+ pbox = find_box_for_y (pbox, pbox_end, y);
/* can stop when both part_out and part_in are TRUE, or we reach prect->y2 */
- for (pbox = PIXREGION_BOXPTR (region), pbox_end = pbox + numRects;
- pbox != pbox_end;
- pbox++)
+ for (; pbox != pbox_end; pbox++)
{
-
if (pbox->y2 <= y)
continue; /* getting up to speed or skipping remainder of band */
--
1.7.4
More information about the Pixman
mailing list