xHere are a bunch of patches for MGA texturing code. mga_mipmap.patch: - Fix tpitch when firstLevel > baseLevel.
- Fix some confusion regarding level vs. hwlevel with dirty_images[0] and tex size calculation. - Call mgaUploadSubImage() starting from firstLevel not 0 and make it take the real level as the argument instead of hwlevel. Eliminates a bunch of ugly warnings. I sent this one earlier but no-one picked it up for the dri tree. It's already in Mesa embedded-2-brach. mga_accel_rop.patch: - Make the two remaining LogicOp fallbacks depend on ACCEL_ROP. It looks like the right thing to do but I maybe wrong... mga_texwrap.patch: - Remove misleading comment about supported wrap modes. - Remove GL_CLAMP_TO_BORDER stuff. Cut'n'paste error? mga_minfilter.patch - Min filters GL_NEAREST and GL_LINEAR should use the base level texture. Probably not the optimal way to solve this but it works ;) mga_texformat.patch: - Add MESA_FORMAT_{AL88,A8,L8,I8} for G400. - G200 doesn't support MESA_FORMAT_YCBCR. mga_texenv.patch: - Fix all texenv modes for all texformats on G400. - Implement GL_DECAL using linear blend mode. The G400 docs aren't very clear on this subject so I'm not entirely sure if it will work correctly with multi texturing. Anyone have a good test? - GL_BLEND suffers from hardware limitations. All three components of Cc must be equal. Additionally GL_INTENSITY requires that Ac is 0.0 or 1.0. If Cc!=0.0 (or Ac!=0.0 for GL_INTENSITY) we need both units to get things done in a single pass. - Passes glean's texenv test (32bpp and 16bpp). And without fallbacks if I change the envcolor to comply with the aforementioned restrictions. Also Quake3 looks ok with the patch ;) - I also removed the useless MGA_FALLBACK_BORDER_MODE thing. It didn't print anything since the debug print stopped at the first enabled fallback bit which was the texture fallback. -- Ville Syrjälä [EMAIL PROTECTED] http://www.sci.fi/~syrjala/
diff -urN mga.orig/mgastate.c mga/mgastate.c --- mga.orig/mgastate.c 2003-07-12 22:40:08.000000000 +0300 +++ mga/mgastate.c 2003-07-12 22:39:47.000000000 +0300 @@ -123,9 +123,11 @@ /* BlendEquation sets ColorLogicOpEnabled in an unexpected * manner. */ +#if !defined(ACCEL_ROP) FALLBACK( ctx, MGA_FALLBACK_LOGICOP, (ctx->Color.ColorLogicOpEnabled && ctx->Color.LogicOp != GL_COPY)); +#endif } static void mgaDDBlendFunc(GLcontext *ctx, GLenum sfactor, GLenum dfactor) @@ -900,9 +902,11 @@ /* For some reason enable(GL_BLEND) affects ColorLogicOpEnabled. */ +#if !defined(ACCEL_ROP) FALLBACK( ctx, MGA_FALLBACK_LOGICOP, (ctx->Color.ColorLogicOpEnabled && ctx->Color.LogicOp != GL_COPY)); +#endif break; case GL_DEPTH_TEST: FLUSH_BATCH( mmesa );
diff -urN mga.orig/mga_texstate.c mga/mga_texstate.c --- mga.orig/mga_texstate.c 2003-07-12 22:40:08.000000000 +0300 +++ mga/mga_texstate.c 2003-07-12 22:42:30.000000000 +0300 @@ -106,14 +106,17 @@ * 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 */ + if (tObj->MinFilter == GL_NEAREST || tObj->MinFilter == GL_LINEAR) { + 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 */ + } log2Width = tObj->Image[firstLevel]->WidthLog2; log2Height = tObj->Image[firstLevel]->HeightLog2; width = tObj->Image[firstLevel]->Width; diff -urN mga.orig/mgatex.c mga/mgatex.c --- mga.orig/mgatex.c 2003-07-12 22:40:08.000000000 +0300 +++ mga/mgatex.c 2003-07-12 22:42:45.000000000 +0300 @@ -449,6 +445,7 @@ switch (pname) { case GL_TEXTURE_MIN_FILTER: + driSwapOutTextureObject( (driTextureObject *) t ); case GL_TEXTURE_MAG_FILTER: FLUSH_BATCH(mmesa); mgaSetTexFilter( t, tObj->MinFilter, tObj->MagFilter );
diff -urN mga.orig/mga_texstate.c mga/mga_texstate.c --- mga.orig/mga_texstate.c 2003-07-12 22:44:37.000000000 +0300 +++ mga/mga_texstate.c 2003-07-12 22:46:49.000000000 +0300 @@ -134,7 +134,7 @@ totalSize = 0; for ( i = 0 ; i < numLevels ; i++ ) { - const struct gl_texture_image * const texImage = tObj->Image[i]; + const struct gl_texture_image * const texImage = tObj->Image[i+firstLevel]; if ( (texImage == NULL) || ((i != 0) @@ -143,10 +143,10 @@ } t->offsets[i] = totalSize; - t->base.dirty_images[0] |= (1<<i); + t->base.dirty_images[0] |= (1<<(i+firstLevel)); - totalSize += ((MAX2( texImage->Width, 8 ) * - MAX2( texImage->Height, 8 ) * + totalSize += ((texImage->Width * + texImage->Height * baseImage->TexFormat->TexelBytes) + 31) & ~31; } @@ -171,7 +171,7 @@ */ t->setup.texctl |= TMC_tpitchlin_enable; - t->setup.texctl |= (baseImage->Width & (2048 - 1)) << TMC_tpitchext_SHIFT; + t->setup.texctl |= (width & (2048 - 1)) << TMC_tpitchext_SHIFT; /* G400 specifies the number of mip levels in a strange way. Since there diff -urN mga.orig/mgatexmem.c mga/mgatexmem.c --- mga.orig/mgatexmem.c 2003-07-12 22:44:37.000000000 +0300 +++ mga/mgatexmem.c 2003-07-12 22:47:41.000000000 +0300 @@ -89,13 +89,13 @@ * been hardware accelerated. */ static void mgaUploadSubImage( mgaContextPtr mmesa, - mgaTextureObjectPtr t, GLint hwlevel ) + mgaTextureObjectPtr t, GLint level ) { struct gl_texture_image * texImage; unsigned offset; unsigned texelBytes; unsigned length; - const int level = hwlevel + t->firstLevel; + const int hwlevel = level - t->firstLevel; if ( (hwlevel < 0) @@ -265,7 +265,7 @@ fprintf(stderr, "[%s:%d] dirty_images[0] = 0x%04x\n", __FILE__, __LINE__, t->base.dirty_images[0] ); - for (i = 0 ; i <= t->lastLevel ; i++) { + for (i = t->firstLevel ; i <= t->lastLevel ; i++) { if ( (t->base.dirty_images[0] & (1U << i)) != 0 ) { mgaUploadSubImage( mmesa, t, i ); }
diff -urN mga.orig/mga_texstate.c mga/mga_texstate.c --- mga.orig/mga_texstate.c 2003-07-12 22:51:53.000000000 +0300 +++ mga/mga_texstate.c 2003-07-12 23:20:07.000000000 +0300 @@ -234,14 +234,13 @@ t->setup.texctl2 |= TMC_decalblend_enable; break; case GL_BLEND: - FALLBACK( ctx, MGA_FALLBACK_TEXTURE, GL_TRUE ); + t->texenv_fallback = GL_TRUE; break; default: break; } } - #define MGA_DISABLE 0 #define MGA_REPLACE 1 #define MGA_MODULATE 2 @@ -260,29 +259,160 @@ (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 + /* GL_BLEND (Cc == 0.0) + * Cv = Cf ( 1 - Cs ) + * Av = Af + */ + (TD0_color_arg1_inv_enable | + TD0_color_arg2_diffuse | + TD0_color_sel_mul | + TD0_alpha_arg2_diffuse | + TD0_alpha_sel_arg2), + + /* 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_arg2), + }, + + /* Unit 1: + */ + { + /* Disable combiner stage */ (0), + + /* GL_REPLACE + * Cv = Cs + * Av = Ap + */ + (TD0_color_sel_arg1 | + TD0_alpha_arg2_prevstage | + TD0_alpha_sel_arg2), + + /* GL_MODULATE + * Cv = Cp Cs + * Av = Ap + */ + (TD0_color_arg2_prevstage | + TD0_color_sel_mul | + TD0_alpha_arg2_prevstage | + TD0_alpha_sel_arg2), + + /* GL_DECAL + * Cv = Cs + * Av = Ap + */ + (TD0_color_sel_arg1 | + TD0_alpha_arg2_prevstage | + TD0_alpha_sel_arg2), + + /* GL_BLEND (Cc == 0.0) + * Cv = Cp ( 1 - Cs ) + * Av = Ap + */ + (TD0_color_arg1_inv_enable | + TD0_color_arg2_prevstage | + TD0_color_sel_mul | + TD0_alpha_arg2_prevstage | + TD0_alpha_sel_arg2), + + /* GL_ADD + * Cv = Cp + Cs + * Av = Ap + */ + (TD0_color_arg2_prevstage | + TD0_color_add_add | + TD0_color_sel_add | + TD0_alpha_arg2_prevstage | + TD0_alpha_sel_arg2), + }, +}; + +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_arg1 | + TD0_alpha_sel_arg1), + + /* GL_MODULATE + * 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_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 (Cc == 0.0) + * Cv = Cf ( 1 - Cs ) + * Av = Af As + */ + (TD0_color_arg1_inv_enable | + TD0_color_arg2_diffuse | + TD0_color_sel_mul | + TD0_alpha_arg2_diffuse | + TD0_alpha_sel_mul), /* GL_ADD + * Cv = Cf + Cs + * Av = Af As */ (TD0_color_arg2_diffuse | TD0_color_add_add | @@ -299,33 +429,53 @@ (0), /* GL_REPLACE + * Cv = Cs + * Av = As */ (TD0_color_sel_arg1 | - TD0_alpha_arg2_diffuse | - TD0_alpha_sel_arg2 ), + TD0_alpha_sel_arg1), /* GL_MODULATE + * Cv = Cp Cs + * Av = Ap As */ (TD0_color_arg2_prevstage | - TD0_color_alpha_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_sel_arg1 | + (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 ), + TD0_alpha_sel_arg2), - /* GL_BLEND + /* GL_BLEND (Cc == 0.0) + * Cv = Cp ( 1 - Cs ) + * Av = Ap As */ - (0), + (TD0_color_arg1_inv_enable | + TD0_color_arg2_prevstage | + TD0_color_sel_mul | + TD0_alpha_arg2_prevstage | + TD0_alpha_sel_mul), /* GL_ADD + * Cv = Cp + Cs + * Av = Ap As */ (TD0_color_arg2_prevstage | - TD0_color_alpha_prevstage | TD0_color_add_add | TD0_color_sel_add | TD0_alpha_arg2_prevstage | @@ -343,20 +493,25 @@ (0), /* GL_REPLACE + * Cv = Cf + * Av = As */ - (TD0_color_sel_arg2 | - TD0_color_arg2_diffuse | - TD0_alpha_sel_arg1 ), + (TD0_color_arg2_diffuse | + TD0_color_sel_arg2 | + TD0_alpha_sel_arg1), /* GL_MODULATE - * FIXME: Is this correct? + * 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), - /* GL_DECAL + /* GL_DECAL (undefined) + * Cv = Cf + * Av = Af */ (TD0_color_arg2_diffuse | TD0_color_sel_arg2 | @@ -364,16 +519,20 @@ TD0_alpha_sel_arg2), /* GL_BLEND + * 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), /* 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), }, @@ -386,21 +545,25 @@ (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 | @@ -408,21 +571,26 @@ TD0_alpha_sel_arg2), /* GL_BLEND + * Cv = Cp + * Av = Ap As */ - (TD0_color_arg2_diffuse | - TD0_color_sel_mul | - TD0_alpha_arg2_diffuse | + (TD0_color_arg2_prevstage | + TD0_color_sel_arg2 | + TD0_alpha_arg2_prevstage | 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 void mgaUpdateTextureEnvG400( GLcontext *ctx, GLuint unit ) { mgaContextPtr mmesa = MGA_CONTEXT( ctx ); @@ -430,6 +598,7 @@ 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); + mgaTextureObjectPtr t; GLenum format; if ( tObj != ctx->Texture.Unit[source].Current2D || !tObj ) @@ -437,127 +606,232 @@ format = tObj->Image[tObj->BaseLevel]->Format; + t = (mgaTextureObjectPtr) tObj->DriverData; + 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->dualtex_env = 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. + *reg = g400_alpha_combine[unit][MGA_BLEND]; + } else { + /* Hardware limitations: + * All three components of Cc must be equal. + * Also for GL_INTENSITY Ac must be either 0.0 or 1.0. + * If Cc != 0.0 (or Ac != 0.0 for GL_INTENSITY) we need both + * texture units to pull this off in a single pass. */ - 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); + if (mmesa->blend_flags & MGA_BLEND_RGB_ZERO) { + if (format == GL_RGB || format == GL_LUMINANCE) { + *reg = g400_color_combine[unit][MGA_BLEND]; + } else if (format == GL_RGBA || format == GL_LUMINANCE_ALPHA) { + *reg = g400_color_alpha_combine[unit][MGA_BLEND]; + } else if (format == GL_INTENSITY) { + if (mmesa->blend_flags & MGA_BLEND_ALPHA_ZERO) { + /* Cv = Cf ( 1 - Cs ) + * Av = Af ( 1 - As ) + */ + if (unit == 0) { + *reg = (TD0_color_arg1_inv_enable | + TD0_color_arg2_diffuse | + TD0_color_sel_mul | + TD0_alpha_arg1_inv_enable | + TD0_alpha_arg2_diffuse | + TD0_alpha_sel_mul); + } else { + *reg = (TD0_color_arg1_inv_enable | + TD0_color_arg2_prevstage | + TD0_color_sel_mul | + TD0_alpha_arg1_inv_enable | + TD0_alpha_arg2_prevstage | + TD0_alpha_sel_mul); + } + } else if (mmesa->blend_flags & MGA_BLEND_ALPHA_ONE && + ctx->Texture._EnabledUnits != 0x03) { + /* C1 = Cf ( 1 - Cs ) + * A1 = Af ( 1 - As ) + */ + *reg = (TD0_color_arg1_inv_enable | + TD0_color_arg2_diffuse | + TD0_color_sel_mul | + TD0_alpha_arg1_inv_enable | + TD0_alpha_arg2_diffuse | + TD0_alpha_sel_mul); + /* Cv = C1 + * Av = A1 + As + */ + *(reg+1) = (TD0_color_arg2_prevstage | + TD0_color_sel_arg2 | + TD0_alpha_arg2_prevstage | + TD0_alpha_add_enable | + TD0_alpha_sel_add); + mmesa->dualtex_env = GL_TRUE; + } else { + t->texenv_fallback = GL_TRUE; + } + } + } else if (mmesa->blend_flags & MGA_BLEND_RGB_EQUAL && + ctx->Texture._EnabledUnits != 0x03) { + if (format == GL_RGB || format == GL_LUMINANCE) { + /* C1 = Cf ( 1 - Cs ) + * A1 = Af + */ + *reg = (TD0_color_arg1_inv_enable | + TD0_color_arg2_diffuse | + TD0_color_sel_mul | + TD0_alpha_arg2_diffuse | + TD0_alpha_sel_arg2); + /* Cv = C1 + Cc Cs + * Av = A1 + */ + *(reg+1) = (TD0_color_arg2_prevstage | + TD0_color_alpha_fcol | + TD0_color_arg2mul_alpha2 | + TD0_color_arg1add_mulout | + TD0_color_add_add | + TD0_color_sel_add | + TD0_alpha_arg2_prevstage | + TD0_alpha_sel_arg2); + mmesa->dualtex_env = GL_TRUE; + } else if (format == GL_RGBA || format == GL_LUMINANCE_ALPHA) { + /* C1 = Cf ( 1 - Cs ) + * A1 = Af As + */ + *reg = (TD0_color_arg1_inv_enable | + TD0_color_arg2_diffuse | + TD0_color_sel_mul | + TD0_alpha_arg2_diffuse | + TD0_alpha_sel_mul); + /* Cv = C1 + Cc Cs + * Av = A1 + */ + *(reg+1) = (TD0_color_arg2_prevstage | + TD0_color_alpha_fcol | + TD0_color_arg2mul_alpha2 | + TD0_color_arg1add_mulout | + TD0_color_add_add | + TD0_color_sel_add | + TD0_alpha_arg2_prevstage | + TD0_alpha_sel_arg2); + mmesa->dualtex_env = GL_TRUE; + } else if (format == GL_INTENSITY) { + if (mmesa->blend_flags & MGA_BLEND_ALPHA_ZERO) { + /* C1 = Cf ( 1 - Cs ) + * A1 = Af ( 1 - As ) + */ + *reg = (TD0_color_arg1_inv_enable | + TD0_color_arg2_diffuse | + TD0_color_sel_mul | + TD0_alpha_arg1_inv_enable | + TD0_alpha_arg2_diffuse | + TD0_alpha_sel_mul); + /* Cv = C1 + Cc Cs + * Av = A1 + */ + *(reg+1) = (TD0_color_arg2_prevstage | + TD0_color_alpha_fcol | + TD0_color_arg2mul_alpha2 | + TD0_color_arg1add_mulout | + TD0_color_add_add | + TD0_color_sel_add | + TD0_alpha_arg2_prevstage | + TD0_alpha_sel_arg2); + mmesa->dualtex_env = GL_TRUE; + } else if (mmesa->blend_flags & MGA_BLEND_ALPHA_ONE) { + /* C1 = Cf ( 1 - Cs ) + * A1 = Af ( 1 - As ) + */ + *reg = (TD0_color_arg1_inv_enable | + TD0_color_arg2_diffuse | + TD0_color_sel_mul | + TD0_alpha_arg1_inv_enable | + TD0_alpha_arg2_diffuse | + TD0_alpha_sel_mul); + /* Cv = C1 + Cc Cs + * Av = A1 + As + */ + *(reg+1) = (TD0_color_arg2_prevstage | + TD0_color_alpha_fcol | + TD0_color_arg2mul_alpha2 | + TD0_color_arg1add_mulout | + TD0_color_add_add | + TD0_color_sel_add | + TD0_alpha_arg2_prevstage | + TD0_alpha_add_enable | + TD0_alpha_sel_add); + mmesa->dualtex_env = GL_TRUE; + } else { + t->texenv_fallback = GL_TRUE; + } + } } 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); + t->texenv_fallback = GL_TRUE; } } break; @@ -566,7 +840,6 @@ } } - static void disable_tex( GLcontext *ctx, int unit ) { mgaContextPtr mmesa = MGA_CONTEXT( ctx ); @@ -582,7 +855,7 @@ mmesa->CurrentTexObj[unit] = NULL; } - if ( unit != 0 ) { + if ( unit != 0 && !mmesa->dualtex_env) { mmesa->setup.tdualstage1 = mmesa->setup.tdualstage0; } @@ -658,6 +931,8 @@ t->setup.texctl2 |= TMC_dualtex_enable; } + t->texenv_fallback = GL_FALSE; + /* FIXME: The Radeon has some cached state so that it can avoid calling * FIXME: UpdateTextureEnv in some cases. Is that possible here? */ @@ -694,8 +969,7 @@ mmesa->setup.dwgctl |= DC_opcod_texture_trap; 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; } @@ -727,6 +1001,7 @@ GLboolean ok; unsigned i; + mmesa->dualtex_env = 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 diff -urN mga.orig/mgacontext.h mga/mgacontext.h --- mga.orig/mgacontext.h 2003-07-12 22:51:53.000000000 +0300 +++ mga/mgacontext.h 2003-07-12 23:20:16.000000000 +0300 @@ -59,7 +59,6 @@ #define MGA_FALLBACK_RENDERMODE 0x10 #define MGA_FALLBACK_STENCIL 0x20 #define MGA_FALLBACK_DEPTH 0x40 -#define MGA_FALLBACK_BORDER_MODE 0x80 /* Use the templated vertex formats: @@ -78,10 +77,12 @@ -/* Reasons why the GL_BLEND fallback mightn't work: +/* GL_BLEND has some limitations: */ -#define MGA_BLEND_ENV_COLOR 0x1 -#define MGA_BLEND_MULTITEX 0x2 +#define MGA_BLEND_RGB_ZERO 0x1 +#define MGA_BLEND_RGB_EQUAL 0x2 +#define MGA_BLEND_ALPHA_ZERO 0x4 +#define MGA_BLEND_ALPHA_ONE 0x8 struct mga_texture_object_s; struct mga_screen_private_s; @@ -150,6 +151,10 @@ * to fallback for GL_CLAMP_TO_BORDER. */ GLboolean border_fallback; + /* Depending on multitexturing and environment color GL_BLEND may need + * to fallback to software. + */ + GLboolean texenv_fallback; } mgaTextureObject_t; struct mga_hw_state { @@ -203,10 +208,11 @@ struct gl_client_array UbyteColor; struct gl_client_array UbyteSecondaryColor; - /* Support for limited GL_BLEND fallback + /* Support for GL_DECAL and GL_BLEND */ unsigned int blend_flags; unsigned int envcolor; + GLboolean dualtex_env; /* Rasterization state */ diff -urN mga.orig/mgastate.c mga/mgastate.c --- mga.orig/mgastate.c 2003-07-12 22:51:53.000000000 +0300 +++ mga/mgastate.c 2003-07-12 23:19:30.000000000 +0300 @@ -1057,7 +1057,11 @@ sizeof(sarea->TexState[1])); } - if ( (sarea->TexState[0].texctl2 & TMC_borderen_MASK) != + if (mmesa->dualtex_env) { + sarea->TexState[0].texctl2 |= TMC_dualtex_enable; + memcpy( &sarea->TexState[1], &sarea->TexState[0], + sizeof(sarea->TexState[0]) ); + } else if ( (sarea->TexState[0].texctl2 & TMC_borderen_MASK) != (sarea->TexState[1].texctl2 & TMC_borderen_MASK) ) { const int borderen = sarea->TexState[1].texctl2 & ~TMC_borderen_MASK; @@ -1233,6 +1237,10 @@ mmesa->setup.tdualstage1 = 0; mmesa->setup.fcol = 0; mmesa->dirty |= MGA_UPLOAD_CONTEXT; + + mmesa->envcolor = 0; + mmesa->blend_flags = MGA_BLEND_RGB_ZERO | MGA_BLEND_ALPHA_ZERO; + mmesa->dualtex_env = GL_FALSE; } diff -urN mga.orig/mgatex.c mga/mgatex.c --- mga.orig/mgatex.c 2003-07-12 22:51:53.000000000 +0300 +++ mga/mgatex.c 2003-07-12 23:00:49.000000000 +0300 @@ -333,24 +333,30 @@ GLuint envColor; UNCLAMPED_FLOAT_TO_RGBA_CHAN( c, texUnit->EnvColor ); - envColor = mgaPackColor( mmesa->mgaScreen->cpp, c[0], c[1], c[2], c[3] ); - mmesa->envcolor = PACK_COLOR_8888( c[3], c[0], c[1], c[2] ); + envColor = PACK_COLOR_8888( c[3], c[0], c[1], c[2] ); - if (mmesa->setup.fcol != envColor) { + if (mmesa->envcolor != envColor) { + mmesa->envcolor = envColor; + + /* We use the alpha part of the register for R,G,B + * which is why all three components must be equal. + */ + envColor = PACK_COLOR_8888( c[0], c[0], c[0], c[0] ); FLUSH_BATCH(mmesa); mmesa->setup.fcol = envColor; mmesa->dirty |= MGA_UPLOAD_CONTEXT; - mmesa->blend_flags &= ~MGA_BLEND_ENV_COLOR; + mmesa->blend_flags = 0; - /* Actually just require all four components to be - * equal. This permits a single-pass GL_BLEND. - * - * More complex multitexture/multipass fallbacks - * for blend can be done later. - */ - if (mmesa->envcolor != 0x0 && mmesa->envcolor != 0xffffffff) - mmesa->blend_flags |= MGA_BLEND_ENV_COLOR; + if ((mmesa->envcolor & 0xffffff) == 0x0) + mmesa->blend_flags |= MGA_BLEND_RGB_ZERO; + else if ((mmesa->envcolor & 0xffffff) == (envColor & 0xffffff)) + mmesa->blend_flags |= MGA_BLEND_RGB_EQUAL; + + if ((mmesa->envcolor >> 24) == 0x0) + mmesa->blend_flags |= MGA_BLEND_ALPHA_ZERO; + else if ((mmesa->envcolor >> 24) == 0xff) + mmesa->blend_flags |= MGA_BLEND_ALPHA_ONE; } break; }
diff -urN mga.orig/mga_texstate.c mga/mga_texstate.c --- mga.orig/mga_texstate.c 2003-07-12 22:48:26.000000000 +0300 +++ mga/mga_texstate.c 2003-07-12 22:51:08.000000000 +0300 @@ -52,6 +52,10 @@ [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_AL88] = TMC_tformat_tw8al | TMC_takey_1 | TMC_tamask_0, + [MESA_FORMAT_A8] = TMC_tformat_tw8a | TMC_takey_1 | TMC_tamask_0, + [MESA_FORMAT_L8] = TMC_tformat_tw8a | TMC_takey_1 | TMC_tamask_0, + [MESA_FORMAT_I8] = TMC_tformat_tw8a | 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, @@ -81,6 +85,10 @@ 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_A8: txformat = TMC_tformat_tw8a; break; + case MESA_FORMAT_L8: txformat = TMC_tformat_tw8a; 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; diff -urN mga.orig/mgatex.c mga/mgatex.c --- mga.orig/mgatex.c 2003-07-12 22:48:26.000000000 +0300 +++ mga/mgatex.c 2003-07-12 22:50:11.000000000 +0300 @@ -219,7 +219,7 @@ case GL_ALPHA16: case GL_COMPRESSED_ALPHA: /* FIXME: This will report incorrect component sizes... */ - return &_mesa_texformat_argb4444; + return MGA_IS_G400(mmesa) ? &_mesa_texformat_a8 : &_mesa_texformat_argb4444; case 1: case GL_LUMINANCE: @@ -229,7 +229,7 @@ case GL_LUMINANCE16: case GL_COMPRESSED_LUMINANCE: /* FIXME: This will report incorrect component sizes... */ - return &_mesa_texformat_rgb565; + return MGA_IS_G400(mmesa) ? &_mesa_texformat_l8 : &_mesa_texformat_rgb565; case 2: case GL_LUMINANCE_ALPHA: @@ -241,7 +241,7 @@ case GL_LUMINANCE16_ALPHA16: case GL_COMPRESSED_LUMINANCE_ALPHA: /* FIXME: This will report incorrect component sizes... */ - return &_mesa_texformat_argb4444; + return MGA_IS_G400(mmesa) ? &_mesa_texformat_al88 : &_mesa_texformat_argb4444; case GL_INTENSITY: case GL_INTENSITY4: @@ -250,11 +250,12 @@ case GL_INTENSITY16: case GL_COMPRESSED_INTENSITY: /* FIXME: This will report incorrect component sizes... */ - return &_mesa_texformat_argb4444; + return MGA_IS_G400(mmesa) ? &_mesa_texformat_i8 : &_mesa_texformat_argb4444; case GL_YCBCR_MESA: - if (type == GL_UNSIGNED_SHORT_8_8_APPLE || - type == GL_UNSIGNED_BYTE) + if (MGA_IS_G400(mmesa) && + (type == GL_UNSIGNED_SHORT_8_8_APPLE || + type == GL_UNSIGNED_BYTE)) return &_mesa_texformat_ycbcr; else return &_mesa_texformat_ycbcr_rev;
diff -urN mga.orig/mgatex.c mga/mgatex.c --- mga.orig/mgatex.c 2003-07-12 22:40:08.000000000 +0300 +++ mga/mgatex.c 2003-07-12 22:41:03.000000000 +0300 @@ -47,7 +47,6 @@ /** * Set the texture wrap modes. - * Currently, only \c GL_REPEAT and \c GL_CLAMP are supported. * * \param t Texture object whose wrap modes are to be set * \param swrap Wrap mode for the \a s texture coordinate @@ -74,9 +73,6 @@ t->setup.texctl |= TMC_clampu_enable; is_clamp_to_edge = GL_TRUE; break; - case GL_CLAMP_TO_BORDER: - t->setup.texctl |= TMC_clampu_enable; - break; default: _mesa_problem(NULL, "bad S wrap mode in %s", __FUNCTION__); }