[PATCH 12/13] mi: Fill all spans for PolyFillArc at once

walter harms wharms at bfs.de
Tue May 6 04:21:01 PDT 2014



Am 06.05.2014 00:02, schrieb Keith Packard:
> This allocates span data for all of the provided arcs and draws the
> whole set in one call, rather than doing them one at a time. For
> modern hardware, this is a significant performance improvement.
> 
> Signed-off-by: Keith Packard <keithp at keithp.com>
> ---
>  mi/mifillarc.c | 98 ++++++++++++++++++++--------------------------------------
>  1 file changed, 34 insertions(+), 64 deletions(-)
> 
> diff --git a/mi/mifillarc.c b/mi/mifillarc.c
> index 337343d..1695121 100644
> --- a/mi/mifillarc.c
> +++ b/mi/mifillarc.c
> @@ -476,26 +476,16 @@ miFillArcSliceSetup(xArc * arc, miArcSliceRec * slice, GCPtr pGC)
>  	*wids++ = slw; \
>      }
>  
> -static void
> -miFillEllipseI(DrawablePtr pDraw, GCPtr pGC, xArc * arc)
> +static int
> +miFillEllipseI(DrawablePtr pDraw, GCPtr pGC, xArc * arc, DDXPointPtr points, int *widths)
>  {
>      int x, y, e;
>      int yk, xk, ym, xm, dx, dy, xorg, yorg;
>      int slw;
>      miFillArcRec info;
> -    DDXPointPtr points;
>      DDXPointPtr pts;
> -    int *widths;
>      int *wids;
>  
> -    points = malloc(sizeof(DDXPointRec) * arc->height);
> -    if (!points)
> -        return;
> -    widths = malloc(sizeof(int) * arc->height);
> -    if (!widths) {
> -        free(points);
> -        return;
> -    }
>      miFillArcSetup(arc, &info);
>      MIFILLARCSETUP();
>      if (pGC->miTranslate) {
> @@ -508,31 +498,19 @@ miFillEllipseI(DrawablePtr pDraw, GCPtr pGC, xArc * arc)
>          MIFILLARCSTEP(slw);
>          ADDSPANS();
>      }
> -    (*pGC->ops->FillSpans) (pDraw, pGC, pts - points, points, widths, FALSE);
> -    free(widths);
> -    free(points);
> +    return pts - points;
>  }
>  
> -static void
> -miFillEllipseD(DrawablePtr pDraw, GCPtr pGC, xArc * arc)
> +static int
> +miFillEllipseD(DrawablePtr pDraw, GCPtr pGC, xArc * arc, DDXPointPtr points, int *widths)
>  {
>      int x, y;
>      int xorg, yorg, dx, dy, slw;
>      double e, yk, xk, ym, xm;
>      miFillArcDRec info;
> -    DDXPointPtr points;
>      DDXPointPtr pts;
> -    int *widths;
>      int *wids;
>  
> -    points = malloc(sizeof(DDXPointRec) * arc->height);
> -    if (!points)
> -        return;
> -    widths = malloc(sizeof(int) * arc->height);
> -    if (!widths) {
> -        free(points);
> -        return;
> -    }
>      miFillArcDSetup(arc, &info);
>      MIFILLARCSETUP();
>      if (pGC->miTranslate) {
> @@ -545,9 +523,7 @@ miFillEllipseD(DrawablePtr pDraw, GCPtr pGC, xArc * arc)
>          MIFILLARCSTEP(slw);
>          ADDSPANS();
>      }
> -    (*pGC->ops->FillSpans) (pDraw, pGC, pts - points, points, widths, FALSE);
> -    free(widths);
> -    free(points);
> +    return pts - points;
>  }
>  
>  #define ADDSPAN(l,r) \
> @@ -572,17 +548,15 @@ miFillEllipseD(DrawablePtr pDraw, GCPtr pGC, xArc * arc)
>  	ADDSPAN(xl, xc); \
>      }
>  
> -static void
> -miFillArcSliceI(DrawablePtr pDraw, GCPtr pGC, xArc * arc)
> +static int
> +miFillArcSliceI(DrawablePtr pDraw, GCPtr pGC, xArc * arc, DDXPointPtr points, int *widths)
>  {
>      int yk, xk, ym, xm, dx, dy, xorg, yorg, slw;
>      int x, y, e;
>      miFillArcRec info;
>      miArcSliceRec slice;
>      int ya, xl, xr, xc;
> -    DDXPointPtr points;
>      DDXPointPtr pts;
> -    int *widths;
>      int *wids;
>  
>      miFillArcSetup(arc, &info);
> @@ -591,14 +565,6 @@ miFillArcSliceI(DrawablePtr pDraw, GCPtr pGC, xArc * arc)
>      slw = arc->height;
>      if (slice.flip_top || slice.flip_bot)
>          slw += (arc->height >> 1) + 1;
> -    points = malloc(sizeof(DDXPointRec) * slw);
> -    if (!points)
> -        return;
> -    widths = malloc(sizeof(int) * slw);
> -    if (!widths) {
> -        free(points);
> -        return;
> -    }
>      if (pGC->miTranslate) {
>          xorg += pDraw->x;
>          yorg += pDraw->y;
> @@ -622,13 +588,11 @@ miFillArcSliceI(DrawablePtr pDraw, GCPtr pGC, xArc * arc)
>              ADDSLICESPANS(slice.flip_bot);
>          }
>      }
> -    (*pGC->ops->FillSpans) (pDraw, pGC, pts - points, points, widths, FALSE);
> -    free(widths);
> -    free(points);
> +    return pts - points;
>  }
>  
> -static void
> -miFillArcSliceD(DrawablePtr pDraw, GCPtr pGC, xArc * arc)
> +static int
> +miFillArcSliceD(DrawablePtr pDraw, GCPtr pGC, xArc * arc, DDXPointPtr points, int *widths)
>  {
>      int x, y;
>      int dx, dy, xorg, yorg, slw;
> @@ -636,9 +600,7 @@ miFillArcSliceD(DrawablePtr pDraw, GCPtr pGC, xArc * arc)
>      miFillArcDRec info;
>      miArcSliceRec slice;
>      int ya, xl, xr, xc;
> -    DDXPointPtr points;
>      DDXPointPtr pts;
> -    int *widths;
>      int *wids;
>  
>      miFillArcDSetup(arc, &info);
> @@ -647,14 +609,6 @@ miFillArcSliceD(DrawablePtr pDraw, GCPtr pGC, xArc * arc)
>      slw = arc->height;
>      if (slice.flip_top || slice.flip_bot)
>          slw += (arc->height >> 1) + 1;
> -    points = malloc(sizeof(DDXPointRec) * slw);
> -    if (!points)
> -        return;
> -    widths = malloc(sizeof(int) * slw);
> -    if (!widths) {
> -        free(points);
> -        return;
> -    }
>      if (pGC->miTranslate) {
>          xorg += pDraw->x;
>          yorg += pDraw->y;
> @@ -678,9 +632,7 @@ miFillArcSliceD(DrawablePtr pDraw, GCPtr pGC, xArc * arc)
>              ADDSLICESPANS(slice.flip_bot);
>          }
>      }
> -    (*pGC->ops->FillSpans) (pDraw, pGC, pts - points, points, widths, FALSE);
> -    free(widths);
> -    free(points);
> +    return pts - points;
>  }
>  
>  /* MIPOLYFILLARC -- The public entry for the PolyFillArc request.
> @@ -692,21 +644,39 @@ miPolyFillArc(DrawablePtr pDraw, GCPtr pGC, int narcs, xArc * parcs)
>  {
>      int i;
>      xArc *arc;
> +    int nspans = 0;
> +    DDXPointPtr pts, points;
> +    int *wids, *widths;
> +    int n;
> +
> +    for (i = narcs, arc = parcs; --i >= 0; arc++)
> +        nspans += arc->height;

nitpicking, i would do it the other way around (i++),
i have learned that ppl are bad at reading that work that way.
(note: perhaps nspans could be unsigned to avoid fancy problems
with extreme large values.)


> +
> +    pts = points = malloc (sizeof (DDXPointRec) * nspans + sizeof(int) * nspans);
> +    if (!points)
> +        return;
> +    wids = widths = (int *) (points + nspans);


this looks like a case for calloc().


>  
>      for (i = narcs, arc = parcs; --i >= 0; arc++) {
>          if (miFillArcEmpty(arc))
>              continue;
>          if ((arc->angle2 >= FULLCIRCLE) || (arc->angle2 <= -FULLCIRCLE)) {
>              if (miCanFillArc(arc))
> -                miFillEllipseI(pDraw, pGC, arc);
> +                n = miFillEllipseI(pDraw, pGC, arc, pts, wids);
>              else
> -                miFillEllipseD(pDraw, pGC, arc);
> +                n = miFillEllipseD(pDraw, pGC, arc, pts, wids);
>          }
>          else {
>              if (miCanFillArc(arc))
> -                miFillArcSliceI(pDraw, pGC, arc);
> +                n = miFillArcSliceI(pDraw, pGC, arc, pts, wids);
>              else
> -                miFillArcSliceD(pDraw, pGC, arc);
> +                n = miFillArcSliceD(pDraw, pGC, arc, pts, wids);
>          }
> +        pts += n;
> +        wids += n;
>      }
> +    nspans = pts - points;
> +    if (nspans)
> +        (*pGC->ops->FillSpans) (pDraw, pGC, nspans, points, widths, FALSE);

IMHO FillSpans should should check nspans (note:no such checks otherwise).

just my 2 cents,
 wh

> +    free (points);
>  }


More information about the xorg-devel mailing list