Mesa (master): draw wip

Zack Rusin zack at kemper.freedesktop.org
Tue Jun 15 06:12:30 PDT 2010


Module: Mesa
Branch: master
Commit: b85a361ccbac956d2842251395c048a4b3f4c440
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=b85a361ccbac956d2842251395c048a4b3f4c440

Author: Keith Whitwell <keithw at vmware.com>
Date:   Mon Jun 14 15:11:59 2010 +0100

draw wip

---

 src/gallium/auxiliary/draw/draw_gs.c               |   53 ++-
 src/gallium/auxiliary/draw/draw_gs.h               |   12 +-
 src/gallium/auxiliary/draw/draw_pipe.c             |   65 ++--
 src/gallium/auxiliary/draw/draw_private.h          |   48 ++-
 src/gallium/auxiliary/draw/draw_pt.h               |   19 +-
 src/gallium/auxiliary/draw/draw_pt_emit.c          |   41 ++-
 .../auxiliary/draw/draw_pt_fetch_shade_pipeline.c  |  397 +++++++++-----------
 src/gallium/auxiliary/draw/draw_pt_so_emit.c       |   26 +-
 8 files changed, 342 insertions(+), 319 deletions(-)

diff --git a/src/gallium/auxiliary/draw/draw_gs.c b/src/gallium/auxiliary/draw/draw_gs.c
index 52f61d2..787d93a 100644
--- a/src/gallium/auxiliary/draw/draw_gs.c
+++ b/src/gallium/auxiliary/draw/draw_gs.c
@@ -327,28 +327,32 @@ static void gs_tri(struct draw_geometry_shader *shader,
 #include "draw_gs_tmp.h"
 
 int draw_geometry_shader_run(struct draw_geometry_shader *shader,
-                             unsigned pipe_prim,
-                             const float (*input)[4],
-                             float (*output)[4],
-                             const void *constants[PIPE_MAX_CONSTANT_BUFFERS],
-                             unsigned count,
-                             unsigned input_stride,
-                             unsigned vertex_size)
+                             const void *constants[PIPE_MAX_CONSTANT_BUFFERS], 
+                             const struct draw_vertex_info *input_verts,
+                             const struct draw_prim_info *input_prim,
+                             struct draw_vertex_info *output_verts,
+                             struct draw_prim_info *output_prims )
 {
+   const float (*input)[4] = input_verts->verts;
+   unsigned input_stride = input_verts->vertex_size;
+   unsigned vertex_size = input_verts->vertex_size;
    struct tgsi_exec_machine *machine = shader->machine;
    unsigned int i;
-   unsigned num_in_primitives =
-      u_gs_prims_for_vertices(pipe_prim, count);
-   unsigned alloc_count = draw_max_output_vertices(shader->draw,
-                                                   pipe_prim,
-                                                   count);
-   /* this is bad, but we can't be overwriting the output array
-    * because it's the same as input array here */
-   struct vertex_header *pipeline_verts =
-      (struct vertex_header *)MALLOC(vertex_size * alloc_count);
-
-   if (!pipeline_verts)
-      return 0;
+   unsigned num_in_primitives = u_gs_prims_for_vertices(input_prim->prim,
+                                                        input_verts->count);
+
+   output_verts->vertex_size = input_verts->vertex_size;
+   output_verts->stride = input_verts->vertex_size;
+
+   output_verts->count = draw_max_output_vertices(draw,
+                                                  input_prim->prim,
+                                                  input_verts->count);
+
+   output_verts->verts =
+         (struct vertex_header *)MALLOC(vert_info.vertex_size *
+                                        vert_info.count);
+
+
 
    if (0) debug_printf("%s count = %d (prims = %d)\n", __FUNCTION__,
                        count, num_in_primitives);
@@ -356,7 +360,7 @@ int draw_geometry_shader_run(struct draw_geometry_shader *shader,
    shader->emitted_vertices = 0;
    shader->emitted_primitives = 0;
    shader->vertex_size = vertex_size;
-   shader->tmp_output = (      float (*)[4])pipeline_verts->data;
+   shader->tmp_output = (float (*)[4])input_verts->verts->data;
    shader->in_prim_idx = 0;
    shader->input_vertex_stride = input_stride;
    shader->input = input;
@@ -373,7 +377,14 @@ int draw_geometry_shader_run(struct draw_geometry_shader *shader,
              vertex_size * (shader->emitted_vertices -1));
    }
 
-   FREE(pipeline_verts);
+   
+   /* Update prim_info: 
+    */
+   output_prims->linear = TRUE;
+   output_prims->elts = NULL;
+   output_prims->primitive_lengths = machine->foo;
+   output_prims->primitive_count = machine->bar;
+
    return shader->emitted_vertices;
 }
 
diff --git a/src/gallium/auxiliary/draw/draw_gs.h b/src/gallium/auxiliary/draw/draw_gs.h
index 65f0c61..2374b12 100644
--- a/src/gallium/auxiliary/draw/draw_gs.h
+++ b/src/gallium/auxiliary/draw/draw_gs.h
@@ -71,13 +71,11 @@ struct draw_geometry_shader {
  * smaller than the GS_MAX_OUTPUT_VERTICES shader property.
  */
 int draw_geometry_shader_run(struct draw_geometry_shader *shader,
-                             unsigned pipe_prim,
-                             const float (*input)[4],
-                             float (*output)[4],
-                             const void *constants[PIPE_MAX_CONSTANT_BUFFERS],
-                             unsigned count,
-                             unsigned input_stride,
-                             unsigned output_stride);
+                             const void *constants[PIPE_MAX_CONSTANT_BUFFERS], 
+                             const struct draw_vertex_info *input_verts,
+                             const struct draw_prim_info *input_prim,
+                             struct draw_vertex_info *output_verts,
+                             struct draw_prim_info *output_prims );
 
 void draw_geometry_shader_prepare(struct draw_geometry_shader *shader,
                                   struct draw_context *draw);
diff --git a/src/gallium/auxiliary/draw/draw_pipe.c b/src/gallium/auxiliary/draw/draw_pipe.c
index 7ea04e3..c1cc32f 100644
--- a/src/gallium/auxiliary/draw/draw_pipe.c
+++ b/src/gallium/auxiliary/draw/draw_pipe.c
@@ -256,27 +256,34 @@ static void do_triangle( struct draw_context *draw,
  * draw_vbuf.c code uses when it has to perform a flush.
  */
 void draw_pipeline_run( struct draw_context *draw,
-                        unsigned prim,
-                        struct vertex_header *vertices,
-                        unsigned vertex_count,
-                        unsigned stride,
-                        const ushort *elts,
-                        unsigned count )
+                        const struct draw_vertex_info *vert_info,
+                        const struct draw_prim_info *prim_info)
 {
-   char *verts = (char *)vertices;
-
-   draw->pipeline.verts = verts;
-   draw->pipeline.vertex_stride = stride;
-   draw->pipeline.vertex_count = vertex_count;
-   
-   pipe_run(draw, prim, vertices, stride, elts, count);
+   unsigned i, start;
    
+   draw->pipeline.verts = (char *)vert_info->verts;
+   draw->pipeline.vertex_stride = vert_info->stride;
+   draw->pipeline.vertex_count = vert_info->count;
+
+   for (start = i = 0;
+        i < prim_info->primitive_count;
+        start += prim_info->primitive_lengths[i], i++)
+   {
+      unsigned count = prim_info->primitive_lengths[i];
+
+      pipe_run(draw,
+               prim_info->prim,
+               vert_info->verts,
+               vert_info->stride,
+               prim_info->elts + start,
+               count);
+   }
+
    draw->pipeline.verts = NULL;
    draw->pipeline.vertex_count = 0;
 }
 
 
-
 /*
  * Set up macros for draw_pt_decompose.h template code.
  * This code is for non-indexed (aka linear) rendering (no elts).
@@ -354,17 +361,27 @@ void draw_pipeline_run( struct draw_context *draw,
  * For drawing non-indexed primitives.
  */
 void draw_pipeline_run_linear( struct draw_context *draw,
-                               unsigned prim,
-                               struct vertex_header *vertices,
-                               unsigned count,
-                               unsigned stride )
+                               const struct draw_vertex_info *vert_info,
+                               const struct draw_prim_info *prim_info)
 {
-   char *verts = (char *)vertices;
-   draw->pipeline.verts = verts;
-   draw->pipeline.vertex_stride = stride;
-   draw->pipeline.vertex_count = count;
-
-   pipe_run_linear(draw, prim, vertices, stride, count);
+   unsigned i, start;
+
+   for (start = i = 0;
+        i < prim_info->primitive_count;
+        start += prim_info->primitive_lengths[i], i++)
+   {
+      unsigned count = prim_info->primitive_lengths[i];
+
+      draw->pipeline.verts = (char *)&vert_info->verts[start];
+      draw->pipeline.vertex_stride = vert_info->stride;
+      draw->pipeline.vertex_count = count;
+
+      pipe_run_linear(draw,
+                      prim_info->prim,
+                      &vert_info->verts[start],
+                      vert_info->stride,
+                      vert_info->count);
+   }
 
    draw->pipeline.verts = NULL;
    draw->pipeline.vertex_count = 0;
diff --git a/src/gallium/auxiliary/draw/draw_private.h b/src/gallium/auxiliary/draw/draw_private.h
index fe867ff..c6dc734 100644
--- a/src/gallium/auxiliary/draw/draw_private.h
+++ b/src/gallium/auxiliary/draw/draw_private.h
@@ -265,6 +265,39 @@ struct draw_context
    void *driver_private;
 };
 
+
+
+
+struct draw_fetch_info {
+   boolean linear;
+   unsigned start;
+   void *elts;
+   unsigned count;
+
+   
+};
+
+struct draw_vertex_info {
+   struct vertex_header *verts;
+   unsigned vertex_size;
+   unsigned stride;
+   unsigned count;
+};
+
+
+struct draw_prim_info {
+   boolean linear;
+   unsigned start;
+
+   ushort *elts;
+   unsigned count;
+
+   unsigned prim;
+   unsigned *primitive_lengths;
+   unsigned primitive_count;
+};
+
+
 /*******************************************************************************
  * Draw common initialization code
  */
@@ -342,18 +375,13 @@ void draw_pipeline_destroy( struct draw_context *draw );
 #define DRAW_PIPE_FLAG_MASK     (0xf<<12)
 
 void draw_pipeline_run( struct draw_context *draw,
-                        unsigned prim,
-                        struct vertex_header *vertices,
-                        unsigned vertex_count,
-                        unsigned stride,
-                        const ushort *elts,
-                        unsigned count );
+                        const struct draw_vertex_info *vert,
+                        const struct draw_prim_info *prim);
 
 void draw_pipeline_run_linear( struct draw_context *draw,
-                               unsigned prim,
-                               struct vertex_header *vertices,
-                               unsigned count,
-                               unsigned stride );
+                               const struct draw_vertex_info *vert,
+                               const struct draw_prim_info *prim);
+
 
 
 
diff --git a/src/gallium/auxiliary/draw/draw_pt.h b/src/gallium/auxiliary/draw/draw_pt.h
index 67ae70f..821a73f 100644
--- a/src/gallium/auxiliary/draw/draw_pt.h
+++ b/src/gallium/auxiliary/draw/draw_pt.h
@@ -39,6 +39,8 @@ typedef unsigned (*pt_elt_func)( const void *elts, unsigned idx );
 
 struct draw_pt_middle_end;
 struct draw_context;
+struct draw_prim_info;
+struct draw_vertex_info;
 
 
 #define PT_SHADE      0x1
@@ -164,16 +166,12 @@ void draw_pt_emit_prepare( struct pt_emit *emit,
                            unsigned *max_vertices );
 
 void draw_pt_emit( struct pt_emit *emit,
-		   const float (*vertex_data)[4],
-		   unsigned vertex_count,
-		   unsigned stride,
-		   const ushort *elts,
-		   unsigned count );
+                   const struct draw_vertex_info *vert_info,
+                   const struct draw_prim_info *prim_info);
 
 void draw_pt_emit_linear( struct pt_emit *emit,
-                          const float (*vertex_data)[4],
-                          unsigned stride,
-                          unsigned count );
+                          const struct draw_vertex_info *vert_info,
+                          const struct draw_prim_info *prim_info);
 
 void draw_pt_emit_destroy( struct pt_emit *emit );
 
@@ -188,9 +186,8 @@ void draw_pt_so_emit_prepare( struct pt_so_emit *emit,
                               unsigned prim );
 
 void draw_pt_so_emit( struct pt_so_emit *emit,
-                      const float (*vertex_data)[4],
-                      unsigned vertex_count,
-                      unsigned stride );
+                      const struct draw_vertex_info *vert_info,
+                      const struct draw_prim_info *prim_info );
 
 void draw_pt_so_emit_destroy( struct pt_so_emit *emit );
 
diff --git a/src/gallium/auxiliary/draw/draw_pt_emit.c b/src/gallium/auxiliary/draw/draw_pt_emit.c
index f623c07..0229bcc 100644
--- a/src/gallium/auxiliary/draw/draw_pt_emit.c
+++ b/src/gallium/auxiliary/draw/draw_pt_emit.c
@@ -127,15 +127,17 @@ void draw_pt_emit_prepare( struct pt_emit *emit,
 
 
 void draw_pt_emit( struct pt_emit *emit,
-		   const float (*vertex_data)[4],
-		   unsigned vertex_count,
-		   unsigned stride,
-		   const ushort *elts,
-		   unsigned count )
+                         const struct draw_vertex_info *vert_info,
+                         const struct draw_prim_info *prim_info)
 {
+   const float (*vertex_data)[4] = (const float (*)[4])vert_info->verts->data;
+   unsigned vertex_count = vert_info->count;
+   unsigned stride = vert_info->stride;
+   const ushort *elts = prim_info->elts;
    struct draw_context *draw = emit->draw;
    struct translate *translate = emit->translate;
    struct vbuf_render *render = draw->render;
+   unsigned start, i;
    void *hw_verts;
 
    /* XXX: need to flush to get prim_vbuf.c to release its allocation?? 
@@ -190,23 +192,31 @@ void draw_pt_emit( struct pt_emit *emit,
                            0, 
                            vertex_count - 1 );
 
-   render->draw_elements(render,
-                         elts,
-                         count);
+   for (start = i = 0;
+        i < prim_info->primitive_count;
+        start += prim_info->primitive_lengths[i], i++)
+   {
+      render->draw_elements(render,
+                            elts + start,
+                            prim_info->primitive_lengths[i]);
+   }
 
    render->release_vertices(render);
 }
 
 
 void draw_pt_emit_linear(struct pt_emit *emit,
-                         const float (*vertex_data)[4],
-                         unsigned stride,
-                         unsigned count)
+                         const struct draw_vertex_info *vert_info,
+                         const struct draw_prim_info *prim_info)
 {
+   const float (*vertex_data)[4] = (const float (*)[4])vert_info->verts->data;
+   unsigned stride = vert_info->stride;
+   unsigned count = vert_info->count;
    struct draw_context *draw = emit->draw;
    struct translate *translate = emit->translate;
    struct vbuf_render *render = draw->render;
    void *hw_verts;
+   unsigned start, i;
 
 #if 0
    debug_printf("Linear emit\n");
@@ -258,7 +268,14 @@ void draw_pt_emit_linear(struct pt_emit *emit,
 
    render->unmap_vertices( render, 0, count - 1 );
 
-   render->draw_arrays(render, 0, count);
+   for (start = i = 0;
+        i < prim_info->primitive_count;
+        start += prim_info->primitive_lengths[i], i++)
+   {
+      render->draw_arrays(render,
+                          start,
+                          prim_info->primitive_lengths[i]);
+   }
 
    render->release_vertices(render);
 
diff --git a/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline.c b/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline.c
index 2301e54..4e39d55 100644
--- a/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline.c
+++ b/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline.c
@@ -127,76 +127,145 @@ static void fetch_pipeline_prepare( struct draw_pt_middle_end *middle,
 }
 
 
+static void fetch( struct pt_fetch *fetch,
+                   const struct draw_fetch_info *fetch_info,
+                   char *output)
+{
+   if (fetch_info->linear) {
+      draw_pt_fetch_run_linear( fetch,
+                                fetch_info->start,
+                                fetch_info->count,
+                                output );
+   }
+   else {
+      draw_pt_fetch_run( fetch,
+                         fetch_info->elts, 
+                         fetch_info->count,
+                         output );
+   }
+}
 
-static void fetch_pipeline_run( struct draw_pt_middle_end *middle,
-                                const unsigned *fetch_elts,
-                                unsigned fetch_count,
-                                const ushort *draw_elts,
-                                unsigned draw_count )
+
+static void pipeline(struct fetch_pipeline_middle_end *fpme,
+                     const struct draw_vertex_info *vert_info,
+                     const struct draw_prim_info *prim_info)
+{
+   if (prim_info->linear)
+      draw_pipeline_run_linear( fpme->draw,
+                                vert_info,
+                                prim_info);
+   else
+      draw_pipeline_run( fpme->draw,
+                         vert_info,
+                         prim_info );
+}
+
+static void emit(struct pt_emit *emit,
+                 const struct draw_vertex_info *vert_info,
+                 const struct draw_prim_info *prim_info)
+{
+   if (prim_info->linear) {
+      draw_pt_emit_linear(emit, vert_info, prim_info);
+   }
+   else {
+      draw_pt_emit(emit, vert_info, prim_info);
+   }
+}
+
+
+static void draw_vertex_shader_run(struct draw_vertex_shader *vshader,
+                                   const void *constants[PIPE_MAX_CONSTANT_BUFFERS], 
+                                   const struct draw_vertex_info *input_verts,
+                                   struct draw_vertex_info *output_verts )
+{
+   output_verts->vertex_size = input_verts->vertex_size;
+   output_verts->stride = input_verts->vertex_size;
+   output_verts->count = input_verts->count;
+   output_verts->verts =
+      (struct vertex_header *)MALLOC(output_verts->vertex_size *
+                                     output_verts->count);
+
+   vshader->run_linear(vshader,
+                       (const float (*)[4])input_verts->verts->data,
+                       (      float (*)[4])output_verts->verts->data,
+                       constants,
+                       input_verts->count,
+                       input_verts->vertex_size,
+                       input_verts->vertex_size);
+}
+
+static void fetch_pipeline_generic( struct draw_pt_middle_end *middle,
+                                    const struct draw_fetch_info *fetch_info,
+                                    const struct draw_prim_info *prim_info )
 {
    struct fetch_pipeline_middle_end *fpme = (struct fetch_pipeline_middle_end *)middle;
    struct draw_context *draw = fpme->draw;
    struct draw_vertex_shader *vshader = draw->vs.vertex_shader;
    struct draw_geometry_shader *gshader = draw->gs.geometry_shader;
-   unsigned opt = fpme->opt;
-   struct vertex_header *pipeline_verts;
-   unsigned alloc_count = draw_max_output_vertices(draw,
-                                                   fpme->input_prim,
-                                                   fetch_count);
-
-   pipeline_verts =
-      (struct vertex_header *)MALLOC(fpme->vertex_size * alloc_count);
-
-   if (!pipeline_verts) {
-      /* Not much we can do here - just skip the rendering.
-       */
+   struct draw_prim_info gs_prim_info;
+   struct draw_vertex_info fetched_vert_info;
+   struct draw_vertex_info vs_vert_info;
+   struct draw_vertex_info gs_vert_info;
+   struct draw_vertex_info *vert_info;
+
+   fetched_vert_info.count = fetch_info->count;
+   fetched_vert_info.vertex_size = fpme->vertex_size;
+   fetched_vert_info.verts =
+      (struct vertex_header *)MALLOC(fetched_vert_info.vertex_size *
+                                     fetch_info->count);
+   if (!fetched_vert_info.verts) {
       assert(0);
       return;
    }
 
-   /* Fetch into our vertex buffer
+   /* Fetch into our vertex buffer.
+    */
+   fetch( fpme->fetch, fetch_info, (char *)fetched_vert_info.verts );
+
+   /* Finished with fetch:
     */
-   draw_pt_fetch_run( fpme->fetch,
-		      fetch_elts, 
-		      fetch_count,
-		      (char *)pipeline_verts );
+   fetch_info = NULL;
+   vert_info = &fetched_vert_info;
 
    /* Run the shader, note that this overwrites the data[] parts of
     * the pipeline verts.
     */
-   if (opt & PT_SHADE)
-   {
-      vshader->run_linear(vshader,
-                          (const float (*)[4])pipeline_verts->data,
-                          (      float (*)[4])pipeline_verts->data,
-                          draw->pt.user.vs_constants,
-                          fetch_count,
-                          fpme->vertex_size,
-                          fpme->vertex_size);
-      if (gshader) {
-         fetch_count =
-            draw_geometry_shader_run(gshader,
-                                     fpme->input_prim,
-                                     (const float (*)[4])pipeline_verts->data,
-                                     (      float (*)[4])pipeline_verts->data,
-                                     draw->pt.user.gs_constants,
-                                     fetch_count,
-                                     fpme->vertex_size,
-                                     fpme->vertex_size);
-         debug_assert(fetch_count <= alloc_count);
-      }
+   if (fpme->opt & PT_SHADE) { 
+      draw_vertex_shader_run(vshader,
+                             draw->pt.user.vs_constants,
+                             vert_info,
+                             &vs_vert_info);
+
+      FREE(vert_info->verts);
+      vert_info = &vs_vert_info;
    }
 
-   /* stream output needs to be done before clipping */
+   if ((fpme->opt & PT_SHADE) && gshader) {
+      draw_geometry_shader_run(gshader,
+                               draw->pt.user.gs_constants,
+                               vert_info,
+                               prim_info,
+                               &gs_vert_info,
+                               &gs_prim_info);
+         
+         
+      FREE(vert_info->verts);
+      vert_info = &gs_vert_info;
+      prim_info = &gs_prim_info;
+   }
+
+
+   /* Stream output needs to be done before clipping.
+    *
+    * XXX: Stream output surely needs to respect the prim_info->elt
+    *      lists.
+    */
    draw_pt_so_emit( fpme->so_emit,
-		    (const float (*)[4])pipeline_verts->data,
-		    fetch_count,
-		    fpme->vertex_size );
+                    vert_info,
+                    prim_info );
 
    if (draw_pt_post_vs_run( fpme->post_vs,
-			    pipeline_verts,
-			    fetch_count,
-			    fpme->vertex_size ))
+                            vert_info ))
    {
       opt |= PT_PIPELINE;
    }
@@ -204,25 +273,38 @@ static void fetch_pipeline_run( struct draw_pt_middle_end *middle,
    /* Do we need to run the pipeline?
     */
    if (opt & PT_PIPELINE) {
-      draw_pipeline_run( fpme->draw,
-                         fpme->output_prim,
-                         pipeline_verts,
-                         fetch_count,
-                         fpme->vertex_size,
-                         draw_elts,
-                         draw_count );
+      pipeline( fpme->draw,
+                vert_info,
+                prim_info );
    }
    else {
-      draw_pt_emit( fpme->emit,
-		    (const float (*)[4])pipeline_verts->data,
-		    fetch_count,
-		    fpme->vertex_size,
-		    draw_elts,
-		    draw_count );
+      emit( fpme->emit,
+            vert_info,
+            prim_info );
    }
 
+}
 
-   FREE(pipeline_verts);
+static void fetch_pipeline_run( struct draw_pt_middle_end *middle,
+                                const unsigned *fetch_elts,
+                                unsigned fetch_count,
+                                const ushort *draw_elts,
+                                unsigned draw_count )
+{
+   struct draw_fetch_info fetch_info;
+   struct draw_prim_info prim_info;
+
+   fetch_info.linear = FALSE;
+   fetch_info.start = 0;
+   fetch_info.elts = fetch_elts;
+   fetch_info.count = fetch_count;
+
+   prim_info.linear = FALSE;
+   prim_info.start = 0;
+   prim_info.count = draw_count;
+   prim_info.elts = draw_elts;
+
+   fetch_pipeline_generic( middle, &fetch_info, &prim_info );
 }
 
 
@@ -230,91 +312,20 @@ static void fetch_pipeline_linear_run( struct draw_pt_middle_end *middle,
                                        unsigned start,
                                        unsigned count)
 {
-   struct fetch_pipeline_middle_end *fpme = (struct fetch_pipeline_middle_end *)middle;
-   struct draw_context *draw = fpme->draw;
-   struct draw_vertex_shader *shader = draw->vs.vertex_shader;
-   struct draw_geometry_shader *geometry_shader = draw->gs.geometry_shader;
-   unsigned opt = fpme->opt;
-   struct vertex_header *pipeline_verts;
-   unsigned alloc_count = draw_max_output_vertices(draw,
-                                                   fpme->input_prim,
-                                                   count);
-
-   pipeline_verts =
-      (struct vertex_header *)MALLOC(fpme->vertex_size * alloc_count);
-
-   if (!pipeline_verts) {
-      /* Not much we can do here - just skip the rendering.
-       */
-      assert(0);
-      return;
-   }
+   struct draw_fetch_info fetch_info;
+   struct draw_prim_info prim_info;
 
-   /* Fetch into our vertex buffer
-    */
-   draw_pt_fetch_run_linear( fpme->fetch,
-                             start,
-                             count,
-                             (char *)pipeline_verts );
+   fetch_info.linear = TRUE;
+   fetch_info.start = start;
+   fetch_info.count = count;
+   fetch_info.elts = NULL;
 
-   /* Run the shader, note that this overwrites the data[] parts of
-    * the pipeline verts.
-    */
-   if (opt & PT_SHADE)
-   {
-      shader->run_linear(shader,
-			 (const float (*)[4])pipeline_verts->data,
-			 (      float (*)[4])pipeline_verts->data,
-                         draw->pt.user.vs_constants,
-			 count,
-			 fpme->vertex_size,
-			 fpme->vertex_size);
-
-      if (geometry_shader) {
-         count =
-            draw_geometry_shader_run(geometry_shader,
-                                     fpme->input_prim,
-                                     (const float (*)[4])pipeline_verts->data,
-                                     (      float (*)[4])pipeline_verts->data,
-                                     draw->pt.user.gs_constants,
-                                     count,
-                                     fpme->vertex_size,
-                                     fpme->vertex_size);
-         debug_assert(count <= alloc_count);
-      }
-   }
-
-   /* stream output needs to be done before clipping */
-   draw_pt_so_emit( fpme->so_emit,
-		    (const float (*)[4])pipeline_verts->data,
-		    count,
-		    fpme->vertex_size );
+   prim_info.linear = TRUE;
+   prim_info.start = 0;
+   prim_info.count = count;
+   prim_info.elts = NULL;
 
-   if (draw_pt_post_vs_run( fpme->post_vs,
-			    pipeline_verts,
-			    count,
-			    fpme->vertex_size ))
-   {
-      opt |= PT_PIPELINE;
-   }
-
-   /* Do we need to run the pipeline?
-    */
-   if (opt & PT_PIPELINE) {
-      draw_pipeline_run_linear( fpme->draw,
-                                fpme->output_prim,
-                                pipeline_verts,
-                                count,
-                                fpme->vertex_size);
-   }
-   else {
-      draw_pt_emit_linear( fpme->emit,
-                           (const float (*)[4])pipeline_verts->data,
-                           fpme->vertex_size,
-                           count );
-   }
-
-   FREE(pipeline_verts);
+   fetch_pipeline_generic( middle, &fetch_info, &prim_info );
 }
 
 
@@ -325,92 +336,20 @@ static boolean fetch_pipeline_linear_run_elts( struct draw_pt_middle_end *middle
                                             const ushort *draw_elts,
                                             unsigned draw_count )
 {
-   struct fetch_pipeline_middle_end *fpme = (struct fetch_pipeline_middle_end *)middle;
-   struct draw_context *draw = fpme->draw;
-   struct draw_vertex_shader *shader = draw->vs.vertex_shader;
-   struct draw_geometry_shader *geometry_shader = draw->gs.geometry_shader;
-   unsigned opt = fpme->opt;
-   struct vertex_header *pipeline_verts;
-   unsigned alloc_count = draw_max_output_vertices(draw,
-                                                   fpme->input_prim,
-                                                   count);
+   struct draw_fetch_info fetch_info;
+   struct draw_prim_info prim_info;
 
-   pipeline_verts =
-      (struct vertex_header *)MALLOC(fpme->vertex_size * alloc_count);
+   fetch_info.linear = TRUE;
+   fetch_info.start = start;
+   fetch_info.count = count;
+   fetch_info.elts = NULL;
 
-   if (!pipeline_verts)
-      return FALSE;
-
-   /* Fetch into our vertex buffer
-    */
-   draw_pt_fetch_run_linear( fpme->fetch,
-                             start,
-                             count,
-                             (char *)pipeline_verts );
-
-   /* Run the shader, note that this overwrites the data[] parts of
-    * the pipeline verts.
-    */
-   if (opt & PT_SHADE)
-   {
-      shader->run_linear(shader,
-			 (const float (*)[4])pipeline_verts->data,
-			 (      float (*)[4])pipeline_verts->data,
-                         draw->pt.user.vs_constants,
-			 count,
-			 fpme->vertex_size,
-			 fpme->vertex_size);
-
-      if (geometry_shader) {
-         count =
-            draw_geometry_shader_run(geometry_shader,
-                                     fpme->input_prim,
-                                     (const float (*)[4])pipeline_verts->data,
-                                     (      float (*)[4])pipeline_verts->data,
-                                     draw->pt.user.gs_constants,
-                                     count,
-                                     fpme->vertex_size,
-                                     fpme->vertex_size);
-         debug_assert(count <= alloc_count);
-      }
-   }
-
-   /* stream output needs to be done before clipping */
-   draw_pt_so_emit( fpme->so_emit,
-		    (const float (*)[4])pipeline_verts->data,
-		    count,
-		    fpme->vertex_size );
-
-   if (draw_pt_post_vs_run( fpme->post_vs,
-			    pipeline_verts,
-			    count,
-			    fpme->vertex_size ))
-   {
-      opt |= PT_PIPELINE;
-   }
-
-   /* Do we need to run the pipeline?
-    */
-   if (opt & PT_PIPELINE) {
-      draw_pipeline_run( fpme->draw,
-                         fpme->output_prim,
-                         pipeline_verts,
-                         count,
-                         fpme->vertex_size,
-                         draw_elts,
-                         draw_count );
-   }
-   else {
-      draw_pt_emit( fpme->emit,
-		    (const float (*)[4])pipeline_verts->data,
-		    count,
-		    fpme->vertex_size,
-		    draw_elts,
-		    draw_count );
-   }
+   prim_info.linear = FALSE;
+   prim_info.start = 0;
+   prim_info.count = draw_count;
+   prim_info.elts = draw_elts;
 
-   FREE(pipeline_verts);
-   return TRUE;
+   fetch_pipeline_generic( middle, &fetch_info, &prim_info );
 }
 
 
diff --git a/src/gallium/auxiliary/draw/draw_pt_so_emit.c b/src/gallium/auxiliary/draw/draw_pt_so_emit.c
index bb153ce..2bdfef1 100644
--- a/src/gallium/auxiliary/draw/draw_pt_so_emit.c
+++ b/src/gallium/auxiliary/draw/draw_pt_so_emit.c
@@ -133,10 +133,12 @@ void draw_pt_so_emit_prepare( struct pt_so_emit *emit,
 
 
 void draw_pt_so_emit( struct pt_so_emit *emit,
-		   const float (*vertex_data)[4],
-		   unsigned vertex_count,
-		   unsigned stride )
+                      const struct draw_vertex_info *vert_info,
+                      const struct draw_prim_info *prim_info )
 {
+   const float (*vertex_data)[4] = vert_info->verts;
+   unsigned vertex_count = vert_info->count;
+   unsigned stride = vert_info->stride;
    struct draw_context *draw = emit->draw;
    struct translate *translate = emit->translate;
    struct vbuf_render *render = draw->render;
@@ -166,8 +168,22 @@ void draw_pt_so_emit( struct pt_so_emit *emit,
 
    translate->set_buffer(translate, 0, vertex_data,
                          stride, ~0);
-   translate->run(translate, 0, vertex_count,
-                  draw->instance_id, so_buffer);
+   
+   for (start = i = 0;
+        i < prim_info->primitive_count;
+        start += prim_info->primitive_lengths[i], i++)
+   {
+      unsigned count = prim_info->primitive_lengths[i];
+      
+      if (prim_info->linear) {
+         translate->runXXX(translate, start, count,
+                           draw->instance_id, so_buffer);
+      }
+      else {
+         translate->runYYY(translate, start, count,
+                           draw->instance_id, so_buffer);
+      }
+   }
 
    render->set_stream_output_info(render, 0, vertex_count);
 }



More information about the mesa-commit mailing list