[Mesa-dev] [PATCH 1/6] mesa: implement clamping controls (ARB_color_buffer_float)

Marek Olšák maraeo at gmail.com
Sun Mar 20 18:12:30 PDT 2011


Squashed commit of the following:

Author: Marek Olšák <maraeo at gmail.com>

    mesa: fix getteximage so that it doesn't clamp values
    mesa: update the compute_version function
    mesa: add display list support for ARB_color_buffer_float
    mesa: fix glGet query with GL_ALPHA_TEST_REF and ARB_color_buffer_float

commit b2f6ddf907935b2594d2831ddab38cf57a1729ce
Author: Luca Barbieri <luca at luca-barbieri.com>
Date:   Tue Aug 31 16:50:57 2010 +0200

    mesa: document known possible deviations from ARB_color_buffer_float

commit 5458935be800c1b19d1c9d1569dc4fa30a97e8b8
Author: Luca Barbieri <luca at luca-barbieri.com>
Date:   Tue Aug 24 21:54:56 2010 +0200

    mesa: expose GL_ARB_color_buffer_float

commit aef5c3c6be6edd076e955e37c80905bc447f8a82
Author: Luca Barbieri <luca at luca-barbieri.com>
Date:   Thu Aug 26 18:12:34 2010 +0200

    mesa, mesa/st: handle read color clamping properly

    (I'll squash the st/mesa part to a separate commit. -Marek)

    We set IMAGE_CLAMP_BIT in the caller based on _ClampReadColor, where
    the operation mandates it.

    TODO: did I get the set of operations mandating it right?

commit 3a9cb5e59b676b6148c50907ce6eef5441677e36
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

commit de26f9e47e886e176aab6e5a2c3d4481efb64362
Author: Luca Barbieri <luca at luca-barbieri.com>
Date:   Thu Aug 26 18:05:53 2010 +0200

    mesa: restore color clamps on glPopAttrib

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

    mesa: clamp color queries if and only if fragment clamping is enabled

commit 9940a3e31c2fb76cc3d28b15ea78dde369825107
Author: Luca Barbieri <luca at luca-barbieri.com>
Date:   Wed Aug 25 00:00:16 2010 +0200

    mesa: introduce derived _ClampXxxColor state resolving FIXED_ONLY

    To do this, we make ClampColor call FLUSH_VERTICES with the appropriate
    _NEW flag.

    We introduce _NEW_FRAG_CLAMP since fragment clamping has wide-ranging
    effects, despite being in the Color attrib group.

    This may be easily changed by s/_NEW_FRAG_CLAMP/_NEW_COLOR/g

commit 6244c446e3beed5473b4e811d10787e4019f59d6
Author: Luca Barbieri <luca at luca-barbieri.com>
Date:   Thu Aug 26 17:58:24 2010 +0200

    mesa: add unclamped color parameters
---
 docs/ARB_color_buffer_float.txt               |    4 ++
 src/mapi/glapi/gen/ARB_color_buffer_float.xml |   25 ++++++++++++++
 src/mapi/glapi/gen/Makefile                   |    1 +
 src/mapi/glapi/gen/gl_API.xml                 |    1 +
 src/mesa/drivers/dri/i915/i915_fragprog.c     |    2 +-
 src/mesa/drivers/dri/i965/brw_program.c       |    2 +-
 src/mesa/main/api_exec.c                      |    2 +
 src/mesa/main/attrib.c                        |   21 +++++++-----
 src/mesa/main/blend.c                         |   37 +++++++++++++-------
 src/mesa/main/clear.c                         |   20 ++++++++---
 src/mesa/main/colortab.c                      |    7 +++-
 src/mesa/main/dlist.c                         |   27 +++++++++++++++
 src/mesa/main/extensions.c                    |    1 +
 src/mesa/main/ff_fragment_shader.cpp          |    4 +-
 src/mesa/main/fog.c                           |    5 +++
 src/mesa/main/get.c                           |   45 ++++++++++++++++++++++--
 src/mesa/main/mtypes.h                        |   20 ++++++++++-
 src/mesa/main/pack.c                          |   11 ------
 src/mesa/main/state.c                         |   40 +++++++++++++++++++++-
 src/mesa/main/texenv.c                        |   21 +++++++----
 src/mesa/main/texparam.c                      |   21 +++++++++--
 src/mesa/main/version.c                       |    2 +
 src/mesa/program/arbprogparse.c               |    5 ++-
 src/mesa/program/prog_statevars.c             |   32 ++++++++++++++++--
 src/mesa/program/prog_statevars.h             |    1 +
 src/mesa/program/programopt.c                 |    5 ++-
 src/mesa/program/programopt.h                 |    2 +-
 27 files changed, 294 insertions(+), 70 deletions(-)
 create mode 100644 docs/ARB_color_buffer_float.txt
 create mode 100644 src/mapi/glapi/gen/ARB_color_buffer_float.xml

diff --git a/docs/ARB_color_buffer_float.txt b/docs/ARB_color_buffer_float.txt
new file mode 100644
index 0000000..e501120
--- /dev/null
+++ b/docs/ARB_color_buffer_float.txt
@@ -0,0 +1,4 @@
+Known issues in the ARB_color_buffer_float implementation:
+- Rendering to multiple render targets, some fixed-point, some floating-point, with FIXED_ONLY fragment clamping and polygon smooth enabled may write incorrect values to the fixed point buffers (depends on spec interpretation)
+- For fragment programs with ARB_fog_* options, colors are clamped before fog application regardless of the fragment clamping setting (this depends on spec interpretation)
+
diff --git a/src/mapi/glapi/gen/ARB_color_buffer_float.xml b/src/mapi/glapi/gen/ARB_color_buffer_float.xml
new file mode 100644
index 0000000..7acf271
--- /dev/null
+++ b/src/mapi/glapi/gen/ARB_color_buffer_float.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0"?>
+<!DOCTYPE OpenGLAPI SYSTEM "gl_API.dtd">
+
+<!-- Note: no GLX protocol info yet. -->
+
+
+<OpenGLAPI>
+
+<category name="GL_ARB_color_buffer_float" number="39">
+
+  <enum name="RGBA_FLOAT_MODE_ARB"              value="0x8820"/>
+  <enum name="CLAMP_VERTEX_COLOR_ARB"           value="0x891A"/>
+  <enum name="CLAMP_FRAGMENT_COLOR_ARB"         value="0x891B"/>
+  <enum name="CLAMP_READ_COLOR_ARB"             value="0x891C"/>
+  <enum name="FIXED_ONLY_ARB"                   value="0x891D"/>
+
+  <function name="ClampColorARB" offset="assign">
+    <param name="target" type="GLenum"/>
+    <param name="clamp" type="GLenum"/>
+    <glx rop="234"/>
+  </function>
+
+</category>
+
+</OpenGLAPI>
diff --git a/src/mapi/glapi/gen/Makefile b/src/mapi/glapi/gen/Makefile
index 1f4642a..e1754b1 100644
--- a/src/mapi/glapi/gen/Makefile
+++ b/src/mapi/glapi/gen/Makefile
@@ -72,6 +72,7 @@ XORG_OUTPUTS = \
 
 API_XML = \
 	gl_API.xml \
+	ARB_color_buffer_float.xml \
 	ARB_copy_buffer.xml \
 	ARB_depth_clamp.xml \
 	ARB_draw_buffers_blend.xml \
diff --git a/src/mapi/glapi/gen/gl_API.xml b/src/mapi/glapi/gen/gl_API.xml
index 56c0ec7..cb20ac7 100644
--- a/src/mapi/glapi/gen/gl_API.xml
+++ b/src/mapi/glapi/gen/gl_API.xml
@@ -7979,6 +7979,7 @@
 
 <xi:include href="ARB_geometry_shader4.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
 
+<xi:include href="ARB_color_buffer_float.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
 
 <!-- Non-ARB extensions sorted by extension number. -->
 
diff --git a/src/mesa/drivers/dri/i915/i915_fragprog.c b/src/mesa/drivers/dri/i915/i915_fragprog.c
index 2bfe665..89de2a8 100644
--- a/src/mesa/drivers/dri/i915/i915_fragprog.c
+++ b/src/mesa/drivers/dri/i915/i915_fragprog.c
@@ -1291,7 +1291,7 @@ i915ProgramStringNotify(struct gl_context * 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 ee68095..2132b82 100644
--- a/src/mesa/drivers/dri/i965/brw_program.c
+++ b/src/mesa/drivers/dri/i965/brw_program.c
@@ -135,7 +135,7 @@ static GLboolean brwProgramStringNotify( struct gl_context *ctx,
       struct gl_shader_program *shader_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/api_exec.c b/src/mesa/main/api_exec.c
index 4da4893..f760370 100644
--- a/src/mesa/main/api_exec.c
+++ b/src/mesa/main/api_exec.c
@@ -691,6 +691,8 @@ _mesa_create_exec_table(void)
    SET_FramebufferTextureFaceARB(exec, _mesa_FramebufferTextureFaceARB);
 #endif
 
+   SET_ClampColorARB(exec, _mesa_ClampColorARB);
+
    /* GL_EXT_texture_integer */
    SET_ClearColorIiEXT(exec, _mesa_ClearColorIiEXT);
    SET_ClearColorIuiEXT(exec, _mesa_ClearColorIuiEXT);
diff --git a/src/mesa/main/attrib.c b/src/mesa/main/attrib.c
index ae7f633..340c06c 100644
--- a/src/mesa/main/attrib.c
+++ b/src/mesa/main/attrib.c
@@ -879,10 +879,10 @@ _mesa_PopAttrib(void)
 
                color = (const struct gl_colorbuffer_attrib *) attr->data;
                _mesa_ClearIndex((GLfloat) color->ClearIndex);
-               _mesa_ClearColor(color->ClearColor[0],
-                                color->ClearColor[1],
-                                color->ClearColor[2],
-                                color->ClearColor[3]);
+               _mesa_ClearColor(color->ClearColorUnclamped[0],
+                                color->ClearColorUnclamped[1],
+                                color->ClearColorUnclamped[2],
+                                color->ClearColorUnclamped[3]);
                _mesa_IndexMask(color->IndexMask);
                if (!ctx->Extensions.EXT_draw_buffers2) {
                   _mesa_ColorMask((GLboolean) (color->ColorMask[0][0] != 0),
@@ -930,7 +930,7 @@ _mesa_PopAttrib(void)
                      _mesa_DrawBuffer(color->DrawBuffer[0]);
                }
                _mesa_set_enable(ctx, GL_ALPHA_TEST, color->AlphaEnabled);
-               _mesa_AlphaFunc(color->AlphaFunc, color->AlphaRef);
+               _mesa_AlphaFunc(color->AlphaFunc, color->AlphaRefUnclamped);
                if (ctx->Color.BlendEnabled != color->BlendEnabled) {
                   if (ctx->Extensions.EXT_draw_buffers2) {
                      GLuint i;
@@ -976,16 +976,18 @@ _mesa_PopAttrib(void)
                                                  color->Blend[0].EquationA);
                   }
                }
-               _mesa_BlendColor(color->BlendColor[0],
-                                color->BlendColor[1],
-                                color->BlendColor[2],
-                                color->BlendColor[3]);
+               _mesa_BlendColor(color->BlendColorUnclamped[0],
+                                color->BlendColorUnclamped[1],
+                                color->BlendColorUnclamped[2],
+                                color->BlendColorUnclamped[3]);
                _mesa_LogicOp(color->LogicOp);
                _mesa_set_enable(ctx, GL_COLOR_LOGIC_OP,
                                 color->ColorLogicOpEnabled);
                _mesa_set_enable(ctx, GL_INDEX_LOGIC_OP,
                                 color->IndexLogicOpEnabled);
                _mesa_set_enable(ctx, GL_DITHER, color->DitherFlag);
+               _mesa_ClampColorARB(GL_CLAMP_FRAGMENT_COLOR_ARB, color->ClampFragmentColor);
+               _mesa_ClampColorARB(GL_CLAMP_READ_COLOR_ARB, color->ClampReadColor);
             }
             break;
          case GL_CURRENT_BIT:
@@ -1108,6 +1110,7 @@ _mesa_PopAttrib(void)
                /* materials */
                memcpy(&ctx->Light.Material, &light->Material,
                       sizeof(struct gl_material));
+               _mesa_ClampColorARB(GL_CLAMP_VERTEX_COLOR_ARB, light->ClampVertexColor);
             }
             break;
          case GL_LINE_BIT:
diff --git a/src/mesa/main/blend.c b/src/mesa/main/blend.c
index c74a168..95c101c 100644
--- a/src/mesa/main/blend.c
+++ b/src/mesa/main/blend.c
@@ -513,19 +513,24 @@ _mesa_BlendColor( GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha )
    GET_CURRENT_CONTEXT(ctx);
    ASSERT_OUTSIDE_BEGIN_END(ctx);
 
-   tmp[0] = CLAMP( red,   0.0F, 1.0F );
-   tmp[1] = CLAMP( green, 0.0F, 1.0F );
-   tmp[2] = CLAMP( blue,  0.0F, 1.0F );
-   tmp[3] = CLAMP( alpha, 0.0F, 1.0F );
+   tmp[0] = red;
+   tmp[1] = green;
+   tmp[2] = blue;
+   tmp[3] = alpha;
 
-   if (TEST_EQ_4V(tmp, ctx->Color.BlendColor))
+   if (TEST_EQ_4V(tmp, ctx->Color.BlendColorUnclamped))
       return;
 
    FLUSH_VERTICES(ctx, _NEW_COLOR);
-   COPY_4FV( ctx->Color.BlendColor, tmp );
+   COPY_4FV( ctx->Color.BlendColorUnclamped, tmp );
+
+   ctx->Color.BlendColor[0] = CLAMP(tmp[0], 0.0F, 1.0F);
+   ctx->Color.BlendColor[1] = CLAMP(tmp[1], 0.0F, 1.0F);
+   ctx->Color.BlendColor[2] = CLAMP(tmp[2], 0.0F, 1.0F);
+   ctx->Color.BlendColor[3] = CLAMP(tmp[3], 0.0F, 1.0F);
 
    if (ctx->Driver.BlendColor)
-      (*ctx->Driver.BlendColor)(ctx, tmp);
+      (*ctx->Driver.BlendColor)(ctx, ctx->Color.BlendColor);
 }
 
 
@@ -558,17 +563,16 @@ _mesa_AlphaFunc( GLenum func, GLclampf ref )
    case GL_NOTEQUAL:
    case GL_GEQUAL:
    case GL_ALWAYS:
-      ref = CLAMP(ref, 0.0F, 1.0F);
-
-      if (ctx->Color.AlphaFunc == func && ctx->Color.AlphaRef == ref)
+      if (ctx->Color.AlphaFunc == func && ctx->Color.AlphaRefUnclamped == ref)
          return; /* no change */
 
       FLUSH_VERTICES(ctx, _NEW_COLOR);
       ctx->Color.AlphaFunc = func;
-      ctx->Color.AlphaRef = ref;
+      ctx->Color.AlphaRefUnclamped = ref;
+      ctx->Color.AlphaRef = CLAMP(ref, 0.0F, 1.0F);
 
       if (ctx->Driver.AlphaFunc)
-         ctx->Driver.AlphaFunc(ctx, func, ref);
+         ctx->Driver.AlphaFunc(ctx, func, ctx->Color.AlphaRef);
       return;
 
    default:
@@ -737,7 +741,7 @@ _mesa_ColorMaskIndexed( GLuint buf, GLboolean red, GLboolean green,
 }
 
 
-extern void GLAPIENTRY
+void GLAPIENTRY
 _mesa_ClampColorARB(GLenum target, GLenum clamp)
 {
    GET_CURRENT_CONTEXT(ctx);
@@ -751,12 +755,15 @@ _mesa_ClampColorARB(GLenum target, GLenum clamp)
 
    switch (target) {
    case GL_CLAMP_VERTEX_COLOR_ARB:
+      FLUSH_VERTICES(ctx, _NEW_LIGHT);
       ctx->Light.ClampVertexColor = clamp;
       break;
    case GL_CLAMP_FRAGMENT_COLOR_ARB:
+      FLUSH_VERTICES(ctx, _NEW_FRAG_CLAMP);
       ctx->Color.ClampFragmentColor = clamp;
       break;
    case GL_CLAMP_READ_COLOR_ARB:
+      FLUSH_VERTICES(ctx, _NEW_COLOR);
       ctx->Color.ClampReadColor = clamp;
       break;
    default:
@@ -789,6 +796,7 @@ void _mesa_init_color( struct gl_context * ctx )
    memset(ctx->Color.ColorMask, 0xff, sizeof(ctx->Color.ColorMask));
    ctx->Color.ClearIndex = 0;
    ASSIGN_4V( ctx->Color.ClearColor, 0, 0, 0, 0 );
+   ASSIGN_4V( ctx->Color.ClearColorUnclamped, 0, 0, 0, 0 );
    ctx->Color.AlphaEnabled = GL_FALSE;
    ctx->Color.AlphaFunc = GL_ALWAYS;
    ctx->Color.AlphaRef = 0;
@@ -802,6 +810,7 @@ void _mesa_init_color( struct gl_context * ctx )
       ctx->Color.Blend[i].EquationA = GL_FUNC_ADD;
    }
    ASSIGN_4V( ctx->Color.BlendColor, 0.0, 0.0, 0.0, 0.0 );
+   ASSIGN_4V( ctx->Color.BlendColorUnclamped, 0.0, 0.0, 0.0, 0.0 );
    ctx->Color.IndexLogicOpEnabled = GL_FALSE;
    ctx->Color.ColorLogicOpEnabled = GL_FALSE;
    ctx->Color._LogicOpEnabled = GL_FALSE;
@@ -816,7 +825,9 @@ void _mesa_init_color( struct gl_context * ctx )
    }
 
    ctx->Color.ClampFragmentColor = GL_FIXED_ONLY_ARB;
+   ctx->Color._ClampFragmentColor = GL_TRUE;
    ctx->Color.ClampReadColor = GL_FIXED_ONLY_ARB;
+   ctx->Color._ClampReadColor = GL_TRUE;
 }
 
 /*@}*/
diff --git a/src/mesa/main/clear.c b/src/mesa/main/clear.c
index 43a9ccc..fa95e45 100644
--- a/src/mesa/main/clear.c
+++ b/src/mesa/main/clear.c
@@ -78,19 +78,27 @@ _mesa_ClearColor( GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha )
    GET_CURRENT_CONTEXT(ctx);
    ASSERT_OUTSIDE_BEGIN_END(ctx);
 
-   tmp[0] = CLAMP(red,   0.0F, 1.0F);
-   tmp[1] = CLAMP(green, 0.0F, 1.0F);
-   tmp[2] = CLAMP(blue,  0.0F, 1.0F);
-   tmp[3] = CLAMP(alpha, 0.0F, 1.0F);
+   tmp[0] = red;
+   tmp[1] = green;
+   tmp[2] = blue;
+   tmp[3] = alpha;
 
-   if (TEST_EQ_4V(tmp, ctx->Color.ClearColor))
+   if (TEST_EQ_4V(tmp, ctx->Color.ClearColorUnclamped))
       return; /* no change */
 
    FLUSH_VERTICES(ctx, _NEW_COLOR);
-   COPY_4V(ctx->Color.ClearColor, tmp);
+   COPY_4V(ctx->Color.ClearColorUnclamped, tmp);
+
+   ctx->Color.ClearColor[0] = CLAMP(tmp[0], 0.0F, 1.0F);
+   ctx->Color.ClearColor[1] = CLAMP(tmp[1], 0.0F, 1.0F);
+   ctx->Color.ClearColor[2] = CLAMP(tmp[2], 0.0F, 1.0F);
+   ctx->Color.ClearColor[3] = CLAMP(tmp[3], 0.0F, 1.0F);
 
    if (ctx->Driver.ClearColor) {
       /* it's OK to call glClearColor in CI mode but it should be a NOP */
+      /* we pass the clamped color, since all drivers that need this don't
+       * support GL_ARB_color_buffer_float
+       */
       (*ctx->Driver.ClearColor)(ctx, ctx->Color.ClearColor);
    }
 }
diff --git a/src/mesa/main/colortab.c b/src/mesa/main/colortab.c
index d0c8657..35b3096 100644
--- a/src/mesa/main/colortab.c
+++ b/src/mesa/main/colortab.c
@@ -516,6 +516,7 @@ _mesa_GetColorTable( GLenum target, GLenum format,
    struct gl_texture_unit *texUnit = _mesa_get_current_tex_unit(ctx);
    struct gl_color_table *table = NULL;
    GLfloat rgba[MAX_COLOR_TABLE_SIZE][4];
+   GLbitfield transferOps = 0;
    ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
 
    if (ctx->NewState) {
@@ -618,8 +619,12 @@ _mesa_GetColorTable( GLenum target, GLenum format,
    if (!data)
       return;
 
+   /* TODO: is this correct? */
+   if(ctx->Color._ClampReadColor)
+      transferOps |= IMAGE_CLAMP_BIT;
+
    _mesa_pack_rgba_span_float(ctx, table->Size, rgba,
-                              format, type, data, &ctx->Pack, 0x0);
+                              format, type, data, &ctx->Pack, transferOps);
 
    _mesa_unmap_pbo_dest(ctx, &ctx->Pack);
 }
diff --git a/src/mesa/main/dlist.c b/src/mesa/main/dlist.c
index 0112d9d..f3c77f2 100644
--- a/src/mesa/main/dlist.c
+++ b/src/mesa/main/dlist.c
@@ -388,6 +388,9 @@ typedef enum
    OPCODE_UNIFORM_3UIV,
    OPCODE_UNIFORM_4UIV,
 
+   /* GL_ARB_color_buffer_float */
+   OPCODE_CLAMP_COLOR,
+
    /* GL_EXT_framebuffer_blit */
    OPCODE_BLIT_FRAMEBUFFER,
 
@@ -6887,6 +6890,22 @@ save_UniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose,
 }
 
 static void GLAPIENTRY
+save_ClampColorARB(GLenum target, GLenum clamp)
+{
+   GET_CURRENT_CONTEXT(ctx);
+   Node *n;
+   ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+   n = alloc_instruction(ctx, OPCODE_CLAMP_COLOR, 2);
+   if (n) {
+      n[1].e = target;
+      n[2].e = clamp;
+   }
+   if (ctx->ExecuteFlag) {
+      CALL_ClampColorARB(ctx->Exec, (target, clamp));
+   }
+}
+
+static void GLAPIENTRY
 save_UseShaderProgramEXT(GLenum type, GLuint program)
 {
    GET_CURRENT_CONTEXT(ctx);
@@ -8071,6 +8090,10 @@ execute_list(struct gl_context *ctx, GLuint list)
                                     (n[1].i, n[2].i, n[3].b, n[4].data));
 	    break;
 
+         case OPCODE_CLAMP_COLOR:
+            CALL_ClampColorARB(ctx->Exec, (n[1].e, n[2].e));
+            break;
+
          case OPCODE_TEX_BUMP_PARAMETER_ATI:
             {
                GLfloat values[4];
@@ -9868,6 +9891,10 @@ _mesa_create_save_table(void)
    SET_UseShaderProgramEXT(table, save_UseShaderProgramEXT);
    SET_ActiveProgramEXT(table, save_ActiveProgramEXT);
 
+   /* GL_ARB_color_buffer_float */
+   SET_ClampColorARB(table, save_ClampColorARB);
+   SET_ClampColor(table, save_ClampColorARB);
+
    /* GL 3.0 */
 #if 0
    SET_ClearBufferiv(table, save_ClearBufferiv);
diff --git a/src/mesa/main/extensions.c b/src/mesa/main/extensions.c
index 4b6e91c..a95cc9d 100644
--- a/src/mesa/main/extensions.c
+++ b/src/mesa/main/extensions.c
@@ -79,6 +79,7 @@ static const struct extension extension_table[] = {
    /* ARB Extensions */
    { "GL_ARB_ES2_compatibility",                   o(ARB_ES2_compatibility),                   GL,             2009 },
    { "GL_ARB_blend_func_extended",                 o(ARB_blend_func_extended),                 GL,             2009 },
+   { "GL_ARB_color_buffer_float",                  o(ARB_color_buffer_float),                  GL,             2004 },
    { "GL_ARB_copy_buffer",                         o(ARB_copy_buffer),                         GL,             2008 },
    { "GL_ARB_depth_buffer_float",                  o(ARB_depth_buffer_float),                  GL,             2008 },
    { "GL_ARB_depth_clamp",                         o(ARB_depth_clamp),                         GL,             2003 },
diff --git a/src/mesa/main/ff_fragment_shader.cpp b/src/mesa/main/ff_fragment_shader.cpp
index 9be5317..bf65a4f 100644
--- a/src/mesa/main/ff_fragment_shader.cpp
+++ b/src/mesa/main/ff_fragment_shader.cpp
@@ -726,7 +726,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 );
    }
 }
 
@@ -1563,7 +1563,7 @@ create_new_program(struct gl_context *ctx, struct state_key *key,
                            p.program->Base.NumInstructions);
 
    if (key->num_draw_buffers && p.program->FogOption) {
-      _mesa_append_fog_code(ctx, p.program);
+      _mesa_append_fog_code(ctx, p.program, GL_FALSE);
       p.program->FogOption = GL_NONE;
    }
 
diff --git a/src/mesa/main/fog.c b/src/mesa/main/fog.c
index 4392322..88aa31a 100644
--- a/src/mesa/main/fog.c
+++ b/src/mesa/main/fog.c
@@ -150,6 +150,10 @@ _mesa_Fogfv( GLenum pname, const GLfloat *params )
 	 if (TEST_EQ_4V(ctx->Fog.Color, params))
 	    return;
 	 FLUSH_VERTICES(ctx, _NEW_FOG);
+	 ctx->Fog.ColorUnclamped[0] = params[0];
+	 ctx->Fog.ColorUnclamped[1] = params[1];
+	 ctx->Fog.ColorUnclamped[2] = params[2];
+	 ctx->Fog.ColorUnclamped[3] = params[3];
 	 ctx->Fog.Color[0] = CLAMP(params[0], 0.0F, 1.0F);
 	 ctx->Fog.Color[1] = CLAMP(params[1], 0.0F, 1.0F);
 	 ctx->Fog.Color[2] = CLAMP(params[2], 0.0F, 1.0F);
@@ -189,6 +193,7 @@ void _mesa_init_fog( struct gl_context * ctx )
    ctx->Fog.Enabled = GL_FALSE;
    ctx->Fog.Mode = GL_EXP;
    ASSIGN_4V( ctx->Fog.Color, 0.0, 0.0, 0.0, 0.0 );
+   ASSIGN_4V( ctx->Fog.ColorUnclamped, 0.0, 0.0, 0.0, 0.0 );
    ctx->Fog.Index = 0.0;
    ctx->Fog.Density = 1.0;
    ctx->Fog.Start = 0.0;
diff --git a/src/mesa/main/get.c b/src/mesa/main/get.c
index 7d1a5cf..146ac0f 100644
--- a/src/mesa/main/get.c
+++ b/src/mesa/main/get.c
@@ -131,6 +131,7 @@ enum value_extra {
    EXTRA_VERSION_32,
    EXTRA_VERSION_ES2,
    EXTRA_NEW_BUFFERS, 
+   EXTRA_NEW_FRAG_CLAMP,
    EXTRA_VALID_DRAW_BUFFER,
    EXTRA_VALID_TEXTURE_UNIT,
    EXTRA_FLUSH_CURRENT,
@@ -223,6 +224,11 @@ static const int extra_new_buffers[] = {
    EXTRA_END
 };
 
+static const int extra_new_frag_clamp[] = {
+   EXTRA_NEW_FRAG_CLAMP,
+   EXTRA_END
+};
+
 static const int extra_valid_draw_buffer[] = {
    EXTRA_VALID_DRAW_BUFFER,
    EXTRA_END
@@ -374,7 +380,7 @@ static const struct value_desc values[] = {
    { GL_BLEND, CONTEXT_BIT0(Color.BlendEnabled), NO_EXTRA },
    { GL_BLEND_SRC, CONTEXT_ENUM(Color.Blend[0].SrcRGB), NO_EXTRA },
    { GL_BLUE_BITS, BUFFER_INT(Visual.blueBits), extra_new_buffers },
-   { GL_COLOR_CLEAR_VALUE, CONTEXT_FIELD(Color.ClearColor[0], TYPE_FLOATN_4), NO_EXTRA },
+   { GL_COLOR_CLEAR_VALUE, LOC_CUSTOM, TYPE_FLOATN_4, 0, extra_new_frag_clamp },
    { GL_COLOR_WRITEMASK, LOC_CUSTOM, TYPE_INT_4, 0, NO_EXTRA },
    { GL_CULL_FACE, CONTEXT_BOOL(Polygon.CullFlag), NO_EXTRA },
    { GL_CULL_FACE_MODE, CONTEXT_ENUM(Polygon.CullFaceMode), NO_EXTRA },
@@ -511,7 +517,7 @@ static const struct value_desc values[] = {
    { GL_LIGHT_MODEL_TWO_SIDE, CONTEXT_BOOL(Light.Model.TwoSide), NO_EXTRA },
    { GL_ALPHA_TEST, CONTEXT_BOOL(Color.AlphaEnabled), NO_EXTRA },
    { GL_ALPHA_TEST_FUNC, CONTEXT_ENUM(Color.AlphaFunc), NO_EXTRA },
-   { GL_ALPHA_TEST_REF, CONTEXT_FIELD(Color.AlphaRef, TYPE_FLOATN), NO_EXTRA },
+   { GL_ALPHA_TEST_REF, LOC_CUSTOM, TYPE_FLOATN, 0, extra_new_frag_clamp },
    { GL_BLEND_DST, CONTEXT_ENUM(Color.Blend[0].DstRGB), NO_EXTRA },
    { GL_CLIP_PLANE0, CONTEXT_BIT0(Transform.ClipPlanesEnabled), NO_EXTRA },
    { GL_CLIP_PLANE1, CONTEXT_BIT1(Transform.ClipPlanesEnabled), NO_EXTRA },
@@ -530,7 +536,7 @@ static const struct value_desc values[] = {
      extra_flush_current_valid_texture_unit },
    { GL_DISTANCE_ATTENUATION_EXT, CONTEXT_FLOAT3(Point.Params[0]), NO_EXTRA },
    { GL_FOG, CONTEXT_BOOL(Fog.Enabled), NO_EXTRA },
-   { GL_FOG_COLOR, CONTEXT_FIELD(Fog.Color[0], TYPE_FLOATN_4), NO_EXTRA },
+   { GL_FOG_COLOR, LOC_CUSTOM, TYPE_FLOATN_4, 0, extra_new_frag_clamp },
    { GL_FOG_DENSITY, CONTEXT_FLOAT(Fog.Density), NO_EXTRA },
    { GL_FOG_END, CONTEXT_FLOAT(Fog.End), NO_EXTRA },
    { GL_FOG_HINT, CONTEXT_ENUM(Hint.Fog), NO_EXTRA },
@@ -674,7 +680,7 @@ static const struct value_desc values[] = {
    /* GL_ARB_draw_buffers */
    { GL_MAX_DRAW_BUFFERS_ARB, CONTEXT_INT(Const.MaxDrawBuffers), NO_EXTRA },
 
-   { GL_BLEND_COLOR_EXT, CONTEXT_FIELD(Color.BlendColor[0], TYPE_FLOATN_4), NO_EXTRA },
+   { GL_BLEND_COLOR_EXT, LOC_CUSTOM, TYPE_FLOATN_4, 0, extra_new_frag_clamp },
    /* GL_ARB_fragment_program */
    { GL_MAX_TEXTURE_IMAGE_UNITS_ARB, /* == GL_MAX_TEXTURE_IMAGE_UNITS_NV */
      CONTEXT_INT(Const.MaxTextureImageUnits),
@@ -1219,6 +1225,9 @@ static const struct value_desc values[] = {
      CONTEXT_INT(Const.MaxVertexVaryingComponents),
      extra_ARB_geometry_shader4 },
 
+   /* GL_ARB_color_buffer_float */
+   { GL_RGBA_FLOAT_MODE_ARB, BUFFER_FIELD(Visual.floatMode, TYPE_BOOLEAN), 0 },
+
    /* GL_EXT_gpu_shader4 / GL 3.0 */
    { GL_MIN_PROGRAM_TEXEL_OFFSET,
      CONTEXT_INT(Const.MinProgramTexelOffset),
@@ -1633,6 +1642,30 @@ find_custom_value(struct gl_context *ctx, const struct value_desc *d, union valu
       v->value_int = ctx->Array.ArrayObj->PointSize.BufferObj->Name;
       break;
 
+   case GL_FOG_COLOR:
+      if(ctx->Color._ClampFragmentColor)
+         COPY_4FV(v->value_float_4, ctx->Fog.Color);
+      else
+         COPY_4FV(v->value_float_4, ctx->Fog.ColorUnclamped);
+      break;
+   case GL_COLOR_CLEAR_VALUE:
+      if(ctx->Color._ClampFragmentColor)
+         COPY_4FV(v->value_float_4, ctx->Color.ClearColor);
+      else
+         COPY_4FV(v->value_float_4, ctx->Color.ClearColorUnclamped);
+      break;
+   case GL_BLEND_COLOR_EXT:
+      if(ctx->Color._ClampFragmentColor)
+         COPY_4FV(v->value_float_4, ctx->Color.BlendColor);
+      else
+         COPY_4FV(v->value_float_4, ctx->Color.BlendColorUnclamped);
+      break;
+   case GL_ALPHA_TEST_REF:
+      if(ctx->Color._ClampFragmentColor)
+         v->value_float = ctx->Color.AlphaRef;
+      else
+         v->value_float = ctx->Color.AlphaRefUnclamped;
+      break;
    case GL_MAX_VERTEX_UNIFORM_VECTORS:
       v->value_int = ctx->Const.VertexProgram.MaxUniformComponents / 4;
       break;
@@ -1687,6 +1720,10 @@ check_extra(struct gl_context *ctx, const char *func, const struct value_desc *d
 	    enabled++;
 	 }
 	 break;
+      case EXTRA_NEW_FRAG_CLAMP:
+         if (ctx->NewState & (_NEW_BUFFERS | _NEW_FRAG_CLAMP))
+            _mesa_update_state(ctx);
+         break;
       case EXTRA_VERSION_ES2:
 	 if (ctx->API == API_OPENGLES2) {
 	    total++;
diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h
index 831774f..c6598ea 100644
--- a/src/mesa/main/mtypes.h
+++ b/src/mesa/main/mtypes.h
@@ -691,7 +691,8 @@ struct gl_accum_attrib
 struct gl_colorbuffer_attrib
 {
    GLuint ClearIndex;			/**< Index to use for glClear */
-   GLclampf ClearColor[4];		/**< Color to use for glClear */
+   GLfloat ClearColorUnclamped[4];              /**< Color to use for glClear*/
+   GLclampf ClearColor[4];               /**< Color to use for glClear */
 
    GLuint IndexMask;			/**< Color index write mask */
    GLubyte ColorMask[MAX_DRAW_BUFFERS][4];/**< Each flag is 0xff or 0x0 */
@@ -704,6 +705,7 @@ struct gl_colorbuffer_attrib
    /*@{*/
    GLboolean AlphaEnabled;		/**< Alpha test enabled flag */
    GLenum AlphaFunc;			/**< Alpha test function */
+   GLfloat AlphaRefUnclamped;
    GLclampf AlphaRef;			/**< Alpha reference value */
    /*@}*/
 
@@ -712,7 +714,14 @@ struct gl_colorbuffer_attrib
     */
    /*@{*/
    GLbitfield BlendEnabled;		/**< Per-buffer blend enable flags */
+
+   /* NOTE: this does _not_ depend on fragment clamping or any other clamping control,
+    * only on the fixed-pointness of the render target.
+    * The query does however depend on fragment color clamping.
+    */
+   GLfloat BlendColorUnclamped[4];               /**< Blending color */
    GLfloat BlendColor[4];		/**< Blending color */
+
    struct
    {
       GLenum SrcRGB;             /**< RGB blend source term */
@@ -741,7 +750,9 @@ struct gl_colorbuffer_attrib
    GLboolean DitherFlag;		/**< Dither enable flag */
 
    GLenum ClampFragmentColor; /**< GL_TRUE, GL_FALSE or GL_FIXED_ONLY_ARB */
+   GLboolean _ClampFragmentColor; /** < with GL_FIXED_ONLY_ARB resolved */
    GLenum ClampReadColor;     /**< GL_TRUE, GL_FALSE or GL_FIXED_ONLY_ARB */
+   GLboolean _ClampReadColor;     /** < with GL_FIXED_ONLY_ARB resolved */
 
    GLboolean sRGBEnabled;	/**< Framebuffer sRGB blending/updating requested */
 };
@@ -840,6 +851,7 @@ struct gl_eval_attrib
 struct gl_fog_attrib
 {
    GLboolean Enabled;		/**< Fog enabled flag */
+   GLfloat ColorUnclamped[4];            /**< Fog color */
    GLfloat Color[4];		/**< Fog color */
    GLfloat Density;		/**< Density >= 0.0 */
    GLfloat Start;		/**< Start distance in eye coords */
@@ -921,6 +933,7 @@ struct gl_light_attrib
    GLbitfield ColorMaterialBitmask;	/**< bitmask formed from Face and Mode */
    GLboolean ColorMaterialEnabled;
    GLenum ClampVertexColor;
+   GLboolean _ClampVertexColor;
 
    struct gl_light EnabledList;         /**< List sentinel */
 
@@ -1396,7 +1409,8 @@ struct gl_texture_unit
    GLbitfield _ReallyEnabled;   /**< 0 or exactly one of TEXTURE_*_BIT flags */
 
    GLenum EnvMode;              /**< GL_MODULATE, GL_DECAL, GL_BLEND, etc. */
-   GLfloat EnvColor[4];
+   GLclampf EnvColor[4];
+   GLfloat EnvColorUnclamped[4];
 
    struct gl_texgen GenS;
    struct gl_texgen GenT;
@@ -2704,6 +2718,7 @@ struct gl_extensions
    GLboolean dummy_false; /* Set false by _mesa_init_extensions(). */
    GLboolean ARB_ES2_compatibility;
    GLboolean ARB_blend_func_extended;
+   GLboolean ARB_color_buffer_float;
    GLboolean ARB_copy_buffer;
    GLboolean ARB_depth_buffer_float;
    GLboolean ARB_depth_clamp;
@@ -2933,6 +2948,7 @@ struct gl_matrix_stack
 #define _NEW_PROGRAM           (1 << 26)  /**< New program/shader state */
 #define _NEW_PROGRAM_CONSTANTS (1 << 27)
 #define _NEW_BUFFER_OBJECT     (1 << 28)
+#define _NEW_FRAG_CLAMP        (1 << 29)
 #define _NEW_ALL ~0
 /*@}*/
 
diff --git a/src/mesa/main/pack.c b/src/mesa/main/pack.c
index 512835c..0215458 100644
--- a/src/mesa/main/pack.c
+++ b/src/mesa/main/pack.c
@@ -504,17 +504,6 @@ _mesa_pack_rgba_span_float(struct gl_context *ctx, GLuint n, GLfloat rgba[][4],
       luminance = NULL;
    }
 
-   /* XXX
-    * This test should probably go away.  Have the caller set/clear the
-    * IMAGE_CLAMP_BIT as needed.
-    */
-   if (dstType != GL_FLOAT || ctx->Color.ClampReadColor == GL_TRUE) {
-      if (!intDstFormat) {
-         /* need to clamp to [0, 1] */
-         transferOps |= IMAGE_CLAMP_BIT;
-      }
-   }
-
    if (transferOps) {
       _mesa_apply_rgba_transfer_ops(ctx, transferOps, n, rgba);
    }
diff --git a/src/mesa/main/state.c b/src/mesa/main/state.c
index 19c9bba..eab58ce 100644
--- a/src/mesa/main/state.c
+++ b/src/mesa/main/state.c
@@ -445,6 +445,35 @@ update_color(struct gl_context *ctx)
    ctx->Color._LogicOpEnabled = _mesa_rgba_logicop_enabled(ctx);
 }
 
+static void
+update_clamp_fragment_color(struct gl_context *ctx)
+{
+   if(ctx->Color.ClampFragmentColor == GL_FIXED_ONLY_ARB)
+      ctx->Color._ClampFragmentColor = !ctx->DrawBuffer || !ctx->DrawBuffer->Visual.floatMode;
+   else
+      ctx->Color._ClampFragmentColor = ctx->Color.ClampFragmentColor;
+}
+
+static void
+update_clamp_vertex_color(struct gl_context *ctx)
+{
+   if(ctx->Light.ClampVertexColor == GL_FIXED_ONLY_ARB)
+      ctx->Light._ClampVertexColor = !ctx->DrawBuffer || !ctx->DrawBuffer->Visual.floatMode;
+   else
+      ctx->Light._ClampVertexColor = ctx->Light.ClampVertexColor;
+}
+
+static void
+update_clamp_read_color(struct gl_context *ctx)
+{
+   if(ctx->Color.ClampReadColor == GL_FIXED_ONLY_ARB)
+      ctx->Color._ClampReadColor = !ctx->ReadBuffer || !ctx->ReadBuffer->Visual.floatMode;
+   else
+      ctx->Color._ClampReadColor = ctx->Color.ClampReadColor;
+}
+
+
+
 
 /*
  * Check polygon state and set DD_TRI_CULL_FRONT_BACK and/or DD_TRI_OFFSET
@@ -565,7 +594,7 @@ _mesa_update_state_locked( struct gl_context *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 |
@@ -599,6 +628,9 @@ _mesa_update_state_locked( struct gl_context *ctx )
    if (new_state & _NEW_LIGHT)
       _mesa_update_lighting( ctx );
 
+   if (new_state & (_NEW_LIGHT | _NEW_BUFFERS))
+      update_clamp_vertex_color(ctx);
+
    if (new_state & (_NEW_STENCIL | _NEW_BUFFERS))
       _mesa_update_stencil( ctx );
 
@@ -617,6 +649,12 @@ _mesa_update_state_locked( struct gl_context *ctx )
    if (new_state & _NEW_COLOR)
       update_color( ctx );
 
+   if (new_state & (_NEW_COLOR | _NEW_BUFFERS))
+      update_clamp_read_color(ctx);
+
+   if(new_state & (_NEW_FRAG_CLAMP | _NEW_BUFFERS))
+      update_clamp_fragment_color(ctx);
+
 #if 0
    if (new_state & (_NEW_POINT | _NEW_LINE | _NEW_POLYGON | _NEW_LIGHT
                     | _NEW_STENCIL | _DD_NEW_SEPARATE_SPECULAR))
diff --git a/src/mesa/main/texenv.c b/src/mesa/main/texenv.c
index 45a2e19..9228e35 100644
--- a/src/mesa/main/texenv.c
+++ b/src/mesa/main/texenv.c
@@ -35,6 +35,7 @@
 #include "main/enums.h"
 #include "main/macros.h"
 #include "main/mtypes.h"
+#include "main/state.h"
 #include "main/texenv.h"
 #include "main/texstate.h"
 
@@ -94,15 +95,14 @@ set_env_color(struct gl_context *ctx,
               struct gl_texture_unit *texUnit,
               const GLfloat *color)
 {
-   GLfloat tmp[4];
-   tmp[0] = CLAMP(color[0], 0.0F, 1.0F);
-   tmp[1] = CLAMP(color[1], 0.0F, 1.0F);
-   tmp[2] = CLAMP(color[2], 0.0F, 1.0F);
-   tmp[3] = CLAMP(color[3], 0.0F, 1.0F);
-   if (TEST_EQ_4V(tmp, texUnit->EnvColor))
+   if (TEST_EQ_4V(color, texUnit->EnvColorUnclamped))
       return;
    FLUSH_VERTICES(ctx, _NEW_TEXTURE);
-   COPY_4FV(texUnit->EnvColor, tmp);
+   COPY_4FV(texUnit->EnvColorUnclamped, color);
+   texUnit->EnvColor[0] = CLAMP(color[0], 0.0F, 1.0F);
+   texUnit->EnvColor[1] = CLAMP(color[1], 0.0F, 1.0F);
+   texUnit->EnvColor[2] = CLAMP(color[2], 0.0F, 1.0F);
+   texUnit->EnvColor[3] = CLAMP(color[3], 0.0F, 1.0F);
 }
 
 
@@ -758,7 +758,12 @@ _mesa_GetTexEnvfv( GLenum target, GLenum pname, GLfloat *params )
 
    if (target == GL_TEXTURE_ENV) {
       if (pname == GL_TEXTURE_ENV_COLOR) {
-         COPY_4FV( params, texUnit->EnvColor );
+         if(ctx->NewState & (_NEW_BUFFERS | _NEW_FRAG_CLAMP))
+            _mesa_update_state(ctx);
+         if(ctx->Color._ClampFragmentColor)
+            COPY_4FV( params, texUnit->EnvColor );
+         else
+            COPY_4FV( params, texUnit->EnvColorUnclamped );
       }
       else {
          GLint val = get_texenvi(ctx, texUnit, pname);
diff --git a/src/mesa/main/texparam.c b/src/mesa/main/texparam.c
index 6e14fac..adb6bce 100644
--- a/src/mesa/main/texparam.c
+++ b/src/mesa/main/texparam.c
@@ -38,6 +38,7 @@
 #include "main/macros.h"
 #include "main/mfeatures.h"
 #include "main/mtypes.h"
+#include "main/state.h"
 #include "main/texcompress.h"
 #include "main/texparam.h"
 #include "main/teximage.h"
@@ -1107,10 +1108,22 @@ _mesa_GetTexParameterfv( GLenum target, GLenum pname, GLfloat *params )
          *params = ENUM_TO_FLOAT(obj->WrapR);
          break;
       case GL_TEXTURE_BORDER_COLOR:
-         params[0] = CLAMP(obj->BorderColor.f[0], 0.0F, 1.0F);
-         params[1] = CLAMP(obj->BorderColor.f[1], 0.0F, 1.0F);
-         params[2] = CLAMP(obj->BorderColor.f[2], 0.0F, 1.0F);
-         params[3] = CLAMP(obj->BorderColor.f[3], 0.0F, 1.0F);
+         if(ctx->NewState & (_NEW_BUFFERS | _NEW_FRAG_CLAMP))
+            _mesa_update_state_locked(ctx);
+         if(ctx->Color._ClampFragmentColor)
+         {
+            params[0] = CLAMP(obj->BorderColor.f[0], 0.0F, 1.0F);
+            params[1] = CLAMP(obj->BorderColor.f[1], 0.0F, 1.0F);
+            params[2] = CLAMP(obj->BorderColor.f[2], 0.0F, 1.0F);
+            params[3] = CLAMP(obj->BorderColor.f[3], 0.0F, 1.0F);
+         }
+         else
+         {
+            params[0] = obj->BorderColor.f[0];
+            params[1] = obj->BorderColor.f[1];
+            params[2] = obj->BorderColor.f[2];
+            params[3] = obj->BorderColor.f[3];
+         }
          break;
       case GL_TEXTURE_RESIDENT:
          {
diff --git a/src/mesa/main/version.c b/src/mesa/main/version.c
index a10b86e..956c7b9 100644
--- a/src/mesa/main/version.c
+++ b/src/mesa/main/version.c
@@ -89,6 +89,8 @@ compute_version(struct gl_context *ctx)
                               ctx->Extensions.EXT_pixel_buffer_object &&
                               ctx->Extensions.EXT_texture_sRGB);
    const GLboolean ver_3_0 = (ver_2_1 &&
+                              ctx->Extensions.ARB_color_buffer_float &&
+                              ctx->Extensions.ARB_depth_buffer_float &&
                               ctx->Extensions.ARB_half_float_pixel &&
                               ctx->Extensions.ARB_map_buffer_range &&
                               ctx->Extensions.ARB_texture_float &&
diff --git a/src/mesa/program/arbprogparse.c b/src/mesa/program/arbprogparse.c
index ca63e72..7f778c3 100644
--- a/src/mesa/program/arbprogparse.c
+++ b/src/mesa/program/arbprogparse.c
@@ -144,7 +144,10 @@ _mesa_parse_arb_fragment_program(struct gl_context* 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 c310acb..384aa2c 100644
--- a/src/mesa/program/prog_statevars.c
+++ b/src/mesa/program/prog_statevars.c
@@ -237,11 +237,17 @@ _mesa_fetch_state(struct gl_context *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;
@@ -399,6 +405,22 @@ _mesa_fetch_state(struct gl_context *ctx, const gl_state_index state[],
          }
          return;
 
+      case STATE_CURRENT_ATTRIB_MAYBE_VP_CLAMPED:
+         {
+            const GLuint idx = (GLuint) state[2];
+            if(ctx->Light._ClampVertexColor &&
+               (idx == VERT_ATTRIB_COLOR0 ||
+                idx == VERT_ATTRIB_COLOR1)) {
+               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, 
@@ -649,10 +671,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;
 
@@ -688,6 +712,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 f2407af..9fe8d81 100644
--- a/src/mesa/program/prog_statevars.h
+++ b/src/mesa/program/prog_statevars.h
@@ -106,6 +106,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 f92881f..5ad9571 100644
--- a/src/mesa/program/programopt.c
+++ b/src/mesa/program/programopt.c
@@ -238,7 +238,7 @@ _mesa_insert_mvp_code(struct gl_context *ctx, struct gl_vertex_program *vprog)
  * to vertex programs too.
  */
 void
-_mesa_append_fog_code(struct gl_context *ctx, struct gl_fragment_program *fprog)
+_mesa_append_fog_code(struct gl_context *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(struct gl_context *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(struct gl_context *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 ef6f1bd..79631aa 100644
--- a/src/mesa/program/programopt.h
+++ b/src/mesa/program/programopt.h
@@ -32,7 +32,7 @@ extern void
 _mesa_insert_mvp_code(struct gl_context *ctx, struct gl_vertex_program *vprog);
 
 extern void
-_mesa_append_fog_code(struct gl_context *ctx, struct gl_fragment_program *fprog);
+_mesa_append_fog_code(struct gl_context *ctx, struct gl_fragment_program *fprog, GLboolean saturate);
 
 extern void
 _mesa_count_texture_indirections(struct gl_program *prog);
-- 
1.7.1



More information about the mesa-dev mailing list