Merge branch 'gallium-edgeflags'
authorRoland Scheidegger <sroland@vmware.com>
Tue, 22 Dec 2009 19:54:26 +0000 (20:54 +0100)
committerRoland Scheidegger <sroland@vmware.com>
Tue, 22 Dec 2009 19:54:26 +0000 (20:54 +0100)
Conflicts:
src/mesa/state_tracker/st_draw.c

12 files changed:
1  2 
src/gallium/auxiliary/tgsi/tgsi_dump.c
src/gallium/auxiliary/tgsi/tgsi_scan.c
src/gallium/auxiliary/tgsi/tgsi_scan.h
src/gallium/drivers/nv30/nv30_context.h
src/gallium/drivers/nv40/nv40_context.h
src/gallium/drivers/nv40/nv40_state_emit.c
src/gallium/drivers/r300/r300_state.c
src/gallium/drivers/r300/r300_vs.c
src/gallium/drivers/svga/svga_context.h
src/gallium/include/pipe/p_shader_tokens.h
src/mesa/state_tracker/st_draw.c
src/mesa/state_tracker/st_program.c

index ba1357697d1041da2f4ce643804ef41b94caa59c,d3a5da4b2b0afbb75704800c61169944acbdfc42..5e7e5d2ff9c9b31489385a68a3489ad15f82e21f
@@@ -101,8 -101,7 +101,8 @@@ static const char *file_names[TGSI_FILE
     "ADDR",
     "IMM",
     "LOOP",
 -   "PRED"
 +   "PRED",
 +   "SV"
  };
  
  static const char *interpolate_names[] =
@@@ -121,7 -120,8 +121,8 @@@ static const char *semantic_names[] 
     "PSIZE",
     "GENERIC",
     "NORMAL",
-    "FACE"
+    "FACE",
+    "EDGEFLAG"
  };
  
  static const char *immediate_type_names[] =
@@@ -150,27 -150,6 +151,27 @@@ static const char *texture_names[] 
     "SHADOWRECT"
  };
  
 +static const char *property_names[] =
 +{
 +   "GS_INPUT_PRIMITIVE",
 +   "GS_OUTPUT_PRIMITIVE",
 +   "GS_MAX_OUTPUT_VERTICES"
 +};
 +
 +static const char *primitive_names[] =
 +{
 +   "POINTS",
 +   "LINES",
 +   "LINE_LOOP",
 +   "LINE_STRIP",
 +   "TRIANGLES",
 +   "TRIANGLE_STRIP",
 +   "TRIANGLE_FAN",
 +   "QUADS",
 +   "QUAD_STRIP",
 +   "POLYGON"
 +};
 +
  
  static void
  _dump_register(
@@@ -294,50 -273,6 +295,50 @@@ tgsi_dump_declaration
     iter_declaration( &ctx.iter, (struct tgsi_full_declaration *)decl );
  }
  
 +static boolean
 +iter_property(
 +   struct tgsi_iterate_context *iter,
 +   struct tgsi_full_property *prop )
 +{
 +   int i;
 +   struct dump_ctx *ctx = (struct dump_ctx *)iter;
 +
 +   assert(Elements(property_names) == TGSI_PROPERTY_COUNT);
 +
 +   TXT( "PROPERTY " );
 +   ENM(prop->Property.PropertyName, property_names);
 +
 +   if (prop->Property.NrTokens > 1)
 +      TXT(" ");
 +
 +   for (i = 0; i < prop->Property.NrTokens - 1; ++i) {
 +      switch (prop->Property.PropertyName) {
 +      case TGSI_PROPERTY_GS_INPUT_PRIM:
 +      case TGSI_PROPERTY_GS_OUTPUT_PRIM:
 +         ENM(prop->u[i].Data, primitive_names);
 +         break;
 +      default:
 +         SID( prop->u[i].Data );
 +         break;
 +      }
 +      if (i < prop->Property.NrTokens - 2)
 +         TXT( ", " );
 +   }
 +   EOL();
 +
 +   return TRUE;
 +}
 +
 +void tgsi_dump_property(
 +   const struct tgsi_full_property *prop )
 +{
 +   struct dump_ctx ctx;
 +
 +   ctx.printf = dump_ctx_printf;
 +
 +   iter_property( &ctx.iter, (struct tgsi_full_property *)prop );
 +}
 +
  static boolean
  iter_immediate(
     struct tgsi_iterate_context *iter,
@@@ -558,7 -493,6 +559,7 @@@ tgsi_dump
     ctx.iter.iterate_instruction = iter_instruction;
     ctx.iter.iterate_declaration = iter_declaration;
     ctx.iter.iterate_immediate = iter_immediate;
 +   ctx.iter.iterate_property = iter_property;
     ctx.iter.epilog = NULL;
  
     ctx.instno = 0;
@@@ -613,7 -547,6 +614,7 @@@ tgsi_dump_str
     ctx.base.iter.iterate_instruction = iter_instruction;
     ctx.base.iter.iterate_declaration = iter_declaration;
     ctx.base.iter.iterate_immediate = iter_immediate;
 +   ctx.base.iter.iterate_property = iter_property;
     ctx.base.iter.epilog = NULL;
  
     ctx.base.instno = 0;
index 5f5c95bfbdb41c2a81f5bed85f0a9b2e9302f8bd,ebee000c06e0346ac15b7370d7bd284f7a3a520c..0f48b0dc3a113ff53ad3e5121bd5f5d91f0dd81b
@@@ -97,8 -97,7 +97,8 @@@ tgsi_scan_shader(const struct tgsi_toke
                 for (i = 0; i < fullinst->Instruction.NumSrcRegs; i++) {
                    const struct tgsi_full_src_register *src =
                       &fullinst->Src[i];
 -                  if (src->Register.File == TGSI_FILE_INPUT) {
 +                  if (src->Register.File == TGSI_FILE_INPUT ||
 +                      src->Register.File == TGSI_FILE_SYSTEM_VALUE) {
                       const int ind = src->Register.Index;
                       if (info->input_semantic_name[ind] == TGSI_SEMANTIC_FOG) {
                          if (src->Register.SwizzleX == TGSI_SWIZZLE_X) {
                 info->file_count[file]++;
                 info->file_max[file] = MAX2(info->file_max[file], (int)reg);
  
 -               if (file == TGSI_FILE_INPUT) {
 +               if (file == TGSI_FILE_INPUT || file == TGSI_FILE_SYSTEM_VALUE) {
                    info->input_semantic_name[reg] = (ubyte)fulldecl->Semantic.Name;
                    info->input_semantic_index[reg] = (ubyte)fulldecl->Semantic.Index;
                    info->input_interpolate[reg] = (ubyte)fulldecl->Declaration.Interpolate;
                    info->output_semantic_name[reg] = (ubyte)fulldecl->Semantic.Name;
                    info->output_semantic_index[reg] = (ubyte)fulldecl->Semantic.Index;
                    info->num_outputs++;
-                }
  
-                /* special case */
-                if (procType == TGSI_PROCESSOR_FRAGMENT &&
-                    file == TGSI_FILE_OUTPUT &&
-                    fulldecl->Semantic.Name == TGSI_SEMANTIC_POSITION) {
-                   info->writes_z = TRUE;
+                   /* extra info for special outputs */
+                   if (procType == TGSI_PROCESSOR_FRAGMENT &&
+                       fulldecl->Semantic.Name == TGSI_SEMANTIC_POSITION) {
+                      info->writes_z = TRUE;
+                   }
+                   if (procType == TGSI_PROCESSOR_VERTEX &&
+                       fulldecl->Semantic.Name == TGSI_SEMANTIC_EDGEFLAG) {
+                      info->writes_edgeflag = TRUE;
+                   }
                 }
-             }
+              }
           }
           break;
  
              info->file_max[file] = MAX2(info->file_max[file], (int)reg);
           }
           break;
 +      case TGSI_TOKEN_TYPE_PROPERTY:
 +      {
 +         const struct tgsi_full_property *fullprop
 +            = &parse.FullToken.FullProperty;
 +
 +         info->properties[info->num_properties].name =
 +            fullprop->Property.PropertyName;
 +         memcpy(info->properties[info->num_properties].data,
 +                fullprop->u, 8 * sizeof(unsigned));;
 +
 +         ++info->num_properties;
 +      }
 +      break;
  
        default:
           assert( 0 );
@@@ -226,7 -216,6 +230,7 @@@ tgsi_is_passthrough_shader(const struc
              /* Do a whole bunch of checks for a simple move */
              if (fullinst->Instruction.Opcode != TGSI_OPCODE_MOV ||
                  src->Register.File != TGSI_FILE_INPUT ||
 +                src->Register.File != TGSI_FILE_SYSTEM_VALUE ||
                  dst->Register.File != TGSI_FILE_OUTPUT ||
                  src->Register.Index != dst->Register.Index ||
  
           /* fall-through */
        case TGSI_TOKEN_TYPE_IMMEDIATE:
           /* fall-through */
 +      case TGSI_TOKEN_TYPE_PROPERTY:
 +         /* fall-through */
        default:
           ; /* no-op */
        }
index a1e8a4f6bb7c7072c9f9fc636acd099f66177be6,3ce0e88e4c6950bd713bffc293203bbb35815495..dae5376c24aae63dbebcab6f9d6d2e36adc75ca7
@@@ -33,6 -33,7 +33,6 @@@
  #include "pipe/p_state.h"
  #include "pipe/p_shader_tokens.h"
  
 -
  /**
   * Shader summary info
   */
@@@ -57,16 -58,12 +57,17 @@@ struct tgsi_shader_inf
     uint opcode_count[TGSI_OPCODE_LAST];  /**< opcode histogram */
  
     boolean writes_z;  /**< does fragment shader write Z value? */
+    boolean writes_edgeflag; /**< vertex shader outputs edgeflag */
     boolean uses_kill;  /**< KIL or KILP instruction used? */
     boolean uses_fogcoord; /**< fragment shader uses fog coord? */
     boolean uses_frontfacing; /**< fragment shader uses front/back-face flag? */
 -};
  
 +   struct {
 +      unsigned name;
 +      unsigned data[8];
 +   } properties[TGSI_PROPERTY_COUNT];
 +   uint num_properties;
 +};
  
  extern void
  tgsi_scan_shader(const struct tgsi_token *tokens,
index 6f44b1c7fe1a42cc07c73c459411f58325c0cfff,026cc82e0af0c64a5d51133b8786b4e2dd0d8b67..864ddaeb598eefb937c2bc7e1ddb482ecba99098
@@@ -144,7 -144,6 +144,6 @@@ struct nv30_context 
        unsigned vtxbuf_nr;
        struct pipe_vertex_element vtxelt[PIPE_MAX_ATTRIBS];
        unsigned vtxelt_nr;
-       const unsigned *edgeflags;
  };
  
  static INLINE struct nv30_context *
@@@ -184,7 -183,6 +183,7 @@@ extern void nv30_fragtex_bind(struct nv
  /* nv30_state.c and friends */
  extern boolean nv30_state_validate(struct nv30_context *nv30);
  extern void nv30_state_emit(struct nv30_context *nv30);
 +extern void nv30_state_flush_notify(struct nouveau_channel *chan);
  extern struct nv30_state_entry nv30_state_rasterizer;
  extern struct nv30_state_entry nv30_state_scissor;
  extern struct nv30_state_entry nv30_state_stipple;
index cf33b64a86dbb91b058bafce61522e0ffcbbbe54,06172e8817523cba23d6252c9eb61e444fadb988..83fcf1785d9f0187655d415b8a3914701df00f3f
@@@ -159,7 -159,6 +159,6 @@@ struct nv40_context 
        unsigned vtxbuf_nr;
        struct pipe_vertex_element vtxelt[PIPE_MAX_ATTRIBS];
        unsigned vtxelt_nr;
-       const unsigned *edgeflags;
  };
  
  static INLINE struct nv40_context *
@@@ -204,7 -203,6 +203,7 @@@ extern void nv40_fragtex_bind(struct nv
  extern boolean nv40_state_validate(struct nv40_context *nv40);
  extern boolean nv40_state_validate_swtnl(struct nv40_context *nv40);
  extern void nv40_state_emit(struct nv40_context *nv40);
 +extern void nv40_state_flush_notify(struct nouveau_channel *chan);
  extern struct nv40_state_entry nv40_state_rasterizer;
  extern struct nv40_state_entry nv40_state_scissor;
  extern struct nv40_state_entry nv40_state_stipple;
index ba0fbcb26a995585914ea7dafd4679e823f1a1e1,980ed217ecc7fa13bd795728ae8f379e7de69c79..789ed16126a330499100a580bcdfe57284ef5611
@@@ -57,7 -57,7 +57,7 @@@ nv40_state_emit(struct nv40_context *nv
        struct nouveau_channel *chan = nv40->screen->base.channel;
        struct nv40_state *state = &nv40->state;
        struct nv40_screen *screen = nv40->screen;
 -      unsigned i, samplers;
 +      unsigned i;
        uint64_t states;
  
        if (nv40->pctx_id != screen->cur_pctx) {
        }
  
        state->dirty = 0;
 +}
 +
 +void
 +nv40_state_flush_notify(struct nouveau_channel *chan)
 +{
 +      struct nv40_context *nv40 = chan->user_private;
 +      struct nv40_state *state = &nv40->state;
 +      unsigned i, samplers;
  
        so_emit_reloc_markers(chan, state->hw[NV40_STATE_FB]);
        for (i = 0, samplers = state->fp_samplers; i < 16 && samplers; i++) {
@@@ -168,7 -160,6 +168,6 @@@ nv40_state_validate_swtnl(struct nv40_c
                draw_set_viewport_state(draw, &nv40->viewport);
  
        if (nv40->draw_dirty & NV40_NEW_ARRAYS) {
-               draw_set_edgeflags(draw, nv40->edgeflags);
                draw_set_vertex_buffers(draw, nv40->vtxbuf_nr, nv40->vtxbuf);
                draw_set_vertex_elements(draw, nv40->vtxelt_nr, nv40->vtxelt);  
        }
index 8bcd6c5060808950c82843e456bf1cb22468989b,a0ebdf30241eec1e4c67f294b180efad488c3176..49072462ec3ff0e27ddd2d7a3fd80a9099ecdd4f
@@@ -283,13 -283,6 +283,6 @@@ static void r300_delete_dsa_state(struc
      FREE(state);
  }
  
- static void r300_set_edgeflags(struct pipe_context* pipe,
-                                const unsigned* bitfield)
- {
-     /* XXX you know it's bad when i915 has this blank too */
-     /* XXX and even worse, I have no idea WTF the bitfield is */
- }
  static void r300_set_scissor_regs(const struct pipe_scissor_state* state,
                                    struct r300_scissor_regs *scissor,
                                    boolean is_r500)
@@@ -339,7 -332,6 +332,7 @@@ static voi
          r300->dirty_state |= R300_NEW_SCISSOR;
      }
      r300->dirty_state |= R300_NEW_FRAMEBUFFERS;
 +    r300->dirty_state |= R300_NEW_BLEND;
  }
  
  /* Create fragment shader state. */
@@@ -355,7 -347,6 +348,7 @@@ static void* r300_create_fs_state(struc
      fs->state.tokens = tgsi_dup_tokens(shader->tokens);
  
      tgsi_scan_shader(shader->tokens, &fs->info);
 +    r300_shader_read_fs_inputs(&fs->info, &fs->inputs);
  
      return (void*)fs;
  }
@@@ -369,10 -360,11 +362,10 @@@ static void r300_bind_fs_state(struct p
      if (fs == NULL) {
          r300->fs = NULL;
          return;
 -    } else if (!fs->translated) {
 -        r300_translate_fragment_shader(r300, fs);
      }
  
      r300->fs = fs;
 +    r300_pick_fragment_shader(r300);
  
      r300->dirty_state |= R300_NEW_FRAGMENT_SHADER | R300_NEW_FRAGMENT_SHADER_CONSTANTS;
  }
  static void r300_delete_fs_state(struct pipe_context* pipe, void* shader)
  {
      struct r300_fragment_shader* fs = (struct r300_fragment_shader*)shader;
 -    rc_constants_destroy(&fs->code.constants);
 +    struct r300_fragment_shader_code *tmp, *ptr = fs->first;
 +
 +    while (ptr) {
 +        tmp = ptr;
 +        ptr = ptr->next;
 +        rc_constants_destroy(&tmp->code.constants);
 +        FREE(tmp);
 +    }
      FREE((void*)fs->state.tokens);
      FREE(shader);
  }
@@@ -427,6 -412,8 +420,6 @@@ static void* r300_create_rs_state(struc
      if (state->bypass_vs_clip_and_viewport ||
              !r300_screen(pipe->screen)->caps->has_tcl) {
          rs->vap_control_status |= R300_VAP_TCL_BYPASS;
 -    } else {
 -        rs->rs.bypass_vs_clip_and_viewport = TRUE;
      }
  
      rs->point_size = pack_float_16_6x(state->point_size) |
          rs->color_control = R300_SHADE_MODEL_SMOOTH;
      }
  
 -    if (!state->flatshade_first) {
 -        rs->color_control |= R300_GA_COLOR_CONTROL_PROVOKING_VERTEX_LAST;
 -    }
 -
      return (void*)rs;
  }
  
@@@ -554,8 -545,6 +547,8 @@@ static void
      int lod_bias;
      union util_color uc;
  
 +    sampler->state = *state;
 +
      sampler->filter0 |=
          (r300_translate_wrap(state->wrap_s) << R300_TX_WRAP_S_SHIFT) |
          (r300_translate_wrap(state->wrap_t) << R300_TX_WRAP_T_SHIFT) |
@@@ -606,14 -595,6 +599,14 @@@ static void r300_bind_sampler_states(st
      }
  
      r300->sampler_count = count;
 +
 +    /* Pick a fragment shader based on the texture compare state. */
 +    if (r300->fs && (r300->dirty_state & R300_ANY_NEW_SAMPLERS)) {
 +        if (r300_pick_fragment_shader(r300)) {
 +            r300->dirty_state |= R300_NEW_FRAGMENT_SHADER |
 +                                 R300_NEW_FRAGMENT_SHADER_CONSTANTS;
 +        }
 +    }
  }
  
  static void r300_lacks_vertex_textures(struct pipe_context* pipe,
@@@ -640,6 -621,8 +633,6 @@@ static void r300_set_sampler_textures(s
          return;
      }
      
 -    r300->context.flush(&r300->context, 0, NULL);
 -
      for (i = 0; i < count; i++) {
          if (r300->textures[i] != (struct r300_texture*)texture[i]) {
              pipe_texture_reference((struct pipe_texture**)&r300->textures[i],
@@@ -850,8 -833,6 +843,6 @@@ void r300_init_state_functions(struct r
      r300->context.bind_depth_stencil_alpha_state = r300_bind_dsa_state;
      r300->context.delete_depth_stencil_alpha_state = r300_delete_dsa_state;
  
-     r300->context.set_edgeflags = r300_set_edgeflags;
      r300->context.set_framebuffer_state = r300_set_framebuffer_state;
  
      r300->context.create_fs_state = r300_create_fs_state;
index fa207c939ca8a65b4b470808c878442eb0da8456,6ab5995244b8f9e5c8b2de47a2b271d2c35c42a7..c4ed0d712f9cb84c6e3d15b5ed33f1207f27ceee
@@@ -77,6 -77,11 +77,11 @@@ static void r300_shader_read_vs_outputs
                  vs_outputs->fog = i;
                  break;
  
+             case TGSI_SEMANTIC_EDGEFLAG:
+                 assert(index == 0);
+                 fprintf(stderr, "r300 VP: cannot handle edgeflag output\n");
+                 assert(0);
+                 break;
              default:
                  assert(0);
          }
@@@ -143,33 -148,35 +148,33 @@@ static void r300_shader_vap_output_fmt
      assert(gen_count <= 8);
  }
  
 -/* Set VS output stream locations for SWTCL. */
 -static void r300_stream_locations_swtcl(
 +/* Sets up stream mapping to equivalent VS outputs if TCL is bypassed
 + * or isn't present. */
 +static void r300_stream_locations_notcl(
      struct r300_shader_semantics* vs_outputs,
 -    int* output_stream_loc)
 +    int* stream_loc)
  {
      int i, tabi = 0, gen_count;
  
 -    /* XXX Check whether the numbers (0, 1, 2+i, etc.) are correct.
 -     * These should go to VAP_PROG_STREAM_CNTL/DST_VEC_LOC. */
 -
      /* Position. */
 -    output_stream_loc[tabi++] = 0;
 +    stream_loc[tabi++] = 0;
  
      /* Point size. */
      if (vs_outputs->psize != ATTR_UNUSED) {
 -        output_stream_loc[tabi++] = 1;
 +        stream_loc[tabi++] = 1;
      }
  
      /* Colors. */
      for (i = 0; i < ATTR_COLOR_COUNT; i++) {
          if (vs_outputs->color[i] != ATTR_UNUSED) {
 -            output_stream_loc[tabi++] = 2 + i;
 +            stream_loc[tabi++] = 2 + i;
          }
      }
  
      /* Back-face colors. */
      for (i = 0; i < ATTR_COLOR_COUNT; i++) {
          if (vs_outputs->bcolor[i] != ATTR_UNUSED) {
 -            output_stream_loc[tabi++] = 4 + i;
 +            stream_loc[tabi++] = 4 + i;
          }
      }
  
      for (i = 0; i < ATTR_GENERIC_COUNT; i++) {
          if (vs_outputs->bcolor[i] != ATTR_UNUSED) {
              assert(tabi < 16);
 -            output_stream_loc[tabi++] = 6 + gen_count;
 +            stream_loc[tabi++] = 6 + gen_count;
              gen_count++;
          }
      }
      /* Fog coordinates. */
      if (vs_outputs->fog != ATTR_UNUSED) {
          assert(tabi < 16);
 -        output_stream_loc[tabi++] = 6 + gen_count;
 +        stream_loc[tabi++] = 6 + gen_count;
          gen_count++;
      }
  
      assert(gen_count <= 8);
  
      for (; tabi < 16;) {
 -        output_stream_loc[tabi++] = -1;
 +        stream_loc[tabi++] = -1;
      }
  }
  
@@@ -252,7 -259,10 +257,7 @@@ void r300_translate_vertex_shader(struc
      /* Initialize. */
      r300_shader_read_vs_outputs(&vs->info, &vs->outputs);
      r300_shader_vap_output_fmt(&vs->outputs, vs->hwfmt);
 -
 -    if (!r300_screen(r300->context.screen)->caps->has_tcl) {
 -        r300_stream_locations_swtcl(&vs->outputs, vs->output_stream_loc_swtcl);
 -    }
 +    r300_stream_locations_notcl(&vs->outputs, vs->stream_loc_notcl);
  
      /* Setup the compiler */
      rc_init(&compiler.Base);
      /* Invoke the compiler */
      r3xx_compile_vertex_program(&compiler);
      if (compiler.Base.Error) {
 -        /* XXX Fail gracefully */
 +        /* XXX We should fallback using Draw. */
          fprintf(stderr, "r300 VP: Compiler error\n");
          abort();
      }
index 8e7b5b3da11898986b6a4c1324bcd269ac826b7f,a851fa67057f58b109e57262aa3c7f740834b149..0885d9ca74101d3f1872b49772c0ecd22608276f
@@@ -202,8 -202,6 +202,6 @@@ struct svga_stat
     struct pipe_clip_state clip;
     struct pipe_viewport_state viewport;
  
-    const unsigned *edgeflags;
     unsigned num_samplers;
     unsigned num_textures;
     unsigned num_vertex_elements;
@@@ -369,7 -367,7 +367,7 @@@ struct svga_contex
  #define SVGA_NEW_FRAME_BUFFER        0x800
  #define SVGA_NEW_STIPPLE             0x1000
  #define SVGA_NEW_SCISSOR             0x2000
 -#define SVGA_NEW_BLEND_COLOR         0x5000
 +#define SVGA_NEW_BLEND_COLOR         0x4000
  #define SVGA_NEW_CLIP                0x8000
  #define SVGA_NEW_VIEWPORT            0x10000
  #define SVGA_NEW_PRESCALE            0x20000
  #define SVGA_NEW_NEED_SWTNL          0x400000
  #define SVGA_NEW_FS_RESULT           0x800000
  #define SVGA_NEW_VS_RESULT           0x1000000
- #define SVGA_NEW_EDGEFLAGS           0x2000000
- #define SVGA_NEW_ZERO_STRIDE         0x4000000
- #define SVGA_NEW_TEXTURE_FLAGS       0x8000000
+ #define SVGA_NEW_ZERO_STRIDE         0x2000000
+ #define SVGA_NEW_TEXTURE_FLAGS       0x4000000
  
  
  
index 79f3d3f056677e286c73ed9ea9762a49b3cd90d1,c051d4dae8449f05ad13fe49a4135226c70ee25d..5da85bbbc24451b026c3aaf19862030cbec4fd4e
@@@ -55,7 -55,6 +55,7 @@@ struct tgsi_processo
  #define TGSI_TOKEN_TYPE_DECLARATION    0
  #define TGSI_TOKEN_TYPE_IMMEDIATE      1
  #define TGSI_TOKEN_TYPE_INSTRUCTION    2
 +#define TGSI_TOKEN_TYPE_PROPERTY       3
  
  struct tgsi_token
  {
  };
  
  enum tgsi_file_type {
 -   TGSI_FILE_NULL        =0,
 -   TGSI_FILE_CONSTANT    =1,
 -   TGSI_FILE_INPUT       =2,
 -   TGSI_FILE_OUTPUT      =3,
 -   TGSI_FILE_TEMPORARY   =4,
 -   TGSI_FILE_SAMPLER     =5,
 -   TGSI_FILE_ADDRESS     =6,
 -   TGSI_FILE_IMMEDIATE   =7,
 -   TGSI_FILE_LOOP        =8,
 -   TGSI_FILE_PREDICATE   =9,
 +   TGSI_FILE_NULL         =0,
 +   TGSI_FILE_CONSTANT     =1,
 +   TGSI_FILE_INPUT        =2,
 +   TGSI_FILE_OUTPUT       =3,
 +   TGSI_FILE_TEMPORARY    =4,
 +   TGSI_FILE_SAMPLER      =5,
 +   TGSI_FILE_ADDRESS      =6,
 +   TGSI_FILE_IMMEDIATE    =7,
 +   TGSI_FILE_LOOP         =8,
 +   TGSI_FILE_PREDICATE    =9,
 +   TGSI_FILE_SYSTEM_VALUE =10,
     TGSI_FILE_COUNT      /**< how many TGSI_FILE_ types */
  };
  
@@@ -129,7 -127,8 +129,8 @@@ struct tgsi_declaration_rang
  #define TGSI_SEMANTIC_GENERIC  5
  #define TGSI_SEMANTIC_NORMAL   6
  #define TGSI_SEMANTIC_FACE     7
- #define TGSI_SEMANTIC_COUNT    8 /**< number of semantic values */
+ #define TGSI_SEMANTIC_EDGEFLAG 8
+ #define TGSI_SEMANTIC_COUNT    9 /**< number of semantic values */
  
  struct tgsi_declaration_semantic
  {
@@@ -153,22 -152,6 +154,22 @@@ union tgsi_immediate_dat
     float Float;
  };
  
 +#define TGSI_PROPERTY_GS_INPUT_PRIM          0
 +#define TGSI_PROPERTY_GS_OUTPUT_PRIM         1
 +#define TGSI_PROPERTY_GS_MAX_VERTICES        2
 +#define TGSI_PROPERTY_COUNT                  3
 +
 +struct tgsi_property {
 +   unsigned Type         : 4;  /**< TGSI_TOKEN_TYPE_PROPERTY */
 +   unsigned NrTokens     : 8;  /**< UINT */
 +   unsigned PropertyName : 8;  /**< one of TGSI_PROPERTY */
 +   unsigned Padding      : 12;
 +};
 +
 +struct tgsi_property_data {
 +   unsigned Data;
 +};
 +
  /* TGSI opcodes.  
   * 
   * For more information on semantics of opcodes and
index ec8092d7e9e78af5c8f79740cab998dc47c7adda,2d287ef4ef52b23f1c00c3d43409ef8776852a32..e54f21be6009c7a1051127df9aeb68f1843c7a61
@@@ -217,59 -217,7 +217,7 @@@ st_pipe_vertex_format(GLenum type, GLui
  }
  
  
- /*
-  * If edge flags are needed, setup an bitvector of flags and call
-  * pipe->set_edgeflags().
-  * XXX memleak: need to free the returned pointer at some point
-  */
- static void *
- setup_edgeflags(GLcontext *ctx, GLenum primMode, GLint start, GLint count,
-                 const struct gl_client_array *array)
- {
-    struct pipe_context *pipe = ctx->st->pipe;
-    if ((primMode == GL_TRIANGLES ||
-         primMode == GL_QUADS ||
-         primMode == GL_POLYGON) &&
-        (ctx->Polygon.FrontMode != GL_FILL ||
-         ctx->Polygon.BackMode != GL_FILL)) {
-       /* need edge flags */
-       GLint i;
-       unsigned *vec;
-       struct st_buffer_object *stobj = st_buffer_object(array->BufferObj);
-       ubyte *map;
-       if (!stobj || stobj->Base.Name == 0) {
-          /* edge flags are not in a VBO */
-          return NULL;
-       }
-       vec = (unsigned *) _mesa_calloc(sizeof(unsigned) * ((count + 31) / 32));
-       if (!vec)
-          return NULL;
-       map = pipe_buffer_map(pipe->screen, stobj->buffer, PIPE_BUFFER_USAGE_CPU_READ);
-       map = ADD_POINTERS(map, array->Ptr);
-       for (i = 0; i < count; i++) {
-          if (*((float *) map))
-             vec[i/32] |= 1 << (i % 32);
-          map += array->StrideB;
-       }
  
-       pipe_buffer_unmap(pipe->screen, stobj->buffer);
-       pipe->set_edgeflags(pipe, vec);
-       return vec;
-    }
-    else {
-       /* edge flags not needed */
-       pipe->set_edgeflags(pipe, NULL);
-       return NULL;
-    }
- }
  
  
  /**
   */
  static GLboolean
  is_interleaved_arrays(const struct st_vertex_program *vp,
+                       const struct st_vp_varient *vpv,
                        const struct gl_client_array **arrays,
                        GLboolean *userSpace)
  {
     GLuint num_client_arrays = 0;
     const GLubyte *client_addr = NULL;
  
-    for (attr = 0; attr < vp->num_inputs; attr++) {
+    for (attr = 0; attr < vpv->num_inputs; attr++) {
        const GLuint mesaAttr = vp->index_to_input[attr];
        const struct gl_buffer_object *bufObj = arrays[mesaAttr]->BufferObj;
        const GLsizei stride = arrays[mesaAttr]->StrideB; /* in bytes */
        }
     }
  
-    *userSpace = (num_client_arrays == vp->num_inputs);
+    *userSpace = (num_client_arrays == vpv->num_inputs);
     /* printf("user space: %d (%d %d)\n", (int) *userSpace,num_client_arrays,vp->num_inputs); */
  
     return GL_TRUE;
   */
  static void
  get_arrays_bounds(const struct st_vertex_program *vp,
-                        const struct gl_client_array **arrays,
-                        GLuint max_index,
-                        const GLubyte **low, const GLubyte **high)
+                   const struct st_vp_varient *vpv,
+                   const struct gl_client_array **arrays,
+                   GLuint max_index,
+                   const GLubyte **low, const GLubyte **high)
  {
     const GLubyte *low_addr = NULL;
     const GLubyte *high_addr = NULL;
     GLuint attr;
  
-    for (attr = 0; attr < vp->num_inputs; attr++) {
+    for (attr = 0; attr < vpv->num_inputs; attr++) {
        const GLuint mesaAttr = vp->index_to_input[attr];
        const GLint stride = arrays[mesaAttr]->StrideB;
        const GLubyte *start = arrays[mesaAttr]->Ptr;
  static void
  setup_interleaved_attribs(GLcontext *ctx,
                            const struct st_vertex_program *vp,
+                           const struct st_vp_varient *vpv,
                            const struct gl_client_array **arrays,
                            GLuint max_index,
                            GLboolean userSpace,
  {
     struct pipe_context *pipe = ctx->st->pipe;
     GLuint attr;
 -   const GLubyte *offset0;
 +   const GLubyte *offset0 = NULL;
  
-    for (attr = 0; attr < vp->num_inputs; attr++) {
+    for (attr = 0; attr < vpv->num_inputs; attr++) {
        const GLuint mesaAttr = vp->index_to_input[attr];
        struct gl_buffer_object *bufobj = arrays[mesaAttr]->BufferObj;
        struct st_buffer_object *stobj = st_buffer_object(bufobj);
        if (attr == 0) {
           const GLubyte *low, *high;
  
-          get_arrays_bounds(vp, arrays, max_index, &low, &high);
+          get_arrays_bounds(vp, vpv, arrays, max_index, &low, &high);
           /*printf("buffer range: %p %p  %d\n", low, high, high-low);*/
  
           offset0 = low;
  static void
  setup_non_interleaved_attribs(GLcontext *ctx,
                                const struct st_vertex_program *vp,
+                               const struct st_vp_varient *vpv,
                                const struct gl_client_array **arrays,
                                GLuint max_index,
                                GLboolean *userSpace,
     struct pipe_context *pipe = ctx->st->pipe;
     GLuint attr;
  
-    for (attr = 0; attr < vp->num_inputs; attr++) {
+    for (attr = 0; attr < vpv->num_inputs; attr++) {
        const GLuint mesaAttr = vp->index_to_input[attr];
        struct gl_buffer_object *bufobj = arrays[mesaAttr]->BufferObj;
        GLsizei stride = arrays[mesaAttr]->StrideB;
@@@ -538,20 -490,6 +490,20 @@@ check_uniforms(GLcontext *ctx
  }
  
  
 +static unsigned translate_prim( GLcontext *ctx,
 +                                unsigned prim )
 +{
 +   /* Avoid quadstrips if it's easy to do so:
 +    */
 +   if (prim == GL_QUAD_STRIP &&
 +       ctx->Light.ShadeModel != GL_FLAT &&
 +       ctx->Polygon.FrontMode == GL_FILL &&
 +       ctx->Polygon.BackMode == GL_FILL)
 +      prim = GL_TRIANGLE_STRIP;
 +
 +   return prim;
 +}
 +
  /**
   * This function gets plugged into the VBO module and is called when
   * we have something to render.
@@@ -569,26 -507,35 +521,36 @@@ st_draw_vbo(GLcontext *ctx
  {
     struct pipe_context *pipe = ctx->st->pipe;
     const struct st_vertex_program *vp;
+    const struct st_vp_varient *vpv;
     const struct pipe_shader_state *vs;
     struct pipe_vertex_buffer vbuffer[PIPE_MAX_SHADER_INPUTS];
     GLuint attr;
     struct pipe_vertex_element velements[PIPE_MAX_ATTRIBS];
     unsigned num_vbuffers, num_velements;
 -   GLboolean userSpace;
 +   GLboolean userSpace = GL_FALSE;
+    GLboolean vertDataEdgeFlags;
  
     /* Gallium probably doesn't want this in some cases. */
     if (!index_bounds_valid)
 -      vbo_get_minmax_index(ctx, prims, ib, &min_index, &max_index);
 +      if (!vbo_all_varyings_in_vbos(arrays))
 +       vbo_get_minmax_index(ctx, prims, ib, &min_index, &max_index);
  
     /* sanity check for pointer arithmetic below */
     assert(sizeof(arrays[0]->Ptr[0]) == 1);
  
+    vertDataEdgeFlags = arrays[VERT_ATTRIB_EDGEFLAG]->BufferObj &&
+                        arrays[VERT_ATTRIB_EDGEFLAG]->BufferObj->Name;
+    if (vertDataEdgeFlags != ctx->st->vertdata_edgeflags) {
+       ctx->st->vertdata_edgeflags = vertDataEdgeFlags;
+       ctx->st->dirty.st |= ST_NEW_EDGEFLAGS_DATA;
+    }
     st_validate_state(ctx->st);
  
     /* must get these after state validation! */
     vp = ctx->st->vp;
-    vs = &ctx->st->vp_varient->state;
+    vpv = ctx->st->vp_varient;
+    vs = &vpv->state;
  
  #if 0
     if (MESA_VERBOSE & VERBOSE_GLSL) {
     /*
      * Setup the vbuffer[] and velements[] arrays.
      */
-    if (is_interleaved_arrays(vp, arrays, &userSpace)) {
+    if (is_interleaved_arrays(vp, vpv, arrays, &userSpace)) {
        /*printf("Draw interleaved\n");*/
-       setup_interleaved_attribs(ctx, vp, arrays, max_index, userSpace,
+       setup_interleaved_attribs(ctx, vp, vpv, arrays, max_index, userSpace,
                                  vbuffer, velements);
        num_vbuffers = 1;
-       num_velements = vp->num_inputs;
+       num_velements = vpv->num_inputs;
        if (num_velements == 0)
           num_vbuffers = 0;
     }
     else {
        /*printf("Draw non-interleaved\n");*/
-       setup_non_interleaved_attribs(ctx, vp, arrays, max_index,
+       setup_non_interleaved_attribs(ctx, vp, vpv, arrays, max_index,
                                      &userSpace, vbuffer, velements);
-       num_vbuffers = vp->num_inputs;
-       num_velements = vp->num_inputs;
+       num_vbuffers = vpv->num_inputs;
+       num_velements = vpv->num_inputs;
     }
  
  #if 0
        struct gl_buffer_object *bufobj = ib->obj;
        struct pipe_buffer *indexBuf = NULL;
        unsigned indexSize, indexOffset, i;
 +      unsigned prim;
  
        switch (ib->type) {
        case GL_UNSIGNED_INT:
            * through to driver & draw module.  These interfaces still
            * need a bit of work...
            */
-          setup_edgeflags(ctx, prims[i].mode,
-                          prims[i].start + indexOffset, prims[i].count,
-                          arrays[VERT_ATTRIB_EDGEFLAG]);
 +         prim = translate_prim( ctx, prims[i].mode );
 +
           pipe->draw_range_elements(pipe, indexBuf, indexSize,
                                     min_index,
                                     max_index,
 -                                   prims[i].mode,
 +                                   prim,
                                     prims[i].start + indexOffset, prims[i].count);
        }
        else {
           for (i = 0; i < nr_prims; i++) {
-             setup_edgeflags(ctx, prims[i].mode,
-                             prims[i].start + indexOffset, prims[i].count,
-                             arrays[VERT_ATTRIB_EDGEFLAG]);
 +            prim = translate_prim( ctx, prims[i].mode );
 +            
              pipe->draw_elements(pipe, indexBuf, indexSize,
 -                                prims[i].mode,
 +                                prim,
                                  prims[i].start + indexOffset, prims[i].count);
           }
        }
     else {
        /* non-indexed */
        GLuint i;
 +      GLuint prim;
 +
        for (i = 0; i < nr_prims; i++) {
-          setup_edgeflags(ctx, prims[i].mode,
-                          prims[i].start, prims[i].count,
-                          arrays[VERT_ATTRIB_EDGEFLAG]);
 -         pipe->draw_arrays(pipe, prims[i].mode, prims[i].start, prims[i].count);
 +         prim = translate_prim( ctx, prims[i].mode );
 +
 +         pipe->draw_arrays(pipe, prim, prims[i].start, prims[i].count);
        }
     }
  
index d91ed6806dcc11f7ece5133808861e8a07d4a307,feaac013c1a6f864a4ac220334d2fbd36d8b540c..6a869fae90443455d20b01c90ecc96b43838629e
@@@ -102,8 -102,6 +102,8 @@@ st_prepare_vertex_program(struct st_con
     if (stvp->Base.IsPositionInvariant)
        _mesa_insert_mvp_code(st->ctx, &stvp->Base);
  
 +   assert(stvp->Base.Base.NumInstructions > 1);
 +
     /*
      * Determine number of inputs, the mappings between VERT_ATTRIB_x
      * and TGSI generic input indexes, plus input attrib semantic info.
           stvp->num_inputs++;
        }
     }
+    /* bit of a hack, presetup potentially unused edgeflag input */
+    stvp->input_to_index[VERT_ATTRIB_EDGEFLAG] = stvp->num_inputs;
+    stvp->index_to_input[stvp->num_inputs] = VERT_ATTRIB_EDGEFLAG;
  
     /* Compute mapping of vertex program outputs to slots.
      */
           }
        }
     }
+    /* similar hack to above, presetup potentially unused edgeflag output */
+    stvp->result_to_output[VERT_RESULT_EDGE] = stvp->num_outputs;
+    stvp->output_semantic_name[stvp->num_outputs] = TGSI_SEMANTIC_EDGEFLAG;
+    stvp->output_semantic_index[stvp->num_outputs] = 0;
  }
  
  
@@@ -194,22 -199,47 +201,47 @@@ st_translate_vertex_program(struct st_c
  {
     struct st_vp_varient *vpv = CALLOC_STRUCT(st_vp_varient);
     struct pipe_context *pipe = st->pipe;
+    struct ureg_program *ureg;
+    enum pipe_error error;
+    unsigned num_outputs;
+    ureg = ureg_create( TGSI_PROCESSOR_VERTEX );
+    if (ureg == NULL)
+       return NULL;
+    vpv->num_inputs = stvp->num_inputs;
+    num_outputs = stvp->num_outputs;
+    if (key->passthrough_edgeflags) {
+       vpv->num_inputs++;
+       num_outputs++;
+    }
  
-    vpv->state.tokens = 
+    error = 
        st_translate_mesa_program(st->ctx,
                                  TGSI_PROCESSOR_VERTEX,
+                                 ureg,
                                  &stvp->Base.Base,
                                  /* inputs */
-                                 stvp->num_inputs,
+                                 vpv->num_inputs,
                                  stvp->input_to_index,
                                  NULL, /* input semantic name */
                                  NULL, /* input semantic index */
                                  NULL,
                                  /* outputs */
-                                 stvp->num_outputs,
+                                 num_outputs,
                                  stvp->result_to_output,
                                  stvp->output_semantic_name,
-                                 stvp->output_semantic_index );
+                                 stvp->output_semantic_index,
+                                 key->passthrough_edgeflags );
+    if (error)
+       goto fail;
+    vpv->state.tokens = ureg_get_tokens( ureg, NULL );
+    if (!vpv->state.tokens)
+       goto fail;
+    ureg_destroy( ureg );
  
     vpv->driver_shader = pipe->create_vs_state(pipe, &vpv->state);
  
     }
  
     return vpv;
+ fail:
+    debug_printf("%s: failed to translate Mesa program:\n", __FUNCTION__);
+    _mesa_print_program(&stvp->Base.Base);
+    debug_assert(0);
+    ureg_destroy( ureg );
+    return NULL;
  }
  
  
@@@ -244,7 -282,9 +284,9 @@@ st_translate_fragment_program(struct st
     GLuint defaultInputMapping[FRAG_ATTRIB_MAX];
     GLuint interpMode[16];  /* XXX size? */
     GLuint attr;
+    enum pipe_error error;
     const GLbitfield inputsRead = stfp->Base.Base.InputsRead;
+    struct ureg_program *ureg;
     GLuint vslot = 0;
  
     uint fs_num_inputs = 0;
     if (!inputMapping)
        inputMapping = defaultInputMapping;
  
-    stfp->state.tokens = 
+    ureg = ureg_create( TGSI_PROCESSOR_FRAGMENT );
+    if (ureg == NULL)
+       return;
+    error = 
        st_translate_mesa_program(st->ctx,
                                  TGSI_PROCESSOR_FRAGMENT,
+                                 ureg,
                                  &stfp->Base.Base,
                                  /* inputs */
                                  fs_num_inputs,
                                  fs_num_outputs,
                                  outputMapping,
                                  fs_output_semantic_name,
-                                 fs_output_semantic_index );
+                                 fs_output_semantic_index, FALSE );
  
+    stfp->state.tokens = ureg_get_tokens( ureg, NULL );
+    ureg_destroy( ureg );
     stfp->driver_shader = pipe->create_fs_state(pipe, &stfp->state);
  
     if ((ST_DEBUG & DEBUG_TGSI) && (ST_DEBUG & DEBUG_MESA)) {