/* * Author: Max Lingua */ #include #include #include "main/glheader.h" #include "main/macros.h" #include "main/mtypes.h" #include "main/simple_list.h" #include "main/enums.h" #include "main/mm.h" #include "s3v_context.h" #include "s3v_tex.h" static void s3vSetTexImages( s3vContextPtr vmesa, struct gl_texture_object *tObj ) { GLuint height, width, pitch, i, /*textureFormat,*/ log_pitch; s3vTextureObjectPtr t = (s3vTextureObjectPtr) tObj->DriverData; const struct gl_texture_image *baseImage = tObj->Image[0][tObj->BaseLevel]; GLint firstLevel, lastLevel, numLevels; GLint log2Width, log2Height; #if TEX_DEBUG_ON static unsigned int times=0; DEBUG_TEX(("*** s3vSetTexImages: #%i ***\n", ++times)); #endif t->texelBytes = 2; /* FIXME: always 2 ? */ /* Compute which mipmap levels we really want to send to the hardware. * This depends on the base image size, GL_TEXTURE_MIN_LOD, * GL_TEXTURE_MAX_LOD, GL_TEXTURE_BASE_LEVEL, and GL_TEXTURE_MAX_LEVEL. * Yes, this looks overly complicated, but it's all needed. */ if (tObj->MinFilter == GL_LINEAR || tObj->MinFilter == GL_NEAREST) { firstLevel = lastLevel = tObj->BaseLevel; } else { firstLevel = tObj->BaseLevel + (GLint) (tObj->MinLod + 0.5); firstLevel = MAX2(firstLevel, tObj->BaseLevel); lastLevel = tObj->BaseLevel + (GLint) (tObj->MaxLod + 0.5); lastLevel = MAX2(lastLevel, tObj->BaseLevel); lastLevel = MIN2(lastLevel, tObj->BaseLevel + baseImage->MaxLog2); lastLevel = MIN2(lastLevel, tObj->MaxLevel); lastLevel = MAX2(firstLevel, lastLevel); /* need at least one level */ } /* save these values */ t->firstLevel = firstLevel; t->lastLevel = lastLevel; numLevels = lastLevel - firstLevel + 1; log2Width = tObj->Image[0][firstLevel]->WidthLog2; log2Height = tObj->Image[0][firstLevel]->HeightLog2; /* Figure out the amount of memory required to hold all the mipmap * levels. Choose the smallest pitch to accomodate the largest * mipmap: */ width = tObj->Image[0][firstLevel]->Width * t->texelBytes; for (pitch = 32, log_pitch=2 ; pitch < width ; pitch *= 2 ) log_pitch++; /* All images must be loaded at this pitch. Count the number of * lines required: */ for ( height = i = 0 ; i < numLevels ; i++ ) { t->image[i].image = tObj->Image[0][firstLevel + i]; t->image[i].offset = height * pitch; t->image[i].internalFormat = baseImage->_BaseFormat; height += t->image[i].image->Height; t->TextureBaseAddr[i] = (t->BufAddr + t->image[i].offset + _TEXALIGN) & (GLuint)(~_TEXALIGN); } t->Pitch = pitch; t->WidthLog2 = log2Width; t->totalSize = height*pitch; t->max_level = i-1; vmesa->dirty |= S3V_UPLOAD_TEX0 /* | S3V_UPLOAD_TEX1*/; vmesa->restore_primitive = -1; DEBUG(("<><>pitch = TexStride = %i\n", pitch)); DEBUG(("log2Width = %i\n", log2Width)); s3vUploadTexImages( vmesa, t ); } static void s3vUpdateTexEnv( GLcontext *ctx, GLuint unit ) { s3vContextPtr vmesa = S3V_CONTEXT(ctx); const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit]; const struct gl_texture_object *tObj = texUnit->_Current; const GLuint format = tObj->Image[0][tObj->BaseLevel]->_BaseFormat; /* s3vTextureObjectPtr t = (s3vTextureObjectPtr)tObj->DriverData; GLuint tc; */ GLuint alpha = 0; GLuint cmd = vmesa->CMD; #if TEX_DEBUG_ON static unsigned int times=0; DEBUG_TEX(("*** s3vUpdateTexEnv: %i ***\n", ++times)); #endif cmd &= ~TEX_COL_MASK; cmd &= ~TEX_BLEND_MAKS; /* cmd &= ~ALPHA_BLEND_MASK; */ DEBUG(("format = ")); switch (format) { case GL_RGB: DEBUG_TEX(("GL_RGB\n")); cmd |= TEX_COL_ARGB1555; break; case GL_LUMINANCE: DEBUG_TEX(("GL_LUMINANCE\n")); cmd |= TEX_COL_ARGB4444; alpha = 1; /* FIXME: check */ break; case GL_ALPHA: DEBUG_TEX(("GL_ALPHA\n")); cmd |= TEX_COL_ARGB4444; alpha = 1; break; case GL_LUMINANCE_ALPHA: DEBUG_TEX(("GL_LUMINANCE_ALPHA\n")); cmd |= TEX_COL_ARGB4444; alpha = 1; break; case GL_INTENSITY: DEBUG_TEX(("GL_INTENSITY\n")); cmd |= TEX_COL_ARGB4444; alpha = 1; break; case GL_RGBA: DEBUG_TEX(("GL_RGBA\n")); cmd |= TEX_COL_ARGB4444; alpha = 1; break; case GL_COLOR_INDEX: DEBUG_TEX(("GL_COLOR_INDEX\n")); cmd |= TEX_COL_PAL; break; } DEBUG_TEX(("EnvMode = ")); switch (texUnit->EnvMode) { case GL_REPLACE: DEBUG_TEX(("GL_REPLACE\n")); cmd |= TEX_REFLECT; /* FIXME */ vmesa->_tri[1] = DO_TEX_UNLIT_TRI; /* FIXME: white tri hack */ vmesa->_alpha_tex = ALPHA_TEX /* * alpha */; break; case GL_MODULATE: DEBUG_TEX(("GL_MODULATE\n")); cmd |= TEX_MODULATE; vmesa->_tri[1] = DO_TEX_LIT_TRI; #if 0 if (alpha) vmesa->_alpha_tex = ALPHA_TEX /* * alpha */; else vmesa->_alpha_tex = ALPHA_SRC /* * alpha */; #else vmesa->_alpha_tex = ALPHA_TEX ; #endif break; case GL_ADD: DEBUG_TEX(("DEBUG_TEX\n")); /* do nothing ???*/ break; case GL_DECAL: DEBUG_TEX(("GL_DECAL\n")); cmd |= TEX_DECAL; vmesa->_tri[1] = DO_TEX_LIT_TRI; vmesa->_alpha_tex = ALPHA_OFF; break; case GL_BLEND: DEBUG_TEX(("GL_BLEND\n")); cmd |= TEX_DECAL; vmesa->_tri[1] = DO_TEX_LIT_TRI; vmesa->_alpha_tex = ALPHA_OFF; /* FIXME: sure? */ break; default: fprintf(stderr, "unknown tex env mode"); return; } DEBUG_TEX(("\n\n vmesa->CMD was 0x%x\n", vmesa->CMD)); DEBUG_TEX(( " vmesa->CMD is 0x%x\n\n", cmd )); vmesa->_alpha[1] = vmesa->_alpha_tex; vmesa->CMD = cmd; /* | MIPMAP_LEVEL(8); */ vmesa->restore_primitive = -1; } static void s3vUpdateTexUnit( GLcontext *ctx, GLuint unit ) { s3vContextPtr vmesa = S3V_CONTEXT(ctx); struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit]; GLuint cmd = vmesa->CMD; #if TEX_DEBUG_ON static unsigned int times=0; DEBUG_TEX(("*** s3vUpdateTexUnit: %i ***\n", ++times)); DEBUG_TEX(("and vmesa->CMD was 0x%x\n", vmesa->CMD)); #endif if (texUnit->_ReallyEnabled == TEXTURE_2D_BIT) { struct gl_texture_object *tObj = texUnit->_Current; s3vTextureObjectPtr t = (s3vTextureObjectPtr)tObj->DriverData; /* Upload teximages (not pipelined) */ if (t->dirty_images) { #if _TEXFLUSH DMAFLUSH(); #endif s3vSetTexImages( vmesa, tObj ); if (!t->MemBlock) { #if _TEXFALLBACK FALLBACK( vmesa, S3V_FALLBACK_TEXTURE, GL_TRUE ); #endif return; } } /* Update state if this is a different texture object to last * time. */ #if 1 if (vmesa->CurrentTexObj[unit] != t) { vmesa->dirty |= S3V_UPLOAD_TEX0 /* << unit */; vmesa->CurrentTexObj[unit] = t; s3vUpdateTexLRU( vmesa, t ); /* done too often */ } #endif /* Update texture environment if texture object image format or * texture environment state has changed. */ if (tObj->Image[0][tObj->BaseLevel]->_BaseFormat != vmesa->TexEnvImageFmt[unit]) { vmesa->TexEnvImageFmt[unit] = tObj->Image[0][tObj->BaseLevel]->_BaseFormat; s3vUpdateTexEnv( ctx, unit ); } #if 1 cmd = vmesa->CMD & ~MIP_MASK; vmesa->dirty |= S3V_UPLOAD_TEX0 /* << unit */; vmesa->CurrentTexObj[unit] = t; vmesa->TexOffset = t->TextureBaseAddr[tObj->BaseLevel]; vmesa->TexStride = t->Pitch; cmd |= MIPMAP_LEVEL(t->WidthLog2); DEBUG_TEX(("\n\n>> vmesa->CMD was 0x%x\n", vmesa->CMD)); DEBUG_TEX(( ">> vmesa->CMD is 0x%x\n\n", cmd )); DEBUG_TEX(("t->WidthLog2 = %i\n", t->WidthLog2)); DEBUG_TEX(("MIPMAP_LEVEL(t->WidthLog2) = 0x%x\n", MIPMAP_LEVEL(t->WidthLog2))); vmesa->CMD = cmd; vmesa->restore_primitive = -1; #endif } else if (texUnit->_ReallyEnabled) { /* _ReallyEnabled but != TEXTURE0_2D */ #if _TEXFALLBACK FALLBACK( vmesa, S3V_FALLBACK_TEXTURE, GL_TRUE ); #endif } else /*if (vmesa->CurrentTexObj[unit])*/ { /* !_ReallyEnabled */ vmesa->CurrentTexObj[unit] = 0; vmesa->TexEnvImageFmt[unit] = 0; vmesa->dirty &= ~(S3V_UPLOAD_TEX0<