st/glsl: support clamping color outputs in compat for gs/tes

This support requires the driver to be a NIR driver as we use the
NIR lowering pass to do the clamping.

Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
diff --git a/src/mesa/state_tracker/st_atom_shader.c b/src/mesa/state_tracker/st_atom_shader.c
index a4475e2..700239a 100644
--- a/src/mesa/state_tracker/st_atom_shader.c
+++ b/src/mesa/state_tracker/st_atom_shader.c
@@ -220,7 +220,25 @@
    if (st->shader_has_one_variant[prog->info.stage] && stp->variants)
       return stp->variants->driver_shader;
 
-   return st_get_basic_variant(st, pipe_shader, stp)->driver_shader;
+   struct st_basic_variant_key key;
+
+   /* use memset, not an initializer to be sure all memory is zeroed */
+   memset(&key, 0, sizeof(key));
+
+   key.st = st->has_shareable_shaders ? NULL : st;
+
+   if (pipe_shader == PIPE_SHADER_GEOMETRY ||
+       pipe_shader == PIPE_SHADER_TESS_EVAL) {
+      key.clamp_color = st->clamp_vert_color_in_shader &&
+                        st->ctx->Light._ClampVertexColor &&
+                        (stp->Base.info.outputs_written &
+                         (VARYING_SLOT_COL0 |
+                          VARYING_SLOT_COL1 |
+                          VARYING_SLOT_BFC0 |
+                          VARYING_SLOT_BFC1));
+   }
+
+   return st_get_basic_variant(st, pipe_shader, stp, &key)->driver_shader;
 }
 
 
diff --git a/src/mesa/state_tracker/st_context.c b/src/mesa/state_tracker/st_context.c
index 875be9d..e609623 100644
--- a/src/mesa/state_tracker/st_context.c
+++ b/src/mesa/state_tracker/st_context.c
@@ -238,8 +238,12 @@
       st->dirty |= ST_NEW_VERTEX_ARRAYS;
 
    /* Update the vertex shader if ctx->Light._ClampVertexColor was changed. */
-   if (st->clamp_vert_color_in_shader && (new_state & _NEW_LIGHT))
+   if (st->clamp_vert_color_in_shader && (new_state & _NEW_LIGHT)) {
       st->dirty |= ST_NEW_VS_STATE;
+      if (st->ctx->API == API_OPENGL_COMPAT && ctx->Version >= 32) {
+         st->dirty |= ST_NEW_GS_STATE | ST_NEW_TES_STATE;
+      }
+   }
 
    /* Which shaders are dirty will be determined manually. */
    if (new_state & _NEW_PROGRAM) {
@@ -701,8 +705,12 @@
          !st->force_persample_in_shader;
 
    st->shader_has_one_variant[MESA_SHADER_TESS_CTRL] = st->has_shareable_shaders;
-   st->shader_has_one_variant[MESA_SHADER_TESS_EVAL] = st->has_shareable_shaders;
-   st->shader_has_one_variant[MESA_SHADER_GEOMETRY] = st->has_shareable_shaders;
+   st->shader_has_one_variant[MESA_SHADER_TESS_EVAL] =
+         st->has_shareable_shaders &&
+         !st->clamp_vert_color_in_shader;
+   st->shader_has_one_variant[MESA_SHADER_GEOMETRY] =
+         st->has_shareable_shaders &&
+         !st->clamp_vert_color_in_shader;
    st->shader_has_one_variant[MESA_SHADER_COMPUTE] = st->has_shareable_shaders;
 
    st->bitmap.cache.empty = true;
diff --git a/src/mesa/state_tracker/st_program.c b/src/mesa/state_tracker/st_program.c
index 9f6e492..3c99721 100644
--- a/src/mesa/state_tracker/st_program.c
+++ b/src/mesa/state_tracker/st_program.c
@@ -1632,14 +1632,12 @@
 struct st_basic_variant *
 st_get_basic_variant(struct st_context *st,
                      unsigned pipe_shader,
-                     struct st_common_program *prog)
+                     struct st_common_program *prog,
+                     const struct st_basic_variant_key *key)
 {
    struct pipe_context *pipe = st->pipe;
    struct st_basic_variant *v;
-   struct st_basic_variant_key key;
    struct pipe_shader_state tgsi = {0};
-   memset(&key, 0, sizeof(key));
-   key.st = st->has_shareable_shaders ? NULL : st;
 
    /* Search for existing variant */
    for (v = prog->variants; v; v = v->next) {
@@ -1656,6 +1654,10 @@
 	 if (prog->tgsi.type == PIPE_SHADER_IR_NIR) {
 	    tgsi.type = PIPE_SHADER_IR_NIR;
 	    tgsi.ir.nir = nir_shader_clone(NULL, prog->tgsi.ir.nir);
+
+            if (key->clamp_color)
+               NIR_PASS_V(tgsi.ir.nir, nir_lower_clamp_color_outputs);
+
             tgsi.stream_output = prog->tgsi.stream_output;
 	 } else
 	    tgsi = prog->tgsi;
@@ -1676,7 +1678,7 @@
             return NULL;
          }
 
-         v->key = key;
+         v->key = *key;
 
          /* insert into list */
          v->next = prog->variants;
@@ -2058,19 +2060,34 @@
 
    case GL_TESS_CONTROL_PROGRAM_NV: {
       struct st_common_program *p = st_common_program(prog);
-      st_get_basic_variant(st, PIPE_SHADER_TESS_CTRL, p);
+      struct st_basic_variant_key key;
+
+      memset(&key, 0, sizeof(key));
+
+      key.st = st->has_shareable_shaders ? NULL : st;
+      st_get_basic_variant(st, PIPE_SHADER_TESS_CTRL, p, &key);
       break;
    }
 
    case GL_TESS_EVALUATION_PROGRAM_NV: {
       struct st_common_program *p = st_common_program(prog);
-      st_get_basic_variant(st, PIPE_SHADER_TESS_EVAL, p);
+      struct st_basic_variant_key key;
+
+      memset(&key, 0, sizeof(key));
+
+      key.st = st->has_shareable_shaders ? NULL : st;
+      st_get_basic_variant(st, PIPE_SHADER_TESS_EVAL, p, &key);
       break;
    }
 
    case GL_GEOMETRY_PROGRAM_NV: {
       struct st_common_program *p = st_common_program(prog);
-      st_get_basic_variant(st, PIPE_SHADER_GEOMETRY, p);
+      struct st_basic_variant_key key;
+
+      memset(&key, 0, sizeof(key));
+
+      key.st = st->has_shareable_shaders ? NULL : st;
+      st_get_basic_variant(st, PIPE_SHADER_GEOMETRY, p, &key);
       break;
    }
 
diff --git a/src/mesa/state_tracker/st_program.h b/src/mesa/state_tracker/st_program.h
index f67ea5e..59a6036 100644
--- a/src/mesa/state_tracker/st_program.h
+++ b/src/mesa/state_tracker/st_program.h
@@ -241,6 +241,9 @@
 struct st_basic_variant_key
 {
    struct st_context *st;          /**< variants are per-context */
+
+   /** For compat profile */
+   bool clamp_color;
 };
 
 
@@ -401,7 +404,8 @@
 extern struct st_basic_variant *
 st_get_basic_variant(struct st_context *st,
                      unsigned pipe_shader,
-                     struct st_common_program *p);
+                     struct st_common_program *p,
+                     const struct st_basic_variant_key *key);
 
 extern void
 st_release_vp_variants( struct st_context *st,