windows-nt/Source/XPSP1/NT/multimedia/opengl/server/soft/so_feedb.c
2020-09-26 16:20:57 +08:00

431 lines
12 KiB
C

/*
** 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];
}
}