/* Copyright (c) 2001, Stanford University
* All rights reserved
*
* See the file LICENSE.txt for information on redistributing this software.
*/
#include <stdio.h>
#include "state.h"
#include "state/cr_statetypes.h"
#include "state_internals.h"
#include "cr_error.h"
#include "cr_mem.h"
/**
* \mainpage state_tracker
*
* \section StateTrackerIntroduction Introduction
*
* Chromium consists of all the top-level files in the cr
* directory. The state_tracker module basically takes care of API dispatch,
* and OpenGL state management.
*
*
*/
void crStateAttribInit (CRAttribState *a)
{
int i;
a->attribStackDepth = 0;
a->accumBufferStackDepth = 0;
a->colorBufferStackDepth = 0;
a->currentStackDepth = 0;
a->depthBufferStackDepth = 0;
a->enableStackDepth = 0;
for ( i = 0 ; i < CR_MAX_ATTRIB_STACK_DEPTH ; i++)
{
a->enableStack[i].clip = NULL;
a->enableStack[i].light = NULL;
a->lightingStack[i].light = NULL;
a->transformStack[i].clip = NULL;
a->transformStack[i].clipPlane = NULL;
}
a->evalStackDepth = 0;
a->fogStackDepth = 0;
a->lightingStackDepth = 0;
a->lineStackDepth = 0;
a->listStackDepth = 0;
a->pixelModeStackDepth = 0;
a->pointStackDepth = 0;
a->polygonStackDepth = 0;
a->polygonStippleStackDepth = 0;
a->scissorStackDepth = 0;
a->stencilBufferStackDepth = 0;
a->textureStackDepth = 0;
a->transformStackDepth = 0;
a->viewportStackDepth = 0;
}
/*@todo check if NV rect needed too*/
static void
copy_texunit(CRTextureUnit *dest, const CRTextureUnit *src)
{
dest->enabled1D = src->enabled1D;
dest->enabled2D = src->enabled2D;
dest->enabled3D = src->enabled3D;
dest->enabledCubeMap = src->enabledCubeMap;
dest->envMode = src->envMode;
dest->envColor = src->envColor;
dest->textureGen = src->textureGen;
dest->objSCoeff = src->objSCoeff;
dest->objTCoeff = src->objTCoeff;
dest->objRCoeff = src->objRCoeff;
dest->objQCoeff = src->objQCoeff;
dest->eyeSCoeff = src->eyeSCoeff;
dest->eyeTCoeff = src->eyeTCoeff;
dest->eyeRCoeff = src->eyeRCoeff;
dest->eyeQCoeff = src->eyeQCoeff;
dest->gen = src->gen;
dest->currentTexture1D = src->currentTexture1D;
dest->currentTexture2D = src->currentTexture2D;
dest->currentTexture3D = src->currentTexture3D;
dest->currentTextureCubeMap = src->currentTextureCubeMap;
}
static void
copy_texobj(CRTextureObj *dest, CRTextureObj *src, GLboolean copyName)
{
if (copyName)
{
dest->id = src->id;
dest->hwid = crStateGetTextureObjHWID(src);
}
dest->borderColor = src->borderColor;
dest->wrapS = src->wrapS;
dest->wrapT = src->wrapT;
dest->minFilter = src->minFilter;
dest->magFilter = src->magFilter;
#ifdef CR_OPENGL_VERSION_1_2
dest->priority = src->priority;
dest->wrapR = src->wrapR;
dest->minLod = src->minLod;
dest->maxLod = src->maxLod;
dest->baseLevel = src->baseLevel;
dest->maxLevel = src->maxLevel;
#endif
#ifdef CR_EXT_texture_filter_anisotropic
dest->maxAnisotropy = src->maxAnisotropy;
#endif
}
void STATE_APIENTRY crStatePushAttrib(GLbitfield mask)
{
CRContext *g = GetCurrentContext();
CRAttribState *a = &(g->attrib);
CRStateBits *sb = GetCurrentBits();
CRAttribBits *ab = &(sb->attrib);
unsigned int i;
if (g->current.inBeginEnd)
{
crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glPushAttrib called in Begin/End");
return;
}
if (a->attribStackDepth == CR_MAX_ATTRIB_STACK_DEPTH - 1)
{
crStateError(__LINE__, __FILE__, GL_STACK_OVERFLOW, "glPushAttrib called with a full stack!" );
return;
}
FLUSH();
a->pushMaskStack[a->attribStackDepth++] = mask;
if (mask & GL_ACCUM_BUFFER_BIT)
{
a->accumBufferStack[a->accumBufferStackDepth].accumClearValue = g->buffer.accumClearValue;
a->accumBufferStackDepth++;
}
if (mask & GL_COLOR_BUFFER_BIT)
{
a->colorBufferStack[a->colorBufferStackDepth].alphaTest = g->buffer.alphaTest;
a->colorBufferStack[a->colorBufferStackDepth].alphaTestFunc = g->buffer.alphaTestFunc;
a->colorBufferStack[a->colorBufferStackDepth].alphaTestRef = g->buffer.alphaTestRef;
a->colorBufferStack[a->colorBufferStackDepth].blend = g->buffer.blend;
a->colorBufferStack[a->colorBufferStackDepth].blendSrcRGB = g->buffer.blendSrcRGB;
a->colorBufferStack[a->colorBufferStackDepth].blendDstRGB = g->buffer.blendDstRGB;
#if defined(CR_EXT_blend_func_separate)
a->colorBufferStack[a->colorBufferStackDepth].blendSrcA = g->buffer.blendSrcA;
a->colorBufferStack[a->colorBufferStackDepth].blendDstA = g->buffer.blendDstA;
#endif
#ifdef CR_EXT_blend_color
a->colorBufferStack[a->colorBufferStackDepth].blendColor = g->buffer.blendColor;
#endif
#if defined(CR_EXT_blend_minmax) || defined(CR_EXT_blend_subtract) || defined(CR_EXT_blend_logic_op)
a->colorBufferStack[a->colorBufferStackDepth].blendEquation = g->buffer.blendEquation;
#endif
a->colorBufferStack[a->colorBufferStackDepth].dither = g->buffer.dither;
a->colorBufferStack[a->colorBufferStackDepth].drawBuffer = g->buffer.drawBuffer;
a->colorBufferStack[a->colorBufferStackDepth].logicOp = g->buffer.logicOp;
a->colorBufferStack[a->colorBufferStackDepth].indexLogicOp = g->buffer.indexLogicOp;
a->colorBufferStack[a->colorBufferStackDepth].logicOpMode = g->buffer.logicOpMode;
a->colorBufferStack[a->colorBufferStackDepth].colorClearValue = g->buffer.colorClearValue;
a->colorBufferStack[a->colorBufferStackDepth].indexClearValue = g->buffer.indexClearValue;
a->colorBufferStack[a->colorBufferStackDepth].colorWriteMask = g->buffer.colorWriteMask;
a->colorBufferStack[a->colorBufferStackDepth].indexWriteMask = g->buffer.indexWriteMask;
a->colorBufferStackDepth++;
}
if (mask & GL_CURRENT_BIT)
{
for (i = 0 ; i < CR_MAX_VERTEX_ATTRIBS ; i++)
{
COPY_4V(a->currentStack[a->currentStackDepth].attrib[i] , g->current.vertexAttrib[i]);
COPY_4V(a->currentStack[a->currentStackDepth].rasterAttrib[i] , g->current.rasterAttrib[i]);
}
a->currentStack[a->currentStackDepth].rasterValid = g->current.rasterValid;
a->currentStack[a->currentStackDepth].edgeFlag = g->current.edgeFlag;
a->currentStack[a->currentStackDepth].colorIndex = g->current.colorIndex;
a->currentStackDepth++;
}
if (mask & GL_DEPTH_BUFFER_BIT)
{
a->depthBufferStack[a->depthBufferStackDepth].depthTest = g->buffer.depthTest;
a->depthBufferStack[a->depthBufferStackDepth].depthFunc = g->buffer.depthFunc;
a->depthBufferStack[a->depthBufferStackDepth].depthClearValue = g->buffer.depthClearValue;
a->depthBufferStack[a->depthBufferStackDepth].depthMask = g->buffer.depthMask;
a->depthBufferStackDepth++;
}
if (mask & GL_ENABLE_BIT)
{
if (a->enableStack[a->enableStackDepth].clip == NULL)
{
a->enableStack[a->enableStackDepth].clip = (GLboolean *) crCalloc( g->limits.maxClipPlanes * sizeof( GLboolean ));
}
if (a->enableStack[a->enableStackDepth].light == NULL)
{
a->enableStack[a->enableStackDepth].light = (GLboolean *) crCalloc( g->limits.maxLights * sizeof( GLboolean ));
}
a->enableStack[a->enableStackDepth].alphaTest = g->buffer.alphaTest;
a->enableStack[a->enableStackDepth].autoNormal = g->eval.autoNormal;
a->enableStack[a->enableStackDepth].blend = g->buffer.blend;
for (i = 0 ; i < g->limits.maxClipPlanes ; i++)
{
a->enableStack[a->enableStackDepth].clip[i] = g->transform.clip[i];
}
a->enableStack[a->enableStackDepth].colorMaterial = g->lighting.colorMaterial;
a->enableStack[a->enableStackDepth].cullFace = g->polygon.cullFace;
a->enableStack[a->enableStackDepth].depthTest = g->buffer.depthTest;
a->enableStack[a->enableStackDepth].dither = g->buffer.dither;
a->enableStack[a->enableStackDepth].fog = g->fog.enable;
for (i = 0 ; i < g->limits.maxLights ; i++)
{
a->enableStack[a->enableStackDepth].light[i] = g->lighting.light[i].enable;
}
a->enableStack[a->enableStackDepth].lighting = g->lighting.lighting;
a->enableStack[a->enableStackDepth].lineSmooth = g->line.lineSmooth;
a->enableStack[a->enableStackDepth].lineStipple = g->line.lineStipple;
a->enableStack[a->enableStackDepth].logicOp = g->buffer.logicOp;
a->enableStack[a->enableStackDepth].indexLogicOp = g->buffer.indexLogicOp;
for (i = 0 ; i < GLEVAL_TOT ; i++)
{
a->enableStack[a->enableStackDepth].map1[i] = g->eval.enable1D[i];
a->enableStack[a->enableStackDepth].map2[i] = g->eval.enable2D[i];
}
a->enableStack[a->enableStackDepth].normalize = g->transform.normalize;
a->enableStack[a->enableStackDepth].pointSmooth = g->point.pointSmooth;
#if CR_ARB_point_sprite
a->enableStack[a->enableStackDepth].pointSprite = g->point.pointSprite;
for (i = 0; i < CR_MAX_TEXTURE_UNITS; i++)
a->enableStack[a->enableStackDepth].coordReplacement[i] = g->point.coordReplacement[i];
#endif
a->enableStack[a->enableStackDepth].polygonOffsetLine = g->polygon.polygonOffsetLine;
a->enableStack[a->enableStackDepth].polygonOffsetFill = g->polygon.polygonOffsetFill;
a->enableStack[a->enableStackDepth].polygonOffsetPoint = g->polygon.polygonOffsetPoint;
a->enableStack[a->enableStackDepth].polygonSmooth = g->polygon.polygonSmooth;
a->enableStack[a->enableStackDepth].polygonStipple = g->polygon.polygonStipple;
#ifdef CR_OPENGL_VERSION_1_2
a->enableStack[a->enableStackDepth].rescaleNormals = g->transform.rescaleNormals;
#endif
a->enableStack[a->enableStackDepth].scissorTest = g->viewport.scissorTest;
a->enableStack[a->enableStackDepth].stencilTest = g->stencil.stencilTest;
for (i = 0 ; i < g->limits.maxTextureUnits; i++)
{
a->enableStack[a->enableStackDepth].texture1D[i] = g->texture.unit[i].enabled1D;
a->enableStack[a->enableStackDepth].texture2D[i] = g->texture.unit[i].enabled2D;
#ifdef CR_OPENGL_VERSION_1_2
a->enableStack[a->enableStackDepth].texture3D[i] = g->texture.unit[i].enabled3D;
#endif
#ifdef CR_ARB_texture_cube_map
a->enableStack[a->enableStackDepth].textureCubeMap[i] = g->texture.unit[i].enabledCubeMap;
#endif
#ifdef CR_NV_texture_rectangle
a->enableStack[a->enableStackDepth].textureRect[i] = g->texture.unit[i].enabledRect;
#endif
a->enableStack[a->enableStackDepth].textureGenS[i] = g->texture.unit[i].textureGen.s;
a->enableStack[a->enableStackDepth].textureGenT[i] = g->texture.unit[i].textureGen.t;
a->enableStack[a->enableStackDepth].textureGenR[i] = g->texture.unit[i].textureGen.r;
a->enableStack[a->enableStackDepth].textureGenQ[i] = g->texture.unit[i].textureGen.q;
}
a->enableStackDepth++;
}
if (mask & GL_EVAL_BIT)
{
for (i = 0 ; i < GLEVAL_TOT ; i++)
{
int size1 = g->eval.eval1D[i].order * gleval_sizes[i] *
sizeof (GLfloat);
int size2 = g->eval.eval2D[i].uorder * g->eval.eval2D[i].vorder *
gleval_sizes[i] * sizeof (GLfloat);
a->evalStack[a->evalStackDepth].enable1D[i] = g->eval.enable1D[i];
a->evalStack[a->evalStackDepth].enable2D[i] = g->eval.enable2D[i];
a->evalStack[a->evalStackDepth].eval1D[i].u1 = g->eval.eval1D[i].u1;
a->evalStack[a->evalStackDepth].eval1D[i].u2 = g->eval.eval1D[i].u2;
a->evalStack[a->evalStackDepth].eval1D[i].order = g->eval.eval1D[i].order;
a->evalStack[a->evalStackDepth].eval1D[i].coeff = (GLfloat*)crCalloc(size1);
crMemcpy(a->evalStack[a->evalStackDepth].eval1D[i].coeff, g->eval.eval1D[i].coeff, size1);
a->evalStack[a->evalStackDepth].eval2D[i].u1 = g->eval.eval2D[i].u1;
a->evalStack[a->evalStackDepth].eval2D[i].u2 = g->eval.eval2D[i].u2;
a->evalStack[a->evalStackDepth].eval2D[i].v1 = g->eval.eval2D[i].v1;
a->evalStack[a->evalStackDepth].eval2D[i].v2 = g->eval.eval2D[i].v2;
a->evalStack[a->evalStackDepth].eval2D[i].uorder = g->eval.eval2D[i].uorder;
a->evalStack[a->evalStackDepth].eval2D[i].vorder = g->eval.eval2D[i].vorder;
a->evalStack[a->evalStackDepth].eval2D[i].coeff = (GLfloat*)crCalloc(size2);
crMemcpy(a->evalStack[a->evalStackDepth].eval2D[i].coeff, g->eval.eval2D[i].coeff, size2);
}
a->evalStack[a->evalStackDepth].autoNormal = g->eval.autoNormal;
a->evalStack[a->evalStackDepth].un1D = g->eval.un1D;
a->evalStack[a->evalStackDepth].u11D = g->eval.u11D;
a->evalStack[a->evalStackDepth].u21D = g->eval.u21D;
a->evalStack[a->evalStackDepth].un2D = g->eval.un2D;
a->evalStack[a->evalStackDepth].u12D = g->eval.u12D;
a->evalStack[a->evalStackDepth].u22D = g->eval.u22D;
a->evalStack[a->evalStackDepth].vn2D = g->eval.vn2D;
a->evalStack[a->evalStackDepth].v12D = g->eval.v12D;
a->evalStack[a->evalStackDepth].v22D = g->eval.v22D;
a->evalStackDepth++;
}
if (mask & GL_FOG_BIT)
{
a->fogStack[a->fogStackDepth].enable = g->fog.enable;
a->fogStack[a->fogStackDepth].color = g->fog.color;
a->fogStack[a->fogStackDepth].density = g->fog.density;
a->fogStack[a->fogStackDepth].start = g->fog.start;
a->fogStack[a->fogStackDepth].end = g->fog.end;
a->fogStack[a->fogStackDepth].index = g->fog.index;
a->fogStack[a->fogStackDepth].mode = g->fog.mode;
a->fogStackDepth++;
}
if (mask & GL_HINT_BIT)
{
a->hintStack[a->hintStackDepth].perspectiveCorrection = g->hint.perspectiveCorrection;
a->hintStack[a->hintStackDepth].pointSmooth = g->hint.pointSmooth;
a->hintStack[a->hintStackDepth].lineSmooth = g->hint.lineSmooth;
a->hintStack[a->hintStackDepth].polygonSmooth = g->hint.polygonSmooth;
a->hintStack[a->hintStackDepth].fog = g->hint.fog;
#ifdef CR_EXT_clip_volume_hint
a->hintStack[a->hintStackDepth].clipVolumeClipping = g->hint.clipVolumeClipping;
#endif
#ifdef CR_ARB_texture_compression
a->hintStack[a->hintStackDepth].textureCompression = g->hint.textureCompression;
#endif
#ifdef CR_SGIS_generate_mipmap
a->hintStack[a->hintStackDepth].generateMipmap = g->hint.generateMipmap;
#endif
a->hintStackDepth++;
}
if (mask & GL_LIGHTING_BIT)
{
if (a->lightingStack[a->lightingStackDepth].light == NULL)
{
a->lightingStack[a->lightingStackDepth].light = (CRLight *) crCalloc( g->limits.maxLights * sizeof( CRLight ));
}
a->lightingStack[a->lightingStackDepth].lightModelAmbient = g->lighting.lightModelAmbient;
a->lightingStack[a->lightingStackDepth].lightModelLocalViewer = g->lighting.lightModelLocalViewer;
a->lightingStack[a->lightingStackDepth].lightModelTwoSide = g->lighting.lightModelTwoSide;
#if defined(CR_EXT_separate_specular_color) || defined(CR_OPENGL_VERSION_1_2)
a->lightingStack[a->lightingStackDepth].lightModelColorControlEXT = g->lighting.lightModelColorControlEXT;
#endif
a->lightingStack[a->lightingStackDepth].lighting = g->lighting.lighting;
a->lightingStack[a->lightingStackDepth].colorMaterial = g->lighting.colorMaterial;
a->lightingStack[a->lightingStackDepth].colorMaterialMode = g->lighting.colorMaterialMode;
a->lightingStack[a->lightingStackDepth].colorMaterialFace = g->lighting.colorMaterialFace;
for (i = 0 ; i < g->limits.maxLights; i++)
{
a->lightingStack[a->lightingStackDepth].light[i].enable = g->lighting.light[i].enable;
a->lightingStack[a->lightingStackDepth].light[i].ambient = g->lighting.light[i].ambient;
a->lightingStack[a->lightingStackDepth].light[i].diffuse = g->lighting.light[i].diffuse;
a->lightingStack[a->lightingStackDepth].light[i].specular = g->lighting.light[i].specular;
a->lightingStack[a->lightingStackDepth].light[i].spotDirection = g->lighting.light[i].spotDirection;
a->lightingStack[a->lightingStackDepth].light[i].position = g->lighting.light[i].position;
a->lightingStack[a->lightingStackDepth].light[i].spotExponent = g->lighting.light[i].spotExponent;
a->lightingStack[a->lightingStackDepth].light[i].spotCutoff = g->lighting.light[i].spotCutoff;
a->lightingStack[a->lightingStackDepth].light[i].constantAttenuation = g->lighting.light[i].constantAttenuation;
a->lightingStack[a->lightingStackDepth].light[i].linearAttenuation = g->lighting.light[i].linearAttenuation;
a->lightingStack[a->lightingStackDepth].light[i].quadraticAttenuation = g->lighting.light[i].quadraticAttenuation;
}
for (i = 0 ; i < 2 ; i++)
{
a->lightingStack[a->lightingStackDepth].ambient[i] = g->lighting.ambient[i];
a->lightingStack[a->lightingStackDepth].diffuse[i] = g->lighting.diffuse[i];
a->lightingStack[a->lightingStackDepth].specular[i] = g->lighting.specular[i];
a->lightingStack[a->lightingStackDepth].emission[i] = g->lighting.emission[i];
a->lightingStack[a->lightingStackDepth].shininess[i] = g->lighting.shininess[i];
a->lightingStack[a->lightingStackDepth].indexes[i][0] = g->lighting.indexes[i][0];
a->lightingStack[a->lightingStackDepth].indexes[i][1] = g->lighting.indexes[i][1];
a->lightingStack[a->lightingStackDepth].indexes[i][2] = g->lighting.indexes[i][2];
}
a->lightingStack[a->lightingStackDepth].shadeModel = g->lighting.shadeModel;
a->lightingStackDepth++;
}
if (mask & GL_LINE_BIT)
{
a->lineStack[a->lineStackDepth].lineSmooth = g->line.lineSmooth;
a->lineStack[a->lineStackDepth].lineStipple = g->line.lineStipple;
a->lineStack[a->lineStackDepth].pattern = g->line.pattern;
a->lineStack[a->lineStackDepth].repeat = g->line.repeat;
a->lineStack[a->lineStackDepth].width = g->line.width;
a->lineStackDepth++;
}
if (mask & GL_LIST_BIT)
{
a->listStack[a->listStackDepth].base = g->lists.base;
a->listStackDepth++;
}
if (mask & GL_PIXEL_MODE_BIT)
{
a->pixelModeStack[a->pixelModeStackDepth].bias = g->pixel.bias;
a->pixelModeStack[a->pixelModeStackDepth].scale = g->pixel.scale;
a->pixelModeStack[a->pixelModeStackDepth].indexOffset = g->pixel.indexOffset;
a->pixelModeStack[a->pixelModeStackDepth].indexShift = g->pixel.indexShift;
a->pixelModeStack[a->pixelModeStackDepth].mapColor = g->pixel.mapColor;
a->pixelModeStack[a->pixelModeStackDepth].mapStencil = g->pixel.mapStencil;
a->pixelModeStack[a->pixelModeStackDepth].xZoom = g->pixel.xZoom;
a->pixelModeStack[a->pixelModeStackDepth].yZoom = g->pixel.yZoom;
a->pixelModeStack[a->pixelModeStackDepth].readBuffer = g->buffer.readBuffer;
a->pixelModeStackDepth++;
}
if (mask & GL_POINT_BIT)
{
a->pointStack[a->pointStackDepth].pointSmooth = g->point.pointSmooth;
#if CR_ARB_point_sprite
a->pointStack[a->pointStackDepth].pointSprite = g->point.pointSprite;
for (i = 0; i < CR_MAX_TEXTURE_UNITS; i++)
a->pointStack[a->enableStackDepth].coordReplacement[i] = g->point.coordReplacement[i];
#endif
a->pointStack[a->pointStackDepth].pointSize = g->point.pointSize;
a->pointStackDepth++;
}
if (mask & GL_POLYGON_BIT)
{
a->polygonStack[a->polygonStackDepth].cullFace = g->polygon.cullFace;
a->polygonStack[a->polygonStackDepth].cullFaceMode = g->polygon.cullFaceMode;
a->polygonStack[a->polygonStackDepth].frontFace = g->polygon.frontFace;
a->polygonStack[a->polygonStackDepth].frontMode = g->polygon.frontMode;
a->polygonStack[a->polygonStackDepth].backMode = g->polygon.backMode;
a->polygonStack[a->polygonStackDepth].polygonSmooth = g->polygon.polygonSmooth;
a->polygonStack[a->polygonStackDepth].polygonStipple = g->polygon.polygonStipple;
a->polygonStack[a->polygonStackDepth].polygonOffsetFill = g->polygon.polygonOffsetFill;
a->polygonStack[a->polygonStackDepth].polygonOffsetLine = g->polygon.polygonOffsetLine;
a->polygonStack[a->polygonStackDepth].polygonOffsetPoint = g->polygon.polygonOffsetPoint;
a->polygonStack[a->polygonStackDepth].offsetFactor = g->polygon.offsetFactor;
a->polygonStack[a->polygonStackDepth].offsetUnits = g->polygon.offsetUnits;
a->polygonStackDepth++;
}
if (mask & GL_POLYGON_STIPPLE_BIT)
{
crMemcpy( a->polygonStippleStack[a->polygonStippleStackDepth].pattern, g->polygon.stipple, 32*sizeof(GLint) );
a->polygonStippleStackDepth++;
}
if (mask & GL_SCISSOR_BIT)
{
a->scissorStack[a->scissorStackDepth].scissorTest = g->viewport.scissorTest;
a->scissorStack[a->scissorStackDepth].scissorX = g->viewport.scissorX;
a->scissorStack[a->scissorStackDepth].scissorY = g->viewport.scissorY;
a->scissorStack[a->scissorStackDepth].scissorW = g->viewport.scissorW;
a->scissorStack[a->scissorStackDepth].scissorH = g->viewport.scissorH;
a->scissorStackDepth++;
}
if (mask & GL_STENCIL_BUFFER_BIT)
{
a->stencilBufferStack[a->stencilBufferStackDepth].stencilTest = g->stencil.stencilTest;
a->stencilBufferStack[a->stencilBufferStackDepth].clearValue = g->stencil.clearValue;
a->stencilBufferStack[a->stencilBufferStackDepth].writeMask = g->stencil.writeMask;
for (i = 0; i < CRSTATE_STENCIL_BUFFER_COUNT; ++i)
{
a->stencilBufferStack[a->stencilBufferStackDepth].buffers[i].func = g->stencil.buffers[i].func;
a->stencilBufferStack[a->stencilBufferStackDepth].buffers[i].mask = g->stencil.buffers[i].mask;
a->stencilBufferStack[a->stencilBufferStackDepth].buffers[i].ref = g->stencil.buffers[i].ref;
a->stencilBufferStack[a->stencilBufferStackDepth].buffers[i].fail = g->stencil.buffers[i].fail;
a->stencilBufferStack[a->stencilBufferStackDepth].buffers[i].passDepthFail = g->stencil.buffers[i].passDepthFail;
a->stencilBufferStack[a->stencilBufferStackDepth].buffers[i].passDepthPass = g->stencil.buffers[i].passDepthPass;
}
a->stencilBufferStackDepth++;
}
if (mask & GL_TEXTURE_BIT)
{
CRTextureStack *tState = a->textureStack + a->textureStackDepth;
tState->curTextureUnit = g->texture.curTextureUnit;
for (i = 0 ; i < g->limits.maxTextureUnits ; i++)
{
/* per-unit state */
copy_texunit(&tState->unit[i], &g->texture.unit[i]);
/* texture object state */
copy_texobj(&tState->unit[i].Saved1D, g->texture.unit[i].currentTexture1D, GL_TRUE);
copy_texobj(&tState->unit[i].Saved2D, g->texture.unit[i].currentTexture2D, GL_TRUE);
#ifdef CR_OPENGL_VERSION_1_2
copy_texobj(&tState->unit[i].Saved3D, g->texture.unit[i].currentTexture3D, GL_TRUE);
#endif
#ifdef CR_ARB_texture_cube_map
copy_texobj(&tState->unit[i].SavedCubeMap, g->texture.unit[i].currentTextureCubeMap, GL_TRUE);
#endif
#ifdef CR_NV_texture_rectangle
copy_texobj(&tState->unit[i].SavedRect, g->texture.unit[i].currentTextureRect, GL_TRUE);
#endif
}
a->textureStackDepth++;
}
if (mask & GL_TRANSFORM_BIT)
{
if (a->transformStack[a->transformStackDepth].clip == NULL)
{
a->transformStack[a->transformStackDepth].clip = (GLboolean *) crCalloc( g->limits.maxClipPlanes * sizeof( GLboolean ));
}
if (a->transformStack[a->transformStackDepth].clipPlane == NULL)
{
a->transformStack[a->transformStackDepth].clipPlane = (GLvectord *) crCalloc( g->limits.maxClipPlanes * sizeof( GLvectord ));
}
a->transformStack[a->transformStackDepth].matrixMode = g->transform.matrixMode;
for (i = 0 ; i < g->limits.maxClipPlanes ; i++)
{
a->transformStack[a->transformStackDepth].clip[i] = g->transform.clip[i];
a->transformStack[a->transformStackDepth].clipPlane[i] = g->transform.clipPlane[i];
}
a->transformStack[a->transformStackDepth].normalize = g->transform.normalize;
#ifdef CR_OPENGL_VERSION_1_2
a->transformStack[a->transformStackDepth].rescaleNormals = g->transform.rescaleNormals;
#endif
a->transformStackDepth++;
}
if (mask & GL_VIEWPORT_BIT)
{
a->viewportStack[a->viewportStackDepth].viewportX = g->viewport.viewportX;
a->viewportStack[a->viewportStackDepth].viewportY = g->viewport.viewportY;
a->viewportStack[a->viewportStackDepth].viewportW = g->viewport.viewportW;
a->viewportStack[a->viewportStackDepth].viewportH = g->viewport.viewportH;
a->viewportStack[a->viewportStackDepth].nearClip = g->viewport.nearClip;
a->viewportStack[a->viewportStackDepth].farClip = g->viewport.farClip;
a->viewportStackDepth++;
}
DIRTY(ab->dirty, g->neg_bitid);
}
void STATE_APIENTRY crStatePopAttrib(void)
{
CRContext *g = GetCurrentContext();
CRAttribState *a = &(g->attrib);
CRStateBits *sb = GetCurrentBits();
CRAttribBits *ab = &(sb->attrib);
CRbitvalue mask;
unsigned int i;
if (g->current.inBeginEnd)
{
crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glPopAttrib called in Begin/End");
return;
}
if (a->attribStackDepth == 0)
{
crStateError(__LINE__, __FILE__, GL_STACK_UNDERFLOW, "glPopAttrib called with an empty stack!" );
return;
}
FLUSH();
mask = a->pushMaskStack[--a->attribStackDepth];
if (mask & GL_ACCUM_BUFFER_BIT)
{
if (a->accumBufferStackDepth == 0)
{
crStateError(__LINE__, __FILE__, GL_STACK_UNDERFLOW, "glPopAttrib called with an empty accum buffer stack!" );
return;
}
a->accumBufferStackDepth--;
g->buffer.accumClearValue = a->accumBufferStack[a->accumBufferStackDepth].accumClearValue;
DIRTY(sb->buffer.dirty, g->neg_bitid);
DIRTY(sb->buffer.clearAccum, g->neg_bitid);
}
if (mask & GL_COLOR_BUFFER_BIT)
{
if (a->colorBufferStackDepth == 0)
{
crStateError(__LINE__, __FILE__, GL_STACK_UNDERFLOW, "glPopAttrib called with an empty color buffer stack!" );
return;
}
a->colorBufferStackDepth--;
g->buffer.alphaTest = a->colorBufferStack[a->colorBufferStackDepth].alphaTest;
g->buffer.alphaTestFunc = a->colorBufferStack[a->colorBufferStackDepth].alphaTestFunc;
g->buffer.alphaTestRef = a->colorBufferStack[a->colorBufferStackDepth].alphaTestRef;
g->buffer.blend = a->colorBufferStack[a->colorBufferStackDepth].blend;
g->buffer.blendSrcRGB = a->colorBufferStack[a->colorBufferStackDepth].blendSrcRGB;
g->buffer.blendDstRGB = a->colorBufferStack[a->colorBufferStackDepth].blendDstRGB;
#if defined(CR_EXT_blend_func_separate)
g->buffer.blendSrcA = a->colorBufferStack[a->colorBufferStackDepth].blendSrcA;
g->buffer.blendDstA = a->colorBufferStack[a->colorBufferStackDepth].blendDstA;
#endif
#ifdef CR_EXT_blend_color
g->buffer.blendColor = a->colorBufferStack[a->colorBufferStackDepth].blendColor;
#endif
#if defined(CR_EXT_blend_minmax) || defined(CR_EXT_blend_subtract) || defined(CR_EXT_blend_logic_op)
g->buffer.blendEquation = a->colorBufferStack[a->colorBufferStackDepth].blendEquation;
#endif
g->buffer.dither = a->colorBufferStack[a->colorBufferStackDepth].dither;
g->buffer.drawBuffer = a->colorBufferStack[a->colorBufferStackDepth].drawBuffer;
g->buffer.logicOp = a->colorBufferStack[a->colorBufferStackDepth].logicOp;
g->buffer.indexLogicOp = a->colorBufferStack[a->colorBufferStackDepth].indexLogicOp;
g->buffer.logicOpMode = a->colorBufferStack[a->colorBufferStackDepth].logicOpMode;
g->buffer.colorClearValue = a->colorBufferStack[a->colorBufferStackDepth].colorClearValue;
g->buffer.indexClearValue = a->colorBufferStack[a->colorBufferStackDepth].indexClearValue;
g->buffer.colorWriteMask = a->colorBufferStack[a->colorBufferStackDepth].colorWriteMask;
g->buffer.indexWriteMask = a->colorBufferStack[a->colorBufferStackDepth].indexWriteMask;
DIRTY(sb->buffer.dirty, g->neg_bitid);
DIRTY(sb->buffer.enable, g->neg_bitid);
DIRTY(sb->buffer.alphaFunc, g->neg_bitid);
DIRTY(sb->buffer.blendFunc, g->neg_bitid);
#ifdef CR_EXT_blend_color
DIRTY(sb->buffer.blendColor, g->neg_bitid);
#endif
#if defined(CR_EXT_blend_minmax) || defined(CR_EXT_blend_subtract) || defined(CR_EXT_blend_logic_op)
DIRTY(sb->buffer.blendEquation, g->neg_bitid);
#endif
DIRTY(sb->buffer.drawBuffer, g->neg_bitid);
DIRTY(sb->buffer.logicOp, g->neg_bitid);
DIRTY(sb->buffer.indexLogicOp, g->neg_bitid);
DIRTY(sb->buffer.clearColor, g->neg_bitid);
DIRTY(sb->buffer.clearIndex, g->neg_bitid);
DIRTY(sb->buffer.colorWriteMask, g->neg_bitid);
DIRTY(sb->buffer.indexMask, g->neg_bitid);
}
if (mask & GL_CURRENT_BIT)
{
if (a->currentStackDepth == 0)
{
crStateError(__LINE__, __FILE__, GL_STACK_UNDERFLOW, "glPopAttrib called with an empty current stack!" );
return;
}
a->currentStackDepth--;
for (i = 0 ; i < CR_MAX_VERTEX_ATTRIBS ; i++)
{
COPY_4V(g->current.vertexAttrib[i], a->currentStack[a->currentStackDepth].attrib[i]);
COPY_4V(g->current.rasterAttrib[i], a->currentStack[a->currentStackDepth].rasterAttrib[i]);
DIRTY(sb->current.vertexAttrib[i], g->neg_bitid);
}
g->current.rasterValid = a->currentStack[a->currentStackDepth].rasterValid;
g->current.edgeFlag = a->currentStack[a->currentStackDepth].edgeFlag;
g->current.colorIndex = a->currentStack[a->currentStackDepth].colorIndex;
DIRTY(sb->current.dirty, g->neg_bitid);
DIRTY(sb->current.edgeFlag, g->neg_bitid);
DIRTY(sb->current.colorIndex, g->neg_bitid);
DIRTY(sb->current.rasterPos, g->neg_bitid);
}
if (mask & GL_DEPTH_BUFFER_BIT)
{
if (a->depthBufferStackDepth == 0)
{
crStateError(__LINE__, __FILE__, GL_STACK_UNDERFLOW, "glPopAttrib called with an empty depth buffer stack!" );
return;
}
a->depthBufferStackDepth--;
g->buffer.depthTest = a->depthBufferStack[a->depthBufferStackDepth].depthTest;
g->buffer.depthFunc = a->depthBufferStack[a->depthBufferStackDepth].depthFunc;
g->buffer.depthClearValue = a->depthBufferStack[a->depthBufferStackDepth].depthClearValue;
g->buffer.depthMask = a->depthBufferStack[a->depthBufferStackDepth].depthMask;
DIRTY(sb->buffer.dirty, g->neg_bitid);
DIRTY(sb->buffer.enable, g->neg_bitid);
DIRTY(sb->buffer.depthFunc, g->neg_bitid);
DIRTY(sb->buffer.clearDepth, g->neg_bitid);
DIRTY(sb->buffer.depthMask, g->neg_bitid);
}
if (mask & GL_ENABLE_BIT)
{
if (a->enableStackDepth == 0)
{
crStateError(__LINE__, __FILE__, GL_STACK_UNDERFLOW, "glPopAttrib called with an empty enable stack!" );
return;
}
a->enableStackDepth--;
g->buffer.alphaTest = a->enableStack[a->enableStackDepth].alphaTest;
g->eval.autoNormal = a->enableStack[a->enableStackDepth].autoNormal;
g->buffer.blend = a->enableStack[a->enableStackDepth].blend;
for (i = 0 ; i < g->limits.maxClipPlanes ; i++)
{
g->transform.clip[i] = a->enableStack[a->enableStackDepth].clip[i];
}
g->lighting.colorMaterial = a->enableStack[a->enableStackDepth].colorMaterial;
g->polygon.cullFace = a->enableStack[a->enableStackDepth].cullFace;
g->buffer.depthTest = a->enableStack[a->enableStackDepth].depthTest;
g->buffer.dither = a->enableStack[a->enableStackDepth].dither;
g->fog.enable = a->enableStack[a->enableStackDepth].fog;
for (i = 0 ; i < g->limits.maxLights ; i++)
{
g->lighting.light[i].enable = a->enableStack[a->enableStackDepth].light[i];
}
g->lighting.lighting = a->enableStack[a->enableStackDepth].lighting;
g->line.lineSmooth = a->enableStack[a->enableStackDepth].lineSmooth;
g->line.lineStipple = a->enableStack[a->enableStackDepth].lineStipple;
g->buffer.logicOp = a->enableStack[a->enableStackDepth].logicOp;
g->buffer.indexLogicOp = a->enableStack[a->enableStackDepth].indexLogicOp;
for (i = 0 ; i < GLEVAL_TOT ; i++)
{
g->eval.enable1D[i] = a->enableStack[a->enableStackDepth].map1[i];
g->eval.enable2D[i] = a->enableStack[a->enableStackDepth].map2[i];
}
g->transform.normalize = a->enableStack[a->enableStackDepth].normalize;
g->point.pointSmooth = a->enableStack[a->enableStackDepth].pointSmooth;
#ifdef CR_ARB_point_sprite
g->point.pointSprite = a->enableStack[a->enableStackDepth].pointSprite;
for (i = 0; i < CR_MAX_TEXTURE_UNITS; i++)
g->point.coordReplacement[i] = a->enableStack[a->enableStackDepth].coordReplacement[i];
#endif
g->polygon.polygonOffsetLine = a->enableStack[a->enableStackDepth].polygonOffsetLine;
g->polygon.polygonOffsetFill = a->enableStack[a->enableStackDepth].polygonOffsetFill;
g->polygon.polygonOffsetPoint = a->enableStack[a->enableStackDepth].polygonOffsetPoint;
g->polygon.polygonSmooth = a->enableStack[a->enableStackDepth].polygonSmooth;
g->polygon.polygonStipple = a->enableStack[a->enableStackDepth].polygonStipple;
#ifdef CR_OPENGL_VERSION_1_2
g->transform.rescaleNormals = a->enableStack[a->enableStackDepth].rescaleNormals;
#endif
g->viewport.scissorTest = a->enableStack[a->enableStackDepth].scissorTest;
g->stencil.stencilTest = a->enableStack[a->enableStackDepth].stencilTest;
for (i = 0 ; i < g->limits.maxTextureUnits; i++)
{
g->texture.unit[i].enabled1D = a->enableStack[a->enableStackDepth].texture1D[i];
g->texture.unit[i].enabled2D = a->enableStack[a->enableStackDepth].texture2D[i];
#ifdef CR_OPENGL_VERSION_1_2
g->texture.unit[i].enabled3D = a->enableStack[a->enableStackDepth].texture3D[i];
#endif
#ifdef CR_ARB_texture_cube_map
g->texture.unit[i].enabledCubeMap = a->enableStack[a->enableStackDepth].textureCubeMap[i];
#endif
#ifdef CR_NV_texture_rectangle
g->texture.unit[i].enabledRect = a->enableStack[a->enableStackDepth].textureRect[i];
#endif
g->texture.unit[i].textureGen.s = a->enableStack[a->enableStackDepth].textureGenS[i];
g->texture.unit[i].textureGen.t = a->enableStack[a->enableStackDepth].textureGenT[i];
g->texture.unit[i].textureGen.r = a->enableStack[a->enableStackDepth].textureGenR[i];
g->texture.unit[i].textureGen.q = a->enableStack[a->enableStackDepth].textureGenQ[i];
}
DIRTY(sb->buffer.dirty, g->neg_bitid);
DIRTY(sb->eval.dirty, g->neg_bitid);
DIRTY(sb->transform.dirty, g->neg_bitid);
DIRTY(sb->lighting.dirty, g->neg_bitid);
DIRTY(sb->fog.dirty, g->neg_bitid);
DIRTY(sb->line.dirty, g->neg_bitid);
DIRTY(sb->polygon.dirty, g->neg_bitid);
DIRTY(sb->viewport.dirty, g->neg_bitid);
DIRTY(sb->stencil.dirty, g->neg_bitid);
DIRTY(sb->texture.dirty, g->neg_bitid);
DIRTY(sb->buffer.enable, g->neg_bitid);
DIRTY(sb->eval.enable, g->neg_bitid);
DIRTY(sb->transform.enable, g->neg_bitid);
DIRTY(sb->lighting.enable, g->neg_bitid);
DIRTY(sb->fog.enable, g->neg_bitid);
DIRTY(sb->line.enable, g->neg_bitid);
DIRTY(sb->polygon.enable, g->neg_bitid);
DIRTY(sb->viewport.enable, g->neg_bitid);
DIRTY(sb->stencil.enable, g->neg_bitid);
for (i = 0 ; i < g->limits.maxTextureUnits ; i++)
{
DIRTY(sb->texture.enable[i], g->neg_bitid);
}
}
if (mask & GL_EVAL_BIT)
{
if (a->evalStackDepth == 0)
{
crStateError(__LINE__, __FILE__, GL_STACK_UNDERFLOW, "glPopAttrib called with an empty eval stack!" );
return;
}
a->evalStackDepth--;
for (i = 0 ; i < GLEVAL_TOT ; i++)
{
int size1 = a->evalStack[a->evalStackDepth].eval1D[i].order * gleval_sizes[i] * sizeof(GLfloat);
int size2 = a->evalStack[a->evalStackDepth].eval2D[i].uorder * a->evalStack[a->evalStackDepth].eval2D[i].vorder * gleval_sizes[i] * sizeof (GLfloat);
g->eval.enable1D[i] = a->evalStack[a->evalStackDepth].enable1D[i];
g->eval.enable2D[i] = a->evalStack[a->evalStackDepth].enable2D[i];
g->eval.eval1D[i].u1 = a->evalStack[a->evalStackDepth].eval1D[i].u1;
g->eval.eval1D[i].u2 = a->evalStack[a->evalStackDepth].eval1D[i].u2;
g->eval.eval1D[i].order = a->evalStack[a->evalStackDepth].eval1D[i].order;
crMemcpy((char*)g->eval.eval1D[i].coeff, a->evalStack[a->evalStackDepth].eval1D[i].coeff, size1);
crFree(a->evalStack[a->evalStackDepth].eval1D[i].coeff);
a->evalStack[a->evalStackDepth].eval1D[i].coeff = NULL;
g->eval.eval2D[i].u1 = a->evalStack[a->evalStackDepth].eval2D[i].u1;
g->eval.eval2D[i].u2 = a->evalStack[a->evalStackDepth].eval2D[i].u2;
g->eval.eval2D[i].v1 = a->evalStack[a->evalStackDepth].eval2D[i].v1;
g->eval.eval2D[i].v2 = a->evalStack[a->evalStackDepth].eval2D[i].v2;
g->eval.eval2D[i].uorder = a->evalStack[a->evalStackDepth].eval2D[i].uorder;
g->eval.eval2D[i].vorder = a->evalStack[a->evalStackDepth].eval2D[i].vorder;
crMemcpy((char*)g->eval.eval2D[i].coeff, a->evalStack[a->evalStackDepth].eval2D[i].coeff, size2);
crFree(a->evalStack[a->evalStackDepth].eval2D[i].coeff);
a->evalStack[a->evalStackDepth].eval2D[i].coeff = NULL;
}
g->eval.autoNormal = a->evalStack[a->evalStackDepth].autoNormal;
g->eval.un1D = a->evalStack[a->evalStackDepth].un1D;
g->eval.u11D = a->evalStack[a->evalStackDepth].u11D;
g->eval.u21D = a->evalStack[a->evalStackDepth].u21D;
g->eval.un2D = a->evalStack[a->evalStackDepth].un2D;
g->eval.u12D = a->evalStack[a->evalStackDepth].u12D;
g->eval.u22D = a->evalStack[a->evalStackDepth].u22D;
g->eval.vn2D = a->evalStack[a->evalStackDepth].vn2D;
g->eval.v12D = a->evalStack[a->evalStackDepth].v12D;
g->eval.v22D = a->evalStack[a->evalStackDepth].v22D;
for (i = 0; i < GLEVAL_TOT; i++) {
DIRTY(sb->eval.eval1D[i], g->neg_bitid);
DIRTY(sb->eval.eval2D[i], g->neg_bitid);
}
DIRTY(sb->eval.dirty, g->neg_bitid);
DIRTY(sb->eval.grid1D, g->neg_bitid);
DIRTY(sb->eval.grid2D, g->neg_bitid);
DIRTY(sb->eval.enable, g->neg_bitid);
}
if (mask & GL_FOG_BIT)
{
if (a->fogStackDepth == 0)
{
crStateError(__LINE__, __FILE__, GL_STACK_UNDERFLOW, "glPopAttrib called with an empty fog stack!" );
return;
}
a->fogStackDepth--;
g->fog.enable = a->fogStack[a->fogStackDepth].enable;
g->fog.color = a->fogStack[a->fogStackDepth].color;
g->fog.density = a->fogStack[a->fogStackDepth].density;
g->fog.start = a->fogStack[a->fogStackDepth].start;
g->fog.end = a->fogStack[a->fogStackDepth].end;
g->fog.index = a->fogStack[a->fogStackDepth].index;
g->fog.mode = a->fogStack[a->fogStackDepth].mode;
DIRTY(sb->fog.dirty, g->neg_bitid);
DIRTY(sb->fog.color, g->neg_bitid);
DIRTY(sb->fog.index, g->neg_bitid);
DIRTY(sb->fog.density, g->neg_bitid);
DIRTY(sb->fog.start, g->neg_bitid);
DIRTY(sb->fog.end, g->neg_bitid);
DIRTY(sb->fog.mode, g->neg_bitid);
DIRTY(sb->fog.enable, g->neg_bitid);
}
if (mask & GL_HINT_BIT)
{
if (a->hintStackDepth == 0)
{
crStateError(__LINE__, __FILE__, GL_STACK_UNDERFLOW, "glPopAttrib called with an empty hint stack!" );
return;
}
a->hintStackDepth--;
g->hint.perspectiveCorrection = a->hintStack[a->hintStackDepth].perspectiveCorrection;
g->hint.pointSmooth = a->hintStack[a->hintStackDepth].pointSmooth;
g->hint.lineSmooth = a->hintStack[a->hintStackDepth].lineSmooth;
g->hint.polygonSmooth = a->hintStack[a->hintStackDepth].polygonSmooth;
g->hint.fog = a->hintStack[a->hintStackDepth].fog;
DIRTY(sb->hint.dirty, g->neg_bitid);
DIRTY(sb->hint.perspectiveCorrection, g->neg_bitid);
DIRTY(sb->hint.pointSmooth, g->neg_bitid);
DIRTY(sb->hint.lineSmooth, g->neg_bitid);
DIRTY(sb->hint.polygonSmooth, g->neg_bitid);
#ifdef CR_EXT_clip_volume_hint
g->hint.clipVolumeClipping = a->hintStack[a->hintStackDepth].clipVolumeClipping;
DIRTY(sb->hint.clipVolumeClipping, g->neg_bitid);
#endif
#ifdef CR_ARB_texture_compression
g->hint.textureCompression = a->hintStack[a->hintStackDepth].textureCompression;
DIRTY(sb->hint.textureCompression, g->neg_bitid);
#endif
#ifdef CR_SGIS_generate_mipmap
g->hint.generateMipmap = a->hintStack[a->hintStackDepth].generateMipmap;
DIRTY(sb->hint.generateMipmap, g->neg_bitid);
#endif
}
if (mask & GL_LIGHTING_BIT)
{
if (a->lightingStackDepth == 0)
{
crStateError(__LINE__, __FILE__, GL_STACK_UNDERFLOW, "glPopAttrib called with an empty lighting stack!" );
return;
}
a->lightingStackDepth--;
g->lighting.lightModelAmbient = a->lightingStack[a->lightingStackDepth].lightModelAmbient;
g->lighting.lightModelLocalViewer = a->lightingStack[a->lightingStackDepth].lightModelLocalViewer;
g->lighting.lightModelTwoSide = a->lightingStack[a->lightingStackDepth].lightModelTwoSide;
#if defined(CR_EXT_separate_specular_color) || defined(CR_OPENGL_VERSION_1_2)
g->lighting.lightModelColorControlEXT = a->lightingStack[a->lightingStackDepth].lightModelColorControlEXT;
#endif
g->lighting.lighting = a->lightingStack[a->lightingStackDepth].lighting;
g->lighting.colorMaterial = a->lightingStack[a->lightingStackDepth].colorMaterial;
g->lighting.colorMaterialMode = a->lightingStack[a->lightingStackDepth].colorMaterialMode;
g->lighting.colorMaterialFace = a->lightingStack[a->lightingStackDepth].colorMaterialFace;
for (i = 0 ; i < g->limits.maxLights; i++)
{
g->lighting.light[i].enable = a->lightingStack[a->lightingStackDepth].light[i].enable;
g->lighting.light[i].ambient = a->lightingStack[a->lightingStackDepth].light[i].ambient;
g->lighting.light[i].diffuse = a->lightingStack[a->lightingStackDepth].light[i].diffuse;
g->lighting.light[i].specular = a->lightingStack[a->lightingStackDepth].light[i].specular;
g->lighting.light[i].spotDirection = a->lightingStack[a->lightingStackDepth].light[i].spotDirection;
g->lighting.light[i].position = a->lightingStack[a->lightingStackDepth].light[i].position;
g->lighting.light[i].spotExponent = a->lightingStack[a->lightingStackDepth].light[i].spotExponent;
g->lighting.light[i].spotCutoff = a->lightingStack[a->lightingStackDepth].light[i].spotCutoff;
g->lighting.light[i].constantAttenuation = a->lightingStack[a->lightingStackDepth].light[i].constantAttenuation;
g->lighting.light[i].linearAttenuation = a->lightingStack[a->lightingStackDepth].light[i].linearAttenuation;
g->lighting.light[i].quadraticAttenuation = a->lightingStack[a->lightingStackDepth].light[i].quadraticAttenuation;
}
for (i = 0 ; i < 2 ; i++)
{
g->lighting.ambient[i] = a->lightingStack[a->lightingStackDepth].ambient[i];
g->lighting.diffuse[i] = a->lightingStack[a->lightingStackDepth].diffuse[i];
g->lighting.specular[i] = a->lightingStack[a->lightingStackDepth].specular[i];
g->lighting.emission[i] = a->lightingStack[a->lightingStackDepth].emission[i];
g->lighting.shininess[i] = a->lightingStack[a->lightingStackDepth].shininess[i];
g->lighting.indexes[i][0] = a->lightingStack[a->lightingStackDepth].indexes[i][0];
g->lighting.indexes[i][1] = a->lightingStack[a->lightingStackDepth].indexes[i][1];
g->lighting.indexes[i][2] = a->lightingStack[a->lightingStackDepth].indexes[i][2];
}
g->lighting.shadeModel = a->lightingStack[a->lightingStackDepth].shadeModel;
DIRTY(sb->lighting.dirty, g->neg_bitid);
DIRTY(sb->lighting.shadeModel, g->neg_bitid);
DIRTY(sb->lighting.lightModel, g->neg_bitid);
DIRTY(sb->lighting.material, g->neg_bitid);
DIRTY(sb->lighting.enable, g->neg_bitid);
for (i = 0 ; i < g->limits.maxLights; i++)
{
DIRTY(sb->lighting.light[i].dirty, g->neg_bitid);
DIRTY(sb->lighting.light[i].enable, g->neg_bitid);
DIRTY(sb->lighting.light[i].ambient, g->neg_bitid);
DIRTY(sb->lighting.light[i].diffuse, g->neg_bitid);
DIRTY(sb->lighting.light[i].specular, g->neg_bitid);
DIRTY(sb->lighting.light[i].position, g->neg_bitid);
DIRTY(sb->lighting.light[i].attenuation, g->neg_bitid);
DIRTY(sb->lighting.light[i].spot, g->neg_bitid);
}
}
if (mask & GL_LINE_BIT)
{
if (a->lineStackDepth == 0)
{
crStateError(__LINE__, __FILE__, GL_STACK_UNDERFLOW, "glPopAttrib called with an empty line stack!" );
return;
}
a->lineStackDepth--;
g->line.lineSmooth = a->lineStack[a->lineStackDepth].lineSmooth;
g->line.lineStipple = a->lineStack[a->lineStackDepth].lineStipple;
g->line.pattern = a->lineStack[a->lineStackDepth].pattern;
g->line.repeat = a->lineStack[a->lineStackDepth].repeat;
g->line.width = a->lineStack[a->lineStackDepth].width;
DIRTY(sb->line.dirty, g->neg_bitid);
DIRTY(sb->line.enable, g->neg_bitid);
DIRTY(sb->line.width, g->neg_bitid);
DIRTY(sb->line.stipple, g->neg_bitid);
}
if (mask & GL_LIST_BIT)
{
if (a->listStackDepth == 0)
{
crStateError(__LINE__, __FILE__, GL_STACK_UNDERFLOW, "glPopAttrib called with an empty list stack!" );
return;
}
a->listStackDepth--;
g->lists.base = a->listStack[a->listStackDepth].base;
DIRTY(sb->lists.dirty, g->neg_bitid);
}
if (mask & GL_PIXEL_MODE_BIT)
{
if (a->pixelModeStackDepth == 0)
{
crStateError(__LINE__, __FILE__, GL_STACK_UNDERFLOW, "glPopAttrib called with an empty pixel mode stack!" );
return;
}
a->pixelModeStackDepth--;
g->pixel.bias = a->pixelModeStack[a->pixelModeStackDepth].bias;
g->pixel.scale = a->pixelModeStack[a->pixelModeStackDepth].scale;
g->pixel.indexOffset = a->pixelModeStack[a->pixelModeStackDepth].indexOffset;
g->pixel.indexShift = a->pixelModeStack[a->pixelModeStackDepth].indexShift;
g->pixel.mapColor = a->pixelModeStack[a->pixelModeStackDepth].mapColor;
g->pixel.mapStencil = a->pixelModeStack[a->pixelModeStackDepth].mapStencil;
g->pixel.xZoom = a->pixelModeStack[a->pixelModeStackDepth].xZoom;
g->pixel.yZoom = a->pixelModeStack[a->pixelModeStackDepth].yZoom;
g->buffer.readBuffer = a->pixelModeStack[a->pixelModeStackDepth].readBuffer;
DIRTY(sb->pixel.dirty, g->neg_bitid);
DIRTY(sb->pixel.transfer, g->neg_bitid);
DIRTY(sb->pixel.zoom, g->neg_bitid);
DIRTY(sb->buffer.dirty, g->neg_bitid);
DIRTY(sb->buffer.readBuffer, g->neg_bitid);
}
if (mask & GL_POINT_BIT)
{
if (a->pointStackDepth == 0)
{
crStateError(__LINE__, __FILE__, GL_STACK_UNDERFLOW, "glPopAttrib called with an empty point stack!" );
return;
}
a->pointStackDepth--;
g->point.pointSmooth = a->pointStack[a->pointStackDepth].pointSmooth;
g->point.pointSize = a->pointStack[a->pointStackDepth].pointSize;
#if GL_ARB_point_sprite
g->point.pointSprite = a->pointStack[a->pointStackDepth].pointSprite;
DIRTY(sb->point.enableSprite, g->neg_bitid);
for (i = 0; i < CR_MAX_TEXTURE_UNITS; i++) {
g->point.coordReplacement[i] = a->enableStack[a->enableStackDepth].coordReplacement[i];
DIRTY(sb->point.coordReplacement[i], g->neg_bitid);
}
#endif
DIRTY(sb->point.dirty, g->neg_bitid);
DIRTY(sb->point.size, g->neg_bitid);
DIRTY(sb->point.enableSmooth, g->neg_bitid);
}
if (mask & GL_POLYGON_BIT)
{
if (a->polygonStackDepth == 0)
{
crStateError(__LINE__, __FILE__, GL_STACK_UNDERFLOW, "glPopAttrib called with an empty polygon stack!" );
return;
}
a->polygonStackDepth--;
g->polygon.cullFace = a->polygonStack[a->polygonStackDepth].cullFace;
g->polygon.cullFaceMode = a->polygonStack[a->polygonStackDepth].cullFaceMode;
g->polygon.frontFace = a->polygonStack[a->polygonStackDepth].frontFace;
g->polygon.frontMode = a->polygonStack[a->polygonStackDepth].frontMode;
g->polygon.backMode = a->polygonStack[a->polygonStackDepth].backMode;
g->polygon.polygonSmooth = a->polygonStack[a->polygonStackDepth].polygonSmooth;
g->polygon.polygonStipple = a->polygonStack[a->polygonStackDepth].polygonStipple;
g->polygon.polygonOffsetFill = a->polygonStack[a->polygonStackDepth].polygonOffsetFill;
g->polygon.polygonOffsetLine = a->polygonStack[a->polygonStackDepth].polygonOffsetLine;
g->polygon.polygonOffsetPoint = a->polygonStack[a->polygonStackDepth].polygonOffsetPoint;
g->polygon.offsetFactor = a->polygonStack[a->polygonStackDepth].offsetFactor;
g->polygon.offsetUnits = a->polygonStack[a->polygonStackDepth].offsetUnits;
DIRTY(sb->polygon.dirty, g->neg_bitid);
DIRTY(sb->polygon.enable, g->neg_bitid);
DIRTY(sb->polygon.offset, g->neg_bitid);
DIRTY(sb->polygon.mode, g->neg_bitid);
DIRTY(sb->polygon.stipple, g->neg_bitid);
}
if (mask & GL_POLYGON_STIPPLE_BIT)
{
if (a->polygonStippleStackDepth == 0)
{
crStateError(__LINE__, __FILE__, GL_STACK_UNDERFLOW, "glPopAttrib called with an empty polygon stipple stack!" );
return;
}
a->polygonStippleStackDepth--;
crMemcpy( g->polygon.stipple, a->polygonStippleStack[a->polygonStippleStackDepth].pattern, 32*sizeof(GLint) );
DIRTY(sb->polygon.dirty, g->neg_bitid);
DIRTY(sb->polygon.stipple, g->neg_bitid);
}
if (mask & GL_SCISSOR_BIT)
{
if (a->scissorStackDepth == 0)
{
crStateError(__LINE__, __FILE__, GL_STACK_UNDERFLOW, "glPopAttrib called with an empty scissor stack!" );
return;
}
a->scissorStackDepth--;
g->viewport.scissorTest = a->scissorStack[a->scissorStackDepth].scissorTest;
g->viewport.scissorX = a->scissorStack[a->scissorStackDepth].scissorX;
g->viewport.scissorY = a->scissorStack[a->scissorStackDepth].scissorY;
g->viewport.scissorW = a->scissorStack[a->scissorStackDepth].scissorW;
g->viewport.scissorH = a->scissorStack[a->scissorStackDepth].scissorH;
DIRTY(sb->viewport.dirty, g->neg_bitid);
DIRTY(sb->viewport.enable, g->neg_bitid);
DIRTY(sb->viewport.s_dims, g->neg_bitid);
}
if (mask & GL_STENCIL_BUFFER_BIT)
{
if (a->stencilBufferStackDepth == 0)
{
crStateError(__LINE__, __FILE__, GL_STACK_UNDERFLOW, "glPopAttrib called with an empty stencil stack!" );
return;
}
a->stencilBufferStackDepth--;
g->stencil.stencilTest = a->stencilBufferStack[a->stencilBufferStackDepth].stencilTest;
g->stencil.clearValue = a->stencilBufferStack[a->stencilBufferStackDepth].clearValue;
g->stencil.writeMask = a->stencilBufferStack[a->stencilBufferStackDepth].writeMask;
for (i = 0; i < CRSTATE_STENCIL_BUFFER_COUNT; ++i)
{
g->stencil.buffers[i].func = a->stencilBufferStack[a->stencilBufferStackDepth].buffers[i].func;
g->stencil.buffers[i].mask = a->stencilBufferStack[a->stencilBufferStackDepth].buffers[i].mask;
g->stencil.buffers[i].ref = a->stencilBufferStack[a->stencilBufferStackDepth].buffers[i].ref;
g->stencil.buffers[i].fail = a->stencilBufferStack[a->stencilBufferStackDepth].buffers[i].fail;
g->stencil.buffers[i].passDepthFail = a->stencilBufferStack[a->stencilBufferStackDepth].buffers[i].passDepthFail;
g->stencil.buffers[i].passDepthPass = a->stencilBufferStack[a->stencilBufferStackDepth].buffers[i].passDepthPass;
}
DIRTY(sb->stencil.dirty, g->neg_bitid);
DIRTY(sb->stencil.enable, g->neg_bitid);
DIRTY(sb->stencil.clearValue, g->neg_bitid);
DIRTY(sb->stencil.writeMask, g->neg_bitid);
for (i = 0; i < CRSTATE_STENCIL_BUFFER_REF_COUNT; ++i)
{
DIRTY(sb->stencil.bufferRefs[i].func, g->neg_bitid);
DIRTY(sb->stencil.bufferRefs[i].op, g->neg_bitid);
}
}
if (mask & GL_TEXTURE_BIT)
{
CRTextureStack *tState;
if (a->textureStackDepth == 0)
{
crStateError(__LINE__, __FILE__, GL_STACK_UNDERFLOW, "glPopAttrib called with an empty texture stack!" );
return;
}
a->textureStackDepth--;
tState = a->textureStack + a->textureStackDepth;
g->texture.curTextureUnit = tState->curTextureUnit;
for (i = 0 ; i < g->limits.maxTextureUnits ; i++)
{
copy_texunit(&g->texture.unit[i], &tState->unit[i]);
/* first, restore the bindings! */
g->texture.unit[i].currentTexture1D = crStateTextureGet(GL_TEXTURE_1D, tState->unit[i].Saved1D.id);
copy_texobj(g->texture.unit[i].currentTexture1D, &tState->unit[i].Saved1D, GL_FALSE);
g->texture.unit[i].currentTexture2D = crStateTextureGet(GL_TEXTURE_2D, tState->unit[i].Saved2D.id);
copy_texobj(g->texture.unit[i].currentTexture2D, &tState->unit[i].Saved2D, GL_FALSE);
#ifdef CR_OPENGL_VERSION_1_2
g->texture.unit[i].currentTexture3D = crStateTextureGet(GL_TEXTURE_3D, tState->unit[i].Saved3D.id);
copy_texobj(g->texture.unit[i].currentTexture3D, &tState->unit[i].Saved3D, GL_FALSE);
#endif
#ifdef CR_ARB_texture_cube_map
g->texture.unit[i].currentTextureCubeMap = crStateTextureGet(GL_TEXTURE_CUBE_MAP_ARB, tState->unit[i].SavedCubeMap.id);
copy_texobj(g->texture.unit[i].currentTextureCubeMap, &tState->unit[i].SavedCubeMap, GL_FALSE);
#endif
#ifdef CR_NV_texture_rectangle
g->texture.unit[i].currentTextureRect = crStateTextureGet(GL_TEXTURE_CUBE_MAP_ARB, tState->unit[i].SavedRect.id);
copy_texobj(g->texture.unit[i].currentTextureRect, &tState->unit[i].SavedRect, GL_FALSE);
#endif
}
DIRTY(sb->texture.dirty, g->neg_bitid);
for (i = 0 ; i < g->limits.maxTextureUnits ; i++)
{
DIRTY(sb->texture.enable[i], g->neg_bitid);
DIRTY(sb->texture.current[i], g->neg_bitid);
DIRTY(sb->texture.objGen[i], g->neg_bitid);
DIRTY(sb->texture.eyeGen[i], g->neg_bitid);
DIRTY(sb->texture.envBit[i], g->neg_bitid);
DIRTY(sb->texture.genMode[i], g->neg_bitid);
}
for (i = 0 ; i < g->limits.maxTextureUnits ; i++)
{
DIRTY(g->texture.unit[i].currentTexture1D->dirty, g->neg_bitid);
DIRTY(g->texture.unit[i].currentTexture2D->dirty, g->neg_bitid);
DIRTY(g->texture.unit[i].currentTexture3D->dirty, g->neg_bitid);
#ifdef CR_ARB_texture_cube_map
DIRTY(g->texture.unit[i].currentTextureCubeMap->dirty, g->neg_bitid);
#endif
#ifdef CR_NV_texture_rectangle
DIRTY(g->texture.unit[i].currentTextureRect->dirty, g->neg_bitid);
#endif
DIRTY(g->texture.unit[i].currentTexture1D->paramsBit[i], g->neg_bitid);
DIRTY(g->texture.unit[i].currentTexture2D->paramsBit[i], g->neg_bitid);
DIRTY(g->texture.unit[i].currentTexture3D->paramsBit[i], g->neg_bitid);
#ifdef CR_ARB_texture_cube_map
DIRTY(g->texture.unit[i].currentTextureCubeMap->paramsBit[i], g->neg_bitid);
#endif
#ifdef CR_NV_texture_rectangle
DIRTY(g->texture.unit[i].currentTextureRect->paramsBit[i], g->neg_bitid);
#endif
}
}
if (mask & GL_TRANSFORM_BIT)
{
if (a->transformStackDepth == 0)
{
crStateError(__LINE__, __FILE__, GL_STACK_UNDERFLOW, "glPopAttrib called with an empty transform stack!" );
return;
}
a->transformStackDepth--;
g->transform.matrixMode = a->transformStack[a->transformStackDepth].matrixMode;
crStateMatrixMode(g->transform.matrixMode);
for (i = 0 ; i < g->limits.maxClipPlanes ; i++)
{
g->transform.clip[i] = a->transformStack[a->transformStackDepth].clip[i];
g->transform.clipPlane[i] = a->transformStack[a->transformStackDepth].clipPlane[i];
}
g->transform.normalize = a->transformStack[a->transformStackDepth].normalize;
#ifdef CR_OPENGL_VERSION_1_2
g->transform.rescaleNormals = a->transformStack[a->transformStackDepth].rescaleNormals;
#endif
DIRTY(sb->transform.dirty, g->neg_bitid);
DIRTY(sb->transform.matrixMode, g->neg_bitid);
DIRTY(sb->transform.clipPlane, g->neg_bitid);
DIRTY(sb->transform.enable, g->neg_bitid);
}
if (mask & GL_VIEWPORT_BIT)
{
if (a->viewportStackDepth == 0)
{
crStateError(__LINE__, __FILE__, GL_STACK_UNDERFLOW, "glPopAttrib called with an empty viewport stack!" );
return;
}
a->viewportStackDepth--;
g->viewport.viewportX = a->viewportStack[a->viewportStackDepth].viewportX;
g->viewport.viewportY = a->viewportStack[a->viewportStackDepth].viewportY;
g->viewport.viewportW = a->viewportStack[a->viewportStackDepth].viewportW;
g->viewport.viewportH = a->viewportStack[a->viewportStackDepth].viewportH;
g->viewport.nearClip = a->viewportStack[a->viewportStackDepth].nearClip;
g->viewport.farClip = a->viewportStack[a->viewportStackDepth].farClip;
DIRTY(sb->viewport.dirty, g->neg_bitid);
DIRTY(sb->viewport.v_dims, g->neg_bitid);
DIRTY(sb->viewport.depth, g->neg_bitid);
}
DIRTY(ab->dirty, g->neg_bitid);
}
void crStateAttribSwitch( CRAttribBits *bb, CRbitvalue *bitID,
CRContext *fromCtx, CRContext *toCtx )
{
CRAttribState *to = &(toCtx->attrib);
CRAttribState *from = &(fromCtx->attrib);
if (to->attribStackDepth != 0 || from->attribStackDepth != 0)
{
crWarning( "Trying to switch contexts when the attribute stacks "
"weren't empty. Currently, this is not supported." );
}
(void) bb;
(void) bitID;
}