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

Keith Packard keithp at keithp.com
Mon May 5 15:02:19 PDT 2014


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;
+
+    pts = points = malloc (sizeof (DDXPointRec) * nspans + sizeof(int) * nspans);
+    if (!points)
+        return;
+    wids = widths = (int *) (points + nspans);
 
     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);
+    free (points);
 }
-- 
2.0.0.rc0



More information about the xorg-devel mailing list