static void
CreatorFillArcSliceSolid(DrawablePtr pDrawable, GCPtr pGC, xArc *arc)
{
	WindowPtr pWin = (WindowPtr) pDrawable;
	FFBPtr pFfb = GET_FFB_FROM_SCREEN(pDrawable->pScreen);
	CreatorPrivGCPtr gcPriv = CreatorGetGCPrivate (pGC);
	ffb_fbcPtr ffb = pFfb->regs;
	miFillArcRec info;
	miArcSliceRec slice;
	int x, y, e, yk, xk, ym, xm, dx, dy, xorg, yorg, slw;
	int ya, xl, xr, xc;

	/* Get the RP ready. */
	if(gcPriv->stipple == NULL) {
		FFB_ATTR_GC(pFfb, pGC, pWin,
			    FFB_PPC_APE_DISABLE | FFB_PPC_CS_CONST,
			    FFB_DRAWOP_RECTANGLE);
	} else {
		unsigned int fbc;

		FFBSetStipple(pFfb, ffb, gcPriv->stipple,
			      FFB_PPC_CS_CONST, FFB_PPC_CS_MASK);
		FFB_WRITE_PMASK(pFfb, ffb, pGC->planemask);
		FFB_WRITE_DRAWOP(pFfb, ffb, FFB_DRAWOP_RECTANGLE);
		fbc = FFB_FBC_WIN(pWin);
		fbc = (fbc & ~FFB_FBC_XE_MASK) | FFB_FBC_XE_OFF;
		FFB_WRITE_FBC(pFfb, ffb, fbc);
		FFB_WRITE_FBC(pFfb, ffb, FFB_FBC_WIN(pWin));
	}
	miFillArcSetup(arc, &info);
	miFillArcSliceSetup(arc, &slice, pGC);
	MIFILLARCSETUP();
	slw = arc->height;
	if (slice.flip_top || slice.flip_bot)
		slw += (arc->height >> 1) + 1;
	if (pGC->miTranslate) {
		xorg += pDrawable->x;
		yorg += pDrawable->y;
		slice.edge1.x += pDrawable->x;
		slice.edge2.x += pDrawable->x;
	}
	while (y > 0) {
		MIFILLARCSTEP(slw);
		MIARCSLICESTEP(slice.edge1);
		MIARCSLICESTEP(slice.edge2);
		if (miFillSliceUpper(slice)) {
			ya = yorg - y;
			MIARCSLICEUPPER(xl, xr, slice, slw);
			ADDSLICESPANS(slice.flip_top);
		}
		if (miFillSliceLower(slice)) {
			ya = yorg + y + dy;
			MIARCSLICELOWER(xl, xr, slice, slw);
			ADDSLICESPANS(slice.flip_bot);
		}
	}
	pFfb->rp_active = 1;
	FFBSync(pFfb, ffb);
}
/* Wheee, circles... */
static void
CreatorFillEllipseSolid(DrawablePtr pDrawable, GCPtr pGC, xArc *arc)
{
	WindowPtr pWin = (WindowPtr) pDrawable;
	FFBPtr pFfb = GET_FFB_FROM_SCREEN(pDrawable->pScreen);
	CreatorPrivGCPtr gcPriv = CreatorGetGCPrivate (pGC);
	ffb_fbcPtr ffb = pFfb->regs;
	miFillArcRec info;
	int x, y, e, yk, xk, ym, xm, dx, dy, xorg, yorg, slw;

	/* Get the RP ready. */
	if(gcPriv->stipple == NULL) {
		FFB_ATTR_GC(pFfb, pGC, pWin,
			    FFB_PPC_APE_DISABLE | FFB_PPC_CS_CONST,
			    FFB_DRAWOP_RECTANGLE);
	} else {
		unsigned int fbc;

		FFBSetStipple(pFfb, ffb, gcPriv->stipple,
			      FFB_PPC_CS_CONST, FFB_PPC_CS_MASK);
		FFB_WRITE_PMASK(pFfb, ffb, pGC->planemask);
		FFB_WRITE_DRAWOP(pFfb, ffb, FFB_DRAWOP_RECTANGLE);
		fbc = FFB_FBC_WIN(pWin);
		fbc = (fbc & ~FFB_FBC_XE_MASK) | FFB_FBC_XE_OFF;
		FFB_WRITE_FBC(pFfb, ffb, fbc);
	}

	/* Start computing the rects. */
	miFillArcSetup(arc, &info);
	MIFILLARCSETUP();
	if(pGC->miTranslate) {
		xorg += pDrawable->x;
		yorg += pDrawable->y;
	}
	while(y > 0) {
		MIFILLARCSTEP(slw);
		if(slw > 0) {
			/* Render. */
			FFBFifo(pFfb, 4);
			FFB_WRITE64(&ffb->by, yorg - y, xorg - x);
			FFB_WRITE64_2(&ffb->bh, 1, slw);
			if(miFillArcLower(slw)) {
				FFBFifo(pFfb, 4);
				FFB_WRITE64(&ffb->by, yorg + y + dy, xorg - x);
				FFB_WRITE64_2(&ffb->bh, 1, slw);
			}
		}
	}
	pFfb->rp_active = 1;
	FFBSync(pFfb, ffb);
}
static void
ReloadSegmentAttrs(FFBPtr pFfb, CreatorPrivGCPtr gcPriv, GCPtr pGC, WindowPtr pWin)
{
	if(gcPriv->stipple == NULL) {
		FFB_ATTR_GC(pFfb, pGC, pWin,
			    FFB_PPC_APE_DISABLE | FFB_PPC_CS_CONST,
			    SEG_DRAWOP(pGC));
	} else {
		ffb_fbcPtr ffb = pFfb->regs;
		unsigned int fbc;

		FFBSetStipple(pFfb, ffb, gcPriv->stipple,
			      FFB_PPC_CS_CONST, FFB_PPC_CS_MASK);
		FFB_WRITE_PMASK(pFfb, ffb, pGC->planemask);
		FFB_WRITE_DRAWOP(pFfb, ffb, SEG_DRAWOP(pGC));
		fbc = FFB_FBC_WIN(pWin);
		fbc = (fbc & ~FFB_FBC_XE_MASK) | FFB_FBC_XE_OFF;
		FFB_WRITE_FBC(pFfb, ffb, fbc);
	}
}
void
CreatorPolySegment (DrawablePtr pDrawable, GCPtr pGC, int nseg, xSegment *pSeg)
{
	WindowPtr pWin = (WindowPtr) pDrawable;
	CreatorPrivGCPtr gcPriv = CreatorGetGCPrivate (pGC);
	FFBPtr pFfb = GET_FFB_FROM_SCREEN (pGC->pScreen);
	ffb_fbcPtr ffb = pFfb->regs;
	BoxPtr extent;
	int xorg, yorg, lpat;

	if (nseg == 0)
		return;

	FFBLOG(("CreatorPolySegment: ALU(%x) PMSK(%08x) nseg(%d) lpat(%08x)\n",
		pGC->alu, pGC->planemask, nseg, gcPriv->linepat));

	if (gcPriv->stipple == NULL) {
		FFB_ATTR_GC(pFfb, pGC, pWin,
			    FFB_PPC_APE_DISABLE | FFB_PPC_CS_CONST,
			    SEG_DRAWOP(pGC));
	} else {
		unsigned int fbc;

		FFBSetStipple(pFfb, ffb, gcPriv->stipple,
			      FFB_PPC_CS_CONST, FFB_PPC_CS_MASK);
		FFB_WRITE_PMASK(pFfb, ffb, pGC->planemask);
		FFB_WRITE_DRAWOP(pFfb, ffb, SEG_DRAWOP(pGC));
		fbc = FFB_FBC_WIN(pWin);
		fbc = (fbc & ~FFB_FBC_XE_MASK) | FFB_FBC_XE_OFF;
		FFB_WRITE_FBC(pFfb, ffb, fbc);
	}

	pFfb->rp_active = 1;
	xorg = pDrawable->x;
	yorg = pDrawable->y;
	extent = REGION_RECTS(cfbGetCompositeClip(pGC));
	lpat = gcPriv->linepat;

	if (lpat == 0) {
		FFBFifo(pFfb, 1);
		ffb->lpat = 0;
		if (pFfb->has_brline_bug) {
			while (nseg--) {
				register int x1 = pSeg->x1 + xorg;
				register int y1 = pSeg->y1 + yorg;
				register int x2 = pSeg->x2 + xorg;
				register int y2 = pSeg->y2 + yorg;

				if (x1 >= extent->x1	&&
				    x2 >= extent->x1	&&
				    x1 < extent->x2	&&
				    x2 < extent->x2	&&
				    y1 >= extent->y1	&&
				    y2 >= extent->y1	&&
				    y1 < extent->y2	&&
				    y2 < extent->y2) {
					FFBFifo(pFfb, 5);
					ffb->ppc = 0;
					FFB_WRITE64(&ffb->by, y1, x1);
					FFB_WRITE64_2(&ffb->bh, y2, x2);
				} else {
					gcPriv->PolySegment(pDrawable, pGC, 1, pSeg);
					ReloadSegmentAttrs(pFfb, gcPriv, pGC, pWin);
					pFfb->rp_active = 1;
				}
				pSeg++;
			}
		} else {
			while (nseg--) {
				register int x1 = pSeg->x1 + xorg;
				register int y1 = pSeg->y1 + yorg;
				register int x2 = pSeg->x2 + xorg;
				register int y2 = pSeg->y2 + yorg;

				if (x1 >= extent->x1	&&
				    x2 >= extent->x1	&&
				    x1 < extent->x2	&&
				    x2 < extent->x2	&&
				    y1 >= extent->y1	&&
				    y2 >= extent->y1	&&
				    y1 < extent->y2	&&
				    y2 < extent->y2) {
					FFBFifo(pFfb, 4);
					FFB_WRITE64(&ffb->by, y1, x1);
					FFB_WRITE64_2(&ffb->bh, y2, x2);
				} else {
					gcPriv->PolySegment(pDrawable, pGC, 1, pSeg);
					ReloadSegmentAttrs(pFfb, gcPriv, pGC, pWin);
					pFfb->rp_active = 1;
				}
				pSeg++;
			}
		}
	} else {
		/* No reason to optimize the non-brline bug case since
		 * we have to write the line pattern register each loop
		 * anyways.
		 */
		while (nseg--) {
			register int x1 = pSeg->x1 + xorg;
			register int y1 = pSeg->y1 + yorg;
			register int x2 = pSeg->x2 + xorg;
			register int y2 = pSeg->y2 + yorg;

			if (x1 >= extent->x1	&&	x2 >= extent->x1	&&
			    x1 < extent->x2	&&	x2 < extent->x2		&&
			    y1 >= extent->y1	&&	y2 >= extent->y1	&&
			    y1 < extent->y2	&&	y2 < extent->y2) {
				FFBFifo(pFfb, 5);
				ffb->lpat = lpat;
				FFB_WRITE64(&ffb->by, y1, x1);
				FFB_WRITE64_2(&ffb->bh, y2, x2);
			} else {
				gcPriv->PolySegment(pDrawable, pGC, 1, pSeg);
				ReloadSegmentAttrs(pFfb, gcPriv, pGC, pWin);
				pFfb->rp_active = 1;
			}
			pSeg++;
		}
	}

	FFBSync(pFfb, ffb);
}
void
CreatorFillPolygon (DrawablePtr pDrawable, GCPtr pGC, int shape, int mode, int count, DDXPointPtr ppt)
{
	WindowPtr pWin = (WindowPtr) pDrawable;
	CreatorPrivGCPtr gcPriv = CreatorGetGCPrivate (pGC);
	FFBPtr pFfb = GET_FFB_FROM_SCREEN (pGC->pScreen);
	ffb_fbcPtr ffb = pFfb->regs;
	BoxRec box;
	int lx, rx, ty, by;
	int t, b, i, j, k, l, tt;
	int xy[12] FFB_ALIGN64;
	int xOrg, yOrg;

	FFBLOG(("CreatorFillPolygon: ALU(%x) PMSK(%08x) shape(%d) mode(%d) count(%d)\n",
		pGC->alu, pGC->planemask, shape, mode, count));
	if (count < 3)
		return;
	
	if (shape != Convex && count > 3) {
		miFillPolygon (pDrawable, pGC, shape, mode, count, ppt);
		return;
	}
	
	xOrg = pDrawable->x;
	yOrg = pDrawable->y;

	ppt->x += xOrg;
	ppt->y += yOrg;	
	lx = ppt->x;
	rx = ppt->x;
	ty = ppt->y;
	by = ppt->y;
	t = b = 0;
	tt = 1;
	for (i = 1; i < count; i++) {
		if (mode == CoordModeOrigin) {
			ppt[i].x += xOrg;
			ppt[i].y += yOrg;
		} else {
			ppt[i].x += ppt[i-1].x;
			ppt[i].y += ppt[i-1].y;
		}
		if (ppt[i].x < lx)
			lx = ppt[i].x;
		if (ppt[i].x > rx)
			rx = ppt[i].x;
		if (ppt[i].y < ty) {
			ty = ppt[i].y;
			t = i;
			tt = 1;
		} else if (ppt[i].y == ty)
			tt++;
		if (ppt[i].y > by) {
			by = ppt[i].y;
			b = i;
		}
	}
	if (tt > 2) {
		miFillConvexPoly(pDrawable, pGC, count, ppt);
		return;
	} else if (tt == 2) {
		i = t - 1;
		if (i < 0)
			i = count - 1;
		if (ppt[i].y == ppt[t].y)
			t = i;
	}
	box.x1 = lx;
	box.x2 = rx + 1;
	box.y1 = ty;
	box.y2 = by + 1;
	
	switch (RECT_IN_REGION(pGC->pScreen, cfbGetCompositeClip(pGC), &box)) {
	case rgnPART:
		miFillConvexPoly(pDrawable, pGC, count, ppt);
	case rgnOUT:
		return;
	}
	if(gcPriv->stipple == NULL) {
		FFB_ATTR_GC(pFfb, pGC, pWin,
			    FFB_PPC_APE_DISABLE | FFB_PPC_CS_CONST,
			    FFB_DRAWOP_POLYGON);
	} else {
		unsigned int fbc;

		FFBSetStipple(pFfb, ffb, gcPriv->stipple,
			      FFB_PPC_CS_CONST, FFB_PPC_CS_MASK);
		FFB_WRITE_PMASK(pFfb, ffb, pGC->planemask);
		FFB_WRITE_DRAWOP(pFfb, ffb, FFB_DRAWOP_POLYGON);
		fbc = FFB_FBC_WIN(pWin);
		fbc = (fbc & ~FFB_FBC_XE_MASK) | FFB_FBC_XE_OFF;
		FFB_WRITE_FBC(pFfb, ffb, fbc);
	}	
	xy[0] = ppt[t].y;
	xy[1] = ppt[t].x;
	j = t + 1;
	if (j == count) j = 0;
	xy[2] = ppt[j].y;
	xy[3] = ppt[j].x;
	j = t + 2;
	if (j >= count)
		j -= count;
	for (i = 2 * count - 4; i; i -= k) {
		b = 2;
		for (k = 0; k < i && k < 8; k+=2) {
			xy[4 + k] = ppt[j].y;
			xy[4 + k + 1] = ppt[j].x;
			if (xy[4 + k] > xy[b])
				b = 4 + k;
			j++; if (j == count) j = 0;
		}
		FFBFifo(pFfb, 4 + k);
		for (l = 0; l < b - 2; l+=2)
			FFB_WRITE64P(&ffb->by, &xy[l]);
		FFB_WRITE64P(&ffb->bh, &xy[l]);
		for (l+=2; l <= k; l+=2)
			FFB_WRITE64P(&ffb->by, &xy[l]);
		FFB_WRITE64P(&ffb->ebyi, &xy[l]);
		xy[2] = xy[l];
		xy[3] = xy[l+1];
	}
	pFfb->rp_active = 1;
	FFBSync(pFfb, ffb);
}