/* ** 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.21 $ ** $Date: 1993/09/23 16:37:59 $ */ #include "precomp.h" #pragma hdrstop void APIPRIVATE __glim_FeedbackBuffer(GLsizei bufferLength, GLenum type, GLfloat buffer[]) { __GL_SETUP_NOT_IN_BEGIN(); if ((type < GL_2D) || (type > GL_4D_COLOR_TEXTURE)) { __glSetError(GL_INVALID_ENUM); return; } if (bufferLength < 0) { __glSetError(GL_INVALID_VALUE); return; } if (gc->renderMode == GL_FEEDBACK) { __glSetError(GL_INVALID_OPERATION); return; } gc->feedback.resultBase = buffer; gc->feedback.result = buffer; gc->feedback.resultLength = bufferLength; gc->feedback.overFlowed = GL_FALSE; gc->feedback.type = type; } void APIPRIVATE __glim_PassThrough(GLfloat element) { __GL_SETUP_NOT_IN_BEGIN(); if (gc->renderMode == GL_FEEDBACK) { __glFeedbackTag(gc, GL_PASS_THROUGH_TOKEN); __glFeedbackTag(gc, element); } } /************************************************************************/ void __glFeedbackTag(__GLcontext *gc, GLfloat f) { if (!gc->feedback.overFlowed) { if (gc->feedback.result >= gc->feedback.resultBase + gc->feedback.resultLength) { gc->feedback.overFlowed = GL_TRUE; } else { gc->feedback.result[0] = f; gc->feedback.result = gc->feedback.result + 1; } } } static void FASTCALL feedback(__GLcontext *gc, __GLvertex *v) { GLenum type = gc->feedback.type; #ifdef NT // Do coordinates __glFeedbackTag(gc, v->window.x - gc->constants.fviewportXAdjust); if (gc->constants.yInverted) __glFeedbackTag(gc, (gc->constants.height - (v->window.y - gc->constants.fviewportYAdjust))); else __glFeedbackTag(gc, v->window.y - gc->constants.fviewportYAdjust); if (type != GL_2D) __glFeedbackTag(gc, v->window.z / gc->depthBuffer.scale); /* ** NOTE: return clip.w, as window.w has no spec defined meaning. ** It is true that this implementation uses window.w, but thats ** something different. */ if (type == GL_4D_COLOR_TEXTURE) __glFeedbackTag(gc, v->clip.w); #else switch (type) { case GL_2D: __glFeedbackTag(gc, v->window.x - gc->constants.fviewportXAdjust); if (gc->constants.yInverted) { __glFeedbackTag(gc, (gc->constants.height - (v->window.y - gc->constants.fviewportYAdjust)) - gc->constants.viewportEpsilon); } else { __glFeedbackTag(gc, v->window.y - gc->constants.fviewportYAdjust); } break; case GL_3D: case GL_3D_COLOR: case GL_3D_COLOR_TEXTURE: __glFeedbackTag(gc, v->window.x - gc->constants.fviewportXAdjust); if (gc->constants.yInverted) { __glFeedbackTag(gc, (gc->constants.height - (v->window.y - gc->constants.fviewportYAdjust)) - gc->constants.viewportEpsilon); } else { __glFeedbackTag(gc, v->window.y - gc->constants.fviewportYAdjust); } __glFeedbackTag(gc, v->window.z / gc->depthBuffer.scale); break; case GL_4D_COLOR_TEXTURE: __glFeedbackTag(gc, v->window.x - gc->constants.fviewportXAdjust); if (gc->constants.yInverted) { __glFeedbackTag(gc, (gc->constants.height - (v->window.y - gc->constants.fviewportYAdjust)) - gc->constants.viewportEpsilon); } else { __glFeedbackTag(gc, v->window.y - gc->constants.fviewportYAdjust); } __glFeedbackTag(gc, v->window.z / gc->depthBuffer.scale); /* ** NOTE: return clip.w, as window.w has no spec defined meaning. ** It is true that this implementation uses window.w, but thats ** something different. */ __glFeedbackTag(gc, v->clip.w); break; } #endif switch (type) { case GL_3D_COLOR: case GL_3D_COLOR_TEXTURE: case GL_4D_COLOR_TEXTURE: { __GLcolor *c = v->color; if (gc->modes.rgbMode) { __glFeedbackTag(gc, c->r * gc->oneOverRedVertexScale); __glFeedbackTag(gc, c->g * gc->oneOverGreenVertexScale); __glFeedbackTag(gc, c->b * gc->oneOverBlueVertexScale); __glFeedbackTag(gc, c->a * gc->oneOverAlphaVertexScale); } else { __glFeedbackTag(gc, c->r); } } break; case GL_2D: case GL_3D: break; } switch (type) { case GL_3D_COLOR_TEXTURE: case GL_4D_COLOR_TEXTURE: __glFeedbackTag(gc, v->texture.x); __glFeedbackTag(gc, v->texture.y); __glFeedbackTag(gc, v->texture.z); __glFeedbackTag(gc, v->texture.w); break; case GL_2D: case GL_3D: case GL_3D_COLOR: break; } } void FASTCALL __glFeedbackCopyPixels(__GLcontext *gc, __GLvertex *vx) { __glFeedbackTag(gc, GL_COPY_PIXEL_TOKEN); feedback(gc, vx); } void FASTCALL __glFeedbackDrawPixels(__GLcontext *gc, __GLvertex *vx) { __glFeedbackTag(gc, GL_DRAW_PIXEL_TOKEN); feedback(gc, vx); } void FASTCALL __glFeedbackBitmap(__GLcontext *gc, __GLvertex *vx) { __glFeedbackTag(gc, GL_BITMAP_TOKEN); feedback(gc, vx); } /* feedback version of renderPoint proc */ void FASTCALL __glFeedbackPoint(__GLcontext *gc, __GLvertex *vx) { __glFeedbackTag(gc, GL_POINT_TOKEN); feedback(gc, vx); } /* feedback version of renderLine proc */ void FASTCALL __glFeedbackLine(__GLcontext *gc, __GLvertex *a, __GLvertex *b, GLuint flags) { GLuint modeFlags = gc->polygon.shader.modeFlags; __GLcolor *oacp; oacp = a->color; if (!(modeFlags & __GL_SHADE_SMOOTH_LIGHT) #ifdef GL_WIN_phong_shading && !(modeFlags & __GL_SHADE_PHONG) #endif //GL_WIN_phong_shading ) { a->color = b->color; } if (gc->line.notResetStipple) { __glFeedbackTag(gc, GL_LINE_TOKEN); } else { gc->line.notResetStipple = GL_TRUE; __glFeedbackTag(gc, GL_LINE_RESET_TOKEN); } feedback(gc, a); feedback(gc, b); a->color = oacp; } /* feedback version of renderTriangle proc */ void FASTCALL __glFeedbackTriangle(__GLcontext *gc, __GLvertex *a, __GLvertex *b, __GLvertex *c) { __GLfloat dxAC, dxBC, dyAC, dyBC, area; GLboolean ccw; GLint face; GLuint modeFlags; #ifdef SGI // not used GLboolean first; __GLfloat x, y, z, wInv; __GLfloat vpXScale, vpYScale, vpZScale; __GLfloat vpXCenter, vpYCenter, vpZCenter; __GLviewport *vp; /* Compute window coordinates first, if not already done */ vp = &gc->state.viewport; vpXCenter = vp->xCenter; vpYCenter = vp->yCenter; vpZCenter = vp->zCenter; vpXScale = vp->xScale; vpYScale = vp->yScale; vpZScale = vp->zScale; #endif /* Compute signed area of the triangle */ dxAC = a->window.x - c->window.x; dxBC = b->window.x - c->window.x; dyAC = a->window.y - c->window.y; dyBC = b->window.y - c->window.y; area = dxAC * dyBC - dxBC * dyAC; ccw = area >= __glZero; /* ** Figure out if face is culled or not. The face check needs to be ** based on the vertex winding before sorting. This code uses the ** reversed flag to invert the sense of ccw - an xor accomplishes ** this conversion without an if test. ** ** ccw reversed xor ** --- -------- --- ** 0 0 0 (remain !ccw) ** 1 0 1 (remain ccw) ** 0 1 1 (become ccw) ** 1 1 0 (become cw) */ face = gc->polygon.face[ccw]; if (face == gc->polygon.cullFace) { /* Culled */ return; } #ifdef NT /* ** Pick face to use for coloring */ modeFlags = gc->polygon.shader.modeFlags; if (modeFlags & __GL_SHADE_SMOOTH_LIGHT) { /* Smooth shading */ if (modeFlags & __GL_SHADE_TWOSIDED && face == __GL_BACKFACE) { a->color++; b->color++; c->color++; } } else { /* Flat shading */ __GLvertex *pv = gc->vertex.provoking; if (modeFlags & __GL_SHADE_TWOSIDED && face == __GL_BACKFACE) pv->color++; a->color = pv->color; b->color = pv->color; c->color = pv->color; } #else /* ** Pick face to use for coloring */ modeFlags = gc->polygon.shader.modeFlags; needs = gc->vertex.needs; if (gc->state.light.shadingModel == GL_FLAT) { __GLvertex *pv = gc->vertex.provoking; GLuint pvneeds; GLuint faceNeeds; GLint colorFace; if (modeFlags & __GL_SHADE_TWOSIDED) { colorFace = face; faceNeeds = gc->vertex.faceNeeds[face]; } else { colorFace = __GL_FRONTFACE; faceNeeds = gc->vertex.faceNeeds[__GL_FRONTFACE]; } pv->color = &pv->colors[colorFace]; a->color = pv->color; b->color = pv->color; c->color = pv->color; pvneeds = faceNeeds & (__GL_HAS_LIGHTING | __GL_HAS_FRONT_COLOR | __GL_HAS_BACK_COLOR); if (~pv->has & pvneeds) { (*pv->validate)(gc, pv, pvneeds); } } else { GLuint faceNeeds; GLint colorFace; if (modeFlags & __GL_SHADE_TWOSIDED) { colorFace = face; needs |= gc->vertex.faceNeeds[face]; } else { colorFace = __GL_FRONTFACE; needs |= gc->vertex.faceNeeds[__GL_FRONTFACE]; } a->color = &a->colors[colorFace]; b->color = &b->colors[colorFace]; c->color = &c->colors[colorFace]; } if (~a->has & needs) (*a->validate)(gc, a, needs); if (~b->has & needs) (*b->validate)(gc, b, needs); if (~c->has & needs) (*c->validate)(gc, c, needs); #endif /* Deal with polygon face modes */ switch (gc->polygon.mode[face]) { case __GL_POLYGON_MODE_POINT: #ifdef NT if (a->has & __GL_HAS_EDGEFLAG_BOUNDARY) __glFeedbackPoint(gc, a); if (b->has & __GL_HAS_EDGEFLAG_BOUNDARY) __glFeedbackPoint(gc, b); if (c->has & __GL_HAS_EDGEFLAG_BOUNDARY) __glFeedbackPoint(gc, c); break; #else if (a->boundaryEdge) { __glFeedbackTag(gc, GL_POINT_TOKEN); feedback(gc, a); } if (b->boundaryEdge) { __glFeedbackTag(gc, GL_POINT_TOKEN); feedback(gc, b); } if (c->boundaryEdge) { __glFeedbackTag(gc, GL_POINT_TOKEN); feedback(gc, c); } break; #endif case __GL_POLYGON_MODE_LINE: #ifdef NT if (a->has & __GL_HAS_EDGEFLAG_BOUNDARY) __glFeedbackLine(gc, a, b, 0); if (b->has & __GL_HAS_EDGEFLAG_BOUNDARY) __glFeedbackLine(gc, b, c, 0); if (c->has & __GL_HAS_EDGEFLAG_BOUNDARY) __glFeedbackLine(gc, c, a, 0); break; #else if (a->boundaryEdge) { if (!gc->line.notResetStipple) { gc->line.notResetStipple = GL_TRUE; __glFeedbackTag(gc, GL_LINE_RESET_TOKEN); } else { __glFeedbackTag(gc, GL_LINE_TOKEN); } feedback(gc, a); feedback(gc, b); } if (b->boundaryEdge) { if (!gc->line.notResetStipple) { gc->line.notResetStipple = GL_TRUE; __glFeedbackTag(gc, GL_LINE_RESET_TOKEN); } else { __glFeedbackTag(gc, GL_LINE_TOKEN); } feedback(gc, b); feedback(gc, c); } if (c->boundaryEdge) { if (!gc->line.notResetStipple) { gc->line.notResetStipple = GL_TRUE; __glFeedbackTag(gc, GL_LINE_RESET_TOKEN); } else { __glFeedbackTag(gc, GL_LINE_TOKEN); } feedback(gc, c); feedback(gc, a); } break; #endif case __GL_POLYGON_MODE_FILL: __glFeedbackTag(gc, GL_POLYGON_TOKEN); __glFeedbackTag(gc, 3); feedback(gc, a); feedback(gc, b); feedback(gc, c); break; } /* Restore color pointers */ a->color = &a->colors[__GL_FRONTFACE]; b->color = &b->colors[__GL_FRONTFACE]; c->color = &c->colors[__GL_FRONTFACE]; if (gc->state.light.shadingModel == GL_FLAT) { __GLvertex *pv = gc->vertex.provoking; pv->color = &pv->colors[__GL_FRONTFACE]; } }