X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmesa%2Fdrivers%2Fdri%2Fmga%2Fmga_texstate.c;h=8f78ab9bd4aaf33ad3f896e02e132591363fbe9b;hb=9fbb8884f034e0d691fed0e099d4d796f3b42848;hp=fc1406cab9ea1a943fa810b09bc75643e4def872;hpb=5df82c82bd53db90eb72c5aad4dd20cf6f1116b1;p=mesa.git diff --git a/src/mesa/drivers/dri/mga/mga_texstate.c b/src/mesa/drivers/dri/mga/mga_texstate.c index fc1406cab9e..8f78ab9bd4a 100644 --- a/src/mesa/drivers/dri/mga/mga_texstate.c +++ b/src/mesa/drivers/dri/mga/mga_texstate.c @@ -26,35 +26,37 @@ * Ian Romanick * Keith Whitwell */ -/* $XFree86:$ */ -#include "mm.h" +#include +#include "main/mm.h" #include "mgacontext.h" #include "mgatex.h" #include "mgaregs.h" #include "mgatris.h" #include "mgaioctl.h" -#include "context.h" -#include "enums.h" -#include "macros.h" -#include "imports.h" +#include "main/context.h" +#include "main/enums.h" +#include "main/macros.h" +#include "main/imports.h" -#include "simple_list.h" -#include "texformat.h" +#include "main/simple_list.h" +#include "main/texformat.h" #define MGA_USE_TABLE_FOR_FORMAT #ifdef MGA_USE_TABLE_FOR_FORMAT #define TMC_nr_tformat (MESA_FORMAT_YCBCR_REV + 1) static const unsigned TMC_tformat[ TMC_nr_tformat ] = { - [MESA_FORMAT_ARGB8888] = TMC_tformat_tw32 | TMC_takey_1 | TMC_tamask_0, - [MESA_FORMAT_RGB565] = TMC_tformat_tw16 | TMC_takey_1 | TMC_tamask_0, - [MESA_FORMAT_ARGB4444] = TMC_tformat_tw12 | TMC_takey_1 | TMC_tamask_0, - [MESA_FORMAT_ARGB1555] = TMC_tformat_tw15 | TMC_takey_1 | TMC_tamask_0, - [MESA_FORMAT_CI8] = TMC_tformat_tw8 | TMC_takey_1 | TMC_tamask_0, - [MESA_FORMAT_YCBCR] = TMC_tformat_tw422uyvy | TMC_takey_1 | TMC_tamask_0, - [MESA_FORMAT_YCBCR_REV] = TMC_tformat_tw422 | TMC_takey_1 | TMC_tamask_0, + [MESA_FORMAT_ARGB8888] = TMC_tformat_tw32, + [MESA_FORMAT_RGB565] = TMC_tformat_tw16, + [MESA_FORMAT_ARGB4444] = TMC_tformat_tw12, + [MESA_FORMAT_ARGB1555] = TMC_tformat_tw15, + [MESA_FORMAT_AL88] = TMC_tformat_tw8al, + [MESA_FORMAT_I8] = TMC_tformat_tw8a, + [MESA_FORMAT_CI8] = TMC_tformat_tw8 , + [MESA_FORMAT_YCBCR] = TMC_tformat_tw422uyvy, + [MESA_FORMAT_YCBCR_REV] = TMC_tformat_tw422, }; #endif @@ -63,11 +65,11 @@ mgaSetTexImages( mgaContextPtr mmesa, const struct gl_texture_object * tObj ) { mgaTextureObjectPtr t = (mgaTextureObjectPtr) tObj->DriverData; - struct gl_texture_image *baseImage = tObj->Image[ tObj->BaseLevel ]; + struct gl_texture_image *baseImage = tObj->Image[0][ tObj->BaseLevel ]; GLint totalSize; GLint width, height; GLint i; - GLint firstLevel, lastLevel, numLevels; + GLint numLevels; GLint log2Width, log2Height; GLuint txformat = 0; GLint ofs; @@ -81,6 +83,8 @@ mgaSetTexImages( mgaContextPtr mmesa, case MESA_FORMAT_RGB565: txformat = TMC_tformat_tw16; break; case MESA_FORMAT_ARGB4444: txformat = TMC_tformat_tw12; break; case MESA_FORMAT_ARGB1555: txformat = TMC_tformat_tw15; break; + case MESA_FORMAT_AL88: txformat = TMC_tformat_tw8al; break; + case MESA_FORMAT_I8: txformat = TMC_tformat_tw8a; break; case MESA_FORMAT_CI8: txformat = TMC_tformat_tw8; break; case MESA_FORMAT_YCBCR: txformat = TMC_tformat_tw422uyvy; break; case MESA_FORMAT_YCBCR_REV: txformat = TMC_tformat_tw422; break; @@ -101,61 +105,55 @@ mgaSetTexImages( mgaContextPtr mmesa, #endif /* MGA_USE_TABLE_FOR_FORMAT */ - if (tObj->MinFilter == GL_NEAREST || tObj->MinFilter == GL_LINEAR) { - /* GL_NEAREST and GL_LINEAR only care about GL_TEXTURE_BASE_LEVEL. - */ - - firstLevel = lastLevel = tObj->BaseLevel; + driCalculateTextureFirstLastLevel( (driTextureObject *) t ); + if (tObj->Target == GL_TEXTURE_RECTANGLE_NV) { + log2Width = 0; + log2Height = 0; } else { - /* 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. - */ - - 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 */ + log2Width = tObj->Image[0][t->base.firstLevel]->WidthLog2; + log2Height = tObj->Image[0][t->base.firstLevel]->HeightLog2; } - log2Width = tObj->Image[firstLevel]->WidthLog2; - log2Height = tObj->Image[firstLevel]->HeightLog2; - width = tObj->Image[firstLevel]->Width; - height = tObj->Image[firstLevel]->Height; + width = tObj->Image[0][t->base.firstLevel]->Width; + height = tObj->Image[0][t->base.firstLevel]->Height; - numLevels = MIN2( lastLevel - firstLevel + 1, + numLevels = MIN2( t->base.lastLevel - t->base.firstLevel + 1, MGA_IS_G200(mmesa) ? G200_TEX_MAXLEVELS : G400_TEX_MAXLEVELS); totalSize = 0; for ( i = 0 ; i < numLevels ; i++ ) { - const struct gl_texture_image * const texImage = tObj->Image[i+firstLevel]; + const struct gl_texture_image * const texImage = + tObj->Image[0][ i + t->base.firstLevel ]; + int size; - if ( (texImage == NULL) - || ((i != 0) - && ((texImage->Width < 8) || (texImage->Height < 8))) ) { + if (texImage == NULL) break; - } + + size = texImage->Width * texImage->Height * + _mesa_get_format_bytes(baseImage->TexFormat->MesaFormat); t->offsets[i] = totalSize; t->base.dirty_images[0] |= (1<Width, 8 ) * - MAX2( texImage->Height, 8 ) * - baseImage->TexFormat->TexelBytes) + 31) & ~31; - } + /* All mipmaps must be 32-byte aligned */ + totalSize += (size + 31) & ~31; - numLevels = i; - lastLevel = firstLevel + numLevels - 1; + /* Since G400 calculates the offsets in hardware + * it can't handle more than one < 32 byte mipmap. + * + * Further testing has indicated that it can't + * handle any < 32 byte mipmaps. + */ + if (MGA_IS_G400( mmesa ) && size <= 32) { + i++; + break; + } + } /* save these values */ - t->base.firstLevel = firstLevel; - t->base.lastLevel = lastLevel; - + numLevels = i; + t->base.lastLevel = t->base.firstLevel + numLevels - 1; t->base.totalSize = totalSize; /* setup hardware register values */ @@ -170,17 +168,17 @@ mgaSetTexImages( mgaContextPtr mmesa, */ t->setup.texctl |= TMC_tpitchlin_enable; - t->setup.texctl |= (width & (2048 - 1)) << TMC_tpitchext_SHIFT; + t->setup.texctl |= MGA_FIELD( TMC_tpitchext, width & (2048 - 1) ); /* G400 specifies the number of mip levels in a strange way. Since there - * are up to 12 levels, it requires 4 bits. Three of the bits are at the + * are up to 11 levels, it requires 4 bits. Three of the bits are at the * high end of TEXFILTER. The other bit is in the middle. Weird. */ - + numLevels--; t->setup.texfilter &= TF_mapnb_MASK & TF_mapnbhigh_MASK & TF_reserved_MASK; - t->setup.texfilter |= (((numLevels-1) & 0x07) << (TF_mapnb_SHIFT)); - t->setup.texfilter |= (((numLevels-1) & 0x08) << (TF_mapnbhigh_SHIFT - 3)); + t->setup.texfilter |= MGA_FIELD( TF_mapnb, numLevels & 0x7 ); + t->setup.texfilter |= MGA_FIELD( TF_mapnbhigh, (numLevels >> 3) & 0x1 ); /* warp texture registers */ ofs = MGA_IS_G200(mmesa) ? 28 : 11; @@ -203,168 +201,290 @@ mgaSetTexImages( mgaContextPtr mmesa, static void mgaUpdateTextureEnvG200( GLcontext *ctx, GLuint unit ) { + mgaContextPtr mmesa = MGA_CONTEXT(ctx); struct gl_texture_object *tObj = ctx->Texture.Unit[0]._Current; - mgaTextureObjectPtr t; + mgaTextureObjectPtr t = (mgaTextureObjectPtr) tObj->DriverData; + GLenum format = tObj->Image[0][tObj->BaseLevel]->_BaseFormat; - if (!tObj || !tObj->DriverData) + if (tObj != ctx->Texture.Unit[0].CurrentTex[TEXTURE_2D_INDEX] && + tObj != ctx->Texture.Unit[0].CurrentTex[TEXTURE_RECT_INDEX]) return; - t = (mgaTextureObjectPtr)tObj->DriverData; - t->setup.texctl2 &= ~TMC_decalblend_enable; + t->setup.texctl &= ~TMC_tmodulate_enable; + t->setup.texctl2 &= ~(TMC_decalblend_enable | + TMC_idecal_enable | + TMC_decaldis_enable); switch (ctx->Texture.Unit[0].EnvMode) { case GL_REPLACE: - t->setup.texctl &= ~TMC_tmodulate_enable; + if (format == GL_ALPHA) + t->setup.texctl2 |= TMC_idecal_enable; + + if (format == GL_RGB || format == GL_LUMINANCE) + mmesa->hw.alpha_sel = AC_alphasel_diffused; + else + mmesa->hw.alpha_sel = AC_alphasel_fromtex; break; + case GL_MODULATE: t->setup.texctl |= TMC_tmodulate_enable; + + if (format == GL_ALPHA) + t->setup.texctl2 |= (TMC_idecal_enable | + TMC_decaldis_enable); + + if (format == GL_RGB || format == GL_LUMINANCE) + mmesa->hw.alpha_sel = AC_alphasel_diffused; + else + mmesa->hw.alpha_sel = AC_alphasel_modulated; break; + case GL_DECAL: - t->setup.texctl &= ~TMC_tmodulate_enable; - t->setup.texctl2 |= TMC_decalblend_enable; + if (format == GL_RGB || format == GL_RGBA) + t->setup.texctl2 |= TMC_decalblend_enable; + else + t->setup.texctl2 |= TMC_idecal_enable; + + mmesa->hw.alpha_sel = AC_alphasel_diffused; break; + case GL_BLEND: - FALLBACK( ctx, MGA_FALLBACK_TEXTURE, GL_TRUE ); + if (format == GL_ALPHA) { + t->setup.texctl2 |= TMC_idecal_enable; + mmesa->hw.alpha_sel = AC_alphasel_modulated; + } else { + t->texenv_fallback = GL_TRUE; + } break; + default: break; } } -#define MGA_DISABLE 0 -#define MGA_REPLACE 1 -#define MGA_MODULATE 2 -#define MGA_DECAL 3 -#define MGA_BLEND 4 -#define MGA_ADD 5 -#define MGA_MAX_COMBFUNC 6 +#define MGA_REPLACE 0 +#define MGA_MODULATE 1 +#define MGA_DECAL 2 +#define MGA_ADD 3 +#define MGA_MAX_COMBFUNC 4 static const GLuint g400_color_combine[][MGA_MAX_COMBFUNC] = { /* Unit 0: */ { - /* Disable combiner stage - */ - (0), - /* GL_REPLACE + * Cv = Cs + * Av = Af */ (TD0_color_sel_arg1 | TD0_alpha_arg2_diffuse | - TD0_alpha_sel_arg2 ), + TD0_alpha_sel_arg2), /* GL_MODULATE + * Cv = Cf Cs + * Av = Af */ (TD0_color_arg2_diffuse | TD0_color_sel_mul | TD0_alpha_arg2_diffuse | - TD0_alpha_sel_mul), + TD0_alpha_sel_arg2), /* GL_DECAL + * Cv = Cs + * Av = Af */ (TD0_color_sel_arg1 | TD0_alpha_arg2_diffuse | TD0_alpha_sel_arg2), - /* GL_BLEND - */ - (0), - /* GL_ADD + * Cv = Cf + Cs + * Av = Af */ (TD0_color_arg2_diffuse | TD0_color_add_add | TD0_color_sel_add | TD0_alpha_arg2_diffuse | - TD0_alpha_sel_mul), + TD0_alpha_sel_arg2), }, /* Unit 1: */ { - /* Disable combiner stage - */ - (0), - /* GL_REPLACE + * Cv = Cs + * Av = Ap */ (TD0_color_sel_arg1 | - TD0_alpha_arg2_diffuse | - TD0_alpha_sel_arg2 ), + TD0_alpha_arg2_prevstage | + TD0_alpha_sel_arg2), /* GL_MODULATE + * Cv = Cp Cs + * Av = Ap */ (TD0_color_arg2_prevstage | - TD0_color_alpha_prevstage | TD0_color_sel_mul | TD0_alpha_arg2_prevstage | - TD0_alpha_sel_mul), + TD0_alpha_sel_arg2), /* GL_DECAL + * Cv = Cs + * Av = Ap */ (TD0_color_sel_arg1 | TD0_alpha_arg2_prevstage | - TD0_alpha_sel_arg2 ), - - /* GL_BLEND - */ - (0), + TD0_alpha_sel_arg2), /* GL_ADD + * Cv = Cp + Cs + * Av = Ap */ (TD0_color_arg2_prevstage | - TD0_color_alpha_prevstage | TD0_color_add_add | TD0_color_sel_add | TD0_alpha_arg2_prevstage | - TD0_alpha_sel_mul), + TD0_alpha_sel_arg2), }, }; -static const GLuint g400_alpha_combine[][MGA_MAX_COMBFUNC] = +static const GLuint g400_color_alpha_combine[][MGA_MAX_COMBFUNC] = { /* Unit 0: */ { - /* Disable combiner stage - */ - (0), - /* GL_REPLACE + * Cv = Cs + * Av = As */ - (TD0_color_sel_arg2 | - TD0_color_arg2_diffuse | - TD0_alpha_sel_arg1 ), + (TD0_color_sel_arg1 | + TD0_alpha_sel_arg1), /* GL_MODULATE - * FIXME: Is this correct? + * Cv = Cf Cs + * Av = Af As */ (TD0_color_arg2_diffuse | TD0_color_sel_mul | TD0_alpha_arg2_diffuse | TD0_alpha_sel_mul), - + /* GL_DECAL + * tmp = Cf ( 1 - As ) + * Cv = tmp + Cs As + * Av = Af */ (TD0_color_arg2_diffuse | - TD0_color_sel_arg2 | + TD0_color_alpha_currtex | + TD0_color_alpha1inv_enable | + TD0_color_arg1mul_alpha1 | + TD0_color_blend_enable | + TD0_color_arg1add_mulout | + TD0_color_arg2add_mulout | + TD0_color_add_add | + TD0_color_sel_add | TD0_alpha_arg2_diffuse | TD0_alpha_sel_arg2), - /* GL_BLEND + /* GL_ADD + * Cv = Cf + Cs + * Av = Af As */ (TD0_color_arg2_diffuse | + TD0_color_add_add | + TD0_color_sel_add | + TD0_alpha_arg2_diffuse | + TD0_alpha_sel_mul), + }, + + /* Unit 1: + */ + { + /* GL_REPLACE + * Cv = Cs + * Av = As + */ + (TD0_color_sel_arg1 | + TD0_alpha_sel_arg1), + + /* GL_MODULATE + * Cv = Cp Cs + * Av = Ap As + */ + (TD0_color_arg2_prevstage | TD0_color_sel_mul | + TD0_alpha_arg2_prevstage | + TD0_alpha_sel_mul), + + /* GL_DECAL + * tmp = Cp ( 1 - As ) + * Cv = tmp + Cs As + * Av = Ap + */ + (TD0_color_arg2_prevstage | + TD0_color_alpha_currtex | + TD0_color_alpha1inv_enable | + TD0_color_arg1mul_alpha1 | + TD0_color_blend_enable | + TD0_color_arg1add_mulout | + TD0_color_arg2add_mulout | + TD0_color_add_add | + TD0_color_sel_add | + TD0_alpha_arg2_prevstage | + TD0_alpha_sel_arg2), + + /* GL_ADD + * Cv = Cp + Cs + * Av = Ap As + */ + (TD0_color_arg2_prevstage | + TD0_color_add_add | + TD0_color_sel_add | + TD0_alpha_arg2_prevstage | + TD0_alpha_sel_mul), + }, +}; + +static const GLuint g400_alpha_combine[][MGA_MAX_COMBFUNC] = +{ + /* Unit 0: + */ + { + /* GL_REPLACE + * Cv = Cf + * Av = As + */ + (TD0_color_arg2_diffuse | + TD0_color_sel_arg2 | + TD0_alpha_sel_arg1), + + /* GL_MODULATE + * Cv = Cf + * Av = Af As + */ + (TD0_color_arg2_diffuse | + TD0_color_sel_arg2 | TD0_alpha_arg2_diffuse | TD0_alpha_sel_mul), + /* GL_DECAL (undefined) + * Cv = Cf + * Av = Af + */ + (TD0_color_arg2_diffuse | + TD0_color_sel_arg2 | + TD0_alpha_arg2_diffuse | + TD0_alpha_sel_arg2), + /* GL_ADD + * Cv = Cf + * Av = Af As */ (TD0_color_arg2_diffuse | - TD0_color_sel_mul | + TD0_color_sel_arg2 | TD0_alpha_arg2_diffuse | TD0_alpha_sel_mul), }, @@ -372,48 +492,139 @@ static const GLuint g400_alpha_combine[][MGA_MAX_COMBFUNC] = /* Unit 1: */ { - /* Disable combiner stage - */ - (0), - /* GL_REPLACE + * Cv = Cp + * Av = As */ - (TD0_color_sel_arg2 | - TD0_color_arg2_diffuse | - TD0_alpha_sel_arg1 ), + (TD0_color_arg2_prevstage | + TD0_color_sel_arg2 | + TD0_alpha_sel_arg1), /* GL_MODULATE - * FIXME: Is this correct? + * Cv = Cp + * Av = Ap As */ (TD0_color_arg2_prevstage | - TD0_color_alpha_prevstage | - TD0_color_sel_mul | + TD0_color_sel_arg2 | TD0_alpha_arg2_prevstage | TD0_alpha_sel_mul), - /* GL_DECAL + /* GL_DECAL (undefined) + * Cv = Cp + * Av = Ap */ (TD0_color_arg2_prevstage | TD0_color_sel_arg2 | TD0_alpha_arg2_prevstage | TD0_alpha_sel_arg2), - /* GL_BLEND - */ - (TD0_color_arg2_diffuse | - TD0_color_sel_mul | - TD0_alpha_arg2_diffuse | - TD0_alpha_sel_mul), - /* GL_ADD + * Cv = Cp + * Av = Ap As */ (TD0_color_arg2_prevstage | - TD0_color_sel_mul | + TD0_color_sel_arg2 | TD0_alpha_arg2_prevstage | TD0_alpha_sel_mul), }, }; +static GLboolean mgaUpdateTextureEnvBlend( GLcontext *ctx, int unit ) +{ + mgaContextPtr mmesa = MGA_CONTEXT(ctx); + const int source = mmesa->tmu_source[unit]; + const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[source]; + const struct gl_texture_object *tObj = texUnit->_Current; + GLuint *reg = ((GLuint *)&mmesa->setup.tdualstage0 + unit); + GLenum format = tObj->Image[0][tObj->BaseLevel]->_BaseFormat; + + *reg = 0; + + if (format == GL_ALPHA) { + /* Cv = Cf */ + *reg |= (TD0_color_arg2_diffuse | + TD0_color_sel_arg2); + /* Av = Af As */ + *reg |= (TD0_alpha_arg2_diffuse | + TD0_alpha_sel_mul); + return GL_TRUE; + } + + /* C1 = Cf ( 1 - Cs ) */ + *reg |= (TD0_color_arg1_inv_enable | + TD0_color_arg2_diffuse | + TD0_color_sel_mul); + + if (format == GL_RGB || format == GL_LUMINANCE) { + /* A1 = Af */ + *reg |= (TD0_alpha_arg2_diffuse | + TD0_alpha_sel_arg2); + } else + if (format == GL_RGBA || format == GL_LUMINANCE_ALPHA) { + /* A1 = Af As */ + *reg |= (TD0_alpha_arg2_diffuse | + TD0_alpha_sel_mul); + } else + if (format == GL_INTENSITY) { + /* A1 = Af ( 1 - As ) */ + *reg |= (TD0_alpha_arg1_inv_enable | + TD0_alpha_arg2_diffuse | + TD0_alpha_sel_mul); + } + + if (RGB_ZERO(mmesa->envcolor[source]) && + (format != GL_INTENSITY || ALPHA_ZERO(mmesa->envcolor[source]))) + return GL_TRUE; /* all done */ + + if (ctx->Texture._EnabledUnits == 0x03) + return GL_FALSE; /* need both units */ + + mmesa->force_dualtex = GL_TRUE; + reg = &mmesa->setup.tdualstage1; + *reg = 0; + + if (RGB_ZERO(mmesa->envcolor[source])) { + /* Cv = C1 */ + *reg |= (TD0_color_arg2_prevstage | + TD0_color_sel_arg2); + } else + if (RGB_ONE(mmesa->envcolor[source])) { + /* Cv = C1 + Cs */ + *reg |= (TD0_color_arg2_prevstage | + TD0_color_add_add | + TD0_color_sel_add); + } else + if (RGBA_EQUAL(mmesa->envcolor[source])) { + /* Cv = C1 + Cc Cs */ + *reg |= (TD0_color_arg2_prevstage | + TD0_color_alpha_fcol | + TD0_color_arg2mul_alpha2 | + TD0_color_arg1add_mulout | + TD0_color_add_add | + TD0_color_sel_add); + + mmesa->setup.fcol = mmesa->envcolor[source]; + } else { + return GL_FALSE; + } + + if (format != GL_INTENSITY || ALPHA_ZERO(mmesa->envcolor[source])) { + /* Av = A1 */ + *reg |= (TD0_alpha_arg2_prevstage | + TD0_alpha_sel_arg2); + } else + if (ALPHA_ONE(mmesa->envcolor[source])) { + /* Av = A1 + As */ + *reg |= (TD0_alpha_arg2_prevstage | + TD0_alpha_add_enable | + TD0_alpha_sel_add); + } else { + return GL_FALSE; + } + + return GL_TRUE; +} + static void mgaUpdateTextureEnvG400( GLcontext *ctx, GLuint unit ) { mgaContextPtr mmesa = MGA_CONTEXT( ctx ); @@ -421,143 +632,96 @@ static void mgaUpdateTextureEnvG400( GLcontext *ctx, GLuint unit ) const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[source]; const struct gl_texture_object *tObj = texUnit->_Current; GLuint *reg = ((GLuint *)&mmesa->setup.tdualstage0 + unit); - GLenum format; + mgaTextureObjectPtr t = (mgaTextureObjectPtr) tObj->DriverData; + GLenum format = tObj->Image[0][tObj->BaseLevel]->_BaseFormat; - if ( tObj != ctx->Texture.Unit[source].Current2D || !tObj ) + if (tObj != ctx->Texture.Unit[source].CurrentTex[TEXTURE_2D_INDEX] && + tObj != ctx->Texture.Unit[source].CurrentTex[TEXTURE_RECT_INDEX]) return; - format = tObj->Image[tObj->BaseLevel]->Format; - switch (ctx->Texture.Unit[source].EnvMode) { case GL_REPLACE: - if (format == GL_RGB || format == GL_LUMINANCE) { - *reg = g400_color_combine[unit][MGA_REPLACE]; - } - else if (format == GL_ALPHA) { + if (format == GL_ALPHA) { *reg = g400_alpha_combine[unit][MGA_REPLACE]; - } - else { - *reg = (TD0_color_sel_arg1 | - TD0_alpha_sel_arg1 ); + } else if (format == GL_RGB || format == GL_LUMINANCE) { + *reg = g400_color_combine[unit][MGA_REPLACE]; + } else { + *reg = g400_color_alpha_combine[unit][MGA_REPLACE]; } break; case GL_MODULATE: - *reg = g400_color_combine[unit][MGA_MODULATE]; + if (format == GL_ALPHA) { + *reg = g400_alpha_combine[unit][MGA_MODULATE]; + } else if (format == GL_RGB || format == GL_LUMINANCE) { + *reg = g400_color_combine[unit][MGA_MODULATE]; + } else { + *reg = g400_color_alpha_combine[unit][MGA_MODULATE]; + } break; + case GL_DECAL: if (format == GL_RGB) { - *reg = g400_color_combine[unit][MGA_DECAL]; + *reg = g400_color_combine[unit][MGA_DECAL]; + } else if (format == GL_RGBA) { + *reg = g400_color_alpha_combine[unit][MGA_DECAL]; + if (ctx->Texture._EnabledUnits != 0x03) { + /* Linear blending mode needs dual texturing enabled */ + *(reg+1) = (TD0_color_arg2_prevstage | + TD0_color_sel_arg2 | + TD0_alpha_arg2_prevstage | + TD0_alpha_sel_arg2); + mmesa->force_dualtex = GL_TRUE; + } + } else { + /* Undefined */ + *reg = g400_alpha_combine[unit][MGA_DECAL]; } - else if ( format == GL_RGBA ) { -#if 0 + break; + + case GL_ADD: + if (format == GL_ALPHA) { + *reg = g400_alpha_combine[unit][MGA_ADD]; + } else if (format == GL_RGB || format == GL_LUMINANCE) { + *reg = g400_color_combine[unit][MGA_ADD]; + } else if (format == GL_RGBA || format == GL_LUMINANCE_ALPHA) { + *reg = g400_color_alpha_combine[unit][MGA_ADD]; + } else if (format == GL_INTENSITY) { + /* Cv = Cf + Cs + * Av = Af + As + */ if (unit == 0) { - /* this doesn't work */ *reg = (TD0_color_arg2_diffuse | - TD0_color_alpha_currtex | - TD0_color_alpha2inv_enable | - TD0_color_arg2mul_alpha2 | - TD0_color_arg1mul_alpha1 | - TD0_color_blend_enable | - TD0_color_arg1add_mulout | - TD0_color_arg2add_mulout | TD0_color_add_add | - TD0_color_sel_mul | + TD0_color_sel_add | TD0_alpha_arg2_diffuse | - TD0_alpha_sel_arg2 ); - } - else { + TD0_alpha_add_enable | + TD0_alpha_sel_add); + } else { *reg = (TD0_color_arg2_prevstage | - TD0_color_alpha_currtex | - TD0_color_alpha2inv_enable | - TD0_color_arg2mul_alpha2 | - TD0_color_arg1mul_alpha1 | TD0_color_add_add | TD0_color_sel_add | TD0_alpha_arg2_prevstage | - TD0_alpha_sel_arg2 ); + TD0_alpha_add_enable | + TD0_alpha_sel_add); } -#else - /* s/w fallback, pretty sure we can't do in h/w */ - FALLBACK( ctx, MGA_FALLBACK_TEXTURE, GL_TRUE ); - if ( MGA_DEBUG & DEBUG_VERBOSE_FALLBACK ) - fprintf( stderr, "FALLBACK: GL_DECAL RGBA texture, unit=%d\n", - unit ); -#endif - } - else { - *reg = g400_alpha_combine[unit][MGA_DECAL]; } break; - case GL_ADD: - if (format == GL_INTENSITY) { - if (unit == 0) { - *reg = ( TD0_color_arg2_diffuse | - TD0_color_add_add | - TD0_color_sel_add | - TD0_alpha_arg2_diffuse | - TD0_alpha_add_enable | - TD0_alpha_sel_add); - } - else { - *reg = ( TD0_color_arg2_prevstage | - TD0_color_add_add | - TD0_color_sel_add | - TD0_alpha_arg2_prevstage | - TD0_alpha_add_enable | - TD0_alpha_sel_add); - } - } - else if (format == GL_ALPHA) { - *reg = g400_alpha_combine[unit][MGA_ADD]; - } - else { - *reg = g400_color_combine[unit][MGA_ADD]; - } - break; - case GL_BLEND: - if (format == GL_ALPHA) { - *reg = g400_alpha_combine[unit][MGA_BLEND]; - } - else { - FALLBACK( ctx, MGA_FALLBACK_TEXTURE, GL_TRUE ); - if ( MGA_DEBUG & DEBUG_VERBOSE_FALLBACK ) - fprintf( stderr, "FALLBACK: GL_BLEND envcolor=0x%08x\n", - mmesa->envcolor ); - - /* Do singletexture GL_BLEND with 'all ones' env-color - * by using both texture units. Multitexture gl_blend - * is a fallback. - */ - if (unit == 0) { - /* Part 1: R1 = Rf ( 1 - Rt ) - * A1 = Af At - */ - *reg = ( TD0_color_arg2_diffuse | - TD0_color_arg1_inv_enable | - TD0_color_sel_mul | - TD0_alpha_arg2_diffuse | - TD0_alpha_sel_arg1); - } else { - /* Part 2: R2 = R1 + Rt - * A2 = A1 - */ - *reg = ( TD0_color_arg2_prevstage | - TD0_color_add_add | - TD0_color_sel_add | - TD0_alpha_arg2_prevstage | - TD0_alpha_sel_arg2); - } - } + if (!mgaUpdateTextureEnvBlend(ctx, unit)) + t->texenv_fallback = GL_TRUE; + break; + + case GL_COMBINE: + if (!mgaUpdateTextureEnvCombine(ctx, unit)) + t->texenv_fallback = GL_TRUE; break; default: break; } } - static void disable_tex( GLcontext *ctx, int unit ) { mgaContextPtr mmesa = MGA_CONTEXT( ctx ); @@ -573,7 +737,7 @@ static void disable_tex( GLcontext *ctx, int unit ) mmesa->CurrentTexObj[unit] = NULL; } - if ( unit != 0 ) { + if ( unit != 0 && !mmesa->force_dualtex ) { mmesa->setup.tdualstage1 = mmesa->setup.tdualstage0; } @@ -586,7 +750,7 @@ static void disable_tex( GLcontext *ctx, int unit ) mmesa->dirty |= MGA_UPLOAD_CONTEXT | (MGA_UPLOAD_TEX0 << unit); } -static GLboolean enable_tex_2d( GLcontext *ctx, int unit ) +static GLboolean enable_tex( GLcontext *ctx, int unit ) { mgaContextPtr mmesa = MGA_CONTEXT(ctx); const int source = mmesa->tmu_source[unit]; @@ -616,7 +780,7 @@ static GLboolean update_tex_common( GLcontext *ctx, int unit ) mgaTextureObjectPtr t = (mgaTextureObjectPtr) tObj->DriverData; /* Fallback if there's a texture border */ - if ( tObj->Image[tObj->BaseLevel]->Border > 0 ) { + if ( tObj->Image[0][tObj->BaseLevel]->Border > 0 ) { return GL_FALSE; } @@ -644,10 +808,13 @@ static GLboolean update_tex_common( GLcontext *ctx, int unit ) mmesa->setup.tdualstage1 = mmesa->setup.tdualstage0; } - t->setup.texctl2 &= TMC_dualtex_MASK; - if (ctx->Texture._EnabledUnits == 0x03) { - t->setup.texctl2 |= TMC_dualtex_enable; - } + t->texenv_fallback = GL_FALSE; + + /* Set this before mgaUpdateTextureEnvG400() since + * GL_ARB_texture_env_crossbar may have to disable texturing. + */ + mmesa->setup.dwgctl &= DC_opcod_MASK; + mmesa->setup.dwgctl |= DC_opcod_texture_trap; /* FIXME: The Radeon has some cached state so that it can avoid calling * FIXME: UpdateTextureEnv in some cases. Is that possible here? @@ -663,30 +830,18 @@ static GLboolean update_tex_common( GLcontext *ctx, int unit ) mgaUpdateTextureEnvG400( ctx, unit ); } else { - mmesa->hw.alpha_sel = 0; - switch (ctx->Texture.Unit[0].EnvMode) { - case GL_DECAL: - mmesa->hw.alpha_sel |= AC_alphasel_diffused; - case GL_REPLACE: - mmesa->hw.alpha_sel |= AC_alphasel_fromtex; - break; - case GL_BLEND: - case GL_MODULATE: - mmesa->hw.alpha_sel |= AC_alphasel_modulated; - break; - default: - break; - } - mgaUpdateTextureEnvG200( ctx, unit ); } - mmesa->setup.dwgctl &= DC_opcod_MASK; - mmesa->setup.dwgctl |= DC_opcod_texture_trap; + t->setup.texctl2 &= TMC_dualtex_MASK; + if (ctx->Texture._EnabledUnits == 0x03 || mmesa->force_dualtex) { + t->setup.texctl2 |= TMC_dualtex_enable; + } + mmesa->dirty |= MGA_UPLOAD_CONTEXT | (MGA_UPLOAD_TEX0 << unit); FALLBACK( ctx, MGA_FALLBACK_BORDER_MODE, t->border_fallback ); - return !t->border_fallback; + return !t->border_fallback && !t->texenv_fallback; } @@ -697,8 +852,9 @@ static GLboolean updateTextureUnit( GLcontext *ctx, int unit ) const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[source]; - if ( texUnit->_ReallyEnabled == TEXTURE_2D_BIT) { - return(enable_tex_2d( ctx, unit ) && + if ( texUnit->_ReallyEnabled == TEXTURE_2D_BIT || + texUnit->_ReallyEnabled == TEXTURE_RECT_BIT ) { + return(enable_tex( ctx, unit ) && update_tex_common( ctx, unit )); } else if ( texUnit->_ReallyEnabled ) { @@ -718,6 +874,8 @@ void mgaUpdateTextureState( GLcontext *ctx ) GLboolean ok; unsigned i; + mmesa->force_dualtex = GL_FALSE; + mmesa->fcol_used = GL_FALSE; /* This works around a quirk with the MGA hardware. If only OpenGL * TEXTURE1 is enabled, then the hardware TEXTURE0 must be used. The @@ -740,8 +898,4 @@ void mgaUpdateTextureState( GLcontext *ctx ) } FALLBACK( ctx, MGA_FALLBACK_TEXTURE, !ok ); - - /* FIXME: I believe that ChooseVertexState should be called here instead of - * FIXME: in mgaDDValidateState. - */ }