mirror of
https://github.com/Stichting-MINIX-Research-Foundation/xsrc.git
synced 2025-09-15 23:55:03 -04:00
474 lines
13 KiB
C
474 lines
13 KiB
C
/* $XConsortium: s3line.c,v 1.3 94/10/12 20:07:37 kaleb Exp $ */
|
|
/* $XFree86: xc/programs/Xserver/hw/xfree86/accel/s3/s3line.c,v 3.5 1995/01/28 17:02:17 dawes Exp $ */
|
|
/*
|
|
|
|
Copyright (c) 1987 X Consortium
|
|
|
|
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 THE X CONSORTIUM 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.
|
|
|
|
Except as contained in this notice, the name of the X Consortium shall
|
|
not be used in advertising or otherwise to promote the sale, use or
|
|
other dealings in this Software without prior written authorization
|
|
from the X Consortium.
|
|
|
|
|
|
Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts,
|
|
All Rights Reserved
|
|
|
|
Permission to use, copy, modify, and distribute this software and its
|
|
documentation for any purpose and without fee is hereby granted,
|
|
provided that the above copyright notice appear in all copies and that
|
|
both that copyright notice and this permission notice appear in
|
|
supporting documentation, and that the name of Digital not be
|
|
used in advertising or publicity pertaining to distribution of the
|
|
software without specific, written prior permission.
|
|
|
|
DIGITAL AND KEVIN E. MARTIN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
|
|
SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
|
|
IN NO EVENT SHALL DIGITAL OR KEVIN E. MARTIN BE LIABLE FOR ANY SPECIAL,
|
|
INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
|
OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
PERFORMANCE OF THIS SOFTWARE.
|
|
|
|
Modified for the 8514/A by Kevin E. Martin (martin@cs.unc.edu)
|
|
|
|
*/
|
|
|
|
/*
|
|
* Modified by Amancio Hasty and Jon Tombs
|
|
*
|
|
* Id: s3line.c,v 2.2 1993/06/22 20:54:09 jon Exp jon
|
|
*/
|
|
|
|
/*
|
|
* Modified for the CyberVision 64 by Michael Teske
|
|
*/
|
|
|
|
#include "amiga.h"
|
|
|
|
#include "Xmd.h"
|
|
#include "gcstruct.h"
|
|
#include "scrnintstr.h"
|
|
#include "pixmapstr.h"
|
|
#include "regionstr.h"
|
|
#include "mistruct.h"
|
|
#include "mifillarc.h"
|
|
#include "fontstruct.h"
|
|
#include "dixfontstr.h"
|
|
#include "cfb.h"
|
|
#include "cfbmskbits.h"
|
|
#include "cfb8bit.h"
|
|
#include "fastblt.h"
|
|
#include "mergerop.h"
|
|
#include "amigaCV.h"
|
|
#include "migc.h"
|
|
#include "miline.h"
|
|
|
|
extern int cfb16ScreenPrivateIndex, cfb32ScreenPrivateIndex;
|
|
|
|
/* Externs from amigaCV.c */
|
|
|
|
extern short s3alu[];
|
|
|
|
|
|
void
|
|
amigaCVLine(pDrawable, pGC, mode, npt, pptInit)
|
|
DrawablePtr pDrawable;
|
|
GCPtr pGC;
|
|
int mode; /* Origin or Previous */
|
|
int npt; /* number of points */
|
|
DDXPointPtr pptInit;
|
|
{
|
|
int nboxInit;
|
|
register int nbox;
|
|
BoxPtr pboxInit;
|
|
register BoxPtr pbox;
|
|
register DDXPointPtr ppt; /* pointer to list of translated points */
|
|
|
|
unsigned int oc1; /* outcode of point 1 */
|
|
unsigned int oc2; /* outcode of point 2 */
|
|
|
|
int xorg, yorg; /* origin of window */
|
|
|
|
int adx; /* abs values of dx and dy */
|
|
int ady;
|
|
int signdx; /* sign of dx and dy */
|
|
int signdy;
|
|
int e, e1, e2; /* bresenham error and increments */
|
|
int len; /* length of segment */
|
|
int axis; /* major axis */
|
|
int octant;
|
|
unsigned int bias = miGetZeroLineBias(pDrawable->pScreen);
|
|
short cmd = CMD_LINE | DRAW | PLANAR | WRTDATA | LASTPIX;
|
|
short cmd2;
|
|
short fix;
|
|
fbFd *inf = amigaInfo(pDrawable->pScreen);
|
|
volatile caddr_t vgaBase = (inf->regs);
|
|
|
|
/* a bunch of temporaries */
|
|
int tmp;
|
|
register int y1, y2;
|
|
register int x1, x2;
|
|
RegionPtr cclip;
|
|
cfbPrivGCPtr devPriv;
|
|
|
|
#if 0
|
|
if (!xf86VTSema)
|
|
{
|
|
switch (s3InfoRec.bitsPerPixel) {
|
|
case 8:
|
|
cfbLineSS(pDrawable, pGC, mode, npt, pptInit);
|
|
break;
|
|
case 16:
|
|
cfb16LineSS(pDrawable, pGC, mode, npt, pptInit);
|
|
break;
|
|
case 32:
|
|
cfb32LineSS(pDrawable, pGC, mode, npt, pptInit);
|
|
break;
|
|
}
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
devPriv = (cfbPrivGC *) (pGC->devPrivates[cfbGCPrivateIndex].ptr);
|
|
cclip = cfbGetCompositeClip(pGC);
|
|
pboxInit = REGION_RECTS(cclip);
|
|
nboxInit = REGION_NUM_RECTS(cclip);
|
|
|
|
BLOCK_CURSOR;
|
|
WaitQueue16_32(3,5);
|
|
S3_OUTW(FRGD_MIX, FSS_FRGDCOL | s3alu[pGC->alu]);
|
|
S3_OUTW32(WRT_MASK, pGC->planemask);
|
|
S3_OUTW32(FRGD_COLOR, pGC->fgPixel);
|
|
#if 0
|
|
/* Fix problem writing to the cursor storage area */
|
|
WaitQueue(1);
|
|
S3_OUTW(MULTIFUNC_CNTL, SCISSORS_B | (pDrawable->pScreen->height-1));
|
|
#endif
|
|
xorg = pDrawable->x;
|
|
yorg = pDrawable->y;
|
|
ppt = pptInit;
|
|
|
|
x2 = ppt->x + xorg;
|
|
y2 = ppt->y + yorg;
|
|
|
|
while (--npt) {
|
|
nbox = nboxInit;
|
|
pbox = pboxInit;
|
|
|
|
x1 = x2;
|
|
y1 = y2;
|
|
++ppt;
|
|
if (mode == CoordModePrevious) {
|
|
xorg = x1;
|
|
yorg = y1;
|
|
}
|
|
x2 = ppt->x + xorg;
|
|
y2 = ppt->y + yorg;
|
|
|
|
if (x1 == x2) {
|
|
|
|
/*
|
|
* make the line go top to bottom of screen, keeping endpoint
|
|
* semantics
|
|
*/
|
|
if (y1 > y2) {
|
|
register int tmp;
|
|
|
|
tmp = y2;
|
|
y2 = y1 + 1;
|
|
y1 = tmp + 1;
|
|
}
|
|
/* get to first band that might contain part of line */
|
|
while ((nbox) && (pbox->y2 <= y1)) {
|
|
pbox++;
|
|
nbox--;
|
|
}
|
|
|
|
if (nbox) {
|
|
/* stop when lower edge of box is beyond end of line */
|
|
while ((nbox) && (y2 >= pbox->y1)) {
|
|
if ((x1 >= pbox->x1) && (x1 < pbox->x2)) {
|
|
int y1t, y2t;
|
|
|
|
/* this box has part of the line in it */
|
|
y1t = max(y1, pbox->y1);
|
|
y2t = min(y2, pbox->y2);
|
|
if (y1t != y2t) {
|
|
WaitQueue(4); PCI_HACK();
|
|
S3_OUTW(CUR_X, (short)x1);
|
|
S3_OUTW(CUR_Y, (short)y1t);
|
|
S3_OUTW(MAJ_AXIS_PCNT, (short)(y2t - y1t - 1));
|
|
S3_OUTW(CMD, CMD_LINE | DRAW | LINETYPE | PLANAR |
|
|
WRTDATA | (6 << 5));
|
|
}
|
|
}
|
|
nbox--;
|
|
pbox++;
|
|
}
|
|
}
|
|
y2 = ppt->y + yorg;
|
|
} else if (y1 == y2) {
|
|
|
|
/*
|
|
* force line from left to right, keeping endpoint semantics
|
|
*/
|
|
if (x1 > x2) {
|
|
register int tmp;
|
|
|
|
tmp = x2;
|
|
x2 = x1 + 1;
|
|
x1 = tmp + 1;
|
|
}
|
|
/* find the correct band */
|
|
while ((nbox) && (pbox->y2 <= y1)) {
|
|
pbox++;
|
|
nbox--;
|
|
}
|
|
|
|
/* try to draw the line, if we haven't gone beyond it */
|
|
if ((nbox) && (pbox->y1 <= y1)) {
|
|
/* when we leave this band, we're done */
|
|
tmp = pbox->y1;
|
|
while ((nbox) && (pbox->y1 == tmp)) {
|
|
int x1t, x2t;
|
|
|
|
if (pbox->x2 <= x1) {
|
|
/* skip boxes until one might contain start point */
|
|
nbox--;
|
|
pbox++;
|
|
continue;
|
|
}
|
|
/* stop if left of box is beyond right of line */
|
|
if (pbox->x1 >= x2) {
|
|
nbox = 0;
|
|
break;
|
|
}
|
|
x1t = max(x1, pbox->x1);
|
|
x2t = min(x2, pbox->x2);
|
|
if (x1t != x2t) {
|
|
WaitQueue(4);PCI_HACK();
|
|
S3_OUTW(CUR_X, (short)x1t);
|
|
S3_OUTW(CUR_Y, (short)y1);
|
|
S3_OUTW(MAJ_AXIS_PCNT, (short)(x2t - x1t - 1));
|
|
S3_OUTW(CMD, CMD_LINE | DRAW | LINETYPE | PLANAR |
|
|
WRTDATA);
|
|
}
|
|
nbox--;
|
|
pbox++;
|
|
}
|
|
}
|
|
x2 = ppt->x + xorg;
|
|
} else { /* sloped line */
|
|
cmd2 = cmd;
|
|
if ((adx = x2 - x1) < 0) {
|
|
fix = 0;
|
|
} else {
|
|
cmd2 |= INC_X;
|
|
fix = -1;
|
|
}
|
|
if ((ady = y2 - y1) >= 0) {
|
|
cmd2 |= INC_Y;
|
|
}
|
|
|
|
CalcLineDeltas(x1, y1, x2, y2, adx, ady, signdx, signdy, 1, 1, octant);
|
|
|
|
if (adx > ady) {
|
|
axis = X_AXIS;
|
|
e1 = ady << 1;
|
|
e2 = e1 - (adx << 1);
|
|
e = e1 - adx;
|
|
} else {
|
|
axis = Y_AXIS;
|
|
e1 = adx << 1;
|
|
e2 = e1 - (ady << 1);
|
|
e = e1 - ady;
|
|
cmd2 |= YMAJAXIS;
|
|
SetYMajorOctant(octant);
|
|
}
|
|
|
|
FIXUP_ERROR(e, octant, bias);
|
|
|
|
/*
|
|
* we have bresenham parameters and two points. all we have to do now
|
|
* is clip and draw.
|
|
*/
|
|
|
|
while (nbox--) {
|
|
oc1 = 0;
|
|
oc2 = 0;
|
|
OUTCODES(oc1, x1, y1, pbox);
|
|
OUTCODES(oc2, x2, y2, pbox);
|
|
if ((oc1 | oc2) == 0) {
|
|
if (axis == X_AXIS)
|
|
len = adx;
|
|
else
|
|
len = ady;
|
|
|
|
/*
|
|
* NOTE: The 8514/A hardware routines for generating lines do
|
|
* not match the software generated lines of mi, cfb, and mfb.
|
|
* This is a problem, and if I ever get time, I'll figure out
|
|
* the 8514/A algorithm and implement it in software for mi,
|
|
* cfb, and mfb.
|
|
* 14-sep-93 TCG: apparently only change needed is
|
|
* addition of 'fix' stuff in cfbline.c
|
|
*/
|
|
WaitQueue(7); PCI_HACK();
|
|
S3_OUTW(CUR_X, (short)x1);
|
|
S3_OUTW(CUR_Y, (short)y1);
|
|
S3_OUTW(ERR_TERM, (short)(e + fix));
|
|
S3_OUTW(DESTY_AXSTP, (short)e1);
|
|
S3_OUTW(DESTX_DIASTP, (short)e2);
|
|
S3_OUTW(MAJ_AXIS_PCNT, (short)len);
|
|
S3_OUTW(CMD, cmd2);
|
|
break;
|
|
} else if (oc1 & oc2) {
|
|
pbox++;
|
|
} else {
|
|
|
|
/*
|
|
* let the mi helper routine do our work; better than
|
|
* duplicating code...
|
|
*/
|
|
int err; /* modified bresenham error term */
|
|
int clip1=0, clip2=0; /* clippedness of the endpoints */
|
|
|
|
int clipdx, clipdy; /* difference between clipped and
|
|
* unclipped start point */
|
|
int new_x1 = x1, new_y1 = y1, new_x2 = x2, new_y2 = y2;
|
|
|
|
if (miZeroClipLine(pbox->x1, pbox->y1,
|
|
pbox->x2-1, pbox->y2-1,
|
|
&new_x1, &new_y1,
|
|
&new_x2, &new_y2,
|
|
adx, ady,
|
|
&clip1, &clip2,
|
|
octant, bias,
|
|
oc1, oc2) == -1)
|
|
{
|
|
pbox++;
|
|
continue;
|
|
}
|
|
if (axis == X_AXIS)
|
|
len = abs(new_x2 - new_x1);
|
|
else
|
|
len = abs(new_y2 - new_y1);
|
|
|
|
len += (clip2 != 0);
|
|
if (len) {
|
|
/* unwind bresenham error term to first point */
|
|
if (clip1) {
|
|
clipdx = abs(new_x1 - x1);
|
|
clipdy = abs(new_y1 - y1);
|
|
if (axis == X_AXIS)
|
|
err = e + ((clipdy * e2) + ((clipdx - clipdy) * e1));
|
|
else
|
|
err = e + ((clipdx * e2) + ((clipdy - clipdx) * e1));
|
|
} else
|
|
err = e;
|
|
/*
|
|
* Here is a problem, the unwound error terms could be
|
|
* upto 16bit now. The poor S3 is only 12 or 13 bit.
|
|
* The rounding error is probably small I favor scaling
|
|
* the error terms, although re-evaluation is also an
|
|
* option I think it might give visable errors
|
|
* - Jon 12/9/93.
|
|
*/
|
|
|
|
if (abs(err) > 4096 || abs(e1) > 4096 || abs(e2) > 4096) {
|
|
#if 1
|
|
int div;
|
|
|
|
if (abs(err) > abs(e1))
|
|
div = (abs(err) > abs(e2)) ?
|
|
(abs(err) + 4095)/ 4096 : (abs(e2) + 4095)/ 4096;
|
|
else
|
|
div = (abs(e1) > abs(e2)) ?
|
|
(abs(e1) + 4095)/ 4096 : (abs(e2) + 4095)/ 4096;
|
|
|
|
err /= div;
|
|
e1 /= div;
|
|
e2 /= div;
|
|
#else
|
|
int minor;
|
|
if (axis == X_AXIS) {
|
|
minor = abs(new_y2 - new_y1);
|
|
err = 2 * minor - len;
|
|
} else {
|
|
minor = abs(new_x2 - new_x1);
|
|
err = 2 * minor - len - 1;
|
|
}
|
|
e1 = minor << 1;
|
|
e2 = e1 - (len << 1);
|
|
#endif
|
|
}
|
|
WaitQueue(7);PCI_HACK();
|
|
S3_OUTW(CUR_X, (short)new_x1);
|
|
S3_OUTW(CUR_Y, (short)new_y1);
|
|
S3_OUTW(ERR_TERM, (short)(err + fix));
|
|
S3_OUTW(DESTY_AXSTP, (short)e1);
|
|
S3_OUTW(DESTX_DIASTP, (short)e2);
|
|
S3_OUTW(MAJ_AXIS_PCNT, (short)len);
|
|
S3_OUTW(CMD, cmd2);
|
|
}
|
|
pbox++;
|
|
}
|
|
} /* while (nbox--) */
|
|
} /* sloped line */
|
|
} /* while (nline--) */
|
|
|
|
/*
|
|
* paint the last point if the end style isn't CapNotLast. (Assume that a
|
|
* projecting, butt, or round cap that is one pixel wide is the same as the
|
|
* single pixel of the endpoint.)
|
|
*/
|
|
|
|
if ((pGC->capStyle != CapNotLast) &&
|
|
((ppt->x + xorg != pptInit->x + pDrawable->x) ||
|
|
(ppt->y + yorg != pptInit->y + pDrawable->y) ||
|
|
(ppt == pptInit + 1))) {
|
|
nbox = nboxInit;
|
|
pbox = pboxInit;
|
|
while (nbox--) {
|
|
if ((x2 >= pbox->x1) &&
|
|
(y2 >= pbox->y1) &&
|
|
(x2 < pbox->x2) &&
|
|
(y2 < pbox->y2)) {
|
|
WaitQueue(4);
|
|
S3_OUTW(CUR_X, (short)x2);
|
|
S3_OUTW(CUR_Y, (short)y2);
|
|
S3_OUTW(MAJ_AXIS_PCNT, 0);
|
|
S3_OUTW(CMD, CMD_LINE | DRAW | LINETYPE | PLANAR | WRTDATA);
|
|
break;
|
|
} else
|
|
pbox++;
|
|
}
|
|
}
|
|
WaitQueue(3);WaitIdle();
|
|
S3_OUTW(FRGD_MIX, FSS_FRGDCOL | MIX_SRC);
|
|
S3_OUTW(BKGD_MIX, BSS_BKGDCOL | MIX_SRC);
|
|
#if 0
|
|
S3_OUTW(MULTIFUNC_CNTL, SCISSORS_B | s3ScissB);
|
|
#endif
|
|
UNBLOCK_CURSOR;
|
|
}
|