diff options
Diffstat (limited to 'src/VBox/GuestHost/OpenGL/state_tracker/state_texdiff.c')
-rw-r--r-- | src/VBox/GuestHost/OpenGL/state_tracker/state_texdiff.c | 1469 |
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); +} |