/* Copyright (c) 2001, Stanford University * All rights reserved * * See the file LICENSE.txt for information on redistributing this software. */ #include "cr_mem.h" #include "state.h" #include "state_internals.h" /* * Note: regardless of GL_NV_vertex_program, we store all per-vertex * attributes in an array now, instead of specially named attributes * like color, normal, texcoord, etc. */ void crStateCurrentInit( CRContext *ctx ) { CRCurrentState *c = &ctx->current; CRStateBits *sb = GetCurrentBits(); CRCurrentBits *cb = &(sb->current); static const GLfloat default_normal[4] = {0.0f, 0.0f, 1.0f, 1.0f}; static const GLfloat default_color[4] = {1.0f, 1.0f, 1.0f, 1.0f}; static const GLfloat default_secondaryColor[4] = {0.0f, 0.0f, 0.0f, 1.0f}; static const GLfloat default_attrib[4] = {0.0f, 0.0f, 0.0f, 1.0f}; unsigned int i; /* * initialize all vertex attributes to <0,0,0,1> for starters */ for (i = 0; i < CR_MAX_VERTEX_ATTRIBS; i++) { COPY_4V(c->vertexAttrib[i], default_attrib); COPY_4V(c->vertexAttribPre[i], default_attrib); } /* now re-do the exceptions */ COPY_4V(c->vertexAttrib[VERT_ATTRIB_COLOR0], default_color); COPY_4V(c->vertexAttrib[VERT_ATTRIB_COLOR1], default_secondaryColor); COPY_4V(c->vertexAttrib[VERT_ATTRIB_NORMAL], default_normal); c->rasterIndex = 1.0f; c->colorIndex = c->colorIndexPre = 1.0; c->edgeFlag = c->edgeFlagPre = GL_TRUE; /* Set the "pre" values and raster position attributes */ for (i = 0; i < CR_MAX_VERTEX_ATTRIBS; i++) { COPY_4V(c->vertexAttribPre[i], c->vertexAttrib[i]); COPY_4V(c->rasterAttrib[i], c->vertexAttrib[i]); COPY_4V(c->rasterAttribPre[i], c->vertexAttrib[i]); } c->rasterValid = GL_TRUE; c->inBeginEnd = GL_FALSE; c->beginEndNum = 0; /*c->beginEndMax = cfg->beginend_max;*/ c->mode = 0x10; /* Undefined Mode */ c->flushOnEnd = 0; c->current = 0; /* picked up by crStateSetCurrentPointers() */ /* init dirty bits */ RESET(cb->dirty, ctx->bitid); for (i = 0; i < CR_MAX_VERTEX_ATTRIBS; i++) { RESET(cb->vertexAttrib[i], ctx->bitid); } RESET(cb->edgeFlag, ctx->bitid); RESET(cb->colorIndex, ctx->bitid); RESET(cb->rasterPos, ctx->bitid); } void STATE_APIENTRY crStateColor3f( GLfloat r, GLfloat g, GLfloat b ) { crStateColor4f(r, g, b, 1.0F); } void STATE_APIENTRY crStateColor3fv( const GLfloat *color ) { crStateColor4f( color[0], color[1], color[2], 1.0F ); } void STATE_APIENTRY crStateColor4f( GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha ) { CRContext *g = GetCurrentContext(); CRCurrentState *c = &(g->current); CRStateBits *sb = GetCurrentBits(); CRCurrentBits *cb = &(sb->current); FLUSH(); c->vertexAttrib[VERT_ATTRIB_COLOR0][0] = red; c->vertexAttrib[VERT_ATTRIB_COLOR0][1] = green; c->vertexAttrib[VERT_ATTRIB_COLOR0][2] = blue; c->vertexAttrib[VERT_ATTRIB_COLOR0][3] = alpha; DIRTY(cb->dirty, g->neg_bitid); DIRTY(cb->vertexAttrib[VERT_ATTRIB_COLOR0], g->neg_bitid); } void STATE_APIENTRY crStateColor4fv( const GLfloat *color ) { crStateColor4f( color[0], color[1], color[2], color[3] ); } void crStateSetCurrentPointers( CRContext *ctx, CRCurrentStatePointers *current ) { CRCurrentState *c = &(ctx->current); c->current = current; } void crStateResetCurrentPointers( CRCurrentStatePointers *current ) { crMemset(&(current->c.index), 0, sizeof(GLindex_p)); crMemset(&(current->c.vertexAttrib), 0, sizeof(GLvertexattrib_p)); crMemset(&(current->c.fogCoord), 0, sizeof(GLfogcoord_p)); crMemset(&(current->c.edgeFlag), 0, sizeof(GLedgeflag_p)); crMemset(&(current->c.normal), 0, sizeof(GLnormal_p)); crMemset(&(current->c.color), 0, sizeof(GLcolor_p)); crMemset(&(current->c.secondaryColor), 0, sizeof(GLsecondarycolor_p)); crMemset(&(current->c.texCoord), 0, sizeof(GLtexcoord_p)); /* current->attribsUsedMask = 0; */ } void STATE_APIENTRY crStateBegin( GLenum mode ) { CRContext *g = GetCurrentContext(); CRCurrentState *c = &(g->current); if (mode > GL_POLYGON) { crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "Begin called with invalid mode: %d", mode); return; } if (c->inBeginEnd) { crStateError( __LINE__, __FILE__, GL_INVALID_OPERATION, "glBegin called inside Begin/End"); return; } c->attribsUsedMask = 0; c->inBeginEnd = GL_TRUE; c->mode = mode; c->beginEndNum++; } void STATE_APIENTRY crStateEnd( void ) { CRContext *g = GetCurrentContext(); CRCurrentState *c = &(g->current); if (!c->inBeginEnd) { crStateError( __LINE__, __FILE__, GL_INVALID_OPERATION, "glEnd called outside Begin/End" ); return; } c->inBeginEnd = GL_FALSE; } void crStateCurrentSwitch( CRCurrentBits *c, CRbitvalue *bitID, CRContext *fromCtx, CRContext *toCtx ) { const CRCurrentState *from = &(fromCtx->current); const CRCurrentState *to = &(toCtx->current); const GLuint maxTextureUnits = fromCtx->limits.maxTextureUnits; unsigned int i, j; CRbitvalue nbitID[CR_MAX_BITARRAY]; for (j=0;jrasterPos, bitID)) { if (to->rasterValid) { const GLfloat fromX = from->rasterAttrib[VERT_ATTRIB_POS][0]; const GLfloat fromY = from->rasterAttrib[VERT_ATTRIB_POS][1]; const GLfloat fromZ = from->rasterAttrib[VERT_ATTRIB_POS][2]; const GLfloat toX = to->rasterAttrib[VERT_ATTRIB_POS][0]; const GLfloat toY = to->rasterAttrib[VERT_ATTRIB_POS][1]; const GLfloat toZ = to->rasterAttrib[VERT_ATTRIB_POS][2]; if (toX != fromX || toY != fromY || toZ != fromZ) { /* Use glWindowPos (which updates raster color) */ diff_api.WindowPos3fvARB(to->rasterAttrib[VERT_ATTRIB_POS]); FILLDIRTY(c->rasterPos); FILLDIRTY(c->dirty); } } CLEARDIRTY(c->rasterPos, nbitID); } /* Vertex Current State Switch Code */ /* Its important that we don't do a value check here because ** current may not actually have the correct values, I think... ** We also need to restore the current state tracking pointer ** since the packing functions will set it. */ if (CHECKDIRTY(c->colorIndex, bitID)) { if (to->colorIndex != from->colorIndex) { diff_api.Indexf(to->colorIndex); FILLDIRTY(c->colorIndex); FILLDIRTY(c->dirty); } CLEARDIRTY(c->colorIndex, nbitID); } if (CHECKDIRTY(c->edgeFlag, bitID)) { if (to->edgeFlag != from->edgeFlag) { diff_api.EdgeFlag(to->edgeFlag); FILLDIRTY(c->edgeFlag); FILLDIRTY(c->dirty); } CLEARDIRTY(c->edgeFlag, nbitID); } /* If using a vertex program, update the generic vertex attributes, * which may or may not be aliased with conventional attributes. */ #if defined(CR_ARB_vertex_program) || defined(CR_NV_vertex_progra) if (toCtx->program.vpEnabled && (toCtx->extensions.ARB_vertex_program || (toCtx->extensions.NV_vertex_program))) { const unsigned attribsUsedMask = toCtx->current.attribsUsedMask; for (i = 1; i < CR_MAX_VERTEX_ATTRIBS; i++) { /* skip zero */ if ((attribsUsedMask & (1 << i)) && CHECKDIRTY(c->vertexAttrib[i], bitID)) { if (COMPARE_VECTOR (from->vertexAttrib[i], to->vertexAttribPre[i])) { diff_api.VertexAttrib4fvARB(i, &(to->vertexAttrib[i][0])); FILLDIRTY(c->vertexAttrib[i]); FILLDIRTY(c->dirty); } CLEARDIRTY(c->vertexAttrib[i], nbitID); } } } /* Fall-through so that attributes which don't have their bit set in the * attribsUsedMask get handled via the conventional attribute functions. */ #endif { /* use conventional attribute functions */ /* NEED TO FIX THIS!!!!!! */ if (CHECKDIRTY(c->vertexAttrib[VERT_ATTRIB_COLOR0], bitID)) { if (COMPARE_COLOR(from->vertexAttrib[VERT_ATTRIB_COLOR0],to->vertexAttrib[VERT_ATTRIB_COLOR0])) { diff_api.Color4fv ((GLfloat *) &(to->vertexAttrib[VERT_ATTRIB_COLOR0])); FILLDIRTY(c->vertexAttrib[VERT_ATTRIB_COLOR0]); FILLDIRTY(c->dirty); } CLEARDIRTY(c->vertexAttrib[VERT_ATTRIB_COLOR0], nbitID); } /* NEED TO FIX THIS, ALSO?!!!!! */ #ifdef CR_EXT_secondary_color if (CHECKDIRTY(c->vertexAttrib[VERT_ATTRIB_COLOR1], bitID)) { if (COMPARE_COLOR(from->vertexAttrib[VERT_ATTRIB_COLOR1],to->vertexAttrib[VERT_ATTRIB_COLOR1])) { diff_api.SecondaryColor3fvEXT ((GLfloat *) &(to->vertexAttrib[VERT_ATTRIB_COLOR1])); FILLDIRTY(c->vertexAttrib[VERT_ATTRIB_COLOR1]); FILLDIRTY(c->dirty); } CLEARDIRTY(c->vertexAttrib[VERT_ATTRIB_COLOR1], nbitID); } #endif /* NEED TO FIX THIS, ALSO?!!!!! */ #ifdef CR_EXT_fog_coord if (CHECKDIRTY(c->vertexAttrib[VERT_ATTRIB_FOG], bitID)) { if (from->vertexAttrib[VERT_ATTRIB_FOG][0] != to->vertexAttrib[VERT_ATTRIB_FOG][0] ) { diff_api.FogCoordfvEXT ((GLfloat *) &(to->vertexAttrib[VERT_ATTRIB_FOG][0] )); FILLDIRTY(c->vertexAttrib[VERT_ATTRIB_FOG]); FILLDIRTY(c->dirty); } CLEARDIRTY(c->vertexAttrib[VERT_ATTRIB_FOG], nbitID); } #endif if (CHECKDIRTY(c->vertexAttrib[VERT_ATTRIB_NORMAL], bitID)) { if (COMPARE_VECTOR (from->vertexAttrib[VERT_ATTRIB_NORMAL], to->vertexAttrib[VERT_ATTRIB_NORMAL])) { diff_api.Normal3fv ((GLfloat *) &(to->vertexAttrib[VERT_ATTRIB_NORMAL][0])); FILLDIRTY(c->vertexAttrib[VERT_ATTRIB_NORMAL]); FILLDIRTY(c->dirty); } CLEARDIRTY(c->vertexAttrib[VERT_ATTRIB_NORMAL], nbitID); } for (i = 0; i < maxTextureUnits; i++) { if (CHECKDIRTY(c->vertexAttrib[VERT_ATTRIB_TEX0 + i], bitID)) { if (COMPARE_TEXCOORD (from->vertexAttrib[VERT_ATTRIB_TEX0 + i], to->vertexAttribPre[VERT_ATTRIB_TEX0 + i])) { diff_api.MultiTexCoord4fvARB (i+GL_TEXTURE0_ARB, (GLfloat *) &(to->vertexAttrib[VERT_ATTRIB_TEX0+ i][0])); FILLDIRTY(c->vertexAttrib[VERT_ATTRIB_TEX0 + i]); FILLDIRTY(c->dirty); } CLEARDIRTY(c->vertexAttrib[VERT_ATTRIB_TEX0 + i], nbitID); } } } CLEARDIRTY(c->dirty, nbitID); } void crStateCurrentDiff( CRCurrentBits *c, CRbitvalue *bitID, CRContext *fromCtx, CRContext *toCtx ) { CRCurrentState *from = &(fromCtx->current); const CRCurrentState *to = &(toCtx->current); unsigned int i, j; CRbitvalue nbitID[CR_MAX_BITARRAY]; for (j=0;jrasterPos, bitID)) { from->rasterValid = to->rasterValid; if (to->rasterValid) { const GLfloat fromX = from->rasterAttrib[VERT_ATTRIB_POS][0]; const GLfloat fromY = from->rasterAttrib[VERT_ATTRIB_POS][1]; const GLfloat fromZ = from->rasterAttrib[VERT_ATTRIB_POS][2]; const GLfloat toX = to->rasterAttrib[VERT_ATTRIB_POS][0]; const GLfloat toY = to->rasterAttrib[VERT_ATTRIB_POS][1]; const GLfloat toZ = to->rasterAttrib[VERT_ATTRIB_POS][2]; if (toX != fromX || toY != fromY || toZ != fromZ) { /* Use glWindowPos (which updates raster color) */ diff_api.WindowPos3fvARB(to->rasterAttrib[VERT_ATTRIB_POS]); from->rasterAttrib[VERT_ATTRIB_POS][0] = toX; from->rasterAttrib[VERT_ATTRIB_POS][1] = toY; from->rasterAttrib[VERT_ATTRIB_POS][2] = toZ; } } CLEARDIRTY(c->rasterPos, nbitID); } /* Vertex Current State Sync Code */ /* Some things to note here: ** 1) Compare is done against the pre value since the ** current value includes the geometry info. ** 2) Update is done with the current value since ** the server will be getting the geometry block ** 3) Copy is done outside of the compare to ensure ** that it happens. */ /* edge flag */ if (CHECKDIRTY(c->edgeFlag, bitID)) { if (from->edgeFlag != to->edgeFlagPre) { diff_api.EdgeFlag (to->edgeFlagPre); } from->edgeFlag = to->edgeFlag; CLEARDIRTY(c->edgeFlag, nbitID); } /* color index */ if (CHECKDIRTY(c->colorIndex, bitID)) { if (from->colorIndex != to->colorIndexPre) { diff_api.Indexf (to->colorIndex); } from->colorIndex = to->colorIndex; CLEARDIRTY(c->colorIndex, nbitID); } /* If using a vertex program, update the generic vertex attributes, * which may or may not be aliased with conventional attributes. */ #if defined(CR_ARB_vertex_program) || defined(CR_NV_vertex_progra) if (toCtx->program.vpEnabled && (toCtx->extensions.ARB_vertex_program || (toCtx->extensions.NV_vertex_program))) { const unsigned attribsUsedMask = toCtx->current.attribsUsedMask; int i; for (i = 1; i < CR_MAX_VERTEX_ATTRIBS; i++) { /* skip zero */ if ((attribsUsedMask & (1 << i)) && CHECKDIRTY(c->vertexAttrib[i], bitID)) { if (COMPARE_VECTOR (from->vertexAttrib[i], to->vertexAttribPre[i])) { diff_api.VertexAttrib4fvARB(i, &(to->vertexAttribPre[i][0])); } COPY_4V(from->vertexAttrib[i] , to->vertexAttrib[i]); CLEARDIRTY(c->vertexAttrib[i], nbitID); } } } /* Fall-through so that attributes which don't have their bit set in the * attribsUsedMask get handled via the conventional attribute functions. */ #endif { /* use conventional attribute functions */ if (CHECKDIRTY(c->vertexAttrib[VERT_ATTRIB_COLOR0], bitID)) { if (COMPARE_COLOR(from->vertexAttrib[VERT_ATTRIB_COLOR0],to->vertexAttribPre[VERT_ATTRIB_COLOR0])) { diff_api.Color4fv ((GLfloat *) &(to->vertexAttribPre[VERT_ATTRIB_COLOR0])); } COPY_4V(from->vertexAttrib[VERT_ATTRIB_COLOR0] , to->vertexAttrib[VERT_ATTRIB_COLOR0]); CLEARDIRTY(c->vertexAttrib[VERT_ATTRIB_COLOR0], nbitID); } #ifdef CR_EXT_secondary_color if (CHECKDIRTY(c->vertexAttrib[VERT_ATTRIB_COLOR1], bitID)) { if (COMPARE_COLOR(from->vertexAttrib[VERT_ATTRIB_COLOR1],to->vertexAttribPre[VERT_ATTRIB_COLOR1])) { diff_api.SecondaryColor3fvEXT ((GLfloat *) &(to->vertexAttribPre[VERT_ATTRIB_COLOR1])); } COPY_4V(from->vertexAttrib[VERT_ATTRIB_COLOR1] , to->vertexAttrib[VERT_ATTRIB_COLOR1]); CLEARDIRTY(c->vertexAttrib[VERT_ATTRIB_COLOR1], nbitID); } #endif #ifdef CR_EXT_fog_coord if (CHECKDIRTY(c->vertexAttrib[VERT_ATTRIB_FOG], bitID)) { if (from->vertexAttrib[VERT_ATTRIB_FOG] != to->vertexAttribPre[VERT_ATTRIB_FOG]) { diff_api.FogCoordfvEXT ((GLfloat *) &(to->vertexAttribPre[VERT_ATTRIB_FOG])); } COPY_4V(from->vertexAttrib[VERT_ATTRIB_FOG] , to->vertexAttrib[VERT_ATTRIB_FOG]); CLEARDIRTY(c->vertexAttrib[VERT_ATTRIB_FOG], nbitID); } #endif if (CHECKDIRTY(c->vertexAttrib[VERT_ATTRIB_NORMAL], bitID)) { if (COMPARE_VECTOR (from->vertexAttrib[VERT_ATTRIB_NORMAL], to->vertexAttribPre[VERT_ATTRIB_NORMAL])) { diff_api.Normal3fv ((GLfloat *) &(to->vertexAttribPre[VERT_ATTRIB_NORMAL])); } COPY_4V(from->vertexAttrib[VERT_ATTRIB_NORMAL] , to->vertexAttrib[VERT_ATTRIB_NORMAL]); CLEARDIRTY(c->vertexAttrib[VERT_ATTRIB_NORMAL], nbitID); } for ( i = 0 ; i < fromCtx->limits.maxTextureUnits ; i++) { if (CHECKDIRTY(c->vertexAttrib[VERT_ATTRIB_TEX0 + i], bitID)) { if (COMPARE_TEXCOORD (from->vertexAttrib[VERT_ATTRIB_TEX0 + i], to->vertexAttribPre[VERT_ATTRIB_TEX0 + i])) { diff_api.MultiTexCoord4fvARB (GL_TEXTURE0_ARB + i, (GLfloat *) &(to->vertexAttribPre[VERT_ATTRIB_TEX0 + i])); } COPY_4V(from->vertexAttrib[VERT_ATTRIB_TEX0 + i] , to->vertexAttrib[VERT_ATTRIB_TEX0 + i]); CLEARDIRTY(c->vertexAttrib[VERT_ATTRIB_TEX0 + i], nbitID); } } } CLEARDIRTY(c->dirty, nbitID); }