diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-06 03:01:46 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-06 03:01:46 +0000 |
commit | f8fe689a81f906d1b91bb3220acde2a4ecb14c5b (patch) | |
tree | 26484e9d7e2c67806c2d1760196ff01aaa858e8c /src/VBox/GuestHost/OpenGL/state_tracker/state_feedback.c | |
parent | Initial commit. (diff) | |
download | virtualbox-f8fe689a81f906d1b91bb3220acde2a4ecb14c5b.tar.xz virtualbox-f8fe689a81f906d1b91bb3220acde2a4ecb14c5b.zip |
Adding upstream version 6.0.4-dfsg.upstream/6.0.4-dfsgupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/VBox/GuestHost/OpenGL/state_tracker/state_feedback.c')
-rw-r--r-- | src/VBox/GuestHost/OpenGL/state_tracker/state_feedback.c | 2423 |
1 files changed, 2423 insertions, 0 deletions
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_feedback.c b/src/VBox/GuestHost/OpenGL/state_tracker/state_feedback.c new file mode 100644 index 00000000..a8591976 --- /dev/null +++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_feedback.c @@ -0,0 +1,2423 @@ +/* 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 appropriately. + */ +#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; + } +} + |