st/mesa: do vertex and fragment color clamping in shaders
authorMarek Olšák <maraeo@gmail.com>
Mon, 23 Jan 2012 02:11:17 +0000 (03:11 +0100)
committerMarek Olšák <maraeo@gmail.com>
Wed, 25 Jan 2012 11:35:18 +0000 (12:35 +0100)
For ARB_color_buffer_float. Most hardware can't do it and st/mesa is
the perfect place for a fallback.
The exceptions are:
- r500 (vertex clamp only)
- nv50 (both)
- nvc0 (both)
- softpipe (both)

We also have to take into account that r300 can do CLAMPED vertex colors only,
while r600 can do UNCLAMPED vertex colors only. The difference can be expressed
with the two new CAPs.

22 files changed:
src/gallium/drivers/i915/i915_screen.c
src/gallium/drivers/nv50/nv50_screen.c
src/gallium/drivers/nvc0/nvc0_screen.c
src/gallium/drivers/nvfx/nvfx_screen.c
src/gallium/drivers/r300/r300_screen.c
src/gallium/drivers/r300/r300_state.c
src/gallium/drivers/r600/r600_pipe.c
src/gallium/drivers/softpipe/sp_screen.c
src/gallium/include/pipe/p_defines.h
src/mesa/state_tracker/st_atom_rasterizer.c
src/mesa/state_tracker/st_atom_shader.c
src/mesa/state_tracker/st_cb_bitmap.c
src/mesa/state_tracker/st_cb_drawpixels.c
src/mesa/state_tracker/st_context.c
src/mesa/state_tracker/st_context.h
src/mesa/state_tracker/st_extensions.c
src/mesa/state_tracker/st_glsl_to_tgsi.cpp
src/mesa/state_tracker/st_glsl_to_tgsi.h
src/mesa/state_tracker/st_mesa_to_tgsi.c
src/mesa/state_tracker/st_mesa_to_tgsi.h
src/mesa/state_tracker/st_program.c
src/mesa/state_tracker/st_program.h

index 6fc854f20f15304493d7b811a9aba4acd1c3fd9a..aef0ed6980d0fd076ceafbc0cf5b87f6ce3adf59 100644 (file)
@@ -181,6 +181,7 @@ i915_get_param(struct pipe_screen *screen, enum pipe_cap cap)
    case PIPE_CAP_VERTEX_ELEMENT_INSTANCE_DIVISOR:
    case PIPE_CAP_BLEND_EQUATION_SEPARATE:
    case PIPE_CAP_TGSI_INSTANCEID:
+   case PIPE_CAP_VERTEX_COLOR_CLAMPED:
       return 1;
 
    /* Unsupported features (boolean caps). */
@@ -196,12 +197,13 @@ i915_get_param(struct pipe_screen *screen, enum pipe_cap cap)
    case PIPE_CAP_SEAMLESS_CUBE_MAP:
    case PIPE_CAP_SEAMLESS_CUBE_MAP_PER_TEXTURE:
    case PIPE_CAP_SCALED_RESOLVE:
-   case PIPE_CAP_FRAGMENT_COLOR_CLAMP_CONTROL:
+   case PIPE_CAP_FRAGMENT_COLOR_CLAMPED:
    case PIPE_CAP_MIXED_COLORBUFFER_FORMATS:
    case PIPE_CAP_CONDITIONAL_RENDER:
    case PIPE_CAP_TEXTURE_BARRIER:
    case PIPE_CAP_TGSI_CAN_COMPACT_VARYINGS:
    case PIPE_CAP_TGSI_CAN_COMPACT_CONSTANTS:
+   case PIPE_CAP_VERTEX_COLOR_UNCLAMPED:
       return 0;
 
    /* Features we can lie about (boolean caps). */
index 7ee90f18543434c587000c1f6415206b0e2c90c7..536e06471b6fe33e3a30d1d0579c93c13e50426e 100644 (file)
@@ -112,7 +112,9 @@ nv50_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param)
       return 1;
    case PIPE_CAP_MAX_RENDER_TARGETS:
       return 8;
-   case PIPE_CAP_FRAGMENT_COLOR_CLAMP_CONTROL:
+   case PIPE_CAP_FRAGMENT_COLOR_CLAMPED:
+   case PIPE_CAP_VERTEX_COLOR_UNCLAMPED:
+   case PIPE_CAP_VERTEX_COLOR_CLAMPED:
       return 1;
    case PIPE_CAP_TIMER_QUERY:
    case PIPE_CAP_OCCLUSION_QUERY:
index f9ad39df70620f3839ee1f9f60a57314284b4a07..5116646949c9e869f7f5d0c09166b075c62b5ce1 100644 (file)
@@ -99,7 +99,9 @@ nvc0_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param)
       return 1;
    case PIPE_CAP_MAX_RENDER_TARGETS:
       return 8;
-   case PIPE_CAP_FRAGMENT_COLOR_CLAMP_CONTROL:
+   case PIPE_CAP_FRAGMENT_COLOR_CLAMPED:
+   case PIPE_CAP_VERTEX_COLOR_UNCLAMPED:
+   case PIPE_CAP_VERTEX_COLOR_CLAMPED:
       return 1;
    case PIPE_CAP_TIMER_QUERY:
    case PIPE_CAP_OCCLUSION_QUERY:
index ead777de784498abefeaedfea1d193ea2ff90b52..2a3289f04fd3f62de7fb9c568aa5bdad0029bdf7 100644 (file)
@@ -72,6 +72,7 @@ nvfx_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param)
        case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_HALF_INTEGER:
        case PIPE_CAP_TGSI_FS_COORD_ORIGIN_UPPER_LEFT:
        case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_INTEGER:
+       case PIPE_CAP_VERTEX_COLOR_CLAMPED:
                return 1;
        case PIPE_CAP_DEPTH_CLIP_DISABLE:
                return 0; // TODO: implement depth clamp
@@ -80,7 +81,8 @@ nvfx_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param)
        case PIPE_CAP_MAX_TEXTURE_ARRAY_LAYERS:
        case PIPE_CAP_TGSI_INSTANCEID:
        case PIPE_CAP_VERTEX_ELEMENT_INSTANCE_DIVISOR:
-       case PIPE_CAP_FRAGMENT_COLOR_CLAMP_CONTROL:
+       case PIPE_CAP_FRAGMENT_COLOR_CLAMPED:
+       case PIPE_CAP_VERTEX_COLOR_UNCLAMPED:
        case PIPE_CAP_SEAMLESS_CUBE_MAP:
        case PIPE_CAP_SEAMLESS_CUBE_MAP_PER_TEXTURE:
        case PIPE_CAP_SHADER_STENCIL_EXPORT:
index cd3c88d170b325d4f8a740127b28be8e41e73866..48a656963598159eeeb3f02cea5a1ba8925e94e4 100644 (file)
@@ -102,6 +102,7 @@ static int r300_get_param(struct pipe_screen* pscreen, enum pipe_cap param)
         case PIPE_CAP_TEXTURE_BARRIER:
         case PIPE_CAP_TGSI_CAN_COMPACT_VARYINGS:
         case PIPE_CAP_TGSI_CAN_COMPACT_CONSTANTS:
+        case PIPE_CAP_VERTEX_COLOR_CLAMPED:
             return 1;
 
         /* r300 cannot do swizzling of compressed textures. Supported otherwise. */
@@ -109,7 +110,7 @@ static int r300_get_param(struct pipe_screen* pscreen, enum pipe_cap param)
             return util_format_s3tc_enabled ? r300screen->caps.dxtc_swizzle : 1;
 
         /* Supported on r500 only. */
-        case PIPE_CAP_FRAGMENT_COLOR_CLAMP_CONTROL:
+        case PIPE_CAP_VERTEX_COLOR_UNCLAMPED:
         case PIPE_CAP_MIXED_COLORBUFFER_FORMATS:
         case PIPE_CAP_SM3:
             return is_r500 ? 1 : 0;
@@ -135,6 +136,7 @@ static int r300_get_param(struct pipe_screen* pscreen, enum pipe_cap param)
         case PIPE_CAP_MAX_STREAM_OUTPUT_SEPARATE_COMPONENTS:
         case PIPE_CAP_MAX_STREAM_OUTPUT_INTERLEAVED_COMPONENTS:
         case PIPE_CAP_STREAM_OUTPUT_PAUSE_RESUME:
+        case PIPE_CAP_FRAGMENT_COLOR_CLAMPED:
             return 0;
 
         /* SWTCL-only features. */
index 2bc703669ae449c2bb28a1e675b55daa57e8dac7..5d4a895e87c9d5bb761b89a71cb7b003c79716da 100644 (file)
@@ -1036,7 +1036,8 @@ static void* r300_create_rs_state(struct pipe_context* pipe,
     float point_texcoord_bottom = 0;/* R300_GA_POINT_T0: 0x4204 */
     float point_texcoord_right = 1; /* R300_GA_POINT_S1: 0x4208 */
     float point_texcoord_top = 0;   /* R300_GA_POINT_T1: 0x420c */
-    boolean vclamp = state->clamp_vertex_color;
+    boolean vclamp = state->clamp_vertex_color ||
+                     !r300_context(pipe)->screen->caps.is_r500;
     CB_LOCALS;
 
     /* Copy rasterizer state. */
index 3d85160c14c1135f15080a4eb33329f9543a6f2e..bd9267f0d9ad1f2a7f167f92a8d356af41488314 100644 (file)
@@ -361,11 +361,11 @@ static int r600_get_param(struct pipe_screen* pscreen, enum pipe_cap param)
        case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_HALF_INTEGER:
        case PIPE_CAP_SM3:
        case PIPE_CAP_SEAMLESS_CUBE_MAP:
-       case PIPE_CAP_FRAGMENT_COLOR_CLAMP_CONTROL:
        case PIPE_CAP_PRIMITIVE_RESTART:
        case PIPE_CAP_CONDITIONAL_RENDER:
        case PIPE_CAP_TEXTURE_BARRIER:
        case PIPE_CAP_STREAM_OUTPUT_PAUSE_RESUME:
+       case PIPE_CAP_VERTEX_COLOR_UNCLAMPED:
                return 1;
 
        /* Supported except the original R600. */
@@ -385,6 +385,8 @@ static int r600_get_param(struct pipe_screen* pscreen, enum pipe_cap param)
        case PIPE_CAP_SCALED_RESOLVE:
        case PIPE_CAP_TGSI_CAN_COMPACT_VARYINGS:
        case PIPE_CAP_TGSI_CAN_COMPACT_CONSTANTS:
+       case PIPE_CAP_FRAGMENT_COLOR_CLAMPED:
+       case PIPE_CAP_VERTEX_COLOR_CLAMPED:
                return 0;
 
        /* Stream output. */
index 34592a9b21f1e5989edd38f30c61b737209b47cc..37bbc43f3255f2e4e592977df6ac67fee8524cc2 100644 (file)
@@ -128,7 +128,9 @@ softpipe_get_param(struct pipe_screen *screen, enum pipe_cap param)
       return 7;
    case PIPE_CAP_CONDITIONAL_RENDER:
       return 1;
-   case PIPE_CAP_FRAGMENT_COLOR_CLAMP_CONTROL:
+   case PIPE_CAP_FRAGMENT_COLOR_CLAMPED:
+   case PIPE_CAP_VERTEX_COLOR_UNCLAMPED: /* draw module */
+   case PIPE_CAP_VERTEX_COLOR_CLAMPED: /* draw module */
       return 1;
    default:
       return 0;
index 4425fc9f9464b59d8ee828fc9139bcb480a2865e..2cd11f988abbf263cc4ed48eac995f4a2bba4007 100644 (file)
@@ -472,7 +472,7 @@ enum pipe_cap {
    PIPE_CAP_SHADER_STENCIL_EXPORT = 42,
    PIPE_CAP_TGSI_INSTANCEID = 43,
    PIPE_CAP_VERTEX_ELEMENT_INSTANCE_DIVISOR = 44,
-   PIPE_CAP_FRAGMENT_COLOR_CLAMP_CONTROL = 45,
+   PIPE_CAP_FRAGMENT_COLOR_CLAMPED = 45,
    PIPE_CAP_MIXED_COLORBUFFER_FORMATS = 46,
    PIPE_CAP_SEAMLESS_CUBE_MAP = 47,
    PIPE_CAP_SEAMLESS_CUBE_MAP_PER_TEXTURE = 48,
@@ -485,7 +485,9 @@ enum pipe_cap {
    PIPE_CAP_MAX_STREAM_OUTPUT_INTERLEAVED_COMPONENTS = 56,
    PIPE_CAP_STREAM_OUTPUT_PAUSE_RESUME = 57,
    PIPE_CAP_TGSI_CAN_COMPACT_VARYINGS = 58, /* temporary */
-   PIPE_CAP_TGSI_CAN_COMPACT_CONSTANTS = 59 /* temporary */
+   PIPE_CAP_TGSI_CAN_COMPACT_CONSTANTS = 59, /* temporary */
+   PIPE_CAP_VERTEX_COLOR_UNCLAMPED = 60,
+   PIPE_CAP_VERTEX_COLOR_CLAMPED = 61
 };
 
 /**
index f3d28e675f53d64c64f9f65f77fb791a8e5756a7..25799bf2bd51e3ead64749084367f8d1e5e59b67 100644 (file)
@@ -112,7 +112,8 @@ static void update_raster_state( struct st_context *st )
       raster->light_twoside = 1;
    }
 
-   raster->clamp_vertex_color = ctx->Light._ClampVertexColor;
+   raster->clamp_vertex_color = !st->clamp_vert_color_in_shader &&
+                                ctx->Light._ClampVertexColor;
 
    /* _NEW_POLYGON
     */
@@ -255,7 +256,8 @@ static void update_raster_state( struct st_context *st )
       raster->scissor = 1;
 
    /* _NEW_FRAG_CLAMP */
-   raster->clamp_fragment_color = ctx->Color._ClampFragmentColor;
+   raster->clamp_fragment_color = !st->clamp_frag_color_in_shader &&
+                                  ctx->Color._ClampFragmentColor;
    raster->gl_rasterization_rules = 1;
 
    /* _NEW_RASTERIZER_DISCARD */
index c311d04393107efa4ee882c7af49170e084ed44c..ae3491097b41a4ac52dcdd369456b86a08c9623e 100644 (file)
@@ -83,6 +83,10 @@ update_fp( struct st_context *st )
    memset(&key, 0, sizeof(key));
    key.st = st;
 
+   /* _NEW_FRAG_CLAMP */
+   key.clamp_color = st->clamp_frag_color_in_shader &&
+                     st->ctx->Color._ClampFragmentColor;
+
    st->fp_variant = st_get_fp_variant(st, stfp, &key);
 
    st_reference_fragprog(st, &st->fp, stfp);
@@ -141,6 +145,9 @@ update_vp( struct st_context *st )
                                 st->ctx->Polygon.FrontMode != GL_FILL ||
                                 st->ctx->Polygon.BackMode != GL_FILL));
 
+   key.clamp_color = st->clamp_vert_color_in_shader &&
+                     st->ctx->Light._ClampVertexColor;
+
    st->vp_variant = st_get_vp_variant(st, stvp, &key);
 
    st_reference_vertprog(st, &st->vp, stvp);
index a9709680208c11da474f3d786a3558e3bbbdd0b9..7c0254d8d22fb145cebaef113a148a5e00421961 100644 (file)
@@ -450,6 +450,8 @@ draw_bitmap_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z,
    memset(&key, 0, sizeof(key));
    key.st = st;
    key.bitmap = GL_TRUE;
+   key.clamp_color = st->clamp_frag_color_in_shader &&
+                     st->ctx->Color._ClampFragmentColor;
 
    fpv = st_get_fp_variant(st, st->fp, &key);
 
index 13c4f3369cc96fae6f4a1b1276c6e923d99621c4..386eed2909f4a140dad8d6c5a0cb52488e2f9b10 100644 (file)
@@ -684,7 +684,8 @@ draw_textured_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z,
    {
       struct pipe_rasterizer_state rasterizer;
       memset(&rasterizer, 0, sizeof(rasterizer));
-      rasterizer.clamp_fragment_color = ctx->Color._ClampFragmentColor;
+      rasterizer.clamp_fragment_color = !st->clamp_frag_color_in_shader &&
+                                        ctx->Color._ClampFragmentColor;
       rasterizer.gl_rasterization_rules = 1;
       rasterizer.depth_clip = !ctx->Transform.DepthClamp;
       rasterizer.scissor = ctx->Scissor.Enabled;
@@ -1007,6 +1008,8 @@ get_color_fp_variant(struct st_context *st)
                        ctx->Pixel.AlphaBias != 0.0 ||
                        ctx->Pixel.AlphaScale != 1.0);
    key.pixelMaps = ctx->Pixel.MapColorFlag;
+   key.clamp_color = st->clamp_frag_color_in_shader &&
+                     st->ctx->Color._ClampFragmentColor;
 
    fpv = st_get_fp_variant(st, st->fp, &key);
 
index dc1d33f1daeb999b62dff374466d907ac8a2c84c..a3fd4dbcb7f5ec36140b8c7e2dcd9f3c0c9c7a54 100644 (file)
@@ -76,6 +76,17 @@ void st_invalidate_state(struct gl_context * ctx, GLuint new_state)
 {
    struct st_context *st = st_context(ctx);
 
+   /* Replace _NEW_FRAG_CLAMP with ST_NEW_FRAGMENT_PROGRAM for the fallback. */
+   if (st->clamp_frag_color_in_shader && (new_state & _NEW_FRAG_CLAMP)) {
+      new_state &= ~_NEW_FRAG_CLAMP;
+      st->dirty.st |= ST_NEW_FRAGMENT_PROGRAM;
+   }
+
+   /* Update the vertex shader if ctx->Light._ClampVertexColor was changed. */
+   if (st->clamp_vert_color_in_shader && (new_state & _NEW_LIGHT)) {
+      st->dirty.st |= ST_NEW_VERTEX_PROGRAM;
+   }
+
    st->dirty.mesa |= new_state;
    st->dirty.st |= ST_NEW_MESA;
 
index 9db50b3f4c8fc874177cb578670c014a42cd5244..da03719fdec909cabf1fdea85ba68ce656b3638d 100644 (file)
@@ -76,6 +76,8 @@ struct st_context
    struct draw_stage *selection_stage;  /**< For GL_SELECT rendermode */
    struct draw_stage *rastpos_stage;  /**< For glRasterPos */
    GLboolean sw_primitive_restart;
+   GLboolean clamp_frag_color_in_shader;
+   GLboolean clamp_vert_color_in_shader;
 
 
    /* On old libGL's for linux we need to invalidate the drawables
index 49c874710bdc0454c1f5fc8adc92bf90cae6fd27..1f3b59fc67eb94562db492dad6c0cd225321e3ec 100644 (file)
@@ -607,33 +607,16 @@ void st_init_extensions(struct st_context *st)
       ctx->Extensions.ARB_depth_clamp = GL_TRUE;
    }
 
-   /* This extension does not actually require support of floating point
-    * render targets, just clamping controls.
-    * Advertise this extension if either fragment color clamping is supported
-    * or no render targets having color values outside of the range [0, 1]
-    * are supported, in which case the fragment color clamping has no effect
-    * on rendering.
-    */
-   if (screen->get_param(screen, PIPE_CAP_FRAGMENT_COLOR_CLAMP_CONTROL) ||
-       (!screen->is_format_supported(screen, PIPE_FORMAT_R8G8B8A8_SNORM,
-                                     PIPE_TEXTURE_2D, 0,
-                                     PIPE_BIND_RENDER_TARGET) &&
-        !screen->is_format_supported(screen, PIPE_FORMAT_R16G16B16A16_SNORM,
-                                     PIPE_TEXTURE_2D, 0,
-                                     PIPE_BIND_RENDER_TARGET) &&
-        !screen->is_format_supported(screen, PIPE_FORMAT_R16G16B16A16_FLOAT,
-                                     PIPE_TEXTURE_2D, 0,
-                                     PIPE_BIND_RENDER_TARGET) &&
-        !screen->is_format_supported(screen, PIPE_FORMAT_R32G32B32A32_FLOAT,
-                                     PIPE_TEXTURE_2D, 0,
-                                     PIPE_BIND_RENDER_TARGET) &&
-        !screen->is_format_supported(screen, PIPE_FORMAT_R11G11B10_FLOAT,
-                                     PIPE_TEXTURE_2D, 0,
-                                     PIPE_BIND_RENDER_TARGET) &&
-        !screen->is_format_supported(screen, PIPE_FORMAT_R9G9B9E5_FLOAT,
-                                     PIPE_TEXTURE_2D, 0,
-                                     PIPE_BIND_RENDER_TARGET))) {
+   if (screen->get_param(screen, PIPE_CAP_VERTEX_COLOR_UNCLAMPED)) {
       ctx->Extensions.ARB_color_buffer_float = GL_TRUE;
+
+      if (!screen->get_param(screen, PIPE_CAP_VERTEX_COLOR_CLAMPED)) {
+         st->clamp_vert_color_in_shader = TRUE;
+      }
+
+      if (!screen->get_param(screen, PIPE_CAP_FRAGMENT_COLOR_CLAMPED)) {
+         st->clamp_frag_color_in_shader = TRUE;
+      }
    }
 
    if (screen->get_param(screen, PIPE_CAP_SHADER_STENCIL_EXPORT)) {
index 92dffe258660e0a4c3bcf738123fd5d18498bc43..188e8d9d5c922caf5abc924d9dbe764d5273a9e4 100644 (file)
@@ -4055,7 +4055,7 @@ src_register(struct st_translate *t,
 static struct ureg_dst
 translate_dst(struct st_translate *t,
               const st_dst_reg *dst_reg,
-              bool saturate)
+              bool saturate, bool clamp_color)
 {
    struct ureg_dst dst = dst_register(t, 
                                       dst_reg->file,
@@ -4065,6 +4065,27 @@ translate_dst(struct st_translate *t,
    
    if (saturate)
       dst = ureg_saturate(dst);
+   else if (clamp_color && dst_reg->file == PROGRAM_OUTPUT) {
+      /* Clamp colors for ARB_color_buffer_float. */
+      switch (t->procType) {
+      case TGSI_PROCESSOR_VERTEX:
+         /* XXX if the geometry shader is present, this must be done there
+          * instead of here. */
+         if (dst_reg->index == VERT_RESULT_COL0 ||
+             dst_reg->index == VERT_RESULT_COL1 ||
+             dst_reg->index == VERT_RESULT_BFC0 ||
+             dst_reg->index == VERT_RESULT_BFC1) {
+            dst = ureg_saturate(dst);
+         }
+         break;
+
+      case TGSI_PROCESSOR_FRAGMENT:
+         if (dst_reg->index >= FRAG_RESULT_COLOR) {
+            dst = ureg_saturate(dst);
+         }
+         break;
+      }
+   }
 
    if (dst_reg->reladdr != NULL)
       dst = ureg_dst_indirect(dst, ureg_src(t->address[0]));
@@ -4134,7 +4155,8 @@ translate_tex_offset(struct st_translate *t,
 
 static void
 compile_tgsi_instruction(struct st_translate *t,
-                         const glsl_to_tgsi_instruction *inst)
+                         const glsl_to_tgsi_instruction *inst,
+                         bool clamp_dst_color_output)
 {
    struct ureg_program *ureg = t->ureg;
    GLuint i;
@@ -4151,7 +4173,8 @@ compile_tgsi_instruction(struct st_translate *t,
    if (num_dst) 
       dst[0] = translate_dst(t, 
                              &inst->dst,
-                             inst->saturate);
+                             inst->saturate,
+                             clamp_dst_color_output);
 
    for (i = 0; i < num_src; i++) 
       src[i] = translate_src(t, &inst->src[i]);
@@ -4457,7 +4480,8 @@ st_translate_program(
    const GLuint outputMapping[],
    const ubyte outputSemanticName[],
    const ubyte outputSemanticIndex[],
-   boolean passthrough_edgeflags)
+   boolean passthrough_edgeflags,
+   boolean clamp_color)
 {
    struct st_translate *t;
    unsigned i;
@@ -4697,7 +4721,8 @@ st_translate_program(
     */
    foreach_iter(exec_list_iterator, iter, program->instructions) {
       set_insn_start(t, ureg_get_instruction_number(ureg));
-      compile_tgsi_instruction(t, (glsl_to_tgsi_instruction *)iter.get());
+      compile_tgsi_instruction(t, (glsl_to_tgsi_instruction *)iter.get(),
+                               clamp_color);
 
       if (t->prevInstWrotePointSize && proginfo->Id) {
          /* The previous instruction wrote to the (fake) vertex point size
index 1f71f33fd47899bd803947e776db6a664a2c1f7c..55d59d571bbb31f1cb64c5538f3a228588bce343 100644 (file)
@@ -49,7 +49,8 @@ enum pipe_error st_translate_program(
    const GLuint outputMapping[],
    const ubyte outputSemanticName[],
    const ubyte outputSemanticIndex[],
-   boolean passthrough_edgeflags);
+   boolean passthrough_edgeflags,
+   boolean clamp_color);
 
 void free_glsl_to_tgsi_visitor(struct glsl_to_tgsi_visitor *v);
 void get_pixel_transfer_visitor(struct st_fragment_program *fp,
index 0764234bd4b164ae6b9f19e121cf23ebfd6d739b..fc77089e7333dea27bf762547830236c47fe344f 100644 (file)
@@ -306,7 +306,8 @@ st_translate_texture_target( GLuint textarget,
 static struct ureg_dst
 translate_dst( struct st_translate *t,
                const struct prog_dst_register *DstReg,
-               boolean saturate )
+               boolean saturate,
+               boolean clamp_color)
 {
    struct ureg_dst dst = dst_register( t, 
                                        DstReg->File,
@@ -317,6 +318,27 @@ translate_dst( struct st_translate *t,
    
    if (saturate)
       dst = ureg_saturate( dst );
+   else if (clamp_color && DstReg->File == PROGRAM_OUTPUT) {
+      /* Clamp colors for ARB_color_buffer_float. */
+      switch (t->procType) {
+      case TGSI_PROCESSOR_VERTEX:
+         /* XXX if the geometry shader is present, this must be done there
+          * instead of here. */
+         if (DstReg->Index == VERT_RESULT_COL0 ||
+             DstReg->Index == VERT_RESULT_COL1 ||
+             DstReg->Index == VERT_RESULT_BFC0 ||
+             DstReg->Index == VERT_RESULT_BFC1) {
+            dst = ureg_saturate(dst);
+         }
+         break;
+
+      case TGSI_PROCESSOR_FRAGMENT:
+         if (DstReg->Index >= FRAG_RESULT_COLOR) {
+            dst = ureg_saturate(dst);
+         }
+         break;
+      }
+   }
 
    if (DstReg->RelAddr)
       dst = ureg_dst_indirect( dst, ureg_src(t->address[0]) );
@@ -662,7 +684,8 @@ translate_opcode( unsigned op )
 static void
 compile_instruction(
    struct st_translate *t,
-   const struct prog_instruction *inst )
+   const struct prog_instruction *inst,
+   boolean clamp_dst_color_output)
 {
    struct ureg_program *ureg = t->ureg;
    GLuint i;
@@ -677,7 +700,8 @@ compile_instruction(
    if (num_dst) 
       dst[0] = translate_dst( t, 
                               &inst->DstReg,
-                              inst->SaturateMode );
+                              inst->SaturateMode,
+                              clamp_dst_color_output);
 
    for (i = 0; i < num_src; i++) 
       src[i] = translate_src( t, &inst->SrcReg[i] );
@@ -1016,7 +1040,8 @@ st_translate_mesa_program(
    const GLuint outputMapping[],
    const ubyte outputSemanticName[],
    const ubyte outputSemanticIndex[],
-   boolean passthrough_edgeflags )
+   boolean passthrough_edgeflags,
+   boolean clamp_color)
 {
    struct st_translate translate, *t;
    unsigned i;
@@ -1233,7 +1258,7 @@ st_translate_mesa_program(
     */
    for (i = 0; i < program->NumInstructions; i++) {
       set_insn_start( t, ureg_get_instruction_number( ureg ));
-      compile_instruction( t, &program->Instructions[i] );
+      compile_instruction( t, &program->Instructions[i], clamp_color );
 
       if (t->prevInstWrotePointSize && program->Id) {
          /* The previous instruction wrote to the (fake) vertex point size
index 7563c8050e350e8ed8399ffa9069cdcd0e595b05..7e1a5abdc60748b8e234c69d680b5f8f86f5ff3f 100644 (file)
@@ -59,7 +59,8 @@ st_translate_mesa_program(
    const GLuint outputMapping[],
    const ubyte outputSemanticName[],
    const ubyte outputSemanticIndex[],
-   boolean passthrough_edgeflags );
+   boolean passthrough_edgeflags,
+   boolean clamp_color);
 
 void
 st_free_tokens(const struct tgsi_token *tokens);
index 8d08b2b0f312ca425505279fa5b94a55b1828937..3ae79ddbf4bd19c576a8626ad646af2d3addc3b0 100644 (file)
@@ -351,7 +351,8 @@ st_translate_vertex_program(struct st_context *st,
                                    stvp->result_to_output,
                                    stvp->output_semantic_name,
                                    stvp->output_semantic_index,
-                                   key->passthrough_edgeflags );
+                                   key->passthrough_edgeflags,
+                                   key->clamp_color);
    else
       error = st_translate_mesa_program(st->ctx,
                                         TGSI_PROCESSOR_VERTEX,
@@ -368,7 +369,8 @@ st_translate_vertex_program(struct st_context *st,
                                         stvp->result_to_output,
                                         stvp->output_semantic_name,
                                         stvp->output_semantic_index,
-                                        key->passthrough_edgeflags );
+                                        key->passthrough_edgeflags,
+                                        key->clamp_color);
 
    if (error)
       goto fail;
@@ -505,7 +507,8 @@ st_translate_fragment_program(struct st_context *st,
    }
 #endif
 
-   if (!stfp->tgsi.tokens) {
+   /* XXX this will be cleaned up in the following commit */
+   if (1) {
       /* need to translate Mesa instructions to TGSI now */
       GLuint outputMapping[FRAG_RESULT_MAX];
       GLuint inputMapping[FRAG_ATTRIB_MAX];
@@ -718,7 +721,8 @@ st_translate_fragment_program(struct st_context *st,
                               fs_num_outputs,
                               outputMapping,
                               fs_output_semantic_name,
-                              fs_output_semantic_index, FALSE );
+                              fs_output_semantic_index, FALSE,
+                              key->clamp_color );
       else
          st_translate_mesa_program(st->ctx,
                                    TGSI_PROCESSOR_FRAGMENT,
@@ -734,7 +738,8 @@ st_translate_fragment_program(struct st_context *st,
                                    fs_num_outputs,
                                    outputMapping,
                                    fs_output_semantic_name,
-                                   fs_output_semantic_index, FALSE );
+                                   fs_output_semantic_index, FALSE,
+                                   key->clamp_color);
 
       stfp->tgsi.tokens = ureg_get_tokens( ureg, NULL );
       ureg_destroy( ureg );
@@ -1022,6 +1027,7 @@ st_translate_geometry_program(struct st_context *st,
                              outputMapping,
                              gs_output_semantic_name,
                              gs_output_semantic_index,
+                             FALSE,
                              FALSE);
 
    stgp->num_inputs = gs_num_inputs;
index 699b6e8ccb770c2e7e516f6c7ff3106371a61510..0ae3420ecb4008e90062465c3a2fd7bcfb862b45 100644 (file)
@@ -55,6 +55,9 @@ struct st_fp_variant_key
    GLuint pixelMaps:1;            /**< glDrawPixels w/ pixel lookup map? */
    GLuint drawpixels_z:1;         /**< glDrawPixels(GL_DEPTH) */
    GLuint drawpixels_stencil:1;   /**< glDrawPixels(GL_STENCIL) */
+
+   /** for ARB_color_buffer_float */
+   GLuint clamp_color:1;
 };
 
 
@@ -98,6 +101,9 @@ struct st_vp_variant_key
 {
    struct st_context *st;          /**< variants are per-context */
    boolean passthrough_edgeflags;
+
+   /** for ARB_color_buffer_float */
+   boolean clamp_color;
 };