2021-10-11 18:37:13 -03:00

225 lines
6.0 KiB
C

#ifndef lint
static char sccsid[] = "@(#)gp1_prims.c 1.1 94/10/31 Copyr 1985-9 Sun Micro";
#endif
/*
* Copyright (c) 1985, 1986, 1987, 1988, 1989 by Sun Microsystems, Inc.
* Permission to use, copy, modify, and distribute this software 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 are retained, and that the name
* of Sun Microsystems, Inc., not be used in advertising or publicity
* pertaining to this software without specific, written prior permission.
* Sun Microsystems, Inc., makes no representations about the suitability
* of this software or the interface defined in this software for any
* purpose. It is provided "as is" without express or implied warranty.
*/
#include "cgipriv.h"
#include <pixrect/gp1cmds.h>
extern Outatt *_cgi_att;
static int old_resetcnt;
static short *gp1_addr, *shmvecbase;
static int pairs_left;
static int fd;
static struct gp1pr *dmd;
static Gp1_attr *g_gpptr;
static short *_cgi_gp1_snd_lines();
/* SPARC requires diff' alignment for int's, so get as two shorts.
* NOTE: Can't do anything tricky with param' inside of the GetGPInt macro!
* (Like "Getint(x++);" is a NO-NO!)
*/
#ifdef sparc
#define GetGPInt(x) *shmptr++ = (short) ((x)>>16), \
*shmptr++ = (x) & 0xffff
#else !sparc
#define GetGPInt(x) *((int *) shmptr)++ = (x)
#endif sparc
_cgi_gp1_pw_polyline(pw, gpptr, npts, pts, mvlist)
Pixwin *pw;
Gp1_attr *gpptr;
int npts;
Ccoor *pts;
u_char *mvlist;
{
register short *shmptr;
register Ccoor *coordptr;
register u_char *mvP;
register int vertex_pairs_left, nlines;
int words_used, roomleft;
Restart:
g_gpptr = gpptr;
fd = ((struct gp1pr *) (pw->pw_pixrect->pr_data))->ioctl_fd;
coordptr = pts;
switch ((int)mvlist)
{
case (int)POLY_DISJOINT:
nlines = npts >> 1;
break;
case (int)POLY_CLOSE:
nlines = npts;
break;
case (int)POLY_DONTCLOSE:
default:
nlines = npts - 1;
break;
}
old_resetcnt = gpptr->resetcnt;
if (gpptr->clpcnt != gpptr->resetcnt)
/* Offset update now handled by _cgi_gp1_pw_updclplst */
(void) _cgi_gp1_pw_updclplst(pw, gpptr);
dmd = gp1_d(pw->pw_pixrect);
gp1_addr = (short *) dmd->gp_shmem;
/*
* This assumes that any GP buffer left allocated was never used, so we can
* start at the base offset without syncronizing with the GP.
*/
while (gpptr->shm_base == 0)
gpptr->shm_base = gp1_alloc(gp1_addr, 1, &gpptr->bitvec, dmd->minordev, fd);
gpptr->offset = gpptr->shm_base;
if (gpptr->attrchg | (gpptr->attrcnt != gpptr->resetcnt))
{
if ((words_used = _cgi_gp1_snd_attr(gp1_addr, gpptr->offset, gpptr, fd))
< 0)
goto Restart;
gpptr->offset += words_used;
shmptr = &gp1_addr[gpptr->offset];
roomleft = 512 - words_used;
}
else
{
shmptr = &gp1_addr[gpptr->offset];
roomleft = 512;
}
shmptr += 3; /* skip words for 2 commands and a count */
shmvecbase = shmptr;
vertex_pairs_left = (roomleft - 6) >> 3;
/* Separate loops for efficiency */
switch ((int)mvlist)
{
case (int)POLY_CLOSE: /* closed polyline */
case (int)POLY_DONTCLOSE: /* normal polyline */
while (--nlines >= 0)
{
GetGPInt(coordptr->x);
GetGPInt(coordptr->y);
coordptr++;
GetGPInt(coordptr->x);
GetGPInt(coordptr->y);
if (--vertex_pairs_left <= 0)
{
if ((shmptr = _cgi_gp1_snd_lines(shmptr)) == (short *) 0)
goto Restart;
vertex_pairs_left = pairs_left;
}
}
if (mvlist == POLY_CLOSE)
{
GetGPInt(coordptr->x);
GetGPInt(coordptr->y);
GetGPInt(pts->x);
GetGPInt(pts->y);
}
break;
case (int)POLY_DISJOINT: /* disjoint polyline */
while (--nlines >= 0)
{
GetGPInt(coordptr->x);
GetGPInt(coordptr->y);
coordptr++;
GetGPInt(coordptr->x);
GetGPInt(coordptr->y);
coordptr++;
if (--vertex_pairs_left <= 0)
{
if ((shmptr = _cgi_gp1_snd_lines(shmptr)) == (short *) 0)
goto Restart;
vertex_pairs_left = pairs_left;
}
}
break;
default: /* polyline with arbitrary move list */
/*
* This doesn't yet implement the pixwin functionality of closing each
* distinct subpolygon (when element 0 of mvlist is non-zero). This
* isn't used by any current callers within CGI.
*/
mvP = mvlist;
while (--nlines >= 0)
{
if (*++mvP == 0)
{
GetGPInt(coordptr->x);
GetGPInt(coordptr->y);
coordptr++;
GetGPInt(coordptr->x);
GetGPInt(coordptr->y);
if (--vertex_pairs_left <= 0)
{
if ((shmptr = _cgi_gp1_snd_lines(shmptr)) == (short *) 0)
goto Restart;
vertex_pairs_left = pairs_left;
}
}
else
coordptr++;
}
break;
}
/* Send remaining vectors in gp buffer */
if (shmptr != shmvecbase)
{
if (_cgi_gp1_snd_lines(shmptr) == (short *) 0)
goto Restart;
}
if (old_resetcnt != gpptr->resetcnt)
goto Restart;
}
static short *_cgi_gp1_snd_lines(endptr)
short *endptr;
{
register short *shmptr;
/*
* First, fill in header information before the vectors
*/
shmptr = shmvecbase - 3;
*shmptr++ = GP1_USEFRAME | g_gpptr->statblkindx; /* frame command */
if (g_gpptr->cmdver[GP1_CGI_LINE >> 8])
*shmptr++ = GP1_CGI_LINE; /* line drawing command */
else
*shmptr++ = GP1_CGIVEC; /* line drawing command */
*shmptr = (endptr - shmvecbase) >> 3; /* # of lines */
shmptr = endptr;
*shmptr++ = GP1_EOCL | GP1_FREEBLKS;
*shmptr++ = (g_gpptr->bitvec >> 16) & 0xffff;
*shmptr = g_gpptr->bitvec & 0xffff;
if (gp1_post(gp1_addr, g_gpptr->offset, fd))
{
while (old_resetcnt == g_gpptr->resetcnt)
;
g_gpptr->offset = g_gpptr->shm_base = 0;
return ((short *) 0);
}
while ((g_gpptr->shm_base = gp1_alloc(gp1_addr, 1, &g_gpptr->bitvec,
dmd->minordev, fd)) == 0)
;
g_gpptr->offset = g_gpptr->shm_base;
shmptr = &gp1_addr[g_gpptr->offset];
pairs_left = (512 - 6) >> 3;
shmvecbase = shmptr + 3;
return (shmvecbase);
}