/* 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" #ifdef DEBUG_misha #include #endif #define UNUSED(x) ((void) (x)) #define GET_TOBJ(tobj, state, id) \ tobj = (CRTextureObj *) crHashtableSearch(g->shared->textureTable, id); void crStateTextureDestroy(CRContext *ctx) { crStateDeleteTextureObjectData(&ctx->texture.base1D); crStateDeleteTextureObjectData(&ctx->texture.proxy1D); crStateDeleteTextureObjectData(&ctx->texture.base2D); crStateDeleteTextureObjectData(&ctx->texture.proxy2D); #ifdef CR_OPENGL_VERSION_1_2 crStateDeleteTextureObjectData(&ctx->texture.base3D); crStateDeleteTextureObjectData(&ctx->texture.proxy3D); #endif #ifdef CR_ARB_texture_cube_map crStateDeleteTextureObjectData(&ctx->texture.baseCubeMap); crStateDeleteTextureObjectData(&ctx->texture.proxyCubeMap); #endif #ifdef CR_NV_texture_rectangle crStateDeleteTextureObjectData(&ctx->texture.baseRect); crStateDeleteTextureObjectData(&ctx->texture.proxyRect); #endif } void crStateTextureInit(CRContext *ctx) { CRLimitsState *limits = &ctx->limits; CRTextureState *t = &ctx->texture; CRStateBits *sb = GetCurrentBits(); CRTextureBits *tb = &(sb->texture); unsigned int i; unsigned int a; GLvectorf zero_vector = {0.0f, 0.0f, 0.0f, 0.0f}; GLcolorf zero_color = {0.0f, 0.0f, 0.0f, 0.0f}; GLvectorf x_vector = {1.0f, 0.0f, 0.0f, 0.0f}; GLvectorf y_vector = {0.0f, 1.0f, 0.0f, 0.0f}; /* compute max levels from max sizes */ for (i=0, a=limits->maxTextureSize; a; i++, a=a>>1); t->maxLevel = i-1; for (i=0, a=limits->max3DTextureSize; a; i++, a=a>>1); t->max3DLevel = i-1; #ifdef CR_ARB_texture_cube_map for (i=0, a=limits->maxCubeMapTextureSize; a; i++, a=a>>1); t->maxCubeMapLevel = i-1; #endif #ifdef CR_NV_texture_rectangle for (i=0, a=limits->maxRectTextureSize; a; i++, a=a>>1); t->maxRectLevel = i-1; #endif crStateTextureInitTextureObj(ctx, &(t->base1D), 0, GL_TEXTURE_1D); crStateTextureInitTextureObj(ctx, &(t->base2D), 0, GL_TEXTURE_2D); #ifdef CR_OPENGL_VERSION_1_2 crStateTextureInitTextureObj(ctx, &(t->base3D), 0, GL_TEXTURE_3D); #endif #ifdef CR_ARB_texture_cube_map crStateTextureInitTextureObj(ctx, &(t->baseCubeMap), 0, GL_TEXTURE_CUBE_MAP_ARB); #endif #ifdef CR_NV_texture_rectangle crStateTextureInitTextureObj(ctx, &(t->baseRect), 0, GL_TEXTURE_RECTANGLE_NV); #endif crStateTextureInitTextureObj(ctx, &(t->proxy1D), 0, GL_TEXTURE_1D); crStateTextureInitTextureObj(ctx, &(t->proxy2D), 0, GL_TEXTURE_2D); #ifdef CR_OPENGL_VERSION_1_2 crStateTextureInitTextureObj(ctx, &(t->proxy3D), 0, GL_TEXTURE_3D); #endif #ifdef CR_ARB_texture_cube_map crStateTextureInitTextureObj(ctx, &(t->proxyCubeMap), 0, GL_TEXTURE_CUBE_MAP_ARB); #endif #ifdef CR_NV_texture_rectangle crStateTextureInitTextureObj(ctx, &(t->proxyRect), 0, GL_TEXTURE_RECTANGLE_NV); #endif t->curTextureUnit = 0; /* Per-unit initialization */ for (i = 0; i < limits->maxTextureUnits; i++) { t->unit[i].currentTexture1D = &(t->base1D); t->unit[i].currentTexture2D = &(t->base2D); t->unit[i].currentTexture3D = &(t->base3D); #ifdef CR_ARB_texture_cube_map t->unit[i].currentTextureCubeMap = &(t->baseCubeMap); #endif #ifdef CR_NV_texture_rectangle t->unit[i].currentTextureRect = &(t->baseRect); #endif t->unit[i].enabled1D = GL_FALSE; t->unit[i].enabled2D = GL_FALSE; t->unit[i].enabled3D = GL_FALSE; t->unit[i].enabledCubeMap = GL_FALSE; #ifdef CR_NV_texture_rectangle t->unit[i].enabledRect = GL_FALSE; #endif t->unit[i].textureGen.s = GL_FALSE; t->unit[i].textureGen.t = GL_FALSE; t->unit[i].textureGen.r = GL_FALSE; t->unit[i].textureGen.q = GL_FALSE; t->unit[i].gen.s = GL_EYE_LINEAR; t->unit[i].gen.t = GL_EYE_LINEAR; t->unit[i].gen.r = GL_EYE_LINEAR; t->unit[i].gen.q = GL_EYE_LINEAR; t->unit[i].objSCoeff = x_vector; t->unit[i].objTCoeff = y_vector; t->unit[i].objRCoeff = zero_vector; t->unit[i].objQCoeff = zero_vector; t->unit[i].eyeSCoeff = x_vector; t->unit[i].eyeTCoeff = y_vector; t->unit[i].eyeRCoeff = zero_vector; t->unit[i].eyeQCoeff = zero_vector; t->unit[i].envMode = GL_MODULATE; t->unit[i].envColor = zero_color; t->unit[i].combineModeRGB = GL_MODULATE; t->unit[i].combineModeA = GL_MODULATE; t->unit[i].combineSourceRGB[0] = GL_TEXTURE; t->unit[i].combineSourceRGB[1] = GL_PREVIOUS_EXT; t->unit[i].combineSourceRGB[2] = GL_CONSTANT_EXT; t->unit[i].combineSourceA[0] = GL_TEXTURE; t->unit[i].combineSourceA[1] = GL_PREVIOUS_EXT; t->unit[i].combineSourceA[2] = GL_CONSTANT_EXT; t->unit[i].combineOperandRGB[0] = GL_SRC_COLOR; t->unit[i].combineOperandRGB[1] = GL_SRC_COLOR; t->unit[i].combineOperandRGB[2] = GL_SRC_ALPHA; t->unit[i].combineOperandA[0] = GL_SRC_ALPHA; t->unit[i].combineOperandA[1] = GL_SRC_ALPHA; t->unit[i].combineOperandA[2] = GL_SRC_ALPHA; t->unit[i].combineScaleRGB = 1.0F; t->unit[i].combineScaleA = 1.0F; #ifdef CR_EXT_texture_lod_bias t->unit[i].lodBias = 0.0F; #endif RESET(tb->enable[i], ctx->bitid); RESET(tb->current[i], ctx->bitid); RESET(tb->objGen[i], ctx->bitid); RESET(tb->eyeGen[i], ctx->bitid); RESET(tb->genMode[i], ctx->bitid); RESET(tb->envBit[i], ctx->bitid); } RESET(tb->dirty, ctx->bitid); } void crStateTextureInitTextureObj(CRContext *ctx, CRTextureObj *tobj, GLuint name, GLenum target) { const CRTextureState *t = &(ctx->texture); int i, face; tobj->borderColor.r = 0.0f; tobj->borderColor.g = 0.0f; tobj->borderColor.b = 0.0f; tobj->borderColor.a = 0.0f; tobj->minFilter = GL_NEAREST_MIPMAP_LINEAR; tobj->magFilter = GL_LINEAR; tobj->wrapS = GL_REPEAT; tobj->wrapT = GL_REPEAT; #ifdef CR_OPENGL_VERSION_1_2 tobj->wrapR = GL_REPEAT; tobj->priority = 1.0f; tobj->minLod = -1000.0; tobj->maxLod = 1000.0; tobj->baseLevel = 0; tobj->maxLevel = 1000; #endif tobj->target = target; tobj->id = name; tobj->hwid = 0; #ifndef IN_GUEST crStateGetTextureObjHWID(tobj); #endif CRASSERT(t->maxLevel); /* XXX don't always need all six faces */ for (face = 0; face < 6; face++) { /* allocate array of mipmap levels */ CRASSERT(t->maxLevel < CR_MAX_MIPMAP_LEVELS); tobj->level[face] = (CRTextureLevel *) crCalloc(sizeof(CRTextureLevel) * CR_MAX_MIPMAP_LEVELS); if (!tobj->level[face]) return; /* out of memory */ /* init non-zero fields */ for (i = 0; i <= t->maxLevel; i++) { CRTextureLevel *tl = &(tobj->level[face][i]); tl->internalFormat = GL_ONE; tl->format = GL_RGBA; tl->type = GL_UNSIGNED_BYTE; crStateTextureInitTextureFormat( tl, tl->internalFormat ); } } #ifdef CR_EXT_texture_filter_anisotropic tobj->maxAnisotropy = 1.0f; #endif #ifdef CR_ARB_depth_texture tobj->depthMode = GL_LUMINANCE; #endif #ifdef CR_ARB_shadow tobj->compareMode = GL_NONE; tobj->compareFunc = GL_LEQUAL; #endif #ifdef CR_ARB_shadow_ambient tobj->compareFailValue = 0.0; #endif RESET(tobj->dirty, ctx->bitid); RESET(tobj->imageBit, ctx->bitid); for (i = 0; i < CR_MAX_TEXTURE_UNITS; i++) { RESET(tobj->paramsBit[i], ctx->bitid); } CR_STATE_SHAREDOBJ_USAGE_INIT(tobj); CR_STATE_SHAREDOBJ_USAGE_SET(tobj, ctx); } /* ================================================================ * Texture internal formats: */ const CRTextureFormat _texformat_rgba8888 = { 8, /* RedBits */ 8, /* GreenBits */ 8, /* BlueBits */ 8, /* AlphaBits */ 0, /* LuminanceBits */ 0, /* IntensityBits */ 0, /* IndexBits */ }; const CRTextureFormat _texformat_argb8888 = { 8, /* RedBits */ 8, /* GreenBits */ 8, /* BlueBits */ 8, /* AlphaBits */ 0, /* LuminanceBits */ 0, /* IntensityBits */ 0, /* IndexBits */ }; const CRTextureFormat _texformat_rgb888 = { 8, /* RedBits */ 8, /* GreenBits */ 8, /* BlueBits */ 0, /* AlphaBits */ 0, /* LuminanceBits */ 0, /* IntensityBits */ 0, /* IndexBits */ }; const CRTextureFormat _texformat_rgb565 = { 5, /* RedBits */ 6, /* GreenBits */ 5, /* BlueBits */ 0, /* AlphaBits */ 0, /* LuminanceBits */ 0, /* IntensityBits */ 0, /* IndexBits */ }; const CRTextureFormat _texformat_argb4444 = { 4, /* RedBits */ 4, /* GreenBits */ 4, /* BlueBits */ 4, /* AlphaBits */ 0, /* LuminanceBits */ 0, /* IntensityBits */ 0, /* IndexBits */ }; const CRTextureFormat _texformat_argb1555 = { 5, /* RedBits */ 5, /* GreenBits */ 5, /* BlueBits */ 1, /* AlphaBits */ 0, /* LuminanceBits */ 0, /* IntensityBits */ 0, /* IndexBits */ }; const CRTextureFormat _texformat_al88 = { 0, /* RedBits */ 0, /* GreenBits */ 0, /* BlueBits */ 8, /* AlphaBits */ 8, /* LuminanceBits */ 0, /* IntensityBits */ 0, /* IndexBits */ }; const CRTextureFormat _texformat_rgb332 = { 3, /* RedBits */ 3, /* GreenBits */ 2, /* BlueBits */ 0, /* AlphaBits */ 0, /* LuminanceBits */ 0, /* IntensityBits */ 0, /* IndexBits */ }; const CRTextureFormat _texformat_a8 = { 0, /* RedBits */ 0, /* GreenBits */ 0, /* BlueBits */ 8, /* AlphaBits */ 0, /* LuminanceBits */ 0, /* IntensityBits */ 0, /* IndexBits */ }; const CRTextureFormat _texformat_l8 = { 0, /* RedBits */ 0, /* GreenBits */ 0, /* BlueBits */ 0, /* AlphaBits */ 8, /* LuminanceBits */ 0, /* IntensityBits */ 0, /* IndexBits */ }; const CRTextureFormat _texformat_i8 = { 0, /* RedBits */ 0, /* GreenBits */ 0, /* BlueBits */ 0, /* AlphaBits */ 0, /* LuminanceBits */ 8, /* IntensityBits */ 0, /* IndexBits */ }; const CRTextureFormat _texformat_ci8 = { 0, /* RedBits */ 0, /* GreenBits */ 0, /* BlueBits */ 0, /* AlphaBits */ 0, /* LuminanceBits */ 0, /* IntensityBits */ 8, /* IndexBits */ }; /** * Given an internal texture format enum or 1, 2, 3, 4 initialize the * texture levels texture format. This basically just indicates the * number of red, green, blue, alpha, luminance, etc. bits are used to * store the image. */ void crStateTextureInitTextureFormat( CRTextureLevel *tl, GLenum internalFormat ) { switch (internalFormat) { case 4: case GL_RGBA: case GL_COMPRESSED_RGBA_ARB: #ifdef CR_EXT_texture_sRGB case GL_SRGB_ALPHA_EXT: case GL_SRGB8_ALPHA8_EXT: case GL_COMPRESSED_SRGB_ALPHA_EXT: #endif tl->texFormat = &_texformat_rgba8888; break; case 3: case GL_RGB: case GL_COMPRESSED_RGB_ARB: #ifdef CR_EXT_texture_sRGB case GL_SRGB_EXT: case GL_SRGB8_EXT: case GL_COMPRESSED_SRGB_EXT: #endif tl->texFormat = &_texformat_rgb888; break; case GL_RGBA2: case GL_RGBA4: case GL_RGB5_A1: case GL_RGBA8: case GL_RGB10_A2: case GL_RGBA12: case GL_RGBA16: tl->texFormat = &_texformat_rgba8888; break; case GL_R3_G3_B2: tl->texFormat = &_texformat_rgb332; break; case GL_RGB4: case GL_RGB5: case GL_RGB8: case GL_RGB10: case GL_RGB12: case GL_RGB16: tl->texFormat = &_texformat_rgb888; break; case GL_ALPHA: case GL_ALPHA4: case GL_ALPHA8: case GL_ALPHA12: case GL_ALPHA16: case GL_COMPRESSED_ALPHA_ARB: tl->texFormat = &_texformat_a8; break; case 1: case GL_LUMINANCE: case GL_LUMINANCE4: case GL_LUMINANCE8: case GL_LUMINANCE12: case GL_LUMINANCE16: case GL_COMPRESSED_LUMINANCE_ARB: #ifdef CR_EXT_texture_sRGB case GL_SLUMINANCE_EXT: case GL_SLUMINANCE8_EXT: case GL_COMPRESSED_SLUMINANCE_EXT: #endif tl->texFormat = &_texformat_l8; break; case 2: case GL_LUMINANCE_ALPHA: case GL_LUMINANCE4_ALPHA4: case GL_LUMINANCE6_ALPHA2: case GL_LUMINANCE8_ALPHA8: case GL_LUMINANCE12_ALPHA4: case GL_LUMINANCE12_ALPHA12: case GL_LUMINANCE16_ALPHA16: case GL_COMPRESSED_LUMINANCE_ALPHA_ARB: #ifdef CR_EXT_texture_sRGB case GL_SLUMINANCE_ALPHA_EXT: case GL_SLUMINANCE8_ALPHA8_EXT: case GL_COMPRESSED_SLUMINANCE_ALPHA_EXT: #endif tl->texFormat = &_texformat_al88; break; case GL_INTENSITY: case GL_INTENSITY4: case GL_INTENSITY8: case GL_INTENSITY12: case GL_INTENSITY16: case GL_COMPRESSED_INTENSITY_ARB: tl->texFormat = &_texformat_i8; break; case GL_COLOR_INDEX: case GL_COLOR_INDEX1_EXT: case GL_COLOR_INDEX2_EXT: case GL_COLOR_INDEX4_EXT: case GL_COLOR_INDEX8_EXT: case GL_COLOR_INDEX12_EXT: case GL_COLOR_INDEX16_EXT: tl->texFormat = &_texformat_ci8; break; default: return; } } #if 0 void crStateTextureInitTexture (GLuint name) { CRContext *g = GetCurrentContext(); CRTextureState *t = &(g->texture); CRTextureObj *tobj; GET_TOBJ(tobj, name); if (!tobj) return; crStateTextureInitTextureObj(g, tobj, name, GL_NONE); } #endif /** * Return the texture object corresponding to the given target and ID. */ CRTextureObj * crStateTextureGet(GLenum target, GLuint name) { CRContext *g = GetCurrentContext(); CRTextureState *t = &(g->texture); CRTextureObj *tobj; if (name == 0) { switch (target) { case GL_TEXTURE_1D: return &t->base1D; case GL_TEXTURE_2D: return &t->base2D; case GL_TEXTURE_3D: return &t->base3D; #ifdef CR_ARB_texture_cube_map case GL_TEXTURE_CUBE_MAP_ARB: return &t->baseCubeMap; #endif #ifdef CR_NV_texture_rectangle case GL_TEXTURE_RECTANGLE_NV: return &t->baseRect; #endif default: return NULL; } } GET_TOBJ(tobj, g, name); return tobj; } /* * Allocate a new texture object with the given name. * Also insert into hash table. */ static CRTextureObj * crStateTextureAllocate_t(CRContext *ctx, GLuint name) { CRTextureObj *tobj; if (!name) return NULL; tobj = crCalloc(sizeof(CRTextureObj)); if (!tobj) return NULL; crHashtableAdd( ctx->shared->textureTable, name, (void *) tobj ); crStateTextureInitTextureObj(ctx, tobj, name, GL_NONE); return tobj; } /** * Delete all the data that hangs off a CRTextureObj, but don't * delete the texture object itself, since it may not have been * dynamically allocated. */ void crStateDeleteTextureObjectData(CRTextureObj *tobj) { int k; int face; CRASSERT(tobj); /* Free the texture images */ for (face = 0; face < 6; face++) { CRTextureLevel *levels = NULL; levels = tobj->level[face]; if (levels) { /* free all mipmap levels for this face */ for (k = 0; k < CR_MAX_MIPMAP_LEVELS; k++) { CRTextureLevel *tl = levels + k; if (tl->img) { crFree(tl->img); tl->img = NULL; tl->bytes = 0; } } crFree(levels); } tobj->level[face] = NULL; } } void crStateDeleteTextureObject(CRTextureObj *tobj) { crStateDeleteTextureObjectData(tobj); crFree(tobj); } void crStateRegNames(CRContext *g, CRHashTable *table, GLsizei n, GLuint *names) { GLint i; for (i = 0; i < n; i++) { if (names[i]) { GLboolean isNewKey = crHashtableAllocRegisterKey(table, names[i]); CRASSERT(isNewKey); } else crWarning("RegNames: requested to register a null name"); } } void crStateRegTextures(GLsizei n, GLuint *names) { CRContext *g = GetCurrentContext(); crStateRegNames(g, g->shared->textureTable, n, names); } void crStateGenNames(CRContext *g, CRHashTable *table, GLsizei n, GLuint *names) { GLint start; FLUSH(); if (g->current.inBeginEnd) { crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "crStateGenNames called in Begin/End"); return; } if (n < 0) { crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "Negative n passed to crStateGenNames: %d", n); return; } start = crHashtableAllocKeys(table, n); if (start) { GLint i; for (i = 0; i < n; i++) names[i] = (GLuint) (start + i); } else { crStateError(__LINE__, __FILE__, GL_OUT_OF_MEMORY, "glGenTextures"); } } void STATE_APIENTRY crStateGenTextures(GLsizei n, GLuint *textures) { CRContext *g = GetCurrentContext(); crStateGenNames(g, g->shared->textureTable, n, textures); } static void crStateTextureCheckFBOAPs(GLenum target, GLuint texture) { GLuint u; CRFBOAttachmentPoint *ap; CRContext *g = GetCurrentContext(); CRFramebufferObjectState *fbo = &g->framebufferobject; CRFramebufferObject *pFBO; pFBO = GL_READ_FRAMEBUFFER==target ? fbo->readFB : fbo->drawFB; if (!pFBO) return; for (u=0; ucolor[u]; if (ap->type==GL_TEXTURE && ap->name==texture) { crStateFramebufferTexture1DEXT(target, u+GL_COLOR_ATTACHMENT0_EXT, 0, 0, 0); } } ap = &pFBO->depth; if (ap->type==GL_TEXTURE && ap->name==texture) { crStateFramebufferTexture1DEXT(target, GL_DEPTH_ATTACHMENT_EXT, 0, 0, 0); } ap = &pFBO->stencil; if (ap->type==GL_TEXTURE && ap->name==texture) { crStateFramebufferTexture1DEXT(target, GL_STENCIL_ATTACHMENT_EXT, 0, 0, 0); } } static void crStateCleanupTextureRefs(CRContext *g, CRTextureObj *tObj) { CRTextureState *t = &(g->texture); GLuint u; /* ** reset back to the base texture. */ for (u = 0; u < g->limits.maxTextureUnits; u++) { if (tObj == t->unit[u].currentTexture1D) { t->unit[u].currentTexture1D = &(t->base1D); } if (tObj == t->unit[u].currentTexture2D) { t->unit[u].currentTexture2D = &(t->base2D); } #ifdef CR_OPENGL_VERSION_1_2 if (tObj == t->unit[u].currentTexture3D) { t->unit[u].currentTexture3D = &(t->base3D); } #endif #ifdef CR_ARB_texture_cube_map if (tObj == t->unit[u].currentTextureCubeMap) { t->unit[u].currentTextureCubeMap = &(t->baseCubeMap); } #endif #ifdef CR_NV_texture_rectangle if (tObj == t->unit[u].currentTextureRect) { t->unit[u].currentTextureRect = &(t->baseRect); } #endif #ifdef CR_EXT_framebuffer_object crStateTextureCheckFBOAPs(GL_DRAW_FRAMEBUFFER, tObj->id); crStateTextureCheckFBOAPs(GL_READ_FRAMEBUFFER, tObj->id); #endif } CR_STATE_SHAREDOBJ_USAGE_CLEAR(tObj, g); } void STATE_APIENTRY crStateDeleteTextures(GLsizei n, const GLuint *textures) { CRContext *g = GetCurrentContext(); CRTextureState *t = &(g->texture); CRStateBits *sb = GetCurrentBits(); CRTextureBits *tb = &(sb->texture); int i; FLUSH(); if (g->current.inBeginEnd) { crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glDeleteTextures called in Begin/End"); return; } if (n < 0) { crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "Negative n passed to glDeleteTextures: %d", n); return; } for (i=0; idispatch_table.DeleteTextures(n, newTextures); * in crServerDispatchDeleteTextures, we just delete a state object here, which crStateDeleteTextureObject does */ crHashtableDelete(g->shared->textureTable, name, (CRHashtableCallback)crStateDeleteTextureObject); } else { /* call crHashtableDelete in any way, to ensure the allocated key is freed */ Assert(crHashtableIsKeyUsed(g->shared->textureTable, name)); crHashtableDelete(g->shared->textureTable, name, NULL); } } DIRTY(tb->dirty, g->neg_bitid); DIRTY(tb->current[t->curTextureUnit], g->neg_bitid); } void STATE_APIENTRY crStateClientActiveTextureARB( GLenum texture ) { CRContext *g = GetCurrentContext(); CRClientState *c = &(g->client); FLUSH(); if (!g->extensions.ARB_multitexture) { crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glClientActiveTextureARB not available"); return; } if (g->current.inBeginEnd) { crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glClientActiveTextureARB called in Begin/End"); return; } if ( texture < GL_TEXTURE0_ARB || texture >= GL_TEXTURE0_ARB + g->limits.maxTextureUnits) { crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "crStateClientActiveTexture: unit = %d (max is %d)", texture, g->limits.maxTextureUnits ); return; } c->curClientTextureUnit = texture - GL_TEXTURE0_ARB; DIRTY(GetCurrentBits()->client.dirty, g->neg_bitid); } void STATE_APIENTRY crStateActiveTextureARB( GLenum texture ) { CRContext *g = GetCurrentContext(); CRTextureState *t = &(g->texture); FLUSH(); if (!g->extensions.ARB_multitexture) { crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glActiveTextureARB not available"); return; } if (g->current.inBeginEnd) { crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glActiveTextureARB called in Begin/End"); return; } if ( texture < GL_TEXTURE0_ARB || texture >= GL_TEXTURE0_ARB + g->limits.maxTextureUnits) { crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "Bad texture unit passed to crStateActiveTexture: %d (max is %d)", texture, g->limits.maxTextureUnits ); return; } t->curTextureUnit = texture - GL_TEXTURE0_ARB; /* update the current matrix pointer, etc. */ if (g->transform.matrixMode == GL_TEXTURE) { crStateMatrixMode(GL_TEXTURE); } } DECLEXPORT(void) crStateSetTextureUsed(GLuint texture, GLboolean used) { CRContext *g = GetCurrentContext(); CRTextureObj *tobj; if (!texture) { crWarning("crStateSetTextureUsed: null texture name specified!"); return; } GET_TOBJ(tobj, g, texture); if (!tobj) { #ifdef IN_GUEST if (used) { tobj = crStateTextureAllocate_t(g, texture); } else #endif { crWarning("crStateSetTextureUsed: failed to fined a HW name for texture(%d)!", texture); return; } } if (used) CR_STATE_SHAREDOBJ_USAGE_SET(tobj, g); else { CRStateBits *sb = GetCurrentBits(); CRTextureBits *tb = &(sb->texture); CRTextureState *t = &(g->texture); crStateCleanupTextureRefs(g, tobj); if (!CR_STATE_SHAREDOBJ_USAGE_IS_USED(tobj)) { /* on the host side, we need to delete an ogl texture object here as well, which crStateDeleteTextureCallback will do * in addition to calling crStateDeleteTextureObject to delete a state object */ crHashtableDelete(g->shared->textureTable, texture, crStateDeleteTextureCallback); } DIRTY(tb->dirty, g->neg_bitid); DIRTY(tb->current[t->curTextureUnit], g->neg_bitid); } } void STATE_APIENTRY crStateBindTexture(GLenum target, GLuint texture) { CRContext *g = GetCurrentContext(); CRTextureState *t = &(g->texture); CRTextureObj *tobj; CRStateBits *sb = GetCurrentBits(); CRTextureBits *tb = &(sb->texture); FLUSH(); if (g->current.inBeginEnd) { crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glBindTexture called in Begin/End"); return; } /* Special Case name = 0 */ if (!texture) { switch (target) { case GL_TEXTURE_1D: t->unit[t->curTextureUnit].currentTexture1D = &(t->base1D); break; case GL_TEXTURE_2D: t->unit[t->curTextureUnit].currentTexture2D = &(t->base2D); break; #ifdef CR_OPENGL_VERSION_1_2 case GL_TEXTURE_3D: t->unit[t->curTextureUnit].currentTexture3D = &(t->base3D); break; #endif #ifdef CR_ARB_texture_cube_map case GL_TEXTURE_CUBE_MAP_ARB: if (!g->extensions.ARB_texture_cube_map) { crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "Invalid target passed to glBindTexture: %d", target); return; } t->unit[t->curTextureUnit].currentTextureCubeMap = &(t->baseCubeMap); break; #endif #ifdef CR_NV_texture_rectangle case GL_TEXTURE_RECTANGLE_NV: if (!g->extensions.NV_texture_rectangle) { crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "Invalid target passed to glBindTexture: %d", target); return; } t->unit[t->curTextureUnit].currentTextureRect = &(t->baseRect); break; #endif default: crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "Invalid target passed to glBindTexture: %d", target); return; } DIRTY(tb->dirty, g->neg_bitid); DIRTY(tb->current[t->curTextureUnit], g->neg_bitid); return; } /* texture != 0 */ /* Get the texture */ GET_TOBJ(tobj, g, texture); if (!tobj) { Assert(crHashtableIsKeyUsed(g->shared->textureTable, texture)); tobj = crStateTextureAllocate_t(g, texture); } CR_STATE_SHAREDOBJ_USAGE_SET(tobj, g); /* Check the targets */ if (tobj->target == GL_NONE) { /* Target isn't set so set it now.*/ tobj->target = target; } else if ((tobj->target != target) && !((target==GL_TEXTURE_RECTANGLE_NV && tobj->target==GL_TEXTURE_2D) ||(target==GL_TEXTURE_2D && tobj->target==GL_TEXTURE_RECTANGLE_NV))) { crWarning( "You called glBindTexture with a target of 0x%x, but the texture you wanted was target 0x%x [1D: %x 2D: %x 3D: %x cube: %x]", (int) target, (int) tobj->target, GL_TEXTURE_1D, GL_TEXTURE_2D, GL_TEXTURE_3D, GL_TEXTURE_CUBE_MAP ); crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "Attempt to bind a texture of different dimensions"); return; } /* Set the current texture */ switch (target) { case GL_TEXTURE_1D: t->unit[t->curTextureUnit].currentTexture1D = tobj; break; case GL_TEXTURE_2D: t->unit[t->curTextureUnit].currentTexture2D = tobj; break; #ifdef CR_OPENGL_VERSION_1_2 case GL_TEXTURE_3D: t->unit[t->curTextureUnit].currentTexture3D = tobj; break; #endif #ifdef CR_ARB_texture_cube_map case GL_TEXTURE_CUBE_MAP_ARB: t->unit[t->curTextureUnit].currentTextureCubeMap = tobj; break; #endif #ifdef CR_NV_texture_rectangle case GL_TEXTURE_RECTANGLE_NV: t->unit[t->curTextureUnit].currentTextureRect = tobj; break; #endif default: crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "Invalid target passed to glBindTexture: %d", target); return; } DIRTY(tb->dirty, g->neg_bitid); DIRTY(tb->current[t->curTextureUnit], g->neg_bitid); } void STATE_APIENTRY crStateTexParameterfv(GLenum target, GLenum pname, const GLfloat *param) { CRContext *g = GetCurrentContext(); CRTextureObj *tobj = NULL; CRTextureLevel *tl = NULL; GLenum e = (GLenum) *param; CRStateBits *sb = GetCurrentBits(); CRTextureBits *tb = &(sb->texture); unsigned int i; FLUSH(); if (g->current.inBeginEnd) { crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "TexParameterfv called in Begin/End"); return; } crStateGetTextureObjectAndImage(g, target, 0, &tobj, &tl); if (!tobj) { crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "TexParamterfv(invalid target=0x%x)", target); return; } switch (pname) { case GL_TEXTURE_MIN_FILTER: if (e != GL_NEAREST && e != GL_LINEAR && e != GL_NEAREST_MIPMAP_NEAREST && e != GL_LINEAR_MIPMAP_NEAREST && e != GL_NEAREST_MIPMAP_LINEAR && e != GL_LINEAR_MIPMAP_LINEAR) { crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "TexParamterfv: GL_TEXTURE_MIN_FILTER invalid param: %d", e); return; } tobj->minFilter = e; break; case GL_TEXTURE_MAG_FILTER: if (e != GL_NEAREST && e != GL_LINEAR) { crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "TexParamterfv: GL_TEXTURE_MAG_FILTER invalid param: %d", e); return; } tobj->magFilter = e; break; case GL_TEXTURE_WRAP_S: if (e == GL_CLAMP || e == GL_REPEAT) { tobj->wrapS = e; } #ifdef CR_OPENGL_VERSION_1_2 else if (e == GL_CLAMP_TO_EDGE) { tobj->wrapS = e; } #endif #ifdef GL_CLAMP_TO_EDGE_EXT else if (e == GL_CLAMP_TO_EDGE_EXT && g->extensions.EXT_texture_edge_clamp) { tobj->wrapS = e; } #endif #ifdef CR_ARB_texture_border_clamp else if (e == GL_CLAMP_TO_BORDER_ARB && g->extensions.ARB_texture_border_clamp) { tobj->wrapS = e; } #endif #ifdef CR_ARB_texture_mirrored_repeat else if (e == GL_MIRRORED_REPEAT_ARB && g->extensions.ARB_texture_mirrored_repeat) { tobj->wrapS = e; } #endif #ifdef CR_ATI_texture_mirror_once else if ((e == GL_MIRROR_CLAMP_ATI || e == GL_MIRROR_CLAMP_TO_EDGE_ATI) && g->extensions.ATI_texture_mirror_once) { tobj->wrapS = e; } #endif else { crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "TexParameterfv: GL_TEXTURE_WRAP_S invalid param: 0x%x", e); return; } break; case GL_TEXTURE_WRAP_T: if (e == GL_CLAMP || e == GL_REPEAT) { tobj->wrapT = e; } #ifdef CR_OPENGL_VERSION_1_2 else if (e == GL_CLAMP_TO_EDGE) { tobj->wrapT = e; } #endif #ifdef GL_CLAMP_TO_EDGE_EXT else if (e == GL_CLAMP_TO_EDGE_EXT && g->extensions.EXT_texture_edge_clamp) { tobj->wrapT = e; } #endif #ifdef CR_ARB_texture_border_clamp else if (e == GL_CLAMP_TO_BORDER_ARB && g->extensions.ARB_texture_border_clamp) { tobj->wrapT = e; } #endif #ifdef CR_ARB_texture_mirrored_repeat else if (e == GL_MIRRORED_REPEAT_ARB && g->extensions.ARB_texture_mirrored_repeat) { tobj->wrapT = e; } #endif #ifdef CR_ATI_texture_mirror_once else if ((e == GL_MIRROR_CLAMP_ATI || e == GL_MIRROR_CLAMP_TO_EDGE_ATI) && g->extensions.ATI_texture_mirror_once) { tobj->wrapT = e; } #endif else { crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "TexParameterfv: GL_TEXTURE_WRAP_T invalid param: 0x%x", e); return; } break; #ifdef CR_OPENGL_VERSION_1_2 case GL_TEXTURE_WRAP_R: if (e == GL_CLAMP || e == GL_REPEAT) { tobj->wrapR = e; } else if (e == GL_CLAMP_TO_EDGE) { tobj->wrapR = e; } #ifdef GL_CLAMP_TO_EDGE_EXT else if (e == GL_CLAMP_TO_EDGE_EXT && g->extensions.EXT_texture_edge_clamp) { tobj->wrapR = e; } #endif #ifdef CR_ARB_texture_border_clamp else if (e == GL_CLAMP_TO_BORDER_ARB && g->extensions.ARB_texture_border_clamp) { tobj->wrapR = e; } #endif #ifdef CR_ARB_texture_mirrored_repeat else if (e == GL_MIRRORED_REPEAT_ARB && g->extensions.ARB_texture_mirrored_repeat) { tobj->wrapR = e; } #endif #ifdef CR_ATI_texture_mirror_once else if ((e == GL_MIRROR_CLAMP_ATI || e == GL_MIRROR_CLAMP_TO_EDGE_ATI) && g->extensions.ATI_texture_mirror_once) { tobj->wrapR = e; } #endif else { crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "TexParameterfv: GL_TEXTURE_WRAP_R invalid param: 0x%x", e); return; } break; case GL_TEXTURE_PRIORITY: tobj->priority = param[0]; break; case GL_TEXTURE_MIN_LOD: tobj->minLod = param[0]; break; case GL_TEXTURE_MAX_LOD: tobj->maxLod = param[0]; break; case GL_TEXTURE_BASE_LEVEL: if (e < 0.0f) { crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "TexParameterfv: GL_TEXTURE_BASE_LEVEL invalid param: 0x%x", e); return; } tobj->baseLevel = e; break; case GL_TEXTURE_MAX_LEVEL: if (e < 0.0f) { crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "TexParameterfv: GL_TEXTURE_MAX_LEVEL invalid param: 0x%x", e); return; } tobj->maxLevel = e; break; #endif case GL_TEXTURE_BORDER_COLOR: tobj->borderColor.r = param[0]; tobj->borderColor.g = param[1]; tobj->borderColor.b = param[2]; tobj->borderColor.a = param[3]; break; #ifdef CR_EXT_texture_filter_anisotropic case GL_TEXTURE_MAX_ANISOTROPY_EXT: if (g->extensions.EXT_texture_filter_anisotropic) { if (param[0] < 1.0f) { crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "TexParameterfv: GL_TEXTURE_MAX_ANISOTROPY_EXT called with parameter less than 1: %f", param[0]); return; } tobj->maxAnisotropy = param[0]; if (tobj->maxAnisotropy > g->limits.maxTextureAnisotropy) { tobj->maxAnisotropy = g->limits.maxTextureAnisotropy; } } break; #endif #ifdef CR_ARB_depth_texture case GL_DEPTH_TEXTURE_MODE_ARB: if (g->extensions.ARB_depth_texture) { if (param[0] == GL_LUMINANCE || param[0] == GL_INTENSITY || param[0] == GL_ALPHA) { tobj->depthMode = (GLenum) param[0]; } else { crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "TexParameterfv: GL_DEPTH_TEXTURE_MODE_ARB called with invalid parameter: 0x%x", param[0]); return; } } break; #endif #ifdef CR_ARB_shadow case GL_TEXTURE_COMPARE_MODE_ARB: if (g->extensions.ARB_shadow) { if (param[0] == GL_NONE || param[0] == GL_COMPARE_R_TO_TEXTURE_ARB) { tobj->compareMode = (GLenum) param[0]; } else { crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "TexParameterfv: GL_TEXTURE_COMPARE_MODE_ARB called with invalid parameter: 0x%x", param[0]); return; } } break; case GL_TEXTURE_COMPARE_FUNC_ARB: if (g->extensions.ARB_shadow) { if (param[0] == GL_LEQUAL || param[0] == GL_GEQUAL) { tobj->compareFunc = (GLenum) param[0]; } } #ifdef CR_EXT_shadow_funcs else if (g->extensions.EXT_shadow_funcs) { if (param[0] == GL_LEQUAL || param[0] == GL_GEQUAL || param[0] == GL_LESS || param[0] == GL_GREATER || param[0] == GL_ALWAYS || param[0] == GL_NEVER ) { tobj->compareFunc = (GLenum) param[0]; } } #endif else { crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "TexParameterfv: GL_TEXTURE_COMPARE_FUNC_ARB called with invalid parameter: 0x%x", param[0]); return; } break; #endif #ifdef CR_ARB_shadow_ambient case GL_TEXTURE_COMPARE_FAIL_VALUE_ARB: if (g->extensions.ARB_shadow_ambient) { tobj->compareFailValue = param[0]; } break; #endif #ifdef CR_SGIS_generate_mipmap case GL_GENERATE_MIPMAP_SGIS: if (g->extensions.SGIS_generate_mipmap) { tobj->generateMipmap = param[0] ? GL_TRUE : GL_FALSE; } break; #endif default: crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "TexParamterfv: Invalid pname: %d", pname); return; } DIRTY(tobj->dirty, g->neg_bitid); for (i = 0; i < g->limits.maxTextureUnits; i++) { DIRTY(tobj->paramsBit[i], g->neg_bitid); } DIRTY(tb->dirty, g->neg_bitid); } void STATE_APIENTRY crStateTexParameteriv(GLenum target, GLenum pname, const GLint *param) { GLfloat f_param; GLcolor f_color; switch (pname) { case GL_TEXTURE_MIN_FILTER: case GL_TEXTURE_MAG_FILTER: case GL_TEXTURE_WRAP_S: case GL_TEXTURE_WRAP_T: #ifdef CR_OPENGL_VERSION_1_2 case GL_TEXTURE_WRAP_R: case GL_TEXTURE_PRIORITY: case GL_TEXTURE_MIN_LOD: case GL_TEXTURE_MAX_LOD: case GL_TEXTURE_BASE_LEVEL: case GL_TEXTURE_MAX_LEVEL: #endif #ifdef CR_EXT_texture_filter_anisotropic case GL_TEXTURE_MAX_ANISOTROPY_EXT: #endif #ifdef CR_ARB_depth_texture case GL_DEPTH_TEXTURE_MODE_ARB: #endif #ifdef CR_ARB_shadow case GL_TEXTURE_COMPARE_MODE_ARB: case GL_TEXTURE_COMPARE_FUNC_ARB: #endif #ifdef CR_ARB_shadow_ambinet case GL_TEXTURE_COMPARE_FAIL_VALUE_ARB: #endif #ifdef CR_SGIS_generate_mipmap case GL_GENERATE_MIPMAP_SGIS: #endif f_param = (GLfloat) (*param); crStateTexParameterfv( target, pname, &(f_param) ); break; case GL_TEXTURE_BORDER_COLOR: f_color.r = ((GLfloat) param[0])/CR_MAXINT; f_color.g = ((GLfloat) param[1])/CR_MAXINT; f_color.b = ((GLfloat) param[2])/CR_MAXINT; f_color.a = ((GLfloat) param[3])/CR_MAXINT; crStateTexParameterfv( target, pname, (const GLfloat *) &(f_color) ); break; default: crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "TexParamteriv: Invalid pname: %d", pname); return; } } void STATE_APIENTRY crStateTexParameterf(GLenum target, GLenum pname, GLfloat param) { crStateTexParameterfv( target, pname, ¶m ); } void STATE_APIENTRY crStateTexParameteri(GLenum target, GLenum pname, GLint param) { GLfloat f_param = (GLfloat) param; crStateTexParameterfv( target, pname, &f_param ); } void STATE_APIENTRY crStateTexEnvfv(GLenum target, GLenum pname, const GLfloat *param) { CRContext *g = GetCurrentContext(); CRTextureState *t = &(g->texture); CRStateBits *sb = GetCurrentBits(); CRTextureBits *tb = &(sb->texture); GLenum e; GLcolorf c; GLuint stage = 0; (void) stage; FLUSH(); if (g->current.inBeginEnd) { crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glTexEnvfv called in begin/end"); return; } #if CR_EXT_texture_lod_bias if (target == GL_TEXTURE_FILTER_CONTROL_EXT) { if (!g->extensions.EXT_texture_lod_bias || pname != GL_TEXTURE_LOD_BIAS_EXT) { crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glTexEnv"); } else { t->unit[t->curTextureUnit].lodBias = *param; DIRTY(tb->envBit[t->curTextureUnit], g->neg_bitid); DIRTY(tb->dirty, g->neg_bitid); } return; } else #endif #if CR_ARB_point_sprite if (target == GL_POINT_SPRITE_ARB) { if (!g->extensions.ARB_point_sprite || pname != GL_COORD_REPLACE_ARB) { crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glTexEnv"); } else { CRPointBits *pb = &(sb->point); g->point.coordReplacement[t->curTextureUnit] = *param ? GL_TRUE : GL_FALSE; DIRTY(pb->coordReplacement[t->curTextureUnit], g->neg_bitid); DIRTY(pb->dirty, g->neg_bitid); } return; } else #endif if (target != GL_TEXTURE_ENV) { crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glTexEnvfv: target != GL_TEXTURE_ENV: %d", target); return; } switch (pname) { case GL_TEXTURE_ENV_MODE: e = (GLenum) *param; if (e != GL_MODULATE && e != GL_DECAL && e != GL_BLEND && e != GL_ADD && e != GL_REPLACE && e != GL_COMBINE_ARB) { crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glTexEnvfv: invalid param: %f", *param); return; } t->unit[t->curTextureUnit].envMode = e; break; case GL_TEXTURE_ENV_COLOR: c.r = param[0]; c.g = param[1]; c.b = param[2]; c.a = param[3]; if (c.r > 1.0f) c.r = 1.0f; if (c.g > 1.0f) c.g = 1.0f; if (c.b > 1.0f) c.b = 1.0f; if (c.a > 1.0f) c.a = 1.0f; if (c.r < 0.0f) c.r = 0.0f; if (c.g < 0.0f) c.g = 0.0f; if (c.b < 0.0f) c.b = 0.0f; if (c.a < 0.0f) c.a = 0.0f; t->unit[t->curTextureUnit].envColor = c; break; #ifdef CR_ARB_texture_env_combine case GL_COMBINE_RGB_ARB: e = (GLenum) (GLint) *param; if (g->extensions.ARB_texture_env_combine && (e == GL_REPLACE || e == GL_MODULATE || e == GL_ADD || e == GL_ADD_SIGNED_ARB || e == GL_INTERPOLATE_ARB || e == GL_SUBTRACT_ARB)) { t->unit[t->curTextureUnit].combineModeRGB = e; } #ifdef CR_ARB_texture_env_dot3 else if (g->extensions.ARB_texture_env_dot3 && (e == GL_DOT3_RGB_ARB || e == GL_DOT3_RGBA_ARB || e == GL_DOT3_RGB_EXT || e == GL_DOT3_RGBA_EXT)) { t->unit[t->curTextureUnit].combineModeRGB = e; } #endif else { crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glTexEnvfv(param=0x%x", e); return; } break; case GL_COMBINE_ALPHA_EXT: e = (GLenum) *param; if (g->extensions.ARB_texture_env_combine && (e == GL_REPLACE || e == GL_MODULATE || e == GL_ADD || e == GL_ADD_SIGNED_ARB || e == GL_INTERPOLATE_ARB || e == GL_SUBTRACT_ARB)) { t->unit[t->curTextureUnit].combineModeA = e; } else { crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glTexEnvfv"); return; } break; case GL_SOURCE0_RGB_ARB: case GL_SOURCE1_RGB_ARB: case GL_SOURCE2_RGB_ARB: e = (GLenum) *param; stage = pname - GL_SOURCE0_RGB_ARB; if (g->extensions.ARB_texture_env_combine && (e == GL_TEXTURE || e == GL_CONSTANT_ARB || e == GL_PRIMARY_COLOR_ARB || e == GL_PREVIOUS_ARB)) { t->unit[t->curTextureUnit].combineSourceRGB[stage] = e; } else if (g->extensions.ARB_texture_env_crossbar && e >= GL_TEXTURE0_ARB && e < GL_TEXTURE0_ARB + g->limits.maxTextureUnits) { t->unit[t->curTextureUnit].combineSourceRGB[stage] = e; } else { crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glTexEnvfv"); return; } break; case GL_SOURCE0_ALPHA_ARB: case GL_SOURCE1_ALPHA_ARB: case GL_SOURCE2_ALPHA_ARB: e = (GLenum) *param; stage = pname - GL_SOURCE0_ALPHA_ARB; if (g->extensions.ARB_texture_env_combine && (e == GL_TEXTURE || e == GL_CONSTANT_ARB || e == GL_PRIMARY_COLOR_ARB || e == GL_PREVIOUS_ARB)) { t->unit[t->curTextureUnit].combineSourceA[stage] = e; } else if (g->extensions.ARB_texture_env_crossbar && e >= GL_TEXTURE0_ARB && e < GL_TEXTURE0_ARB + g->limits.maxTextureUnits) { t->unit[t->curTextureUnit].combineSourceA[stage] = e; } else { crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glTexEnvfv"); return; } break; case GL_OPERAND0_RGB_ARB: case GL_OPERAND1_RGB_ARB: case GL_OPERAND2_RGB_ARB: e = (GLenum) *param; stage = pname - GL_OPERAND0_RGB_ARB; if (g->extensions.ARB_texture_env_combine && (e == GL_SRC_COLOR || e == GL_ONE_MINUS_SRC_COLOR || e == GL_SRC_ALPHA || e == GL_ONE_MINUS_SRC_ALPHA)) { t->unit[t->curTextureUnit].combineOperandRGB[stage] = e; } else { crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glTexEnvfv"); return; } break; case GL_OPERAND0_ALPHA_ARB: case GL_OPERAND1_ALPHA_ARB: case GL_OPERAND2_ALPHA_ARB: e = (GLenum) *param; stage = pname - GL_OPERAND0_ALPHA_ARB; if (g->extensions.ARB_texture_env_combine && (e == GL_SRC_ALPHA || e == GL_ONE_MINUS_SRC_ALPHA)) { t->unit[t->curTextureUnit].combineOperandA[stage] = e; } else { crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glTexEnvfv(param=0x%x)", e); return; } break; case GL_RGB_SCALE_ARB: if (g->extensions.ARB_texture_env_combine && (*param == 1.0 || *param == 2.0 || *param == 4.0)) { t->unit[t->curTextureUnit].combineScaleRGB = *param; } else { crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "glTexEnvfv"); return; } break; case GL_ALPHA_SCALE: if (g->extensions.ARB_texture_env_combine && (*param == 1.0 || *param == 2.0 || *param == 4.0)) { t->unit[t->curTextureUnit].combineScaleA = *param; } else { crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "glTexEnvfv"); return; } break; #endif /* CR_ARB_texture_env_combine */ default: crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glTexEnvfv: invalid pname: %d", pname); return; } DIRTY(tb->envBit[t->curTextureUnit], g->neg_bitid); DIRTY(tb->dirty, g->neg_bitid); } void STATE_APIENTRY crStateTexEnviv(GLenum target, GLenum pname, const GLint *param) { GLfloat f_param; GLcolor f_color; switch (pname) { case GL_TEXTURE_ENV_MODE: f_param = (GLfloat) (*param); crStateTexEnvfv( target, pname, &f_param ); break; case GL_TEXTURE_ENV_COLOR: f_color.r = ((GLfloat) param[0]) / CR_MAXINT; f_color.g = ((GLfloat) param[1]) / CR_MAXINT; f_color.b = ((GLfloat) param[2]) / CR_MAXINT; f_color.a = ((GLfloat) param[3]) / CR_MAXINT; crStateTexEnvfv( target, pname, (const GLfloat *) &f_color ); break; #ifdef CR_ARB_texture_env_combine case GL_COMBINE_RGB_ARB: case GL_COMBINE_ALPHA_EXT: case GL_SOURCE0_RGB_ARB: case GL_SOURCE1_RGB_ARB: case GL_SOURCE2_RGB_ARB: case GL_SOURCE0_ALPHA_ARB: case GL_SOURCE1_ALPHA_ARB: case GL_SOURCE2_ALPHA_ARB: case GL_OPERAND0_RGB_ARB: case GL_OPERAND1_RGB_ARB: case GL_OPERAND2_RGB_ARB: case GL_OPERAND0_ALPHA_ARB: case GL_OPERAND1_ALPHA_ARB: case GL_OPERAND2_ALPHA_ARB: case GL_RGB_SCALE_ARB: case GL_ALPHA_SCALE: f_param = (GLfloat) (*param); crStateTexEnvfv( target, pname, &f_param ); break; #endif #ifdef CR_EXT_texture_lod_bias case GL_TEXTURE_LOD_BIAS_EXT: f_param = (GLfloat) (*param); crStateTexEnvfv( target, pname, &f_param); break; #endif #ifdef CR_ARB_point_sprite case GL_COORD_REPLACE_ARB: f_param = (GLfloat) *param; crStateTexEnvfv( target, pname, &f_param); break; #endif default: crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glTexEnvfv: invalid pname: %d", pname); return; } } void STATE_APIENTRY crStateTexEnvf(GLenum target, GLenum pname, GLfloat param) { crStateTexEnvfv( target, pname, ¶m ); } void STATE_APIENTRY crStateTexEnvi(GLenum target, GLenum pname, GLint param) { GLfloat f_param = (GLfloat) param; crStateTexEnvfv( target, pname, &f_param ); } void STATE_APIENTRY crStateGetTexEnvfv(GLenum target, GLenum pname, GLfloat *param) { CRContext *g = GetCurrentContext(); CRTextureState *t = &(g->texture); if (g->current.inBeginEnd) { crStateError(__LINE__, __FILE__,GL_INVALID_OPERATION, "glGetTexEnvfv called in begin/end"); return; } #if CR_EXT_texture_lod_bias if (target == GL_TEXTURE_FILTER_CONTROL_EXT) { if (!g->extensions.EXT_texture_lod_bias || pname != GL_TEXTURE_LOD_BIAS_EXT) { crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexEnv"); } else { *param = t->unit[t->curTextureUnit].lodBias; } return; } else #endif #if CR_ARB_point_sprite if (target == GL_POINT_SPRITE_ARB) { if (!g->extensions.ARB_point_sprite || pname != GL_COORD_REPLACE_ARB) { crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexEnv"); } else { *param = (GLfloat) g->point.coordReplacement[t->curTextureUnit]; } return; } else #endif if (target != GL_TEXTURE_ENV) { crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexEnvfv: target != GL_TEXTURE_ENV: %d", target); return; } switch (pname) { case GL_TEXTURE_ENV_MODE: *param = (GLfloat) t->unit[t->curTextureUnit].envMode; break; case GL_TEXTURE_ENV_COLOR: param[0] = t->unit[t->curTextureUnit].envColor.r; param[1] = t->unit[t->curTextureUnit].envColor.g; param[2] = t->unit[t->curTextureUnit].envColor.b; param[3] = t->unit[t->curTextureUnit].envColor.a; break; case GL_COMBINE_RGB_ARB: if (g->extensions.ARB_texture_env_combine) { *param = (GLfloat) t->unit[t->curTextureUnit].combineModeRGB; } else { crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexEnvfv(pname)"); return; } break; case GL_COMBINE_ALPHA_ARB: if (g->extensions.ARB_texture_env_combine) { *param = (GLfloat) t->unit[t->curTextureUnit].combineModeA; } else { crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexEnvfv(pname)"); return; } break; case GL_SOURCE0_RGB_ARB: if (g->extensions.ARB_texture_env_combine) { *param = (GLfloat) t->unit[t->curTextureUnit].combineSourceRGB[0]; } else { crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexEnvfv(pname)"); return; } break; case GL_SOURCE1_RGB_ARB: if (g->extensions.ARB_texture_env_combine) { *param = (GLfloat) t->unit[t->curTextureUnit].combineSourceRGB[1]; } else { crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexEnvfv(pname)"); return; } break; case GL_SOURCE2_RGB_ARB: if (g->extensions.ARB_texture_env_combine) { *param = (GLfloat) t->unit[t->curTextureUnit].combineSourceRGB[2]; } else { crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexEnvfv(pname)"); return; } break; case GL_SOURCE0_ALPHA_ARB: if (g->extensions.ARB_texture_env_combine) { *param = (GLfloat) t->unit[t->curTextureUnit].combineSourceA[0]; } else { crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexEnvfv(pname)"); return; } break; case GL_SOURCE1_ALPHA_ARB: if (g->extensions.ARB_texture_env_combine) { *param = (GLfloat) t->unit[t->curTextureUnit].combineSourceA[1]; } else { crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexEnvfv(pname)"); return; } break; case GL_SOURCE2_ALPHA_ARB: if (g->extensions.ARB_texture_env_combine) { *param = (GLfloat) t->unit[t->curTextureUnit].combineSourceA[2]; } else { crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexEnvfv(pname)"); return; } break; case GL_OPERAND0_RGB_ARB: if (g->extensions.ARB_texture_env_combine) { *param = (GLfloat) t->unit[t->curTextureUnit].combineOperandRGB[0]; } else { crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexEnvfv(pname)"); return; } break; case GL_OPERAND1_RGB_ARB: if (g->extensions.ARB_texture_env_combine) { *param = (GLfloat) t->unit[t->curTextureUnit].combineOperandRGB[1]; } else { crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexEnvfv(pname)"); return; } break; case GL_OPERAND2_RGB_ARB: if (g->extensions.ARB_texture_env_combine) { *param = (GLfloat) t->unit[t->curTextureUnit].combineOperandRGB[2]; } else { crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexEnvfv(pname)"); return; } break; case GL_OPERAND0_ALPHA_ARB: if (g->extensions.ARB_texture_env_combine) { *param = (GLfloat) t->unit[t->curTextureUnit].combineOperandA[0]; } else { crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexEnvfv(pname)"); return; } break; case GL_OPERAND1_ALPHA_ARB: if (g->extensions.ARB_texture_env_combine) { *param = (GLfloat) t->unit[t->curTextureUnit].combineOperandA[1]; } else { crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexEnvfv(pname)"); return; } break; case GL_OPERAND2_ALPHA_ARB: if (g->extensions.ARB_texture_env_combine) { *param = (GLfloat) t->unit[t->curTextureUnit].combineOperandA[2]; } else { crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexEnvfv(pname)"); return; } break; case GL_RGB_SCALE_ARB: if (g->extensions.ARB_texture_env_combine) { *param = t->unit[t->curTextureUnit].combineScaleRGB; } else { crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexEnvfv(pname)"); return; } break; case GL_ALPHA_SCALE: if (g->extensions.ARB_texture_env_combine) { *param = t->unit[t->curTextureUnit].combineScaleA; } else { crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexEnvfv(pname)"); return; } break; default: crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexEnvfv: invalid pname: %d", pname); return; } } void STATE_APIENTRY crStateGetTexEnviv(GLenum target, GLenum pname, GLint *param) { CRContext *g = GetCurrentContext(); CRTextureState *t = &(g->texture); if (g->current.inBeginEnd) { crStateError(__LINE__, __FILE__,GL_INVALID_OPERATION, "glGetTexEnviv called in begin/end"); return; } #if CR_EXT_texture_lod_bias if (target == GL_TEXTURE_FILTER_CONTROL_EXT) { if (!g->extensions.EXT_texture_lod_bias || pname != GL_TEXTURE_LOD_BIAS_EXT) { crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexEnv"); } else { *param = (GLint) t->unit[t->curTextureUnit].lodBias; } return; } else #endif #if CR_ARB_point_sprite if (target == GL_POINT_SPRITE_ARB) { if (!g->extensions.ARB_point_sprite || pname != GL_COORD_REPLACE_ARB) { crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexEnv"); } else { *param = (GLint) g->point.coordReplacement[t->curTextureUnit]; } return; } else #endif if (target != GL_TEXTURE_ENV) { crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexEnviv: target != GL_TEXTURE_ENV: %d", target); return; } switch (pname) { case GL_TEXTURE_ENV_MODE: *param = (GLint) t->unit[t->curTextureUnit].envMode; break; case GL_TEXTURE_ENV_COLOR: param[0] = (GLint) (t->unit[t->curTextureUnit].envColor.r * CR_MAXINT); param[1] = (GLint) (t->unit[t->curTextureUnit].envColor.g * CR_MAXINT); param[2] = (GLint) (t->unit[t->curTextureUnit].envColor.b * CR_MAXINT); param[3] = (GLint) (t->unit[t->curTextureUnit].envColor.a * CR_MAXINT); break; case GL_COMBINE_RGB_ARB: if (g->extensions.ARB_texture_env_combine) { *param = (GLint) t->unit[t->curTextureUnit].combineModeRGB; } else { crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexEnviv(pname)"); return; } break; case GL_COMBINE_ALPHA_ARB: if (g->extensions.ARB_texture_env_combine) { *param = (GLint) t->unit[t->curTextureUnit].combineModeA; } else { crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexEnviv(pname)"); return; } break; case GL_SOURCE0_RGB_ARB: if (g->extensions.ARB_texture_env_combine) { *param = (GLint) t->unit[t->curTextureUnit].combineSourceRGB[0]; } else { crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexEnviv(pname)"); return; } break; case GL_SOURCE1_RGB_ARB: if (g->extensions.ARB_texture_env_combine) { *param = (GLint) t->unit[t->curTextureUnit].combineSourceRGB[1]; } else { crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexEnviv(pname)"); return; } break; case GL_SOURCE2_RGB_ARB: if (g->extensions.ARB_texture_env_combine) { *param = (GLint) t->unit[t->curTextureUnit].combineSourceRGB[2]; } else { crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexEnviv(pname)"); return; } break; case GL_SOURCE0_ALPHA_ARB: if (g->extensions.ARB_texture_env_combine) { *param = (GLint) t->unit[t->curTextureUnit].combineSourceA[0]; } else { crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexEnviv(pname)"); return; } break; case GL_SOURCE1_ALPHA_ARB: if (g->extensions.ARB_texture_env_combine) { *param = (GLint) t->unit[t->curTextureUnit].combineSourceA[1]; } else { crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexEnviv(pname)"); return; } break; case GL_SOURCE2_ALPHA_ARB: if (g->extensions.ARB_texture_env_combine) { *param = (GLint) t->unit[t->curTextureUnit].combineSourceA[2]; } else { crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexEnviv(pname)"); return; } break; case GL_OPERAND0_RGB_ARB: if (g->extensions.ARB_texture_env_combine) { *param = (GLint) t->unit[t->curTextureUnit].combineOperandRGB[0]; } else { crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexEnviv(pname)"); return; } break; case GL_OPERAND1_RGB_ARB: if (g->extensions.ARB_texture_env_combine) { *param = (GLint) t->unit[t->curTextureUnit].combineOperandRGB[1]; } else { crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexEnviv(pname)"); return; } break; case GL_OPERAND2_RGB_ARB: if (g->extensions.ARB_texture_env_combine) { *param = (GLint) t->unit[t->curTextureUnit].combineOperandRGB[2]; } else { crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexEnviv(pname)"); return; } break; case GL_OPERAND0_ALPHA_ARB: if (g->extensions.ARB_texture_env_combine) { *param = (GLint) t->unit[t->curTextureUnit].combineOperandA[0]; } else { crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexEnviv(pname)"); return; } break; case GL_OPERAND1_ALPHA_ARB: if (g->extensions.ARB_texture_env_combine) { *param = (GLint) t->unit[t->curTextureUnit].combineOperandA[1]; } else { crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexEnviv(pname)"); return; } break; case GL_OPERAND2_ALPHA_ARB: if (g->extensions.ARB_texture_env_combine) { *param = (GLint) t->unit[t->curTextureUnit].combineOperandA[2]; } else { crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexEnviv(pname)"); return; } break; case GL_RGB_SCALE_ARB: if (g->extensions.ARB_texture_env_combine) { *param = (GLint) t->unit[t->curTextureUnit].combineScaleRGB; } else { crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexEnviv(pname)"); return; } break; case GL_ALPHA_SCALE: if (g->extensions.ARB_texture_env_combine) { *param = (GLint) t->unit[t->curTextureUnit].combineScaleA; } else { crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexEnviv(pname)"); return; } break; default: crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexEnviv: invalid pname: %d", pname); return; } } void STATE_APIENTRY crStateTexGendv(GLenum coord, GLenum pname, const GLdouble *param) { CRContext *g = GetCurrentContext(); CRTextureState *t = &(g->texture); CRTransformState *trans = &(g->transform); GLvectorf v; GLenum e; CRmatrix inv; CRStateBits *sb = GetCurrentBits(); CRTextureBits *tb = &(sb->texture); FLUSH(); if (g->current.inBeginEnd) { crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glTexGen called in begin/end"); return; } switch (coord) { case GL_S: switch (pname) { case GL_TEXTURE_GEN_MODE: e = (GLenum) *param; if (e == GL_OBJECT_LINEAR || e == GL_EYE_LINEAR || e == GL_SPHERE_MAP #if defined(GL_ARB_texture_cube_map) || defined(GL_EXT_texture_cube_map) || defined(GL_NV_texgen_reflection) || ((e == GL_REFLECTION_MAP_ARB || e == GL_NORMAL_MAP_ARB) && g->extensions.ARB_texture_cube_map) #endif ) { t->unit[t->curTextureUnit].gen.s = e; DIRTY(tb->genMode[t->curTextureUnit], g->neg_bitid); DIRTY(tb->dirty, g->neg_bitid); } else { crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glTexGendv called with bad param: %lf", *param); return; } break; case GL_OBJECT_PLANE: v.x = (GLfloat) param[0]; v.y = (GLfloat) param[1]; v.z = (GLfloat) param[2]; v.w = (GLfloat) param[3]; t->unit[t->curTextureUnit].objSCoeff = v; DIRTY(tb->objGen[t->curTextureUnit], g->neg_bitid); DIRTY(tb->dirty, g->neg_bitid); break; case GL_EYE_PLANE: v.x = (GLfloat) param[0]; v.y = (GLfloat) param[1]; v.z = (GLfloat) param[2]; v.w = (GLfloat) param[3]; crMatrixInvertTranspose(&inv, trans->modelViewStack.top); crStateTransformXformPointMatrixf(&inv, &v); t->unit[t->curTextureUnit].eyeSCoeff = v; DIRTY(tb->eyeGen[t->curTextureUnit], g->neg_bitid); DIRTY(tb->dirty, g->neg_bitid); break; default: crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glTexGendv called with bogus pname: %d", pname); return; } break; case GL_T: switch (pname) { case GL_TEXTURE_GEN_MODE: e = (GLenum) *param; if (e == GL_OBJECT_LINEAR || e == GL_EYE_LINEAR || e == GL_SPHERE_MAP #if defined(GL_ARB_texture_cube_map) || defined(GL_EXT_texture_cube_map) || defined(GL_NV_texgen_reflection) || ((e == GL_REFLECTION_MAP_ARB || e == GL_NORMAL_MAP_ARB) && g->extensions.ARB_texture_cube_map) #endif ) { t->unit[t->curTextureUnit].gen.t = e; DIRTY(tb->genMode[t->curTextureUnit], g->neg_bitid); DIRTY(tb->dirty, g->neg_bitid); } else { crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glTexGendv called with bad param: %lf", *param); return; } break; case GL_OBJECT_PLANE: v.x = (GLfloat) param[0]; v.y = (GLfloat) param[1]; v.z = (GLfloat) param[2]; v.w = (GLfloat) param[3]; t->unit[t->curTextureUnit].objTCoeff = v; DIRTY(tb->objGen[t->curTextureUnit], g->neg_bitid); DIRTY(tb->dirty, g->neg_bitid); break; case GL_EYE_PLANE: v.x = (GLfloat) param[0]; v.y = (GLfloat) param[1]; v.z = (GLfloat) param[2]; v.w = (GLfloat) param[3]; crMatrixInvertTranspose(&inv, trans->modelViewStack.top); crStateTransformXformPointMatrixf(&inv, &v); t->unit[t->curTextureUnit].eyeTCoeff = v; DIRTY(tb->eyeGen[t->curTextureUnit], g->neg_bitid); DIRTY(tb->dirty, g->neg_bitid); break; default: crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glTexGen called with bogus pname: %d", pname); return; } break; case GL_R: switch (pname) { case GL_TEXTURE_GEN_MODE: e = (GLenum) *param; if (e == GL_OBJECT_LINEAR || e == GL_EYE_LINEAR || e == GL_SPHERE_MAP #if defined(GL_ARB_texture_cube_map) || defined(GL_EXT_texture_cube_map) || defined(GL_NV_texgen_reflection) || ((e == GL_REFLECTION_MAP_ARB || e == GL_NORMAL_MAP_ARB) && g->extensions.ARB_texture_cube_map) #endif ) { t->unit[t->curTextureUnit].gen.r = e; DIRTY(tb->genMode[t->curTextureUnit], g->neg_bitid); DIRTY(tb->dirty, g->neg_bitid); } else { crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glTexGen called with bad param: %lf", *param); return; } break; case GL_OBJECT_PLANE: v.x = (GLfloat) param[0]; v.y = (GLfloat) param[1]; v.z = (GLfloat) param[2]; v.w = (GLfloat) param[3]; t->unit[t->curTextureUnit].objRCoeff = v; DIRTY(tb->objGen[t->curTextureUnit], g->neg_bitid); DIRTY(tb->dirty, g->neg_bitid); break; case GL_EYE_PLANE: v.x = (GLfloat) param[0]; v.y = (GLfloat) param[1]; v.z = (GLfloat) param[2]; v.w = (GLfloat) param[3]; crMatrixInvertTranspose(&inv, trans->modelViewStack.top); crStateTransformXformPointMatrixf(&inv, &v); t->unit[t->curTextureUnit].eyeRCoeff = v; DIRTY(tb->eyeGen[t->curTextureUnit], g->neg_bitid); DIRTY(tb->dirty, g->neg_bitid); break; default: crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glTexGen called with bogus pname: %d", pname); return; } break; case GL_Q: switch (pname) { case GL_TEXTURE_GEN_MODE: e = (GLenum) *param; if (e == GL_OBJECT_LINEAR || e == GL_EYE_LINEAR || e == GL_SPHERE_MAP #if defined(GL_ARB_texture_cube_map) || defined(GL_EXT_texture_cube_map) || defined(GL_NV_texgen_reflection) || ((e == GL_REFLECTION_MAP_ARB || e == GL_NORMAL_MAP_ARB) && g->extensions.ARB_texture_cube_map) #endif ) { t->unit[t->curTextureUnit].gen.q = e; DIRTY(tb->genMode[t->curTextureUnit], g->neg_bitid); DIRTY(tb->dirty, g->neg_bitid); } else { crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glTexGen called with bad param: %lf", *param); return; } break; case GL_OBJECT_PLANE: v.x = (GLfloat) param[0]; v.y = (GLfloat) param[1]; v.z = (GLfloat) param[2]; v.w = (GLfloat) param[3]; t->unit[t->curTextureUnit].objQCoeff = v; DIRTY(tb->objGen[t->curTextureUnit], g->neg_bitid); DIRTY(tb->dirty, g->neg_bitid); break; case GL_EYE_PLANE: v.x = (GLfloat) param[0]; v.y = (GLfloat) param[1]; v.z = (GLfloat) param[2]; v.w = (GLfloat) param[3]; crMatrixInvertTranspose(&inv, trans->modelViewStack.top); crStateTransformXformPointMatrixf(&inv, &v); t->unit[t->curTextureUnit].eyeQCoeff = v; DIRTY(tb->eyeGen[t->curTextureUnit], g->neg_bitid); DIRTY(tb->dirty, g->neg_bitid); break; default: crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glTexGen called with bogus pname: %d", pname); return; } break; default: crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glTexGen called with bogus coord: %d", coord); return; } } void STATE_APIENTRY crStateTexGenfv(GLenum coord, GLenum pname, const GLfloat *param) { GLdouble d_param; GLvectord d_vector; switch (pname) { case GL_TEXTURE_GEN_MODE: d_param = (GLdouble) *param; crStateTexGendv( coord, pname, &d_param ); break; case GL_OBJECT_PLANE: case GL_EYE_PLANE: d_vector.x = (GLdouble) param[0]; d_vector.y = (GLdouble) param[1]; d_vector.z = (GLdouble) param[2]; d_vector.w = (GLdouble) param[3]; crStateTexGendv( coord, pname, (const double *) &d_vector ); break; default: crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glTexGen called with bogus pname: %d", pname); return; } } void STATE_APIENTRY crStateTexGeniv(GLenum coord, GLenum pname, const GLint *param) { GLdouble d_param; GLvectord d_vector; switch (pname) { case GL_TEXTURE_GEN_MODE: d_param = (GLdouble) *param; crStateTexGendv( coord, pname, &d_param ); break; case GL_OBJECT_PLANE: case GL_EYE_PLANE: d_vector.x = (GLdouble) param[0]; d_vector.y = (GLdouble) param[1]; d_vector.z = (GLdouble) param[2]; d_vector.w = (GLdouble) param[3]; crStateTexGendv( coord, pname, (const double *) &d_vector ); break; default: crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glTexGen called with bogus pname: %d", pname); return; } } void STATE_APIENTRY crStateTexGend (GLenum coord, GLenum pname, GLdouble param) { crStateTexGendv( coord, pname, ¶m ); } void STATE_APIENTRY crStateTexGenf(GLenum coord, GLenum pname, GLfloat param) { GLdouble d_param = (GLdouble) param; crStateTexGendv( coord, pname, &d_param ); } void STATE_APIENTRY crStateTexGeni(GLenum coord, GLenum pname, GLint param) { GLdouble d_param = (GLdouble) param; crStateTexGendv( coord, pname, &d_param ); } void STATE_APIENTRY crStateGetTexGendv(GLenum coord, GLenum pname, GLdouble *param) { CRContext *g = GetCurrentContext(); CRTextureState *t = &(g->texture); if (g->current.inBeginEnd) { crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glGetTexGen called in begin/end"); return; } switch (pname) { case GL_TEXTURE_GEN_MODE: switch (coord) { case GL_S: *param = (GLdouble) t->unit[t->curTextureUnit].gen.s; break; case GL_T: *param = (GLdouble) t->unit[t->curTextureUnit].gen.t; break; case GL_R: *param = (GLdouble) t->unit[t->curTextureUnit].gen.r; break; case GL_Q: *param = (GLdouble) t->unit[t->curTextureUnit].gen.q; break; default: crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexGen called with bogus coord: %d", coord); return; } break; case GL_OBJECT_PLANE: switch (coord) { case GL_S: param[0] = (GLdouble) t->unit[t->curTextureUnit].objSCoeff.x; param[1] = (GLdouble) t->unit[t->curTextureUnit].objSCoeff.y; param[2] = (GLdouble) t->unit[t->curTextureUnit].objSCoeff.z; param[3] = (GLdouble) t->unit[t->curTextureUnit].objSCoeff.w; break; case GL_T: param[0] = (GLdouble) t->unit[t->curTextureUnit].objTCoeff.x; param[1] = (GLdouble) t->unit[t->curTextureUnit].objTCoeff.y; param[2] = (GLdouble) t->unit[t->curTextureUnit].objTCoeff.z; param[3] = (GLdouble) t->unit[t->curTextureUnit].objTCoeff.w; break; case GL_R: param[0] = (GLdouble) t->unit[t->curTextureUnit].objRCoeff.x; param[1] = (GLdouble) t->unit[t->curTextureUnit].objRCoeff.y; param[2] = (GLdouble) t->unit[t->curTextureUnit].objRCoeff.z; param[3] = (GLdouble) t->unit[t->curTextureUnit].objRCoeff.w; break; case GL_Q: param[0] = (GLdouble) t->unit[t->curTextureUnit].objQCoeff.x; param[1] = (GLdouble) t->unit[t->curTextureUnit].objQCoeff.y; param[2] = (GLdouble) t->unit[t->curTextureUnit].objQCoeff.z; param[3] = (GLdouble) t->unit[t->curTextureUnit].objQCoeff.w; break; default: crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexGen called with bogus coord: %d", coord); return; } break; case GL_EYE_PLANE: switch (coord) { case GL_S: param[0] = (GLdouble) t->unit[t->curTextureUnit].eyeSCoeff.x; param[1] = (GLdouble) t->unit[t->curTextureUnit].eyeSCoeff.y; param[2] = (GLdouble) t->unit[t->curTextureUnit].eyeSCoeff.z; param[3] = (GLdouble) t->unit[t->curTextureUnit].eyeSCoeff.w; break; case GL_T: param[0] = (GLdouble) t->unit[t->curTextureUnit].eyeTCoeff.x; param[1] = (GLdouble) t->unit[t->curTextureUnit].eyeTCoeff.y; param[2] = (GLdouble) t->unit[t->curTextureUnit].eyeTCoeff.z; param[3] = (GLdouble) t->unit[t->curTextureUnit].eyeTCoeff.w; break; case GL_R: param[0] = (GLdouble) t->unit[t->curTextureUnit].eyeRCoeff.x; param[1] = (GLdouble) t->unit[t->curTextureUnit].eyeRCoeff.y; param[2] = (GLdouble) t->unit[t->curTextureUnit].eyeRCoeff.z; param[3] = (GLdouble) t->unit[t->curTextureUnit].eyeRCoeff.w; break; case GL_Q: param[0] = (GLdouble) t->unit[t->curTextureUnit].eyeQCoeff.x; param[1] = (GLdouble) t->unit[t->curTextureUnit].eyeQCoeff.y; param[2] = (GLdouble) t->unit[t->curTextureUnit].eyeQCoeff.z; param[3] = (GLdouble) t->unit[t->curTextureUnit].eyeQCoeff.w; break; default: crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexGen called with bogus coord: %d", coord); return; } break; default: crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexGen called with bogus pname: %d", pname); return; } } void STATE_APIENTRY crStateGetTexGenfv(GLenum coord, GLenum pname, GLfloat *param) { CRContext *g = GetCurrentContext(); CRTextureState *t = &(g->texture); if (g->current.inBeginEnd) { crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glGetTexGenfv called in begin/end"); return; } switch (pname) { case GL_TEXTURE_GEN_MODE: switch (coord) { case GL_S: *param = (GLfloat) t->unit[t->curTextureUnit].gen.s; break; case GL_T: *param = (GLfloat) t->unit[t->curTextureUnit].gen.t; break; case GL_R: *param = (GLfloat) t->unit[t->curTextureUnit].gen.r; break; case GL_Q: *param = (GLfloat) t->unit[t->curTextureUnit].gen.q; break; default: crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexGenfv called with bogus coord: %d", coord); return; } break; case GL_OBJECT_PLANE: switch (coord) { case GL_S: param[0] = t->unit[t->curTextureUnit].objSCoeff.x; param[1] = t->unit[t->curTextureUnit].objSCoeff.y; param[2] = t->unit[t->curTextureUnit].objSCoeff.z; param[3] = t->unit[t->curTextureUnit].objSCoeff.w; break; case GL_T: param[0] = t->unit[t->curTextureUnit].objTCoeff.x; param[1] = t->unit[t->curTextureUnit].objTCoeff.y; param[2] = t->unit[t->curTextureUnit].objTCoeff.z; param[3] = t->unit[t->curTextureUnit].objTCoeff.w; break; case GL_R: param[0] = t->unit[t->curTextureUnit].objRCoeff.x; param[1] = t->unit[t->curTextureUnit].objRCoeff.y; param[2] = t->unit[t->curTextureUnit].objRCoeff.z; param[3] = t->unit[t->curTextureUnit].objRCoeff.w; break; case GL_Q: param[0] = t->unit[t->curTextureUnit].objQCoeff.x; param[1] = t->unit[t->curTextureUnit].objQCoeff.y; param[2] = t->unit[t->curTextureUnit].objQCoeff.z; param[3] = t->unit[t->curTextureUnit].objQCoeff.w; break; default: crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexGenfv called with bogus coord: %d", coord); return; } break; case GL_EYE_PLANE: switch (coord) { case GL_S: param[0] = t->unit[t->curTextureUnit].eyeSCoeff.x; param[1] = t->unit[t->curTextureUnit].eyeSCoeff.y; param[2] = t->unit[t->curTextureUnit].eyeSCoeff.z; param[3] = t->unit[t->curTextureUnit].eyeSCoeff.w; break; case GL_T: param[0] = t->unit[t->curTextureUnit].eyeTCoeff.x; param[1] = t->unit[t->curTextureUnit].eyeTCoeff.y; param[2] = t->unit[t->curTextureUnit].eyeTCoeff.z; param[3] = t->unit[t->curTextureUnit].eyeTCoeff.w; break; case GL_R: param[0] = t->unit[t->curTextureUnit].eyeRCoeff.x; param[1] = t->unit[t->curTextureUnit].eyeRCoeff.y; param[2] = t->unit[t->curTextureUnit].eyeRCoeff.z; param[3] = t->unit[t->curTextureUnit].eyeRCoeff.w; break; case GL_Q: param[0] = t->unit[t->curTextureUnit].eyeQCoeff.x; param[1] = t->unit[t->curTextureUnit].eyeQCoeff.y; param[2] = t->unit[t->curTextureUnit].eyeQCoeff.z; param[3] = t->unit[t->curTextureUnit].eyeQCoeff.w; break; default: crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexGenfv called with bogus coord: %d", coord); return; } break; default: crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexGenfv called with bogus pname: %d", pname); return; } } void STATE_APIENTRY crStateGetTexGeniv(GLenum coord, GLenum pname, GLint *param) { CRContext *g = GetCurrentContext(); CRTextureState *t = &(g->texture); if (g->current.inBeginEnd) { crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glGetTexGeniv called in begin/end"); return; } switch (pname) { case GL_TEXTURE_GEN_MODE: switch (coord) { case GL_S: *param = (GLint) t->unit[t->curTextureUnit].gen.s; break; case GL_T: *param = (GLint) t->unit[t->curTextureUnit].gen.t; break; case GL_R: *param = (GLint) t->unit[t->curTextureUnit].gen.r; break; case GL_Q: *param = (GLint) t->unit[t->curTextureUnit].gen.q; break; default: crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexGeniv called with bogus coord: %d", coord); return; } break; case GL_OBJECT_PLANE: switch (coord) { case GL_S: param[0] = (GLint) t->unit[t->curTextureUnit].objSCoeff.x; param[1] = (GLint) t->unit[t->curTextureUnit].objSCoeff.y; param[2] = (GLint) t->unit[t->curTextureUnit].objSCoeff.z; param[3] = (GLint) t->unit[t->curTextureUnit].objSCoeff.w; break; case GL_T: param[0] = (GLint) t->unit[t->curTextureUnit].objTCoeff.x; param[1] = (GLint) t->unit[t->curTextureUnit].objTCoeff.y; param[2] = (GLint) t->unit[t->curTextureUnit].objTCoeff.z; param[3] = (GLint) t->unit[t->curTextureUnit].objTCoeff.w; break; case GL_R: param[0] = (GLint) t->unit[t->curTextureUnit].objRCoeff.x; param[1] = (GLint) t->unit[t->curTextureUnit].objRCoeff.y; param[2] = (GLint) t->unit[t->curTextureUnit].objRCoeff.z; param[3] = (GLint) t->unit[t->curTextureUnit].objRCoeff.w; break; case GL_Q: param[0] = (GLint) t->unit[t->curTextureUnit].objQCoeff.x; param[1] = (GLint) t->unit[t->curTextureUnit].objQCoeff.y; param[2] = (GLint) t->unit[t->curTextureUnit].objQCoeff.z; param[3] = (GLint) t->unit[t->curTextureUnit].objQCoeff.w; break; default: crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexGeniv called with bogus coord: %d", coord); return; } break; case GL_EYE_PLANE: switch (coord) { case GL_S: param[0] = (GLint) t->unit[t->curTextureUnit].eyeSCoeff.x; param[1] = (GLint) t->unit[t->curTextureUnit].eyeSCoeff.y; param[2] = (GLint) t->unit[t->curTextureUnit].eyeSCoeff.z; param[3] = (GLint) t->unit[t->curTextureUnit].eyeSCoeff.w; break; case GL_T: param[0] = (GLint) t->unit[t->curTextureUnit].eyeTCoeff.x; param[1] = (GLint) t->unit[t->curTextureUnit].eyeTCoeff.y; param[2] = (GLint) t->unit[t->curTextureUnit].eyeTCoeff.z; param[3] = (GLint) t->unit[t->curTextureUnit].eyeTCoeff.w; break; case GL_R: param[0] = (GLint) t->unit[t->curTextureUnit].eyeRCoeff.x; param[1] = (GLint) t->unit[t->curTextureUnit].eyeRCoeff.y; param[2] = (GLint) t->unit[t->curTextureUnit].eyeRCoeff.z; param[3] = (GLint) t->unit[t->curTextureUnit].eyeRCoeff.w; break; case GL_Q: param[0] = (GLint) t->unit[t->curTextureUnit].eyeQCoeff.x; param[1] = (GLint) t->unit[t->curTextureUnit].eyeQCoeff.y; param[2] = (GLint) t->unit[t->curTextureUnit].eyeQCoeff.z; param[3] = (GLint) t->unit[t->curTextureUnit].eyeQCoeff.w; break; default: crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexGeniv called with bogus coord: %d", coord); return; } break; default: crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexGen called with bogus pname: %d", pname); return; } } void STATE_APIENTRY crStateGetTexLevelParameterfv(GLenum target, GLint level, GLenum pname, GLfloat *params) { CRContext *g = GetCurrentContext(); CRTextureState *t = &(g->texture); CRTextureObj *tobj; CRTextureLevel *timg; if (g->current.inBeginEnd) { crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glGetTexLevelParameterfv called in begin/end"); return; } if (level < 0 && level > t->maxLevel) { crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "glGetTexLevelParameterfv: Invalid level: %d", level); return; } crStateGetTextureObjectAndImage(g, target, level, &tobj, &timg); if (!timg) { crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "GetTexLevelParameterfv: invalid target: 0x%x or level %d", target, level); return; } switch (pname) { case GL_TEXTURE_WIDTH: *params = (GLfloat) timg->width; break; case GL_TEXTURE_HEIGHT: *params = (GLfloat) timg->height; break; #ifdef CR_OPENGL_VERSION_1_2 case GL_TEXTURE_DEPTH: *params = (GLfloat) timg->depth; break; #endif case GL_TEXTURE_INTERNAL_FORMAT: *params = (GLfloat) timg->internalFormat; break; case GL_TEXTURE_BORDER: *params = (GLfloat) timg->border; break; case GL_TEXTURE_RED_SIZE: *params = (GLfloat) timg->texFormat->redbits; break; case GL_TEXTURE_GREEN_SIZE: *params = (GLfloat) timg->texFormat->greenbits; break; case GL_TEXTURE_BLUE_SIZE: *params = (GLfloat) timg->texFormat->bluebits; break; case GL_TEXTURE_ALPHA_SIZE: *params = (GLfloat) timg->texFormat->alphabits; break; case GL_TEXTURE_INTENSITY_SIZE: *params = (GLfloat) timg->texFormat->intensitybits; break; case GL_TEXTURE_LUMINANCE_SIZE: *params = (GLfloat) timg->texFormat->luminancebits; break; #if CR_ARB_texture_compression case GL_TEXTURE_COMPRESSED_IMAGE_SIZE_ARB: *params = (GLfloat) timg->bytes; break; case GL_TEXTURE_COMPRESSED_ARB: *params = (GLfloat) timg->compressed; break; #endif default: crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "GetTexLevelParameterfv: invalid pname: 0x%x", pname); return; } } void STATE_APIENTRY crStateGetTexLevelParameteriv(GLenum target, GLint level, GLenum pname, GLint *params) { CRContext *g = GetCurrentContext(); CRTextureState *t = &(g->texture); CRTextureObj *tobj; CRTextureLevel *timg; if (g->current.inBeginEnd) { crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glGetTexLevelParameteriv called in begin/end"); return; } if (level < 0 && level > t->maxLevel) { crStateError(__LINE__, __FILE__, GL_INVALID_VALUE, "glGetTexLevelParameteriv: Invalid level: %d", level); return; } crStateGetTextureObjectAndImage(g, target, level, &tobj, &timg); if (!timg) { crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "GetTexLevelParameteriv: invalid target: 0x%x", target); return; } switch (pname) { case GL_TEXTURE_WIDTH: *params = (GLint) timg->width; break; case GL_TEXTURE_HEIGHT: *params = (GLint) timg->height; break; #ifdef CR_OPENGL_VERSION_1_2 case GL_TEXTURE_DEPTH: *params = (GLint) timg->depth; break; #endif case GL_TEXTURE_INTERNAL_FORMAT: *params = (GLint) timg->internalFormat; break; case GL_TEXTURE_BORDER: *params = (GLint) timg->border; break; case GL_TEXTURE_RED_SIZE: *params = (GLint) timg->texFormat->redbits; break; case GL_TEXTURE_GREEN_SIZE: *params = (GLint) timg->texFormat->greenbits; break; case GL_TEXTURE_BLUE_SIZE: *params = (GLint) timg->texFormat->bluebits; break; case GL_TEXTURE_ALPHA_SIZE: *params = (GLint) timg->texFormat->alphabits; break; case GL_TEXTURE_INTENSITY_SIZE: *params = (GLint) timg->texFormat->intensitybits; break; case GL_TEXTURE_LUMINANCE_SIZE: *params = (GLint) timg->texFormat->luminancebits; break; #if 0 /* XXX TODO */ case GL_TEXTURE_DEPTH_SIZE: *params = (GLint) timg->texFormat->depthSize; break; #endif #if CR_ARB_texture_compression case GL_TEXTURE_COMPRESSED_IMAGE_SIZE_ARB: *params = (GLint) timg->bytes; break; case GL_TEXTURE_COMPRESSED_ARB: *params = (GLint) timg->compressed; break; #endif default: crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "GetTexLevelParameteriv: invalid pname: 0x%x", pname); return; } } void STATE_APIENTRY crStateGetTexParameterfv(GLenum target, GLenum pname, GLfloat *params) { CRContext *g = GetCurrentContext(); CRTextureObj *tobj; CRTextureLevel *tl; if (g->current.inBeginEnd) { crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glGetTexParameterfv called in begin/end"); return; } crStateGetTextureObjectAndImage(g, target, 0, &tobj, &tl); if (!tobj) { crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexParameterfv: invalid target: 0x%x", target); return; } switch (pname) { case GL_TEXTURE_MAG_FILTER: *params = (GLfloat) tobj->magFilter; break; case GL_TEXTURE_MIN_FILTER: *params = (GLfloat) tobj->minFilter; break; case GL_TEXTURE_WRAP_S: *params = (GLfloat) tobj->wrapS; break; case GL_TEXTURE_WRAP_T: *params = (GLfloat) tobj->wrapT; break; #ifdef CR_OPENGL_VERSION_1_2 case GL_TEXTURE_WRAP_R: *params = (GLfloat) tobj->wrapR; break; case GL_TEXTURE_PRIORITY: *params = (GLfloat) tobj->priority; break; #endif case GL_TEXTURE_BORDER_COLOR: params[0] = tobj->borderColor.r; params[1] = tobj->borderColor.g; params[2] = tobj->borderColor.b; params[3] = tobj->borderColor.a; break; #ifdef CR_EXT_texture_filter_anisotropic case GL_TEXTURE_MAX_ANISOTROPY_EXT: if (g->extensions.EXT_texture_filter_anisotropic) { *params = (GLfloat) tobj->maxAnisotropy; } else { crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexParameterfv: invalid pname: 0x%x", pname); return; } break; #endif #ifdef CR_ARB_depth_texture case GL_DEPTH_TEXTURE_MODE_ARB: if (g->extensions.ARB_depth_texture) { *params = (GLfloat) tobj->depthMode; } else { crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexParameter: invalid pname: 0x%x", pname); return; } break; #endif #ifdef CR_ARB_shadow case GL_TEXTURE_COMPARE_MODE_ARB: if (g->extensions.ARB_shadow) { *params = (GLfloat) tobj->compareMode; } else { crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexParameter: invalid pname: 0x%x", pname); return; } break; case GL_TEXTURE_COMPARE_FUNC_ARB: if (g->extensions.ARB_shadow) { *params = (GLfloat) tobj->compareFunc; } else { crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexParameter: invalid pname: 0x%x", pname); return; } break; #endif #ifdef CR_ARB_shadow_ambient case GL_TEXTURE_COMPARE_FAIL_VALUE_ARB: if (g->extensions.ARB_shadow_ambient) { *params = (GLfloat) tobj->compareFailValue; } else { crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexParameter: invalid pname: 0x%x", pname); return; } break; #endif #ifdef CR_SGIS_generate_mipmap case GL_GENERATE_MIPMAP_SGIS: if (g->extensions.SGIS_generate_mipmap) { *params = (GLfloat) tobj->generateMipmap; } else { crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexParameter: invalid pname: 0x%x", pname); return; } break; #endif #ifdef CR_OPENGL_VERSION_1_2 case GL_TEXTURE_MIN_LOD: *params = (GLfloat) tobj->minLod; break; case GL_TEXTURE_MAX_LOD: *params = (GLfloat) tobj->maxLod; break; case GL_TEXTURE_BASE_LEVEL: *params = (GLfloat) tobj->baseLevel; break; case GL_TEXTURE_MAX_LEVEL: *params = (GLfloat) tobj->maxLevel; break; #endif #if 0 case GL_TEXTURE_LOD_BIAS_EXT: /* XXX todo */ *params = (GLfloat) tobj->lodBias; break; #endif case GL_TEXTURE_RESIDENT: /* XXX todo */ crWarning("glGetTexParameterfv GL_TEXTURE_RESIDENT is unimplemented"); break; default: crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexParameterfv: invalid pname: %d", pname); return; } } void STATE_APIENTRY crStateGetTexParameteriv(GLenum target, GLenum pname, GLint *params) { CRContext *g = GetCurrentContext(); CRTextureObj *tobj; CRTextureLevel *tl; if (g->current.inBeginEnd) { crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glGetTexParameter called in begin/end"); return; } crStateGetTextureObjectAndImage(g, target, 0, &tobj, &tl); if (!tobj) { crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexParameteriv: invalid target: 0x%x", target); return; } switch (pname) { case GL_TEXTURE_MAG_FILTER: *params = (GLint) tobj->magFilter; break; case GL_TEXTURE_MIN_FILTER: *params = (GLint) tobj->minFilter; break; case GL_TEXTURE_WRAP_S: *params = (GLint) tobj->wrapS; break; case GL_TEXTURE_WRAP_T: *params = (GLint) tobj->wrapT; break; #ifdef CR_OPENGL_VERSION_1_2 case GL_TEXTURE_WRAP_R: *params = (GLint) tobj->wrapR; break; case GL_TEXTURE_PRIORITY: *params = (GLint) tobj->priority; break; #endif case GL_TEXTURE_BORDER_COLOR: params[0] = (GLint) (tobj->borderColor.r * CR_MAXINT); params[1] = (GLint) (tobj->borderColor.g * CR_MAXINT); params[2] = (GLint) (tobj->borderColor.b * CR_MAXINT); params[3] = (GLint) (tobj->borderColor.a * CR_MAXINT); break; #ifdef CR_OPENGL_VERSION_1_2 case GL_TEXTURE_MIN_LOD: *params = (GLint) tobj->minLod; break; case GL_TEXTURE_MAX_LOD: *params = (GLint) tobj->maxLod; break; case GL_TEXTURE_BASE_LEVEL: *params = (GLint) tobj->baseLevel; break; case GL_TEXTURE_MAX_LEVEL: *params = (GLint) tobj->maxLevel; break; #endif #ifdef CR_EXT_texture_filter_anisotropic case GL_TEXTURE_MAX_ANISOTROPY_EXT: if (g->extensions.EXT_texture_filter_anisotropic) { *params = (GLint) tobj->maxAnisotropy; } else { crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexParameter: invalid pname: 0x%x", pname); return; } break; #endif #ifdef CR_ARB_depth_texture case GL_DEPTH_TEXTURE_MODE_ARB: if (g->extensions.ARB_depth_texture) { *params = (GLint) tobj->depthMode; } else { crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexParameter: invalid pname: 0x%x", pname); return; } break; #endif #ifdef CR_ARB_shadow case GL_TEXTURE_COMPARE_MODE_ARB: if (g->extensions.ARB_shadow) { *params = (GLint) tobj->compareMode; } else { crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexParameter: invalid pname: 0x%x", pname); return; } break; case GL_TEXTURE_COMPARE_FUNC_ARB: if (g->extensions.ARB_shadow) { *params = (GLint) tobj->compareFunc; } else { crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexParameter: invalid pname: 0x%x", pname); return; } break; #endif #ifdef CR_ARB_shadow_ambient case GL_TEXTURE_COMPARE_FAIL_VALUE_ARB: if (g->extensions.ARB_shadow_ambient) { *params = (GLint) tobj->compareFailValue; } else { crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexParameter: invalid pname: 0x%x", pname); return; } break; #endif #ifdef CR_SGIS_generate_mipmap case GL_GENERATE_MIPMAP_SGIS: if (g->extensions.SGIS_generate_mipmap) { *params = (GLint) tobj->generateMipmap; } else { crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexParameter: invalid pname: 0x%x", pname); return; } break; #endif case GL_TEXTURE_RESIDENT: /* XXX todo */ crWarning("glGetTexParameteriv GL_TEXTURE_RESIDENT is unimplemented"); break; default: crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glGetTexParameter: invalid pname: %d", pname); return; } } void STATE_APIENTRY crStatePrioritizeTextures(GLsizei n, const GLuint *textures, const GLclampf *priorities) { CRContext *g = GetCurrentContext(); CRTextureObj *tobj; GLsizei i; UNUSED(priorities); for (i = 0; i < n; ++i) { GLuint tex = textures[i]; GET_TOBJ(tobj, g, tex); if (!tobj) { Assert(crHashtableIsKeyUsed(g->shared->textureTable, tex)); tobj = crStateTextureAllocate_t(g, tex); } /* so far the code just ensures the tex object is created to make * the crserverlib code be able to pass it to host ogl */ /* TODO: store texture priorities in the state data to be able to restore it properly * on save state load */ } return; } GLboolean STATE_APIENTRY crStateAreTexturesResident(GLsizei n, const GLuint *textures, GLboolean *residences) { UNUSED(n); UNUSED(textures); UNUSED(residences); /* TODO: */ return GL_TRUE; } GLboolean STATE_APIENTRY crStateIsTexture(GLuint texture) { CRContext *g = GetCurrentContext(); CRTextureObj *tobj; GET_TOBJ(tobj, g, texture); return tobj != NULL; } static void crStateCheckTextureHWIDCB(unsigned long key, void *data1, void *data2) { CRTextureObj *pTex = (CRTextureObj *) data1; crCheckIDHWID_t *pParms = (crCheckIDHWID_t*) data2; (void) key; if (crStateGetTextureObjHWID(pTex)==pParms->hwid) pParms->id = pTex->id; } DECLEXPORT(GLuint) STATE_APIENTRY crStateTextureHWIDtoID(GLuint hwid) { CRContext *g = GetCurrentContext(); crCheckIDHWID_t parms; parms.id = hwid; parms.hwid = hwid; crHashtableWalk(g->shared->textureTable, crStateCheckTextureHWIDCB, &parms); return parms.id; } DECLEXPORT(GLuint) STATE_APIENTRY crStateGetTextureHWID(GLuint id) { CRContext *g = GetCurrentContext(); CRTextureObj *tobj; GET_TOBJ(tobj, g, id); #ifdef DEBUG_misha if (id) { Assert(tobj); } else { Assert(!tobj); } if (tobj) { crDebug("tex id(%d), hwid(%d)", tobj->id, tobj->hwid); } #endif return tobj ? crStateGetTextureObjHWID(tobj) : 0; } DECLEXPORT(GLuint) STATE_APIENTRY crStateGetTextureObjHWID(CRTextureObj *tobj) { CRASSERT(tobj); #ifndef IN_GUEST if (tobj->id && !tobj->hwid) { CRASSERT(diff_api.GenTextures); diff_api.GenTextures(1, &tobj->hwid); #ifdef DEBUG_misha crDebug("tex id(%d), hwid(%d)", tobj->id, tobj->hwid); #endif CRASSERT(tobj->hwid); } #endif return tobj->hwid; }