/* * Author: Max Lingua */ #include "main/glheader.h" #include "main/mtypes.h" #include "main/simple_list.h" #include "main/enums.h" #include "main/mm.h" #include "main/texstore.h" #include "main/teximage.h" #include "swrast/swrast.h" #include "s3v_context.h" #include "s3v_tex.h" extern void s3vSwapOutTexObj(s3vContextPtr vmesa, s3vTextureObjectPtr t); extern void s3vDestroyTexObj(s3vContextPtr vmesa, s3vTextureObjectPtr t); /* static GLuint s3vComputeLodBias(GLfloat bias) { #if TEX_DEBUG_ON DEBUG_TEX(("*** s3vComputeLodBias ***\n")); #endif return bias; } */ static void s3vSetTexWrapping(s3vContextPtr vmesa, s3vTextureObjectPtr t, GLenum wraps, GLenum wrapt) { GLuint t0 = t->TextureCMD; GLuint cmd = vmesa->CMD; #if TEX_DEBUG_ON static unsigned int times=0; DEBUG_TEX(("*** s3vSetTexWrapping: #%i ***\n", ++times)); #endif t0 &= ~TEX_WRAP_MASK; cmd &= ~TEX_WRAP_MASK; if ((wraps != GL_CLAMP) || (wrapt != GL_CLAMP)) { DEBUG(("TEX_WRAP_ON\n")); t0 |= TEX_WRAP_ON; cmd |= TEX_WRAP_ON; } cmd |= TEX_WRAP_ON; /* FIXME: broken if off */ t->TextureCMD = t0; vmesa->CMD = cmd; } static void s3vSetTexFilter(s3vContextPtr vmesa, s3vTextureObjectPtr t, GLenum minf, GLenum magf) { GLuint t0 = t->TextureCMD; GLuint cmd = vmesa->CMD; #if TEX_DEBUG_ON static unsigned int times=0; DEBUG_TEX(("*** s3vSetTexFilter: #%i ***\n", ++times)); #endif t0 &= ~TEX_FILTER_MASK; cmd &= ~TEX_FILTER_MASK; switch (minf) { case GL_NEAREST: DEBUG(("GL_NEAREST\n")); t0 |= NEAREST; cmd |= NEAREST; break; case GL_LINEAR: DEBUG(("GL_LINEAR\n")); t0 |= LINEAR; cmd |= LINEAR; break; case GL_NEAREST_MIPMAP_NEAREST: DEBUG(("GL_MIPMAP_NEAREST\n")); t0 |= MIP_NEAREST; cmd |= MIP_NEAREST; break; case GL_LINEAR_MIPMAP_NEAREST: DEBUG(("GL_LINEAR_MIPMAP_NEAREST\n")); t0 |= LINEAR_MIP_NEAREST; cmd |= LINEAR_MIP_NEAREST; break; case GL_NEAREST_MIPMAP_LINEAR: DEBUG(("GL_NEAREST_MIPMAP_LINEAR\n")); t0 |= MIP_LINEAR; cmd |= MIP_LINEAR; break; case GL_LINEAR_MIPMAP_LINEAR: DEBUG(("GL_LINEAR_MIPMAP_LINEAR\n")); t0 |= LINEAR_MIP_LINEAR; cmd |= LINEAR_MIP_LINEAR; break; default: break; } /* FIXME: bilinear? */ #if 0 switch (magf) { case GL_NEAREST: break; case GL_LINEAR: break; default: break; } #endif t->TextureCMD = t0; DEBUG(("CMD was = 0x%x\n", vmesa->CMD)); DEBUG(("CMD is = 0x%x\n", cmd)); vmesa->CMD = cmd; /* CMDCHANGE(); */ } static void s3vSetTexBorderColor(s3vContextPtr vmesa, s3vTextureObjectPtr t, const GLfloat color[4]) { GLubyte c[4]; CLAMPED_FLOAT_TO_UBYTE(c[0], color[0]); CLAMPED_FLOAT_TO_UBYTE(c[1], color[1]); CLAMPED_FLOAT_TO_UBYTE(c[2], color[2]); CLAMPED_FLOAT_TO_UBYTE(c[3], color[3]); #if TEX_DEBUG_ON static unsigned int times=0; DEBUG_TEX(("*** s3vSetTexBorderColor: #%i ***\n", ++times)); #endif /*FIXME: it should depend on tex col format */ /* switch(t0 ... t->TextureColorMode) */ /* case TEX_COL_ARGB1555: */ t->TextureBorderColor = S3VIRGEPACKCOLOR555(c[0], c[1], c[2], c[3]); DEBUG(("TextureBorderColor = 0x%x\n", t->TextureBorderColor)); vmesa->TextureBorderColor = t->TextureBorderColor; } static void s3vTexParameter( GLcontext *ctx, GLenum target, struct gl_texture_object *tObj, GLenum pname, const GLfloat *params ) { s3vContextPtr vmesa = S3V_CONTEXT(ctx); s3vTextureObjectPtr t = (s3vTextureObjectPtr) tObj->DriverData; #if TEX_DEBUG_ON static unsigned int times=0; DEBUG_TEX(("*** s3vTexParameter: #%i ***\n", ++times)); #endif if (!t) return; /* Can't do the update now as we don't know whether to flush * vertices or not. Setting vmesa->new_state means that * s3vUpdateTextureState() 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: s3vSetTexFilter( vmesa, t, tObj->MinFilter, tObj->MagFilter ); break; case GL_TEXTURE_WRAP_S: case GL_TEXTURE_WRAP_T: s3vSetTexWrapping( vmesa, t, tObj->WrapS, tObj->WrapT ); break; case GL_TEXTURE_BORDER_COLOR: s3vSetTexBorderColor( vmesa, t, tObj->BorderColor ); 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 Virge. Since there's no LOD clamping, * we just have to rely on loading the right subset of mipmap levels * to simulate a clamped LOD. */ s3vSwapOutTexObj( vmesa, t ); break; default: return; } if (t == vmesa->CurrentTexObj[0]) vmesa->dirty |= S3V_UPLOAD_TEX0; #if 0 if (t == vmesa->CurrentTexObj[1]) { vmesa->dirty |= S3V_UPLOAD_TEX1; } #endif } static void s3vTexEnv( GLcontext *ctx, GLenum target, GLenum pname, const GLfloat *param ) { s3vContextPtr vmesa = S3V_CONTEXT( ctx ); GLuint unit = ctx->Texture.CurrentUnit; #if TEX_DEBUG_ON static unsigned int times=0; DEBUG_TEX(("*** s3vTexEnv: #%i ***\n", ++times)); #endif /* 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: vmesa->TexEnvImageFmt[unit] = 0; /* force recalc of env state */ break; case GL_TEXTURE_LOD_BIAS_EXT: { /* struct gl_texture_object *tObj = ctx->Texture.Unit[unit]._Current; s3vTextureObjectPtr t = (s3vTextureObjectPtr) tObj->DriverData; */ break; } default: break; } } static void s3vTexImage1D( 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 ) { s3vContextPtr vmesa = S3V_CONTEXT( ctx ); s3vTextureObjectPtr t = (s3vTextureObjectPtr) texObj->DriverData; #if TEX_DEBUG_ON static unsigned int times=0; DEBUG_TEX(("*** s3vTexImage1D: #%i ***\n", ++times)); #endif #if 1 if (t) { #if _TEXFLUSH DMAFLUSH(); #endif s3vSwapOutTexObj( vmesa, t ); /* s3vDestroyTexObj( vmesa, t ); texObj->DriverData = 0; */ } #endif _mesa_store_teximage1d( ctx, target, level, internalFormat, width, border, format, type, pixels, pack, texObj, texImage ); } static void s3vTexSubImage1D( 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 ) { s3vContextPtr vmesa = S3V_CONTEXT( ctx ); s3vTextureObjectPtr t = (s3vTextureObjectPtr) texObj->DriverData; #if TEX_DEBUG_ON static unsigned int times=0; DEBUG_TEX(("*** s3vTexSubImage1D: #%i ***\n", ++times)); #endif #if 1 if (t) { #if _TEXFLUSH DMAFLUSH(); #endif s3vSwapOutTexObj( vmesa, t ); /* s3vDestroyTexObj( vmesa, t ); texObj->DriverData = 0; */ } #endif _mesa_store_texsubimage1d(ctx, target, level, xoffset, width, format, type, pixels, pack, texObj, texImage); } static void s3vTexImage2D( 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 ) { s3vContextPtr vmesa = S3V_CONTEXT( ctx ); s3vTextureObjectPtr t = (s3vTextureObjectPtr) texObj->DriverData; #if TEX_DEBUG_ON static unsigned int times=0; DEBUG_TEX(("*** s3vTexImage2D: #%i ***\n", ++times)); #endif #if 1 if (t) { #if _TEXFLUSH DMAFLUSH(); #endif s3vSwapOutTexObj( vmesa, t ); /* s3vDestroyTexObj( vmesa, t ); texObj->DriverData = 0; */ } #endif _mesa_store_teximage2d( ctx, target, level, internalFormat, width, height, border, format, type, pixels, packing, texObj, texImage ); } static void s3vTexSubImage2D( 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 ) { s3vContextPtr vmesa = S3V_CONTEXT( ctx ); s3vTextureObjectPtr t = (s3vTextureObjectPtr) texObj->DriverData; #if TEX_DEBUG_ON static unsigned int times=0; DEBUG_TEX(("*** s3vTexSubImage2D: #%i ***\n", ++times)); #endif #if 1 if (t) { #if _TEXFLUSH DMAFLUSH(); #endif s3vSwapOutTexObj( vmesa, t ); /* s3vDestroyTexObj( vmesa, t ); texObj->DriverData = 0; */ } #endif _mesa_store_texsubimage2d(ctx, target, level, xoffset, yoffset, width, height, format, type, pixels, packing, texObj, texImage); } static void s3vBindTexture( GLcontext *ctx, GLenum target, struct gl_texture_object *tObj ) { s3vContextPtr vmesa = S3V_CONTEXT( ctx ); s3vTextureObjectPtr t = (s3vTextureObjectPtr) tObj->DriverData; GLuint cmd = vmesa->CMD; #if TEX_DEBUG_ON static unsigned int times=0; DEBUG_TEX(("*** s3vBindTexture: #%i ***\n", ++times)); #endif if (!t) { /* GLfloat bias = ctx->Texture.Unit[ctx->Texture.CurrentUnit].LodBias; */ t = CALLOC_STRUCT(s3v_texture_object_t); /* Initialize non-image-dependent parts of the state: */ t->globj = tObj; #if 0 if (target == GL_TEXTURE_2D) { } else if (target == GL_TEXTURE_1D) { } #if X_BYTE_ORDER == X_LITTLE_ENDIAN t->TextureFormat = (TF_LittleEndian | #else t->TextureFormat = (TF_BigEndian | #endif #endif t->dirty_images = ~0; tObj->DriverData = t; make_empty_list( t ); #if 0 s3vSetTexWrapping( vmesa, t, tObj->WrapS, tObj->WrapT ); s3vSetTexFilter( vmesa, t, tObj->MinFilter, tObj->MagFilter ); s3vSetTexBorderColor( vmesa, t, tObj->BorderColor ); #endif } cmd = vmesa->CMD & ~MIP_MASK; vmesa->dirty |= S3V_UPLOAD_TEX0; vmesa->TexOffset = t->TextureBaseAddr[tObj->BaseLevel]; vmesa->TexStride = t->Pitch; cmd |= MIPMAP_LEVEL(t->WidthLog2); vmesa->CMD = cmd; vmesa->restore_primitive = -1; #if 0 printf("t->TextureBaseAddr[0] = 0x%x\n", t->TextureBaseAddr[0]); printf("t->TextureBaseAddr[1] = 0x%x\n", t->TextureBaseAddr[1]); printf("t->TextureBaseAddr[2] = 0x%x\n", t->TextureBaseAddr[2]); #endif } static void s3vDeleteTexture( GLcontext *ctx, struct gl_texture_object *tObj ) { s3vTextureObjectPtr t = (s3vTextureObjectPtr)tObj->DriverData; #if TEX_DEBUG_ON static unsigned int times=0; DEBUG_TEX(("*** s3vDeleteTexture: #%i ***\n", ++times)); #endif if (t) { s3vContextPtr vmesa = S3V_CONTEXT( ctx ); #if _TEXFLUSH if (vmesa) { DMAFLUSH(); } #endif s3vDestroyTexObj( vmesa, t ); tObj->DriverData = 0; } } static GLboolean s3vIsTextureResident( GLcontext *ctx, struct gl_texture_object *tObj ) { s3vTextureObjectPtr t = (s3vTextureObjectPtr)tObj->DriverData; #if TEX_DEBUG_ON static unsigned int times=0; DEBUG_TEX(("*** s3vIsTextureResident: #%i ***\n", ++times)); #endif return (t && t->MemBlock); } static void s3vInitTextureObjects( GLcontext *ctx ) { /* s3vContextPtr vmesa = S3V_CONTEXT(ctx); */ struct gl_texture_object *texObj; GLuint tmp = ctx->Texture.CurrentUnit; #if TEX_DEBUG_ON static unsigned int times=0; DEBUG_TEX(("*** s3vInitTextureObjects: #%i ***\n", ++times)); #endif #if 1 ctx->Texture.CurrentUnit = 0; texObj = ctx->Texture.Unit[0].CurrentTex[TEXTURE_1D_INDEX]; s3vBindTexture( ctx, GL_TEXTURE_1D, texObj ); texObj = ctx->Texture.Unit[0].CurrentTex[TEXTURE_2D_INDEX]; s3vBindTexture( ctx, GL_TEXTURE_2D, texObj ); #endif #if 0 ctx->Texture.CurrentUnit = 1; texObj = ctx->Texture.Unit[1].CurrentTex[TEXTURE_1D_INDEX]; s3vBindTexture( ctx, GL_TEXTURE_1D, texObj ); texObj = ctx->Texture.Unit[1].CurrentTex[TEXTURE_2D_INDEX]; s3vBindTexture( ctx, GL_TEXTURE_2D, texObj ); #endif ctx->Texture.CurrentUnit = tmp; } void s3vInitTextureFuncs( GLcontext *ctx ) { #if TEX_DEBUG_ON static unsigned int times=0; DEBUG_TEX(("*** s3vInitTextureFuncs: #%i ***\n", ++times)); #endif ctx->Driver.TexEnv = s3vTexEnv; ctx->Driver.TexImage2D = s3vTexImage2D; ctx->Driver.TexSubImage2D = s3vTexSubImage2D; ctx->Driver.BindTexture = s3vBindTexture; ctx->Driver.DeleteTexture = s3vDeleteTexture; ctx->Driver.TexParameter = s3vTexParameter; ctx->Driver.UpdateTexturePalette = 0; ctx->Driver.IsTextureResident = s3vIsTextureResident; s3vInitTextureObjects( ctx ); }