summaryrefslogtreecommitdiffstats
path: root/src/VBox/GuestHost/OpenGL/state_tracker/state_texdiff.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/VBox/GuestHost/OpenGL/state_tracker/state_texdiff.c')
-rw-r--r--src/VBox/GuestHost/OpenGL/state_tracker/state_texdiff.c1469
1 files changed, 1469 insertions, 0 deletions
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_texdiff.c b/src/VBox/GuestHost/OpenGL/state_tracker/state_texdiff.c
new file mode 100644
index 00000000..6854334b
--- /dev/null
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_texdiff.c
@@ -0,0 +1,1469 @@
+/* Copyright (c) 2001, Stanford University
+ * All rights reserved
+ *
+ * See the file LICENSE.txt for information on redistributing this software.
+ */
+
+#include "state.h"
+#include "state/cr_statetypes.h"
+#include "state/cr_texture.h"
+#include "cr_hash.h"
+#include "cr_string.h"
+#include "cr_mem.h"
+#include "cr_version.h"
+#include "state_internals.h"
+
+
+#define UNIMPLEMENTED() crStateError(__LINE__,__FILE__,GL_INVALID_OPERATION, "Unimplemented something or other" )
+
+
+#if 0 /* NOT USED??? */
+void crStateTextureObjSwitchCallback( unsigned long key, void *data1, void *data2 )
+{
+ CRTextureObj *tobj = (CRTextureObj *) data1;
+ CRContext *fromCtx = (CRContext *) data2;
+ unsigned int i = 0;
+ unsigned int j = 0;
+ CRbitvalue *bitID = fromCtx->bitid;
+ CRbitvalue nbitID[CR_MAX_BITARRAY];
+
+ for (j=0;j<CR_MAX_BITARRAY;j++)
+ nbitID[j] = ~bitID[j];
+
+ if (!tobj) return;
+
+ FILLDIRTY(tobj->dirty);
+ FILLDIRTY(tobj->imageBit);
+
+ for (i = 0; i < fromCtx->limits.maxTextureUnits; i++)
+ {
+ int j;
+
+ FILLDIRTY(tobj->paramsBit[i]);
+
+ switch (tobj->target)
+ {
+ case GL_TEXTURE_1D:
+ case GL_TEXTURE_2D:
+ for (j = 0; j <= fromCtx->texture.maxLevel; j++)
+ {
+ CRTextureLevel *tl = &(tobj->level[j]);
+ FILLDIRTY(tl->dirty);
+ }
+ break;
+#ifdef CR_OPENGL_VERSION_1_2
+ case GL_TEXTURE_3D:
+#endif
+ for (j = 0; j <= fromCtx->texture.max3DLevel; j++)
+ {
+ CRTextureLevel *tl = &(tobj->level[j]);
+ FILLDIRTY(tl->dirty);
+ }
+ break;
+#ifdef CR_ARB_texture_cube_map
+ case GL_TEXTURE_CUBE_MAP_ARB:
+ for (j = 0; j <= fromCtx->texture.maxCubeMapLevel; j++)
+ {
+ CRTextureLevel *tl;
+ /* Positive X */
+ tl = &(tobj->level[j]);
+ FILLDIRTY(tl->dirty);
+ /* Negative X */
+ tl = &(tobj->negativeXlevel[j]);
+ FILLDIRTY(tl->dirty);
+ /* Positive Y */
+ tl = &(tobj->positiveYlevel[j]);
+ FILLDIRTY(tl->dirty);
+ /* Negative Y */
+ tl = &(tobj->negativeYlevel[j]);
+ FILLDIRTY(tl->dirty);
+ /* Positive Z */
+ tl = &(tobj->positiveZlevel[j]);
+ FILLDIRTY(tl->dirty);
+ /* Negative Z */
+ tl = &(tobj->negativeZlevel[j]);
+ FILLDIRTY(tl->dirty);
+ }
+ 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->hwid != to->unit[i].currentTexture1D->hwid)
+ {
+ diff_api.BindTexture(GL_TEXTURE_1D, crStateGetTextureObjHWID(to->unit[i].currentTexture1D));
+ FILLDIRTY(tb->current[i]);
+ FILLDIRTY(tb->dirty);
+ }
+ if (from->unit[i].currentTexture2D->hwid != to->unit[i].currentTexture2D->hwid)
+ {
+ diff_api.BindTexture(GL_TEXTURE_2D, crStateGetTextureObjHWID(to->unit[i].currentTexture2D));
+ FILLDIRTY(tb->current[i]);
+ FILLDIRTY(tb->dirty);
+ }
+#ifdef CR_OPENGL_VERSION_1_2
+ if (from->unit[i].currentTexture3D->hwid != to->unit[i].currentTexture3D->hwid)
+ {
+ diff_api.BindTexture(GL_TEXTURE_3D, crStateGetTextureObjHWID(to->unit[i].currentTexture3D));
+ 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->hwid != to->unit[i].currentTextureCubeMap->hwid)
+ {
+ diff_api.BindTexture(GL_TEXTURE_CUBE_MAP_ARB, crStateGetTextureObjHWID(to->unit[i].currentTextureCubeMap));
+ FILLDIRTY(tb->current[i]);
+ FILLDIRTY(tb->dirty);
+ }
+#endif
+#ifdef CR_NV_texture_rectangle
+ if (fromCtx->extensions.NV_texture_rectangle &&
+ from->unit[i].currentTextureRect->hwid != to->unit[i].currentTextureRect->hwid)
+ {
+ diff_api.BindTexture(GL_TEXTURE_RECTANGLE_NV, crStateGetTextureObjHWID(to->unit[i].currentTextureRect));
+ FILLDIRTY(tb->current[i]);
+ FILLDIRTY(tb->dirty);
+ }
+#endif
+ CLEARDIRTY(tb->current[i], nbitID);
+ }
+
+ 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->shared->bTexResyncNeeded)
+ {
+ toCtx->shared->bTexResyncNeeded = 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 */
+ GLuint hwid = crStateGetTextureObjHWID(tobj);
+
+ if (!hwid)
+ return;
+
+ 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, hwid);
+
+ 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->width)
+ {
+ 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->width && tl->height)
+ {
+ 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->width && tl->height)
+ {
+ 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->width && tl->height)
+ {
+ 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->width && tl->height)
+ {
+ 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, crStateGetTextureObjHWID(tobj));
+ *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;
+ (void)key;
+
+ /*
+ 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 = crStateGetTextureObjHWID(g->texture.unit[0].currentTexture1D);
+ orig2D = crStateGetTextureObjHWID(g->texture.unit[0].currentTexture2D);
+ orig3D = crStateGetTextureObjHWID(g->texture.unit[0].currentTexture3D);
+#ifdef CR_ARB_texture_cube_map
+ origCube = crStateGetTextureObjHWID(g->texture.unit[0].currentTextureCubeMap);
+#endif
+#ifdef CR_NV_texture_rectangle
+ origRect = crStateGetTextureObjHWID(g->texture.unit[0].currentTextureRect);
+#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 */
+ /* first restore unit 0 bindings the unit 0 is active currently */
+ 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
+ /* now restore the proper active unit */
+ diff_api.ActiveTextureARB(GL_TEXTURE0_ARB + origUnit);
+}