Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

556 lines
16 KiB

/*
** Copyright 1991, Silicon Graphics, Inc.
** All Rights Reserved.
**
** This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
** the contents of this file may not be disclosed to third parties, copied or
** duplicated in any form, in whole or in part, without the prior written
** permission of Silicon Graphics, Inc.
**
** RESTRICTED RIGHTS LEGEND:
** 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.
**
** $Revision: 1.16 $
** $Date: 1993/09/23 16:33:23 $
*/
#include "precomp.h"
#pragma hdrstop
/*
** Clip an input polygon against a clipping plane outputing the new
** vertex pointers in ov and return the number of them. See the line
** clipping code for an in depth discussion of how "t" is computed.
**
** NOTE: In order to handle non-convex polygons here without dying,
** we count the number of verticies generated by clipping. If the
** count ever gets to 3, then it must be a non-convex polygon (because
** it means the polygon crossed the clipping plane three times, which is
** impossible for a convex polygon).
*/
static GLint clipToPlane(__GLcontext *gc, __GLvertex **iv, GLint niv,
__GLvertex **ov, GLuint offs, GLboolean negate)
{
GLint i, nout, generated;
__GLvertex *s, *p, *newVertex, *temp;
__GLfloat pDist, sDist, t;
PFN_VERTEX_CLIP_PROC clip;
nout = 0;
generated = 0;
temp = gc->transform.nextClipTemp;
clip = gc->procs.polyClipParam;
s = iv[niv-1];
if (negate)
{
sDist = s->clip.w - *(__GLfloat *)((GLubyte *)s + offs);
}
else
{
sDist = *(__GLfloat *)((GLubyte *)s + offs) + s->clip.w;
}
for (i = 0; i < niv; i++) {
p = iv[i];
if (negate)
{
pDist = p->clip.w - *(__GLfloat *)((GLubyte *)p + offs);
}
else
{
pDist = *(__GLfloat *)((GLubyte *)p + offs) + p->clip.w;
}
if (__GL_FLOAT_GEZ(pDist)) {
/* p is inside the clipping plane half space */
if (__GL_FLOAT_GEZ(sDist)) {
/* s is inside the clipping plane half space */
*ov++ = p;
nout++;
} else {
/* s is outside the clipping plane half space */
t = pDist / (pDist - sDist);
newVertex = temp++;
(*clip)(newVertex, s, p, t);
#ifndef NT
// edgeflag is now part of has field.
newVertex->boundaryEdge = s->boundaryEdge;
#endif
newVertex->has = s->has;
newVertex->clipCode = s->clipCode;
assert(newVertex->color == &newVertex->colors[__GL_FRONTFACE]);
*ov++ = newVertex;
*ov++ = p;
nout += 2;
if (++generated >= 3) {
/* Toss the non-convex polygon */
return 0;
}
}
} else {
/* p is outside the clipping plane half space */
if (__GL_FLOAT_GEZ(sDist)) {
/*
** s is inside the clipping plane half space
**
** NOTE: To avoid cracking in polygons with shared
** clipped edges we always compute "t" from the out
** vertex to the in vertex. The above clipping code gets
** this for free (p is in and s is out). In this code p
** is out and s is in, so we reverse the t computation
** and the argument order to __glDoClip.
*/
t = sDist / (sDist - pDist);
newVertex = temp++;
(*clip)(newVertex, p, s, t);
#ifdef NT
// edgeflag is now part of has field.
newVertex->has = s->has | __GL_HAS_EDGEFLAG_BOUNDARY;
newVertex->clipCode = p->clipCode;
#else
newVertex->boundaryEdge = GL_TRUE;
newVertex->has = s->has;
#endif
assert(newVertex->color == &newVertex->colors[__GL_FRONTFACE]);
*ov++ = newVertex;
nout++;
if (++generated >= 3) {
/* Toss the non-convex polygon */
return 0;
}
} else {
/* both points are outside */
}
}
s = p;
sDist = pDist;
}
gc->transform.nextClipTemp = temp;
return nout;
}
/*
** Identical to clipToPlane(), except that the clipping is done in eye
** space.
*/
static GLint clipToPlaneEye(__GLcontext *gc, __GLvertex **iv, GLint niv,
__GLvertex **ov, __GLcoord *plane)
{
GLint i, nout, generated;
__GLvertex *s, *p, *newVertex, *temp;
__GLfloat pDist, sDist, t;
PFN_VERTEX_CLIP_PROC clip;
nout = 0;
generated = 0;
temp = gc->transform.nextClipTemp;
clip = gc->procs.polyClipParam;
s = iv[niv-1];
sDist = (((POLYDATA *)s)->eye.x * plane->x) +
(((POLYDATA *)s)->eye.y * plane->y) +
(((POLYDATA *)s)->eye.z * plane->z) +
(((POLYDATA *)s)->eye.w * plane->w);
for (i = 0; i < niv; i++) {
p = iv[i];
pDist = (((POLYDATA *)p)->eye.x * plane->x) +
(((POLYDATA *)p)->eye.y * plane->y) +
(((POLYDATA *)p)->eye.z * plane->z) +
(((POLYDATA *)p)->eye.w * plane->w);
if (__GL_FLOAT_GEZ(pDist)) {
/* p is inside the clipping plane half space */
if (__GL_FLOAT_GEZ(sDist)) {
/* s is inside the clipping plane half space */
*ov++ = p;
nout++;
} else {
/* s is outside the clipping plane half space */
t = pDist / (pDist - sDist);
newVertex = temp++;
(*clip)(newVertex, s, p, t);
((POLYDATA *)newVertex)->eye.x =
t*(((POLYDATA *)s)->eye.x - ((POLYDATA *)p)->eye.x) +
((POLYDATA *)p)->eye.x;
((POLYDATA *)newVertex)->eye.y =
t*(((POLYDATA *)s)->eye.y - ((POLYDATA *)p)->eye.y) +
((POLYDATA *)p)->eye.y;
((POLYDATA *)newVertex)->eye.z =
t*(((POLYDATA *)s)->eye.z - ((POLYDATA *)p)->eye.z) +
((POLYDATA *)p)->eye.z;
((POLYDATA *)newVertex)->eye.w =
t*(((POLYDATA *)s)->eye.w - ((POLYDATA *)p)->eye.w) +
((POLYDATA *)p)->eye.w;
#ifndef NT
// edgeflag is now part of has field.
newVertex->boundaryEdge = s->boundaryEdge;
#endif
newVertex->has = s->has;
newVertex->clipCode = s->clipCode;
assert(newVertex->color == &newVertex->colors[__GL_FRONTFACE]);
*ov++ = newVertex;
*ov++ = p;
nout += 2;
if (++generated >= 3) {
/* Toss the non-convex polygon */
return 0;
}
}
} else {
/* p is outside the clipping plane half space */
if (__GL_FLOAT_GEZ(sDist)) {
/*
** s is inside the clipping plane half space
**
** NOTE: To avoid cracking in polygons with shared
** clipped edges we always compute "t" from the out
** vertex to the in vertex. The above clipping code gets
** this for free (p is in and s is out). In this code p
** is out and s is in, so we reverse the t computation
** and the argument order to __glDoClip.
*/
t = sDist / (sDist - pDist);
newVertex = temp++;
(*clip)(newVertex, p, s, t);
((POLYDATA *)newVertex)->eye.x =
t*(((POLYDATA *)p)->eye.x - ((POLYDATA *)s)->eye.x) +
((POLYDATA *)s)->eye.x;
((POLYDATA *)newVertex)->eye.y =
t*(((POLYDATA *)p)->eye.y - ((POLYDATA *)s)->eye.y) +
((POLYDATA *)s)->eye.y;
((POLYDATA *)newVertex)->eye.z =
t*(((POLYDATA *)p)->eye.z - ((POLYDATA *)s)->eye.z) +
((POLYDATA *)s)->eye.z;
((POLYDATA *)newVertex)->eye.w =
t*(((POLYDATA *)p)->eye.w - ((POLYDATA *)s)->eye.w) +
((POLYDATA *)s)->eye.w;
#ifdef NT
// edgeflag is now part of has field.
newVertex->has = s->has | __GL_HAS_EDGEFLAG_BOUNDARY;
newVertex->clipCode = p->clipCode;
#else
newVertex->boundaryEdge = GL_TRUE;
newVertex->has = s->has;
#endif
assert(newVertex->color == &newVertex->colors[__GL_FRONTFACE]);
*ov++ = newVertex;
nout++;
if (++generated >= 3) {
/* Toss the non-convex polygon */
return 0;
}
} else {
/* both points are outside */
}
}
s = p;
sDist = pDist;
}
gc->transform.nextClipTemp = temp;
return nout;
}
/*
** Each clipping plane can add at most one vertex to a convex polygon (it may
** remove up to all of the verticies). The clipping will leave a polygon
** convex. Because of this the maximum number of verticies output from
** the clipToPlane procedure will be total number of clip planes (assuming
** each plane adds one new vertex) plus the original number of verticies
** (3 since this if for triangles).
*/
#define __GL_TOTAL_CLIP_PLANES 20 /*XXX*/
#ifdef NT
#define __GL_MAX_CLIP_VERTEX (__GL_TOTAL_CLIP_PLANES + __GL_MAX_POLYGON_CLIP_SIZE)
#else
#define __GL_MAX_CLIP_VERTEX (__GL_TOTAL_CLIP_PLANES + __GL_NVBUF)
#endif
void __glDoPolygonClip(__GLcontext *gc, __GLvertex **iv, GLint nout,
GLuint allClipCodes)
{
__GLvertex *ov[__GL_TOTAL_CLIP_PLANES][__GL_MAX_CLIP_VERTEX];
__GLvertex **ivp;
__GLvertex **ovp;
__GLvertex *p0, *p1, *p2;
__GLcoord *plane;
GLint i;
__GLviewport *vp;
__GLfloat one, vpXScale, vpYScale, vpZScale;
__GLfloat vpXCenter, vpYCenter, vpZCenter;
PFN_RENDER_TRIANGLE rt;
__GLfloat llx, lly, urx, ury;
__GLfloat winx, winy;
GLuint clipCodes;
/*
** Reset nextClipTemp pointer for any new verticies that are generated
** during the clipping.
*/
gc->transform.nextClipTemp = gc->transform.clipTemp;
ivp = &iv[0];
/*
** Check each of the clipping planes by examining the allClipCodes
** mask. Note that no bits will be set in allClipCodes for clip
** planes that are not enabled.
*/
if (allClipCodes) {
#ifdef NT_DEADCODE_POLYARRAY
GLuint needs = gc->vertex.faceNeeds[__GL_FRONTFACE] |
gc->vertex.faceNeeds[__GL_BACKFACE];
/* Validate vertex data before clipping */
ovp = ivp;
for (i = nout; --i >= 0; ) {
__GLvertex *vx = *ovp++;
if (~vx->has & needs) (*vx->validate)(gc, vx, needs);
#ifdef NT
// don't need this anymore
vx->has &= ~(__GL_HAS_FIXEDPT);
#endif
}
#endif // NT_DEADCODE_POLYARRAY
/* Now clip against the clipping planes */
ovp = &ov[0][0];
/*
** Do user clip planes first, because we will maintain eye coordinates
** only while doing user clip planes. They are ignored for the
** frustum clipping planes.
*/
clipCodes = allClipCodes >> 6;
if (clipCodes) {
plane = &gc->state.transform.eyeClipPlanes[0];
do {
if (clipCodes & 1) {
nout = clipToPlaneEye(gc, ivp, nout, ovp, plane);
assert(nout <= __GL_MAX_CLIP_VERTEX);
if (nout < 3) {
return;
}
ivp = ovp;
ovp += __GL_MAX_CLIP_VERTEX;
}
clipCodes >>= 1;
plane++;
} while (clipCodes);
}
allClipCodes &= __GL_FRUSTUM_CLIP_MASK;
if (allClipCodes) {
i = 0;
do {
if (allClipCodes & 1) {
nout = clipToPlane(gc, ivp, nout, ovp,
__glFrustumOffsets[i],
(GLboolean)(i & 1));
assert(nout <= __GL_MAX_CLIP_VERTEX);
if (nout < 3) {
return;
}
ivp = ovp;
ovp += __GL_MAX_CLIP_VERTEX;
}
allClipCodes >>= 1;
i++;
} while (allClipCodes);
}
/*
** Calculate final screen coordinates. Next phase of polygon
** processing assumes that window coordinates are already computed.
*/
vp = &gc->state.viewport;
vpXCenter = vp->xCenter;
vpYCenter = vp->yCenter;
vpZCenter = vp->zCenter;
vpXScale = vp->xScale;
vpYScale = vp->yScale;
vpZScale = vp->zScale;
ovp = ivp;
one = __glOne;
llx = vpXCenter - vpXScale;
urx = vpXCenter + vpXScale;
if (vpYScale > 0) {
lly = vpYCenter - vpYScale;
ury = vpYCenter + vpYScale;
} else {
lly = vpYCenter + vpYScale;
ury = vpYCenter - vpYScale;
}
for (i = nout; --i >= 0; ) {
__GLfloat x, y, z, wInv;
p0 = *ovp++;
// If the clipCode is zero then the window coordinates
// were computed at the time of clipCode determination
// Generated vertices' clipCodes are set to the out vertex
// to ensure that their window coords are computed
if (p0->clipCode != 0)
{
#ifdef NT
/* XXX (mf) prevent divide-by-zero */
if (__GL_FLOAT_EQZ(p0->clip.w))
wInv = __glZero;
else
wInv = one / p0->clip.w;
#else
wInv = one / p0->clip.w;
#endif
x = p0->clip.x; y = p0->clip.y; z = p0->clip.z;
winx = x * vpXScale * wInv + vpXCenter;
winy = y * vpYScale * wInv + vpYCenter;
p0->window.z = z * vpZScale * wInv + vpZCenter;
p0->window.w = wInv;
/*
** Check if these window coordinates are legal. At this
** point, it is quite possible that they are not. Trivially
** pull them into the legal viewport region if necessary.
*/
if (winx < llx) winx = llx;
else if (winx > urx) winx = urx;
if (winy < lly) winy = lly;
else if (winy > ury) winy = ury;
p0->window.x = winx;
p0->window.y = winy;
}
}
}
/*
** Subdivide the clipped polygon into triangles. Only convex polys
** are supported so this is okay to do. Non-convex polys will do
** something odd here, but thats the clients fault.
*/
p0 = *ivp++;
p1 = *ivp++;
p2 = *ivp++;
rt = gc->procs.renderTriangle;
if (nout == 3) {
(*rt)(gc, p0, p1, p2);
} else {
for (i = 0; i < nout - 2; i++) {
GLuint t1, t2;
if (i == 0) {
/*
** Third edge of first sub-triangle is always non-boundary
*/
#ifdef NT
// edgeflag is now part of has field.
t1 = p2->has & __GL_HAS_EDGEFLAG_BOUNDARY;
p2->has &= ~__GL_HAS_EDGEFLAG_BOUNDARY;
(*rt)(gc, p0, p1, p2);
p2->has |= t1;
#else
t1 = p2->boundaryEdge;
p2->boundaryEdge = GL_FALSE;
(*rt)(gc, p0, p1, p2);
p2->boundaryEdge = t1;
#endif
} else
if (i == nout - 3) {
/*
** First edge of last sub-triangle is always non-boundary
*/
#ifdef NT
// edgeflag is now part of has field.
t1 = p0->has & __GL_HAS_EDGEFLAG_BOUNDARY;
p0->has &= ~__GL_HAS_EDGEFLAG_BOUNDARY;
(*rt)(gc, p0, p1, p2);
p0->has |= t1;
#else
t1 = p0->boundaryEdge;
p0->boundaryEdge = GL_FALSE;
(*rt)(gc, p0, p1, p2);
p0->boundaryEdge = t1;
#endif
} else {
/*
** Interior sub-triangles have the first and last edge
** marked non-boundary
*/
#ifdef NT
// edgeflag is now part of has field.
t1 = p0->has & __GL_HAS_EDGEFLAG_BOUNDARY;
t2 = p2->has & __GL_HAS_EDGEFLAG_BOUNDARY;
p0->has &= ~__GL_HAS_EDGEFLAG_BOUNDARY;
p2->has &= ~__GL_HAS_EDGEFLAG_BOUNDARY;
(*rt)(gc, p0, p1, p2);
p0->has |= t1;
p2->has |= t2;
#else
t1 = p0->boundaryEdge;
t2 = p2->boundaryEdge;
p0->boundaryEdge = GL_FALSE;
p2->boundaryEdge = GL_FALSE;
(*rt)(gc, p0, p1, p2);
p0->boundaryEdge = t1;
p2->boundaryEdge = t2;
#endif
}
p1 = p2;
p2 = (__GLvertex *) *ivp++;
}
}
}
void FASTCALL __glClipPolygon(__GLcontext *gc, __GLvertex *v0, GLint nv)
{
#ifdef NT
__GLvertex *iv[__GL_MAX_POLYGON_CLIP_SIZE];
#else
__GLvertex *iv[__GL_NVBUF];
#endif
__GLvertex **ivp;
GLint i;
GLuint andCodes, orCodes;
gc->vertex.provoking = v0;
/*
** Generate array of addresses of the verticies. And all the
** clip codes together while we are at it.
*/
ivp = &iv[0];
andCodes = 0;
orCodes = 0;
for (i = nv; --i >= 0; ) {
andCodes &= v0->clipCode;
orCodes |= v0->clipCode;
*ivp++ = v0++;
}
if (andCodes != 0) {
/*
** Trivially reject the polygon. If andCodes is non-zero then
** every vertex in the polygon is outside of the same set of
** clipping planes (at least one).
*/
return;
}
__glDoPolygonClip(gc, &iv[0], nv, orCodes);
}
void FASTCALL __glClipTriangle(__GLcontext *gc, __GLvertex *a, __GLvertex *b,
__GLvertex *c, GLuint orCodes)
{
__GLvertex *iv[3];
iv[0] = a;
iv[1] = b;
iv[2] = c;
__glDoPolygonClip(gc, &iv[0], 3, orCodes);
}