llvmpipe: fix race between draw and setting fragment shader.
[mesa.git] / src / gallium / drivers / llvmpipe / lp_state_so.c
index fa58f79c9c15326578c12b29b95c675bb7297d8d..0fd38c17e5073e42793c5cd29df648319ebbb6a3 100644 (file)
@@ -64,17 +64,31 @@ static void
 llvmpipe_set_so_targets(struct pipe_context *pipe,
                         unsigned num_targets,
                         struct pipe_stream_output_target **targets,
-                        unsigned append_bitmask)
+                        const unsigned *offsets)
 {
    struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe);
    int i;
    for (i = 0; i < num_targets; i++) {
+      const boolean append = (offsets[i] == (unsigned)-1);
+      /*
+       * Warn if the so target was created in another context.
+       * XXX Not entirely sure if mesa/st may rely on this?
+       * Otherwise should just assert.
+       */
+      if (targets[i] && targets[i]->context != pipe) {
+         debug_printf("Illegal setting of so target with target %d created in "
+                       "another context\n", i);
+      }
       pipe_so_target_reference((struct pipe_stream_output_target **)&llvmpipe->so_targets[i], targets[i]);
-      /* if we're not appending then lets reset the internal
-         data of our so target */
-      if (!(append_bitmask & (1 << i)) && llvmpipe->so_targets[i]) {
-         llvmpipe->so_targets[i]->internal_offset = 0;
-         llvmpipe->so_targets[i]->emitted_vertices = 0;
+      /* If we're not appending then lets set the internal
+         offset to what was requested */
+      if (!append && llvmpipe->so_targets[i]) {
+         llvmpipe->so_targets[i]->internal_offset = offsets[i];
+      }
+
+      if (targets[i]) {
+         void *buf = llvmpipe_resource(targets[i]->buffer)->data;
+         llvmpipe->so_targets[i]->mapping = buf;
       }
    }
 
@@ -82,6 +96,9 @@ llvmpipe_set_so_targets(struct pipe_context *pipe,
       pipe_so_target_reference((struct pipe_stream_output_target **)&llvmpipe->so_targets[i], NULL);
    }
    llvmpipe->num_so_targets = num_targets;
+
+   draw_set_mapped_so_targets(llvmpipe->draw, llvmpipe->num_so_targets,
+                              llvmpipe->so_targets);
 }
 
 void