/* $XFree86: xc/lib/GL/mesa/src/drv/gamma/gamma_tex.c,v 1.4 2002/11/05 17:46:07 tsi Exp $ */ #include #include #include "glheader.h" #include "mtypes.h" #include "imports.h" #include "simple_list.h" #include "enums.h" #include "texstore.h" #include "teximage.h" #include "texformat.h" #include "texobj.h" #include "swrast/swrast.h" #include "mm.h" #include "gamma_context.h" #include "colormac.h" /* * Compute the 'S2.4' lod bias factor from the floating point OpenGL bias. */ #if 0 static GLuint gammaComputeLodBias(GLfloat bias) { return bias; } #endif static void gammaSetTexWrapping(gammaTextureObjectPtr t, GLenum wraps, GLenum wrapt) { CARD32 t1 = t->TextureAddressMode; CARD32 t2 = t->TextureReadMode; t1 &= ~(TAM_SWrap_Mask | TAM_TWrap_Mask); t2 &= ~(TRM_UWrap_Mask | TRM_VWrap_Mask); if (wraps != GL_CLAMP) { t1 |= TAM_SWrap_Repeat; t2 |= TRM_UWrap_Repeat; } if (wrapt != GL_CLAMP) { t1 |= TAM_TWrap_Repeat; t2 |= TRM_VWrap_Repeat; } t->TextureAddressMode = t1; t->TextureReadMode = t2; } static void gammaSetTexFilter(gammaContextPtr gmesa, gammaTextureObjectPtr t, GLenum minf, GLenum magf, GLfloat bias) { CARD32 t1 = t->TextureAddressMode; CARD32 t2 = t->TextureReadMode; t2 &= ~(TRM_Mag_Mask | TRM_Min_Mask); switch (minf) { case GL_NEAREST: t1 &= ~TAM_LODEnable; t2 &= ~TRM_MipMapEnable; t2 |= TRM_Min_Nearest; break; case GL_LINEAR: t1 &= ~TAM_LODEnable; t2 &= ~TRM_MipMapEnable; t2 |= TRM_Min_Linear; break; case GL_NEAREST_MIPMAP_NEAREST: t2 |= TRM_Min_NearestMMNearest; break; case GL_LINEAR_MIPMAP_NEAREST: t2 |= TRM_Min_LinearMMNearest; break; case GL_NEAREST_MIPMAP_LINEAR: t2 |= TRM_Min_NearestMMLinear; break; case GL_LINEAR_MIPMAP_LINEAR: t2 |= TRM_Min_LinearMMLinear; break; default: break; } switch (magf) { case GL_NEAREST: t2 |= TRM_Mag_Nearest; break; case GL_LINEAR: t2 |= TRM_Mag_Linear; break; default: break; } t->TextureAddressMode = t1; t->TextureReadMode = t2; } static void gammaSetTexBorderColor(gammaContextPtr gmesa, gammaTextureObjectPtr t, GLubyte color[4]) { t->TextureBorderColor = PACK_COLOR_8888(color[0], color[1], color[2], color[3]); } static void gammaTexParameter( GLcontext *ctx, GLenum target, struct gl_texture_object *tObj, GLenum pname, const GLfloat *params ) { gammaContextPtr gmesa = GAMMA_CONTEXT(ctx); gammaTextureObjectPtr t = (gammaTextureObjectPtr) tObj->DriverData; if (!t) return; /* Can't do the update now as we don't know whether to flush * vertices or not. Setting gmesa->new_state means that * gammaUpdateTextureState() will be called before any triangles are * rendered. If a statechange has occurred, it will be detected at * that point, and buffered vertices flushed. */ switch (pname) { case GL_TEXTURE_MIN_FILTER: case GL_TEXTURE_MAG_FILTER: { GLfloat bias = ctx->Texture.Unit[ctx->Texture.CurrentUnit].LodBias; gammaSetTexFilter( gmesa, t, tObj->MinFilter, tObj->MagFilter, bias ); } break; case GL_TEXTURE_WRAP_S: case GL_TEXTURE_WRAP_T: gammaSetTexWrapping( t, tObj->WrapS, tObj->WrapT ); break; case GL_TEXTURE_BORDER_COLOR: gammaSetTexBorderColor( gmesa, t, tObj->_BorderChan ); break; case GL_TEXTURE_BASE_LEVEL: case GL_TEXTURE_MAX_LEVEL: case GL_TEXTURE_MIN_LOD: case GL_TEXTURE_MAX_LOD: /* This isn't the most efficient solution but there doesn't appear to * be a nice alternative for Radeon. Since there's no LOD clamping, * we just have to rely on loading the right subset of mipmap levels * to simulate a clamped LOD. */ gammaSwapOutTexObj( gmesa, t ); break; default: return; } if (t == gmesa->CurrentTexObj[0]) gmesa->dirty |= GAMMA_UPLOAD_TEX0; #if 0 if (t == gmesa->CurrentTexObj[1]) { gmesa->dirty |= GAMMA_UPLOAD_TEX1; } #endif } static void gammaTexEnv( GLcontext *ctx, GLenum target, GLenum pname, const GLfloat *param ) { gammaContextPtr gmesa = GAMMA_CONTEXT( ctx ); GLuint unit = ctx->Texture.CurrentUnit; /* Only one env color. Need a fallback if env colors are different * and texture setup references env color in both units. */ switch (pname) { case GL_TEXTURE_ENV_COLOR: { struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit]; GLfloat *fc = texUnit->EnvColor; GLuint r, g, b, a, col; CLAMPED_FLOAT_TO_UBYTE(r, fc[0]); CLAMPED_FLOAT_TO_UBYTE(g, fc[1]); CLAMPED_FLOAT_TO_UBYTE(b, fc[2]); CLAMPED_FLOAT_TO_UBYTE(a, fc[3]); col = ((a << 24) | (r << 16) | (g << 8) | (b << 0)); break; } case GL_TEXTURE_ENV_MODE: gmesa->TexEnvImageFmt[unit] = 0; /* force recalc of env state */ break; case GL_TEXTURE_LOD_BIAS_EXT: #if 0 /* ?!?!?! */ { struct gl_texture_object *tObj = ctx->Texture.Unit[unit]._Current; gammaTextureObjectPtr t = (gammaTextureObjectPtr) tObj->DriverData; (void) t; /* XXX Looks like there's something missing here */ } #endif break; default: break; } } #if 0 static void gammaTexImage1D( GLcontext *ctx, GLenum target, GLint level, GLint internalFormat, GLint width, GLint border, GLenum format, GLenum type, const GLvoid *pixels, const struct gl_pixelstore_attrib *pack, struct gl_texture_object *texObj, struct gl_texture_image *texImage ) { gammaTextureObjectPtr t = (gammaTextureObjectPtr) texObj->DriverData; if (t) { gammaSwapOutTexObj( GAMMA_CONTEXT(ctx), t ); } _mesa_store_teximage1d( ctx, target, level, internalFormat, width, border, format, type, pixels, pack, texObj, texImage ); } #endif #if 0 static void gammaTexSubImage1D( GLcontext *ctx, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels, const struct gl_pixelstore_attrib *pack, struct gl_texture_object *texObj, struct gl_texture_image *texImage ) { gammaTextureObjectPtr t = (gammaTextureObjectPtr) texObj->DriverData; if (t) { gammaSwapOutTexObj( GAMMA_CONTEXT(ctx), t ); } _mesa_store_texsubimage1d(ctx, target, level, xoffset, width, format, type, pixels, pack, texObj, texImage); } #endif static void gammaTexImage2D( GLcontext *ctx, GLenum target, GLint level, GLint internalFormat, GLint width, GLint height, GLint border, GLenum format, GLenum type, const GLvoid *pixels, const struct gl_pixelstore_attrib *packing, struct gl_texture_object *texObj, struct gl_texture_image *texImage ) { gammaTextureObjectPtr t = (gammaTextureObjectPtr) texObj->DriverData; if (t) { gammaSwapOutTexObj( GAMMA_CONTEXT(ctx), t ); } _mesa_store_teximage2d( ctx, target, level, internalFormat, width, height, border, format, type, pixels, packing, texObj, texImage ); } static void gammaTexSubImage2D( GLcontext *ctx, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels, const struct gl_pixelstore_attrib *packing, struct gl_texture_object *texObj, struct gl_texture_image *texImage ) { gammaTextureObjectPtr t = (gammaTextureObjectPtr) texObj->DriverData; if (t) { gammaSwapOutTexObj( GAMMA_CONTEXT(ctx), t ); } _mesa_store_texsubimage2d(ctx, target, level, xoffset, yoffset, width, height, format, type, pixels, packing, texObj, texImage); } #if 0 /* no longer needed */ static void gammaBindTexture( GLcontext *ctx, GLenum target, struct gl_texture_object *tObj ) { gammaContextPtr gmesa = GAMMA_CONTEXT( ctx ); gammaTextureObjectPtr t = (gammaTextureObjectPtr) tObj->DriverData; if (!t) { GLfloat bias = ctx->Texture.Unit[ctx->Texture.CurrentUnit].LodBias; t = CALLOC_STRUCT(gamma_texture_object_t); /* Initialize non-image-dependent parts of the state: */ t->globj = tObj; t->TextureAddressMode = TextureAddressModeEnable | TAM_Operation_3D | TAM_DY_Enable | TAM_LODEnable; t->TextureReadMode = TextureReadModeEnable | TRM_PrimaryCacheEnable | TRM_MipMapEnable | TRM_BorderClamp | TRM_Border; t->TextureColorMode = TextureColorModeEnable; t->TextureFilterMode = TextureFilterModeEnable; if (target == GL_TEXTURE_2D) { t->TextureAddressMode |= TAM_TexMapType_2D; t->TextureReadMode |= TRM_TexMapType_2D; } else if (target == GL_TEXTURE_1D) { t->TextureAddressMode |= TAM_TexMapType_1D; t->TextureReadMode |= TRM_TexMapType_1D; } t->TextureColorMode = TextureColorModeEnable; t->TextureFilterMode = TextureFilterModeEnable; #ifdef MESA_LITTLE_ENDIAN t->TextureFormat = (TF_LittleEndian | #else t->TextureFormat = (TF_BigEndian | #endif TF_ColorOrder_RGB | TF_OutputFmt_Texel); t->dirty_images = ~0; tObj->DriverData = t; make_empty_list( t ); gammaSetTexWrapping( t, tObj->WrapS, tObj->WrapT ); gammaSetTexFilter( gmesa, t, tObj->MinFilter, tObj->MagFilter, bias ); gammaSetTexBorderColor( gmesa, t, tObj->_BorderChan ); } } #endif static void gammaDeleteTexture( GLcontext *ctx, struct gl_texture_object *tObj ) { gammaTextureObjectPtr t = (gammaTextureObjectPtr)tObj->DriverData; if (t) { gammaContextPtr gmesa = GAMMA_CONTEXT( ctx ); #if 0 if (gmesa) GAMMA_FIREVERTICES( gmesa ); #endif gammaDestroyTexObj( gmesa, t ); tObj->DriverData = 0; } /* Free mipmap images and the texture object itself */ _mesa_delete_texture_object(ctx, tObj); } static GLboolean gammaIsTextureResident( GLcontext *ctx, struct gl_texture_object *tObj ) { gammaTextureObjectPtr t = (gammaTextureObjectPtr)tObj->DriverData; return t && t->MemBlock; } /** * Allocate a new texture object. * Called via ctx->Driver.NewTextureObject. * Note: this function will be called during context creation to * allocate the default texture objects. */ static struct gl_texture_object * gammaNewTextureObject( GLcontext *ctx, GLuint name, GLenum target ) { gammaContextPtr gmesa = GAMMA_CONTEXT( ctx ); struct gl_texture_object *obj; gammaTextureObjectPtr t; obj = _mesa_new_texture_object(ctx, name, target); if (!obj) return NULL; t = CALLOC_STRUCT(gamma_texture_object_t); if (!t) { _mesa_delete_texture_object(ctx, obj); return NULL; } /* Initialize non-image-dependent parts of the state: */ t->globj = obj; obj->DriverData = t; t->TextureAddressMode = TextureAddressModeEnable | TAM_Operation_3D | TAM_DY_Enable | TAM_LODEnable; t->TextureReadMode = TextureReadModeEnable | TRM_PrimaryCacheEnable | TRM_MipMapEnable | TRM_BorderClamp | TRM_Border; t->TextureColorMode = TextureColorModeEnable; t->TextureFilterMode = TextureFilterModeEnable; if (target == GL_TEXTURE_2D) { t->TextureAddressMode |= TAM_TexMapType_2D; t->TextureReadMode |= TRM_TexMapType_2D; } else if (target == GL_TEXTURE_1D) { t->TextureAddressMode |= TAM_TexMapType_1D; t->TextureReadMode |= TRM_TexMapType_1D; } t->TextureColorMode = TextureColorModeEnable; t->TextureFilterMode = TextureFilterModeEnable; #ifdef MESA_LITTLE_ENDIAN t->TextureFormat = (TF_LittleEndian | #else t->TextureFormat = (TF_BigEndian | #endif TF_ColorOrder_RGB | TF_OutputFmt_Texel); t->dirty_images = ~0; make_empty_list( t ); gammaSetTexWrapping( t, obj->WrapS, obj->WrapT ); gammaSetTexFilter( gmesa, t, obj->MinFilter, obj->MagFilter, ctx->Texture.Unit[ctx->Texture.CurrentUnit].LodBias); gammaSetTexBorderColor( gmesa, t, obj->_BorderChan ); return obj; } #if 0 /* no longer needed */ void gammaInitTextureObjects( GLcontext *ctx ) { struct gl_texture_object *texObj; GLuint tmp = ctx->Texture.CurrentUnit; ctx->Texture.CurrentUnit = 0; texObj = ctx->Texture.Unit[0].Current1D; gammaBindTexture( ctx, GL_TEXTURE_1D, texObj ); texObj = ctx->Texture.Unit[0].Current2D; gammaBindTexture( ctx, GL_TEXTURE_2D, texObj ); #if 0 ctx->Texture.CurrentUnit = 1; texObj = ctx->Texture.Unit[1].Current1D; gammaBindTexture( ctx, GL_TEXTURE_1D, texObj ); texObj = ctx->Texture.Unit[1].Current2D; gammaBindTexture( ctx, GL_TEXTURE_2D, texObj ); #endif ctx->Texture.CurrentUnit = tmp; } #endif void gammaDDInitTextureFuncs( struct dd_function_table *functions ) { functions->TexEnv = gammaTexEnv; functions->TexImage2D = gammaTexImage2D; functions->TexSubImage2D = gammaTexSubImage2D; /*functions->BindTexture = gammaBindTexture;*/ functions->DeleteTexture = gammaDeleteTexture; functions->TexParameter = gammaTexParameter; functions->IsTextureResident = gammaIsTextureResident; }