xserver: Branch 'master' - 3 commits

Adam Jackson ajax at kemper.freedesktop.org
Thu Mar 2 17:50:26 UTC 2017


 mi/miarc.c |  426 ++++++++++++++++++++++++++++++-------------------------------
 1 file changed, 216 insertions(+), 210 deletions(-)

New commits:
commit 0d7f05ed99b71a4641415c9f26e245c3bb24a9a0
Author: Adam Jackson <ajax at redhat.com>
Date:   Wed Mar 1 16:13:59 2017 -0500

    miarc: "Cache" arc span data for dashed arcs
    
    This avoids recomputing the span data for every dash. x11perf thinks
    this is a pretty modest speedup:
    
        832919.4       840471.1 ( 1.009)   100-pixel dashed ellipse
        672353.1       680652.2 ( 1.012)   100-pixel double-dashed ellipse
         13748.9        24287.9 ( 1.767)   100-pixel wide dashed ellipse
          9236.3        21298.2 ( 2.306)   100-pixel wide double-dashed ellipse
    
    But part of the reason it's so modest there is that the arcs are
    relatively small (100 pixel diameter at line width 10, so ~6000 pixels)
    and the dashes relatively large (30 on 20 off so ~6 dashes per
    quadrant).
    
    With larger arcs and finer dashes this is much more impressive. A fairly
    trivial testcase of a single 15000x13000 arc with the default {2, 2}
    dash pattern drops from ~3500 milliseconds to 10 milliseconds.
    
    Reviewed-by: Keith Packard <keithp at keithp.com>
    Signed-off-by: Adam Jackson <ajax at redhat.com>

diff --git a/mi/miarc.c b/mi/miarc.c
index d6be990..71df4ab 100644
--- a/mi/miarc.c
+++ b/mi/miarc.c
@@ -1021,6 +1021,7 @@ miWideArc(DrawablePtr pDraw, GCPtr pGC, int narcs, xArc * parcs)
     join[0] = join[1] = 0;
     for (iphase = (pGC->lineStyle == LineDoubleDash); iphase >= 0; iphase--) {
         miArcSpanData *spdata = NULL;
+        xArc lastArc;
         ChangeGCVal gcval;
 
         if (iphase == 1) {
@@ -1037,10 +1038,17 @@ miWideArc(DrawablePtr pDraw, GCPtr pGC, int narcs, xArc * parcs)
             miArcDataPtr arcData;
 
             arcData = &polyArcs[iphase].arcs[i];
+            if (spdata) {
+                if (lastArc.width != arcData->arc.width ||
+                    lastArc.height != arcData->arc.height) {
+                    free(spdata);
+                    spdata = NULL;
+                }
+            }
+            memcpy(&lastArc, &arcData->arc, sizeof(xArc));
             spdata = miArcSegment(pDrawTo, pGCTo, arcData->arc,
                                   &arcData->bounds[RIGHT_END],
                                   &arcData->bounds[LEFT_END], spdata);
-            free(spdata);
             if (polyArcs[iphase].arcs[i].render) {
                 fillSpans(pDrawTo, pGCTo);
                 /* don't cap self-joining arcs */
@@ -1097,6 +1105,8 @@ miWideArc(DrawablePtr pDraw, GCPtr pGC, int narcs, xArc * parcs)
                 }
             }
         }
+        free(spdata);
+        spdata = NULL;
     }
     miFreeArcs(polyArcs, pGC);
 
commit 849c825855b82caf44d25edb8155bc9f17869256
Author: Adam Jackson <ajax at redhat.com>
Date:   Wed Mar 1 16:13:58 2017 -0500

    miarc: Make the caller free the arc span data
    
    drawArc does some fairly expensive computation, but it's only sensitive
    to arc width/height. Thread the span data up through the call chain so
    it's at least possible for the caller to cache things.
    
    Reviewed-by: Keith Packard <keithp at keithp.com>
    Signed-off-by: Adam Jackson <ajax at redhat.com>

diff --git a/mi/miarc.c b/mi/miarc.c
index fed5c9f..d6be990 100644
--- a/mi/miarc.c
+++ b/mi/miarc.c
@@ -215,10 +215,21 @@ typedef struct _miPolyArc {
     miArcJoinPtr joins;
 } miPolyArcRec, *miPolyArcPtr;
 
+typedef struct {
+    short lx, lw, rx, rw;
+} miArcSpan;
+
+typedef struct {
+    miArcSpan *spans;
+    int count1, count2, k;
+    char top, bot, hole;
+} miArcSpanData;
+
 static void fillSpans(DrawablePtr pDrawable, GCPtr pGC);
 static void newFinalSpan(int y, int xmin, int xmax);
-static void drawArc(xArc * tarc, int l, int a0, int a1, miArcFacePtr right,
-                    miArcFacePtr left);
+static miArcSpanData *drawArc(xArc * tarc, int l, int a0, int a1,
+                              miArcFacePtr right, miArcFacePtr left,
+                              miArcSpanData *spdata);
 static void drawZeroArc(DrawablePtr pDraw, GCPtr pGC, xArc * tarc, int lw,
                         miArcFacePtr left, miArcFacePtr right);
 static void miArcJoin(DrawablePtr pDraw, GCPtr pGC, miArcFacePtr pLeft,
@@ -244,9 +255,9 @@ static int miGetArcPts(SppArcPtr parc, int cpt, SppPointPtr * ppPts);
  * draw one segment of the arc using the arc spans generation routines
  */
 
-static void
-miArcSegment(DrawablePtr pDraw,
-             GCPtr pGC, xArc tarc, miArcFacePtr right, miArcFacePtr left)
+static miArcSpanData *
+miArcSegment(DrawablePtr pDraw, GCPtr pGC, xArc tarc, miArcFacePtr right,
+             miArcFacePtr left, miArcSpanData *spdata)
 {
     int l = pGC->lineWidth;
     int a0, a1, startAngle, endAngle;
@@ -257,7 +268,7 @@ miArcSegment(DrawablePtr pDraw,
 
     if (tarc.width == 0 || tarc.height == 0) {
         drawZeroArc(pDraw, pGC, &tarc, l, left, right);
-        return;
+        return spdata;
     }
 
     if (pGC->miTranslate) {
@@ -298,7 +309,7 @@ miArcSegment(DrawablePtr pDraw,
         endAngle = FULLCIRCLE;
     }
 
-    drawArc(&tarc, l, startAngle, endAngle, right, left);
+    return drawArc(&tarc, l, startAngle, endAngle, right, left, spdata);
 }
 
 /*
@@ -364,16 +375,6 @@ correspond to the inner and outer boundaries.
 
 */
 
-typedef struct {
-    short lx, lw, rx, rw;
-} miArcSpan;
-
-typedef struct {
-    miArcSpan *spans;
-    int count1, count2, k;
-    char top, bot, hole;
-} miArcSpanData;
-
 static void drawQuadrant(struct arc_def *def, struct accelerators *acc,
                          int a0, int a1, int mask, miArcFacePtr right,
                          miArcFacePtr left, miArcSpanData * spdata);
@@ -905,8 +906,11 @@ miWideArc(DrawablePtr pDraw, GCPtr pGC, int narcs, xArc * parcs)
     int halfWidth;
 
     if (width == 0 && pGC->lineStyle == LineSolid) {
-        for (i = narcs, parc = parcs; --i >= 0; parc++)
-            miArcSegment(pDraw, pGC, *parc, NULL, NULL);
+        for (i = narcs, parc = parcs; --i >= 0; parc++) {
+            miArcSpanData *spdata;
+            spdata = miArcSegment(pDraw, pGC, *parc, NULL, NULL, NULL);
+            free(spdata);
+        }
         fillSpans(pDraw, pGC);
         return;
     }
@@ -1016,6 +1020,7 @@ miWideArc(DrawablePtr pDraw, GCPtr pGC, int narcs, xArc * parcs)
     cap[0] = cap[1] = 0;
     join[0] = join[1] = 0;
     for (iphase = (pGC->lineStyle == LineDoubleDash); iphase >= 0; iphase--) {
+        miArcSpanData *spdata = NULL;
         ChangeGCVal gcval;
 
         if (iphase == 1) {
@@ -1032,9 +1037,10 @@ miWideArc(DrawablePtr pDraw, GCPtr pGC, int narcs, xArc * parcs)
             miArcDataPtr arcData;
 
             arcData = &polyArcs[iphase].arcs[i];
-            miArcSegment(pDrawTo, pGCTo, arcData->arc,
-                         &arcData->bounds[RIGHT_END],
-                         &arcData->bounds[LEFT_END]);
+            spdata = miArcSegment(pDrawTo, pGCTo, arcData->arc,
+                                  &arcData->bounds[RIGHT_END],
+                                  &arcData->bounds[LEFT_END], spdata);
+            free(spdata);
             if (polyArcs[iphase].arcs[i].render) {
                 fillSpans(pDrawTo, pGCTo);
                 /* don't cap self-joining arcs */
@@ -3240,9 +3246,9 @@ mirrorSppPoint(int quadrant, SppPointPtr sppPoint)
  * first quadrant.
  */
 
-static void
-drawArc(xArc * tarc,
-        int l, int a0, int a1, miArcFacePtr right, miArcFacePtr left)
+static miArcSpanData *
+drawArc(xArc * tarc, int l, int a0, int a1, miArcFacePtr right,
+        miArcFacePtr left, miArcSpanData *spdata)
 {                               /* save end line points */
     struct arc_def def;
     struct accelerators acc;
@@ -3258,11 +3264,11 @@ drawArc(xArc * tarc,
     int i, j;
     int flipRight = 0, flipLeft = 0;
     int copyEnd = 0;
-    miArcSpanData *spdata;
 
-    spdata = miComputeWideEllipse(l, tarc);
     if (!spdata)
-        return;
+        spdata = miComputeWideEllipse(l, tarc);
+    if (!spdata)
+        return NULL;
 
     if (a1 < a0)
         a1 += 360 * 64;
@@ -3472,7 +3478,7 @@ drawArc(xArc * tarc,
             left->counterClock = temp;
         }
     }
-    free(spdata);
+    return spdata;
 }
 
 static void
commit 9426c5500b72e1fe004fef4c3b259023c4ec49f7
Author: Adam Jackson <ajax at redhat.com>
Date:   Wed Mar 1 16:13:57 2017 -0500

    miarc: Style cleanup for miWideArc
    
    Outdent, normalize comment formatting, and use 'goto out' idiom for
    error paths. No functional change.
    
    Reviewed-by: Keith Packard <keithp at keithp.com>
    Signed-off-by: Adam Jackson <ajax at redhat.com>

diff --git a/mi/miarc.c b/mi/miarc.c
index 2588ee4..fed5c9f 100644
--- a/mi/miarc.c
+++ b/mi/miarc.c
@@ -894,7 +894,7 @@ miWideArc(DrawablePtr pDraw, GCPtr pGC, int narcs, xArc * parcs)
     int xMin, xMax, yMin, yMax;
     int pixmapWidth = 0, pixmapHeight = 0;
     int xOrg = 0, yOrg = 0;
-    int width;
+    int width = pGC->lineWidth;
     Bool fTricky;
     DrawablePtr pDrawTo;
     CARD32 fg, bg;
@@ -904,210 +904,200 @@ miWideArc(DrawablePtr pDraw, GCPtr pGC, int narcs, xArc * parcs)
     int iphase;
     int halfWidth;
 
-    width = pGC->lineWidth;
     if (width == 0 && pGC->lineStyle == LineSolid) {
         for (i = narcs, parc = parcs; --i >= 0; parc++)
-            miArcSegment(pDraw, pGC, *parc, (miArcFacePtr) 0, (miArcFacePtr) 0);
+            miArcSegment(pDraw, pGC, *parc, NULL, NULL);
         fillSpans(pDraw, pGC);
+        return;
     }
-    else {
-        if ((pGC->lineStyle == LineSolid) && narcs) {
-            while (parcs->width && parcs->height &&
-                   (parcs->angle2 >= FULLCIRCLE ||
-                    parcs->angle2 <= -FULLCIRCLE)) {
-                miFillWideEllipse(pDraw, pGC, parcs);
-                if (!--narcs)
-                    return;
-                parcs++;
-            }
-        }
-
-        /* Set up pDrawTo and pGCTo based on the rasterop */
-        switch (pGC->alu) {
-        case GXclear:          /* 0 */
-        case GXcopy:           /* src */
-        case GXcopyInverted:   /* NOT src */
-        case GXset:            /* 1 */
-            fTricky = FALSE;
-            pDrawTo = pDraw;
-            pGCTo = pGC;
-            break;
-        default:
-            fTricky = TRUE;
-
-            /* find bounding box around arcs */
-            xMin = yMin = MAXSHORT;
-            xMax = yMax = MINSHORT;
-
-            for (i = narcs, parc = parcs; --i >= 0; parc++) {
-                xMin = min(xMin, parc->x);
-                yMin = min(yMin, parc->y);
-                xMax = max(xMax, (parc->x + (int) parc->width));
-                yMax = max(yMax, (parc->y + (int) parc->height));
-            }
-
-            /* expand box to deal with line widths */
-            halfWidth = (width + 1) / 2;
-            xMin -= halfWidth;
-            yMin -= halfWidth;
-            xMax += halfWidth;
-            yMax += halfWidth;
-
-            /* compute pixmap size; limit it to size of drawable */
-            xOrg = max(xMin, 0);
-            yOrg = max(yMin, 0);
-            pixmapWidth = min(xMax, pDraw->width) - xOrg;
-            pixmapHeight = min(yMax, pDraw->height) - yOrg;
-
-            /* if nothing left, return */
-            if ((pixmapWidth <= 0) || (pixmapHeight <= 0))
-                return;
-
-            for (i = narcs, parc = parcs; --i >= 0; parc++) {
-                parc->x -= xOrg;
-                parc->y -= yOrg;
-            }
-            if (pGC->miTranslate) {
-                xOrg += pDraw->x;
-                yOrg += pDraw->y;
-            }
-
-            /* set up scratch GC */
-
-            pGCTo = GetScratchGC(1, pDraw->pScreen);
-            if (!pGCTo)
-                return;
-            {
-                ChangeGCVal gcvals[6];
-
-                gcvals[0].val = GXcopy;
-                gcvals[1].val = 1;
-                gcvals[2].val = 0;
-                gcvals[3].val = pGC->lineWidth;
-                gcvals[4].val = pGC->capStyle;
-                gcvals[5].val = pGC->joinStyle;
-                ChangeGC(NullClient, pGCTo, GCFunction |
-                         GCForeground | GCBackground | GCLineWidth |
-                         GCCapStyle | GCJoinStyle, gcvals);
-            }
 
-            /* allocate a 1 bit deep pixmap of the appropriate size, and
-             * validate it */
-            pDrawTo = (DrawablePtr) (*pDraw->pScreen->CreatePixmap)
-                (pDraw->pScreen, pixmapWidth, pixmapHeight, 1,
-                 CREATE_PIXMAP_USAGE_SCRATCH);
-            if (!pDrawTo) {
-                FreeScratchGC(pGCTo);
+    if ((pGC->lineStyle == LineSolid) && narcs) {
+        while (parcs->width && parcs->height &&
+               (parcs->angle2 >= FULLCIRCLE || parcs->angle2 <= -FULLCIRCLE)) {
+            miFillWideEllipse(pDraw, pGC, parcs);
+            if (!--narcs)
                 return;
-            }
-            ValidateGC(pDrawTo, pGCTo);
-            miClearDrawable(pDrawTo, pGCTo);
+            parcs++;
         }
+    }
 
-        fg = pGC->fgPixel;
-        bg = pGC->bgPixel;
-        if ((pGC->fillStyle == FillTiled) ||
-            (pGC->fillStyle == FillOpaqueStippled))
-            bg = fg;            /* the protocol sez these don't cause color changes */
+    /* Set up pDrawTo and pGCTo based on the rasterop */
+    switch (pGC->alu) {
+    case GXclear:          /* 0 */
+    case GXcopy:           /* src */
+    case GXcopyInverted:   /* NOT src */
+    case GXset:            /* 1 */
+        fTricky = FALSE;
+        pDrawTo = pDraw;
+        pGCTo = pGC;
+        break;
+    default:
+        fTricky = TRUE;
+
+        /* find bounding box around arcs */
+        xMin = yMin = MAXSHORT;
+        xMax = yMax = MINSHORT;
+
+        for (i = narcs, parc = parcs; --i >= 0; parc++) {
+            xMin = min(xMin, parc->x);
+            yMin = min(yMin, parc->y);
+            xMax = max(xMax, (parc->x + (int) parc->width));
+            yMax = max(yMax, (parc->y + (int) parc->height));
+        }
+
+        /* expand box to deal with line widths */
+        halfWidth = (width + 1) / 2;
+        xMin -= halfWidth;
+        yMin -= halfWidth;
+        xMax += halfWidth;
+        yMax += halfWidth;
+
+        /* compute pixmap size; limit it to size of drawable */
+        xOrg = max(xMin, 0);
+        yOrg = max(yMin, 0);
+        pixmapWidth = min(xMax, pDraw->width) - xOrg;
+        pixmapHeight = min(yMax, pDraw->height) - yOrg;
+
+        /* if nothing left, return */
+        if ((pixmapWidth <= 0) || (pixmapHeight <= 0))
+            return;
 
-        polyArcs = miComputeArcs(parcs, narcs, pGC);
+        for (i = narcs, parc = parcs; --i >= 0; parc++) {
+            parc->x -= xOrg;
+            parc->y -= yOrg;
+        }
+        if (pGC->miTranslate) {
+            xOrg += pDraw->x;
+            yOrg += pDraw->y;
+        }
 
-        if (!polyArcs) {
-            if (fTricky) {
-                (*pDraw->pScreen->DestroyPixmap) ((PixmapPtr) pDrawTo);
-                FreeScratchGC(pGCTo);
-            }
+        /* set up scratch GC */
+        pGCTo = GetScratchGC(1, pDraw->pScreen);
+        if (!pGCTo)
+            return;
+        {
+            ChangeGCVal gcvals[6];
+
+            gcvals[0].val = GXcopy;
+            gcvals[1].val = 1;
+            gcvals[2].val = 0;
+            gcvals[3].val = pGC->lineWidth;
+            gcvals[4].val = pGC->capStyle;
+            gcvals[5].val = pGC->joinStyle;
+            ChangeGC(NullClient, pGCTo, GCFunction |
+                     GCForeground | GCBackground | GCLineWidth |
+                     GCCapStyle | GCJoinStyle, gcvals);
+        }
+
+        /* allocate a bitmap of the appropriate size, and validate it */
+        pDrawTo = (DrawablePtr) (*pDraw->pScreen->CreatePixmap)
+            (pDraw->pScreen, pixmapWidth, pixmapHeight, 1,
+             CREATE_PIXMAP_USAGE_SCRATCH);
+        if (!pDrawTo) {
+            FreeScratchGC(pGCTo);
             return;
         }
-
-        cap[0] = cap[1] = 0;
-        join[0] = join[1] = 0;
-        for (iphase = ((pGC->lineStyle == LineDoubleDash) ? 1 : 0);
-             iphase >= 0; iphase--) {
-            ChangeGCVal gcval;
-
-            if (iphase == 1) {
-                gcval.val = bg;
-                ChangeGC(NullClient, pGC, GCForeground, &gcval);
-                ValidateGC(pDraw, pGC);
-            }
-            else if (pGC->lineStyle == LineDoubleDash) {
-                gcval.val = fg;
-                ChangeGC(NullClient, pGC, GCForeground, &gcval);
-                ValidateGC(pDraw, pGC);
-            }
-            for (i = 0; i < polyArcs[iphase].narcs; i++) {
-                miArcDataPtr arcData;
-
-                arcData = &polyArcs[iphase].arcs[i];
-                miArcSegment(pDrawTo, pGCTo, arcData->arc,
-                             &arcData->bounds[RIGHT_END],
-                             &arcData->bounds[LEFT_END]);
-                if (polyArcs[iphase].arcs[i].render) {
-                    fillSpans(pDrawTo, pGCTo);
-                    /*
-                     * don't cap self-joining arcs
-                     */
-                    if (polyArcs[iphase].arcs[i].selfJoin &&
-                        cap[iphase] < polyArcs[iphase].arcs[i].cap)
-                        cap[iphase]++;
-                    while (cap[iphase] < polyArcs[iphase].arcs[i].cap) {
-                        int arcIndex, end;
-                        miArcDataPtr arcData0;
-
-                        arcIndex = polyArcs[iphase].caps[cap[iphase]].arcIndex;
-                        end = polyArcs[iphase].caps[cap[iphase]].end;
-                        arcData0 = &polyArcs[iphase].arcs[arcIndex];
-                        miArcCap(pDrawTo, pGCTo,
-                                 &arcData0->bounds[end], end,
-                                 arcData0->arc.x, arcData0->arc.y,
-                                 (double) arcData0->arc.width / 2.0,
-                                 (double) arcData0->arc.height / 2.0);
-                        ++cap[iphase];
-                    }
-                    while (join[iphase] < polyArcs[iphase].arcs[i].join) {
-                        int arcIndex0, arcIndex1, end0, end1;
-                        int phase0, phase1;
-                        miArcDataPtr arcData0, arcData1;
-                        miArcJoinPtr joinp;
-
-                        joinp = &polyArcs[iphase].joins[join[iphase]];
-                        arcIndex0 = joinp->arcIndex0;
-                        end0 = joinp->end0;
-                        arcIndex1 = joinp->arcIndex1;
-                        end1 = joinp->end1;
-                        phase0 = joinp->phase0;
-                        phase1 = joinp->phase1;
-                        arcData0 = &polyArcs[phase0].arcs[arcIndex0];
-                        arcData1 = &polyArcs[phase1].arcs[arcIndex1];
-                        miArcJoin(pDrawTo, pGCTo,
-                                  &arcData0->bounds[end0],
-                                  &arcData1->bounds[end1],
-                                  arcData0->arc.x, arcData0->arc.y,
-                                  (double) arcData0->arc.width / 2.0,
-                                  (double) arcData0->arc.height / 2.0,
-                                  arcData1->arc.x, arcData1->arc.y,
-                                  (double) arcData1->arc.width / 2.0,
-                                  (double) arcData1->arc.height / 2.0);
-                        ++join[iphase];
-                    }
-                    if (fTricky) {
-                        if (pGC->serialNumber != pDraw->serialNumber)
-                            ValidateGC(pDraw, pGC);
-                        (*pGC->ops->PushPixels) (pGC, (PixmapPtr) pDrawTo,
-                                                 pDraw, pixmapWidth,
-                                                 pixmapHeight, xOrg, yOrg);
-                        miClearDrawable((DrawablePtr) pDrawTo, pGCTo);
-                    }
+        ValidateGC(pDrawTo, pGCTo);
+        miClearDrawable(pDrawTo, pGCTo);
+    }
+
+    fg = pGC->fgPixel;
+    bg = pGC->bgPixel;
+
+    /* the protocol sez these don't cause color changes */
+    if ((pGC->fillStyle == FillTiled) ||
+        (pGC->fillStyle == FillOpaqueStippled))
+        bg = fg;
+
+    polyArcs = miComputeArcs(parcs, narcs, pGC);
+    if (!polyArcs)
+        goto out;
+
+    cap[0] = cap[1] = 0;
+    join[0] = join[1] = 0;
+    for (iphase = (pGC->lineStyle == LineDoubleDash); iphase >= 0; iphase--) {
+        ChangeGCVal gcval;
+
+        if (iphase == 1) {
+            gcval.val = bg;
+            ChangeGC(NullClient, pGC, GCForeground, &gcval);
+            ValidateGC(pDraw, pGC);
+        }
+        else if (pGC->lineStyle == LineDoubleDash) {
+            gcval.val = fg;
+            ChangeGC(NullClient, pGC, GCForeground, &gcval);
+            ValidateGC(pDraw, pGC);
+        }
+        for (i = 0; i < polyArcs[iphase].narcs; i++) {
+            miArcDataPtr arcData;
+
+            arcData = &polyArcs[iphase].arcs[i];
+            miArcSegment(pDrawTo, pGCTo, arcData->arc,
+                         &arcData->bounds[RIGHT_END],
+                         &arcData->bounds[LEFT_END]);
+            if (polyArcs[iphase].arcs[i].render) {
+                fillSpans(pDrawTo, pGCTo);
+                /* don't cap self-joining arcs */
+                if (polyArcs[iphase].arcs[i].selfJoin &&
+                    cap[iphase] < polyArcs[iphase].arcs[i].cap)
+                    cap[iphase]++;
+                while (cap[iphase] < polyArcs[iphase].arcs[i].cap) {
+                    int arcIndex, end;
+                    miArcDataPtr arcData0;
+
+                    arcIndex = polyArcs[iphase].caps[cap[iphase]].arcIndex;
+                    end = polyArcs[iphase].caps[cap[iphase]].end;
+                    arcData0 = &polyArcs[iphase].arcs[arcIndex];
+                    miArcCap(pDrawTo, pGCTo,
+                             &arcData0->bounds[end], end,
+                             arcData0->arc.x, arcData0->arc.y,
+                             (double) arcData0->arc.width / 2.0,
+                             (double) arcData0->arc.height / 2.0);
+                    ++cap[iphase];
+                }
+                while (join[iphase] < polyArcs[iphase].arcs[i].join) {
+                    int arcIndex0, arcIndex1, end0, end1;
+                    int phase0, phase1;
+                    miArcDataPtr arcData0, arcData1;
+                    miArcJoinPtr joinp;
+
+                    joinp = &polyArcs[iphase].joins[join[iphase]];
+                    arcIndex0 = joinp->arcIndex0;
+                    end0 = joinp->end0;
+                    arcIndex1 = joinp->arcIndex1;
+                    end1 = joinp->end1;
+                    phase0 = joinp->phase0;
+                    phase1 = joinp->phase1;
+                    arcData0 = &polyArcs[phase0].arcs[arcIndex0];
+                    arcData1 = &polyArcs[phase1].arcs[arcIndex1];
+                    miArcJoin(pDrawTo, pGCTo,
+                              &arcData0->bounds[end0],
+                              &arcData1->bounds[end1],
+                              arcData0->arc.x, arcData0->arc.y,
+                              (double) arcData0->arc.width / 2.0,
+                              (double) arcData0->arc.height / 2.0,
+                              arcData1->arc.x, arcData1->arc.y,
+                              (double) arcData1->arc.width / 2.0,
+                              (double) arcData1->arc.height / 2.0);
+                    ++join[iphase];
+                }
+                if (fTricky) {
+                    if (pGC->serialNumber != pDraw->serialNumber)
+                        ValidateGC(pDraw, pGC);
+                    (*pGC->ops->PushPixels) (pGC, (PixmapPtr) pDrawTo,
+                                             pDraw, pixmapWidth,
+                                             pixmapHeight, xOrg, yOrg);
+                    miClearDrawable((DrawablePtr) pDrawTo, pGCTo);
                 }
             }
         }
-        miFreeArcs(polyArcs, pGC);
+    }
+    miFreeArcs(polyArcs, pGC);
 
-        if (fTricky) {
-            (*pGCTo->pScreen->DestroyPixmap) ((PixmapPtr) pDrawTo);
-            FreeScratchGC(pGCTo);
-        }
+out:
+    if (fTricky) {
+        (*pGCTo->pScreen->DestroyPixmap) ((PixmapPtr) pDrawTo);
+        FreeScratchGC(pGCTo);
     }
 }
 


More information about the xorg-commit mailing list