This patch implements these extensions: GL_ARB_texture_env_combine GL_EXT_texture_env_combine GL_ARB_texture_env_crossbar
G400 or better needed obviously. My older texenv stuff is included with a slight modification. Since I can't easily play with FCOL like I did before GL_BLEND has some more restricions. Now both Cc and Ac must be either 0.0 or 1.0. I could still add a Cc==Ac case which would work with other formats except GL_INTENSITY. Also I had to change GL_ALPHA and GL_LUMINANCE to use TW8AL format since TW8A behaves like GL_INTENSITY and now it's possible to specify SRC_ALPHA operand for GL_LUMINANCE and so on. I'm hoping Mesa will take care of fillning the unused component with 0.0 or 1.0... I made the mapping between OpenGL args and hw args flexible. This way it doesn't matter in which order the user specifies the arguments. Hw can't support dot3 stuff. Also RGB_SCALE and ALPHA_SCALE only work fully with GL_MODULATE. GL_REPLACE can't support this at all the others support only a value of 1. So far I've only tested with an emboss bumpmapping sample from ATI. Good news is that it looks ok :) It uses GL_MODULATE, GL_REPLACE and GL_ADD_SIGNED. Are there any other good tests I could try? PS. I use Mesa embedded-2-branch as my working copy so I made the changes to dri sources manually. Hopefully I got all of them... -- Ville Syrjälä [EMAIL PROTECTED] http://www.sci.fi/~syrjala/
Index: Imakefile.inc =================================================================== RCS file: /cvsroot/dri/xc/xc/lib/GL/mesa/src/drv/mga/Imakefile.inc,v retrieving revision 1.6 diff -u -r1.6 Imakefile.inc --- Imakefile.inc 30 Apr 2003 01:50:40 -0000 1.6 +++ Imakefile.inc 3 Aug 2003 16:07:23 -0000 @@ -43,6 +43,7 @@ $(MESADRVMGABUILDDIR)mgatex.c \ $(MESADRVMGABUILDDIR)mgatexmem.c \ $(MESADRVMGABUILDDIR)mga_texstate.c \ + $(MESADRVMGABUILDDIR)mga_texcombine.c \ $(MESADRVMGABUILDDIR)mgatris.c \ $(MESADRVMGABUILDDIR)mgavb.c \ $(MESADRVMGABUILDDIR)mga_xmesa.c \ @@ -56,6 +57,7 @@ $(MESADRVMGABUILDDIR)mgatex.o \ $(MESADRVMGABUILDDIR)mgatexmem.o \ $(MESADRVMGABUILDDIR)mga_texstate.o \ + $(MESADRVMGABUILDDIR)mga_texcombine.o \ $(MESADRVMGABUILDDIR)mgatris.o \ $(MESADRVMGABUILDDIR)mgavb.o \ $(MESADRVMGABUILDDIR)mga_xmesa.o @@ -69,6 +71,7 @@ $(MESADRVMGABUILDDIR)unshared/mgatex.o \ $(MESADRVMGABUILDDIR)unshared/mgatexmem.o \ $(MESADRVMGABUILDDIR)unshared/mga_texstate.o \ + $(MESADRVMGABUILDDIR)unshared/mga_texcombine.o \ $(MESADRVMGABUILDDIR)unshared/mgatris.o \ $(MESADRVMGABUILDDIR)unshared/mgavb.o \ $(MESADRVMGABUILDDIR)unshared/mga_xmesa.o @@ -82,6 +85,7 @@ $(MESADRVMGABUILDDIR)debugger/mgatex.o \ $(MESADRVMGABUILDDIR)debugger/mgatexmem.o \ $(MESADRVMGABUILDDIR)debugger/mga_texstate.o \ + $(MESADRVMGABUILDDIR)debugger/mga_texcombine.o \ $(MESADRVMGABUILDDIR)debugger/mgatris.o \ $(MESADRVMGABUILDDIR)debugger/mgavb.o \ $(MESADRVMGABUILDDIR)debugger/mga_xmesa.o @@ -95,6 +99,7 @@ $(MESADRVMGABUILDDIR)profiled/mgatex.o \ $(MESADRVMGABUILDDIR)profiled/mgatexmem.o \ $(MESADRVMGABUILDDIR)profiled/mga_texstate.o \ + $(MESADRVMGABUILDDIR)profiled/mga_texcombine.o \ $(MESADRVMGABUILDDIR)profiled/mgatris.o \ $(MESADRVMGABUILDDIR)profiled/mgavb.o \ $(MESADRVMGABUILDDIR)profiled/mga_xmesa.o @@ -109,6 +114,7 @@ LinkSourceFile(mgatex.c, $(MESADRVSRCDIR)/mga) LinkSourceFile(mgatexmem.c, $(MESADRVSRCDIR)/mga) LinkSourceFile(mga_texstate.c, $(MESADRVSRCDIR)/mga) +LinkSourceFile(mga_texcombine.c, $(MESADRVSRCDIR)/mga) LinkSourceFile(mgatris.c, $(MESADRVSRCDIR)/mga) LinkSourceFile(mgavb.c, $(MESADRVSRCDIR)/mga) LinkSourceFile(mga_xmesa.c, $(MESADRVSRCDIR)/mga) Index: mga_texstate.c =================================================================== RCS file: /cvsroot/dri/xc/xc/lib/GL/mesa/src/drv/mga/mga_texstate.c,v retrieving revision 1.9 diff -u -r1.9 mga_texstate.c --- mga_texstate.c 25 Jul 2003 00:24:53 -0000 1.9 +++ mga_texstate.c 3 Aug 2003 16:07:23 -0000 @@ -52,6 +52,8 @@ [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_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 +83,8 @@ 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; @@ -251,29 +255,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 | @@ -290,33 +425,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 | @@ -334,20 +489,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 | @@ -355,16 +515,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), }, @@ -377,21 +541,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 | @@ -399,16 +567,20 @@ 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), }, @@ -421,6 +593,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 ) @@ -428,136 +601,226 @@ 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. - */ - 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); + *reg = g400_alpha_combine[unit][MGA_BLEND]; + } else { + 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_ONE && + 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 + Cs + * Av = A1 + */ + *(reg+1) = (TD0_color_arg2_prevstage | + 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 + Cs + * Av = A1 + */ + *(reg+1) = (TD0_color_arg2_prevstage | + 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 + Cs + * Av = A1 + */ + *(reg+1) = (TD0_color_arg2_prevstage | + 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 + Cs + * Av = A1 + As + */ + *(reg+1) = (TD0_color_arg2_prevstage | + 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; + case GL_COMBINE_EXT: + 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 +836,7 @@ mmesa->CurrentTexObj[unit] = NULL; } - if ( unit != 0 ) { + if ( unit != 0 && !mmesa->dualtex_env ) { mmesa->setup.tdualstage1 = mmesa->setup.tdualstage0; } @@ -649,6 +912,14 @@ 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? */ @@ -680,13 +951,10 @@ mgaUpdateTextureEnvG200( ctx, unit ); } - - mmesa->setup.dwgctl &= DC_opcod_MASK; - 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; } @@ -718,6 +986,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 Index: mga_xmesa.c =================================================================== RCS file: /cvsroot/dri/xc/xc/lib/GL/mesa/src/drv/mga/mga_xmesa.c,v retrieving revision 1.54 diff -u -r1.54 mga_xmesa.c --- mga_xmesa.c 25 Jun 2003 17:13:46 -0000 1.54 +++ mga_xmesa.c 3 Aug 2003 16:07:25 -0000 @@ -259,6 +259,9 @@ "GL_ARB_multitexture", "GL_ARB_texture_env_add", "GL_EXT_texture_env_add", + "GL_ARB_texture_env_combine", + "GL_EXT_texture_env_combine", + "GL_ARB_texture_env_crossbar", "GL_EXT_texture_edge_clamp", "GL_SGIS_texture_edge_clamp", #if defined (MESA_packed_depth_stencil) Index: mgacontext.h =================================================================== RCS file: /cvsroot/dri/xc/xc/lib/GL/mesa/src/drv/mga/mgacontext.h,v retrieving revision 1.26 diff -u -r1.26 mgacontext.h --- mgacontext.h 22 Jul 2003 04:54:31 -0000 1.26 +++ mgacontext.h 3 Aug 2003 16:07:25 -0000 @@ -78,10 +78,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_ONE 0x2 +#define MGA_BLEND_ALPHA_ZERO 0x4 +#define MGA_BLEND_ALPHA_ONE 0x8 struct mga_texture_object_s; struct mga_screen_private_s; @@ -148,6 +150,10 @@ * to fallback for GL_CLAMP_TO_BORDER. */ GLboolean border_fallback; + /* Depending on multitxturing and environment color + * GL_BLEND may have to be a software fallback. + */ + GLboolean texenv_fallback; } mgaTextureObject_t; struct mga_hw_state { @@ -201,10 +207,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 */ Index: mgastate.c =================================================================== RCS file: /cvsroot/dri/xc/xc/lib/GL/mesa/src/drv/mga/mgastate.c,v retrieving revision 1.41 diff -u -r1.41 mgastate.c --- mgastate.c 23 Jul 2003 13:40:07 -0000 1.41 +++ mgastate.c 3 Aug 2003 16:07:26 -0000 @@ -1053,8 +1053,13 @@ sizeof(sarea->TexState[1])); } - if ( (sarea->TexState[0].texctl2 & TMC_borderen_MASK) != - (sarea->TexState[1].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]) ); + mmesa->dirty |= MGA_UPLOAD_TEX1|MGA_UPLOAD_TEX0; + } 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; memcpy( &sarea->TexState[1], &sarea->TexState[0], @@ -1229,6 +1234,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; } Index: mgatex.c =================================================================== RCS file: /cvsroot/dri/xc/xc/lib/GL/mesa/src/drv/mga/mgatex.c,v retrieving revision 1.49 diff -u -r1.49 mgatex.c --- mgatex.c 25 Jul 2003 07:42:21 -0000 1.49 +++ mgatex.c 3 Aug 2003 16:07:27 -0000 @@ -220,7 +220,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_al88 : &_mesa_texformat_argb4444; case 1: case GL_LUMINANCE: @@ -230,7 +230,8 @@ case GL_LUMINANCE16: case GL_COMPRESSED_LUMINANCE: /* FIXME: This will report incorrect component sizes... */ - return &_mesa_texformat_rgb565; + return + return MGA_IS_G400(mmesa) ? &_mesa_texformat_al88 : &_mesa_texformat_rgb565; case 2: case GL_LUMINANCE_ALPHA: @@ -242,7 +243,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: @@ -251,7 +252,7 @@ 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 (MGA_IS_G400(mmesa) && @@ -331,27 +332,28 @@ switch( pname ) { case GL_TEXTURE_ENV_COLOR: { GLubyte c[4]; - 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] ); - if (mmesa->setup.fcol != envColor) { + if (mmesa->setup.fcol != mmesa->envcolor) { FLUSH_BATCH(mmesa); - mmesa->setup.fcol = envColor; + mmesa->setup.fcol = mmesa->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) == 0xffffff) { + mmesa->blend_flags |= MGA_BLEND_RGB_ONE; + } + + 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; } Index: mgatex.h =================================================================== RCS file: /cvsroot/dri/xc/xc/lib/GL/mesa/src/drv/mga/mgatex.h,v retrieving revision 1.13 diff -u -r1.13 mgatex.h --- mgatex.h 30 Apr 2003 01:50:43 -0000 1.13 +++ mgatex.h 3 Aug 2003 16:07:27 -0000 @@ -46,4 +46,6 @@ void mgaDDInitTextureFuncs( GLcontext *ctx ); +GLboolean mgaUpdateTextureEnvCombine( GLcontext *ctx, int unit ); + #endif
#include "glheader.h" #include "imports.h" #include "colormac.h" #include "context.h" #include "enums.h" #include "macros.h" #include "mmath.h" #include "texformat.h" #include "mga_xmesa.h" #include "mgastate.h" #include "mgaioctl.h" #include "mgatex.h" #include "mgaregs.h" /* GL_EXT_texture_env_combine support */ #define ARG_DISABLE 0xffffffff #define MGA_ARG1 0 #define MGA_ARG2 1 #define MGA_ALPHA 2 GLboolean mgaUpdateTextureEnvCombine( 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]; GLuint *reg = ((GLuint *)&mmesa->setup.tdualstage0 + unit); GLuint numColorArgs = 0, numAlphaArgs = 0; GLuint arg1[3], arg2[3], alpha[3]; int args[3]; int i; switch (texUnit->CombineModeRGB) { case GL_REPLACE: numColorArgs = 1; break; case GL_MODULATE: case GL_ADD: case GL_ADD_SIGNED: case GL_SUBTRACT: numColorArgs = 2; break; case GL_INTERPOLATE: numColorArgs = 3; break; default: return GL_FALSE; } switch (texUnit->CombineModeA) { case GL_REPLACE: numAlphaArgs = 1; break; case GL_MODULATE: case GL_ADD: case GL_ADD_SIGNED: case GL_SUBTRACT: numAlphaArgs = 2; break; default: return GL_FALSE; } /* Start fresh :) */ *reg = 0; /* COLOR */ for (i = 0; i < 3; i++) { arg1[i] = 0; arg2[i] = 0; alpha[i] = 0; } for (i = 0;i < numColorArgs; i++) { switch (texUnit->CombineSourceRGB[i]) { case GL_TEXTURE: arg1[i] |= 0; arg2[i] |= ARG_DISABLE; alpha[i] |= TD0_color_alpha_currtex; break; case GL_TEXTURE0: if (source == 0) { arg1[i] |= 0; arg2[i] |= ARG_DISABLE; alpha[i] |= TD0_color_alpha_currtex; } else { if (ctx->Texture._EnabledUnits != 0x03) { /* disable texturing */ mmesa->setup.dwgctl &= DC_opcod_MASK; mmesa->setup.dwgctl |= DC_opcod_trap; mmesa->hw.alpha_sel = AC_alphasel_diffused; /* return GL_TRUE since we don't need a fallback */ return GL_TRUE; } arg1[i] |= ARG_DISABLE; arg2[i] |= ARG_DISABLE; alpha[i] |= TD0_color_alpha_prevtex; } break; case GL_TEXTURE1: if (source == 0) { if (ctx->Texture._EnabledUnits != 0x03) { /* disable texturing */ mmesa->setup.dwgctl &= DC_opcod_MASK; mmesa->setup.dwgctl |= DC_opcod_trap; mmesa->hw.alpha_sel = AC_alphasel_diffused; /* return GL_TRUE since we don't need a fallback */ return GL_TRUE; } arg1[i] |= ARG_DISABLE; /* G400 specs.(TDUALSTAGE0) */ arg2[i] |= TD0_color_arg2_prevstage; alpha[i] |= TD0_color_alpha_prevstage; } else { arg1[i] |= 0; arg2[i] |= ARG_DISABLE; alpha[i] |= TD0_color_alpha_currtex; } break; case GL_CONSTANT: arg1[i] |= ARG_DISABLE; arg2[i] |= TD0_color_arg2_fcol; alpha[i] |= TD0_color_alpha_fcol; break; case GL_PRIMARY_COLOR: arg1[i] |= ARG_DISABLE; /* G400 specs.(TDUALSTAGE1) */ if (unit == 0 || (mmesa->setup.tdualstage0 & ((TD0_color_sel_mul & TD0_color_sel_add) | (TD0_alpha_sel_mul & TD0_alpha_sel_add)))) { arg2[i] |= TD0_color_arg2_diffuse; alpha[i] |= TD0_color_alpha_diffuse; } else { arg2[i] |= ARG_DISABLE; alpha[i] |= ARG_DISABLE; } break; case GL_PREVIOUS: arg1[i] |= ARG_DISABLE; if (unit == 0) { arg2[i] |= TD0_color_arg2_diffuse; alpha[i] |= TD0_color_alpha_diffuse; } else { arg2[i] |= TD0_color_arg2_prevstage; alpha[i] |= TD0_color_alpha_prevstage; } break; } switch (texUnit->CombineOperandRGB[i]) { case GL_SRC_COLOR: arg1[i] |= 0; arg2[i] |= 0; alpha[i] |= ARG_DISABLE; break; case GL_ONE_MINUS_SRC_COLOR: arg1[i] |= TD0_color_arg1_inv_enable; arg2[i] |= TD0_color_arg2_inv_enable; alpha[i] |= ARG_DISABLE; break; case GL_SRC_ALPHA: arg1[i] |= TD0_color_arg1_replicatealpha_enable; arg2[i] |= TD0_color_arg2_replicatealpha_enable; alpha[i] |= 0; break; case GL_ONE_MINUS_SRC_ALPHA: arg1[i] |= (TD0_color_arg1_replicatealpha_enable | TD0_color_arg1_inv_enable); arg2[i] |= (TD0_color_arg2_replicatealpha_enable | TD0_color_arg2_inv_enable); alpha[i] |= (TD0_color_alpha1inv_enable | TD0_color_alpha2inv_enable); break; } } /* Find working combo of arg1, arg2 and alpha. * * Keep the Arg0 == alpha cases last since there's * no way to get alpha out by itself (GL_REPLACE). * * Keep the Arg2 == alpha cases first because only alpha has the * capabilities to function as Arg2 (GL_INTERPOLATE). * Also we can't get alpha to the adder so keep it away from Arg0 and Arg1 * for as long as possible (GL_ADD,GL_ADD_SIGNED,GL_SUBTRACT). */ if ((arg1[0] | arg2[1] | alpha[2]) != ARG_DISABLE) { *reg |= arg1[0] | arg2[1] | alpha[2]; args[0] = MGA_ARG1; args[1] = MGA_ARG2; args[2] = MGA_ALPHA; } else if ((arg1[1] | arg2[0] | alpha[2]) != ARG_DISABLE) { *reg |= arg1[1] | arg2[0] | alpha[2]; args[0] = MGA_ARG2; args[1] = MGA_ARG1; args[2] = MGA_ALPHA; } else if (!(arg1[0] | arg2[2] | alpha[1]) != ARG_DISABLE) { *reg |= arg1[0] | arg2[2] | alpha[1]; args[0] = MGA_ARG1; args[1] = MGA_ALPHA; args[2] = MGA_ARG2; } else if (!(arg1[2] | arg2[0] | alpha[1]) != ARG_DISABLE) { *reg |= arg1[2] | arg2[0] | alpha[1]; args[0] = MGA_ARG2; args[1] = MGA_ALPHA; args[2] = MGA_ARG1; } else if (!(arg1[1] | arg2[2] | alpha[0]) != ARG_DISABLE) { *reg |= arg1[1] | arg2[2] | alpha[0]; args[0] = MGA_ALPHA; args[1] = MGA_ARG1; args[2] = MGA_ARG2; } else if (!(arg1[2] | arg2[1] | alpha[0]) != ARG_DISABLE) { *reg |= arg1[2] | arg2[1] | alpha[0]; args[0] = MGA_ALPHA; args[1] = MGA_ARG2; args[2] = MGA_ARG1; } else { /* nothing suitable */ return GL_FALSE; } switch (texUnit->CombineModeRGB) { case GL_REPLACE: if (texUnit->CombineScaleShiftRGB) { return GL_FALSE; } if (args[0] == MGA_ARG1) { *reg |= TD0_color_sel_arg1; } else if (args[0] == MGA_ARG2) { *reg |= TD0_color_sel_arg2; } else if (args[0] == MGA_ALPHA) { /* Can't get alpha out by itself */ return GL_FALSE; } break; case GL_MODULATE: if (texUnit->CombineScaleShiftRGB == 1) { *reg |= TD0_color_modbright_2x; } else if (texUnit->CombineScaleShiftRGB == 2) { *reg |= TD0_color_modbright_4x; } *reg |= TD0_color_sel_mul; if (args[0] == MGA_ALPHA || args[1] == MGA_ALPHA) { if (args[0] == MGA_ARG1 || args[1] == MGA_ARG1) { *reg |= TD0_color_arg2mul_alpha2; } else if (args[0] == MGA_ARG2 || args[1] == MGA_ARG2) { *reg |= TD0_color_arg1mul_alpha1; } } break; case GL_ADD: if (args[0] == MGA_ALPHA || args[1] == MGA_ALPHA){ /* Can't get alpha to the adder */ return GL_FALSE; } if (texUnit->CombineScaleShiftRGB == 1) { *reg |= TD0_color_add2x_enable; } else if (texUnit->CombineScaleShiftRGB == 2) { return GL_FALSE; } *reg |= (TD0_color_add_add | TD0_color_sel_add); break; case GL_ADD_SIGNED: if (args[0] == MGA_ALPHA || args[1] == MGA_ALPHA){ /* Can't get alpha to the adder */ return GL_FALSE; } if (texUnit->CombineScaleShiftRGB == 1) { *reg |= TD0_color_add2x_enable; } else if (texUnit->CombineScaleShiftRGB == 2) { return GL_FALSE; } *reg |= (TD0_color_addbias_enable | TD0_color_add_add | TD0_color_sel_add); break; case GL_INTERPOLATE: if (args[2] != MGA_ALPHA) { /* Only alpha can function as Arg2 */ return GL_FALSE; } if (texUnit->CombineScaleShiftRGB == 1) { *reg |= TD0_color_add2x_enable; } else if (texUnit->CombineScaleShiftRGB == 2) { return GL_FALSE; } *reg |= (TD0_color_arg1mul_alpha1 | TD0_color_blend_enable | TD0_color_arg1add_mulout | TD0_color_arg2add_mulout | TD0_color_add_add | TD0_color_sel_add); /* Have to do this with xor since GL_ONE_MINUS_SRC_ALPHA may have * already touched these bits. */ *reg ^= TD0_color_alpha1inv_enable; if (args[0] == MGA_ARG2) { /* Swap arguments */ *reg ^= (TD0_color_arg1mul_alpha1 | TD0_color_arg2mul_alpha2 | TD0_color_alpha1inv_enable | TD0_color_alpha2inv_enable); } if (ctx->Texture._EnabledUnits != 0x03) { /* Linear blending mode needs dualtex enabled */ mmesa->dualtex_env = GL_TRUE; } break; case GL_SUBTRACT: if (args[0] == MGA_ALPHA || args[1] == MGA_ALPHA) { /* Can't get alpha to the adder */ return GL_FALSE; } if (texUnit->CombineScaleShiftRGB == 1) { *reg |= TD0_color_add2x_enable; } else if (texUnit->CombineScaleShiftRGB == 2) { return GL_FALSE; } *reg |= (TD0_color_add_sub | TD0_color_sel_add); if (args[0] == MGA_ARG2) { /* Swap arguments */ *reg ^= (TD0_color_arg1_inv_enable | TD0_color_arg2_inv_enable); } break; } /* ALPHA */ for (i = 0; i < 2; i++) { arg1[i] = 0; arg2[i] = 0; } for (i = 0; i < numAlphaArgs; i++) { switch (texUnit->CombineSourceA[i]) { case GL_TEXTURE: arg1[i] |= 0; arg2[i] |= ARG_DISABLE; break; case GL_TEXTURE0: if (source == 0) { arg1[i] |= 0; arg2[i] |= ARG_DISABLE; } else { if (ctx->Texture._EnabledUnits != 0x03) { /* disable texturing */ mmesa->setup.dwgctl &= DC_opcod_MASK; mmesa->setup.dwgctl |= DC_opcod_trap; mmesa->hw.alpha_sel = AC_alphasel_diffused; /* return GL_TRUE since we don't need a fallback */ return GL_TRUE; } arg1[i] |= ARG_DISABLE; arg2[i] |= TD0_alpha_arg2_prevtex; } break; case GL_TEXTURE1: if (source == 0) { if (ctx->Texture._EnabledUnits != 0x03) { /* disable texturing */ mmesa->setup.dwgctl &= DC_opcod_MASK; mmesa->setup.dwgctl |= DC_opcod_trap; mmesa->hw.alpha_sel = AC_alphasel_diffused; /* return GL_TRUE since we don't need a fallback */ return GL_TRUE; } arg1[i] |= ARG_DISABLE; /* G400 specs.(TDUALSTAGE0) */ arg2[i] |= TD0_alpha_arg2_prevstage; } else { arg1[i] |= 0; arg2[i] |= ARG_DISABLE; } break; case GL_CONSTANT: arg1[i] |= ARG_DISABLE; arg2[i] |= TD0_alpha_arg2_fcol; break; case GL_PRIMARY_COLOR: arg1[i] |= ARG_DISABLE; /* G400 specs.(TDUALSTAGE1) */ if (unit == 0 || (mmesa->setup.tdualstage0 & ((TD0_color_sel_mul & TD0_color_sel_add) | (TD0_alpha_sel_mul & TD0_alpha_sel_add)))) { arg2[i] |= TD0_alpha_arg2_diffuse; } else { arg2[i] |= ARG_DISABLE; } break; case GL_PREVIOUS: arg1[i] |= ARG_DISABLE; if (unit == 0) { arg2[i] |= TD0_alpha_arg2_diffuse; } else { arg2[i] |= TD0_alpha_arg2_prevstage; } break; } switch (texUnit->CombineOperandA[i]) { case GL_SRC_ALPHA: arg1[i] |= 0; arg2[i] |= 0; break; case GL_ONE_MINUS_SRC_ALPHA: arg1[i] |= TD0_alpha_arg1_inv_enable; arg2[i] |= TD0_alpha_arg2_inv_enable; break; } } /* Find a working combo of arg1 and arg2 */ if ((arg1[0] | arg2[1]) != ARG_DISABLE) { *reg |= arg1[0] | arg2[1]; args[0] = MGA_ARG1; args[1] = MGA_ARG2; } else if ((arg1[1] | arg2[0]) != ARG_DISABLE) { *reg |= arg1[1] | arg2[0]; args[0] = MGA_ARG2; args[1] = MGA_ARG1; } else { /* nothing suitable */ return GL_FALSE; } switch (texUnit->CombineModeA) { case GL_REPLACE: if (texUnit->CombineScaleShiftA) { return GL_FALSE; } if (args[0] == MGA_ARG1){ *reg |= TD0_alpha_sel_arg1; } else if (args[0] == MGA_ARG2) { *reg |= TD0_alpha_sel_arg2; } break; case GL_MODULATE: if (texUnit->CombineScaleShiftA == 1) { *reg |= TD0_alpha_modbright_2x; } else if (texUnit->CombineScaleShiftA == 2) { *reg |= TD0_alpha_modbright_4x; } *reg |= TD0_alpha_sel_mul; break; case GL_ADD: if (texUnit->CombineScaleShiftA == 1) { *reg |= TD0_alpha_add2x_enable; } else if (texUnit->CombineScaleShiftA == 2) { return GL_FALSE; } *reg |= (TD0_alpha_add_enable | TD0_alpha_sel_add); break; case GL_ADD_SIGNED: if (texUnit->CombineScaleShiftA == 1) { *reg |= TD0_alpha_add2x_enable; } else if (texUnit->CombineScaleShiftA == 2) { return GL_FALSE; } *reg |= (TD0_alpha_addbias_enable | TD0_alpha_add_enable | TD0_alpha_sel_add); break; case GL_INTERPOLATE: /* fallback */ return GL_FALSE; case GL_SUBTRACT: if (texUnit->CombineScaleShiftA == 1) { *reg |= TD0_alpha_add2x_enable; } else if (texUnit->CombineScaleShiftA == 2) { return GL_FALSE; } *reg |= (TD0_alpha_add_disable | TD0_alpha_sel_add); if (args[0] == MGA_ARG2) { /* Swap arguments */ *reg ^= (TD0_alpha_arg1_inv_enable | TD0_alpha_arg2_inv_enable); } break; } return GL_TRUE; }