state_texdiff.c revision 0bebd3a2671042901f1fcceff14f8c58dd397478
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster/* Copyright (c) 2001, Stanford University
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * All rights reserved
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster *
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * See the file LICENSE.txt for information on redistributing this software.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster */
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster#include "state.h"
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster#include "state/cr_statetypes.h"
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster#include "state/cr_texture.h"
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster#include "cr_hash.h"
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster#include "cr_string.h"
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster#include "cr_mem.h"
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster#include "cr_version.h"
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster#include "state_internals.h"
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster#define UNIMPLEMENTED() crStateError(__LINE__,__FILE__,GL_INVALID_OPERATION, "Unimplemented something or other" )
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster#if 0 /* NOT USED??? */
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fostervoid crStateTextureObjSwitchCallback( unsigned long key, void *data1, void *data2 )
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster{
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster CRTextureObj *tobj = (CRTextureObj *) data1;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster CRContext *fromCtx = (CRContext *) data2;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster unsigned int i = 0;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster unsigned int j = 0;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster CRbitvalue *bitID = fromCtx->bitid;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster CRbitvalue nbitID[CR_MAX_BITARRAY];
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster for (j=0;j<CR_MAX_BITARRAY;j++)
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster nbitID[j] = ~bitID[j];
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster if (!tobj) return;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster FILLDIRTY(tobj->dirty);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster FILLDIRTY(tobj->imageBit);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster for (i = 0; i < fromCtx->limits.maxTextureUnits; i++)
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster {
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster int j;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster FILLDIRTY(tobj->paramsBit[i]);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster switch (tobj->target)
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster {
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster case GL_TEXTURE_1D:
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster case GL_TEXTURE_2D:
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster for (j = 0; j <= fromCtx->texture.maxLevel; j++)
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster {
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster CRTextureLevel *tl = &(tobj->level[j]);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster FILLDIRTY(tl->dirty);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster }
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster break;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster#ifdef CR_OPENGL_VERSION_1_2
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster case GL_TEXTURE_3D:
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster#endif
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster for (j = 0; j <= fromCtx->texture.max3DLevel; j++)
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster {
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster CRTextureLevel *tl = &(tobj->level[j]);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster FILLDIRTY(tl->dirty);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster }
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster break;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster#ifdef CR_ARB_texture_cube_map
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster case GL_TEXTURE_CUBE_MAP_ARB:
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster for (j = 0; j <= fromCtx->texture.maxCubeMapLevel; j++)
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster {
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster CRTextureLevel *tl;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster /* Positive X */
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster tl = &(tobj->level[j]);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster FILLDIRTY(tl->dirty);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster /* Negative X */
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster tl = &(tobj->negativeXlevel[j]);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster FILLDIRTY(tl->dirty);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster /* Positive Y */
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster tl = &(tobj->positiveYlevel[j]);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster FILLDIRTY(tl->dirty);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster /* Negative Y */
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster tl = &(tobj->negativeYlevel[j]);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster FILLDIRTY(tl->dirty);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster /* Positive Z */
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster tl = &(tobj->positiveZlevel[j]);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster FILLDIRTY(tl->dirty);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster /* Negative Z */
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster tl = &(tobj->negativeZlevel[j]);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster FILLDIRTY(tl->dirty);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster }
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster break;
#endif
default:
UNIMPLEMENTED();
}
}
}
#endif
void crStateTextureSwitch( CRTextureBits *tb, CRbitvalue *bitID,
CRContext *fromCtx, CRContext *toCtx )
{
CRTextureState *from = &(fromCtx->texture);
const CRTextureState *to = &(toCtx->texture);
unsigned int i,j;
glAble able[2];
CRbitvalue nbitID[CR_MAX_BITARRAY];
unsigned int activeUnit = (unsigned int) -1;
for (j=0;j<CR_MAX_BITARRAY;j++)
nbitID[j] = ~bitID[j];
able[0] = diff_api.Disable;
able[1] = diff_api.Enable;
for (i = 0; i < fromCtx->limits.maxTextureUnits; i++)
{
if (CHECKDIRTY(tb->enable[i], bitID))
{
if (activeUnit != i) {
diff_api.ActiveTextureARB( i + GL_TEXTURE0_ARB );
activeUnit = i;
}
if (from->unit[i].enabled1D != to->unit[i].enabled1D)
{
able[to->unit[i].enabled1D](GL_TEXTURE_1D);
FILLDIRTY(tb->enable[i]);
FILLDIRTY(tb->dirty);
}
if (from->unit[i].enabled2D != to->unit[i].enabled2D)
{
able[to->unit[i].enabled2D](GL_TEXTURE_2D);
FILLDIRTY(tb->enable[i]);
FILLDIRTY(tb->dirty);
}
#ifdef CR_OPENGL_VERSION_1_2
if (from->unit[i].enabled3D != to->unit[i].enabled3D)
{
able[to->unit[i].enabled3D](GL_TEXTURE_3D);
FILLDIRTY(tb->enable[i]);
FILLDIRTY(tb->dirty);
}
#endif
#ifdef CR_ARB_texture_cube_map
if (fromCtx->extensions.ARB_texture_cube_map &&
from->unit[i].enabledCubeMap != to->unit[i].enabledCubeMap)
{
able[to->unit[i].enabledCubeMap](GL_TEXTURE_CUBE_MAP_ARB);
FILLDIRTY(tb->enable[i]);
FILLDIRTY(tb->dirty);
}
#endif
#ifdef CR_NV_texture_rectangle
if (fromCtx->extensions.NV_texture_rectangle &&
from->unit[i].enabledRect != to->unit[i].enabledRect)
{
able[to->unit[i].enabledRect](GL_TEXTURE_RECTANGLE_NV);
FILLDIRTY(tb->enable[i]);
FILLDIRTY(tb->dirty);
}
#endif
if (from->unit[i].textureGen.s != to->unit[i].textureGen.s ||
from->unit[i].textureGen.t != to->unit[i].textureGen.t ||
from->unit[i].textureGen.r != to->unit[i].textureGen.r ||
from->unit[i].textureGen.q != to->unit[i].textureGen.q)
{
able[to->unit[i].textureGen.s](GL_TEXTURE_GEN_S);
able[to->unit[i].textureGen.t](GL_TEXTURE_GEN_T);
able[to->unit[i].textureGen.r](GL_TEXTURE_GEN_R);
able[to->unit[i].textureGen.q](GL_TEXTURE_GEN_Q);
FILLDIRTY(tb->enable[i]);
FILLDIRTY(tb->dirty);
}
CLEARDIRTY(tb->enable[i], nbitID);
}
/*
** A thought on switching with textures:
** Since we are only performing a switch
** and not a sync, we won't need to
** update individual textures, just
** the bindings....
*/
if (CHECKDIRTY(tb->current[i], bitID))
{
if (activeUnit != i) {
diff_api.ActiveTextureARB( i + GL_TEXTURE0_ARB );
activeUnit = i;
}
if (from->unit[i].currentTexture1D->name != to->unit[i].currentTexture1D->name)
{
diff_api.BindTexture(GL_TEXTURE_1D, to->unit[i].currentTexture1D->name);
FILLDIRTY(tb->current[i]);
FILLDIRTY(tb->dirty);
}
if (from->unit[i].currentTexture2D->name != to->unit[i].currentTexture2D->name)
{
diff_api.BindTexture(GL_TEXTURE_2D, to->unit[i].currentTexture2D->name);
FILLDIRTY(tb->current[i]);
FILLDIRTY(tb->dirty);
}
#ifdef CR_OPENGL_VERSION_1_2
if (from->unit[i].currentTexture3D->name != to->unit[i].currentTexture3D->name) {
diff_api.BindTexture(GL_TEXTURE_3D, to->unit[i].currentTexture3D->name);
FILLDIRTY(tb->current[i]);
FILLDIRTY(tb->dirty);
}
#endif
#ifdef CR_ARB_texture_cube_map
if (fromCtx->extensions.ARB_texture_cube_map &&
from->unit[i].currentTextureCubeMap->name != to->unit[i].currentTextureCubeMap->name) {
diff_api.BindTexture(GL_TEXTURE_CUBE_MAP_ARB, to->unit[i].currentTextureCubeMap->name);
FILLDIRTY(tb->current[i]);
FILLDIRTY(tb->dirty);
}
#endif
#ifdef CR_NV_texture_rectangle
if (fromCtx->extensions.NV_texture_rectangle &&
from->unit[i].currentTextureRect->name != to->unit[i].currentTextureRect->name) {
diff_api.BindTexture(GL_TEXTURE_RECTANGLE_NV, to->unit[i].currentTextureRect->name);
FILLDIRTY(tb->current[i]);
FILLDIRTY(tb->dirty);
}
#endif
}
if (CHECKDIRTY(tb->objGen[i], bitID))
{
if (activeUnit != i) {
diff_api.ActiveTextureARB( i + GL_TEXTURE0_ARB );
activeUnit = i;
}
if (from->unit[i].objSCoeff.x != to->unit[i].objSCoeff.x ||
from->unit[i].objSCoeff.y != to->unit[i].objSCoeff.y ||
from->unit[i].objSCoeff.z != to->unit[i].objSCoeff.z ||
from->unit[i].objSCoeff.w != to->unit[i].objSCoeff.w)
{
GLfloat f[4];
f[0] = to->unit[i].objSCoeff.x;
f[1] = to->unit[i].objSCoeff.y;
f[2] = to->unit[i].objSCoeff.z;
f[3] = to->unit[i].objSCoeff.w;
diff_api.TexGenfv (GL_S, GL_OBJECT_PLANE, (const GLfloat *) f);
FILLDIRTY(tb->objGen[i]);
FILLDIRTY(tb->dirty);
}
if (from->unit[i].objTCoeff.x != to->unit[i].objTCoeff.x ||
from->unit[i].objTCoeff.y != to->unit[i].objTCoeff.y ||
from->unit[i].objTCoeff.z != to->unit[i].objTCoeff.z ||
from->unit[i].objTCoeff.w != to->unit[i].objTCoeff.w) {
GLfloat f[4];
f[0] = to->unit[i].objTCoeff.x;
f[1] = to->unit[i].objTCoeff.y;
f[2] = to->unit[i].objTCoeff.z;
f[3] = to->unit[i].objTCoeff.w;
diff_api.TexGenfv (GL_T, GL_OBJECT_PLANE, (const GLfloat *) f);
FILLDIRTY(tb->objGen[i]);
FILLDIRTY(tb->dirty);
}
if (from->unit[i].objRCoeff.x != to->unit[i].objRCoeff.x ||
from->unit[i].objRCoeff.y != to->unit[i].objRCoeff.y ||
from->unit[i].objRCoeff.z != to->unit[i].objRCoeff.z ||
from->unit[i].objRCoeff.w != to->unit[i].objRCoeff.w) {
GLfloat f[4];
f[0] = to->unit[i].objRCoeff.x;
f[1] = to->unit[i].objRCoeff.y;
f[2] = to->unit[i].objRCoeff.z;
f[3] = to->unit[i].objRCoeff.w;
diff_api.TexGenfv (GL_R, GL_OBJECT_PLANE, (const GLfloat *) f);
FILLDIRTY(tb->objGen[i]);
FILLDIRTY(tb->dirty);
}
if (from->unit[i].objQCoeff.x != to->unit[i].objQCoeff.x ||
from->unit[i].objQCoeff.y != to->unit[i].objQCoeff.y ||
from->unit[i].objQCoeff.z != to->unit[i].objQCoeff.z ||
from->unit[i].objQCoeff.w != to->unit[i].objQCoeff.w) {
GLfloat f[4];
f[0] = to->unit[i].objQCoeff.x;
f[1] = to->unit[i].objQCoeff.y;
f[2] = to->unit[i].objQCoeff.z;
f[3] = to->unit[i].objQCoeff.w;
diff_api.TexGenfv (GL_Q, GL_OBJECT_PLANE, (const GLfloat *) f);
FILLDIRTY(tb->objGen[i]);
FILLDIRTY(tb->dirty);
}
CLEARDIRTY(tb->objGen[i], nbitID);
}
if (CHECKDIRTY(tb->eyeGen[i], bitID))
{
if (activeUnit != i) {
diff_api.ActiveTextureARB( i + GL_TEXTURE0_ARB );
activeUnit = i;
}
diff_api.MatrixMode(GL_MODELVIEW);
diff_api.PushMatrix();
diff_api.LoadIdentity();
if (from->unit[i].eyeSCoeff.x != to->unit[i].eyeSCoeff.x ||
from->unit[i].eyeSCoeff.y != to->unit[i].eyeSCoeff.y ||
from->unit[i].eyeSCoeff.z != to->unit[i].eyeSCoeff.z ||
from->unit[i].eyeSCoeff.w != to->unit[i].eyeSCoeff.w) {
GLfloat f[4];
f[0] = to->unit[i].eyeSCoeff.x;
f[1] = to->unit[i].eyeSCoeff.y;
f[2] = to->unit[i].eyeSCoeff.z;
f[3] = to->unit[i].eyeSCoeff.w;
diff_api.TexGenfv (GL_S, GL_EYE_PLANE, (const GLfloat *) f);
FILLDIRTY(tb->eyeGen[i]);
FILLDIRTY(tb->dirty);
}
if (from->unit[i].eyeTCoeff.x != to->unit[i].eyeTCoeff.x ||
from->unit[i].eyeTCoeff.y != to->unit[i].eyeTCoeff.y ||
from->unit[i].eyeTCoeff.z != to->unit[i].eyeTCoeff.z ||
from->unit[i].eyeTCoeff.w != to->unit[i].eyeTCoeff.w) {
GLfloat f[4];
f[0] = to->unit[i].eyeTCoeff.x;
f[1] = to->unit[i].eyeTCoeff.y;
f[2] = to->unit[i].eyeTCoeff.z;
f[3] = to->unit[i].eyeTCoeff.w;
diff_api.TexGenfv (GL_T, GL_EYE_PLANE, (const GLfloat *) f);
FILLDIRTY(tb->eyeGen[i]);
FILLDIRTY(tb->dirty);
}
if (from->unit[i].eyeRCoeff.x != to->unit[i].eyeRCoeff.x ||
from->unit[i].eyeRCoeff.y != to->unit[i].eyeRCoeff.y ||
from->unit[i].eyeRCoeff.z != to->unit[i].eyeRCoeff.z ||
from->unit[i].eyeRCoeff.w != to->unit[i].eyeRCoeff.w) {
GLfloat f[4];
f[0] = to->unit[i].eyeRCoeff.x;
f[1] = to->unit[i].eyeRCoeff.y;
f[2] = to->unit[i].eyeRCoeff.z;
f[3] = to->unit[i].eyeRCoeff.w;
diff_api.TexGenfv (GL_R, GL_EYE_PLANE, (const GLfloat *) f);
FILLDIRTY(tb->eyeGen[i]);
FILLDIRTY(tb->dirty);
}
if (from->unit[i].eyeQCoeff.x != to->unit[i].eyeQCoeff.x ||
from->unit[i].eyeQCoeff.y != to->unit[i].eyeQCoeff.y ||
from->unit[i].eyeQCoeff.z != to->unit[i].eyeQCoeff.z ||
from->unit[i].eyeQCoeff.w != to->unit[i].eyeQCoeff.w) {
GLfloat f[4];
f[0] = to->unit[i].eyeQCoeff.x;
f[1] = to->unit[i].eyeQCoeff.y;
f[2] = to->unit[i].eyeQCoeff.z;
f[3] = to->unit[i].eyeQCoeff.w;
diff_api.TexGenfv (GL_Q, GL_EYE_PLANE, (const GLfloat *) f);
FILLDIRTY(tb->eyeGen[i]);
FILLDIRTY(tb->dirty);
}
diff_api.PopMatrix();
CLEARDIRTY(tb->eyeGen[i], nbitID);
}
if (CHECKDIRTY(tb->genMode[i], bitID))
{
if (activeUnit != i) {
diff_api.ActiveTextureARB( i + GL_TEXTURE0_ARB );
activeUnit = i;
}
if (from->unit[i].gen.s != to->unit[i].gen.s ||
from->unit[i].gen.t != to->unit[i].gen.t ||
from->unit[i].gen.r != to->unit[i].gen.r ||
from->unit[i].gen.q != to->unit[i].gen.q)
{
diff_api.TexGeni (GL_S, GL_TEXTURE_GEN_MODE, to->unit[i].gen.s);
diff_api.TexGeni (GL_T, GL_TEXTURE_GEN_MODE, to->unit[i].gen.t);
diff_api.TexGeni (GL_R, GL_TEXTURE_GEN_MODE, to->unit[i].gen.r);
diff_api.TexGeni (GL_Q, GL_TEXTURE_GEN_MODE, to->unit[i].gen.q);
FILLDIRTY(tb->genMode[i]);
FILLDIRTY(tb->dirty);
}
CLEARDIRTY(tb->genMode[i], nbitID);
}
CLEARDIRTY(tb->dirty, nbitID);
/* Texture enviroment */
if (CHECKDIRTY(tb->envBit[i], bitID))
{
if (activeUnit != i) {
diff_api.ActiveTextureARB( i + GL_TEXTURE0_ARB );
activeUnit = i;
}
if (from->unit[i].envMode != to->unit[i].envMode)
{
diff_api.TexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, to->unit[i].envMode);
FILLDIRTY(tb->envBit[i]);
FILLDIRTY(tb->dirty);
}
if (from->unit[i].envColor.r != to->unit[i].envColor.r ||
from->unit[i].envColor.g != to->unit[i].envColor.g ||
from->unit[i].envColor.b != to->unit[i].envColor.b ||
from->unit[i].envColor.a != to->unit[i].envColor.a)
{
GLfloat f[4];
f[0] = to->unit[i].envColor.r;
f[1] = to->unit[i].envColor.g;
f[2] = to->unit[i].envColor.b;
f[3] = to->unit[i].envColor.a;
diff_api.TexEnvfv (GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, (const GLfloat *) f);
FILLDIRTY(tb->envBit[i]);
FILLDIRTY(tb->dirty);
}
if (from->unit[i].combineModeRGB != to->unit[i].combineModeRGB)
{
diff_api.TexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, to->unit[i].combineModeRGB);
FILLDIRTY(tb->envBit[i]);
FILLDIRTY(tb->dirty);
}
if (from->unit[i].combineModeA != to->unit[i].combineModeA)
{
diff_api.TexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, to->unit[i].combineModeA);
FILLDIRTY(tb->envBit[i]);
FILLDIRTY(tb->dirty);
}
if (from->unit[i].combineSourceRGB[0] != to->unit[i].combineSourceRGB[0])
{
diff_api.TexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, to->unit[i].combineSourceRGB[0]);
FILLDIRTY(tb->envBit[i]);
FILLDIRTY(tb->dirty);
}
if (from->unit[i].combineSourceRGB[1] != to->unit[i].combineSourceRGB[1])
{
diff_api.TexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, to->unit[i].combineSourceRGB[1]);
FILLDIRTY(tb->envBit[i]);
FILLDIRTY(tb->dirty);
}
if (from->unit[i].combineSourceRGB[2] != to->unit[i].combineSourceRGB[2])
{
diff_api.TexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB, to->unit[i].combineSourceRGB[2]);
FILLDIRTY(tb->envBit[i]);
FILLDIRTY(tb->dirty);
}
if (from->unit[i].combineSourceA[0] != to->unit[i].combineSourceA[0])
{
diff_api.TexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, to->unit[i].combineSourceA[0]);
FILLDIRTY(tb->envBit[i]);
FILLDIRTY(tb->dirty);
}
if (from->unit[i].combineSourceA[1] != to->unit[i].combineSourceA[1])
{
diff_api.TexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_ARB, to->unit[i].combineSourceA[1]);
FILLDIRTY(tb->envBit[i]);
FILLDIRTY(tb->dirty);
}
if (from->unit[i].combineSourceA[2] != to->unit[i].combineSourceA[2])
{
diff_api.TexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_ALPHA_ARB, to->unit[i].combineSourceA[2]);
FILLDIRTY(tb->envBit[i]);
FILLDIRTY(tb->dirty);
}
if (from->unit[i].combineOperandRGB[0] != to->unit[i].combineOperandRGB[0])
{
diff_api.TexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, to->unit[i].combineOperandRGB[0]);
FILLDIRTY(tb->envBit[i]);
FILLDIRTY(tb->dirty);
}
if (from->unit[i].combineOperandRGB[1] != to->unit[i].combineOperandRGB[1])
{
diff_api.TexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, to->unit[i].combineOperandRGB[1]);
FILLDIRTY(tb->envBit[i]);
FILLDIRTY(tb->dirty);
}
if (from->unit[i].combineOperandRGB[2] != to->unit[i].combineOperandRGB[2])
{
diff_api.TexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_ARB, to->unit[i].combineOperandRGB[2]);
FILLDIRTY(tb->envBit[i]);
FILLDIRTY(tb->dirty);
}
if (from->unit[i].combineOperandA[0] != to->unit[i].combineOperandA[0])
{
diff_api.TexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, to->unit[i].combineOperandA[0]);
FILLDIRTY(tb->envBit[i]);
FILLDIRTY(tb->dirty);
}
if (from->unit[i].combineOperandA[1] != to->unit[i].combineOperandA[1])
{
diff_api.TexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_ARB, to->unit[i].combineOperandA[1]);
FILLDIRTY(tb->envBit[i]);
FILLDIRTY(tb->dirty);
}
if (from->unit[i].combineOperandA[2] != to->unit[i].combineOperandA[2])
{
diff_api.TexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_ALPHA_ARB, to->unit[i].combineOperandA[2]);
FILLDIRTY(tb->envBit[i]);
FILLDIRTY(tb->dirty);
}
if (from->unit[i].combineScaleRGB != to->unit[i].combineScaleRGB)
{
diff_api.TexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, to->unit[i].combineScaleRGB);
FILLDIRTY(tb->envBit[i]);
FILLDIRTY(tb->dirty);
}
if (from->unit[i].combineScaleA != to->unit[i].combineScaleA)
{
diff_api.TexEnvf(GL_TEXTURE_ENV, GL_ALPHA_SCALE, to->unit[i].combineScaleA);
FILLDIRTY(tb->envBit[i]);
FILLDIRTY(tb->dirty);
}
CLEARDIRTY(tb->envBit[i], nbitID);
}
}
/* Resend texture images */
if (toCtx->texture.bResyncNeeded)
{
toCtx->texture.bResyncNeeded = GL_FALSE;
crStateDiffAllTextureObjects(toCtx, bitID, GL_TRUE);
}
/* After possible fiddling put them back now */
if (activeUnit != toCtx->texture.curTextureUnit) {
diff_api.ActiveTextureARB( toCtx->texture.curTextureUnit + GL_TEXTURE0_ARB );
}
diff_api.MatrixMode(toCtx->transform.matrixMode);
}
/*
* Check the dirty bits for the specified texture on a given unit to
* determine if any of its images are dirty.
* Return: 1 -- dirty, 0 -- clean
*/
int crStateTextureCheckDirtyImages(CRContext *from, CRContext *to, GLenum target, int textureUnit)
{
CRContext *g = GetCurrentContext();
CRTextureState *tsto;
CRbitvalue *bitID;
CRTextureObj *tobj = NULL;
int maxLevel = 0, i;
int face, numFaces;
CRASSERT(to);
CRASSERT(from);
tsto = &(to->texture);
bitID = from->bitid;
CRASSERT(tsto);
switch(target)
{
case GL_TEXTURE_1D:
tobj = tsto->unit[textureUnit].currentTexture1D;
maxLevel = tsto->maxLevel;
break;
case GL_TEXTURE_2D:
tobj = tsto->unit[textureUnit].currentTexture2D;
maxLevel = tsto->maxLevel;
break;
#ifdef CR_OPENGL_VERSION_1_2
case GL_TEXTURE_3D:
tobj = tsto->unit[textureUnit].currentTexture3D;
maxLevel = tsto->max3DLevel;
break;
#endif
#ifdef CR_ARB_texture_cube_map
case GL_TEXTURE_CUBE_MAP:
if (g->extensions.ARB_texture_cube_map) {
tobj = tsto->unit[textureUnit].currentTextureCubeMap;
maxLevel = tsto->maxCubeMapLevel;
}
break;
#endif
#ifdef CR_NV_texture_rectangle
case GL_TEXTURE_RECTANGLE_NV:
if (g->extensions.NV_texture_rectangle) {
tobj = tsto->unit[textureUnit].currentTextureRect;
maxLevel = 1;
}
break;
#endif
default:
crError("Bad texture target in crStateTextureCheckDirtyImages()");
return 0;
}
if (!tobj)
{
return 0;
}
numFaces = (target == GL_TEXTURE_CUBE_MAP) ? 6 : 1;
for (face = 0; face < numFaces; face++) {
for (i = 0; i < maxLevel; i++) {
if (CHECKDIRTY(tobj->level[face][i].dirty, bitID))
return 1;
}
}
return 0;
}
/*
* Do texture state differencing for the given texture object.
*/
void
crStateTextureObjectDiff(CRContext *fromCtx,
const CRbitvalue *bitID, const CRbitvalue *nbitID,
CRTextureObj *tobj, GLboolean alwaysDirty)
{
CRTextureState *from = &(fromCtx->texture);
glAble able[2];
int u = 0; /* always use texture unit 0 for diff'ing */
able[0] = diff_api.Disable;
able[1] = diff_api.Enable;
#if 0
/* XXX disabling this code fixed Wes Bethel's problem with missing/white
* textures. Setting the active texture unit here can screw up the
* current texture object bindings.
*/
/* Set active texture unit, and bind this texture object */
if (from->curTextureUnit != u) {
diff_api.ActiveTextureARB( u + GL_TEXTURE0_ARB );
from->curTextureUnit = u;
}
#endif
diff_api.BindTexture( tobj->target, tobj->name );
if (alwaysDirty || CHECKDIRTY(tobj->paramsBit[u], bitID))
{
GLfloat f[4];
f[0] = tobj->borderColor.r;
f[1] = tobj->borderColor.g;
f[2] = tobj->borderColor.b;
f[3] = tobj->borderColor.a;
diff_api.TexParameteri(tobj->target, GL_TEXTURE_BASE_LEVEL, tobj->baseLevel);
diff_api.TexParameteri(tobj->target, GL_TEXTURE_MAX_LEVEL, tobj->maxLevel);
diff_api.TexParameteri(tobj->target, GL_TEXTURE_MIN_FILTER, tobj->minFilter);
diff_api.TexParameteri(tobj->target, GL_TEXTURE_MAG_FILTER, tobj->magFilter);
diff_api.TexParameteri(tobj->target, GL_TEXTURE_WRAP_S, tobj->wrapS);
diff_api.TexParameteri(tobj->target, GL_TEXTURE_WRAP_T, tobj->wrapT);
#ifdef CR_OPENGL_VERSION_1_2
diff_api.TexParameteri(tobj->target, GL_TEXTURE_WRAP_R, tobj->wrapR);
diff_api.TexParameterf(tobj->target, GL_TEXTURE_PRIORITY, tobj->priority);
#endif
diff_api.TexParameterfv(tobj->target, GL_TEXTURE_BORDER_COLOR, (const GLfloat *) f);
#ifdef CR_EXT_texture_filter_anisotropic
if (fromCtx->extensions.EXT_texture_filter_anisotropic) {
diff_api.TexParameterf(tobj->target, GL_TEXTURE_MAX_ANISOTROPY_EXT, tobj->maxAnisotropy);
}
#endif
#ifdef CR_ARB_depth_texture
if (fromCtx->extensions.ARB_depth_texture)
diff_api.TexParameteri(tobj->target, GL_DEPTH_TEXTURE_MODE_ARB, tobj->depthMode);
#endif
#ifdef CR_ARB_shadow
if (fromCtx->extensions.ARB_shadow) {
diff_api.TexParameteri(tobj->target, GL_TEXTURE_COMPARE_MODE_ARB, tobj->compareMode);
diff_api.TexParameteri(tobj->target, GL_TEXTURE_COMPARE_FUNC_ARB, tobj->compareFunc);
}
#endif
#ifdef CR_ARB_shadow_ambient
if (fromCtx->extensions.ARB_shadow_ambient) {
diff_api.TexParameterf(tobj->target, GL_TEXTURE_COMPARE_FAIL_VALUE_ARB, tobj->compareFailValue);
}
#endif
#ifdef CR_SGIS_generate_mipmap
if (fromCtx->extensions.SGIS_generate_mipmap) {
diff_api.TexParameteri(tobj->target, GL_GENERATE_MIPMAP_SGIS, tobj->generateMipmap);
}
#endif
if (!alwaysDirty)
CLEARDIRTY(tobj->paramsBit[u], nbitID);
}
/* now, if the texture images are dirty */
if (alwaysDirty || CHECKDIRTY(tobj->imageBit, bitID))
{
int lvl;
int face;
switch (tobj->target)
{
case GL_TEXTURE_1D:
for (lvl = 0; lvl <= from->maxLevel; lvl++)
{
CRTextureLevel *tl = &(tobj->level[0][lvl]);
if (alwaysDirty || CHECKDIRTY(tl->dirty, bitID))
{
if (tl->generateMipmap) {
diff_api.TexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP_SGIS, 1);
}
if (tl->compressed) {
diff_api.CompressedTexImage1DARB(GL_TEXTURE_1D, lvl,
tl->internalFormat, tl->width,
tl->border, tl->bytes, tl->img);
}
else {
/* alignment must be one */
diff_api.PixelStorei(GL_UNPACK_ROW_LENGTH, 0);
diff_api.PixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
diff_api.PixelStorei(GL_UNPACK_SKIP_ROWS, 0);
diff_api.PixelStorei(GL_UNPACK_ALIGNMENT, 1);
if (tl->generateMipmap) {
diff_api.TexParameteri(GL_TEXTURE_1D, GL_GENERATE_MIPMAP_SGIS, 1);
}
diff_api.TexImage1D(GL_TEXTURE_1D, lvl,
tl->internalFormat,
tl->width, tl->border,
tl->format, tl->type, tl->img);
}
if (!alwaysDirty)
{
CLEARDIRTY(tl->dirty, nbitID);
}
#ifdef CR_STATE_NO_TEXTURE_IMAGE_STORE
else
{
crFree(tl->img);
tl->img = NULL;
}
#endif
}
}
break;
case GL_TEXTURE_2D:
for (lvl = 0; lvl <= from->maxLevel; lvl++)
{
CRTextureLevel *tl = &(tobj->level[0][lvl]);
if (alwaysDirty || CHECKDIRTY(tl->dirty, bitID))
{
if (tl->generateMipmap) {
diff_api.TexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP_SGIS, 1);
}
if (tl->compressed) {
diff_api.CompressedTexImage2DARB(GL_TEXTURE_2D, lvl,
tl->internalFormat, tl->width,
tl->height, tl->border,
tl->bytes, tl->img);
}
else {
/* alignment must be one */
diff_api.PixelStorei(GL_UNPACK_ROW_LENGTH, 0);
diff_api.PixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
diff_api.PixelStorei(GL_UNPACK_SKIP_ROWS, 0);
diff_api.PixelStorei(GL_UNPACK_ALIGNMENT, 1);
diff_api.TexImage2D(GL_TEXTURE_2D, lvl,
tl->internalFormat,
tl->width, tl->height, tl->border,
tl->format, tl->type, tl->img);
}
if (!alwaysDirty)
{
CLEARDIRTY(tl->dirty, nbitID);
}
#ifdef CR_STATE_NO_TEXTURE_IMAGE_STORE
else
{
crFree(tl->img);
tl->img = NULL;
}
#endif
}
}
break;
#ifdef CR_OPENGL_VERSION_1_2
case GL_TEXTURE_3D:
for (lvl = 0; lvl <= from->max3DLevel; lvl++)
{
CRTextureLevel *tl = &(tobj->level[0][lvl]);
if (alwaysDirty || CHECKDIRTY(tl->dirty, bitID))
{
if (tl->generateMipmap) {
diff_api.TexParameteri(GL_TEXTURE_3D, GL_GENERATE_MIPMAP_SGIS, 1);
}
if (tl->compressed) {
diff_api.CompressedTexImage3DARB(GL_TEXTURE_3D, lvl,
tl->internalFormat, tl->width,
tl->height, tl->depth,
tl->border, tl->bytes, tl->img);
}
else {
/* alignment must be one */
diff_api.PixelStorei(GL_UNPACK_ROW_LENGTH, 0);
diff_api.PixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
diff_api.PixelStorei(GL_UNPACK_SKIP_ROWS, 0);
diff_api.PixelStorei(GL_UNPACK_ALIGNMENT, 1);
diff_api.TexImage3D(GL_TEXTURE_3D, lvl,
tl->internalFormat,
tl->width, tl->height, tl->depth,
tl->border, tl->format,
tl->type, tl->img);
}
if (!alwaysDirty)
{
CLEARDIRTY(tl->dirty, nbitID);
}
#ifdef CR_STATE_NO_TEXTURE_IMAGE_STORE
else
{
crFree(tl->img);
tl->img = NULL;
}
#endif
}
}
break;
#endif
#ifdef CR_NV_texture_rectangle
case GL_TEXTURE_RECTANGLE_NV:
/* only one level */
for (lvl = 0; lvl <= from->maxRectLevel; lvl++)
{
CRTextureLevel *tl = &(tobj->level[0][lvl]);
if (alwaysDirty || CHECKDIRTY(tl->dirty, bitID))
{
if (tl->compressed) {
diff_api.CompressedTexImage2DARB(GL_TEXTURE_RECTANGLE_NV, lvl,
tl->internalFormat, tl->width,
tl->height, tl->border,
tl->bytes, tl->img);
}
else {
/* alignment must be one */
diff_api.PixelStorei(GL_UNPACK_ROW_LENGTH, 0);
diff_api.PixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
diff_api.PixelStorei(GL_UNPACK_SKIP_ROWS, 0);
diff_api.PixelStorei(GL_UNPACK_ALIGNMENT, 1);
diff_api.TexImage2D(GL_TEXTURE_RECTANGLE_NV, lvl,
tl->internalFormat,
tl->width, tl->height, tl->border,
tl->format, tl->type, tl->img);
}
if (!alwaysDirty)
{
CLEARDIRTY(tl->dirty, nbitID);
}
#ifdef CR_STATE_NO_TEXTURE_IMAGE_STORE
else
{
crFree(tl->img);
tl->img = NULL;
}
#endif
}
}
break;
#endif
#ifdef CR_ARB_texture_cube_map
case GL_TEXTURE_CUBE_MAP_ARB:
for (face = 0; face < 6; face++)
{
const GLenum target = GL_TEXTURE_CUBE_MAP_POSITIVE_X + face;
for (lvl = 0; lvl <= from->maxCubeMapLevel; lvl++)
{
CRTextureLevel *tl = &(tobj->level[face][lvl]);
if (alwaysDirty || CHECKDIRTY(tl->dirty, bitID))
{
if (tl->generateMipmap) {
diff_api.TexParameteri(GL_TEXTURE_CUBE_MAP_ARB,
GL_GENERATE_MIPMAP_SGIS, 1);
}
if (tl->compressed) {
diff_api.CompressedTexImage2DARB(target,
lvl, tl->internalFormat,
tl->width, tl->height,
tl->border, tl->bytes, tl->img);
}
else {
/* alignment must be one */
diff_api.PixelStorei(GL_UNPACK_ROW_LENGTH, 0);
diff_api.PixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
diff_api.PixelStorei(GL_UNPACK_SKIP_ROWS, 0);
diff_api.PixelStorei(GL_UNPACK_ALIGNMENT, 1);
diff_api.TexImage2D(target, lvl,
tl->internalFormat,
tl->width, tl->height, tl->border,
tl->format, tl->type, tl->img);
}
if (!alwaysDirty)
{
CLEARDIRTY(tl->dirty, nbitID);
}
#ifdef CR_STATE_NO_TEXTURE_IMAGE_STORE
else
{
crFree(tl->img);
tl->img = NULL;
}
#endif
}
} /* for lvl */
} /* for face */
break;
#endif
default:
UNIMPLEMENTED();
} /* switch */
} /* if (CHECKDIRTY(tobj->imageBit, bitID)) */
}
void
crStateTextureDiff( CRTextureBits *tb, CRbitvalue *bitID,
CRContext *fromCtx, CRContext *toCtx )
{
CRTextureState *from = &(fromCtx->texture);
CRTextureState *to = &(toCtx->texture);
unsigned int u, t, j;
glAble able[2];
CRbitvalue nbitID[CR_MAX_BITARRAY];
const GLboolean haveFragProg = fromCtx->extensions.ARB_fragment_program || fromCtx->extensions.NV_fragment_program;
for (j=0;j<CR_MAX_BITARRAY;j++)
nbitID[j] = ~bitID[j];
able[0] = diff_api.Disable;
able[1] = diff_api.Enable;
/* loop over texture units */
for (u = 0; u < fromCtx->limits.maxTextureUnits; u++)
{
CRTextureObj **fromBinding = NULL;
CRTextureObj *tobj;
/* take care of enables/disables */
if (CHECKDIRTY(tb->enable[u], bitID))
{
/* Activate texture unit u if needed */
if (fromCtx->texture.curTextureUnit != u) {
diff_api.ActiveTextureARB( GL_TEXTURE0_ARB + u);
fromCtx->texture.curTextureUnit = u;
}
if (from->unit[u].enabled1D != to->unit[u].enabled1D)
{
able[to->unit[u].enabled1D](GL_TEXTURE_1D);
from->unit[u].enabled1D = to->unit[u].enabled1D;
}
if (from->unit[u].enabled2D != to->unit[u].enabled2D)
{
able[to->unit[u].enabled2D](GL_TEXTURE_2D);
from->unit[u].enabled2D = to->unit[u].enabled2D;
}
#ifdef CR_OPENGL_VERSION_1_2
if (from->unit[u].enabled3D != to->unit[u].enabled3D)
{
able[to->unit[u].enabled3D](GL_TEXTURE_3D);
from->unit[u].enabled3D = to->unit[u].enabled3D;
}
#endif
#ifdef CR_ARB_texture_cube_map
if (fromCtx->extensions.ARB_texture_cube_map &&
from->unit[u].enabledCubeMap != to->unit[u].enabledCubeMap)
{
able[to->unit[u].enabledCubeMap](GL_TEXTURE_CUBE_MAP_ARB);
from->unit[u].enabledCubeMap = to->unit[u].enabledCubeMap;
}
#endif
#ifdef CR_NV_texture_rectangle
if (fromCtx->extensions.NV_texture_rectangle &&
from->unit[u].enabledRect != to->unit[u].enabledRect)
{
able[to->unit[u].enabledRect](GL_TEXTURE_RECTANGLE_NV);
from->unit[u].enabledRect = to->unit[u].enabledRect;
}
#endif
/* texgen enables */
if (from->unit[u].textureGen.s != to->unit[u].textureGen.s ||
from->unit[u].textureGen.t != to->unit[u].textureGen.t ||
from->unit[u].textureGen.r != to->unit[u].textureGen.r ||
from->unit[u].textureGen.q != to->unit[u].textureGen.q)
{
able[to->unit[u].textureGen.s](GL_TEXTURE_GEN_S);
able[to->unit[u].textureGen.t](GL_TEXTURE_GEN_T);
able[to->unit[u].textureGen.r](GL_TEXTURE_GEN_R);
able[to->unit[u].textureGen.q](GL_TEXTURE_GEN_Q);
from->unit[u].textureGen = to->unit[u].textureGen;
}
CLEARDIRTY(tb->enable[u], nbitID);
}
/* Texgen coefficients */
if (CHECKDIRTY(tb->objGen[u], bitID))
{
if (fromCtx->texture.curTextureUnit != u) {
diff_api.ActiveTextureARB( u + GL_TEXTURE0_ARB );
fromCtx->texture.curTextureUnit = u;
}
if (from->unit[u].objSCoeff.x != to->unit[u].objSCoeff.x ||
from->unit[u].objSCoeff.y != to->unit[u].objSCoeff.y ||
from->unit[u].objSCoeff.z != to->unit[u].objSCoeff.z ||
from->unit[u].objSCoeff.w != to->unit[u].objSCoeff.w)
{
GLfloat f[4];
f[0] = to->unit[u].objSCoeff.x;
f[1] = to->unit[u].objSCoeff.y;
f[2] = to->unit[u].objSCoeff.z;
f[3] = to->unit[u].objSCoeff.w;
diff_api.TexGenfv (GL_S, GL_OBJECT_PLANE, (const GLfloat *) f);
from->unit[u].objSCoeff = to->unit[u].objSCoeff;
}
if (from->unit[u].objTCoeff.x != to->unit[u].objTCoeff.x ||
from->unit[u].objTCoeff.y != to->unit[u].objTCoeff.y ||
from->unit[u].objTCoeff.z != to->unit[u].objTCoeff.z ||
from->unit[u].objTCoeff.w != to->unit[u].objTCoeff.w)
{
GLfloat f[4];
f[0] = to->unit[u].objTCoeff.x;
f[1] = to->unit[u].objTCoeff.y;
f[2] = to->unit[u].objTCoeff.z;
f[3] = to->unit[u].objTCoeff.w;
diff_api.TexGenfv (GL_T, GL_OBJECT_PLANE, (const GLfloat *) f);
from->unit[u].objTCoeff = to->unit[u].objTCoeff;
}
if (from->unit[u].objRCoeff.x != to->unit[u].objRCoeff.x ||
from->unit[u].objRCoeff.y != to->unit[u].objRCoeff.y ||
from->unit[u].objRCoeff.z != to->unit[u].objRCoeff.z ||
from->unit[u].objRCoeff.w != to->unit[u].objRCoeff.w)
{
GLfloat f[4];
f[0] = to->unit[u].objRCoeff.x;
f[1] = to->unit[u].objRCoeff.y;
f[2] = to->unit[u].objRCoeff.z;
f[3] = to->unit[u].objRCoeff.w;
diff_api.TexGenfv (GL_R, GL_OBJECT_PLANE, (const GLfloat *) f);
from->unit[u].objRCoeff = to->unit[u].objRCoeff;
}
if (from->unit[u].objQCoeff.x != to->unit[u].objQCoeff.x ||
from->unit[u].objQCoeff.y != to->unit[u].objQCoeff.y ||
from->unit[u].objQCoeff.z != to->unit[u].objQCoeff.z ||
from->unit[u].objQCoeff.w != to->unit[u].objQCoeff.w)
{
GLfloat f[4];
f[0] = to->unit[u].objQCoeff.x;
f[1] = to->unit[u].objQCoeff.y;
f[2] = to->unit[u].objQCoeff.z;
f[3] = to->unit[u].objQCoeff.w;
diff_api.TexGenfv (GL_Q, GL_OBJECT_PLANE, (const GLfloat *) f);
from->unit[u].objQCoeff = to->unit[u].objQCoeff;
}
CLEARDIRTY(tb->objGen[u], nbitID);
}
if (CHECKDIRTY(tb->eyeGen[u], bitID))
{
if (fromCtx->texture.curTextureUnit != u) {
diff_api.ActiveTextureARB( u + GL_TEXTURE0_ARB );
fromCtx->texture.curTextureUnit = u;
}
if (fromCtx->transform.matrixMode != GL_MODELVIEW) {
diff_api.MatrixMode(GL_MODELVIEW);
fromCtx->transform.matrixMode = GL_MODELVIEW;
}
diff_api.PushMatrix();
diff_api.LoadIdentity();
if (from->unit[u].eyeSCoeff.x != to->unit[u].eyeSCoeff.x ||
from->unit[u].eyeSCoeff.y != to->unit[u].eyeSCoeff.y ||
from->unit[u].eyeSCoeff.z != to->unit[u].eyeSCoeff.z ||
from->unit[u].eyeSCoeff.w != to->unit[u].eyeSCoeff.w)
{
GLfloat f[4];
f[0] = to->unit[u].eyeSCoeff.x;
f[1] = to->unit[u].eyeSCoeff.y;
f[2] = to->unit[u].eyeSCoeff.z;
f[3] = to->unit[u].eyeSCoeff.w;
diff_api.TexGenfv (GL_S, GL_EYE_PLANE, (const GLfloat *) f);
from->unit[u].eyeSCoeff = to->unit[u].eyeSCoeff;
}
if (from->unit[u].eyeTCoeff.x != to->unit[u].eyeTCoeff.x ||
from->unit[u].eyeTCoeff.y != to->unit[u].eyeTCoeff.y ||
from->unit[u].eyeTCoeff.z != to->unit[u].eyeTCoeff.z ||
from->unit[u].eyeTCoeff.w != to->unit[u].eyeTCoeff.w)
{
GLfloat f[4];
f[0] = to->unit[u].eyeTCoeff.x;
f[1] = to->unit[u].eyeTCoeff.y;
f[2] = to->unit[u].eyeTCoeff.z;
f[3] = to->unit[u].eyeTCoeff.w;
diff_api.TexGenfv (GL_T, GL_EYE_PLANE, (const GLfloat *) f);
from->unit[u].eyeTCoeff = to->unit[u].eyeTCoeff;
}
if (from->unit[u].eyeRCoeff.x != to->unit[u].eyeRCoeff.x ||
from->unit[u].eyeRCoeff.y != to->unit[u].eyeRCoeff.y ||
from->unit[u].eyeRCoeff.z != to->unit[u].eyeRCoeff.z ||
from->unit[u].eyeRCoeff.w != to->unit[u].eyeRCoeff.w)
{
GLfloat f[4];
f[0] = to->unit[u].eyeRCoeff.x;
f[1] = to->unit[u].eyeRCoeff.y;
f[2] = to->unit[u].eyeRCoeff.z;
f[3] = to->unit[u].eyeRCoeff.w;
diff_api.TexGenfv (GL_R, GL_EYE_PLANE, (const GLfloat *) f);
from->unit[u].eyeRCoeff = to->unit[u].eyeRCoeff;
}
if (from->unit[u].eyeQCoeff.x != to->unit[u].eyeQCoeff.x ||
from->unit[u].eyeQCoeff.y != to->unit[u].eyeQCoeff.y ||
from->unit[u].eyeQCoeff.z != to->unit[u].eyeQCoeff.z ||
from->unit[u].eyeQCoeff.w != to->unit[u].eyeQCoeff.w)
{
GLfloat f[4];
f[0] = to->unit[u].eyeQCoeff.x;
f[1] = to->unit[u].eyeQCoeff.y;
f[2] = to->unit[u].eyeQCoeff.z;
f[3] = to->unit[u].eyeQCoeff.w;
diff_api.TexGenfv (GL_Q, GL_EYE_PLANE, (const GLfloat *) f);
from->unit[u].eyeQCoeff = to->unit[u].eyeQCoeff;
}
diff_api.PopMatrix();
CLEARDIRTY(tb->eyeGen[u], nbitID);
}
if (CHECKDIRTY(tb->genMode[u], bitID))
{
if (fromCtx->texture.curTextureUnit != u) {
diff_api.ActiveTextureARB( u + GL_TEXTURE0_ARB );
fromCtx->texture.curTextureUnit = u;
}
if (from->unit[u].gen.s != to->unit[u].gen.s ||
from->unit[u].gen.t != to->unit[u].gen.t ||
from->unit[u].gen.r != to->unit[u].gen.r ||
from->unit[u].gen.q != to->unit[u].gen.q)
{
diff_api.TexGeni (GL_S, GL_TEXTURE_GEN_MODE, to->unit[u].gen.s);
diff_api.TexGeni (GL_T, GL_TEXTURE_GEN_MODE, to->unit[u].gen.t);
diff_api.TexGeni (GL_R, GL_TEXTURE_GEN_MODE, to->unit[u].gen.r);
diff_api.TexGeni (GL_Q, GL_TEXTURE_GEN_MODE, to->unit[u].gen.q);
from->unit[u].gen = to->unit[u].gen;
}
CLEARDIRTY(tb->genMode[u], nbitID);
}
/* Texture enviroment */
if (CHECKDIRTY(tb->envBit[u], bitID))
{
if (from->unit[u].envMode != to->unit[u].envMode)
{
diff_api.TexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, to->unit[u].envMode);
from->unit[u].envMode = to->unit[u].envMode;
}
if (from->unit[u].envColor.r != to->unit[u].envColor.r ||
from->unit[u].envColor.g != to->unit[u].envColor.g ||
from->unit[u].envColor.b != to->unit[u].envColor.b ||
from->unit[u].envColor.a != to->unit[u].envColor.a)
{
GLfloat f[4];
f[0] = to->unit[u].envColor.r;
f[1] = to->unit[u].envColor.g;
f[2] = to->unit[u].envColor.b;
f[3] = to->unit[u].envColor.a;
diff_api.TexEnvfv (GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, (const GLfloat *) f);
from->unit[u].envColor = to->unit[u].envColor;
}
#ifdef CR_ARB_texture_env_combine
if (from->unit[u].combineModeRGB != to->unit[u].combineModeRGB)
{
diff_api.TexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, to->unit[u].combineModeRGB);
from->unit[u].combineModeRGB = to->unit[u].combineModeRGB;
}
if (from->unit[u].combineModeA != to->unit[u].combineModeA)
{
diff_api.TexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, to->unit[u].combineModeA);
from->unit[u].combineModeA = to->unit[u].combineModeA;
}
if (from->unit[u].combineSourceRGB[0] != to->unit[u].combineSourceRGB[0])
{
diff_api.TexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, to->unit[u].combineSourceRGB[0]);
from->unit[u].combineSourceRGB[0] = to->unit[u].combineSourceRGB[0];
}
if (from->unit[u].combineSourceRGB[1] != to->unit[u].combineSourceRGB[1])
{
diff_api.TexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, to->unit[u].combineSourceRGB[1]);
from->unit[u].combineSourceRGB[1] = to->unit[u].combineSourceRGB[1];
}
if (from->unit[u].combineSourceRGB[2] != to->unit[u].combineSourceRGB[2])
{
diff_api.TexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB, to->unit[u].combineSourceRGB[2]);
from->unit[u].combineSourceRGB[2] = to->unit[u].combineSourceRGB[2];
}
if (from->unit[u].combineSourceA[0] != to->unit[u].combineSourceA[0])
{
diff_api.TexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, to->unit[u].combineSourceA[0]);
from->unit[u].combineSourceA[0] = to->unit[u].combineSourceA[0];
}
if (from->unit[u].combineSourceA[1] != to->unit[u].combineSourceA[1])
{
diff_api.TexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_ARB, to->unit[u].combineSourceA[1]);
from->unit[u].combineSourceA[1] = to->unit[u].combineSourceA[1];
}
if (from->unit[u].combineSourceA[2] != to->unit[u].combineSourceA[2])
{
diff_api.TexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_ALPHA_ARB, to->unit[u].combineSourceA[2]);
from->unit[u].combineSourceA[2] = to->unit[u].combineSourceA[2];
}
if (from->unit[u].combineOperandRGB[0] != to->unit[u].combineOperandRGB[0])
{
diff_api.TexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, to->unit[u].combineOperandRGB[0]);
from->unit[u].combineOperandRGB[0] = to->unit[u].combineOperandRGB[0];
}
if (from->unit[u].combineOperandRGB[1] != to->unit[u].combineOperandRGB[1])
{
diff_api.TexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, to->unit[u].combineOperandRGB[1]);
from->unit[u].combineOperandRGB[1] = to->unit[u].combineOperandRGB[1];
}
if (from->unit[u].combineOperandRGB[2] != to->unit[u].combineOperandRGB[2])
{
diff_api.TexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_ARB, to->unit[u].combineOperandRGB[2]);
from->unit[u].combineOperandRGB[2] = to->unit[u].combineOperandRGB[2];
}
if (from->unit[u].combineOperandA[0] != to->unit[u].combineOperandA[0])
{
diff_api.TexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, to->unit[u].combineOperandA[0]);
from->unit[u].combineOperandA[0] = to->unit[u].combineOperandA[0];
}
if (from->unit[u].combineOperandA[1] != to->unit[u].combineOperandA[1])
{
diff_api.TexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_ARB, to->unit[u].combineOperandA[1]);
from->unit[u].combineOperandA[1] = to->unit[u].combineOperandA[1];
}
if (from->unit[u].combineOperandA[2] != to->unit[u].combineOperandA[2])
{
diff_api.TexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_ALPHA_ARB, to->unit[u].combineOperandA[2]);
from->unit[u].combineOperandA[2] = to->unit[u].combineOperandA[2];
}
if (from->unit[u].combineScaleRGB != to->unit[u].combineScaleRGB)
{
diff_api.TexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, to->unit[u].combineScaleRGB);
from->unit[u].combineScaleRGB = to->unit[u].combineScaleRGB;
}
if (from->unit[u].combineScaleA != to->unit[u].combineScaleA)
{
diff_api.TexEnvf(GL_TEXTURE_ENV, GL_ALPHA_SCALE, to->unit[u].combineScaleA);
from->unit[u].combineScaleA = to->unit[u].combineScaleA;
}
#endif
#if CR_EXT_texture_lod_bias
if (from->unit[u].lodBias != to->unit[u].lodBias)
{
diff_api.TexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT, GL_TEXTURE_LOD_BIAS_EXT, to->unit[u].lodBias);
from->unit[u].lodBias = to->unit[u].lodBias;
}
#endif
CLEARDIRTY(tb->envBit[u], nbitID);
}
/* loop over texture targets */
for (t = 0; t < 5; t++)
{
tobj = NULL;
switch (t) {
case 0:
if (to->unit[u].enabled1D || haveFragProg) {
tobj = to->unit[u].currentTexture1D;
fromBinding = &(from->unit[u].currentTexture1D);
}
break;
case 1:
if (to->unit[u].enabled2D || haveFragProg) {
tobj = to->unit[u].currentTexture2D;
fromBinding = &(from->unit[u].currentTexture2D);
}
break;
#ifdef CR_OPENGL_VERSION_1_2
case 2:
if (to->unit[u].enabled3D || haveFragProg) {
tobj = to->unit[u].currentTexture3D;
fromBinding = &(from->unit[u].currentTexture3D);
}
break;
#endif
#ifdef CR_ARB_texture_cube_map
case 3:
if (fromCtx->extensions.ARB_texture_cube_map &&
(to->unit[u].enabledCubeMap || haveFragProg)) {
tobj = to->unit[u].currentTextureCubeMap;
fromBinding = &(from->unit[u].currentTextureCubeMap);
}
break;
#endif
#ifdef CR_NV_texture_rectangle
case 4:
if (fromCtx->extensions.NV_texture_rectangle &&
(to->unit[u].enabledRect || haveFragProg)) {
tobj = to->unit[u].currentTextureRect;
fromBinding = &(from->unit[u].currentTextureRect);
}
break;
#endif
default:
/* maybe don't support cube maps or rects */
continue;
}
if (!tobj) {
continue; /* with next target */
}
/* Activate texture unit u if needed */
if (fromCtx->texture.curTextureUnit != u) {
diff_api.ActiveTextureARB( GL_TEXTURE0_ARB + u);
fromCtx->texture.curTextureUnit = u;
}
/* bind this texture if needed */
if (CHECKDIRTY(tb->current[u], bitID))
{
if (*fromBinding != tobj)
{
diff_api.BindTexture(tobj->target, tobj->name);
*fromBinding = tobj;
}
}
/* now, if the texture object is dirty */
if (CHECKDIRTY(tobj->dirty, bitID))
{
crStateTextureObjectDiff(fromCtx, bitID, nbitID, tobj, GL_FALSE);
}
CLEARDIRTY(tobj->dirty, nbitID);
} /* loop over targets */
CLEARDIRTY(tb->current[u], nbitID);
} /* loop over units */
/* After possible fiddling with the active unit, put it back now */
if (fromCtx->texture.curTextureUnit != toCtx->texture.curTextureUnit) {
diff_api.ActiveTextureARB( toCtx->texture.curTextureUnit + GL_TEXTURE0_ARB );
fromCtx->texture.curTextureUnit = toCtx->texture.curTextureUnit;
}
if (fromCtx->transform.matrixMode != toCtx->transform.matrixMode) {
diff_api.MatrixMode(toCtx->transform.matrixMode);
fromCtx->transform.matrixMode = toCtx->transform.matrixMode;
}
CLEARDIRTY(tb->dirty, nbitID);
}
struct callback_info
{
CRbitvalue *bitID, *nbitID;
CRContext *g;
GLboolean bForceUpdate;
};
/* Called by crHashtableWalk() below */
static void
DiffTextureObjectCallback( unsigned long key, void *texObj , void *cbData)
{
struct callback_info *info = (struct callback_info *) cbData;
CRTextureObj *tobj = (CRTextureObj *) texObj;
/*
printf(" Checking %d 0x%x bitid=0x%x\n",tobj->name, tobj->dirty[0], info->bitID[0]);
*/
if (info->bForceUpdate || CHECKDIRTY(tobj->dirty, info->bitID)) {
/*
printf(" Found Dirty! %d\n", tobj->name);
*/
crStateTextureObjectDiff(info->g, info->bitID, info->nbitID, tobj, info->bForceUpdate);
CLEARDIRTY(tobj->dirty, info->nbitID);
}
}
/*
* This isn't used right now, but will be used in the future to fix some
* potential display list problems. Specifically, if glBindTexture is
* in a display list, we have to be sure that all outstanding texture object
* updates are resolved before the list is called. If we don't, we may
* wind up binding texture objects that are stale.
*/
void
crStateDiffAllTextureObjects( CRContext *g, CRbitvalue *bitID, GLboolean bForceUpdate )
{
CRbitvalue nbitID[CR_MAX_BITARRAY];
struct callback_info info;
int j;
int origUnit, orig1D, orig2D, orig3D, origCube, origRect;
for (j = 0; j < CR_MAX_BITARRAY; j++)
nbitID[j] = ~bitID[j];
info.bitID = bitID;
info.nbitID = nbitID;
info.g = g;
info.bForceUpdate = bForceUpdate;
/* save current texture bindings */
origUnit = g->texture.curTextureUnit;
orig1D = g->texture.unit[0].currentTexture1D->name;
orig2D = g->texture.unit[0].currentTexture2D->name;
orig3D = g->texture.unit[0].currentTexture3D->name;
#ifdef CR_ARB_texture_cube_map
origCube = g->texture.unit[0].currentTextureCubeMap->name;
#endif
#ifdef CR_NV_texture_rectangle
origRect = g->texture.unit[0].currentTextureRect->name;
#endif
/* use texture unit 0 for updates */
diff_api.ActiveTextureARB(GL_TEXTURE0_ARB);
/* diff all the textures */
crHashtableWalk(g->shared->textureTable, DiffTextureObjectCallback, (void *) &info);
/* default ones */
crStateTextureObjectDiff(g, bitID, nbitID, &g->texture.base1D, GL_TRUE);
crStateTextureObjectDiff(g, bitID, nbitID, &g->texture.base2D, GL_TRUE);
crStateTextureObjectDiff(g, bitID, nbitID, &g->texture.base3D, GL_TRUE);
crStateTextureObjectDiff(g, bitID, nbitID, &g->texture.proxy1D, GL_TRUE);
crStateTextureObjectDiff(g, bitID, nbitID, &g->texture.proxy2D, GL_TRUE);
crStateTextureObjectDiff(g, bitID, nbitID, &g->texture.proxy3D, GL_TRUE);
#ifdef CR_ARB_texture_cube_map
crStateTextureObjectDiff(g, bitID, nbitID, &g->texture.baseCubeMap, GL_TRUE);
crStateTextureObjectDiff(g, bitID, nbitID, &g->texture.proxyCubeMap, GL_TRUE);
#endif
#ifdef CR_NV_texture_rectangle
if (g->extensions.NV_texture_rectangle)
{
crStateTextureObjectDiff(g, bitID, nbitID, &g->texture.baseRect, GL_TRUE);
crStateTextureObjectDiff(g, bitID, nbitID, &g->texture.proxyRect, GL_TRUE);
}
#endif
/* restore bindings */
diff_api.ActiveTextureARB(GL_TEXTURE0_ARB + origUnit);
diff_api.BindTexture(GL_TEXTURE_1D, orig1D);
diff_api.BindTexture(GL_TEXTURE_2D, orig2D);
diff_api.BindTexture(GL_TEXTURE_3D, orig3D);
#ifdef CR_ARB_texture_cube_map
diff_api.BindTexture(GL_TEXTURE_CUBE_MAP_ARB, origCube);
#endif
#ifdef CR_NV_texture_rectangle
diff_api.BindTexture(GL_TEXTURE_RECTANGLE_NV, origRect);
#endif
}