state_feedback.c revision e0e0c19eefceaf5d4ec40f9466b58a771f50e799
/* Copyright (c) 2001, Stanford University
* All rights reserved
*
* See the file LICENSE.txt for information on redistributing this software.
*/
#include "state.h"
#include "state_internals.h"
#include "state/cr_statetypes.h"
#include "state/cr_feedback.h"
/*
* This file is really a complement to the feedbackSPU and as such
* has big dependencies upon it. We have to monitor a whole bunch
* of state in the feedbackSPU to be able to properly implement
* full functionality.
*
* We have to intercept glColor3f(v)/4f(v) to get state updates on
* color properties and also glTexCoord* too, as unlike the tilesortSPU
* we don't have a pincher that pulls these out as they're passing
* through.
*
* - Alan.
*/
/*
* Selection and feedback
*
* TODO:
* 1. Implement lighting for vertex colors for feedback
* 2. Implement user clip planes for points and lines
*/
/**********************************************************************/
/***** Vertex Transformation and Clipping *****/
/**********************************************************************/
/*
* Transform a point (column vector) by a matrix: Q = M * P
*/
#define TRANSFORM_POINT( Q, M, P ) \
Q.x = (M).m00 * P.x + (M).m10 * P.y + (M).m20 * P.z + (M).m30 * P.w; \
Q.y = (M).m01 * P.x + (M).m11 * P.y + (M).m21 * P.z + (M).m31 * P.w; \
Q.z = (M).m02 * P.x + (M).m12 * P.y + (M).m22 * P.z + (M).m32 * P.w; \
Q.w = (M).m03 * P.x + (M).m13 * P.y + (M).m23 * P.z + (M).m33 * P.w;
#define TRANSFORM_POINTA( Q, M, P ) \
Q.x = (M).m00 * (P)[0] + (M).m10 * (P)[1] + (M).m20 * (P)[2] + (M).m30 * (P)[3]; \
Q.y = (M).m01 * (P)[0] + (M).m11 * (P)[1] + (M).m21 * (P)[2] + (M).m31 * (P)[3]; \
Q.z = (M).m02 * (P)[0] + (M).m12 * (P)[1] + (M).m22 * (P)[2] + (M).m32 * (P)[3]; \
Q.w = (M).m03 * (P)[0] + (M).m13 * (P)[1] + (M).m23 * (P)[2] + (M).m33 * (P)[3];
/*
* clip coord to window coord mapping
*/
#define MAP_POINT( Q, P, VP ) \
Q.x = (GLfloat) (((P.x / P.w) + 1.0) * VP.viewportW / 2.0 + VP.viewportX); \
Q.y = (GLfloat) (((P.y / P.w) + 1.0) * VP.viewportH / 2.0 + VP.viewportY); \
Q.z = (GLfloat) (((P.z / P.w) + 1.0) * (VP.farClip - VP.nearClip) / 2.0 + VP.nearClip);\
Q.w = (GLfloat) P.w;
/*
* Linear interpolation:
*/
#define INTERPOLATE(T, A, B) ((A) + ((B) - (A)) * (T))
/*
* Interpolate vertex position, color, texcoords, etc.
*/
static void
interpolate_vertex(GLfloat t,
const CRVertex *v0, const CRVertex *v1,
CRVertex *vOut)
{
vOut->eyePos.x = INTERPOLATE(t, v0->eyePos.x, v1->eyePos.x);
vOut->eyePos.y = INTERPOLATE(t, v0->eyePos.y, v1->eyePos.y);
vOut->eyePos.z = INTERPOLATE(t, v0->eyePos.z, v1->eyePos.z);
vOut->eyePos.w = INTERPOLATE(t, v0->eyePos.w, v1->eyePos.w);
vOut->clipPos.x = INTERPOLATE(t, v0->clipPos.x, v1->clipPos.x);
vOut->clipPos.y = INTERPOLATE(t, v0->clipPos.y, v1->clipPos.y);
vOut->clipPos.z = INTERPOLATE(t, v0->clipPos.z, v1->clipPos.z);
vOut->clipPos.w = INTERPOLATE(t, v0->clipPos.w, v1->clipPos.w);
vOut->attrib[VERT_ATTRIB_COLOR0][0] = INTERPOLATE(t, v0->attrib[VERT_ATTRIB_COLOR0][0], v1->attrib[VERT_ATTRIB_COLOR0][0]);
vOut->attrib[VERT_ATTRIB_COLOR0][1] = INTERPOLATE(t, v0->attrib[VERT_ATTRIB_COLOR0][1], v1->attrib[VERT_ATTRIB_COLOR0][1]);
vOut->attrib[VERT_ATTRIB_COLOR0][2] = INTERPOLATE(t, v0->attrib[VERT_ATTRIB_COLOR0][2], v1->attrib[VERT_ATTRIB_COLOR0][2]);
vOut->attrib[VERT_ATTRIB_COLOR0][3] = INTERPOLATE(t, v0->attrib[VERT_ATTRIB_COLOR0][3], v1->attrib[VERT_ATTRIB_COLOR0][3]);
vOut->colorIndex = INTERPOLATE(t, v0->colorIndex, v1->colorIndex);
vOut->attrib[VERT_ATTRIB_TEX0][0] = INTERPOLATE(t, v0->attrib[VERT_ATTRIB_TEX0][0], v1->attrib[VERT_ATTRIB_TEX0][0]);
vOut->attrib[VERT_ATTRIB_TEX0][1] = INTERPOLATE(t, v0->attrib[VERT_ATTRIB_TEX0][1], v1->attrib[VERT_ATTRIB_TEX0][0]);
vOut->attrib[VERT_ATTRIB_TEX0][2] = INTERPOLATE(t, v0->attrib[VERT_ATTRIB_TEX0][2], v1->attrib[VERT_ATTRIB_TEX0][0]);
vOut->attrib[VERT_ATTRIB_TEX0][3] = INTERPOLATE(t, v0->attrib[VERT_ATTRIB_TEX0][3], v1->attrib[VERT_ATTRIB_TEX0][0]);
}
/* clip bit codes */
#define CLIP_LEFT 1
#define CLIP_RIGHT 2
#define CLIP_BOTTOM 4
#define CLIP_TOP 8
#define CLIP_NEAR 16
#define CLIP_FAR 32
#define CLIP_USER0 64
#define CLIP_USER1 128
/*
* Apply clip testing to a point.
* Return: 0 - visible
* non-zero - clip code mask (or of above CLIP_ bits)
*/
static GLuint
clip_point(const CRVertex *v)
{
CRContext *g = GetCurrentContext();
GLuint mask = 0;
GLuint i;
/* user-defined clip planes */
for (i = 0; i < g->limits.maxClipPlanes; i++)
{
if (g->transform.clip[i])
{
const GLvectord *plane = g->transform.clipPlane + i;
if (plane->x * v->eyePos.x +
plane->y * v->eyePos.y +
plane->z * v->eyePos.z +
plane->w * v->eyePos.w < 0.0)
mask |= (CLIP_USER0 << i);
}
}
/* view volume clipping */
if (v->clipPos.x > v->clipPos.w)
mask |= CLIP_RIGHT;
if (v->clipPos.x < -v->clipPos.w)
mask |= CLIP_LEFT;
if (v->clipPos.y > v->clipPos.w)
mask |= CLIP_TOP;
if (v->clipPos.y < -v->clipPos.w)
mask |= CLIP_BOTTOM;
if (v->clipPos.z > v->clipPos.w)
mask |= CLIP_FAR;
if (v->clipPos.z < -v->clipPos.w)
mask |= CLIP_NEAR;
return mask;
}
/*
* Apply clipping to a line segment.
* Input: v0, v1 - incoming vertices
* Output: v0out, v1out - result/clipped vertices
* Return: GL_TRUE: visible
* GL_FALSE: totally clipped
*/
static GLboolean
clip_line(const CRVertex *v0in, const CRVertex *v1in,
CRVertex *v0new, CRVertex *v1new)
{
CRVertex v0, v1, vNew;
GLfloat dx, dy, dz, dw, t;
GLuint code0, code1;
/* XXX need to do user-clip planes */
code0 = clip_point(v0in);
code1 = clip_point(v1in);
if (code0 & code1)
return GL_FALSE; /* totally clipped */
*v0new = *v0in;
*v1new = *v1in;
if (code0 == 0 && code1 == 0)
return GL_TRUE; /* no clipping needed */
v0 = *v0in;
v1 = *v1in;
/*
* We use 6 instances of this code to clip agains the 6 planes.
* For each plane, we define the OUTSIDE and COMPUTE_INTERSECTION
* macros apprpriately.
*/
#define GENERAL_CLIP \
if (OUTSIDE(v0)) { \
if (OUTSIDE(v1)) { \
/* both verts are outside ==> return 0 */ \
return 0; \
} \
else { \
/* v0 is outside, v1 is inside ==> clip */ \
COMPUTE_INTERSECTION( v1, v0, vNew ) \
interpolate_vertex(t, &v1, &v0, &vNew); \
v0 = vNew; \
} \
} \
else { \
if (OUTSIDE(v1)) { \
/* v0 is inside, v1 is outside ==> clip */ \
COMPUTE_INTERSECTION( v0, v1, vNew ) \
interpolate_vertex(t, &v0, &v1, &vNew); \
v1 = vNew; \
} \
/* else both verts are inside ==> do nothing */ \
}
/*** Clip against +X side ***/
#define OUTSIDE(V) (V.clipPos.x > V.clipPos.w)
#define COMPUTE_INTERSECTION( IN, OUT, NEW ) \
dx = OUT.clipPos.x - IN.clipPos.x; \
dw = OUT.clipPos.w - IN.clipPos.w; \
t = (IN.clipPos.x - IN.clipPos.w) / (dw-dx);
GENERAL_CLIP
#undef OUTSIDE
#undef COMPUTE_INTERSECTION
/*** Clip against -X side ***/
#define OUTSIDE(V) (V.clipPos.x < -(V.clipPos.w))
#define COMPUTE_INTERSECTION( IN, OUT, NEW ) \
dx = OUT.clipPos.x - IN.clipPos.x; \
dw = OUT.clipPos.w - IN.clipPos.w; \
t = -(IN.clipPos.x + IN.clipPos.w) / (dw+dx);
GENERAL_CLIP
#undef OUTSIDE
#undef COMPUTE_INTERSECTION
/*** Clip against +Y side ***/
#define OUTSIDE(V) (V.clipPos.y > V.clipPos.w)
#define COMPUTE_INTERSECTION( IN, OUT, NEW ) \
dy = OUT.clipPos.y - IN.clipPos.y; \
dw = OUT.clipPos.w - IN.clipPos.w; \
t = (IN.clipPos.y - IN.clipPos.w) / (dw-dy);
GENERAL_CLIP
#undef OUTSIDE
#undef COMPUTE_INTERSECTION
/*** Clip against -Y side ***/
#define OUTSIDE(V) (V.clipPos.y < -(V.clipPos.w))
#define COMPUTE_INTERSECTION( IN, OUT, NEW ) \
dy = OUT.clipPos.y - IN.clipPos.y; \
dw = OUT.clipPos.w - IN.clipPos.w; \
t = -(IN.clipPos.y + IN.clipPos.w) / (dw+dy);
GENERAL_CLIP
#undef OUTSIDE
#undef COMPUTE_INTERSECTION
/*** Clip against +Z side ***/
#define OUTSIDE(V) (V.clipPos.z > V.clipPos.w)
#define COMPUTE_INTERSECTION( IN, OUT, NEW ) \
dz = OUT.clipPos.z - IN.clipPos.z; \
dw = OUT.clipPos.w - IN.clipPos.w; \
t = (IN.clipPos.z - IN.clipPos.w) / (dw-dz);
GENERAL_CLIP
#undef OUTSIDE
#undef COMPUTE_INTERSECTION
/*** Clip against -Z side ***/
#define OUTSIDE(V) (V.clipPos.z < -(V.clipPos.w))
#define COMPUTE_INTERSECTION( IN, OUT, NEW ) \
dz = OUT.clipPos.z - IN.clipPos.z; \
dw = OUT.clipPos.w - IN.clipPos.w; \
t = -(IN.clipPos.z + IN.clipPos.w) / (dw+dz);
GENERAL_CLIP
#undef OUTSIDE
#undef COMPUTE_INTERSECTION
#undef GENERAL_CLIP
*v0new = v0;
*v1new = v1;
return GL_TRUE;
}
/*
* Apply clipping to a polygon.
* Input: vIn - array of input vertices
* inCount - number of input vertices
* Output: vOut - new vertices
* Return: number of vertices in vOut
*/
static GLuint
clip_polygon(const CRVertex *vIn, unsigned int inCount,
CRVertex *vOut)
{
CRVertex inlist[20], outlist[20];
GLfloat dx, dy, dz, dw, t;
GLuint incount, outcount, previ, curri, result;
const CRVertex *currVert, *prevVert;
CRVertex *newVert;
/* XXX need to do user-clip planes */
#define GENERAL_CLIP(INCOUNT, INLIST, OUTCOUNT, OUTLIST) \
if (INCOUNT < 3) \
return GL_FALSE; \
previ = INCOUNT - 1; /* let previous = last vertex */ \
prevVert = INLIST + previ; \
OUTCOUNT = 0; \
for (curri = 0; curri < INCOUNT; curri++) { \
currVert = INLIST + curri; \
if (INSIDE(currVert)) { \
if (INSIDE(prevVert)) { \
/* both verts are inside ==> copy current to outlist */ \
OUTLIST[OUTCOUNT] = *currVert; \
OUTCOUNT++; \
} \
else { \
newVert = OUTLIST + OUTCOUNT; \
/* current is inside and previous is outside ==> clip */ \
COMPUTE_INTERSECTION( currVert, prevVert, newVert ) \
OUTCOUNT++; \
/* Output current */ \
OUTLIST[OUTCOUNT] = *currVert; \
OUTCOUNT++; \
} \
} \
else { \
if (INSIDE(prevVert)) { \
newVert = OUTLIST + OUTCOUNT; \
/* current is outside and previous is inside ==> clip */ \
COMPUTE_INTERSECTION( prevVert, currVert, newVert ); \
OUTLIST[OUTCOUNT] = *newVert; \
OUTCOUNT++; \
} \
/* else both verts are outside ==> do nothing */ \
} \
/* let previous = current */ \
previ = curri; \
prevVert = currVert; \
}
/*
* Clip against +X
*/
#define INSIDE(V) (V->clipPos.x <= V->clipPos.w)
#define COMPUTE_INTERSECTION( IN, OUT, NEW ) \
dx = OUT->clipPos.x - IN->clipPos.x; \
dw = OUT->clipPos.w - IN->clipPos.w; \
t = (IN->clipPos.x - IN->clipPos.w) / (dw - dx); \
interpolate_vertex(t, IN, OUT, NEW );
GENERAL_CLIP(inCount, vIn, outcount, outlist)
#undef INSIDE
#undef COMPUTE_INTERSECTION
/*
* Clip against -X
*/
#define INSIDE(V) (V->clipPos.x >= -V->clipPos.w)
#define COMPUTE_INTERSECTION( IN, OUT, NEW ) \
dx = OUT->clipPos.x - IN->clipPos.x; \
dw = OUT->clipPos.w - IN->clipPos.w; \
t = -(IN->clipPos.x + IN->clipPos.w) / (dw + dx); \
interpolate_vertex(t, IN, OUT, NEW );
GENERAL_CLIP(outcount, outlist, incount, inlist)
#undef INSIDE
#undef COMPUTE_INTERSECTION
/*
* Clip against +Y
*/
#define INSIDE(V) (V->clipPos.y <= V->clipPos.w)
#define COMPUTE_INTERSECTION( IN, OUT, NEW ) \
dy = OUT->clipPos.y - IN->clipPos.y; \
dw = OUT->clipPos.w - IN->clipPos.w; \
t = (IN->clipPos.y - IN->clipPos.w) / (dw - dy); \
interpolate_vertex(t, IN, OUT, NEW );
GENERAL_CLIP(incount, inlist, outcount, outlist)
#undef INSIDE
#undef COMPUTE_INTERSECTION
/*
* Clip against -Y
*/
#define INSIDE(V) (V->clipPos.y >= -V->clipPos.w)
#define COMPUTE_INTERSECTION( IN, OUT, NEW ) \
dy = OUT->clipPos.y - IN->clipPos.y; \
dw = OUT->clipPos.w - IN->clipPos.w; \
t = -(IN->clipPos.y + IN->clipPos.w) / (dw + dy); \
interpolate_vertex(t, IN, OUT, NEW );
GENERAL_CLIP(outcount, outlist, incount, inlist)
#undef INSIDE
#undef COMPUTE_INTERSECTION
/*
* Clip against +Z
*/
#define INSIDE(V) (V->clipPos.z <= V->clipPos.w)
#define COMPUTE_INTERSECTION( IN, OUT, NEW ) \
dz = OUT->clipPos.z - IN->clipPos.z; \
dw = OUT->clipPos.w - IN->clipPos.w; \
t = (IN->clipPos.z - IN->clipPos.w) / (dw - dz); \
interpolate_vertex(t, IN, OUT, NEW );
GENERAL_CLIP(incount, inlist, outcount, outlist)
#undef INSIDE
#undef COMPUTE_INTERSECTION
/*
* Clip against -Z
*/
#define INSIDE(V) (V->clipPos.z >= -V->clipPos.w)
#define COMPUTE_INTERSECTION( IN, OUT, NEW ) \
dz = OUT->clipPos.z - IN->clipPos.z; \
dw = OUT->clipPos.w - IN->clipPos.w; \
t = -(IN->clipPos.z + IN->clipPos.w) / (dw + dz); \
interpolate_vertex(t, IN, OUT, NEW );
GENERAL_CLIP(outcount, outlist, result, vOut)
#undef INSIDE
#undef COMPUTE_INTERSECTION
#undef GENERAL_CLIP
return result;
}
/**********************************************************************/
/***** Feedback *****/
/**********************************************************************/
#define FB_3D 0x01
#define FB_4D 0x02
#define FB_INDEX 0x04
#define FB_COLOR 0x08
#define FB_TEXTURE 0X10
#define FEEDBACK_TOKEN( T ) \
do { \
if (f->count < f->bufferSize) { \
f->buffer[f->count] = (GLfloat) (T); \
} \
f->count++; \
} while (0)
/*
* Put a vertex into the feedback buffer.
*/
static void
feedback_vertex(const CRVertex *v)
{
CRContext *g = GetCurrentContext();
CRFeedbackState *f = &(g->feedback);
CRTransformState *t = &(g->transform);
FEEDBACK_TOKEN(v->winPos.x);
FEEDBACK_TOKEN(v->winPos.y);
if (f->mask & FB_3D)
{
FEEDBACK_TOKEN(v->winPos.z);
}
if (f->mask & FB_4D)
{
FEEDBACK_TOKEN(v->winPos.w);
}
/* We don't deal with color index in Chromium */
if (f->mask & FB_INDEX)
{
FEEDBACK_TOKEN(v->colorIndex);
}
if (f->mask & FB_COLOR)
{
FEEDBACK_TOKEN(v->attrib[VERT_ATTRIB_COLOR0][0]);
FEEDBACK_TOKEN(v->attrib[VERT_ATTRIB_COLOR0][1]);
FEEDBACK_TOKEN(v->attrib[VERT_ATTRIB_COLOR0][2]);
FEEDBACK_TOKEN(v->attrib[VERT_ATTRIB_COLOR0][3]);
}
if (f->mask & FB_TEXTURE)
{
GLvectorf coord, transCoord;
/* Ugh, copy (s,t,r,q) to (x,y,z,w) */
coord.x = v->attrib[VERT_ATTRIB_TEX0][0];
coord.y = v->attrib[VERT_ATTRIB_TEX0][1];
coord.z = v->attrib[VERT_ATTRIB_TEX0][2];
coord.w = v->attrib[VERT_ATTRIB_TEX0][3];
TRANSFORM_POINT(transCoord, *(t->textureStack[0].top), coord);
FEEDBACK_TOKEN(transCoord.x);
FEEDBACK_TOKEN(transCoord.y);
FEEDBACK_TOKEN(transCoord.z);
FEEDBACK_TOKEN(transCoord.w);
}
}
static void
feedback_rasterpos(void)
{
CRContext *g = GetCurrentContext();
CRVertex *tv = g->vBuffer + g->vCount;
CRVertex v;
v.winPos.x = g->current.rasterAttrib[VERT_ATTRIB_POS][0];
v.winPos.y = g->current.rasterAttrib[VERT_ATTRIB_POS][1];
v.winPos.z = g->current.rasterAttrib[VERT_ATTRIB_POS][2];
v.winPos.w = g->current.rasterAttrib[VERT_ATTRIB_POS][3];
COPY_4V(v.attrib[VERT_ATTRIB_COLOR0] , g->current.rasterAttrib[VERT_ATTRIB_COLOR0]); /* XXX need to apply lighting */
COPY_4V(v.attrib[VERT_ATTRIB_COLOR1] , g->current.rasterAttrib[VERT_ATTRIB_COLOR1]);
v.colorIndex = (GLfloat) g->current.rasterIndex;
/* Don't do this, we're capturing TexCoord ourselves and
* we'd miss the conversion in RasterPosUpdate */
/* v.texCoord[0] = g->current.rasterTexture; */
/* So we do this instead, and pluck it from the current vertex */
COPY_4V(v.attrib[VERT_ATTRIB_TEX0] , tv->attrib[VERT_ATTRIB_TEX0]);
feedback_vertex(&v);
}
static void
feedback_point(const CRVertex *v)
{
CRContext *g = GetCurrentContext();
CRFeedbackState *f = &(g->feedback);
if (clip_point(v) == 0)
{
CRVertex c = *v;
MAP_POINT(c.winPos, c.clipPos, g->viewport);
FEEDBACK_TOKEN((GLfloat) GL_POINT_TOKEN);
feedback_vertex(&c);
}
}
static void
feedback_line(const CRVertex *v0, const CRVertex *v1, GLboolean reset)
{
CRContext *g = GetCurrentContext();
CRFeedbackState *f = &(g->feedback);
CRVertex c0, c1;
if (clip_line(v0, v1, &c0, &c1))
{
MAP_POINT(c0.winPos, c0.clipPos, g->viewport);
MAP_POINT(c1.winPos, c1.clipPos, g->viewport);
if (reset)
FEEDBACK_TOKEN((GLfloat) GL_LINE_RESET_TOKEN);
else
FEEDBACK_TOKEN((GLfloat) GL_LINE_TOKEN);
feedback_vertex(&c0);
feedback_vertex(&c1);
}
}
static void
feedback_triangle(const CRVertex *v0, const CRVertex *v1, const CRVertex *v2)
{
CRContext *g = GetCurrentContext();
CRFeedbackState *f = &(g->feedback);
CRVertex vlist[3], vclipped[8];
GLuint i, n;
vlist[0] = *v0;
vlist[1] = *v1;
vlist[2] = *v2;
n = clip_polygon(vlist, 3, vclipped);
FEEDBACK_TOKEN( (GLfloat) GL_POLYGON_TOKEN );
FEEDBACK_TOKEN( (GLfloat) n );
for (i = 0; i < n; i++) {
MAP_POINT(vclipped[i].winPos, vclipped[i].clipPos, g->viewport);
feedback_vertex(vclipped + i);
}
}
void STATE_APIENTRY
crStateFeedbackVertex4f(GLfloat x, GLfloat y, GLfloat z, GLfloat w)
{
CRContext *g = GetCurrentContext();
CRTransformState *t = &(g->transform);
CRPolygonState *p = &(g->polygon);
CRVertex *v = g->vBuffer + g->vCount;
/* store the vertex */
v->attrib[VERT_ATTRIB_POS][0] = x;
v->attrib[VERT_ATTRIB_POS][1] = y;
v->attrib[VERT_ATTRIB_POS][2] = z;
v->attrib[VERT_ATTRIB_POS][3] = w;
COPY_4V(v->attrib[VERT_ATTRIB_COLOR0] , g->current.vertexAttrib[VERT_ATTRIB_COLOR0]); /* XXX need to apply lighting */
v->colorIndex = g->current.colorIndex; /* XXX need to apply lighting */
/* Don't do this, we're capturing TexCoord ourselves as
* we don't have a pincher like the tilesortSPU */
/* v->texCoord[0] = g->current.texCoord[0]; */
/* transform to eye space, then clip space */
TRANSFORM_POINTA(v->eyePos, *(t->modelViewStack.top), v->attrib[VERT_ATTRIB_POS]);
TRANSFORM_POINT(v->clipPos, *(t->projectionStack.top), v->eyePos);
switch (g->current.mode) {
case GL_POINTS:
CRASSERT(g->vCount == 0);
feedback_point(v);
break;
case GL_LINES:
if (g->vCount == 0)
{
g->vCount = 1;
}
else
{
CRASSERT(g->vCount == 1);
feedback_line(g->vBuffer + 0, g->vBuffer + 1, g->lineReset);
g->vCount = 0;
}
break;
case GL_LINE_STRIP:
if (g->vCount == 0)
{
g->vCount = 1;
}
else
{
CRASSERT(g->vCount == 1);
feedback_line(g->vBuffer + 0, g->vBuffer + 1, g->lineReset);
g->vBuffer[0] = g->vBuffer[1];
g->lineReset = GL_FALSE;
/* leave g->vCount at 1 */
}
break;
case GL_LINE_LOOP:
if (g->vCount == 0)
{
g->lineLoop = GL_FALSE;
g->vCount = 1;
}
else if (g->vCount == 1)
{
feedback_line(g->vBuffer + 0, g->vBuffer + 1, g->lineReset);
g->lineReset = GL_FALSE;
g->lineLoop = GL_TRUE;
g->vCount = 2;
}
else
{
CRASSERT(g->vCount == 2);
CRASSERT(g->lineReset == GL_FALSE);
g->lineLoop = GL_FALSE;
feedback_line(g->vBuffer + 1, g->vBuffer + 2, g->lineReset);
g->vBuffer[1] = g->vBuffer[2];
/* leave g->vCount at 2 */
}
break;
case GL_TRIANGLES:
if (g->vCount == 0 || g->vCount == 1)
{
g->vCount++;
}
else
{
CRASSERT(g->vCount == 2);
feedback_triangle(g->vBuffer + 0, g->vBuffer + 1, g->vBuffer + 2);
g->vCount = 0;
}
break;
case GL_TRIANGLE_STRIP:
if (g->vCount == 0 || g->vCount == 1)
{
g->vCount++;
}
else if (g->vCount == 2)
{
feedback_triangle(g->vBuffer + 0, g->vBuffer + 1, g->vBuffer + 2);
g->vCount = 3;
}
else
{
CRASSERT(g->vCount == 3);
feedback_triangle(g->vBuffer + 1, g->vBuffer + 3, g->vBuffer + 2);
g->vBuffer[0] = g->vBuffer[2];
g->vBuffer[1] = g->vBuffer[3];
g->vCount = 2;
}
break;
case GL_TRIANGLE_FAN:
if (g->vCount == 0 || g->vCount == 1)
{
g->vCount++;
}
else
{
CRASSERT(g->vCount == 2);
feedback_triangle(g->vBuffer + 0, g->vBuffer + 1, g->vBuffer + 2);
g->vBuffer[1] = g->vBuffer[2];
/* leave g->vCount = 2 */
}
break;
case GL_QUADS:
if (g->vCount < 3)
{
g->vCount++;
}
else
{
CRASSERT(g->vCount == 3);
feedback_triangle(g->vBuffer + 0, g->vBuffer + 1, g->vBuffer + 2);
feedback_triangle(g->vBuffer + 0, g->vBuffer + 2, g->vBuffer + 3);
g->vCount = 0;
}
break;
case GL_QUAD_STRIP:
if (g->vCount < 3)
{
g->vCount++;
}
else
{
CRASSERT(g->vCount == 3);
feedback_triangle(g->vBuffer + 0, g->vBuffer + 1, g->vBuffer + 2);
feedback_triangle(g->vBuffer + 1, g->vBuffer + 3, g->vBuffer + 2);
g->vBuffer[0] = g->vBuffer[2];
g->vBuffer[1] = g->vBuffer[3];
g->vCount = 2;
}
break;
case GL_POLYGON:
/* XXX need to observe polygon mode for the above TRI/QUAD prims */
switch (p->frontMode) {
case GL_POINT:
CRASSERT(g->vCount == 0);
feedback_point(v);
break;
case GL_LINE:
if (g->vCount == 0)
{
g->lineLoop = GL_FALSE;
g->vCount = 1;
}
else if (g->vCount == 1)
{
feedback_line(g->vBuffer + 0, g->vBuffer + 1, g->lineReset);
g->lineReset = GL_FALSE;
g->lineLoop = GL_TRUE;
g->vCount = 2;
}
else
{
CRASSERT(g->vCount == 2);
CRASSERT(g->lineReset == GL_FALSE);
g->lineLoop = GL_FALSE;
feedback_line(g->vBuffer + 1, g->vBuffer + 2, g->lineReset);
g->vBuffer[1] = g->vBuffer[2];
/* leave g->vCount at 2 */
}
break;
case GL_FILL:
/* draw as a tri-fan */
if (g->vCount == 0 || g->vCount == 1)
{
g->vCount++;
}
else
{
CRASSERT(g->vCount == 2);
feedback_triangle(g->vBuffer + 0, g->vBuffer + 1, g->vBuffer + 2);
g->vBuffer[1] = g->vBuffer[2];
/* leave g->vCount = 2 */
}
break;
default:
; /* impossible */
}
break;
default:
; /* impossible */
}
}
void STATE_APIENTRY
crStateFeedbackBegin(GLenum mode)
{
CRContext *g = GetCurrentContext();
crStateBegin(mode);
g->vCount = 0;
g->lineReset = GL_TRUE;
g->lineLoop = GL_FALSE;
}
void STATE_APIENTRY
crStateFeedbackEnd(void)
{
CRContext *g = GetCurrentContext();
if ( (g->current.mode == GL_LINE_LOOP ||
(g->current.mode == GL_POLYGON && g->polygon.frontMode == GL_LINE))
&& g->vCount == 2 )
{
/* draw the last line segment */
if (g->lineLoop)
feedback_line(g->vBuffer + 1, g->vBuffer + 0, GL_FALSE);
else
feedback_line(g->vBuffer + 2, g->vBuffer + 0, GL_FALSE);
}
crStateEnd();
}
void STATE_APIENTRY
crStateFeedbackBuffer(GLsizei size, GLenum type, GLfloat * buffer)
{
CRContext *g = GetCurrentContext();
CRFeedbackState *f = &(g->feedback);
if (g->current.inBeginEnd)
{
crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
"FeedbackBuffer called in begin/end");
return;
}
if (g->renderMode == GL_FEEDBACK)
{
crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
"Invalid Operation GL_FEEDBACK");
return;
}
if (size < 0)
{
crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
"Invalid Value size < 0");
return;
}
if (!buffer)
{
crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
"Invalid Value buffer = NULL");
f->bufferSize = 0;
return;
}
FLUSH();
switch (type)
{
case GL_2D:
f->mask = 0;
break;
case GL_3D:
f->mask = FB_3D;
break;
case GL_3D_COLOR:
f->mask = (FB_3D | FB_COLOR); /* FB_INDEX ?? */
break;
case GL_3D_COLOR_TEXTURE:
f->mask = (FB_3D | FB_COLOR | FB_TEXTURE); /* FB_INDEX ?? */
break;
case GL_4D_COLOR_TEXTURE:
f->mask = (FB_3D | FB_4D | FB_COLOR | FB_TEXTURE); /* FB_INDEX ?? */
break;
default:
crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "invalid type");
return;
}
f->type = type;
f->bufferSize = size;
f->buffer = buffer;
f->count = 0;
}
void STATE_APIENTRY
crStatePassThrough(GLfloat token)
{
CRContext *g = GetCurrentContext();
CRFeedbackState *f = &(g->feedback);
if (g->current.inBeginEnd)
{
crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
"PassThrough called in begin/end");
return;
}
FLUSH();
if (g->renderMode == GL_FEEDBACK)
{
FEEDBACK_TOKEN((GLfloat) (GLint) GL_PASS_THROUGH_TOKEN);
FEEDBACK_TOKEN(token);
}
}
/*
* Although these functions are used by the feedbackSPU alone,
* I've left them here as they interface to the other functions.....
*/
void STATE_APIENTRY
crStateFeedbackGetBooleanv(GLenum pname, GLboolean * params)
{
CRContext *g = GetCurrentContext();
switch (pname)
{
case GL_FEEDBACK_BUFFER_SIZE:
params[0] = (GLboolean) (g->feedback.bufferSize != 0);
break;
case GL_FEEDBACK_BUFFER_TYPE:
params[0] = (GLboolean) (g->feedback.type != 0);
break;
case GL_SELECTION_BUFFER_SIZE:
params[0] = (GLboolean) (g->selection.bufferSize != 0);
break;
default:
break;
}
}
void STATE_APIENTRY
crStateFeedbackGetDoublev(GLenum pname, GLdouble * params)
{
CRContext *g = GetCurrentContext();
switch (pname)
{
case GL_FEEDBACK_BUFFER_SIZE:
params[0] = (GLdouble) g->feedback.bufferSize;
break;
case GL_FEEDBACK_BUFFER_TYPE:
params[0] = (GLdouble) g->feedback.type;
break;
case GL_SELECTION_BUFFER_SIZE:
params[0] = (GLdouble) g->selection.bufferSize;
break;
default:
break;
}
}
void STATE_APIENTRY
crStateFeedbackGetFloatv(GLenum pname, GLfloat * params)
{
CRContext *g = GetCurrentContext();
switch (pname)
{
case GL_FEEDBACK_BUFFER_SIZE:
params[0] = (GLfloat) g->feedback.bufferSize;
break;
case GL_FEEDBACK_BUFFER_TYPE:
params[0] = (GLfloat) g->feedback.type;
break;
case GL_SELECTION_BUFFER_SIZE:
params[0] = (GLfloat) g->selection.bufferSize;
break;
default:
break;
}
}
void STATE_APIENTRY
crStateFeedbackGetIntegerv(GLenum pname, GLint * params)
{
CRContext *g = GetCurrentContext();
switch (pname)
{
case GL_FEEDBACK_BUFFER_SIZE:
params[0] = (GLint) g->feedback.bufferSize;
break;
case GL_FEEDBACK_BUFFER_TYPE:
params[0] = (GLint) g->feedback.type;
break;
case GL_SELECTION_BUFFER_SIZE:
params[0] = (GLint) g->selection.bufferSize;
break;
default:
break;
}
}
void STATE_APIENTRY
crStateFeedbackDrawPixels(GLsizei width, GLsizei height, GLenum format,
GLenum type, const GLvoid * pixels)
{
CRContext *g = GetCurrentContext();
CRFeedbackState *f = &(g->feedback);
(void) width;
(void) height;
(void) format;
(void) type;
(void) pixels;
FEEDBACK_TOKEN((GLfloat) (GLint) GL_DRAW_PIXEL_TOKEN);
feedback_rasterpos();
}
void STATE_APIENTRY
crStateFeedbackCopyPixels(GLint x, GLint y, GLsizei width, GLsizei height,
GLenum type)
{
CRContext *g = GetCurrentContext();
CRFeedbackState *f = &(g->feedback);
(void) x;
(void) y;
(void) width;
(void) height;
(void) type;
FEEDBACK_TOKEN((GLfloat) (GLint) GL_COPY_PIXEL_TOKEN);
feedback_rasterpos();
}
void STATE_APIENTRY
crStateFeedbackBitmap(GLsizei width, GLsizei height, GLfloat xorig,
GLfloat yorig, GLfloat xmove, GLfloat ymove,
const GLubyte * bitmap)
{
CRContext *g = GetCurrentContext();
CRFeedbackState *f = &(g->feedback);
(void) width;
(void) height;
(void) bitmap;
(void) xorig;
(void) yorig;
FEEDBACK_TOKEN((GLfloat) (GLint) GL_BITMAP_TOKEN);
feedback_rasterpos();
if (g->current.rasterValid)
{
g->current.rasterAttrib[VERT_ATTRIB_POS][0] += xmove;
g->current.rasterAttrib[VERT_ATTRIB_POS][1] += ymove;
}
}
void STATE_APIENTRY
crStateFeedbackVertex4fv(const GLfloat * v)
{
crStateFeedbackVertex4f(v[0], v[1], v[2], v[3]);
}
void STATE_APIENTRY
crStateFeedbackVertex4s(GLshort v0, GLshort v1, GLshort v2, GLshort v3)
{
crStateFeedbackVertex4f((GLfloat) v0, (GLfloat) v1, (GLfloat) v2,
(GLfloat) v3);
}
void STATE_APIENTRY
crStateFeedbackVertex4sv(const GLshort * v)
{
crStateFeedbackVertex4f((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2],
(GLfloat) v[3]);
}
void STATE_APIENTRY
crStateFeedbackVertex4i(GLint v0, GLint v1, GLint v2, GLint v3)
{
crStateFeedbackVertex4f((GLfloat) v0, (GLfloat) v1, (GLfloat) v2,
(GLfloat) v3);
}
void STATE_APIENTRY
crStateFeedbackVertex4iv(const GLint * v)
{
crStateFeedbackVertex4f((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2],
(GLfloat) v[3]);
}
void STATE_APIENTRY
crStateFeedbackVertex4d(GLdouble v0, GLdouble v1, GLdouble v2, GLdouble v3)
{
crStateFeedbackVertex4f((GLfloat) v0, (GLfloat) v1, (GLfloat) v2,
(GLfloat) v3);
}
void STATE_APIENTRY
crStateFeedbackVertex4dv(const GLdouble * v)
{
crStateFeedbackVertex4f((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2],
(GLfloat) v[3]);
}
void STATE_APIENTRY
crStateFeedbackVertex2i(GLint v0, GLint v1)
{
crStateFeedbackVertex4f((GLfloat) v0, (GLfloat) v1, 0.0f, 1.0f);
}
void STATE_APIENTRY
crStateFeedbackVertex2iv(const GLint * v)
{
crStateFeedbackVertex4f((GLfloat) v[0], (GLfloat) v[1], 0.0f, 1.0f);
}
void STATE_APIENTRY
crStateFeedbackVertex2s(GLshort v0, GLshort v1)
{
crStateFeedbackVertex4f((GLfloat) v0, (GLfloat) v1, 0.0f, 1.0f);
}
void STATE_APIENTRY
crStateFeedbackVertex2sv(const GLshort * v)
{
crStateFeedbackVertex4f((GLfloat) v[0], (GLfloat) v[1], 0.0f, 1.0f);
}
void STATE_APIENTRY
crStateFeedbackVertex2f(GLfloat v0, GLfloat v1)
{
crStateFeedbackVertex4f(v0, v1, 0.0f, 1.0f);
}
void STATE_APIENTRY
crStateFeedbackVertex2fv(const GLfloat * v)
{
crStateFeedbackVertex4f(v[0], v[1], 0.0f, 1.0f);
}
void STATE_APIENTRY
crStateFeedbackVertex2d(GLdouble v0, GLdouble v1)
{
crStateFeedbackVertex4f((GLfloat) v0, (GLfloat) v1, 0.0f, 1.0f);
}
void STATE_APIENTRY
crStateFeedbackVertex2dv(const GLdouble * v)
{
crStateFeedbackVertex4f((GLfloat) v[0], (GLfloat) v[1], 0.0f, 1.0f);
}
void STATE_APIENTRY
crStateFeedbackVertex3i(GLint v0, GLint v1, GLint v2)
{
crStateFeedbackVertex4f((GLfloat) v0, (GLfloat) v1, (GLfloat) v2, 1.0f);
}
void STATE_APIENTRY
crStateFeedbackVertex3iv(const GLint * v)
{
crStateFeedbackVertex4f((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2], 1.0f);
}
void STATE_APIENTRY
crStateFeedbackVertex3s(GLshort v0, GLshort v1, GLshort v2)
{
crStateFeedbackVertex4f((GLfloat) v0, (GLfloat) v1, (GLfloat) v2, 1.0f);
}
void STATE_APIENTRY
crStateFeedbackVertex3sv(const GLshort * v)
{
crStateFeedbackVertex4f((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2],
1.0f);
}
void STATE_APIENTRY
crStateFeedbackVertex3f(GLfloat v0, GLfloat v1, GLfloat v2)
{
crStateFeedbackVertex4f(v0, v1, v2, 1.0f);
}
void STATE_APIENTRY
crStateFeedbackVertex3fv(const GLfloat * v)
{
crStateFeedbackVertex4f(v[0], v[1], v[2], 1.0f);
}
void STATE_APIENTRY
crStateFeedbackVertex3d(GLdouble v0, GLdouble v1, GLdouble v2)
{
crStateFeedbackVertex4f((GLfloat) v0, (GLfloat) v1, (GLfloat) v2, 1.0f);
}
void STATE_APIENTRY
crStateFeedbackVertex3dv(const GLdouble * v)
{
crStateFeedbackVertex4f((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2],
1.0f);
}
void STATE_APIENTRY
crStateFeedbackTexCoord4f( GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3 )
{
CRContext *g = GetCurrentContext();
CRVertex *v = g->vBuffer + g->vCount;
/* store the texCoord in the current vertex */
v->attrib[VERT_ATTRIB_TEX0][0] = v0;
v->attrib[VERT_ATTRIB_TEX0][1] = v1;
v->attrib[VERT_ATTRIB_TEX0][2] = v2;
v->attrib[VERT_ATTRIB_TEX0][3] = v3;
}
void STATE_APIENTRY
crStateFeedbackTexCoord4fv( const GLfloat *v )
{
crStateFeedbackTexCoord4f( v[0], v[1], v[2], v[3] );
}
void STATE_APIENTRY
crStateFeedbackTexCoord4s( GLshort v0, GLshort v1, GLshort v2, GLshort v3 )
{
crStateFeedbackTexCoord4f( (GLfloat)v0, (GLfloat)v1, (GLfloat)v2, (GLfloat)v3 );
}
void STATE_APIENTRY
crStateFeedbackTexCoord4sv( const GLshort *v )
{
crStateFeedbackTexCoord4f( (GLfloat)v[0], (GLfloat)v[1], (GLfloat)v[2], (GLfloat)v[3] );
}
void STATE_APIENTRY
crStateFeedbackTexCoord4i( GLint v0, GLint v1, GLint v2, GLint v3 )
{
crStateFeedbackTexCoord4f( (GLfloat)v0, (GLfloat)v1, (GLfloat)v2, (GLfloat)v3 );
}
void STATE_APIENTRY
crStateFeedbackTexCoord4iv( const GLint *v )
{
crStateFeedbackTexCoord4f( (GLfloat)v[0], (GLfloat)v[1], (GLfloat)v[2], (GLfloat)v[3] );
}
void STATE_APIENTRY
crStateFeedbackTexCoord4d( GLdouble v0, GLdouble v1, GLdouble v2, GLdouble v3 )
{
crStateFeedbackTexCoord4f( (GLfloat)v0, (GLfloat)v1, (GLfloat)v2, (GLfloat)v3 );
}
void STATE_APIENTRY
crStateFeedbackTexCoord4dv( const GLdouble *v )
{
crStateFeedbackTexCoord4f( (GLfloat)v[0], (GLfloat)v[1], (GLfloat)v[2], (GLfloat)v[3] );
}
void STATE_APIENTRY
crStateFeedbackTexCoord1i( GLint v0 )
{
crStateFeedbackTexCoord4f( (GLfloat)v0, 0.0f, 0.0f, 1.0f );
}
void STATE_APIENTRY
crStateFeedbackTexCoord1iv( const GLint *v )
{
crStateFeedbackTexCoord4f( (GLfloat)v[0], 0.0f, 0.0f, 1.0f );
}
void STATE_APIENTRY
crStateFeedbackTexCoord1s( GLshort v0 )
{
crStateFeedbackTexCoord4f( (GLfloat)v0, 0.0f, 0.0f, 1.0f );
}
void STATE_APIENTRY
crStateFeedbackTexCoord1sv( const GLshort *v )
{
crStateFeedbackTexCoord4f( (GLfloat)v[0], 0.0f, 0.0f, 1.0f );
}
void STATE_APIENTRY
crStateFeedbackTexCoord1f( GLfloat v0 )
{
crStateFeedbackTexCoord4f( v0, 0.0f, 0.0f, 1.0f );
}
void STATE_APIENTRY
crStateFeedbackTexCoord1fv( const GLfloat *v )
{
crStateFeedbackTexCoord4f( v[0], 0.0f, 0.0f, 1.0f );
}
void STATE_APIENTRY
crStateFeedbackTexCoord1d( GLdouble v0 )
{
crStateFeedbackTexCoord4f( (GLfloat)v0, 0.0f, 0.0f, 1.0f );
}
void STATE_APIENTRY
crStateFeedbackTexCoord1dv( const GLdouble *v )
{
crStateFeedbackTexCoord4f( (GLfloat)v[0], 0.0f, 0.0f, 1.0f );
}
void STATE_APIENTRY
crStateFeedbackTexCoord2i( GLint v0, GLint v1 )
{
crStateFeedbackTexCoord4f( (GLfloat)v0, (GLfloat)v1, 0.0f, 1.0f );
}
void STATE_APIENTRY
crStateFeedbackTexCoord2iv( const GLint *v )
{
crStateFeedbackTexCoord4f( (GLfloat)v[0], (GLfloat)v[1], 0.0f, 1.0f );
}
void STATE_APIENTRY
crStateFeedbackTexCoord2s( GLshort v0, GLshort v1 )
{
crStateFeedbackTexCoord4f( (GLfloat)v0, (GLfloat)v1, 0.0f, 1.0f );
}
void STATE_APIENTRY
crStateFeedbackTexCoord2sv( const GLshort *v )
{
crStateFeedbackTexCoord4f( (GLfloat)v[0], (GLfloat)v[1], 0.0f, 1.0f );
}
void STATE_APIENTRY
crStateFeedbackTexCoord2f( GLfloat v0, GLfloat v1 )
{
crStateFeedbackTexCoord4f( v0, v1, 0.0f, 1.0f );
}
void STATE_APIENTRY
crStateFeedbackTexCoord2fv( const GLfloat *v )
{
crStateFeedbackTexCoord4f( v[0], v[1], 0.0f, 1.0f );
}
void STATE_APIENTRY
crStateFeedbackTexCoord2d( GLdouble v0, GLdouble v1 )
{
crStateFeedbackTexCoord4f( (GLfloat)v0, (GLfloat)v1, 0.0f, 1.0f );
}
void STATE_APIENTRY
crStateFeedbackTexCoord2dv( const GLdouble *v )
{
crStateFeedbackTexCoord4f( (GLfloat)v[0], (GLfloat)v[1], 0.0f, 1.0f );
}
void STATE_APIENTRY
crStateFeedbackTexCoord3i( GLint v0, GLint v1, GLint v2 )
{
crStateFeedbackTexCoord4f( (GLfloat)v0, (GLfloat)v1, (GLfloat)v2, 1.0f );
}
void STATE_APIENTRY
crStateFeedbackTexCoord3iv( const GLint *v )
{
crStateFeedbackTexCoord4f( (GLfloat)v[0], (GLfloat)v[1], 0.0f, 1.0f );
}
void STATE_APIENTRY
crStateFeedbackTexCoord3s( GLshort v0, GLshort v1, GLshort v2 )
{
crStateFeedbackTexCoord4f( (GLfloat)v0, (GLfloat)v1, (GLfloat)v2, 1.0f );
}
void STATE_APIENTRY
crStateFeedbackTexCoord3sv( const GLshort *v )
{
crStateFeedbackTexCoord4f( (GLfloat)v[0], (GLfloat)v[1], (GLfloat)v[2], 1.0f );
}
void STATE_APIENTRY
crStateFeedbackTexCoord3f( GLfloat v0, GLfloat v1, GLfloat v2 )
{
crStateFeedbackTexCoord4f( v0, v1, v2, 1.0f );
}
void STATE_APIENTRY
crStateFeedbackTexCoord3fv( const GLfloat *v )
{
crStateFeedbackTexCoord4f( v[0], v[1], v[2], 1.0f );
}
void STATE_APIENTRY
crStateFeedbackTexCoord3d( GLdouble v0, GLdouble v1, GLdouble v2 )
{
crStateFeedbackTexCoord4f( (GLfloat)v0, (GLfloat)v1, (GLfloat)v2, 1.0f );
}
void STATE_APIENTRY
crStateFeedbackTexCoord3dv( const GLdouble *v )
{
crStateFeedbackTexCoord4f( (GLfloat)v[0], (GLfloat)v[1], (GLfloat)v[2], 1.0f );
}
void STATE_APIENTRY
crStateFeedbackRectf(GLfloat x0, GLfloat y0, GLfloat x1, GLfloat y1)
{
crStateFeedbackBegin(GL_QUADS);
crStateFeedbackVertex2f(x0, y0);
crStateFeedbackVertex2f(x0, y1);
crStateFeedbackVertex2f(x1, y1);
crStateFeedbackVertex2f(x1, y0);
crStateFeedbackEnd();
}
void STATE_APIENTRY
crStateFeedbackRecti(GLint x0, GLint y0, GLint x1, GLint y1)
{
crStateFeedbackRectf((GLfloat) x0, (GLfloat) y0, (GLfloat) x1, (GLfloat) y1);
}
void STATE_APIENTRY
crStateFeedbackRectd(GLdouble x0, GLdouble y0, GLdouble x1, GLdouble y1)
{
crStateFeedbackRectf((GLfloat) x0, (GLfloat) y0, (GLfloat) x1, (GLfloat) y1);
}
void STATE_APIENTRY
crStateFeedbackRects(GLshort x0, GLshort y0, GLshort x1, GLshort y1)
{
crStateFeedbackRectf((GLfloat) x0, (GLfloat) y0, (GLfloat) x1, (GLfloat) y1);
}
void STATE_APIENTRY
crStateFeedbackRectiv(const GLint *v0, const GLint *v1)
{
crStateFeedbackRectf((GLfloat) v0[0], (GLfloat) v0[1], (GLfloat) v1[0], (GLfloat) v1[1]);
}
void STATE_APIENTRY
crStateFeedbackRectfv(const GLfloat *v0, const GLfloat *v1)
{
crStateFeedbackRectf(v0[0], v0[1], v1[0], v1[1]);
}
void STATE_APIENTRY
crStateFeedbackRectdv(const GLdouble *v0, const GLdouble *v1)
{
crStateFeedbackRectf((GLfloat) v0[0], (GLfloat) v0[1], (GLfloat) v1[0], (GLfloat) v1[1]);
}
void STATE_APIENTRY
crStateFeedbackRectsv(const GLshort *v0, const GLshort *v1)
{
crStateFeedbackRectf((GLfloat) v0[0], (GLfloat) v0[1], (GLfloat) v1[0], (GLfloat) v1[1]);
}
/**********************************************************************/
/***** Selection *****/
/**********************************************************************/
void STATE_APIENTRY
crStateSelectBuffer(GLsizei size, GLuint * buffer)
{
CRContext *g = GetCurrentContext();
CRSelectionState *se = &(g->selection);
if (g->current.inBeginEnd)
{
crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
"SelectBuffer called in begin/end");
return;
}
if (g->renderMode == GL_SELECT)
{
crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
"SelectBuffer called with RenderMode = GL_SELECT");
return;
}
FLUSH();
se->buffer = buffer;
se->bufferSize = size;
se->bufferCount = 0;
se->hitFlag = GL_FALSE;
se->hitMinZ = 1.0;
se->hitMaxZ = 0.0;
}
#define WRITE_RECORD( V ) \
if (se->bufferCount < se->bufferSize) { \
se->buffer[se->bufferCount] = (V); \
} \
se->bufferCount++;
static void
write_hit_record(CRSelectionState * se)
{
GLuint i;
GLuint zmin, zmax, zscale = (~0u);
/* hitMinZ and hitMaxZ are in [0,1]. Multiply these values by */
/* 2^32-1 and round to nearest unsigned integer. */
zmin = (GLuint) ((GLfloat) zscale * se->hitMinZ);
zmax = (GLuint) ((GLfloat) zscale * se->hitMaxZ);
WRITE_RECORD(se->nameStackDepth);
WRITE_RECORD(zmin);
WRITE_RECORD(zmax);
for (i = 0; i < se->nameStackDepth; i++)
{
WRITE_RECORD(se->nameStack[i]);
}
se->hits++;
se->hitFlag = GL_FALSE;
se->hitMinZ = 1.0;
se->hitMaxZ = -1.0;
}
void STATE_APIENTRY
crStateInitNames(void)
{
CRContext *g = GetCurrentContext();
CRSelectionState *se = &(g->selection);
if (g->current.inBeginEnd)
{
crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
"InitNames called in begin/end");
return;
}
FLUSH();
/* Record the hit before the hitFlag is wiped out again. */
if (g->renderMode == GL_SELECT)
{
if (se->hitFlag)
{
write_hit_record(se);
}
}
se->nameStackDepth = 0;
se->hitFlag = GL_FALSE;
se->hitMinZ = 1.0;
se->hitMaxZ = 0.0;
}
void STATE_APIENTRY
crStateLoadName(GLuint name)
{
CRContext *g = GetCurrentContext();
CRSelectionState *se = &(g->selection);
if (g->current.inBeginEnd)
{
crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
"LoadName called in begin/end");
return;
}
if (g->renderMode != GL_SELECT)
{
return;
}
if (se->nameStackDepth == 0)
{
crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
"nameStackDepth = 0");
return;
}
FLUSH();
if (se->hitFlag)
{
write_hit_record(se);
}
if (se->nameStackDepth < MAX_NAME_STACK_DEPTH)
{
se->nameStack[se->nameStackDepth - 1] = name;
}
else
{
se->nameStack[MAX_NAME_STACK_DEPTH - 1] = name;
}
}
void STATE_APIENTRY
crStatePushName(GLuint name)
{
CRContext *g = GetCurrentContext();
CRSelectionState *se = &(g->selection);
if (g->current.inBeginEnd)
{
crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
"PushName called in begin/end");
return;
}
if (g->renderMode != GL_SELECT)
{
return;
}
FLUSH();
if (se->hitFlag)
{
write_hit_record(se);
}
if (se->nameStackDepth >= MAX_NAME_STACK_DEPTH)
{
crStateError(__LINE__, __FILE__, GL_STACK_OVERFLOW,
"nameStackDepth overflow");
}
else
se->nameStack[se->nameStackDepth++] = name;
}
void STATE_APIENTRY
crStatePopName(void)
{
CRContext *g = GetCurrentContext();
CRSelectionState *se = &(g->selection);
if (g->current.inBeginEnd)
{
crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
"PopName called in begin/end");
return;
}
if (g->renderMode != GL_SELECT)
{
return;
}
FLUSH();
if (se->hitFlag)
{
write_hit_record(se);
}
if (se->nameStackDepth == 0)
{
crStateError(__LINE__, __FILE__, GL_STACK_UNDERFLOW,
"nameStackDepth underflow");
}
else
se->nameStackDepth--;
}
static void
update_hitflag(GLfloat z)
{
CRContext *g = GetCurrentContext();
CRSelectionState *se = &(g->selection);
se->hitFlag = GL_TRUE;
if (z < se->hitMinZ)
se->hitMinZ = z;
if (z > se->hitMaxZ)
se->hitMaxZ = z;
}
static void
select_rasterpos(void)
{
CRContext *g = GetCurrentContext();
if (g->current.rasterValid)
update_hitflag(g->current.rasterAttrib[VERT_ATTRIB_POS][2]);
}
static void
select_point(const CRVertex *v)
{
CRContext *g = GetCurrentContext();
if (clip_point(v) == 0)
{
CRVertex c = *v;
MAP_POINT(c.winPos, c.clipPos, g->viewport);
update_hitflag(c.winPos.z);
}
}
static void
select_line(const CRVertex *v0, const CRVertex *v1)
{
CRContext *g = GetCurrentContext();
CRVertex c0, c1;
if (clip_line(v0, v1, &c0, &c1))
{
MAP_POINT(c0.winPos, c0.clipPos, g->viewport);
MAP_POINT(c1.winPos, c1.clipPos, g->viewport);
update_hitflag(c0.winPos.z);
update_hitflag(c1.winPos.z);
}
}
static void
select_triangle(const CRVertex *v0,
const CRVertex *v1,
const CRVertex *v2)
{
CRContext *g = GetCurrentContext();
CRVertex vlist[3], vclipped[8];
GLuint i, n;
vlist[0] = *v0;
vlist[1] = *v1;
vlist[2] = *v2;
n = clip_polygon(vlist, 3, vclipped);
for (i = 0; i < n; i++) {
MAP_POINT(vclipped[i].winPos, vclipped[i].clipPos, g->viewport);
update_hitflag(vclipped[i].winPos.z);
}
}
void STATE_APIENTRY
crStateSelectVertex4f(GLfloat x, GLfloat y, GLfloat z, GLfloat w)
{
CRContext *g = GetCurrentContext();
CRTransformState *t = &(g->transform);
CRVertex *v = g->vBuffer + g->vCount;
/* store the vertex */
v->attrib[VERT_ATTRIB_POS][0] = x;
v->attrib[VERT_ATTRIB_POS][1] = y;
v->attrib[VERT_ATTRIB_POS][2] = z;
v->attrib[VERT_ATTRIB_POS][3] = w;
COPY_4V(v->attrib[VERT_ATTRIB_COLOR0] , g->current.vertexAttrib[VERT_ATTRIB_COLOR0]); /* XXX need to apply lighting */
v->colorIndex = g->current.colorIndex; /* XXX need to apply lighting */
/* Don't do this, we're capturing TexCoord ourselves as
* we don't have a pincher like the tilesortSPU */
/* v->texCoord[0] = g->current.texCoord[0]; */
/* transform to eye space, then clip space */
TRANSFORM_POINTA(v->eyePos, *(t->modelViewStack.top), v->attrib[VERT_ATTRIB_POS]);
TRANSFORM_POINT(v->clipPos, *(t->projectionStack.top), v->eyePos);
switch (g->current.mode) {
case GL_POINTS:
CRASSERT(g->vCount == 0);
select_point(v);
break;
case GL_LINES:
if (g->vCount == 0)
{
g->vCount = 1;
}
else
{
CRASSERT(g->vCount == 1);
select_line(g->vBuffer + 0, g->vBuffer + 1);
g->vCount = 0;
}
break;
case GL_LINE_STRIP:
if (g->vCount == 0)
{
g->vCount = 1;
}
else
{
CRASSERT(g->vCount == 1);
select_line(g->vBuffer + 0, g->vBuffer + 1);
g->vBuffer[0] = g->vBuffer[1];
/* leave g->vCount at 1 */
}
break;
case GL_LINE_LOOP:
if (g->vCount == 0)
{
g->vCount = 1;
g->lineLoop = GL_FALSE;
}
else if (g->vCount == 1)
{
select_line(g->vBuffer + 0, g->vBuffer + 1);
g->lineLoop = GL_TRUE;
g->vCount = 2;
}
else
{
CRASSERT(g->vCount == 2);
g->lineLoop = GL_FALSE;
select_line(g->vBuffer + 1, g->vBuffer + 2);
g->vBuffer[1] = g->vBuffer[2];
/* leave g->vCount at 2 */
}
break;
case GL_TRIANGLES:
if (g->vCount == 0 || g->vCount == 1)
{
g->vCount++;
}
else
{
CRASSERT(g->vCount == 2);
select_triangle(g->vBuffer + 0, g->vBuffer + 1, g->vBuffer + 2);
g->vCount = 0;
}
break;
case GL_TRIANGLE_STRIP:
if (g->vCount == 0 || g->vCount == 1)
{
g->vCount++;
}
else if (g->vCount == 2)
{
select_triangle(g->vBuffer + 0, g->vBuffer + 1, g->vBuffer + 2);
g->vCount = 3;
}
else
{
CRASSERT(g->vCount == 3);
select_triangle(g->vBuffer + 1, g->vBuffer + 3, g->vBuffer + 2);
g->vBuffer[0] = g->vBuffer[2];
g->vBuffer[1] = g->vBuffer[3];
g->vCount = 2;
}
break;
case GL_TRIANGLE_FAN:
if (g->vCount == 0 || g->vCount == 1)
{
g->vCount++;
}
else
{
CRASSERT(g->vCount == 2);
select_triangle(g->vBuffer + 0, g->vBuffer + 1, g->vBuffer + 2);
g->vBuffer[1] = g->vBuffer[2];
/* leave g->vCount = 2 */
}
break;
case GL_QUADS:
if (g->vCount < 3)
{
g->vCount++;
}
else
{
CRASSERT(g->vCount == 3);
select_triangle(g->vBuffer + 0, g->vBuffer + 1, g->vBuffer + 2);
select_triangle(g->vBuffer + 0, g->vBuffer + 2, g->vBuffer + 3);
g->vCount = 0;
}
break;
case GL_QUAD_STRIP:
if (g->vCount < 3)
{
g->vCount++;
}
else
{
CRASSERT(g->vCount == 3);
select_triangle(g->vBuffer + 0, g->vBuffer + 1, g->vBuffer + 2);
select_triangle(g->vBuffer + 1, g->vBuffer + 3, g->vBuffer + 2);
g->vBuffer[0] = g->vBuffer[2];
g->vBuffer[1] = g->vBuffer[3];
g->vCount = 2;
}
break;
case GL_POLYGON:
/* draw as a tri-fan */
if (g->vCount == 0 || g->vCount == 1)
{
g->vCount++;
}
else
{
CRASSERT(g->vCount == 2);
select_triangle(g->vBuffer + 0, g->vBuffer + 1, g->vBuffer + 2);
g->vBuffer[1] = g->vBuffer[2];
/* leave g->vCount = 2 */
}
break;
default:
; /* impossible */
}
}
void STATE_APIENTRY
crStateSelectRasterPos4f(GLfloat x, GLfloat y, GLfloat z, GLfloat w)
{
crStateRasterPos4f( x, y, z, w );
select_rasterpos();
}
void STATE_APIENTRY
crStateSelectBegin(GLenum mode)
{
CRContext *g = GetCurrentContext();
crStateBegin(mode);
g->vCount = 0;
g->lineReset = GL_TRUE;
g->lineLoop = GL_FALSE;
}
void STATE_APIENTRY
crStateSelectEnd(void)
{
CRContext *g = GetCurrentContext();
if (g->current.mode == GL_LINE_LOOP && g->vCount == 2)
{
/* draw the last line segment */
select_line(g->vBuffer + 1, g->vBuffer + 0);
}
crStateEnd();
}
void STATE_APIENTRY
crStateSelectVertex2d(GLdouble x, GLdouble y)
{
crStateSelectVertex4f((GLfloat) x, (GLfloat) y, 0.0, 1.0);
}
void STATE_APIENTRY
crStateSelectVertex2dv(const GLdouble * v)
{
crStateSelectVertex4f((GLfloat) v[0], (GLfloat) v[1], 0.0, 1.0);
}
void STATE_APIENTRY
crStateSelectVertex2f(GLfloat x, GLfloat y)
{
crStateSelectVertex4f(x, y, 0.0, 1.0);
}
void STATE_APIENTRY
crStateSelectVertex2fv(const GLfloat * v)
{
crStateSelectVertex4f(v[0], v[1], 0.0, 1.0);
}
void STATE_APIENTRY
crStateSelectVertex2i(GLint x, GLint y)
{
crStateSelectVertex4f((GLfloat) x, (GLfloat) y, 0.0, 1.0);
}
void STATE_APIENTRY
crStateSelectVertex2iv(const GLint * v)
{
crStateSelectVertex4f((GLfloat) v[0], (GLfloat) v[1], 0.0, 1.0);
}
void STATE_APIENTRY
crStateSelectVertex2s(GLshort x, GLshort y)
{
crStateSelectVertex4f((GLfloat) x, (GLfloat) y, 0.0, 1.0);
}
void STATE_APIENTRY
crStateSelectVertex2sv(const GLshort * v)
{
crStateSelectVertex4f((GLfloat) v[0], (GLfloat) v[1], 0.0, 1.0);
}
void STATE_APIENTRY
crStateSelectVertex3d(GLdouble x, GLdouble y, GLdouble z)
{
crStateSelectVertex4f((GLfloat) x, (GLfloat) y, (GLfloat) z, 1.0);
}
void STATE_APIENTRY
crStateSelectVertex3dv(const GLdouble * v)
{
crStateSelectVertex4f((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2], 1.0);
}
void STATE_APIENTRY
crStateSelectVertex3f(GLfloat x, GLfloat y, GLfloat z)
{
crStateSelectVertex4f(x, y, z, 1.0);
}
void STATE_APIENTRY
crStateSelectVertex3fv(const GLfloat * v)
{
crStateSelectVertex4f(v[0], v[1], v[2], 1.0);
}
void STATE_APIENTRY
crStateSelectVertex3i(GLint x, GLint y, GLint z)
{
crStateSelectVertex4f((GLfloat) x, (GLfloat) y, (GLfloat) z, 1.0);
}
void STATE_APIENTRY
crStateSelectVertex3iv(const GLint * v)
{
crStateSelectVertex4f((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2], 1.0);
}
void STATE_APIENTRY
crStateSelectVertex3s(GLshort x, GLshort y, GLshort z)
{
crStateSelectVertex4f((GLfloat) x, (GLfloat) y, (GLfloat) z, 1.0);
}
void STATE_APIENTRY
crStateSelectVertex3sv(const GLshort * v)
{
crStateSelectVertex4f((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2], 1.0);
}
void STATE_APIENTRY
crStateSelectVertex4d(GLdouble x, GLdouble y, GLdouble z, GLdouble w)
{
crStateSelectVertex4f((GLfloat) x, (GLfloat) y, (GLfloat) z, (GLfloat) w);
}
void STATE_APIENTRY
crStateSelectVertex4dv(const GLdouble * v)
{
crStateSelectVertex4f((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2], (GLfloat) v[3]);
}
void STATE_APIENTRY
crStateSelectVertex4fv(const GLfloat * v)
{
crStateSelectVertex4f(v[0], v[1], v[2], v[3]);
}
void STATE_APIENTRY
crStateSelectVertex4i(GLint x, GLint y, GLint z, GLint w)
{
crStateSelectVertex4f((GLfloat) x, (GLfloat) y, (GLfloat) z, (GLfloat) w);
}
void STATE_APIENTRY
crStateSelectVertex4iv(const GLint * v)
{
crStateSelectVertex4f((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2], (GLfloat) v[3]);
}
void STATE_APIENTRY
crStateSelectVertex4s(GLshort x, GLshort y, GLshort z, GLshort w)
{
crStateSelectVertex4f(x, y, z, w);
}
void STATE_APIENTRY
crStateSelectVertex4sv(const GLshort * v)
{
crStateSelectVertex4f((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2], (GLfloat) v[3]);
}
void STATE_APIENTRY
crStateSelectRasterPos2d(GLdouble x, GLdouble y)
{
crStateSelectRasterPos4f((GLfloat) x, (GLfloat) y, 0.0, 1.0);
}
void STATE_APIENTRY
crStateSelectRasterPos2dv(const GLdouble * v)
{
crStateSelectRasterPos4f((GLfloat) v[0], (GLfloat) v[1], 0.0, 1.0);
}
void STATE_APIENTRY
crStateSelectRasterPos2f(GLfloat x, GLfloat y)
{
crStateSelectRasterPos4f(x, y, 0.0, 1.0);
}
void STATE_APIENTRY
crStateSelectRasterPos2fv(const GLfloat * v)
{
crStateSelectRasterPos4f(v[0], v[1], 0.0, 1.0);
}
void STATE_APIENTRY
crStateSelectRasterPos2i(GLint x, GLint y)
{
crStateSelectRasterPos4f((GLfloat) x, (GLfloat) y, 0.0, 1.0);
}
void STATE_APIENTRY
crStateSelectRasterPos2iv(const GLint * v)
{
crStateSelectRasterPos4f((GLfloat) v[0], (GLfloat) v[1], 0.0, 1.0);
}
void STATE_APIENTRY
crStateSelectRasterPos2s(GLshort x, GLshort y)
{
crStateSelectRasterPos4f((GLfloat) x, (GLfloat) y, 0.0, 1.0);
}
void STATE_APIENTRY
crStateSelectRasterPos2sv(const GLshort * v)
{
crStateSelectRasterPos4f((GLfloat) v[0], (GLfloat) v[1], 0.0, 1.0);
}
void STATE_APIENTRY
crStateSelectRasterPos3d(GLdouble x, GLdouble y, GLdouble z)
{
crStateSelectRasterPos4f((GLfloat) x, (GLfloat) y, (GLfloat) z, 1.0);
}
void STATE_APIENTRY
crStateSelectRasterPos3dv(const GLdouble * v)
{
crStateSelectRasterPos4f((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2] , 1.0);
}
void STATE_APIENTRY
crStateSelectRasterPos3f(GLfloat x, GLfloat y, GLfloat z)
{
crStateSelectRasterPos4f(x, y, z, 1.0);
}
void STATE_APIENTRY
crStateSelectRasterPos3fv(const GLfloat * v)
{
crStateSelectRasterPos4f((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2] , 1.0);
}
void STATE_APIENTRY
crStateSelectRasterPos3i(GLint x, GLint y, GLint z)
{
crStateSelectRasterPos4f((GLfloat) x, (GLfloat) y, (GLfloat) z, 1.0);
}
void STATE_APIENTRY
crStateSelectRasterPos3iv(const GLint * v)
{
crStateSelectRasterPos4f((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2] , 1.0);
}
void STATE_APIENTRY
crStateSelectRasterPos3s(GLshort x, GLshort y, GLshort z)
{
crStateSelectRasterPos4f((GLfloat) x, (GLfloat) y, (GLfloat) z, 1.0);
}
void STATE_APIENTRY
crStateSelectRasterPos3sv(const GLshort * v)
{
crStateSelectRasterPos4f((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2] , 1.0);
}
void STATE_APIENTRY
crStateSelectRasterPos4d(GLdouble x, GLdouble y, GLdouble z, GLdouble w)
{
crStateSelectRasterPos4f((GLfloat) x, (GLfloat) y, (GLfloat) z, (GLfloat) w);
}
void STATE_APIENTRY
crStateSelectRasterPos4dv(const GLdouble * v)
{
crStateSelectRasterPos4f((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2] , (GLfloat) v[3]);
}
void STATE_APIENTRY
crStateSelectRasterPos4fv(const GLfloat * v)
{
crStateSelectRasterPos4f(v[0], v[1], v[2], v[3]);
}
void STATE_APIENTRY
crStateSelectRasterPos4i(GLint x, GLint y, GLint z, GLint w)
{
crStateSelectRasterPos4f((GLfloat) x, (GLfloat) y, (GLfloat) z, (GLfloat) w);
}
void STATE_APIENTRY
crStateSelectRasterPos4iv(const GLint * v)
{
crStateSelectRasterPos4f((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2], (GLfloat) v[3]);
}
void STATE_APIENTRY
crStateSelectRasterPos4s(GLshort x, GLshort y, GLshort z, GLshort w)
{
crStateSelectRasterPos4f((GLfloat) x, (GLfloat) y, (GLfloat) z, (GLfloat) w);
}
void STATE_APIENTRY
crStateSelectRasterPos4sv(const GLshort * v)
{
crStateSelectRasterPos4f((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2] , (GLfloat) v[3]);
}
void STATE_APIENTRY
crStateSelectRectf(GLfloat x0, GLfloat y0, GLfloat x1, GLfloat y1)
{
crStateSelectBegin(GL_QUADS);
crStateSelectVertex2f(x0, y0);
crStateSelectVertex2f(x0, y1);
crStateSelectVertex2f(x1, y1);
crStateSelectVertex2f(x1, y0);
crStateSelectEnd();
}
void STATE_APIENTRY
crStateSelectRecti(GLint x0, GLint y0, GLint x1, GLint y1)
{
crStateSelectRectf((GLfloat) x0, (GLfloat) y0, (GLfloat) x1, (GLfloat) y1);
}
void STATE_APIENTRY
crStateSelectRectd(GLdouble x0, GLdouble y0, GLdouble x1, GLdouble y1)
{
crStateSelectRectf((GLfloat) x0, (GLfloat) y0, (GLfloat) x1, (GLfloat) y1);
}
void STATE_APIENTRY
crStateSelectRects(GLshort x0, GLshort y0, GLshort x1, GLshort y1)
{
crStateSelectRectf((GLfloat) x0, (GLfloat) y0, (GLfloat) x1, (GLfloat) y1);
}
void STATE_APIENTRY
crStateSelectRectiv(const GLint *v0, const GLint *v1)
{
crStateSelectRectf((GLfloat) v0[0], (GLfloat) v0[1], (GLfloat) v1[0], (GLfloat) v1[1]);
}
void STATE_APIENTRY
crStateSelectRectfv(const GLfloat *v0, const GLfloat *v1)
{
crStateSelectRectf(v0[0], v0[1], v1[0], v1[1]);
}
void STATE_APIENTRY
crStateSelectRectdv(const GLdouble *v0, const GLdouble *v1)
{
crStateSelectRectf((GLfloat) v0[0], (GLfloat) v0[1], (GLfloat) v1[0], (GLfloat) v1[1]);
}
void STATE_APIENTRY
crStateSelectRectsv(const GLshort *v0, const GLshort *v1)
{
crStateSelectRectf((GLfloat) v0[0], (GLfloat) v0[1], (GLfloat) v1[0], (GLfloat) v1[1]);
}
GLint STATE_APIENTRY
crStateRenderMode(GLenum mode)
{
CRContext *g = GetCurrentContext();
CRFeedbackState *f = &(g->feedback);
CRSelectionState *se = &(g->selection);
GLint result;
if (g->current.inBeginEnd)
{
crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
"RenderMode called in begin/end");
return 0;
}
FLUSH();
switch (g->renderMode)
{
case GL_RENDER:
result = 0;
break;
case GL_SELECT:
if (se->hitFlag)
{
write_hit_record(se);
}
if (se->bufferCount > se->bufferSize)
{
/* overflow */
result = -1;
}
else
{
result = se->hits;
}
se->bufferCount = 0;
se->hits = 0;
se->nameStackDepth = 0;
break;
case GL_FEEDBACK:
if (f->count > f->bufferSize)
{
/* overflow */
result = -1;
}
else
{
result = f->count;
}
f->count = 0;
break;
default:
crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "invalid rendermode");
return 0;
}
switch (mode)
{
case GL_RENDER:
break;
case GL_SELECT:
if (se->bufferSize == 0)
{
/* haven't called glSelectBuffer yet */
crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
"buffersize = 0");
}
break;
case GL_FEEDBACK:
if (f->bufferSize == 0)
{
/* haven't called glFeedbackBuffer yet */
crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
"buffersize = 0");
}
break;
default:
crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "invalid rendermode");
return 0;
}
g->renderMode = mode;
return result;
}
void STATE_APIENTRY
crStateSelectDrawPixels(GLsizei width, GLsizei height, GLenum format,
GLenum type, const GLvoid * pixels)
{
(void) width;
(void) height;
(void) format;
(void) type;
(void) pixels;
select_rasterpos();
}
void STATE_APIENTRY
crStateSelectCopyPixels(GLint x, GLint y, GLsizei width, GLsizei height,
GLenum type)
{
(void) x;
(void) y;
(void) width;
(void) height;
(void) type;
select_rasterpos();
}
void STATE_APIENTRY
crStateSelectBitmap(GLsizei width, GLsizei height, GLfloat xorig,
GLfloat yorig, GLfloat xmove, GLfloat ymove,
const GLubyte * bitmap)
{
CRContext *g = GetCurrentContext();
(void) width;
(void) height;
(void) xorig;
(void) yorig;
(void) bitmap;
select_rasterpos();
if (g->current.rasterValid)
{
g->current.rasterAttrib[VERT_ATTRIB_POS][0] += xmove;
g->current.rasterAttrib[VERT_ATTRIB_POS][1] += ymove;
}
}