1131 lines
35 KiB
C
1131 lines
35 KiB
C
/*
|
|
** THIS SOFTWARE IS SUBJECT TO COPYRIGHT PROTECTION AND IS OFFERED ONLY
|
|
** PURSUANT TO THE 3DFX GLIDE GENERAL PUBLIC LICENSE. THERE IS NO RIGHT
|
|
** TO USE THE GLIDE TRADEMARK WITHOUT PRIOR WRITTEN PERMISSION OF 3DFX
|
|
** INTERACTIVE, INC. A COPY OF THIS LICENSE MAY BE OBTAINED FROM THE
|
|
** DISTRIBUTOR OR BY CONTACTING 3DFX INTERACTIVE INC(info@3dfx.com).
|
|
** THIS PROGRAM IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
|
|
** EXPRESSED OR IMPLIED. SEE THE 3DFX GLIDE GENERAL PUBLIC LICENSE FOR A
|
|
** FULL TEXT OF THE NON-WARRANTY PROVISIONS.
|
|
**
|
|
** USE, DUPLICATION OR DISCLOSURE BY THE GOVERNMENT IS SUBJECT TO
|
|
** RESTRICTIONS AS SET FORTH IN SUBDIVISION (C)(1)(II) OF THE RIGHTS IN
|
|
** TECHNICAL DATA AND COMPUTER SOFTWARE CLAUSE AT DFARS 252.227-7013,
|
|
** AND/OR IN SIMILAR OR SUCCESSOR CLAUSES IN THE FAR, DOD OR NASA FAR
|
|
** SUPPLEMENT. UNPUBLISHED RIGHTS RESERVED UNDER THE COPYRIGHT LAWS OF
|
|
** THE UNITED STATES.
|
|
**
|
|
** COPYRIGHT 3DFX INTERACTIVE, INC. 1999, ALL RIGHTS RESERVED
|
|
**
|
|
** $Header$
|
|
** $Log$
|
|
** Revision 1.3 2000/01/17 22:18:41 joseph
|
|
** A nicer, cleaner fix than the evil hack.
|
|
**
|
|
** Revision 1.2 2000/01/15 00:08:22 joseph
|
|
** Evil nasty hack to fix dispatch code using binutils 2.9.5.
|
|
**
|
|
** Revision 1.1.1.1 1999/12/07 21:49:10 joseph
|
|
** Initial checkin into SourceForge.
|
|
**
|
|
**
|
|
** 98 6/02/98 8:03p Peter
|
|
** Mmmmm.... points
|
|
**
|
|
** 97 6/01/98 6:44p Peter
|
|
** snapped/unsnapped points
|
|
**
|
|
** 96 5/20/98 3:51p Peter
|
|
** no fifo glide
|
|
**
|
|
** 95 5/18/98 12:14p Peter
|
|
** better point code
|
|
**
|
|
** 94 2/20/98 11:00a Peter
|
|
** removed glide3 from glid2 tree
|
|
**
|
|
** 93 2/11/98 5:23p Peter
|
|
** workaround for tombraider rgb > 255.0
|
|
*
|
|
* 92 1/15/98 2:46p Atai
|
|
* fixed grDrawPoint and grDrawLine in aa mode
|
|
*
|
|
* 90 12/17/97 4:45p Peter
|
|
* groundwork for CrybabyGlide
|
|
*
|
|
* 89 12/15/97 5:52p Atai
|
|
* disable obsolete glide2 api for glide3
|
|
*
|
|
* 85 12/08/97 12:06p Atai
|
|
* change prototype for grDrawPoint, grDrawLine, grDrawTriangel
|
|
*
|
|
* 83 11/21/97 6:05p Atai
|
|
* use one datalist (tsuDataList) in glide3
|
|
*
|
|
* 82 11/21/97 3:20p Peter
|
|
* direct writes tsu registers
|
|
*
|
|
* 81 11/19/97 4:33p Atai
|
|
* make vSize debug variable
|
|
*
|
|
* 80 11/18/97 4:36p Peter
|
|
* chipfield stuff cleanup and w/ direct writes
|
|
*
|
|
* 79 11/17/97 4:55p Peter
|
|
* watcom warnings/chipfield stuff
|
|
*
|
|
* 78 11/16/97 2:20p Peter
|
|
* cleanup
|
|
*
|
|
* 77 11/15/97 7:43p Peter
|
|
* more comdex silliness
|
|
*
|
|
**
|
|
*/
|
|
#include <memory.h>
|
|
|
|
#include <3dfx.h>
|
|
|
|
#define FX_DLL_DEFINITION
|
|
#include <fxdll.h>
|
|
#include <glide.h>
|
|
#include "fxglide.h"
|
|
|
|
#if GLIDE_DISPATCH_SETUP
|
|
#include "fxinline.h"
|
|
#endif
|
|
|
|
#define SST_XY_HALF (1 << (SST_XY_FRACBITS - 1))
|
|
#define SST_XY_ONE (1 << SST_XY_FRACBITS)
|
|
|
|
#define OUTBOUNDSX(a) ((a->x < 0.f ? 1 : 0) || (a->x > gc->state.screen_width ? 1 : 0))
|
|
#define OUTBOUNDSY(a) ((a->y < 0.f ? 1 : 0) || (a->y > gc->state.screen_height ? 1 : 0))
|
|
#define OUTBOUNDS(a) (OUTBOUNDSX(a) || OUTBOUNDSY(a))
|
|
|
|
/*---------------------------------------------------------------------------
|
|
** grDrawPoint
|
|
*/
|
|
GR_ENTRY(grDrawPoint, void, (const GrVertex *p))
|
|
{
|
|
#define FN_NAME "grDrawPoint"
|
|
FxU32 x, y;
|
|
GR_BEGIN_NOFIFOCHECK(FN_NAME, 90);
|
|
GDBG_INFO_MORE(gc->myLevel, "(0x%X) : (%f %f)\n", p, p->x, p->y);
|
|
|
|
GR_FLUSH_STATE();
|
|
|
|
/* we snap to an integer by adding a large enough number that it
|
|
* shoves all fraction bits off the right side of the mantissa.
|
|
*
|
|
* NB: IEEE rounds to nearest integer by default, but applications
|
|
* can change the rounding mode so that it is difficult to get the
|
|
* correct truncation/ceiling operation w/ a simple adjustment to
|
|
* the bias.
|
|
*
|
|
* NB: The constant kNumMantissaBits defines how many bits of
|
|
* integer precision a coordinate can have. This needs to be atleast
|
|
* as large as the maximum hw screen resolution. We later use this
|
|
* to compute a logical 1/2 value to fill an entire pixel.
|
|
*/
|
|
#define kNumMantissaBits 18UL
|
|
{
|
|
const float bias = (const float)(3UL << kNumMantissaBits);
|
|
|
|
/* Convert to 32-bit representation */
|
|
#define FP_TRUNC_BIAS(__fpVal, __fpBias) \
|
|
((__fpVal) < (__fpBias) ? (float)((__fpVal) + (__fpBias)) : (__fpVal))
|
|
_GlideRoot.pool.ftemp1 = FP_TRUNC_BIAS(p->x, bias);
|
|
_GlideRoot.pool.ftemp2 = FP_TRUNC_BIAS(p->y, bias);
|
|
|
|
/* Mask off the real fractional bits from the mantissa */
|
|
x = ((*(FxU32*)&_GlideRoot.pool.ftemp1 & (0xFFFFFFFFUL << (22UL - kNumMantissaBits))) +
|
|
(0x01UL << (22UL - kNumMantissaBits)));
|
|
y = ((*(FxU32*)&_GlideRoot.pool.ftemp2 & (0xFFFFFFFFUL << (22UL - kNumMantissaBits))) +
|
|
(0x01UL << (22UL - kNumMantissaBits)));
|
|
}
|
|
|
|
/* draw a little triangle, with the lower left corner at pixel center. */
|
|
#if GLIDE_HW_TRI_SETUP && GLIDE_PACKET3_TRI_SETUP
|
|
/* The approach here is to split the triangle into two packets, one
|
|
* that sends just the coordinates of the last two points of the
|
|
* triangle w/ no other parameter information, and then the
|
|
* centered point w/ all of the parameter information. The first
|
|
* packet is has a BDD command, but is incomplete, so nothing
|
|
* draws, the next packet has a DDD command so will complete the
|
|
* triangle from the first packet sent.
|
|
*/
|
|
GR_SET_EXPECTED_SIZE((sizeof(FxU32) << 2) + /* Size of Initial coordinate packet */
|
|
_GlideRoot.curVertexSize, /* The full coordinate vertex */
|
|
2); /* We do two split packets */
|
|
TRI_PACKET_BEGIN(kSetupStrip | kSetupCullDisable, 0x00,
|
|
0x02, sizeof(FxU32) << 1, SSTCP_PKT3_BDDDDD);
|
|
{
|
|
/* Lower right corner */
|
|
TRI_SET(x);
|
|
TRI_SET(y);
|
|
|
|
/* Upper right corner. */
|
|
y -= (0x01UL << (21UL - kNumMantissaBits));
|
|
TRI_SET(x);
|
|
TRI_SET(y);
|
|
|
|
/* Upper Left corner */
|
|
x -= (0x01UL << (21UL - kNumMantissaBits));
|
|
}
|
|
TRI_END;
|
|
|
|
/* Packet w/ actual point coordinate and parameter data */
|
|
TRI_PACKET_BEGIN(kSetupStrip | kSetupCullDisable, gc->cmdTransportInfo.paramMask,
|
|
1, _GlideRoot.curVertexSize, SSTCP_PKT3_DDDDDD);
|
|
{
|
|
TRI_SET(x);
|
|
TRI_SET(y);
|
|
|
|
/* Vertex parameters */
|
|
{
|
|
const int* dataList = gc->tsuDataList;
|
|
|
|
#if GLIDE_PACKED_RGB
|
|
if ((gc->cmdTransportInfo.paramMask & SSTCP_PKT3_PACKEDCOLOR) != 0) {
|
|
FxU32 packedColor = 0x00;
|
|
|
|
if (*dataList == (GR_VERTEX_R_OFFSET << 2)) {
|
|
packedColor = (RGBA_COMP_CLAMP(FARRAY(p, (GR_VERTEX_B_OFFSET << 2)), B) |
|
|
RGBA_COMP_CLAMP(FARRAY(p, (GR_VERTEX_G_OFFSET << 2)), G) |
|
|
RGBA_COMP_CLAMP(FARRAY(p, (GR_VERTEX_R_OFFSET << 2)), R));
|
|
|
|
dataList++;
|
|
}
|
|
|
|
if (*dataList == (GR_VERTEX_A_OFFSET << 2)) {
|
|
packedColor |= RGBA_COMP_CLAMP(FARRAY(p, (GR_VERTEX_A_OFFSET << 2)), A);
|
|
dataList++;
|
|
}
|
|
|
|
TRI_SET(packedColor);
|
|
}
|
|
#endif /* GLIDE_PACKED_RGB */
|
|
|
|
#if GLIDE_FP_CLAMP_TEX
|
|
while(*dataList != 0) {
|
|
TRI_SETF(FARRAY(p, *dataList));
|
|
dataList++;
|
|
}
|
|
|
|
dataList++;
|
|
#endif /* GLIDE_FP_CLAMP_TEX */
|
|
|
|
while(*dataList != 0) {
|
|
TRI_SETF_CLAMP(FARRAY(p, *dataList));
|
|
dataList++;
|
|
}
|
|
}
|
|
}
|
|
TRI_END;
|
|
GR_CHECK_SIZE();
|
|
|
|
_GlideRoot.stats.pointsDrawn++;
|
|
#else /* !(GLIDE_HW_TRI_SETUP && GLIDE_PACKET3_TRI_SETUP) */
|
|
/* GMT: gross overestimate of fifo requirements */
|
|
GR_SET_EXPECTED_SIZE(_GlideRoot.curTriSize, _GlideRoot.curTriSize >> 2);
|
|
{
|
|
const struct dataList_s* dlp = gc->regDataList;
|
|
int i;
|
|
|
|
#ifdef GLIDE_USE_ALT_REGMAP
|
|
hw = SST_WRAP(hw,128); /* use alternate register mapping */
|
|
#endif
|
|
|
|
GR_SET(BROADCAST_ID, hw, FvA.x, x);
|
|
GR_SET(BROADCAST_ID, hw, FvA.y, y);
|
|
|
|
x += (0x01UL << (22UL - kNumMantissaBits));
|
|
GR_SET(BROADCAST_ID, hw, FvB.x, x);
|
|
GR_SET(BROADCAST_ID, hw, FvB.y, y);
|
|
|
|
y += (0x01UL << (22UL - kNumMantissaBits));
|
|
GR_SET(BROADCAST_ID, hw, FvC.x, x);
|
|
GR_SET(BROADCAST_ID, hw, FvC.y, y);
|
|
|
|
i = _GlideRoot.stats.pointsDrawn++;
|
|
_GlideRoot.stats.pointsDrawn = ++i;
|
|
|
|
dlp = gc->regDataList;
|
|
i = dlp->i;
|
|
|
|
/* we don't care what the slopes are because the pixel center that is drawn */
|
|
/* is exactly at vertex A - isn't that wonderful */
|
|
while (i) {
|
|
GR_SETF_INDEX(BROADCAST_ID, hw, ((FxU32*)dlp->addr - (FxU32*)hw), FARRAY(p,i));
|
|
dlp++;
|
|
i = dlp->i;
|
|
}
|
|
|
|
GR_SET(BROADCAST_ID, hw, triangleCMD, 1);
|
|
}
|
|
GR_CHECK_SIZE();
|
|
#endif /* !(GLIDE_HW_TRI_SETUP && GLIDE_PACKET3_TRI_SETUP) */
|
|
|
|
GR_END();
|
|
#undef FN_NAME
|
|
} /* grDrawPoint */
|
|
|
|
/*---------------------------------------------------------------------------
|
|
** grDrawLine
|
|
**
|
|
** NOTE: 1. this will not fill the last pixel in line because
|
|
** B2 or C is on the right edge and the right edge is not
|
|
** drawn.
|
|
** (0,0)
|
|
**
|
|
** A(x1,y1-0.5)+
|
|
** | \
|
|
** | \ \
|
|
** (x1,y1)* \
|
|
** | * \
|
|
** | *\ \
|
|
** B1(x1,y1+0.5)+ * \
|
|
** \ \ * +B2(x2,y2-0.5)
|
|
** \ * |
|
|
** \ \ * |
|
|
** \ \ + (x2,y2)
|
|
** \ |
|
|
** \ |
|
|
** +C(x2,y2+0.5)
|
|
*/
|
|
|
|
GR_ENTRY(grDrawLine, void, (const GrVertex *a, const GrVertex *b))
|
|
{
|
|
#define FN_NAME "grDrawLine"
|
|
int i, j;
|
|
|
|
#define DX _GlideRoot.pool.ftemp1
|
|
#define ADY _GlideRoot.pool.ftemp2
|
|
|
|
GR_BEGIN_NOFIFOCHECK("grDrawLine", 91);
|
|
GDBG_INFO_MORE(gc->myLevel, "A: (%f %f) B: (%f %f)\n",
|
|
a->x, a->y, b->x, b->y);
|
|
|
|
GR_FLUSH_STATE();
|
|
|
|
/*
|
|
** compute absolute deltas and draw from low Y to high Y
|
|
*/
|
|
ADY = b->y - a->y;
|
|
i = *(long *)&ADY;
|
|
if (i < 0) {
|
|
const GrVertex *tv;
|
|
tv = a; a = b; b = tv;
|
|
i ^= 0x80000000; /* ady = -ady; */
|
|
(*(long *)&ADY) = i;
|
|
}
|
|
|
|
DX = b->x - a->x;
|
|
j = *(long *)&DX;
|
|
if (j < 0) {
|
|
j ^= 0x80000000; /* adx = -adx; */
|
|
}
|
|
|
|
/* check for zero-length lines */
|
|
if ((j >= i) && (j == 0)) goto all_done;
|
|
|
|
#if GLIDE_HW_TRI_SETUP && GLIDE_PACKET3_TRI_SETUP
|
|
/* One packet w/ 4 vertices */
|
|
GR_SET_EXPECTED_SIZE((_GlideRoot.curVertexSize << 2), 1);
|
|
{
|
|
const float* const fa = (float*)a;
|
|
const float* const fb = (float*)b;
|
|
|
|
/* Draw the triangle pair as a strip of 4 vertices.
|
|
* We can skip all of the gradient calculation stuff.
|
|
*
|
|
* NB: There are two cases, x/y major lines, and each of these
|
|
* loops are unrolled to send one set of endpoints of the 'line'
|
|
* per iteration since we can use the same bias per iteration.
|
|
*/
|
|
TRI_PACKET_BEGIN(kSetupCullDisable | kSetupStrip, gc->cmdTransportInfo.paramMask,
|
|
0x04UL, _GlideRoot.curVertexSize, SSTCP_PKT3_BDDDDD);
|
|
{
|
|
float fBias = - _GlideRoot.pool.fHalf;
|
|
int vIndex;
|
|
|
|
/* x macjor */
|
|
if (j >= i) {
|
|
for(vIndex = 0; vIndex < 2; vIndex++) {
|
|
TRI_SETF(fb[GR_VERTEX_X_OFFSET]);
|
|
TRI_SETF(fb[GR_VERTEX_Y_OFFSET] + fBias);
|
|
|
|
{
|
|
const int* dataList = gc->tsuDataList;
|
|
|
|
#if GLIDE_PACKED_RGB
|
|
if ((gc->cmdTransportInfo.paramMask & SSTCP_PKT3_PACKEDCOLOR) != 0) {
|
|
FxU32 packedColor = 0x00;
|
|
|
|
if (*dataList == (GR_VERTEX_R_OFFSET << 2)) {
|
|
packedColor = (RGBA_COMP_CLAMP(FARRAY(fb, (GR_VERTEX_B_OFFSET << 2)), B) |
|
|
RGBA_COMP_CLAMP(FARRAY(fb, (GR_VERTEX_G_OFFSET << 2)), G) |
|
|
RGBA_COMP_CLAMP(FARRAY(fb, (GR_VERTEX_R_OFFSET << 2)), R));
|
|
|
|
dataList++;
|
|
}
|
|
|
|
if (*dataList == (GR_VERTEX_A_OFFSET << 2)) {
|
|
packedColor |= RGBA_COMP_CLAMP(FARRAY(fb, (GR_VERTEX_A_OFFSET << 2)), A);
|
|
dataList++;
|
|
}
|
|
|
|
TRI_SET(packedColor);
|
|
}
|
|
#endif /* GLIDE_PACKED_RGB */
|
|
|
|
#if GLIDE_FP_CLAMP_TEX
|
|
while(*dataList != 0) {
|
|
TRI_SETF(FARRAY(fb, *dataList));
|
|
dataList++;
|
|
}
|
|
|
|
dataList++;
|
|
#endif /* GLIDE_FP_CLAMP_TEX */
|
|
|
|
while(*dataList != 0) {
|
|
TRI_SETF_CLAMP(FARRAY(fb, *dataList));
|
|
dataList++;
|
|
}
|
|
}
|
|
|
|
TRI_SETF(fa[GR_VERTEX_X_OFFSET]);
|
|
TRI_SETF(fa[GR_VERTEX_Y_OFFSET] + fBias);
|
|
|
|
{
|
|
const int* dataList = gc->tsuDataList;
|
|
|
|
#if GLIDE_PACKED_RGB
|
|
if ((gc->cmdTransportInfo.paramMask & SSTCP_PKT3_PACKEDCOLOR) != 0) {
|
|
FxU32 packedColor = 0x00;
|
|
|
|
if (*dataList == (GR_VERTEX_R_OFFSET << 2)) {
|
|
packedColor = (RGBA_COMP_CLAMP(FARRAY(fa, (GR_VERTEX_B_OFFSET << 2)), B) |
|
|
RGBA_COMP_CLAMP(FARRAY(fa, (GR_VERTEX_G_OFFSET << 2)), G) |
|
|
RGBA_COMP_CLAMP(FARRAY(fa, (GR_VERTEX_R_OFFSET << 2)), R));
|
|
|
|
dataList++;
|
|
}
|
|
|
|
if (*dataList == (GR_VERTEX_A_OFFSET << 2)) {
|
|
packedColor |= RGBA_COMP_CLAMP(FARRAY(fa, (GR_VERTEX_A_OFFSET << 2)), A);
|
|
dataList++;
|
|
}
|
|
|
|
TRI_SET(packedColor);
|
|
}
|
|
#endif /* GLIDE_PACKED_RGB */
|
|
|
|
#if GLIDE_FP_CLAMP_TEX
|
|
while(*dataList != 0) {
|
|
TRI_SETF(FARRAY(fa, *dataList));
|
|
dataList++;
|
|
}
|
|
|
|
dataList++;
|
|
#endif /* GLIDE_FP_CLAMP_TEX */
|
|
|
|
while (*dataList != 0) {
|
|
TRI_SETF_CLAMP(FARRAY(fa, *dataList));
|
|
dataList++;
|
|
}
|
|
}
|
|
|
|
fBias *= -1.0f;
|
|
}
|
|
} else { /* y major */
|
|
for(vIndex = 0; vIndex < 2; vIndex++) {
|
|
TRI_SETF(fb[GR_VERTEX_X_OFFSET] + fBias);
|
|
TRI_SETF(fb[GR_VERTEX_Y_OFFSET]);
|
|
|
|
{
|
|
const int* dataList = gc->tsuDataList;
|
|
|
|
#if GLIDE_PACKED_RGB
|
|
if ((gc->cmdTransportInfo.paramMask & SSTCP_PKT3_PACKEDCOLOR) != 0) {
|
|
FxU32 packedColor = 0x00;
|
|
|
|
if (*dataList == (GR_VERTEX_R_OFFSET << 2)) {
|
|
packedColor = (RGBA_COMP_CLAMP(FARRAY(fb, (GR_VERTEX_B_OFFSET << 2)), B) |
|
|
RGBA_COMP_CLAMP(FARRAY(fb, (GR_VERTEX_G_OFFSET << 2)), G) |
|
|
RGBA_COMP_CLAMP(FARRAY(fb, (GR_VERTEX_R_OFFSET << 2)), R));
|
|
|
|
dataList++;
|
|
}
|
|
|
|
if (*dataList == (GR_VERTEX_A_OFFSET << 2)) {
|
|
packedColor |= RGBA_COMP_CLAMP(FARRAY(fb, (GR_VERTEX_A_OFFSET << 2)), A);
|
|
dataList++;
|
|
}
|
|
|
|
TRI_SET(packedColor);
|
|
}
|
|
#endif /* GLIDE_PACKED_RGB */
|
|
|
|
#if GLIDE_FP_CLAMP_TEX
|
|
while(*dataList != 0) {
|
|
TRI_SETF(FARRAY(fb, *dataList));
|
|
dataList++;
|
|
}
|
|
|
|
dataList++;
|
|
#endif /* GLIDE_FP_CLAMP_TEX */
|
|
|
|
while (*dataList != 0) {
|
|
TRI_SETF_CLAMP(FARRAY(fb, *dataList));
|
|
dataList++;
|
|
}
|
|
}
|
|
|
|
TRI_SETF(fa[GR_VERTEX_X_OFFSET] + fBias);
|
|
TRI_SETF(fa[GR_VERTEX_Y_OFFSET]);
|
|
|
|
{
|
|
const int* dataList = gc->tsuDataList;
|
|
|
|
#if GLIDE_PACKED_RGB
|
|
if ((gc->cmdTransportInfo.paramMask & SSTCP_PKT3_PACKEDCOLOR) != 0) {
|
|
FxU32 packedColor = 0x00;
|
|
|
|
if (*dataList == (GR_VERTEX_R_OFFSET << 2)) {
|
|
packedColor = (RGBA_COMP_CLAMP(FARRAY(fa, (GR_VERTEX_B_OFFSET << 2)), B) |
|
|
RGBA_COMP_CLAMP(FARRAY(fa, (GR_VERTEX_G_OFFSET << 2)), G) |
|
|
RGBA_COMP_CLAMP(FARRAY(fa, (GR_VERTEX_R_OFFSET << 2)), R));
|
|
|
|
dataList++;
|
|
}
|
|
|
|
if (*dataList == (GR_VERTEX_A_OFFSET << 2)) {
|
|
packedColor |= RGBA_COMP_CLAMP(FARRAY(fa, (GR_VERTEX_A_OFFSET << 2)), A);
|
|
dataList++;
|
|
}
|
|
|
|
TRI_SET(packedColor);
|
|
}
|
|
#endif /* GLIDE_PACKED_RGB */
|
|
|
|
#if GLIDE_FP_CLAMP_TEX
|
|
while(*dataList != 0) {
|
|
TRI_SETF(FARRAY(fa, *dataList));
|
|
dataList++;
|
|
}
|
|
|
|
dataList++;
|
|
#endif /* GLIDE_FP_CLAMP_TEX */
|
|
|
|
while (*dataList != 0) {
|
|
TRI_SETF_CLAMP(FARRAY(fa, *dataList));
|
|
dataList++;
|
|
}
|
|
}
|
|
|
|
fBias *= -1.0f;
|
|
}
|
|
}
|
|
}
|
|
TRI_END;
|
|
}
|
|
GR_CHECK_SIZE();
|
|
#else /* !(GLIDE_HW_TRI_SETUP && GLIDE_PACKET3_TRI_SETUP) */
|
|
#ifdef GLIDE_USE_ALT_REGMAP
|
|
hw = SST_WRAP(hw,128); /* use alternate register mapping */
|
|
#endif
|
|
|
|
GR_SET_EXPECTED_SIZE(12 + _GlideRoot.curTriSize, (_GlideRoot.curTriSize + 12) >> 2);
|
|
{
|
|
float m, dp;
|
|
struct dataList_s* dlp;
|
|
|
|
/*
|
|
** X major line
|
|
*/
|
|
if (j >= i) { /* if (adx > ady) */
|
|
if (j == 0) goto all_done; /* check for zero-length lines */
|
|
/* start up divide and overlap with as much integer stuff as possible*/
|
|
m = _GlideRoot.pool.f1 / DX;
|
|
dlp = gc->regDataList;
|
|
GR_SETF(BROADCAST_ID, hw, FvA.x, a->x);
|
|
dp = b->x;
|
|
GR_SETF(BROADCAST_ID, hw, FvB.x, dp);
|
|
GR_SETF(BROADCAST_ID, hw, FvC.x, dp);
|
|
|
|
GR_SETF(BROADCAST_ID, hw, FvA.y, a->y - _GlideRoot.pool.fHalf);
|
|
|
|
dp = b->y;
|
|
GR_SETF(BROADCAST_ID, hw, FvB.y, dp - _GlideRoot.pool.fHalf);
|
|
|
|
i = dlp->i;
|
|
GR_SETF(BROADCAST_ID, hw, FvC.y, dp + _GlideRoot.pool.fHalf);
|
|
|
|
while (i) {
|
|
dp = FARRAY(a,i);
|
|
GR_SETF_INDEX(BROADCAST_ID, hw,
|
|
((FxU32*)dlp->addr - (FxU32*)hw), dp);
|
|
|
|
dp = FARRAY(b,i) - dp;
|
|
GR_SETF_INDEX(BROADCAST_ID, hw,
|
|
((FxU32*)&dlp->addr[DPDX_OFFSET >> 2] - (FxU32*)hw), dp * m);
|
|
|
|
dlp++;
|
|
i = dlp->i;
|
|
GR_SETF_INDEX(BROADCAST_ID, hw,
|
|
((FxU32*)&dlp->addr[DPDY_OFFSET >> 2] - (FxU32*)hw), _GlideRoot.pool.f0);
|
|
}
|
|
GR_SETF(BROADCAST_ID, hw, FtriangleCMD,_GlideRoot.pool.ftemp1);
|
|
|
|
GR_SETF(BROADCAST_ID, hw, FvB.x,a->x);
|
|
GR_SETF(BROADCAST_ID, hw, FvB.y,a->y + _GlideRoot.pool.fHalf);
|
|
GR_SETF(BROADCAST_ID, hw, FtriangleCMD,-_GlideRoot.pool.ftemp1);
|
|
}
|
|
|
|
/*
|
|
** Y major line
|
|
*/
|
|
else {
|
|
m = _GlideRoot.pool.f1 / ADY;
|
|
dlp = gc->regDataList;
|
|
GR_SETF(BROADCAST_ID, hw, FvA.y,a->y);
|
|
dp = b->y;
|
|
GR_SETF(BROADCAST_ID, hw, FvB.y,dp);
|
|
GR_SETF(BROADCAST_ID, hw, FvC.y,dp);
|
|
|
|
GR_SETF(BROADCAST_ID, hw, FvA.x,a->x - _GlideRoot.pool.fHalf);
|
|
|
|
dp = b->x;
|
|
GR_SETF(BROADCAST_ID, hw, FvB.x,dp - _GlideRoot.pool.fHalf);
|
|
|
|
i = dlp->i;
|
|
GR_SETF(BROADCAST_ID, hw, FvC.x,dp + _GlideRoot.pool.fHalf);
|
|
|
|
while (i) {
|
|
dp = FARRAY(a,i);
|
|
GR_SETF_INDEX(BROADCAST_ID, hw, ((FxU32*)dlp->addr - (FxU32*)hw), dp);
|
|
|
|
dp = FARRAY(b,i) - dp;
|
|
GR_SETF_INDEX(BROADCAST_ID, hw,
|
|
((FxU32*)&dlp->addr[DPDX_OFFSET >> 2] - (FxU32*)hw), _GlideRoot.pool.f0);
|
|
|
|
dlp++;
|
|
i = dlp->i;
|
|
GR_SETF_INDEX(BROADCAST_ID, hw,
|
|
((FxU32*)&dlp->addr[DPDY_OFFSET >> 2] - (FxU32*)hw), dp * m);
|
|
}
|
|
GR_SET(BROADCAST_ID, hw, triangleCMD, 0xFFFFFFFF);
|
|
|
|
GR_SETF(BROADCAST_ID, hw, FvB.x, a->x + _GlideRoot.pool.fHalf);
|
|
GR_SETF(BROADCAST_ID, hw, FvB.y, a->y);
|
|
GR_SET(BROADCAST_ID, hw, triangleCMD, 1);
|
|
}
|
|
}
|
|
GR_CHECK_SIZE();
|
|
#endif /* !(GLIDE_HW_TRI_SETUP && GLIDE_PACKET3_TRI_SETUP) */
|
|
|
|
all_done: /* come here on degenerate lines */
|
|
_GlideRoot.stats.linesDrawn++;
|
|
|
|
GR_END();
|
|
#undef FN_NAME
|
|
} /* grDrawLine */
|
|
|
|
/*---------------------------------------------------------------------------
|
|
** grDrawTriangle
|
|
*/
|
|
|
|
GR_ENTRY(grDrawTriangle, void, (const GrVertex *a, const GrVertex *b, const GrVertex *c))
|
|
{
|
|
#define FN_NAME grDrawTriangle
|
|
#if defined(GLIDE_USE_C_TRISETUP) || defined(__WATCOMC__) || defined(GLIDE_DEBUG)
|
|
GR_BEGIN_NOFIFOCHECK("grDrawTriangle",92);
|
|
GDBG_INFO_MORE(gc->myLevel,"(0x%x,0x%x,0x%x)\n",a,b,c);
|
|
GR_CHECK_F(myName, !a || !b || !c, "NULL pointer passed");
|
|
|
|
GR_FLUSH_STATE();
|
|
|
|
/* Silly warning killer */
|
|
if (0) goto all_done;
|
|
|
|
#ifdef GLIDE_DEBUG
|
|
if (_GlideRoot.environment.triBoundsCheck) {
|
|
if (OUTBOUNDS(a) || OUTBOUNDS(b) || OUTBOUNDS(c)) {
|
|
GDBG_PRINTF("Triangle out of bounds:\n");
|
|
GDBG_PRINTF("a->x = %3.2f, a->y = %3.2f\n", a->x, a->y);
|
|
GDBG_PRINTF("b->x = %3.2f, b->y = %3.2f\n", b->x, b->y);
|
|
GDBG_PRINTF("c->x = %3.2f, c->y = %3.2f\n", c->x, c->y);
|
|
GDBG_PRINTF("Culling triangle based on these bogus values.\n");
|
|
goto all_done;
|
|
}
|
|
}
|
|
#endif /* GLIDE_DEBUG */
|
|
|
|
/* _trisetup and _trisetup_asm return 0 if culled, 1 if drawn */
|
|
#if GLIDE_DEBUG && !GLIDE_USE_C_TRISETUP
|
|
/* HackAlert: Nuke the fifo ptr checking stuff here if we're just
|
|
* debugging teh asm tri code.
|
|
*/
|
|
if (TRISETUP(a, b, c) != 0) {
|
|
gc->checkPtr = (FxU32)gc->cmdTransportInfo.fifoPtr;
|
|
gc->checkCounter = 0;
|
|
}
|
|
#else
|
|
TRISETUP(a, b, c);
|
|
#endif
|
|
|
|
all_done:
|
|
GR_END();
|
|
#else
|
|
#if defined(__MSC__)
|
|
{
|
|
extern struct _GlideRoot_s _GlideRoot;
|
|
|
|
_asm {
|
|
mov eax, [_GlideRoot + kCurGCOffset];
|
|
mov eax, [eax + kTriProcOffset];
|
|
jmp eax;
|
|
}
|
|
}
|
|
#endif
|
|
#if defined( __linux__ )
|
|
|
|
/* Here's the basic strategy for this dispatch code:
|
|
* We jump to _GlideRoot.curGC->archDispatchProcs.triSetupProc
|
|
* which contains code that looks like a function, we leave the
|
|
* paramters passed to grDrawTriangle on the stack and the dispatched
|
|
* function picks them up. However we have to compensate for
|
|
* the compiler pushing anything on the stack. The following describes
|
|
* why and when we have to pop.
|
|
*
|
|
* BIG_OPT: gcc pushes a frame pointer to maintain things, BIG_OPT
|
|
* turns on -fomit-frame-pointer so we don't have to pop it.
|
|
*
|
|
* PIC: When using position independant code gcc stores eip in ebx
|
|
* so it saves ebx from the previous call automatically.
|
|
* Therefore, once we have the jump address we have to pop ebx
|
|
* to restore the stack.
|
|
*
|
|
* The syntax is further complicated by the fact that gcc can (and will)
|
|
* emit code between the asm statements, so they all need to be in a single
|
|
* asm statement, wrapped with #ifdef's. This means we have fun with
|
|
* deciding if we need to list trashed registers and when we need commas
|
|
* between them.
|
|
*/
|
|
|
|
asm (
|
|
#if defined(PIC)
|
|
"popl %%ebx\n\t"
|
|
#endif
|
|
#if !defined(BIG_OPT)
|
|
"popl %%ebp\n\t"
|
|
#endif
|
|
"jmp *%0"
|
|
: /* no outputs */
|
|
: "m" (_GlideRoot.curGC->cmdTransportInfo.triSetupProc)
|
|
#if defined (PIC) || !defined (BIG_OPT)
|
|
:
|
|
#endif
|
|
#if defined (PIC)
|
|
"ebx"
|
|
#endif
|
|
#if defined (PIC) && !defined (BIG_OPT)
|
|
,
|
|
#endif
|
|
#if !defined(BIG_OPT)
|
|
"ebp"
|
|
#endif
|
|
);
|
|
#endif
|
|
#endif
|
|
#undef FN_NAME
|
|
} /* grDrawTriangle */
|
|
|
|
/*---------------------------------------------------------------------------
|
|
** grDrawPlanarPolygon
|
|
**
|
|
** Brute force "triangle-fan" implementation of a convex polygon drawer.
|
|
*/
|
|
GR_ENTRY(grDrawPlanarPolygon,
|
|
void,
|
|
(int nVerts, const int iList[], const GrVertex vList[]))
|
|
{
|
|
GR_BEGIN_NOFIFOCHECK("grDrawPlanarPolygon",93);
|
|
GDBG_INFO_MORE(gc->myLevel,"(%d,0x%x,0x%x)\n",nVerts,iList,vList);
|
|
GR_CHECK_F(myName, !iList || !vList, "NULL pointer passed");
|
|
|
|
GR_FLUSH_STATE();
|
|
|
|
#if GLIDE_HW_TRI_SETUP && GLIDE_PACKET3_TRI_SETUP
|
|
grDrawPolygon(nVerts, iList, vList);
|
|
#else /* !(GLIDE_HW_TRI_SETUP && GLIDE_PACKET3_TRI_SETUP) */
|
|
{
|
|
int n,i = nVerts-2;
|
|
const GrVertex *firstv = &vList[iList[0]];
|
|
|
|
for (i = 1; i < nVerts - 1; i++) {
|
|
n = TRISETUP(firstv, &vList[iList[i]], &vList[iList[i+1]]);
|
|
if (n > 0) break; /* stop after 1st non-zero-area triangle */
|
|
if (n < 0) goto all_done;
|
|
}
|
|
/* now all the gradients are loaded into the chip, so we just have to */
|
|
/* draw all the rest of the triangles */
|
|
for (i = i+1; i < nVerts - 1; i++) {
|
|
_trisetup_nogradients(firstv, &vList[iList[i]], &vList[iList[i+1]]);
|
|
}
|
|
}
|
|
all_done:
|
|
#endif /* !(GLIDE_HW_TRI_SETUP && GLIDE_PACKET3_TRI_SETUP) */
|
|
|
|
GR_END();
|
|
} /* grDrawPlanarPolygon */
|
|
|
|
/*---------------------------------------------------------------------------
|
|
** grDrawPlanarPolygonVertexList
|
|
**
|
|
** Brute force "triangle-fan" implementation of a convex polygon drawer.
|
|
*/
|
|
|
|
GR_ENTRY(grDrawPlanarPolygonVertexList, void, (int nVerts, const GrVertex vList[]))
|
|
{
|
|
GR_BEGIN_NOFIFOCHECK("grDrawPlanarPolygonVertexList",93);
|
|
GDBG_INFO_MORE(gc->myLevel,"(%d,0x%x)\n",nVerts,vList);
|
|
GR_CHECK_F(myName, !vList, "NULL pointer passed");
|
|
|
|
GR_FLUSH_STATE();
|
|
|
|
#if GLIDE_HW_TRI_SETUP && GLIDE_PACKET3_TRI_SETUP
|
|
grDrawPolygonVertexList(nVerts, vList);
|
|
#else /* !(GLIDE_HW_TRI_SETUP && GLIDE_PACKET3_TRI_SETUP) */
|
|
{
|
|
int n,i = nVerts-2;
|
|
const GrVertex *firstv = &vList[0];
|
|
|
|
for (i = 1; i < nVerts - 1; i++) {
|
|
n = TRISETUP(firstv, &vList[i], &vList[i+1]);
|
|
if (n > 0) break; /* stop after 1st non-zero-area triangle */
|
|
if (n < 0) goto all_done;
|
|
}
|
|
/* now all the gradients are loaded into the chip, so we just have to */
|
|
/* draw all the rest of the triangles */
|
|
for (i = i+1; i < nVerts - 1; i++) {
|
|
_trisetup_nogradients(firstv, &vList[i], &vList[i+1]);
|
|
}
|
|
|
|
all_done:
|
|
;
|
|
}
|
|
#endif /* !(GLIDE_HW_TRI_SETUP && GLIDE_PACKET3_TRI_SETUP) */
|
|
|
|
GR_END();
|
|
} /* grDrawPlanarPolygonVertexList */
|
|
|
|
#if GLIDE_HW_TRI_SETUP && GLIDE_PACKET3_TRI_SETUP
|
|
#define kMaxPacket3Vertex 0x0FUL
|
|
|
|
/* Packet 3 requires at least one vertex, if there isn't enough room
|
|
* in the fifo then force a wrap now and write up to the max.
|
|
*/
|
|
#define FIFO_VERT(__vertSize, __polyVerts) \
|
|
((gc->cmdTransportInfo.fifoRoom < (FxI32)(sizeof(FxU32) + (__vertSize))) \
|
|
? (__polyVerts) \
|
|
: MIN((__polyVerts), ((gc->cmdTransportInfo.fifoRoom - sizeof(FxU32)) / (__vertSize))))
|
|
|
|
#define FIFO_MAX_VERT(__polyVerts) MIN(kMaxPacket3Vertex, (__polyVerts))
|
|
#endif /* GLIDE_HW_TRI_SETUP && GLIDE_PACKET3_TRI_SETUP */
|
|
|
|
/*---------------------------------------------------------------------------
|
|
** grDrawPolygon
|
|
**
|
|
** Brute force "triangle-fan" implementation of a convex polygon drawer.
|
|
*/
|
|
|
|
GR_ENTRY(grDrawPolygon, void, (int nVerts, const int iList[], const GrVertex vList[]))
|
|
{
|
|
#define FN_NAME "grDrawPolygon"
|
|
GR_BEGIN_NOFIFOCHECK("grDrawPolygon",93);
|
|
GDBG_INFO_MORE(gc->myLevel,"(%d,0x%x,0x%x)\n",nVerts,iList,vList);
|
|
GR_CHECK_F(myName, !iList || !vList, "NULL pointer passed");
|
|
|
|
GR_FLUSH_STATE();
|
|
|
|
/* Zero length vertex lists are allowed, but we can't send them to
|
|
* the hw.
|
|
*/
|
|
if (nVerts <= 0) goto __exitNoVerts;
|
|
|
|
#if GLIDE_HW_TRI_SETUP && GLIDE_PACKET3_TRI_SETUP
|
|
{
|
|
const FxU32 vertexParamOffset = _GlideRoot.curVertexSize;
|
|
const int* vertexIndexP = iList;
|
|
FxU32 packVertMax = FIFO_MAX_VERT(nVerts); /* Max possible verts for this packet */
|
|
FxU32 packVerts = FIFO_VERT(vertexParamOffset, packVertMax); /* # verts for this packet */
|
|
FxU32 packType = SSTCP_PKT3_BDDDDD;
|
|
|
|
__doPolyVertexSend:
|
|
{
|
|
const FxU32 packSize = packVerts * vertexParamOffset;
|
|
FxU32 vertexOffset;
|
|
|
|
GR_ASSERT((packSize % vertexParamOffset) == 0);
|
|
GR_ASSERT(packSize >= vertexParamOffset);
|
|
|
|
GR_SET_EXPECTED_SIZE(packSize, 1);
|
|
TRI_STRIP_BEGIN(kSetupFan,
|
|
packSize / vertexParamOffset, vertexParamOffset,
|
|
packType);
|
|
for(vertexOffset = 0; vertexOffset < packSize; vertexOffset += vertexParamOffset) {
|
|
const float* vertex = (const float*)(vList + *vertexIndexP++);
|
|
|
|
TRI_SETF(vertex[GR_VERTEX_X_OFFSET]);
|
|
TRI_SETF(vertex[GR_VERTEX_Y_OFFSET]);
|
|
|
|
{
|
|
const int* dataList = gc->tsuDataList;
|
|
|
|
#if GLIDE_PACKED_RGB
|
|
{
|
|
FxBool doColorP = FXFALSE;
|
|
FxU32 packedColor = 0x00;
|
|
|
|
if (*dataList == (GR_VERTEX_R_OFFSET << 2)) {
|
|
packedColor = (RGBA_COMP_CLAMP(FARRAY(vertex, (GR_VERTEX_B_OFFSET << 2)), B) |
|
|
RGBA_COMP_CLAMP(FARRAY(vertex, (GR_VERTEX_G_OFFSET << 2)), G) |
|
|
RGBA_COMP_CLAMP(FARRAY(vertex, (GR_VERTEX_R_OFFSET << 2)), R));
|
|
doColorP = FXTRUE;
|
|
dataList++;
|
|
}
|
|
|
|
if (*dataList == (GR_VERTEX_A_OFFSET << 2)) {
|
|
packedColor |= RGBA_COMP_CLAMP(FARRAY(vertex, (GR_VERTEX_A_OFFSET << 2)), A);
|
|
doColorP = FXTRUE;
|
|
dataList++;
|
|
}
|
|
|
|
if (doColorP) TRI_SET(packedColor);
|
|
}
|
|
#endif /* GLIDE_PACKED_RGB */
|
|
|
|
#if GLIDE_FP_CLAMP_TEX
|
|
while(*dataList != 0) {
|
|
TRI_SETF(FARRAY(vertex, *dataList));
|
|
dataList++;
|
|
}
|
|
|
|
dataList++;
|
|
#endif /* GLIDE_FP_CLAMP_TEX */
|
|
|
|
while (*dataList != 0) {
|
|
TRI_SETF_CLAMP(FARRAY(vertex, *dataList));
|
|
dataList++;
|
|
}
|
|
}
|
|
}
|
|
TRI_END;
|
|
GR_CHECK_SIZE();
|
|
}
|
|
|
|
/* Are there more vertices that need to be sent for this
|
|
* polygon? Reset the parameters and do the rest of them.
|
|
*/
|
|
if (vertexIndexP < iList + nVerts) {
|
|
/* Reset the # of verts maxing out the send based on the
|
|
* space left in the fifo and the max packet size.
|
|
*/
|
|
nVerts -= packVerts;
|
|
packVertMax = FIFO_MAX_VERT(nVerts); /* Max possible verts for this packet */
|
|
packVerts = FIFO_VERT(vertexParamOffset, packVertMax); /* # verts for this packet */
|
|
|
|
packType = SSTCP_PKT3_DDDDDD;
|
|
|
|
GDBG_INFO(120, "\tSending continueing polygon data (0x%X : 0x%X)\n", nVerts, packVerts);
|
|
|
|
goto __doPolyVertexSend;
|
|
}
|
|
}
|
|
#else /* !(GLIDE_HW_TRI_SETUP && GLIDE_PACKET3_TRI_SETUP) */
|
|
{
|
|
int i;
|
|
for (i = 1; i < nVerts - 1; i++) {
|
|
grDrawTriangle(&vList[iList[0]], &vList[iList[i]], &vList[iList[i+1]]);
|
|
}
|
|
}
|
|
#endif /* !(GLIDE_HW_TRI_SETUP && GLIDE_PACKET3_TRI_SETUP) */
|
|
|
|
__exitNoVerts:
|
|
GR_END();
|
|
#undef FN_NAME
|
|
} /* grDrawPolygon */
|
|
|
|
/*---------------------------------------------------------------------------
|
|
** grDrawPolygonVertexList
|
|
**
|
|
** Brute force "triangle-fan" implementation of a convex polygon drawer.
|
|
*/
|
|
|
|
GR_ENTRY(grDrawPolygonVertexList, void, (int nVerts, const GrVertex vList[]))
|
|
{
|
|
#define FN_NAME "grDrawPolygonVertexList"
|
|
GR_BEGIN_NOFIFOCHECK("grDrawPolygonVertexList", 92);
|
|
GDBG_INFO_MORE(gc->myLevel,"(%d,0x%x)\n",nVerts,vList);
|
|
GR_CHECK_F(myName, !vList, "NULL pointer passed");
|
|
|
|
GR_FLUSH_STATE();
|
|
|
|
/* Zero length vertex lists are allowed, but we can't send them to
|
|
* the hw.
|
|
*/
|
|
if (nVerts <= 0) goto __exitNoVerts;
|
|
|
|
#if GLIDE_HW_TRI_SETUP && GLIDE_PACKET3_TRI_SETUP
|
|
{
|
|
const FxU32 vertexParamOffset = _GlideRoot.curVertexSize;
|
|
const GrVertex* vertexListP = vList;
|
|
FxU32 packVertMax = FIFO_MAX_VERT(nVerts); /* Max possible verts for this packet */
|
|
FxU32 packVerts = FIFO_VERT(vertexParamOffset, packVertMax); /* # verts for this packet */
|
|
FxU32 packType = SSTCP_PKT3_BDDDDD;
|
|
|
|
__doPolyVertexSend:
|
|
GR_ASSERT(packVerts > 0);
|
|
GR_ASSERT(packVerts <= kMaxPacket3Vertex);
|
|
|
|
{
|
|
const FxU32 packSize = packVerts * vertexParamOffset;
|
|
FxU32 vertexOffset;
|
|
|
|
GR_SET_EXPECTED_SIZE(packSize, 1);
|
|
TRI_STRIP_BEGIN(kSetupFan, packVerts, vertexParamOffset, packType);
|
|
|
|
for(vertexOffset = 0; vertexOffset < packSize; vertexOffset += vertexParamOffset) {
|
|
const float* vertex = (const float*)vertexListP++;
|
|
|
|
TRI_SETF(vertex[GR_VERTEX_X_OFFSET]);
|
|
TRI_SETF(vertex[GR_VERTEX_Y_OFFSET]);
|
|
|
|
{
|
|
const int* dataList = gc->tsuDataList;
|
|
|
|
#if GLIDE_PACKED_RGB
|
|
/* dpc - 10 feb 1998 -
|
|
* Some apps send color values outside of the range [0..255]
|
|
*/
|
|
#undef RGBA_COMP
|
|
#define RGBA_COMP(__fpVal, __fpBias, __fpShift, __fpMask) \
|
|
((_GlideRoot.pool.ftemp1 = (float)((float)(__fpVal) + (float)(__fpBias))), \
|
|
((((float)(__fpVal)) > 255.0f) \
|
|
? (__fpMask) \
|
|
: ((((float)(__fpVal)) < 0.0f) \
|
|
? 0x00UL \
|
|
: ((*(const FxU32*)&_GlideRoot.pool.ftemp1) & (__fpMask)))) << (__fpShift))
|
|
|
|
{
|
|
FxBool doColorP = FXFALSE;
|
|
FxU32 packedColor = 0x00;
|
|
|
|
if (*dataList == (GR_VERTEX_R_OFFSET << 2)) {
|
|
packedColor = (RGBA_COMP_CLAMP(FARRAY(vertex, (GR_VERTEX_B_OFFSET << 2)), B) |
|
|
RGBA_COMP_CLAMP(FARRAY(vertex, (GR_VERTEX_G_OFFSET << 2)), G) |
|
|
RGBA_COMP_CLAMP(FARRAY(vertex, (GR_VERTEX_R_OFFSET << 2)), R));
|
|
doColorP = FXTRUE;
|
|
dataList++;
|
|
}
|
|
|
|
if (*dataList == (GR_VERTEX_A_OFFSET << 2)) {
|
|
packedColor |= RGBA_COMP_CLAMP(FARRAY(vertex, (GR_VERTEX_A_OFFSET << 2)), A);
|
|
doColorP = FXTRUE;
|
|
dataList++;
|
|
}
|
|
|
|
if (doColorP) TRI_SET(packedColor);
|
|
}
|
|
#endif /* GLIDE_PACKED_RGB */
|
|
|
|
#if GLIDE_FP_CLAMP_TEX
|
|
while(*dataList != 0) {
|
|
TRI_SETF(FARRAY(vertex, *dataList));
|
|
dataList++;
|
|
}
|
|
|
|
dataList++;
|
|
#endif /* GLIDE_FP_CLAMP_TEX */
|
|
|
|
while (*dataList != 0) {
|
|
TRI_SETF_CLAMP(FARRAY(vertex, *dataList));
|
|
dataList++;
|
|
}
|
|
}
|
|
}
|
|
TRI_END;
|
|
GR_CHECK_SIZE();
|
|
}
|
|
|
|
/* More verts? */
|
|
if (vertexListP < vList + nVerts) {
|
|
/* Reset the # of verts maxing out the send based on the
|
|
* space left in the fifo and the max packet size.
|
|
*/
|
|
nVerts -= packVerts;
|
|
packVertMax = FIFO_MAX_VERT(nVerts); /* Max possible verts for this packet */
|
|
packVerts = FIFO_VERT(vertexParamOffset, packVertMax); /* # verts for this packet */
|
|
|
|
/* Packet type to continue strip */
|
|
packType = SSTCP_PKT3_DDDDDD;
|
|
|
|
GDBG_INFO(120, "\tSending continueing polygon data (0x%X : 0x%X)\n", packVerts, nVerts);
|
|
|
|
goto __doPolyVertexSend;
|
|
}
|
|
}
|
|
#else /* !(GLIDE_HW_TRI_SETUP && GLIDE_PACKET3_TRI_SETUP) */
|
|
{
|
|
int i;
|
|
|
|
for (i = 1; i < nVerts - 1; i++) {
|
|
grDrawTriangle(&vList[0], &vList[i], &vList[i+1]);
|
|
}
|
|
}
|
|
#endif /* !(GLIDE_HW_TRI_SETUP && GLIDE_PACKET3_TRI_SETUP) */
|
|
|
|
__exitNoVerts:
|
|
GR_END();
|
|
#undef FN_NAME
|
|
} /* grDrawPolygonVertexList */
|
|
|
|
/*---------------------------------------------------------------------------
|
|
** _grColorCombineDelta0Mode
|
|
**
|
|
** GMT: when we are in delta0 mode, color comes from the RGB iterators
|
|
** but the slopes are 0.0. So when we enter delta0 mode we set
|
|
** the iterators up and then we leave them alone during primitive
|
|
** rendering
|
|
*/
|
|
|
|
GR_DDFUNC(_grColorCombineDelta0Mode, void, (FxBool delta0mode))
|
|
{
|
|
#define FN_NAME "_grColorCombineDelta0Mode"
|
|
GR_BEGIN_NOFIFOCHECK("_grColorCombineDelta0Mode",85);
|
|
GDBG_INFO_MORE(gc->myLevel,"(%d)\n",delta0mode);
|
|
|
|
if (delta0mode) {
|
|
GR_SET_EXPECTED_SIZE(9 << 2, 9);
|
|
{
|
|
GR_SETF(BROADCAST_ID, hw, Fr, gc->state.r);
|
|
GR_SETF(BROADCAST_ID, hw, Fg, gc->state.g);
|
|
GR_SETF(BROADCAST_ID, hw, Fb, gc->state.b);
|
|
GR_SET(BROADCAST_ID, hw, drdx, 0);
|
|
GR_SET(BROADCAST_ID, hw, drdy, 0);
|
|
GR_SET(BROADCAST_ID, hw, dgdx, 0);
|
|
GR_SET(BROADCAST_ID, hw, dgdy, 0);
|
|
GR_SET(BROADCAST_ID, hw, dbdx, 0);
|
|
GR_SET(BROADCAST_ID, hw, dbdy, 0);
|
|
}
|
|
GR_CHECK_SIZE();
|
|
}
|
|
|
|
gc->state.cc_delta0mode = delta0mode;
|
|
GR_END();
|
|
#undef FN_NAME
|
|
} /* _grColorCombineDeltaMode */
|
|
|