[Mesa-dev] [PATCH] draw/softpipe: EXT_transform_feedback support (v1)

Dave Airlie airlied at gmail.com
Thu Jan 5 06:17:54 PST 2012


From: Dave Airlie <airlied at redhat.com>

This replaces the current code with an implementation compatible with
the new gallium interface. I've left some of the remains of the interface
intact so llvmpipe keeps building correctly, and I'll take a look at fixing
llvmpipe up later.

This passes 119/134 of the piglit EXT_transform_feedback tests, the alignment tests fail due to an unrelated integer vertex fetching bug, need to look into the others later.

Signed-off-by: Dave Airlie <airlied at redhat.com>
---
 src/gallium/auxiliary/draw/draw_context.c     |   21 +++--
 src/gallium/auxiliary/draw/draw_context.h     |   12 +++-
 src/gallium/auxiliary/draw/draw_private.h     |    4 +-
 src/gallium/auxiliary/draw/draw_pt_so_emit.c  |  112 ++++++++++++++----------
 src/gallium/auxiliary/draw/draw_vbuf.h        |    3 +-
 src/gallium/auxiliary/draw/draw_vs_exec.c     |    1 +
 src/gallium/drivers/softpipe/sp_context.c     |    1 -
 src/gallium/drivers/softpipe/sp_context.h     |   12 +--
 src/gallium/drivers/softpipe/sp_draw_arrays.c |   62 ++-----------
 src/gallium/drivers/softpipe/sp_prim_vbuf.c   |   11 +--
 src/gallium/drivers/softpipe/sp_query.c       |   25 +++++-
 src/gallium/drivers/softpipe/sp_screen.c      |    5 +-
 src/gallium/drivers/softpipe/sp_setup.c       |    6 +-
 src/gallium/drivers/softpipe/sp_state.h       |    3 -
 src/gallium/drivers/softpipe/sp_state_so.c    |  118 +++++++-----------------
 15 files changed, 179 insertions(+), 217 deletions(-)

diff --git a/src/gallium/auxiliary/draw/draw_context.c b/src/gallium/auxiliary/draw/draw_context.c
index 9c00687..b4acbe1 100644
--- a/src/gallium/auxiliary/draw/draw_context.c
+++ b/src/gallium/auxiliary/draw/draw_context.c
@@ -708,16 +708,25 @@ draw_get_rasterizer_no_cull( struct draw_context *draw,
 }
 
 void
+draw_set_mapped_so_targets(struct draw_context *draw,
+                           int num_targets,
+                           struct draw_so_target *targets[PIPE_MAX_SO_BUFFERS])
+{
+   int i;
+
+   for (i = 0; i < num_targets; i++)
+      draw->so.targets[i] = targets[i];
+   for (i = num_targets; i < PIPE_MAX_SO_BUFFERS; i++)
+      draw->so.targets[i] = NULL;
+
+   draw->so.num_targets = num_targets;
+}
+
+void
 draw_set_mapped_so_buffers(struct draw_context *draw,
                            void *buffers[PIPE_MAX_SO_BUFFERS],
                            unsigned num_buffers)
 {
-   int i;
-
-   for (i = 0; i < num_buffers; ++i) {
-      draw->so.buffers[i] = buffers[i];
-   }
-   draw->so.num_buffers = num_buffers;
 }
 
 void
diff --git a/src/gallium/auxiliary/draw/draw_context.h b/src/gallium/auxiliary/draw/draw_context.h
index 93577d0..6b20130 100644
--- a/src/gallium/auxiliary/draw/draw_context.h
+++ b/src/gallium/auxiliary/draw/draw_context.h
@@ -50,7 +50,11 @@ struct draw_fragment_shader;
 struct tgsi_sampler;
 struct gallivm_state;
 
-
+struct draw_so_target {
+   struct pipe_stream_output_target b;
+   void *mapping;
+   int internal_offset;
+};
 
 struct draw_context *draw_create( struct pipe_context *pipe );
 
@@ -200,6 +204,12 @@ void
 draw_set_mapped_so_buffers(struct draw_context *draw,
                            void *buffers[PIPE_MAX_SO_BUFFERS],
                            unsigned num_buffers);
+
+void
+draw_set_mapped_so_targets(struct draw_context *draw,
+                           int num_targets,
+                           struct draw_so_target *targets[PIPE_MAX_SO_BUFFERS]);
+
 void
 draw_set_so_state(struct draw_context *draw,
                   struct pipe_stream_output_info *state);
diff --git a/src/gallium/auxiliary/draw/draw_private.h b/src/gallium/auxiliary/draw/draw_private.h
index 89653e1..b5de5d2 100644
--- a/src/gallium/auxiliary/draw/draw_private.h
+++ b/src/gallium/auxiliary/draw/draw_private.h
@@ -271,8 +271,8 @@ struct draw_context
    /** Stream output (vertex feedback) state */
    struct {
       struct pipe_stream_output_info state;
-      void *buffers[PIPE_MAX_SO_BUFFERS];
-      uint num_buffers;
+      struct draw_so_target *targets[PIPE_MAX_SO_BUFFERS];
+      uint num_targets;
    } so;
 
    /* Clip derived state:
diff --git a/src/gallium/auxiliary/draw/draw_pt_so_emit.c b/src/gallium/auxiliary/draw/draw_pt_so_emit.c
index 2dc9e29..241a4a6 100644
--- a/src/gallium/auxiliary/draw/draw_pt_so_emit.c
+++ b/src/gallium/auxiliary/draw/draw_pt_so_emit.c
@@ -25,29 +25,29 @@
  *
  **************************************************************************/
 
-#include "draw/draw_context.h"
 #include "draw/draw_private.h"
+#include "draw/draw_vs.h"
+#include "draw/draw_context.h"
 #include "draw/draw_vbuf.h"
 #include "draw/draw_vertex.h"
 #include "draw/draw_pt.h"
 
+#include "pipe/p_state.h"
+
 #include "util/u_math.h"
 #include "util/u_memory.h"
 
 struct pt_so_emit {
    struct draw_context *draw;
 
-   void *buffers[PIPE_MAX_SO_BUFFERS];
-
    unsigned input_vertex_stride;
    const float (*inputs)[4];
 
    boolean has_so;
 
-   boolean single_buffer;
-
    unsigned emitted_primitives;
    unsigned emitted_vertices;
+   unsigned generated_primitives;
 };
 
 
@@ -55,15 +55,15 @@ void draw_pt_so_emit_prepare(struct pt_so_emit *emit)
 {
    struct draw_context *draw = emit->draw;
 
-   emit->has_so = (draw->so.state.num_outputs > 0);
+   emit->has_so = (draw->vs.vertex_shader->state.stream_output.num_outputs > 0);
 
    /* if we have a state with outputs make sure we have
     * buffers to output to */
    if (emit->has_so) {
       boolean has_valid_buffer = FALSE;
       unsigned i;
-      for (i = 0; i < draw->so.num_buffers; ++i) {
-         if (draw->so.buffers[i]) {
+      for (i = 0; i < draw->so.num_targets; ++i) {
+         if (draw->so.targets[i]) {
             has_valid_buffer = TRUE;
             break;
          }
@@ -122,6 +122,29 @@ is_component_writable(unsigned mask,
    }
 }
 
+static inline int mask_num_comps(int register_mask)
+{
+   int comps = 0;
+   switch (register_mask) {
+   case TGSI_WRITEMASK_XYZW:
+      comps = 4;
+      break;
+   case TGSI_WRITEMASK_XYZ:
+      comps = 3;
+      break;
+   case TGSI_WRITEMASK_XY:
+      comps = 2;
+      break;
+   case TGSI_WRITEMASK_X:
+      comps = 1;
+      break;
+   default:
+      assert(0);
+      break;
+   }
+   return comps;
+}
+
 static void so_emit_prim(struct pt_so_emit *so,
                          unsigned *indices,
                          unsigned num_vertices)
@@ -131,57 +154,56 @@ static void so_emit_prim(struct pt_so_emit *so,
    struct draw_context *draw = so->draw;
    const float (*input_ptr)[4];
    const struct pipe_stream_output_info *state =
-      &draw->so.state;
-   float **buffer = 0;
+      &draw->vs.vertex_shader->state.stream_output;
+   float *buffer;
+   int buffer_total_bytes[PIPE_MAX_SO_BUFFERS];
 
    input_ptr = so->inputs;
 
+   ++so->generated_primitives;
+
+   for (i = 0; i < draw->so.num_targets; i++) {
+      struct draw_so_target *target = draw->so.targets[i];
+      buffer_total_bytes[i] = target->internal_offset;
+   }
+
+   /* check have we space to emit prim first - if not don't do anything */
+   for (i = 0; i < num_vertices; ++i) {
+      for (slot = 0; slot < state->num_outputs; ++slot) {
+         unsigned writemask = state->output[slot].register_mask;
+         int ob = state->output[slot].output_buffer;
+
+         if ((buffer_total_bytes[ob] + mask_num_comps(writemask) * sizeof(float)) >
+             draw->so.targets[ob]->b.buffer_size) {
+            return;
+         }
+         buffer_total_bytes[ob] += mask_num_comps(writemask) * sizeof(float);
+      }
+   }
+
    for (i = 0; i < num_vertices; ++i) {
       const float (*input)[4];
       unsigned total_written_compos = 0;
       /*debug_printf("%d) vertex index = %d (prim idx = %d)\n", i, indices[i], prim_idx);*/
       input = (const float (*)[4])(
          (const char *)input_ptr + (indices[i] * input_vertex_stride));
+
       for (slot = 0; slot < state->num_outputs; ++slot) {
          unsigned idx = state->output[slot].register_index;
          unsigned writemask = state->output[slot].register_mask;
          unsigned written_compos = 0;
          unsigned compo;
+         int ob = state->output[slot].output_buffer;
 
-         buffer = (float**)&so->buffers[state->output[slot].output_buffer];
-
-         /*debug_printf("\tSlot = %d, vs_slot = %d, idx = %d:\n",
-           slot, vs_slot, idx);*/
-#if 1
-         assert(!util_is_inf_or_nan(input[idx][0]));
-         assert(!util_is_inf_or_nan(input[idx][1]));
-         assert(!util_is_inf_or_nan(input[idx][2]));
-         assert(!util_is_inf_or_nan(input[idx][3]));
-#endif
+         buffer = (float *)((char *)draw->so.targets[ob]->mapping + draw->so.targets[ob]->b.buffer_offset + draw->so.targets[ob]->internal_offset);
          for (compo = 0; compo < 4; ++compo) {
             if (is_component_writable(writemask, compo)) {
-               float *buf = *buffer;
-               buf[written_compos++] = input[idx][compo];
+               buffer[written_compos++] = input[idx][compo];
             }
          }
-#if 0
-         debug_printf("\t\t(writemask = %d)%f %f %f %f\n",
-                      writemask,
-                      input[idx][0],
-                      input[idx][1],
-                      input[idx][2],
-                      input[idx][3]);
-#endif
-         *buffer += written_compos;
+         draw->so.targets[ob]->internal_offset += written_compos * sizeof(float);
          total_written_compos += written_compos;
       }
-      if (so->single_buffer) {
-         int stride = (int)state->stride -
-                      sizeof(float) * total_written_compos;
-
-         debug_assert(stride >= 0);
-         *buffer = (float*) (((char*)*buffer) + stride);
-      }
    }
    so->emitted_vertices += num_vertices;
    ++so->emitted_primitives;
@@ -235,23 +257,18 @@ void draw_pt_so_emit( struct pt_so_emit *emit,
 {
    struct draw_context *draw = emit->draw;
    struct vbuf_render *render = draw->render;
+   struct pipe_stream_output_info *so;
    unsigned start, i;
 
    if (!emit->has_so)
       return;
 
+   so = &draw->vs.vertex_shader->state.stream_output;
    emit->emitted_vertices = 0;
    emit->emitted_primitives = 0;
+   emit->generated_primitives = 0;
    emit->input_vertex_stride = input_verts->stride;
    emit->inputs = (const float (*)[4])input_verts->verts->data;
-   for (i = 0; i < draw->so.num_buffers; ++i) {
-      emit->buffers[i] = draw->so.buffers[i];
-   }
-   emit->single_buffer = TRUE;
-   for (i = 0; i < draw->so.state.num_outputs; ++i) {
-      if (draw->so.state.output[i].output_buffer != 0)
-         emit->single_buffer = FALSE;
-   }
 
    /* XXX: need to flush to get prim_vbuf.c to release its allocation??*/
    draw_do_flush( draw, DRAW_FLUSH_BACKEND );
@@ -272,7 +289,8 @@ void draw_pt_so_emit( struct pt_so_emit *emit,
 
    render->set_stream_output_info(render,
                                   emit->emitted_primitives,
-                                  emit->emitted_vertices);
+                                  emit->emitted_vertices,
+                                  emit->generated_primitives);
 }
 
 
diff --git a/src/gallium/auxiliary/draw/draw_vbuf.h b/src/gallium/auxiliary/draw/draw_vbuf.h
index e32803c..6496fe3 100644
--- a/src/gallium/auxiliary/draw/draw_vbuf.h
+++ b/src/gallium/auxiliary/draw/draw_vbuf.h
@@ -124,7 +124,8 @@ struct vbuf_render {
     */
    void (*set_stream_output_info)( struct vbuf_render *vbufr,
                                    unsigned primitive_count,
-                                   unsigned vertices_count );
+                                   unsigned vertices_count,
+                                   unsigned primitive_generated );
 };
 
 
diff --git a/src/gallium/auxiliary/draw/draw_vs_exec.c b/src/gallium/auxiliary/draw/draw_vs_exec.c
index d9c4209..3f89881 100644
--- a/src/gallium/auxiliary/draw/draw_vs_exec.c
+++ b/src/gallium/auxiliary/draw/draw_vs_exec.c
@@ -217,6 +217,7 @@ draw_create_vs_exec(struct draw_context *draw,
 
    tgsi_scan_shader(state->tokens, &vs->base.info);
 
+   vs->base.state.stream_output = state->stream_output;
    vs->base.draw = draw;
    vs->base.prepare = vs_exec_prepare;
    vs->base.run_linear = vs_exec_run_linear;
diff --git a/src/gallium/drivers/softpipe/sp_context.c b/src/gallium/drivers/softpipe/sp_context.c
index a720600..1299384 100644
--- a/src/gallium/drivers/softpipe/sp_context.c
+++ b/src/gallium/drivers/softpipe/sp_context.c
@@ -257,7 +257,6 @@ softpipe_create_context( struct pipe_screen *screen,
    softpipe->pipe.set_framebuffer_state = softpipe_set_framebuffer_state;
 
    softpipe->pipe.draw_vbo = softpipe_draw_vbo;
-   /* XXX softpipe->pipe.draw_stream_output = softpipe_draw_stream_output; */
 
    softpipe->pipe.clear = softpipe_clear;
    softpipe->pipe.flush = softpipe_flush_wrapped;
diff --git a/src/gallium/drivers/softpipe/sp_context.h b/src/gallium/drivers/softpipe/sp_context.h
index 5442aba..c657bd6 100644
--- a/src/gallium/drivers/softpipe/sp_context.h
+++ b/src/gallium/drivers/softpipe/sp_context.h
@@ -55,7 +55,6 @@ struct sp_vertex_shader;
 struct sp_velems_state;
 struct sp_so_state;
 
-
 struct softpipe_context {
    struct pipe_context pipe;  /**< base class */
 
@@ -88,13 +87,12 @@ struct softpipe_context {
    struct pipe_viewport_state viewport;
    struct pipe_vertex_buffer vertex_buffer[PIPE_MAX_ATTRIBS];
    struct pipe_index_buffer index_buffer;
-   struct {
-      struct softpipe_resource *buffer[PIPE_MAX_SO_BUFFERS];
-      int offset[PIPE_MAX_SO_BUFFERS];
-      int so_count[PIPE_MAX_SO_BUFFERS];
-      int num_buffers;
-   } so_target;
+
+   struct draw_so_target *so_targets[PIPE_MAX_SO_BUFFERS];
+   int num_so_targets;
+   
    struct pipe_query_data_so_statistics so_stats;
+   unsigned num_primitives_generated;
 
    unsigned num_fragment_samplers;
    unsigned num_fragment_sampler_views;
diff --git a/src/gallium/drivers/softpipe/sp_draw_arrays.c b/src/gallium/drivers/softpipe/sp_draw_arrays.c
index 69b5b96..10b625c 100644
--- a/src/gallium/drivers/softpipe/sp_draw_arrays.c
+++ b/src/gallium/drivers/softpipe/sp_draw_arrays.c
@@ -43,58 +43,6 @@
 
 #include "draw/draw_context.h"
 
-
-
-
-
-void
-softpipe_draw_stream_output(struct pipe_context *pipe, unsigned mode)
-{
-   struct softpipe_context *sp = softpipe_context(pipe);
-   struct draw_context *draw = sp->draw;
-   const unsigned start = 0;
-   const unsigned count = sp->so_target.so_count[0];
-   void *buf = sp->so_target.buffer[0]->data;
-   int offset = sp->so_target.offset[0];
-
-   if (!softpipe_check_render_cond(sp) ||
-       sp->so_target.num_buffers != 1)
-      return;
-
-   sp->reduced_api_prim = u_reduced_prim(mode);
-
-   if (sp->dirty) {
-      softpipe_update_derived(sp, sp->reduced_api_prim);
-   }
-
-   softpipe_map_transfers(sp);
-
-   /* Map so buffers */
-   if (offset < 0) /* we were appending so start from beginning */
-      offset = 0;
-   buf = (void*)((int32_t*)buf + offset);
-   draw_set_mapped_vertex_buffer(draw, 0, buf);
-
-   draw_set_mapped_index_buffer(draw, NULL);
-
-   /* draw! */
-   draw_arrays(draw, mode, start, count);
-
-   /* unmap vertex/index buffers - will cause draw module to flush */
-   draw_set_mapped_vertex_buffer(draw, 0, NULL);
-
-   /*
-    * TODO: Flush only when a user vertex/index buffer is present
-    * (or even better, modify draw module to do this
-    * internally when this condition is seen?)
-    */
-   draw_flush(draw);
-
-   /* Note: leave drawing surfaces mapped */
-   sp->dirty_render_cache = TRUE;
-}
-
-
 /**
  * This function handles drawing indexed and non-indexed prims,
  * instanced and non-instanced drawing, with or without min/max element
@@ -139,6 +87,14 @@ softpipe_draw_vbo(struct pipe_context *pipe,
 
    draw_set_mapped_index_buffer(draw, mapped_indices);
 
+   for (i = 0; i < sp->num_so_targets; i++) {
+      void *buf = softpipe_resource(sp->so_targets[i]->b.buffer)->data;
+      sp->so_targets[i]->mapping = buf;
+   }
+
+   draw_set_mapped_so_targets(draw, sp->num_so_targets,
+                              sp->so_targets);
+
    /* draw! */
    draw_vbo(draw, info);
 
@@ -150,6 +106,8 @@ softpipe_draw_vbo(struct pipe_context *pipe,
       draw_set_mapped_index_buffer(draw, NULL);
    }
 
+   draw_set_mapped_so_targets(draw, 0, NULL);
+
    /*
     * TODO: Flush only when a user vertex/index buffer is present
     * (or even better, modify draw module to do this
diff --git a/src/gallium/drivers/softpipe/sp_prim_vbuf.c b/src/gallium/drivers/softpipe/sp_prim_vbuf.c
index c60249d..acc7e45 100644
--- a/src/gallium/drivers/softpipe/sp_prim_vbuf.c
+++ b/src/gallium/drivers/softpipe/sp_prim_vbuf.c
@@ -543,19 +543,16 @@ sp_vbuf_draw_arrays(struct vbuf_render *vbr, uint start, uint nr)
 }
 
 static void
-sp_vbuf_so_info(struct vbuf_render *vbr, uint primitives, uint vertices)
+sp_vbuf_so_info(struct vbuf_render *vbr, uint primitives, uint vertices,
+                uint prim_generated)
 {
    struct softpipe_vbuf_render *cvbr = softpipe_vbuf_render(vbr);
    struct softpipe_context *softpipe = cvbr->softpipe;
-   unsigned i;
-
-   for (i = 0; i < softpipe->so_target.num_buffers; ++i) {
-      softpipe->so_target.so_count[i] += vertices;
-   }
 
-   softpipe->so_stats.num_primitives_written = primitives;
+   softpipe->so_stats.num_primitives_written += primitives;
    softpipe->so_stats.primitives_storage_needed =
       vertices * 4 /*sizeof(float|int32)*/ * 4 /*x,y,z,w*/;
+   softpipe->num_primitives_generated += prim_generated;
 }
 
 
diff --git a/src/gallium/drivers/softpipe/sp_query.c b/src/gallium/drivers/softpipe/sp_query.c
index c2c48e8..2e54e02 100644
--- a/src/gallium/drivers/softpipe/sp_query.c
+++ b/src/gallium/drivers/softpipe/sp_query.c
@@ -42,6 +42,7 @@ struct softpipe_query {
    uint64_t start;
    uint64_t end;
    struct pipe_query_data_so_statistics so;
+   unsigned num_primitives_generated;
 };
 
 
@@ -59,6 +60,8 @@ softpipe_create_query(struct pipe_context *pipe,
    assert(type == PIPE_QUERY_OCCLUSION_COUNTER ||
           type == PIPE_QUERY_TIME_ELAPSED ||
           type == PIPE_QUERY_SO_STATISTICS ||
+          type == PIPE_QUERY_PRIMITIVES_EMITTED ||
+          type == PIPE_QUERY_PRIMITIVES_GENERATED ||
           type == PIPE_QUERY_GPU_FINISHED ||
           type == PIPE_QUERY_TIMESTAMP ||
           type == PIPE_QUERY_TIMESTAMP_DISJOINT);
@@ -91,8 +94,14 @@ softpipe_begin_query(struct pipe_context *pipe, struct pipe_query *q)
       sq->start = 1000*os_time_get();
       break;
    case PIPE_QUERY_SO_STATISTICS:
-      sq->so.num_primitives_written = 0;
       sq->so.primitives_storage_needed = 0;
+   case PIPE_QUERY_PRIMITIVES_EMITTED:
+      sq->so.num_primitives_written = 0;
+      softpipe->so_stats.num_primitives_written = 0;
+      break;
+   case PIPE_QUERY_PRIMITIVES_GENERATED:
+      sq->num_primitives_generated = 0;
+      softpipe->num_primitives_generated = 0;
       break;
    case PIPE_QUERY_TIMESTAMP:
    case PIPE_QUERY_GPU_FINISHED:
@@ -125,10 +134,14 @@ softpipe_end_query(struct pipe_context *pipe, struct pipe_query *q)
       sq->end = 1000*os_time_get();
       break;
    case PIPE_QUERY_SO_STATISTICS:
-      sq->so.num_primitives_written =
-         softpipe->so_stats.num_primitives_written;
       sq->so.primitives_storage_needed =
          softpipe->so_stats.primitives_storage_needed;
+   case PIPE_QUERY_PRIMITIVES_EMITTED:
+      sq->so.num_primitives_written =
+         softpipe->so_stats.num_primitives_written;
+      break;
+   case PIPE_QUERY_PRIMITIVES_GENERATED:
+      sq->num_primitives_generated = softpipe->num_primitives_generated;
       break;
    case PIPE_QUERY_GPU_FINISHED:
       break;
@@ -166,6 +179,12 @@ softpipe_get_query_result(struct pipe_context *pipe,
              sizeof(struct pipe_query_data_timestamp_disjoint));
    }
       break;
+   case PIPE_QUERY_PRIMITIVES_EMITTED:
+      *result = sq->so.num_primitives_written;
+      break;
+   case PIPE_QUERY_PRIMITIVES_GENERATED:
+      *result = sq->num_primitives_generated;
+      break;
    default:
       *result = sq->end - sq->start;
       break;
diff --git a/src/gallium/drivers/softpipe/sp_screen.c b/src/gallium/drivers/softpipe/sp_screen.c
index e58a486..8e88bb5 100644
--- a/src/gallium/drivers/softpipe/sp_screen.c
+++ b/src/gallium/drivers/softpipe/sp_screen.c
@@ -106,7 +106,10 @@ softpipe_get_param(struct pipe_screen *screen, enum pipe_cap param)
    case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_INTEGER:
       return 1;
    case PIPE_CAP_MAX_STREAM_OUTPUT_BUFFERS:
-      return 0;
+      return 4;
+   case PIPE_CAP_MAX_STREAM_OUTPUT_SEPARATE_COMPONENTS:
+   case PIPE_CAP_MAX_STREAM_OUTPUT_INTERLEAVED_COMPONENTS:
+      return 16*4;
    case PIPE_CAP_PRIMITIVE_RESTART:
       return 1;
    case PIPE_CAP_DEPTHSTENCIL_CLEAR_SEPARATE:
diff --git a/src/gallium/drivers/softpipe/sp_setup.c b/src/gallium/drivers/softpipe/sp_setup.c
index 656d001..0d67af3 100644
--- a/src/gallium/drivers/softpipe/sp_setup.c
+++ b/src/gallium/drivers/softpipe/sp_setup.c
@@ -807,7 +807,7 @@ sp_setup_tri(struct setup_context *setup,
    print_vertex(setup, v2);
 #endif
 
-   if (setup->softpipe->no_rast)
+   if (setup->softpipe->no_rast || setup->softpipe->rasterizer->rasterizer_discard)
       return;
    
    det = calc_det(v0, v1, v2);
@@ -1073,7 +1073,7 @@ sp_setup_line(struct setup_context *setup,
    print_vertex(setup, v1);
 #endif
 
-   if (setup->softpipe->no_rast)
+   if (setup->softpipe->no_rast || setup->softpipe->rasterizer->rasterizer_discard)
       return;
 
    if (dx == 0 && dy == 0)
@@ -1206,7 +1206,7 @@ sp_setup_point(struct setup_context *setup,
    print_vertex(setup, v0);
 #endif
 
-   if (softpipe->no_rast)
+   if (setup->softpipe->no_rast || setup->softpipe->rasterizer->rasterizer_discard)
       return;
 
    assert(setup->softpipe->reduced_prim == PIPE_PRIM_POINTS);
diff --git a/src/gallium/drivers/softpipe/sp_state.h b/src/gallium/drivers/softpipe/sp_state.h
index bdda294..6df40c6 100644
--- a/src/gallium/drivers/softpipe/sp_state.h
+++ b/src/gallium/drivers/softpipe/sp_state.h
@@ -159,9 +159,6 @@ softpipe_draw_vbo(struct pipe_context *pipe,
                   const struct pipe_draw_info *info);
 
 void
-softpipe_draw_stream_output(struct pipe_context *pipe, unsigned mode);
-
-void
 softpipe_map_transfers(struct softpipe_context *sp);
 
 void
diff --git a/src/gallium/drivers/softpipe/sp_state_so.c b/src/gallium/drivers/softpipe/sp_state_so.c
index 31ef384..7abaa1a 100644
--- a/src/gallium/drivers/softpipe/sp_state_so.c
+++ b/src/gallium/drivers/softpipe/sp_state_so.c
@@ -32,109 +32,61 @@
 #include "util/u_format.h"
 #include "util/u_memory.h"
 #include "draw/draw_context.h"
+#include "pipebuffer/pb_buffer.h"
 
-
-static void *
-softpipe_create_stream_output_state(struct pipe_context *pipe,
-                                    const struct pipe_stream_output_info *templ)
-{
-   struct sp_so_state *so;
-   so = (struct sp_so_state *) CALLOC_STRUCT(sp_so_state);
-
-   if (so) {
-      so->base.num_outputs = templ->num_outputs;
-      so->base.stride = templ->stride;
-      memcpy(so->base.output, templ->output,
-             templ->num_outputs * sizeof(templ->output[0]));
-   }
-   return so;
-}
-
-
-static void
-softpipe_bind_stream_output_state(struct pipe_context *pipe,
-                                  void *so)
+static struct pipe_stream_output_target *
+softpipe_create_so_target(struct pipe_context *pipe,
+                          struct pipe_resource *buffer,
+                          unsigned buffer_offset,
+                          unsigned buffer_size)
 {
-   struct softpipe_context *softpipe = softpipe_context(pipe);
-   struct sp_so_state *sp_so = (struct sp_so_state *) so;
-
-   softpipe->so = sp_so;
-
-   softpipe->dirty |= SP_NEW_SO;
-
-   if (sp_so)
-      draw_set_so_state(softpipe->draw, &sp_so->base);
+   struct draw_so_target *t;
+
+   t = CALLOC_STRUCT(draw_so_target);
+   t->b.context = pipe;
+   t->b.reference.count = 1;
+   pipe_resource_reference(&t->b.buffer, buffer);
+   t->b.buffer_offset = buffer_offset;
+   t->b.buffer_size = buffer_size;
+   return &t->b;
 }
 
-
-static void
-softpipe_delete_stream_output_state(struct pipe_context *pipe, void *so)
+static void softpipe_so_target_destroy(struct pipe_context *pipe,
+                                       struct pipe_stream_output_target *target)
 {
-   FREE( so );
+   struct pipe_stream_output_target *b = target;
+   pipe_resource_reference(&b->buffer, NULL);
+   FREE(b);
 }
 
-
-static void
-softpipe_set_stream_output_buffers(struct pipe_context *pipe,
-                                   struct pipe_resource **buffers,
-                                   int *offsets,
-                                   int num_buffers)
+static void softpipe_set_so_targets(struct pipe_context *pipe,
+                                    unsigned num_targets,
+                                    struct pipe_stream_output_target **targets,
+                                    unsigned append_bitmask)
 {
    struct softpipe_context *softpipe = softpipe_context(pipe);
    int i;
-   void *map_buffers[PIPE_MAX_SO_BUFFERS];
-
-   assert(num_buffers <= PIPE_MAX_SO_BUFFERS);
-   if (num_buffers > PIPE_MAX_SO_BUFFERS)
-      num_buffers = PIPE_MAX_SO_BUFFERS;
-
-   softpipe->dirty |= SP_NEW_SO_BUFFERS;
 
-   for (i = 0; i < num_buffers; ++i) {
-      void *mapped;
-      struct softpipe_resource *res = softpipe_resource(buffers[i]);
+   if (softpipe->num_so_targets) {
 
-      if (!res) {
-         /* the whole call is invalid, bail out */
-         softpipe->so_target.num_buffers = 0;
-         draw_set_mapped_so_buffers(softpipe->draw, 0, 0);
-         return;
-      }
+   }
 
-      softpipe->so_target.buffer[i] = res;
-      softpipe->so_target.offset[i] = offsets[i];
-      softpipe->so_target.so_count[i] = 0;
+   for (i = 0; i < num_targets; i++) {
+      pipe_so_target_reference((struct pipe_stream_output_target **)&softpipe->so_targets[i], targets[i]);
+   }
 
-      mapped = res->data;
-      if (offsets[i] >= 0)
-         map_buffers[i] = ((char*)mapped) + offsets[i];
-      else {
-         /* this is a buffer append */
-         assert(!"appending not implemented");
-         map_buffers[i] = mapped;
-      }
+   for (; i < softpipe->num_so_targets; i++) {
+      pipe_so_target_reference((struct pipe_stream_output_target **)&softpipe->so_targets[i], NULL);
    }
-   softpipe->so_target.num_buffers = num_buffers;
 
-   draw_set_mapped_so_buffers(softpipe->draw, map_buffers, num_buffers);
+   softpipe->num_so_targets = num_targets;
 }
 
-
-
 void
 softpipe_init_streamout_funcs(struct pipe_context *pipe)
 {
-#if 0
-   pipe->create_stream_output_state = softpipe_create_stream_output_state;
-   pipe->bind_stream_output_state = softpipe_bind_stream_output_state;
-   pipe->delete_stream_output_state = softpipe_delete_stream_output_state;
-
-   pipe->set_stream_output_buffers = softpipe_set_stream_output_buffers;
-#else
-   (void) softpipe_create_stream_output_state;
-   (void) softpipe_bind_stream_output_state;
-   (void) softpipe_delete_stream_output_state;
-   (void) softpipe_set_stream_output_buffers;
-#endif
+   pipe->create_stream_output_target = softpipe_create_so_target;
+   pipe->stream_output_target_destroy = softpipe_so_target_destroy;
+   pipe->set_stream_output_targets = softpipe_set_so_targets;
 }
 
-- 
1.7.7.4



More information about the mesa-dev mailing list