Mesa (floating): mesa: respect color clamping in texenv programs (v2)

Luca Barbieri lb at kemper.freedesktop.org
Fri Aug 27 17:25:20 UTC 2010


Module: Mesa
Branch: floating
Commit: 5d40bdbbb3c5c5c5fe056435fe2baee25ac482fb
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=5d40bdbbb3c5c5c5fe056435fe2baee25ac482fb

Author: Luca Barbieri <luca at luca-barbieri.com>
Date:   Thu Aug 26 18:09:41 2010 +0200

mesa: respect color clamping in texenv programs (v2)

Changes in v2:
- Fix attributes other than vertex color sometimes getting clamped

---

 src/mesa/drivers/dri/i915/i915_fragprog.c |    2 +-
 src/mesa/drivers/dri/i965/brw_program.c   |    2 +-
 src/mesa/main/state.c                     |    2 +-
 src/mesa/main/texenvprogram.c             |   24 +++++++++++++--------
 src/mesa/program/arbprogparse.c           |    5 +++-
 src/mesa/program/prog_statevars.c         |   33 ++++++++++++++++++++++++++--
 src/mesa/program/prog_statevars.h         |    1 +
 src/mesa/program/programopt.c             |    5 ++-
 src/mesa/program/programopt.h             |    2 +-
 9 files changed, 57 insertions(+), 19 deletions(-)

diff --git a/src/mesa/drivers/dri/i915/i915_fragprog.c b/src/mesa/drivers/dri/i915/i915_fragprog.c
index 4a2e620..ea72752 100644
--- a/src/mesa/drivers/dri/i915/i915_fragprog.c
+++ b/src/mesa/drivers/dri/i915/i915_fragprog.c
@@ -1294,7 +1294,7 @@ i915ProgramStringNotify(GLcontext * ctx,
        */
       if (p->FragProg.FogOption) {
          /* add extra instructions to do fog, then turn off FogOption field */
-         _mesa_append_fog_code(ctx, &p->FragProg);
+         _mesa_append_fog_code(ctx, &p->FragProg, TRUE);
          p->FragProg.FogOption = GL_NONE;
       }
    }
diff --git a/src/mesa/drivers/dri/i965/brw_program.c b/src/mesa/drivers/dri/i965/brw_program.c
index 1cdc8c6..3dc0aff 100644
--- a/src/mesa/drivers/dri/i965/brw_program.c
+++ b/src/mesa/drivers/dri/i965/brw_program.c
@@ -134,7 +134,7 @@ static GLboolean brwProgramStringNotify( GLcontext *ctx,
          brw_fragment_program_const(brw->fragment_program);
 
       if (fprog->FogOption) {
-         _mesa_append_fog_code(ctx, fprog);
+         _mesa_append_fog_code(ctx, fprog, TRUE);
          fprog->FogOption = GL_NONE;
       }
 
diff --git a/src/mesa/main/state.c b/src/mesa/main/state.c
index b71d068..0cfb2bb 100644
--- a/src/mesa/main/state.c
+++ b/src/mesa/main/state.c
@@ -596,7 +596,7 @@ _mesa_update_state_locked( GLcontext *ctx )
    if (ctx->FragmentProgram._MaintainTexEnvProgram) {
       prog_flags |= (_NEW_BUFFERS | _NEW_TEXTURE | _NEW_FOG |
 		     _NEW_ARRAY | _NEW_LIGHT | _NEW_POINT | _NEW_RENDERMODE |
-		     _NEW_PROGRAM);
+		     _NEW_PROGRAM | _NEW_FRAG_CLAMP);
    }
    if (ctx->VertexProgram._MaintainTnlProgram) {
       prog_flags |= (_NEW_ARRAY | _NEW_TEXTURE | _NEW_TEXTURE_MATRIX |
diff --git a/src/mesa/main/texenvprogram.c b/src/mesa/main/texenvprogram.c
index 7f25bae..ea1fd6f 100644
--- a/src/mesa/main/texenvprogram.c
+++ b/src/mesa/main/texenvprogram.c
@@ -100,6 +100,9 @@ struct state_key {
    GLuint inputs_available:12;
    GLuint num_draw_buffers:4;
 
+   /* enabling clamping throughout the shader, see ClampFragmentColor */
+   GLuint clamp_color:1;
+
    /* NOTE: This array of structs must be last! (see "keySize" below) */
    struct {
       GLuint enabled:1;
@@ -491,6 +494,9 @@ static GLuint make_state_key( GLcontext *ctx,  struct state_key *key )
 
    key->inputs_available = (inputs_available & inputs_referenced);
 
+   /* _NEW_BUFFERS | _NEW_FRAG_CLAMP */
+   key->clamp_color = ctx->Color._ClampFragmentColor;
+
    /* compute size of state key, ignoring unused texture units */
    keySize = sizeof(*key) - sizeof(key->unit)
       + key->nr_enabled_units * sizeof(key->unit[0]);
@@ -722,7 +728,7 @@ static struct ureg register_input( struct texenv_fragment_program *p, GLuint inp
    }
    else {
       GLuint idx = frag_to_vert_attrib( input );
-      return register_param3( p, STATE_INTERNAL, STATE_CURRENT_ATTRIB, idx );
+      return register_param3( p, STATE_INTERNAL, STATE_CURRENT_ATTRIB_MAYBE_VP_CLAMPED, idx );
    }
 }
 
@@ -824,7 +830,7 @@ static struct ureg emit_texld( struct texenv_fragment_program *p,
 {
    struct prog_instruction *inst = emit_op( p, op, 
 					  dest, destmask, 
-					  GL_TRUE, /* ARB_texture_float requires saturation here */
+					  p->state->clamp_color, /* ARB_texture_float requires saturation here */
 					  coord, 	/* arg 0? */
 					  undef,
 					  undef);
@@ -1192,14 +1198,14 @@ emit_texenv(struct texenv_fragment_program *p, GLuint unit)
    if (rgb_shift)
       rgb_saturate = GL_FALSE;  /* saturate after rgb shift */
    else if (need_saturate(key->unit[unit].ModeRGB))
-      rgb_saturate = GL_TRUE;
+      rgb_saturate = key->clamp_color;
    else
       rgb_saturate = GL_FALSE;
 
    if (alpha_shift)
       alpha_saturate = GL_FALSE;  /* saturate after alpha shift */
    else if (need_saturate(key->unit[unit].ModeA))
-      alpha_saturate = GL_TRUE;
+      alpha_saturate = key->clamp_color;
    else
       alpha_saturate = GL_FALSE;
 
@@ -1254,7 +1260,7 @@ emit_texenv(struct texenv_fragment_program *p, GLuint unit)
     */
    if (alpha_shift || rgb_shift) {
       struct ureg shift;
-      GLboolean saturate = GL_TRUE;  /* always saturate at this point */
+      GLboolean saturate = key->clamp_color;  /* always saturate at this point */
 
       if (rgb_shift == alpha_shift) {
 	 shift = register_scalar_const(p, (GLfloat)(1<<rgb_shift));
@@ -1511,14 +1517,14 @@ create_new_program(GLcontext *ctx, struct state_key *key,
 	 /* Emit specular add.
 	  */
 	 struct ureg s = register_input(&p, FRAG_ATTRIB_COL1);
-	 emit_arith( &p, OPCODE_ADD, out, WRITEMASK_XYZ, 0, cf, s, undef );
-	 emit_arith( &p, OPCODE_MOV, out, WRITEMASK_W, 0, cf, undef, undef );
+	 emit_arith( &p, OPCODE_ADD, out, WRITEMASK_XYZ, key->clamp_color, cf, s, undef );
+	 emit_arith( &p, OPCODE_MOV, out, WRITEMASK_W, key->clamp_color, cf, undef, undef );
       }
       else if (memcmp(&cf, &out, sizeof(cf)) != 0) {
 	 /* Will wind up in here if no texture enabled or a couple of
 	  * other scenarios (GL_REPLACE for instance).
 	  */
-	 emit_arith( &p, OPCODE_MOV, out, WRITEMASK_XYZW, 0, cf, undef, undef );
+	 emit_arith( &p, OPCODE_MOV, out, WRITEMASK_XYZW, key->clamp_color, cf, undef, undef );
       }
    }
    /* Finish up:
@@ -1559,7 +1565,7 @@ create_new_program(GLcontext *ctx, struct state_key *key,
                            p.program->Base.NumInstructions);
 
    if (p.program->FogOption) {
-      _mesa_append_fog_code(ctx, p.program);
+      _mesa_append_fog_code(ctx, p.program, key->clamp_color);
       p.program->FogOption = GL_NONE;
    }
 
diff --git a/src/mesa/program/arbprogparse.c b/src/mesa/program/arbprogparse.c
index f834aaf..2c67b29 100644
--- a/src/mesa/program/arbprogparse.c
+++ b/src/mesa/program/arbprogparse.c
@@ -144,7 +144,10 @@ _mesa_parse_arb_fragment_program(GLcontext* ctx, GLenum target,
     * from the fragment shader.
     */
    if (program->FogOption != GL_NONE) {
-      _mesa_append_fog_code(ctx, program);
+      /* XXX: we should somehow recompile this to remove clamping if disabled
+       * On the ATI driver, this is unclampled if fragment clamping is disabled
+       */
+      _mesa_append_fog_code(ctx, program, GL_TRUE);
       program->FogOption = GL_NONE;
    }
 
diff --git a/src/mesa/program/prog_statevars.c b/src/mesa/program/prog_statevars.c
index ead3ece..b3ad847 100644
--- a/src/mesa/program/prog_statevars.c
+++ b/src/mesa/program/prog_statevars.c
@@ -237,11 +237,17 @@ _mesa_fetch_state(GLcontext *ctx, const gl_state_index state[],
       {
          /* state[1] is the texture unit */
          const GLuint unit = (GLuint) state[1];
-         COPY_4V(value, ctx->Texture.Unit[unit].EnvColor);
+         if(ctx->Color._ClampFragmentColor)
+            COPY_4V(value, ctx->Texture.Unit[unit].EnvColor);
+         else
+            COPY_4V(value, ctx->Texture.Unit[unit].EnvColorUnclamped);
       }
       return;
    case STATE_FOG_COLOR:
-      COPY_4V(value, ctx->Fog.Color);
+      if(ctx->Color._ClampFragmentColor)
+         COPY_4V(value, ctx->Fog.Color);
+      else
+         COPY_4V(value, ctx->Fog.ColorUnclamped);
       return;
    case STATE_FOG_PARAMS:
       value[0] = ctx->Fog.Density;
@@ -403,6 +409,23 @@ _mesa_fetch_state(GLcontext *ctx, const gl_state_index state[],
          }
          return;
 
+      case STATE_CURRENT_ATTRIB_MAYBE_VP_CLAMPED:
+         {
+            const GLuint idx = (GLuint) state[2];
+            if(ctx->Light._ClampVertexColor
+                  && (ctx->Current.Attrib == VERT_ATTRIB_COLOR0
+                        || ctx->Current.Attrib == VERT_ATTRIB_COLOR0))
+            {
+               value[0] = CLAMP(ctx->Current.Attrib[idx][0], 0.0f, 1.0f);
+               value[1] = CLAMP(ctx->Current.Attrib[idx][1], 0.0f, 1.0f);
+               value[2] = CLAMP(ctx->Current.Attrib[idx][2], 0.0f, 1.0f);
+               value[3] = CLAMP(ctx->Current.Attrib[idx][3], 0.0f, 1.0f);
+            }
+            else
+               COPY_4V(value, ctx->Current.Attrib[idx]);
+         }
+         return;
+
       case STATE_NORMAL_SCALE:
          ASSIGN_4V(value, 
                    ctx->_ModelViewInvScale, 
@@ -643,10 +666,12 @@ _mesa_program_state_flags(const gl_state_index state[STATE_LENGTH])
       return _NEW_LIGHT;
 
    case STATE_TEXGEN:
-   case STATE_TEXENV_COLOR:
       return _NEW_TEXTURE;
+   case STATE_TEXENV_COLOR:
+      return _NEW_TEXTURE | _NEW_BUFFERS | _NEW_FRAG_CLAMP;
 
    case STATE_FOG_COLOR:
+      return _NEW_FOG | _NEW_BUFFERS | _NEW_FRAG_CLAMP;
    case STATE_FOG_PARAMS:
       return _NEW_FOG;
 
@@ -684,6 +709,8 @@ _mesa_program_state_flags(const gl_state_index state[STATE_LENGTH])
       switch (state[1]) {
       case STATE_CURRENT_ATTRIB:
          return _NEW_CURRENT_ATTRIB;
+      case STATE_CURRENT_ATTRIB_MAYBE_VP_CLAMPED:
+         return _NEW_CURRENT_ATTRIB | _NEW_LIGHT | _NEW_BUFFERS;
 
       case STATE_NORMAL_SCALE:
          return _NEW_MODELVIEW;
diff --git a/src/mesa/program/prog_statevars.h b/src/mesa/program/prog_statevars.h
index 1753471..c0fe54e 100644
--- a/src/mesa/program/prog_statevars.h
+++ b/src/mesa/program/prog_statevars.h
@@ -105,6 +105,7 @@ typedef enum gl_state_index_ {
 
    STATE_INTERNAL,		/* Mesa additions */
    STATE_CURRENT_ATTRIB,        /* ctx->Current vertex attrib value */
+   STATE_CURRENT_ATTRIB_MAYBE_VP_CLAMPED,        /* ctx->Current vertex attrib value after passthrough vertex processing */
    STATE_NORMAL_SCALE,
    STATE_TEXRECT_SCALE,
    STATE_FOG_PARAMS_OPTIMIZED,  /* for faster fog calc */
diff --git a/src/mesa/program/programopt.c b/src/mesa/program/programopt.c
index fb2ebe6..8f7e7dc 100644
--- a/src/mesa/program/programopt.c
+++ b/src/mesa/program/programopt.c
@@ -238,7 +238,7 @@ _mesa_insert_mvp_code(GLcontext *ctx, struct gl_vertex_program *vprog)
  * to vertex programs too.
  */
 void
-_mesa_append_fog_code(GLcontext *ctx, struct gl_fragment_program *fprog)
+_mesa_append_fog_code(GLcontext *ctx, struct gl_fragment_program *fprog, GLboolean saturate)
 {
    static const gl_state_index fogPStateOpt[STATE_LENGTH]
       = { STATE_INTERNAL, STATE_FOG_PARAMS_OPTIMIZED, 0, 0, 0 };
@@ -290,7 +290,7 @@ _mesa_append_fog_code(GLcontext *ctx, struct gl_fragment_program *fprog)
          /* change the instruction to write to colorTemp w/ clamping */
          inst->DstReg.File = PROGRAM_TEMPORARY;
          inst->DstReg.Index = colorTemp;
-         inst->SaturateMode = SATURATE_ZERO_ONE;
+         inst->SaturateMode = saturate;
          /* don't break (may be several writes to result.color) */
       }
       inst++;
@@ -300,6 +300,7 @@ _mesa_append_fog_code(GLcontext *ctx, struct gl_fragment_program *fprog)
    _mesa_init_instructions(inst, 5);
 
    /* emit instructions to compute fog blending factor */
+   /* this is always clamped to [0, 1] regardless of fragment clamping */
    if (fprog->FogOption == GL_LINEAR) {
       /* MAD fogFactorTemp.x, fragment.fogcoord.x, fogPRefOpt.x, fogPRefOpt.y; */
       inst->Opcode = OPCODE_MAD;
diff --git a/src/mesa/program/programopt.h b/src/mesa/program/programopt.h
index 4af6357..78906da 100644
--- a/src/mesa/program/programopt.h
+++ b/src/mesa/program/programopt.h
@@ -32,7 +32,7 @@ extern void
 _mesa_insert_mvp_code(GLcontext *ctx, struct gl_vertex_program *vprog);
 
 extern void
-_mesa_append_fog_code(GLcontext *ctx, struct gl_fragment_program *fprog);
+_mesa_append_fog_code(GLcontext *ctx, struct gl_fragment_program *fprog, GLboolean saturate);
 
 extern void
 _mesa_count_texture_indirections(struct gl_program *prog);




More information about the mesa-commit mailing list