[Pixman] [PATCH 3/4] Speed up pixman_region{, 32}_contains_rectangle()

Andrea Canciani ranma42 at gmail.com
Thu Aug 4 00:00:22 PDT 2011


On Thu, Aug 4, 2011 at 4:21 AM, Søren Sandmann <sandmann at cs.au.dk> wrote:
> 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 */

If this test is not needed anymore, I think it should be deleted,
otherwise the documentation of find_box_for_y should be modified.

The same objection applies to patch 4/4.

Again, some trailing whitespace (both in 3/4 and in 4/4).

Andrea

>
> --
> 1.7.4
>
> _______________________________________________
> Pixman mailing list
> Pixman at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/pixman
>


More information about the Pixman mailing list