summaryrefslogtreecommitdiff
path: root/src/ffb_zeroarc.c
diff options
context:
space:
mode:
authorKaleb Keithley <kaleb@freedesktop.org>2003-11-14 16:48:55 +0000
committerKaleb Keithley <kaleb@freedesktop.org>2003-11-14 16:48:55 +0000
commit68c56916d79bf06e26e01c3e84206edc928d9b51 (patch)
treed39c13092dc680721e163e448a57df847a6fad62 /src/ffb_zeroarc.c
Initial revision
Diffstat (limited to 'src/ffb_zeroarc.c')
-rw-r--r--src/ffb_zeroarc.c536
1 files changed, 536 insertions, 0 deletions
diff --git a/src/ffb_zeroarc.c b/src/ffb_zeroarc.c
new file mode 100644
index 0000000..86b5876
--- /dev/null
+++ b/src/ffb_zeroarc.c
@@ -0,0 +1,536 @@
+/*
+ * Acceleration for the Creator and Creator3D framebuffer - Zero arc
+ * rops.
+ *
+ * Copyright (C) 1999 Jakub Jelinek (jakub@redhat.com)
+ *
+ * Derived from mi/mizerarc.c, see there for authors.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * JAKUB JELINEK OR DAVID MILLER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/sunffb/ffb_zeroarc.c,v 1.2 2000/05/23 04:47:45 dawes Exp $ */
+
+#include "ffb.h"
+#include "ffb_regs.h"
+#include "ffb_rcache.h"
+#include "ffb_fifo.h"
+#include "ffb_stip.h"
+
+#include "pixmapstr.h"
+#include "scrnintstr.h"
+
+#define PSZ 8
+#include "cfb.h"
+#undef PSZ
+#include "cfb32.h"
+
+#include "mi.h"
+#include "mizerarc.h"
+
+#define FULLCIRCLE (360 * 64)
+#define OCTANT (45 * 64)
+#define QUADRANT (90 * 64)
+#define HALFCIRCLE (180 * 64)
+#define QUADRANT3 (270 * 64)
+
+typedef struct {
+ int skipStart;
+ int haveStart;
+ DDXPointRec startPt;
+ int haveLast;
+ int skipLast;
+ DDXPointRec endPt;
+ int dashIndex;
+ int dashOffset;
+ int dashIndexInit;
+ int dashOffsetInit;
+} DashInfo;
+
+#define Pixelate(xval,yval,ext) \
+if (((xval)+xoff) >= (ext)->x1 && \
+ ((xval)+xoff) < (ext)->x2 && \
+ ((yval)+yoff) >= (ext)->y1 && \
+ ((yval)+yoff) < (ext)->y2) { \
+ FFBFifo(pFfb, 2); \
+ FFB_WRITE64(&ffb->bh, ((yval)+yoff), ((xval)+xoff)); \
+}
+
+#define Pixelate1(xval,yval,ext) \
+if (((xval)+xoff) >= (ext)->x1 && \
+ ((xval)+xoff) < (ext)->x2 && \
+ ((yval)+yoff) >= (ext)->y1 && \
+ ((yval)+yoff) < (ext)->y2) { \
+ FFBFifo(pFfb, 2); \
+ FFB_WRITE64(&ffb->bh, ((yval)+yoff), ((xval)+xoff)); \
+}
+
+#define DoPix(idx,xval,yval,ext) if (mask & (1 << idx)) Pixelate(xval, yval,ext);
+
+static void
+CreatorZeroArcPts(xArc *arc, DrawablePtr pDrawable, GCPtr pGC, BoxPtr pextent)
+{
+ miZeroArcRec info;
+ register int x, y, a, b, d, mask;
+ register int k1, k3, dx, dy;
+ int xoff, yoff;
+ Bool do360;
+ FFBPtr pFfb = GET_FFB_FROM_SCREEN(pDrawable->pScreen);
+ ffb_fbcPtr ffb = pFfb->regs;
+
+ xoff = 0;
+ yoff = 0;
+ if (pGC->miTranslate) {
+ xoff = pDrawable->x;
+ yoff = pDrawable->y;
+ }
+ do360 = miZeroArcSetup(arc, &info, TRUE);
+ MIARCSETUP();
+ mask = info.initialMask;
+ if (!(arc->width & 1)) {
+ DoPix(1, info.xorgo, info.yorg, pextent);
+ DoPix(3, info.xorgo, info.yorgo, pextent);
+ }
+ if (!info.end.x || !info.end.y) {
+ mask = info.end.mask;
+ info.end = info.altend;
+ }
+ if (do360 && (arc->width == arc->height) && !(arc->width & 1)) {
+ int yorgh = info.yorg + info.h;
+ int xorghp = info.xorg + info.h;
+ int xorghn = info.xorg - info.h;
+ int lastx = 0, lasty = 0;
+
+ while (1) {
+ if (a < 0)
+ break;
+ Pixelate1(info.xorg + x, info.yorg + y, pextent);
+ Pixelate1(info.xorg - x, info.yorg + y, pextent);
+ Pixelate1(info.xorg - x, info.yorgo - y, pextent);
+ Pixelate1(info.xorg + x, info.yorgo - y, pextent);
+ Pixelate1(xorghp - y, yorgh - x, pextent);
+ Pixelate1(xorghn + y, yorgh - x, pextent);
+ Pixelate1(xorghn + y, yorgh + x, pextent);
+ lastx = xorghp - y; lasty = yorgh + x;
+ Pixelate1(xorghp - y, yorgh + x, pextent);
+ MIARCCIRCLESTEP(;);
+ }
+ if (x <= 0 || lastx != info.xorg + x || lasty != info.yorg + y) {
+ Pixelate1(info.xorg + x, info.yorg + y, pextent);
+ Pixelate1(info.xorg - x, info.yorg + y, pextent);
+ Pixelate1(info.xorg - x, info.yorgo - y, pextent);
+ Pixelate1(info.xorg + x, info.yorgo - y, pextent);
+ }
+ x = info.w;
+ y = info.h;
+ } else if (do360) {
+ while (y < info.h || x < info.w) {
+ MIARCOCTANTSHIFT(;);
+ Pixelate1(info.xorg + x, info.yorg + y, pextent);
+ Pixelate1(info.xorgo - x, info.yorg + y, pextent);
+ Pixelate1(info.xorgo - x, info.yorgo - y, pextent);
+ Pixelate1(info.xorg + x, info.yorgo - y, pextent);
+ MIARCSTEP(;,;);
+ }
+ } else {
+ while (y < info.h || x < info.w) {
+ MIARCOCTANTSHIFT(;);
+ if ((x == info.start.x) || (y == info.start.y)) {
+ mask = info.start.mask;
+ info.start = info.altstart;
+ }
+ DoPix(0, info.xorg + x, info.yorg + y, pextent);
+ DoPix(1, info.xorgo - x, info.yorg + y, pextent);
+ DoPix(2, info.xorgo - x, info.yorgo - y, pextent);
+ DoPix(3, info.xorg + x, info.yorgo - y, pextent);
+ if (x == info.end.x || y == info.end.y) {
+ mask = info.end.mask;
+ info.end = info.altend;
+ }
+ MIARCSTEP(;,;);
+ }
+ }
+ if (x == info.start.x || y == info.start.y)
+ mask = info.start.mask;
+ DoPix(0, info.xorg + x, info.yorg + y, pextent);
+ DoPix(2, info.xorgo - x, info.yorgo - y, pextent);
+ if (arc->height & 1) {
+ DoPix(1, info.xorgo - x, info.yorg + y, pextent);
+ DoPix(3, info.xorg + x, info.yorgo - y, pextent);
+ }
+}
+
+#undef DoPix
+#define DoPix(idx,xval,yval) \
+ if (mask & (1 << idx)) \
+ { \
+ arcPts[idx]->x = xval; \
+ arcPts[idx]->y = yval; \
+ arcPts[idx]++; \
+ }
+
+static void
+CreatorZeroArcDashPts(GCPtr pGC, xArc *arc, DashInfo *dinfo, DDXPointPtr points,
+ int maxPts, DDXPointPtr *evenPts, DDXPointPtr *oddPts)
+{
+ miZeroArcRec info;
+ register int x, y, a, b, d, mask;
+ register int k1, k3, dx, dy;
+ int dashRemaining;
+ DDXPointPtr arcPts[4];
+ DDXPointPtr startPts[5], endPts[5];
+ int deltas[5];
+ DDXPointPtr startPt, pt, lastPt, pts;
+ int i, j, delta, ptsdelta, seg, startseg;
+
+ for (i = 0; i < 4; i++)
+ arcPts[i] = points + (i * maxPts);
+ miZeroArcSetup(arc, &info, FALSE);
+ MIARCSETUP();
+ mask = info.initialMask;
+ startseg = info.startAngle / QUADRANT;
+ startPt = arcPts[startseg];
+ if (!(arc->width & 1)) {
+ DoPix(1, info.xorgo, info.yorg);
+ DoPix(3, info.xorgo, info.yorgo);
+ }
+ if (!info.end.x || !info.end.y) {
+ mask = info.end.mask;
+ info.end = info.altend;
+ }
+ while (y < info.h || x < info.w) {
+ MIARCOCTANTSHIFT(;);
+ if ((x == info.firstx) || (y == info.firsty))
+ startPt = arcPts[startseg];
+ if ((x == info.start.x) || (y == info.start.y)) {
+ mask = info.start.mask;
+ info.start = info.altstart;
+ }
+ DoPix(0, info.xorg + x, info.yorg + y);
+ DoPix(1, info.xorgo - x, info.yorg + y);
+ DoPix(2, info.xorgo - x, info.yorgo - y);
+ DoPix(3, info.xorg + x, info.yorgo - y);
+ if (x == info.end.x || y == info.end.y) {
+ mask = info.end.mask;
+ info.end = info.altend;
+ }
+ MIARCSTEP(;,;);
+ }
+ if (x == info.firstx || y == info.firsty)
+ startPt = arcPts[startseg];
+ if (x == info.start.x || y == info.start.y)
+ mask = info.start.mask;
+ DoPix(0, info.xorg + x, info.yorg + y);
+ DoPix(2, info.xorgo - x, info.yorgo - y);
+ if (arc->height & 1) {
+ DoPix(1, info.xorgo - x, info.yorg + y);
+ DoPix(3, info.xorg + x, info.yorgo - y);
+ }
+ for (i = 0; i < 4; i++) {
+ seg = (startseg + i) & 3;
+ pt = points + (seg * maxPts);
+ if (seg & 1) {
+ startPts[i] = pt;
+ endPts[i] = arcPts[seg];
+ deltas[i] = 1;
+ } else {
+ startPts[i] = arcPts[seg] - 1;
+ endPts[i] = pt - 1;
+ deltas[i] = -1;
+ }
+ }
+ startPts[4] = startPts[0];
+ endPts[4] = startPt;
+ startPts[0] = startPt;
+ if (startseg & 1) {
+ if (startPts[4] != endPts[4])
+ endPts[4]--;
+ deltas[4] = 1;
+ } else {
+ if (startPts[0] > startPts[4])
+ startPts[0]--;
+ if (startPts[4] < endPts[4])
+ endPts[4]--;
+ deltas[4] = -1;
+ }
+ if (arc->angle2 < 0) {
+ DDXPointPtr tmps, tmpe;
+ int tmpd;
+
+ tmpd = deltas[0];
+ tmps = startPts[0] - tmpd;
+ tmpe = endPts[0] - tmpd;
+ startPts[0] = endPts[4] - deltas[4];
+ endPts[0] = startPts[4] - deltas[4];
+ deltas[0] = -deltas[4];
+ startPts[4] = tmpe;
+ endPts[4] = tmps;
+ deltas[4] = -tmpd;
+ tmpd = deltas[1];
+ tmps = startPts[1] - tmpd;
+ tmpe = endPts[1] - tmpd;
+ startPts[1] = endPts[3] - deltas[3];
+ endPts[1] = startPts[3] - deltas[3];
+ deltas[1] = -deltas[3];
+ startPts[3] = tmpe;
+ endPts[3] = tmps;
+ deltas[3] = -tmpd;
+ tmps = startPts[2] - deltas[2];
+ startPts[2] = endPts[2] - deltas[2];
+ endPts[2] = tmps;
+ deltas[2] = -deltas[2];
+ }
+ for (i = 0; i < 5 && startPts[i] == endPts[i]; i++);
+ if (i == 5)
+ return;
+ pt = startPts[i];
+ for (j = 4; startPts[j] == endPts[j]; j--);
+ lastPt = endPts[j] - deltas[j];
+ if (dinfo->haveLast &&
+ (pt->x == dinfo->endPt.x) && (pt->y == dinfo->endPt.y)) {
+ startPts[i] += deltas[i];
+ } else {
+ dinfo->dashIndex = dinfo->dashIndexInit;
+ dinfo->dashOffset = dinfo->dashOffsetInit;
+ }
+ if (!dinfo->skipStart && (info.startAngle != info.endAngle)) {
+ dinfo->startPt = *pt;
+ dinfo->haveStart = TRUE;
+ } else if (!dinfo->skipLast && dinfo->haveStart &&
+ (lastPt->x == dinfo->startPt.x) &&
+ (lastPt->y == dinfo->startPt.y) &&
+ (lastPt != startPts[i]))
+ endPts[j] = lastPt;
+ if (info.startAngle != info.endAngle) {
+ dinfo->haveLast = TRUE;
+ dinfo->endPt = *lastPt;
+ }
+ dashRemaining = pGC->dash[dinfo->dashIndex] - dinfo->dashOffset;
+ for (i = 0; i < 5; i++) {
+ pt = startPts[i];
+ lastPt = endPts[i];
+ delta = deltas[i];
+ while (pt != lastPt) {
+ if (dinfo->dashIndex & 1) {
+ pts = *oddPts;
+ ptsdelta = -1;
+ } else {
+ pts = *evenPts;
+ ptsdelta = 1;
+ }
+ while ((pt != lastPt) && --dashRemaining >= 0) {
+ *pts = *pt;
+ pts += ptsdelta;
+ pt += delta;
+ }
+ if (dinfo->dashIndex & 1)
+ *oddPts = pts;
+ else
+ *evenPts = pts;
+ if (dashRemaining <= 0) {
+ if (++(dinfo->dashIndex) == pGC->numInDashList)
+ dinfo->dashIndex = 0;
+ dashRemaining = pGC->dash[dinfo->dashIndex];
+ }
+ }
+ }
+ dinfo->dashOffset = pGC->dash[dinfo->dashIndex] - dashRemaining;
+}
+
+void
+CreatorZeroPolyArc(DrawablePtr pDrawable, GCPtr pGC, int narcs, xArc *parcs)
+{
+ WindowPtr pWin = (WindowPtr) pDrawable;
+ int maxPts = 0;
+ register int n;
+ register xArc *arc;
+ register int i;
+ register int j, k;
+ DDXPointPtr points = NULL, pts, oddPts;
+ int numPts = 0;
+ DashInfo dinfo;
+ FFBPtr pFfb;
+ ffb_fbcPtr ffb;
+ RegionPtr clip;
+ int numRects, ppc;
+ BoxPtr pbox;
+ CreatorPrivGCPtr gcPriv;
+ register int off = 0, c1, c2;
+ register char *addrp = NULL;
+ register int *ppt, pt, pix;
+
+ gcPriv = CreatorGetGCPrivate (pGC);
+ pFfb = GET_FFB_FROM_SCREEN(pDrawable->pScreen);
+ ffb = pFfb->regs;
+ clip = cfbGetCompositeClip(pGC);
+ numRects = REGION_NUM_RECTS(clip);
+ if (!numRects)
+ return;
+ if (pGC->lineStyle == LineSolid && numRects != 1) {
+ miZeroPolyArc(pDrawable, pGC, narcs, parcs);
+ return;
+ }
+ FFBLOG(("CreatorZeroPolyArc: ALU(%x) PMSK(%08x) narcs(%d)\n",
+ pGC->alu, pGC->planemask, narcs));
+ if (pGC->lineStyle == LineSolid)
+ for (arc = parcs, i = narcs, j = 0; --i >= 0; arc++) {
+ if (!miCanZeroArc(arc))
+ miPolyArc(pDrawable, pGC, 1, arc);
+ else
+ j++;
+ }
+ else
+ for (arc = parcs, i = narcs, j = 0; --i >= 0; arc++) {
+ if (!miCanZeroArc(arc))
+ miPolyArc(pDrawable, pGC, 1, arc);
+ else {
+ j++;
+ if (arc->width > arc->height)
+ n = arc->width + (arc->height >> 1);
+ else
+ n = arc->height + (arc->width >> 1);
+ if (n > maxPts)
+ maxPts = n;
+ }
+ }
+ if (!j)
+ return;
+
+ if (pGC->lineStyle != LineSolid) {
+ numPts = maxPts << 2;
+ points = (DDXPointPtr)ALLOCATE_LOCAL(sizeof(DDXPointRec) * (numPts + (maxPts << 1)));
+ if (!points) return;
+ dinfo.haveStart = FALSE;
+ dinfo.skipStart = FALSE;
+ dinfo.haveLast = FALSE;
+ dinfo.dashIndexInit = 0;
+ dinfo.dashOffsetInit = 0;
+ miStepDash((int)pGC->dashOffset, &dinfo.dashIndexInit,
+ (unsigned char *) pGC->dash, (int)pGC->numInDashList,
+ &dinfo.dashOffsetInit);
+ off = *(int *)&pDrawable->x;
+ off -= (off & 0x8000) << 1;
+ if (pGC->depth == 8) {
+ addrp = (char *)pFfb->sfb8r +
+ (pDrawable->y << 11) + (pDrawable->x << 0);
+ } else {
+ addrp = (char *)pFfb->sfb32 +
+ (pDrawable->y << 13) + (pDrawable->x << 2);
+ }
+ ppc = FFB_PPC_CS_VAR;
+ } else
+ ppc = FFB_PPC_CS_CONST;
+
+ if(gcPriv->stipple == NULL) {
+ FFB_ATTR_GC(pFfb, pGC, pWin,
+ ppc | FFB_PPC_APE_DISABLE,
+ FFB_DRAWOP_DOT);
+ } else {
+ unsigned int fbc;
+
+ FFBSetStipple(pFfb, ffb, gcPriv->stipple,
+ ppc, FFB_PPC_CS_MASK);
+ FFB_WRITE_PMASK(pFfb, ffb, pGC->planemask);
+ FFB_WRITE_DRAWOP(pFfb, ffb, FFB_DRAWOP_DOT);
+ fbc = FFB_FBC_WIN(pWin);
+ fbc = (fbc & ~FFB_FBC_XE_MASK) | FFB_FBC_XE_OFF;
+ FFB_WRITE_FBC(pFfb, ffb, fbc);
+ }
+ if((ppc & FFB_PPC_CS_MASK) == FFB_PPC_CS_VAR)
+ FFBWait(pFfb, ffb);
+
+ for (arc = parcs, i = narcs; --i >= 0; arc++) {
+ if (miCanZeroArc(arc)) {
+ if (pGC->lineStyle == LineSolid)
+ CreatorZeroArcPts(arc, pDrawable, pGC, REGION_RECTS(clip));
+ else {
+ pts = points;
+ oddPts = &points[(numPts >> 1) - 1];
+ dinfo.skipLast = i;
+ CreatorZeroArcDashPts(pGC, arc, &dinfo,
+ oddPts + 1, maxPts, &pts, &oddPts);
+ dinfo.skipStart = TRUE;
+ n = pts - points;
+ pbox = REGION_RECTS(clip);
+ j = numRects;
+ pix = pGC->fgPixel;
+ if (pGC->depth == 8) {
+ while (j--) {
+ c1 = *(int *)&pbox->x1 - off;
+ c2 = *(int *)&pbox->x2 - off - 0x00010001;
+ for (ppt = (int *)points, k = n; --k >= 0; ) {
+ pt = *ppt++;
+ if (!(((pt - c1) | (c2 - pt)) & 0x80008000))
+ *(unsigned char *)(addrp + ((pt << 11) & 0x3ff800) + ((pt >> 16) & 0x07ff)) = pix;
+ }
+ pbox++;
+ }
+ } else {
+ while (j--) {
+ c1 = *(int *)&pbox->x1 - off;
+ c2 = *(int *)&pbox->x2 - off - 0x00010001;
+ for (ppt = (int *)points, k = n; --k >= 0; ) {
+ pt = *ppt++;
+ if (!(((pt - c1) | (c2 - pt)) & 0x80008000))
+ *(unsigned int *)(addrp + ((pt << 13) & 0xffe000) + ((pt >> 14) & 0x1ffc)) = pix;
+ }
+ pbox++;
+ }
+ }
+ if (pGC->lineStyle != LineDoubleDash)
+ continue;
+ if ((pGC->fillStyle == FillSolid) || (pGC->fillStyle == FillStippled))
+ pix = pGC->bgPixel;
+ pts = &points[numPts >> 1];
+ oddPts++;
+ n = pts - oddPts;
+ pbox = REGION_RECTS(clip);
+ j = numRects;
+ if (pGC->depth == 8) {
+ while (j--) {
+ c1 = *(int *)&pbox->x1 - off;
+ c2 = *(int *)&pbox->x2 - off - 0x00010001;
+ for (ppt = (int *)oddPts, k = n; --k >= 0; ) {
+ pt = *ppt++;
+ if (!(((pt - c1) | (c2 - pt)) & 0x80008000))
+ *(unsigned char *)(addrp + ((pt << 11) & 0x3ff800) + ((pt >> 16) & 0x07ff)) = pix;
+ }
+ pbox++;
+ }
+ } else {
+ while (j--) {
+ c1 = *(int *)&pbox->x1 - off;
+ c2 = *(int *)&pbox->x2 - off - 0x00010001;
+ for (ppt = (int *)oddPts, k = n; --k >= 0; ) {
+ pt = *ppt++;
+ if (!(((pt - c1) | (c2 - pt)) & 0x80008000))
+ *(unsigned int *)(addrp + ((pt << 13) & 0xffe000) + ((pt >> 14) & 0x1ffc)) = pix;
+ }
+ pbox++;
+ }
+ }
+ }
+ }
+ }
+ if (pGC->lineStyle != LineSolid) {
+ DEALLOCATE_LOCAL(points);
+ } else {
+ pFfb->rp_active = 1;
+ FFBSync(pFfb, ffb);
+ }
+}