r300: Implement ARB_shadow_ambient; add STATE_SHADOW_AMBIENT
diff --git a/src/mesa/drivers/dri/r300/r300_context.c b/src/mesa/drivers/dri/r300/r300_context.c
index a9c581b..fcf571d 100644
--- a/src/mesa/drivers/dri/r300/r300_context.c
+++ b/src/mesa/drivers/dri/r300/r300_context.c
@@ -101,6 +101,7 @@
   {"GL_ARB_multitexture",		NULL},
   {"GL_ARB_point_parameters",		GL_ARB_point_parameters_functions},
   {"GL_ARB_shadow",			NULL},
+  {"GL_ARB_shadow_ambient",		NULL},
   {"GL_ARB_texture_border_clamp",	NULL},
   {"GL_ARB_texture_compression",	GL_ARB_texture_compression_functions},
   {"GL_ARB_texture_cube_map",		NULL},
diff --git a/src/mesa/drivers/dri/r300/r300_fragprog.c b/src/mesa/drivers/dri/r300/r300_fragprog.c
index d390de5..453dda7 100644
--- a/src/mesa/drivers/dri/r300/r300_fragprog.c
+++ b/src/mesa/drivers/dri/r300/r300_fragprog.c
@@ -58,6 +58,20 @@
 	reg->Swizzle = SWIZZLE_NOOP;
 }
 
+static struct prog_src_register shadow_ambient(struct gl_program *program, int tmu)
+{
+	gl_state_index fail_value_tokens[STATE_LENGTH] = {
+		STATE_INTERNAL, STATE_SHADOW_AMBIENT, 0, 0, 0
+	};
+	struct prog_src_register reg = { 0, };
+
+	fail_value_tokens[2] = tmu;
+	reg.File = PROGRAM_STATE_VAR;
+	reg.Index = _mesa_add_state_reference(program->Parameters, fail_value_tokens);
+	reg.Swizzle = SWIZZLE_WWWW;
+	return reg;
+}
+
 /**
  * Transform TEX, TXP, TXB, and KIL instructions in the following way:
  *  - premultiply texture coordinates for RECT
@@ -92,8 +106,12 @@
 
 			tgt->Opcode = OPCODE_MOV;
 			tgt->DstReg = inst.DstReg;
-			tgt->SrcReg[0].File = PROGRAM_BUILTIN;
-			tgt->SrcReg[0].Swizzle = comparefunc == GL_ALWAYS ? SWIZZLE_1111 : SWIZZLE_0000;
+			if (comparefunc == GL_ALWAYS) {
+				tgt->SrcReg[0].File = PROGRAM_BUILTIN;
+				tgt->SrcReg[0].Swizzle = SWIZZLE_1111;
+			} else {
+				tgt->SrcReg[0] = shadow_ambient(t->Program, inst.TexSrcUnit);
+			}
 			return GL_TRUE;
 		}
 
@@ -153,6 +171,7 @@
 		GLuint comparefunc = GL_NEVER + compiler->fp->state.unit[inst.TexSrcUnit].texture_compare_func;
 		GLuint depthmode = compiler->fp->state.unit[inst.TexSrcUnit].depth_texture_mode;
 		int rcptemp = radeonFindFreeTemporary(t);
+		int pass, fail;
 
 		tgt = radeonAppendInstructions(t->Program, 3);
 
@@ -190,16 +209,18 @@
 		tgt[2].DstReg = orig_inst->DstReg;
 		tgt[2].SrcReg[0].File = PROGRAM_TEMPORARY;
 		tgt[2].SrcReg[0].Index = tgt[1].DstReg.Index;
-		tgt[2].SrcReg[1].File = PROGRAM_BUILTIN;
-		tgt[2].SrcReg[2].File = PROGRAM_BUILTIN;
 
 		if (comparefunc == GL_LESS || comparefunc == GL_GREATER) {
-			tgt[2].SrcReg[1].Swizzle = SWIZZLE_1111;
-			tgt[2].SrcReg[2].Swizzle = SWIZZLE_0000;
+			pass = 1;
+			fail = 2;
 		} else {
-			tgt[2].SrcReg[1].Swizzle = SWIZZLE_0000;
-			tgt[2].SrcReg[2].Swizzle = SWIZZLE_1111;
+			pass = 2;
+			fail = 1;
 		}
+
+		tgt[2].SrcReg[pass].File = PROGRAM_BUILTIN;
+		tgt[2].SrcReg[pass].Swizzle = SWIZZLE_1111;
+		tgt[2].SrcReg[fail] = shadow_ambient(t->Program, inst.TexSrcUnit);
 	} else if (destredirect) {
 		tgt = radeonAppendInstructions(t->Program, 1);
 
diff --git a/src/mesa/drivers/dri/r300/r500_fragprog.c b/src/mesa/drivers/dri/r300/r500_fragprog.c
index 3fbdb30..a84ba13 100644
--- a/src/mesa/drivers/dri/r300/r500_fragprog.c
+++ b/src/mesa/drivers/dri/r300/r500_fragprog.c
@@ -31,6 +31,20 @@
 #include "radeon_program_alu.h"
 
 
+static struct prog_src_register shadow_ambient(struct gl_program *program, int tmu)
+{
+	gl_state_index fail_value_tokens[STATE_LENGTH] = {
+		STATE_INTERNAL, STATE_SHADOW_AMBIENT, 0, 0, 0
+	};
+	struct prog_src_register reg = { 0, };
+
+	fail_value_tokens[2] = tmu;
+	reg.File = PROGRAM_STATE_VAR;
+	reg.Index = _mesa_add_state_reference(program->Parameters, fail_value_tokens);
+	reg.Swizzle = SWIZZLE_WWWW;
+	return reg;
+}
+
 /**
  * Transform TEX, TXP, TXB, and KIL instructions in the following way:
  *  - premultiply texture coordinates for RECT
@@ -63,11 +77,13 @@
 			tgt = radeonAppendInstructions(t->Program, 1);
 
 			tgt->Opcode = OPCODE_MOV;
-			tgt->DstReg.File = inst.DstReg.File;
-			tgt->DstReg.Index = inst.DstReg.Index;
-			tgt->DstReg.WriteMask = inst.DstReg.WriteMask;
-			tgt->SrcReg[0].File = PROGRAM_BUILTIN;
-			tgt->SrcReg[0].Swizzle = comparefunc == GL_ALWAYS ? SWIZZLE_1111 : SWIZZLE_0000;
+			tgt->DstReg = inst.DstReg;
+			if (comparefunc == GL_ALWAYS) {
+				tgt->SrcReg[0].File = PROGRAM_BUILTIN;
+				tgt->SrcReg[0].Swizzle = SWIZZLE_1111;
+			} else {
+				tgt->SrcReg[0] = shadow_ambient(t->Program, inst.TexSrcUnit);
+			}
 			return GL_TRUE;
 		}
 
@@ -91,6 +107,7 @@
 		GLuint comparefunc = GL_NEVER + compiler->fp->state.unit[inst.TexSrcUnit].texture_compare_func;
 		GLuint depthmode = compiler->fp->state.unit[inst.TexSrcUnit].depth_texture_mode;
 		int rcptemp = radeonFindFreeTemporary(t);
+		int pass, fail;
 
 		tgt = radeonAppendInstructions(t->Program, 3);
 
@@ -128,16 +145,18 @@
 		tgt[2].DstReg = orig_inst->DstReg;
 		tgt[2].SrcReg[0].File = PROGRAM_TEMPORARY;
 		tgt[2].SrcReg[0].Index = tgt[1].DstReg.Index;
-		tgt[2].SrcReg[1].File = PROGRAM_BUILTIN;
-		tgt[2].SrcReg[2].File = PROGRAM_BUILTIN;
 
 		if (comparefunc == GL_LESS || comparefunc == GL_GREATER) {
-			tgt[2].SrcReg[1].Swizzle = SWIZZLE_1111;
-			tgt[2].SrcReg[2].Swizzle = SWIZZLE_0000;
+			pass = 1;
+			fail = 2;
 		} else {
-			tgt[2].SrcReg[1].Swizzle = SWIZZLE_0000;
-			tgt[2].SrcReg[2].Swizzle = SWIZZLE_1111;
+			pass = 2;
+			fail = 1;
 		}
+
+		tgt[2].SrcReg[pass].File = PROGRAM_BUILTIN;
+		tgt[2].SrcReg[pass].Swizzle = SWIZZLE_1111;
+		tgt[2].SrcReg[fail] = shadow_ambient(t->Program, inst.TexSrcUnit);
 	} else if (destredirect) {
 		tgt = radeonAppendInstructions(t->Program, 1);
 
diff --git a/src/mesa/shader/prog_statevars.c b/src/mesa/shader/prog_statevars.c
index 539057b..e446e1c 100644
--- a/src/mesa/shader/prog_statevars.c
+++ b/src/mesa/shader/prog_statevars.c
@@ -132,7 +132,7 @@
 	       ADD_3V(value, p, eye_z);
 	       NORMALIZE_3FV(value);
 	       value[3] = 1.0;
-            }						  
+            }
             return;
 	 case STATE_POSITION_NORMALIZED:
             COPY_4V(value, ctx->Light.Light[ln].EyePosition);
@@ -240,11 +240,11 @@
          }
       }
    case STATE_TEXENV_COLOR:
-      {		
+      {
          /* state[1] is the texture unit */
          const GLuint unit = (GLuint) state[1];
          COPY_4V(value, ctx->Texture.Unit[unit].EnvColor);
-      }			
+      }
       return;
    case STATE_FOG_COLOR:
       COPY_4V(value, ctx->Fog.Color);
@@ -374,7 +374,7 @@
          }
       }
       return;
-		
+
    case STATE_VERTEX_PROGRAM:
       {
          /* state[1] = {STATE_ENV, STATE_LOCAL} */
@@ -458,6 +458,20 @@
       case STATE_PCM_BIAS:
          COPY_4V(value, ctx->Pixel.PostColorMatrixBias);
          break;
+      case STATE_SHADOW_AMBIENT:
+         {
+            const int unit = (int) state[2];
+            const struct gl_texture_object *texObj
+               = ctx->Texture.Unit[unit]._Current;
+            if (texObj) {
+               value[0] = texObj->ShadowAmbient;
+               value[1] = texObj->ShadowAmbient;
+               value[2] = texObj->ShadowAmbient;
+               value[3] = texObj->ShadowAmbient;
+            }
+         }
+         return;
+
       default:
          /* unknown state indexes are silently ignored
           *  should be handled by the driver.
@@ -532,6 +546,7 @@
    case STATE_INTERNAL:
       switch (state[1]) {
       case STATE_TEXRECT_SCALE:
+      case STATE_SHADOW_AMBIENT:
 	 return _NEW_TEXTURE;
       case STATE_FOG_PARAMS_OPTIMIZED:
 	 return _NEW_FOG;
@@ -711,6 +726,9 @@
    case STATE_PCM_BIAS:
       append(dst, "PCMbias");
       break;
+   case STATE_SHADOW_AMBIENT:
+      append(dst, "ShadowAmbient");
+      break;
    default:
       ;
    }
@@ -861,7 +879,7 @@
 
    for (i = 0; i < paramList->NumParameters; i++) {
       if (paramList->Parameters[i].Type == PROGRAM_STATE_VAR) {
-         _mesa_fetch_state(ctx, 
+         _mesa_fetch_state(ctx,
 			   (gl_state_index *) paramList->Parameters[i].StateIndexes,
                            paramList->ParameterValues[i]);
       }
diff --git a/src/mesa/shader/prog_statevars.h b/src/mesa/shader/prog_statevars.h
index 64820a5..da75ca7 100644
--- a/src/mesa/shader/prog_statevars.h
+++ b/src/mesa/shader/prog_statevars.h
@@ -77,7 +77,7 @@
    STATE_SPECULAR,
    STATE_EMISSION,
    STATE_SHININESS,
-   STATE_HALF_VECTOR,	
+   STATE_HALF_VECTOR,
 
    STATE_POSITION,
    STATE_ATTENUATION,
@@ -94,7 +94,7 @@
    STATE_TEXGEN_OBJECT_Q,
 
    STATE_TEXENV_COLOR,
-	
+
    STATE_DEPTH_RANGE,
 
    STATE_VERTEX_PROGRAM,
@@ -113,6 +113,7 @@
    STATE_PT_BIAS,               /**< Pixel transfer RGBA bias */
    STATE_PCM_SCALE,             /**< Post color matrix RGBA scale */
    STATE_PCM_BIAS,              /**< Post color matrix RGBA bias */
+   STATE_SHADOW_AMBIENT,        /**< ARB_shadow_ambient fail value; token[2] is texture unit index */
    STATE_INTERNAL_DRIVER	/* first available state index for drivers (must be last) */
 } gl_state_index;