diff options
| author | Brian Paul <brianp@vmware.com> | 2010-09-17 18:41:30 -0600 | 
|---|---|---|
| committer | Brian Paul <brianp@vmware.com> | 2010-09-17 18:45:13 -0600 | 
| commit | e22e3927b056806e9bbb089734132ad0bcb98df1 (patch) | |
| tree | 54e1a8fcdec93e315f9c04afefadedd43cc7877d /src | |
| parent | 49cb978aa46af0d86ab609013d7883c8105a6d1d (diff) | |
gallium: rework handling of sprite_coord_enable state
Implement the pipe_rasterizer_state::sprite_coord_enable field
in the draw module (and softpipe) according to what's specified
in the documentation.
The draw module can now add any number of extra vertex attributes
to a post-transformed vertex and generate texcoords for those
attributes per sprite_coord_enable.  Auto-generated texcoords
for sprites only worked for one texcoord unit before.
The frag shader gl_PointCoord input is now implemented like any
other generic/texcoord attribute.
The draw module now needs to be informed about fragment shaders
since we need to look at the fragment shader's inputs to know
which ones need auto-generated texcoords.
Only softpipe has been updated so far.
Diffstat (limited to 'src')
| -rw-r--r-- | src/gallium/auxiliary/Makefile | 1 | ||||
| -rw-r--r-- | src/gallium/auxiliary/SConscript | 1 | ||||
| -rw-r--r-- | src/gallium/auxiliary/draw/draw_context.c | 56 | ||||
| -rw-r--r-- | src/gallium/auxiliary/draw/draw_context.h | 12 | ||||
| -rw-r--r-- | src/gallium/auxiliary/draw/draw_pipe_aaline.c | 9 | ||||
| -rw-r--r-- | src/gallium/auxiliary/draw/draw_pipe_aapoint.c | 8 | ||||
| -rw-r--r-- | src/gallium/auxiliary/draw/draw_pipe_wide_point.c | 114 | ||||
| -rw-r--r-- | src/gallium/auxiliary/draw/draw_private.h | 17 | ||||
| -rw-r--r-- | src/gallium/drivers/softpipe/sp_state.h | 2 | ||||
| -rw-r--r-- | src/gallium/drivers/softpipe/sp_state_fs.c | 15 | ||||
| -rw-r--r-- | src/mesa/state_tracker/st_atom_rasterizer.c | 14 | ||||
| -rw-r--r-- | src/mesa/state_tracker/st_program.c | 17 | 
12 files changed, 172 insertions, 94 deletions
| diff --git a/src/gallium/auxiliary/Makefile b/src/gallium/auxiliary/Makefile index 2de764c4ee..f05538bbac 100644 --- a/src/gallium/auxiliary/Makefile +++ b/src/gallium/auxiliary/Makefile @@ -8,6 +8,7 @@ C_SOURCES = \  	cso_cache/cso_context.c \  	cso_cache/cso_hash.c \  	draw/draw_context.c \ +	draw/draw_fs.c \  	draw/draw_gs.c \  	draw/draw_pipe.c \  	draw/draw_pipe_aaline.c \ diff --git a/src/gallium/auxiliary/SConscript b/src/gallium/auxiliary/SConscript index 294df30094..baaa26fea9 100644 --- a/src/gallium/auxiliary/SConscript +++ b/src/gallium/auxiliary/SConscript @@ -54,6 +54,7 @@ source = [      'cso_cache/cso_context.c',      'cso_cache/cso_hash.c',      'draw/draw_context.c', +    'draw/draw_fs.c',      'draw/draw_gs.c',      'draw/draw_pipe.c',      'draw/draw_pipe_aaline.c', diff --git a/src/gallium/auxiliary/draw/draw_context.c b/src/gallium/auxiliary/draw/draw_context.c index 937b093479..b07de76a49 100644 --- a/src/gallium/auxiliary/draw/draw_context.c +++ b/src/gallium/auxiliary/draw/draw_context.c @@ -413,6 +413,42 @@ draw_set_force_passthrough( struct draw_context *draw, boolean enable )  } + +/** + * Allocate an extra vertex/geometry shader vertex attribute. + * This is used by some of the optional draw module stages such + * as wide_point which may need to allocate additional generic/texcoord + * attributes. + */ +int +draw_alloc_extra_vertex_attrib(struct draw_context *draw, +                               uint semantic_name, uint semantic_index) +{ +   const int num_outputs = draw_current_shader_outputs(draw); +   const int n = draw->extra_shader_outputs.num; + +   assert(n < Elements(draw->extra_shader_outputs.semantic_name)); + +   draw->extra_shader_outputs.semantic_name[n] = semantic_name; +   draw->extra_shader_outputs.semantic_index[n] = semantic_index; +   draw->extra_shader_outputs.slot[n] = num_outputs + n; +   draw->extra_shader_outputs.num++; + +   return draw->extra_shader_outputs.slot[n]; +} + + +/** + * Remove all extra vertex attributes that were allocated with + * draw_alloc_extra_vertex_attrib(). + */ +void +draw_remove_extra_vertex_attribs(struct draw_context *draw) +{ +   draw->extra_shader_outputs.num = 0; +} + +  /**   * Ask the draw module for the location/slot of the given vertex attribute in   * a post-transformed vertex. @@ -446,12 +482,12 @@ draw_find_shader_output(const struct draw_context *draw,           return i;     } -   /* XXX there may be more than one extra vertex attrib. -    * For example, simulated gl_FragCoord and gl_PointCoord. -    */ -   if (draw->extra_shader_outputs.semantic_name == semantic_name && -       draw->extra_shader_outputs.semantic_index == semantic_index) { -      return draw->extra_shader_outputs.slot; +   /* Search the extra vertex attributes */ +   for (i = 0; i < draw->extra_shader_outputs.num; i++) { +      if (draw->extra_shader_outputs.semantic_name[i] == semantic_name && +          draw->extra_shader_outputs.semantic_index[i] == semantic_index) { +         return draw->extra_shader_outputs.slot[i]; +      }     }     return 0; @@ -470,16 +506,18 @@ draw_find_shader_output(const struct draw_context *draw,  uint  draw_num_shader_outputs(const struct draw_context *draw)  { -   uint count = draw->vs.vertex_shader->info.num_outputs; +   uint count;     /* If a geometry shader is present, its outputs go to the      * driver, else the vertex shader's outputs.      */     if (draw->gs.geometry_shader)        count = draw->gs.geometry_shader->info.num_outputs; +   else +      count = draw->vs.vertex_shader->info.num_outputs; + +   count += draw->extra_shader_outputs.num; -   if (draw->extra_shader_outputs.slot > 0) -      count++;     return count;  } diff --git a/src/gallium/auxiliary/draw/draw_context.h b/src/gallium/auxiliary/draw/draw_context.h index 4f0d30123a..1f27cbf488 100644 --- a/src/gallium/auxiliary/draw/draw_context.h +++ b/src/gallium/auxiliary/draw/draw_context.h @@ -46,6 +46,7 @@ struct draw_context;  struct draw_stage;  struct draw_vertex_shader;  struct draw_geometry_shader; +struct draw_fragment_shader;  struct tgsi_sampler;  #define DRAW_MAX_TEXTURE_LEVELS 13  /* 4K x 4K for now */ @@ -138,6 +139,17 @@ void draw_delete_vertex_shader(struct draw_context *draw,  /* + * Fragment shader functions + */ +struct draw_fragment_shader * +draw_create_fragment_shader(struct draw_context *draw, +                            const struct pipe_shader_state *shader); +void draw_bind_fragment_shader(struct draw_context *draw, +                               struct draw_fragment_shader *dvs); +void draw_delete_fragment_shader(struct draw_context *draw, +                                 struct draw_fragment_shader *dvs); + +/*   * Geometry shader functions   */  struct draw_geometry_shader * diff --git a/src/gallium/auxiliary/draw/draw_pipe_aaline.c b/src/gallium/auxiliary/draw/draw_pipe_aaline.c index eac21110be..d1aba76309 100644 --- a/src/gallium/auxiliary/draw/draw_pipe_aaline.c +++ b/src/gallium/auxiliary/draw/draw_pipe_aaline.c @@ -688,10 +688,9 @@ aaline_first_line(struct draw_stage *stage, struct prim_header *header)     aaline->tex_slot = draw_current_shader_outputs(draw);     aaline->pos_slot = draw_current_shader_position_output(draw);; -   /* advertise the extra post-transformed vertex attribute */ -   draw->extra_shader_outputs.semantic_name = TGSI_SEMANTIC_GENERIC; -   draw->extra_shader_outputs.semantic_index = aaline->fs->generic_attrib; -   draw->extra_shader_outputs.slot = aaline->tex_slot; +   /* allocate the extra post-transformed vertex attribute */ +   (void) draw_alloc_extra_vertex_attrib(draw, TGSI_SEMANTIC_GENERIC, +                                         aaline->fs->generic_attrib);     /* how many samplers? */     /* we'll use sampler/texture[pstip->sampler_unit] for the stipple */ @@ -744,7 +743,7 @@ aaline_flush(struct draw_stage *stage, unsigned flags)     draw->suspend_flushing = FALSE; -   draw->extra_shader_outputs.slot = 0; +   draw_remove_extra_vertex_attribs(draw);  } diff --git a/src/gallium/auxiliary/draw/draw_pipe_aapoint.c b/src/gallium/auxiliary/draw/draw_pipe_aapoint.c index d406a86ccb..5ea552f51c 100644 --- a/src/gallium/auxiliary/draw/draw_pipe_aapoint.c +++ b/src/gallium/auxiliary/draw/draw_pipe_aapoint.c @@ -701,9 +701,9 @@ aapoint_first_point(struct draw_stage *stage, struct prim_header *header)     aapoint->pos_slot = draw_current_shader_position_output(draw); -   draw->extra_shader_outputs.semantic_name = TGSI_SEMANTIC_GENERIC; -   draw->extra_shader_outputs.semantic_index = aapoint->fs->generic_attrib; -   draw->extra_shader_outputs.slot = aapoint->tex_slot; +   /* allocate the extra post-transformed vertex attribute */ +   (void) draw_alloc_extra_vertex_attrib(draw, TGSI_SEMANTIC_GENERIC, +                                         aapoint->fs->generic_attrib);     /* find psize slot in post-transform vertex */     aapoint->psize_slot = -1; @@ -754,7 +754,7 @@ aapoint_flush(struct draw_stage *stage, unsigned flags)     draw->suspend_flushing = FALSE; -   draw->extra_shader_outputs.slot = 0; +   draw_remove_extra_vertex_attribs(draw);  } diff --git a/src/gallium/auxiliary/draw/draw_pipe_wide_point.c b/src/gallium/auxiliary/draw/draw_pipe_wide_point.c index ee2945c7c9..40843c58c2 100644 --- a/src/gallium/auxiliary/draw/draw_pipe_wide_point.c +++ b/src/gallium/auxiliary/draw/draw_pipe_wide_point.c @@ -57,26 +57,24 @@  #include "util/u_memory.h"  #include "pipe/p_defines.h"  #include "pipe/p_shader_tokens.h" +#include "draw_fs.h"  #include "draw_vs.h"  #include "draw_pipe.h"  struct widepoint_stage { -   struct draw_stage stage; +   struct draw_stage stage;  /**< base class */     float half_point_size;     float xbias;     float ybias; -   uint texcoord_slot[PIPE_MAX_SHADER_OUTPUTS]; -   uint texcoord_enable[PIPE_MAX_SHADER_OUTPUTS]; -   uint num_texcoords; -   uint texcoord_mode; +   /** for automatic texcoord generation/replacement */ +   uint num_texcoord_gen; +   uint texcoord_gen_slot[PIPE_MAX_SHADER_OUTPUTS];     int psize_slot; - -   int point_coord_fs_input;  /**< input for pointcoord */  }; @@ -96,30 +94,20 @@ widepoint_stage( struct draw_stage *stage )  static void set_texcoords(const struct widepoint_stage *wide,                            struct vertex_header *v, const float tc[4])  { +   const struct draw_context *draw = wide->stage.draw; +   const struct pipe_rasterizer_state *rast = draw->rasterizer; +   const uint texcoord_mode = rast->sprite_coord_mode;     uint i; -   for (i = 0; i < wide->num_texcoords; i++) { -      if (wide->texcoord_enable[i]) { -         uint j = wide->texcoord_slot[i]; -         v->data[j][0] = tc[0]; -         if (wide->texcoord_mode == PIPE_SPRITE_COORD_LOWER_LEFT) -            v->data[j][1] = 1.0f - tc[1]; -         else -            v->data[j][1] = tc[1]; -         v->data[j][2] = tc[2]; -         v->data[j][3] = tc[3]; -      } -   } -   if (wide->point_coord_fs_input >= 0) { -      /* put gl_PointCoord into the extra vertex slot */ -      uint slot = wide->stage.draw->extra_shader_outputs.slot; +   for (i = 0; i < wide->num_texcoord_gen; i++) { +      const uint slot = wide->texcoord_gen_slot[i];        v->data[slot][0] = tc[0]; -      if (wide->texcoord_mode == PIPE_SPRITE_COORD_LOWER_LEFT) +      if (texcoord_mode == PIPE_SPRITE_COORD_LOWER_LEFT)           v->data[slot][1] = 1.0f - tc[1];        else           v->data[slot][1] = tc[1]; -      v->data[slot][2] = 0.0F; -      v->data[slot][3] = 1.0F; +      v->data[slot][2] = tc[2]; +      v->data[slot][3] = tc[3];     }  } @@ -201,18 +189,9 @@ static void widepoint_point( struct draw_stage *stage,  } -static int -find_pntc_input_attrib(struct draw_context *draw) -{ -   /* Scan the fragment program's input decls to find the pointcoord -    * attribute.  The xy components will store the point coord. -    */ -   return 0; /* XXX fix this */ -} - - -static void widepoint_first_point( struct draw_stage *stage,  -			      struct prim_header *header ) +static void +widepoint_first_point(struct draw_stage *stage,  +                      struct prim_header *header)  {     struct widepoint_stage *wide = widepoint_stage(stage);     struct draw_context *draw = stage->draw; @@ -244,31 +223,45 @@ static void widepoint_first_point( struct draw_stage *stage,        stage->point = draw_pipe_passthrough_point;     } +   draw_remove_extra_vertex_attribs(draw); +     if (rast->point_quad_rasterization) { -      /* find vertex shader texcoord outputs */ -      const struct draw_vertex_shader *vs = draw->vs.vertex_shader; -      uint i, j = 0; -      wide->texcoord_mode = rast->sprite_coord_mode; -      for (i = 0; i < vs->info.num_outputs; i++) { -         if (vs->info.output_semantic_name[i] == TGSI_SEMANTIC_GENERIC) { -            wide->texcoord_slot[j] = i; -            wide->texcoord_enable[j] = (rast->sprite_coord_enable >> j) & 1; -            j++; -         } -      } -      wide->num_texcoords = j; +      const struct draw_fragment_shader *fs = draw->fs.fragment_shader; +      uint i; -      /* find fragment shader PointCoord input */ -      wide->point_coord_fs_input = find_pntc_input_attrib(draw); +      wide->num_texcoord_gen = 0; -      /* setup extra vp output (point coord implemented as a texcoord) */ -      draw->extra_shader_outputs.semantic_name = TGSI_SEMANTIC_GENERIC; -      draw->extra_shader_outputs.semantic_index = 0; -      draw->extra_shader_outputs.slot = draw_current_shader_outputs(draw); -   } -   else { -      wide->point_coord_fs_input = -1; -      draw->extra_shader_outputs.slot = 0; +      /* Loop over fragment shader inputs looking for generic inputs +       * for which bit 'k' in sprite_coord_enable is set. +       */ +      for (i = 0; i < fs->info.num_inputs; i++) { +         if (fs->info.input_semantic_name[i] == TGSI_SEMANTIC_GENERIC) { +            const int generic_index = fs->info.input_semantic_index[i]; +            if (rast->sprite_coord_enable & (1 << generic_index)) { +               /* OK, this generic attribute needs to be replaced with a +                * texcoord (see above). +                */ +               int slot = draw_find_shader_output(draw, +                                                  TGSI_SEMANTIC_GENERIC, +                                                  generic_index); + +               if (slot > 0) { +                  /* there's already a post-vertex shader attribute +                   * for this fragment shader input attribute. +                   */ +               } +               else { +                  /* need to allocate a new post-vertex shader attribute */ +                  slot = draw_alloc_extra_vertex_attrib(draw, +                                                        TGSI_SEMANTIC_GENERIC, +                                                        generic_index); +               } + +               /* add this slot to the texcoord-gen list */ +               wide->texcoord_gen_slot[wide->num_texcoord_gen++] = slot; +            } +         } +      }     }     wide->psize_slot = -1; @@ -295,7 +288,8 @@ static void widepoint_flush( struct draw_stage *stage, unsigned flags )     stage->point = widepoint_first_point;     stage->next->flush( stage->next, flags ); -   stage->draw->extra_shader_outputs.slot = 0; + +   draw_remove_extra_vertex_attribs(draw);     /* restore original rasterizer state */     if (draw->rast_handle) { diff --git a/src/gallium/auxiliary/draw/draw_private.h b/src/gallium/auxiliary/draw/draw_private.h index 362f563ba6..d417f825a0 100644 --- a/src/gallium/auxiliary/draw/draw_private.h +++ b/src/gallium/auxiliary/draw/draw_private.h @@ -250,6 +250,11 @@ struct draw_context        struct tgsi_sampler **samplers;     } gs; +   /** Fragment shader state */ +   struct { +      struct draw_fragment_shader *fragment_shader; +   } fs; +     /** Stream output (vertex feedback) state */     struct {        struct pipe_stream_output_state state; @@ -266,9 +271,10 @@ struct draw_context     /* If a prim stage introduces new vertex attributes, they'll be stored here      */     struct { -      uint semantic_name; -      uint semantic_index; -      int slot; +      uint num; +      uint semantic_name[10]; +      uint semantic_index[10]; +      uint slot[10];     } extra_shader_outputs;     unsigned reduced_prim; @@ -362,6 +368,11 @@ void draw_gs_destroy( struct draw_context *draw );  uint draw_current_shader_outputs(const struct draw_context *draw);  uint draw_current_shader_position_output(const struct draw_context *draw); +int draw_alloc_extra_vertex_attrib(struct draw_context *draw, +                                   uint semantic_name, uint semantic_index); +void draw_remove_extra_vertex_attribs(struct draw_context *draw); + +  /*******************************************************************************   * Vertex processing (was passthrough) code:   */ diff --git a/src/gallium/drivers/softpipe/sp_state.h b/src/gallium/drivers/softpipe/sp_state.h index 39d204de8a..c5d61f840f 100644 --- a/src/gallium/drivers/softpipe/sp_state.h +++ b/src/gallium/drivers/softpipe/sp_state.h @@ -70,6 +70,8 @@ struct sp_fragment_shader {     struct tgsi_shader_info info; +   struct draw_fragment_shader *draw_shader; +     boolean origin_lower_left; /**< fragment shader uses lower left position origin? */     boolean pixel_center_integer; /**< fragment shader uses integer pixel center? */ diff --git a/src/gallium/drivers/softpipe/sp_state_fs.c b/src/gallium/drivers/softpipe/sp_state_fs.c index ded242d3dc..50bc2eea5f 100644 --- a/src/gallium/drivers/softpipe/sp_state_fs.c +++ b/src/gallium/drivers/softpipe/sp_state_fs.c @@ -60,7 +60,15 @@ softpipe_create_fs_state(struct pipe_context *pipe,        state = softpipe_create_fs_exec( softpipe, templ );     } -   assert(state); +   if (!state) +      return NULL; + +   /* draw's fs state */ +   state->draw_shader = draw_create_fragment_shader(softpipe->draw, templ); +   if (!state->draw_shader) { +      state->delete( state ); +      return NULL; +   }     /* get/save the summary info for this shader */     tgsi_scan_shader(templ->tokens, &state->info); @@ -90,6 +98,9 @@ softpipe_bind_fs_state(struct pipe_context *pipe, void *fs)     softpipe->fs = fs; +   draw_bind_fragment_shader(softpipe->draw, +                             (softpipe->fs ? softpipe->fs->draw_shader : NULL)); +     softpipe->dirty |= SP_NEW_FS;  } @@ -109,6 +120,8 @@ softpipe_delete_fs_state(struct pipe_context *pipe, void *fs)        tgsi_exec_machine_bind_shader(softpipe->fs_machine, NULL, 0, NULL);     } +   draw_delete_fragment_shader(softpipe->draw, state->draw_shader); +     state->delete( state );  } diff --git a/src/mesa/state_tracker/st_atom_rasterizer.c b/src/mesa/state_tracker/st_atom_rasterizer.c index 2599bd5ca0..0fe333ae8a 100644 --- a/src/mesa/state_tracker/st_atom_rasterizer.c +++ b/src/mesa/state_tracker/st_atom_rasterizer.c @@ -60,6 +60,7 @@ static void update_raster_state( struct st_context *st )     GLcontext *ctx = st->ctx;     struct pipe_rasterizer_state *raster = &st->state.rasterizer;     const struct gl_vertex_program *vertProg = ctx->VertexProgram._Current; +   const struct gl_fragment_program *fragProg = ctx->FragmentProgram._Current;     uint i;     memset(raster, 0, sizeof(*raster)); @@ -175,17 +176,30 @@ static void update_raster_state( struct st_context *st )     if (!ctx->Point.PointSprite && ctx->Point.SmoothFlag)        raster->point_smooth = 1; +   /* _NEW_POINT | _NEW_PROGRAM +    */     if (ctx->Point.PointSprite) { +      /* origin */        if ((ctx->Point.SpriteOrigin == GL_UPPER_LEFT) ^            (st_fb_orientation(ctx->DrawBuffer) == Y_0_BOTTOM))           raster->sprite_coord_mode = PIPE_SPRITE_COORD_UPPER_LEFT;        else            raster->sprite_coord_mode = PIPE_SPRITE_COORD_LOWER_LEFT; + +      /* Coord replacement flags.  If bit 'k' is set that means +       * that we need to replace GENERIC[k] attrib with an automatically +       * computed texture coord. +       */        for (i = 0; i < MAX_TEXTURE_COORD_UNITS; i++) {           if (ctx->Point.CoordReplace[i]) {              raster->sprite_coord_enable |= 1 << i;           }        } +      if (fragProg->Base.InputsRead & FRAG_BIT_PNTC) { +         raster->sprite_coord_enable |= +            1 << (FRAG_ATTRIB_PNTC - FRAG_ATTRIB_TEX0); +      } +        raster->point_quad_rasterization = 1;     } diff --git a/src/mesa/state_tracker/st_program.c b/src/mesa/state_tracker/st_program.c index 8c2d8b6154..18a7bbe0f9 100644 --- a/src/mesa/state_tracker/st_program.c +++ b/src/mesa/state_tracker/st_program.c @@ -338,17 +338,6 @@ st_translate_fragment_program(struct st_context *st,              input_semantic_index[slot] = 0;              interpMode[slot] = TGSI_INTERPOLATE_CONSTANT;              break; -         case FRAG_ATTRIB_PNTC: -            /* This is a hack.  We really need a new semantic label for -             * point coord.  The draw module needs to know which fragment -             * shader input is the point coord attribute so that it can set -             * up the right vertex attribute values. -             */ -            input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC; -            input_semantic_index[slot] = 0; -            interpMode[slot] = TGSI_INTERPOLATE_PERSPECTIVE; -            break; -              /* In most cases, there is nothing special about these               * inputs, so adopt a convention to use the generic               * semantic name and the mesa FRAG_ATTRIB_ number as the @@ -364,6 +353,7 @@ st_translate_fragment_program(struct st_context *st,               * zero or be restricted to a particular range -- nobody               * should be building tables based on semantic index.               */ +         case FRAG_ATTRIB_PNTC:           case FRAG_ATTRIB_TEX0:           case FRAG_ATTRIB_TEX1:           case FRAG_ATTRIB_TEX2: @@ -380,7 +370,10 @@ st_translate_fragment_program(struct st_context *st,              assert(attr >= FRAG_ATTRIB_TEX0);              input_semantic_index[slot] = (attr - FRAG_ATTRIB_TEX0);              input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC; -            interpMode[slot] = TGSI_INTERPOLATE_PERSPECTIVE; +            if (attr == FRAG_ATTRIB_PNTC) +               interpMode[slot] = TGSI_INTERPOLATE_LINEAR; +            else +               interpMode[slot] = TGSI_INTERPOLATE_PERSPECTIVE;              break;           }        } | 
