static GLboolean update_tex_common( GLcontext *ctx, int unit ) { r128ContextPtr rmesa = R128_CONTEXT(ctx); const int source = rmesa->tmu_source[unit]; const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[source]; const struct gl_texture_object *tObj = texUnit->_Current; r128TexObjPtr t = (r128TexObjPtr) tObj->DriverData; /* Fallback if there's a texture border */ if ( tObj->Image[0][tObj->BaseLevel]->Border > 0 ) { return GL_FALSE; } /* Update state if this is a different texture object to last * time. */ if ( rmesa->CurrentTexObj[unit] != t ) { if ( rmesa->CurrentTexObj[unit] != NULL ) { /* The old texture is no longer bound to this texture unit. * Mark it as such. */ rmesa->CurrentTexObj[unit]->base.bound &= ~(1UL << unit); } rmesa->CurrentTexObj[unit] = t; t->base.bound |= (1UL << unit); rmesa->dirty |= R128_UPLOAD_TEX0 << unit; driUpdateTextureLRU( (driTextureObject *) t ); /* XXX: should be locked! */ } /* FIXME: We need to update the texture unit if any texture parameters have * changed, but this texture was already bound. This could be changed to * work like the Radeon driver where the texture object has it's own * dirty state flags */ rmesa->dirty |= R128_UPLOAD_TEX0 << unit; /* register setup */ rmesa->setup.tex_size_pitch_c &= ~(R128_TEX_SIZE_PITCH_MASK << (R128_SEC_TEX_SIZE_PITCH_SHIFT * unit)); if ( unit == 0 ) { rmesa->setup.tex_cntl_c |= R128_TEXMAP_ENABLE; rmesa->setup.tex_size_pitch_c |= t->setup.tex_size_pitch << 0; rmesa->setup.scale_3d_cntl &= ~R128_TEX_CACHE_SPLIT; t->setup.tex_cntl &= ~R128_SEC_SELECT_SEC_ST; } else { rmesa->setup.tex_cntl_c |= R128_SEC_TEXMAP_ENABLE; rmesa->setup.tex_size_pitch_c |= t->setup.tex_size_pitch << 16; rmesa->setup.scale_3d_cntl |= R128_TEX_CACHE_SPLIT; t->setup.tex_cntl |= R128_SEC_SELECT_SEC_ST; /* If the second TMU is enabled, then multitexturing is happening. */ if ( R128_IS_PLAIN( rmesa ) ) rmesa->blend_flags |= R128_BLEND_MULTITEX; } rmesa->dirty |= R128_UPLOAD_CONTEXT; /* FIXME: The Radeon has some cached state so that it can avoid calling * FIXME: UpdateTextureEnv in some cases. Is that possible here? */ return r128UpdateTextureEnv( ctx, unit ); }
static void r128TexEnv( GLcontext *ctx, GLenum target, GLenum pname, const GLfloat *param ) { r128ContextPtr rmesa = R128_CONTEXT(ctx); struct gl_texture_unit *texUnit; GLubyte c[4]; if ( R128_DEBUG & DEBUG_VERBOSE_API ) { fprintf( stderr, "%s( %s )\n", __FUNCTION__, _mesa_lookup_enum_by_nr( pname ) ); } switch ( pname ) { case GL_TEXTURE_ENV_MODE: FLUSH_BATCH( rmesa ); rmesa->new_state |= R128_NEW_ALPHA; break; case GL_TEXTURE_ENV_COLOR: texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; CLAMPED_FLOAT_TO_UBYTE( c[0], texUnit->EnvColor[0] ); CLAMPED_FLOAT_TO_UBYTE( c[1], texUnit->EnvColor[1] ); CLAMPED_FLOAT_TO_UBYTE( c[2], texUnit->EnvColor[2] ); CLAMPED_FLOAT_TO_UBYTE( c[3], texUnit->EnvColor[3] ); rmesa->env_color = r128PackColor( 4, c[0], c[1], c[2], c[3] ); if ( rmesa->setup.constant_color_c != rmesa->env_color ) { FLUSH_BATCH( rmesa ); rmesa->setup.constant_color_c = rmesa->env_color; /* More complex multitexture/multipass fallbacks for GL_BLEND * can be done later, but this allows a single pass GL_BLEND * in some cases (ie. Performer town demo). This is only * applicable to the regular Rage 128, as the Pro and M3 can * handle true single-pass GL_BLEND texturing. */ rmesa->blend_flags &= ~R128_BLEND_ENV_COLOR; if ( R128_IS_PLAIN( rmesa ) && rmesa->env_color != 0x00000000 && rmesa->env_color != 0xff000000 && rmesa->env_color != 0x00ffffff && rmesa->env_color != 0xffffffff ) { rmesa->blend_flags |= R128_BLEND_ENV_COLOR; } } break; case GL_TEXTURE_LOD_BIAS: { uint32_t t = rmesa->setup.tex_cntl_c; GLint bias; uint32_t b; /* GTH: This isn't exactly correct, but gives good results up to a * certain point. It is better than completely ignoring the LOD * bias. Unfortunately there isn't much range in the bias, the * spec mentions strides that vary between 0.5 and 2.0 but these * numbers don't seem to relate to the GL LOD bias value at all. */ if ( param[0] >= 1.0 ) { bias = -128; } else if ( param[0] >= 0.5 ) { bias = -64; } else if ( param[0] >= 0.25 ) { bias = 0; } else if ( param[0] >= 0.0 ) { bias = 63; } else { bias = 127; } b = (uint32_t)bias & 0xff; t &= ~R128_LOD_BIAS_MASK; t |= (b << R128_LOD_BIAS_SHIFT); if ( rmesa->setup.tex_cntl_c != t ) { FLUSH_BATCH( rmesa ); rmesa->setup.tex_cntl_c = t; rmesa->dirty |= R128_UPLOAD_CONTEXT; } } break; default: return; } }
static GLboolean r128UpdateTextureEnv( GLcontext *ctx, int unit ) { r128ContextPtr rmesa = R128_CONTEXT(ctx); GLint source = rmesa->tmu_source[unit]; const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[source]; const struct gl_texture_object *tObj = texUnit->_Current; const GLenum format = tObj->Image[0][tObj->BaseLevel]->_BaseFormat; GLuint combine; if ( R128_DEBUG & DEBUG_VERBOSE_API ) { fprintf( stderr, "%s( %p, %d )\n", __FUNCTION__, (void *) ctx, unit ); } if ( unit == 0 ) { combine = INPUT_INTERP; } else { combine = INPUT_PREVIOUS; } /* Set the texture environment state */ switch ( texUnit->EnvMode ) { case GL_REPLACE: switch ( format ) { case GL_RGBA: case GL_LUMINANCE_ALPHA: case GL_INTENSITY: combine |= (COLOR_COMB_DISABLE | /* C = Ct */ ALPHA_COMB_DISABLE); /* A = At */ break; case GL_RGB: case GL_LUMINANCE: combine |= (COLOR_COMB_DISABLE | /* C = Ct */ ALPHA_COMB_COPY_INPUT); /* A = Af */ break; case GL_ALPHA: combine |= (COLOR_COMB_COPY_INPUT | /* C = Cf */ ALPHA_COMB_DISABLE); /* A = At */ break; case GL_COLOR_INDEX: default: return GL_FALSE; } break; case GL_MODULATE: switch ( format ) { case GL_RGBA: case GL_LUMINANCE_ALPHA: case GL_INTENSITY: combine |= (COLOR_COMB_MODULATE | /* C = CfCt */ ALPHA_COMB_MODULATE); /* A = AfAt */ break; case GL_RGB: case GL_LUMINANCE: combine |= (COLOR_COMB_MODULATE | /* C = CfCt */ ALPHA_COMB_COPY_INPUT); /* A = Af */ break; case GL_ALPHA: combine |= (COLOR_COMB_COPY_INPUT | /* C = Cf */ ALPHA_COMB_MODULATE); /* A = AfAt */ break; case GL_COLOR_INDEX: default: return GL_FALSE; } break; case GL_DECAL: switch ( format ) { case GL_RGBA: combine |= (COLOR_COMB_BLEND_TEX | /* C = Cf(1-At)+CtAt */ ALPHA_COMB_COPY_INPUT); /* A = Af */ break; case GL_RGB: combine |= (COLOR_COMB_DISABLE | /* C = Ct */ ALPHA_COMB_COPY_INPUT); /* A = Af */ break; case GL_ALPHA: case GL_LUMINANCE: case GL_LUMINANCE_ALPHA: case GL_INTENSITY: /* Undefined behaviour - just copy the incoming fragment */ combine |= (COLOR_COMB_COPY_INPUT | /* C = undefined */ ALPHA_COMB_COPY_INPUT); /* A = undefined */ break; case GL_COLOR_INDEX: default: return GL_FALSE; } break; case GL_BLEND: /* Rage 128 Pro and M3 can handle GL_BLEND texturing. */ if ( !R128_IS_PLAIN( rmesa ) ) { /* XXX this hasn't been fully tested, I don't have a Pro card. -BP */ switch ( format ) { case GL_RGBA: case GL_LUMINANCE_ALPHA: combine |= (COLOR_COMB_BLEND_COLOR | /* C = Cf(1-Ct)+CcCt */ ALPHA_COMB_MODULATE); /* A = AfAt */ break; case GL_RGB: case GL_LUMINANCE: combine |= (COLOR_COMB_BLEND_COLOR | /* C = Cf(1-Ct)+CcCt */ ALPHA_COMB_COPY_INPUT); /* A = Af */ break; case GL_ALPHA: combine |= (COLOR_COMB_COPY_INPUT | /* C = Cf */ ALPHA_COMB_MODULATE); /* A = AfAt */ break; case GL_INTENSITY: /* GH: We could be smarter about this... */ switch ( rmesa->env_color & 0xff000000 ) { case 0x00000000: combine |= (COLOR_COMB_BLEND_COLOR | /* C = Cf(1-It)+CcIt */ ALPHA_COMB_MODULATE_NTEX); /* A = Af(1-It) */ default: combine |= (COLOR_COMB_MODULATE | /* C = fallback */ ALPHA_COMB_MODULATE); /* A = fallback */ return GL_FALSE; } break; case GL_COLOR_INDEX: default: return GL_FALSE; } break; } /* Rage 128 has to fake some cases of GL_BLEND, otherwise fallback * to software rendering. */ if ( rmesa->blend_flags ) { return GL_FALSE; } switch ( format ) { case GL_RGBA: case GL_LUMINANCE_ALPHA: switch ( rmesa->env_color & 0x00ffffff ) { case 0x00000000: combine |= (COLOR_COMB_MODULATE_NTEX | /* C = Cf(1-Ct) */ ALPHA_COMB_MODULATE); /* A = AfAt */ break; #if 0 /* This isn't right - BP */ case 0x00ffffff: if ( unit == 0 ) { combine |= (COLOR_COMB_MODULATE_NTEX | /* C = Cf(1-Ct) */ ALPHA_COMB_MODULATE); /* A = AfAt */ } else { combine |= (COLOR_COMB_ADD | /* C = Cf+Ct */ ALPHA_COMB_COPY_INPUT); /* A = Af */ } break; #endif default: combine |= (COLOR_COMB_MODULATE | /* C = fallback */ ALPHA_COMB_MODULATE); /* A = fallback */ return GL_FALSE; } break; case GL_RGB: case GL_LUMINANCE: switch ( rmesa->env_color & 0x00ffffff ) { case 0x00000000: combine |= (COLOR_COMB_MODULATE_NTEX | /* C = Cf(1-Ct) */ ALPHA_COMB_COPY_INPUT); /* A = Af */ break; #if 0 /* This isn't right - BP */ case 0x00ffffff: if ( unit == 0 ) { combine |= (COLOR_COMB_MODULATE_NTEX | /* C = Cf(1-Ct) */ ALPHA_COMB_COPY_INPUT); /* A = Af */ } else { combine |= (COLOR_COMB_ADD | /* C = Cf+Ct */ ALPHA_COMB_COPY_INPUT); /* A = Af */ } break; #endif default: combine |= (COLOR_COMB_MODULATE | /* C = fallback */ ALPHA_COMB_COPY_INPUT); /* A = fallback */ return GL_FALSE; } break; case GL_ALPHA: if ( unit == 0 ) { combine |= (COLOR_COMB_COPY_INPUT | /* C = Cf */ ALPHA_COMB_MODULATE); /* A = AfAt */ } else { combine |= (COLOR_COMB_COPY_INPUT | /* C = Cf */ ALPHA_COMB_COPY_INPUT); /* A = Af */ } break; case GL_INTENSITY: switch ( rmesa->env_color & 0x00ffffff ) { case 0x00000000: combine |= COLOR_COMB_MODULATE_NTEX; /* C = Cf(1-It) */ break; #if 0 /* This isn't right - BP */ case 0x00ffffff: if ( unit == 0 ) { combine |= COLOR_COMB_MODULATE_NTEX; /* C = Cf(1-It) */ } else { combine |= COLOR_COMB_ADD; /* C = Cf+It */ } break; #endif default: combine |= (COLOR_COMB_MODULATE | /* C = fallback */ ALPHA_COMB_MODULATE); /* A = fallback */ return GL_FALSE; } switch ( rmesa->env_color & 0xff000000 ) { case 0x00000000: combine |= ALPHA_COMB_MODULATE_NTEX; /* A = Af(1-It) */ break; #if 0 /* This isn't right - BP */ case 0xff000000: if ( unit == 0 ) { combine |= ALPHA_COMB_MODULATE_NTEX; /* A = Af(1-It) */ } else { combine |= ALPHA_COMB_ADD; /* A = Af+It */ } break; #endif default: combine |= (COLOR_COMB_MODULATE | /* C = fallback */ ALPHA_COMB_MODULATE); /* A = fallback */ return GL_FALSE; } break; case GL_COLOR_INDEX: default: return GL_FALSE; } break; case GL_ADD: switch ( format ) { case GL_RGBA: case GL_LUMINANCE_ALPHA: combine |= (COLOR_COMB_ADD | /* C = Cf+Ct */ ALPHA_COMB_MODULATE); /* A = AfAt */ break; case GL_RGB: case GL_LUMINANCE: combine |= (COLOR_COMB_ADD | /* C = Cf+Ct */ ALPHA_COMB_COPY_INPUT); /* A = Af */ break; case GL_ALPHA: combine |= (COLOR_COMB_COPY_INPUT | /* C = Cf */ ALPHA_COMB_MODULATE); /* A = AfAt */ break; case GL_INTENSITY: combine |= (COLOR_COMB_ADD | /* C = Cf+Ct */ ALPHA_COMB_ADD); /* A = Af+At */ break; case GL_COLOR_INDEX: default: return GL_FALSE; } break; default: return GL_FALSE; } if ( rmesa->tex_combine[unit] != combine ) { rmesa->tex_combine[unit] = combine; rmesa->dirty |= R128_UPLOAD_TEX0 << unit; } return GL_TRUE; }