| /* |
| * Author: Max Lingua <sunmax@libero.it> |
| */ |
| |
| #include <stdlib.h> |
| #include <stdio.h> |
| |
| #include "glheader.h" |
| #include "mtypes.h" |
| #include "simple_list.h" |
| #include "enums.h" |
| #include "texstore.h" |
| #include "texformat.h" |
| #include "teximage.h" |
| #include "swrast/swrast.h" |
| |
| #include "mm.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, |
| GLubyte color[4]) |
| { |
| #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(color[0], color[1], color[2], color[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->_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 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].Current1D; |
| s3vBindTexture( ctx, GL_TEXTURE_1D, texObj ); |
| |
| texObj = ctx->Texture.Unit[0].Current2D; |
| s3vBindTexture( ctx, GL_TEXTURE_2D, texObj ); |
| #endif |
| |
| #if 0 |
| ctx->Texture.CurrentUnit = 1; |
| |
| texObj = ctx->Texture.Unit[1].Current1D; |
| s3vBindTexture( ctx, GL_TEXTURE_1D, texObj ); |
| |
| texObj = ctx->Texture.Unit[1].Current2D; |
| 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.ChooseTextureFormat = _mesa_choose_tex_format; |
| ctx->Driver.TexImage1D = _mesa_store_teximage1d; |
| ctx->Driver.TexImage2D = s3vTexImage2D; |
| ctx->Driver.TexImage3D = _mesa_store_teximage3d; |
| ctx->Driver.TexSubImage1D = _mesa_store_texsubimage1d; |
| ctx->Driver.TexSubImage2D = s3vTexSubImage2D; |
| ctx->Driver.TexSubImage3D = _mesa_store_texsubimage3d; |
| ctx->Driver.CopyTexImage1D = _swrast_copy_teximage1d; |
| ctx->Driver.CopyTexImage2D = _swrast_copy_teximage2d; |
| ctx->Driver.CopyTexSubImage1D = _swrast_copy_texsubimage1d; |
| ctx->Driver.CopyTexSubImage2D = _swrast_copy_texsubimage2d; |
| ctx->Driver.CopyTexSubImage3D = _swrast_copy_texsubimage3d; |
| ctx->Driver.BindTexture = s3vBindTexture; |
| ctx->Driver.DeleteTexture = s3vDeleteTexture; |
| ctx->Driver.TexParameter = s3vTexParameter; |
| ctx->Driver.UpdateTexturePalette = 0; |
| ctx->Driver.IsTextureResident = s3vIsTextureResident; |
| ctx->Driver.TestProxyTexImage = _mesa_test_proxy_teximage; |
| |
| s3vInitTextureObjects( ctx ); |
| } |