Git-commit: 849c825855b82caf44d25edb8155bc9f17869256
Path-Mainline: Upstream
Author: Adam Jackson <ajax@redhat.com>
Subject: [PATCH xserver] miarc: Make the caller free the arc span data
References: bnc#1019649
Signed-off-by: Michal Srb <msrb@suse.com>

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@keithp.com>
Signed-off-by: Adam Jackson <ajax@redhat.com>

Index: xorg-server-1.6.5/mi/miarc.c
===================================================================
--- xorg-server-1.6.5.orig/mi/miarc.c
+++ xorg-server-1.6.5/mi/miarc.c
@@ -213,6 +213,16 @@ 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;
+
 #define GCValsFunction		0
 #define GCValsForeground 	1
 #define GCValsBackground 	2
@@ -225,8 +235,9 @@ static CARD32 gcvals[6];
 
 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,
@@ -252,13 +263,14 @@ static int miGetArcPts(SppArcPtr parc, i
  * draw one segment of the arc using the arc spans generation routines
  */
 
-static void
+static miArcSpanData*
 miArcSegment(
     DrawablePtr   pDraw,
     GCPtr         pGC,
     xArc          tarc,
     miArcFacePtr	right,
-    miArcFacePtr	left)
+    miArcFacePtr	left,
+    miArcSpanData *spdata)
 {
     int l = pGC->lineWidth;
     int a0, a1, startAngle, endAngle;
@@ -269,7 +281,7 @@ miArcSegment(
 
     if (tarc.width == 0 || tarc.height == 0) {
     	drawZeroArc (pDraw, pGC, &tarc, l, left, right);
-	return;
+	return spdata;
     }
 
     if (pGC->miTranslate) {
@@ -309,7 +321,7 @@ miArcSegment(
 	endAngle = FULLCIRCLE;
     }
 
-    drawArc (&tarc, l, startAngle, endAngle, right, left);
+    return drawArc (&tarc, l, startAngle, endAngle, right, left, spdata);
 }
 
 /*
@@ -375,16 +387,6 @@ correspond to the inner and outer bounda
 
 */
 
-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);
@@ -971,8 +973,11 @@ miPolyArc(DrawablePtr pDraw, GCPtr pGC,
     int		halfWidth;
 
     if (width == 0 && pGC->lineStyle == LineSolid) {
-        for (i = narcs, parc = parcs; --i >= 0; parc++)
-            miArcSegment(pDraw, pGC, *parc, (miArcFacePtr) 0, (miArcFacePtr) 0);
+        for (i = narcs, parc = parcs; --i >= 0; parc++) {
+            miArcSpanData *spdata;
+            spdata = miArcSegment(pDraw, pGC, *parc, (miArcFacePtr) 0, (miArcFacePtr) 0, (miArcSpanData*) 0);
+            free(spdata);
+        }
         fillSpans(pDraw, pGC);
         return;
     }
@@ -1081,6 +1086,7 @@ miPolyArc(DrawablePtr pDraw, GCPtr pGC,
           iphase >= 0;
           iphase--)
     {
+        miArcSpanData *spdata = NULL;
         if (iphase == 1) {
             dixChangeGC (NullClient, pGC, GCForeground, &bg, NULL);
             ValidateGC (pDraw, pGC);
@@ -1092,9 +1098,10 @@ miPolyArc(DrawablePtr pDraw, GCPtr pGC,
             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 */
@@ -3231,14 +3238,15 @@ mirrorSppPoint (
  * first quadrant.
  */
 
-static void
+static miArcSpanData *
 drawArc (
 	xArc *tarc,
 	int	l,
 	int	a0,
 	int	a1,
 	miArcFacePtr	right,
-	miArcFacePtr	left)	/* save end line points */
+	miArcFacePtr	left,
+        miArcSpanData *spdata)	/* save end line points */
 {
 	struct arc_def		def;
 	struct accelerators	acc;
@@ -3254,9 +3262,9 @@ drawArc (
 	int			i, j;
 	int			flipRight = 0, flipLeft = 0;			
 	int			copyEnd = 0;
-	miArcSpanData		*spdata;
 
-	spdata = miComputeWideEllipse(l, tarc);
+        if (!spdata)
+	    spdata = miComputeWideEllipse(l, tarc);
 	if (!spdata)
 	    return;
 
@@ -3468,7 +3476,7 @@ drawArc (
 			left->counterClock = temp;
 		}
 	}
-	xfree(spdata);
+	return spdata;
 }
 
 static void
