llvmpipe: add missing fallthrough comments
[mesa.git] / src / gallium / drivers / llvmpipe / lp_state_so.c
index ed2272d05eefbb6df10848bd1b1ddd260b4bbe5d..0fd38c17e5073e42793c5cd29df648319ebbb6a3 100644 (file)
 #include "util/u_memory.h"
 #include "draw/draw_context.h"
 
-
-static void *
-llvmpipe_create_stream_output_state(struct pipe_context *pipe,
-                                    const struct pipe_stream_output_info *templ)
-{
-   struct lp_so_state *so;
-   so = (struct lp_so_state *) CALLOC_STRUCT(lp_so_state);
-
-   if (so) {
-      so->base.num_outputs = templ->num_outputs;
-      memcpy(so->base.stride, templ->stride, sizeof(templ->stride));
-      memcpy(so->base.output, templ->output,
-             templ->num_outputs * sizeof(templ->output[0]));
-   }
-   return so;
-}
-
-static void
-llvmpipe_bind_stream_output_state(struct pipe_context *pipe,
-                                  void *so)
+static struct pipe_stream_output_target *
+llvmpipe_create_so_target(struct pipe_context *pipe,
+                          struct pipe_resource *buffer,
+                          unsigned buffer_offset,
+                          unsigned buffer_size)
 {
-   struct llvmpipe_context *lp = llvmpipe_context(pipe);
-   struct lp_so_state *lp_so = (struct lp_so_state *) so;
-
-   lp->so = lp_so;
-
-   lp->dirty |= LP_NEW_SO;
-
-   if (lp_so)
-      draw_set_so_state(lp->draw, &lp_so->base);
+   struct draw_so_target *t;
+
+   t = CALLOC_STRUCT(draw_so_target);
+   if (!t)
+      return NULL;
+
+   t->target.context = pipe;
+   t->target.reference.count = 1;
+   pipe_resource_reference(&t->target.buffer, buffer);
+   t->target.buffer_offset = buffer_offset;
+   t->target.buffer_size = buffer_size;
+   return &t->target;
 }
-
 static void
-llvmpipe_delete_stream_output_state(struct pipe_context *pipe, void *so)
+llvmpipe_so_target_destroy(struct pipe_context *pipe,
+                           struct pipe_stream_output_target *target)
 {
-   FREE( so );
+   pipe_resource_reference(&target->buffer, NULL);
+   FREE(target);
 }
 
 static void
-llvmpipe_set_stream_output_buffers(struct pipe_context *pipe,
-                                   struct pipe_resource **buffers,
-                                   int *offsets,
-                                   int num_buffers)
+llvmpipe_set_so_targets(struct pipe_context *pipe,
+                        unsigned num_targets,
+                        struct pipe_stream_output_target **targets,
+                        const unsigned *offsets)
 {
-   struct llvmpipe_context *lp = llvmpipe_context(pipe);
+   struct llvmpipe_context *llvmpipe = llvmpipe_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;
-
-   lp->dirty |= LP_NEW_SO_BUFFERS;
-
-   for (i = 0; i < num_buffers; ++i) {
-      void *mapped;
-      struct llvmpipe_resource *res = llvmpipe_resource(buffers[i]);
-
-      if (!res) {
-         /* the whole call is invalid, bail out */
-         lp->so_target.num_buffers = 0;
-         draw_set_mapped_so_buffers(lp->draw, 0, 0);
-         return;
+   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 set the internal
+         offset to what was requested */
+      if (!append && llvmpipe->so_targets[i]) {
+         llvmpipe->so_targets[i]->internal_offset = offsets[i];
       }
 
-      lp->so_target.buffer[i] = res;
-      lp->so_target.offset[i] = offsets[i];
-      lp->so_target.so_count[i] = 0;
-
-      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;
+      if (targets[i]) {
+         void *buf = llvmpipe_resource(targets[i]->buffer)->data;
+         llvmpipe->so_targets[i]->mapping = buf;
       }
    }
-   lp->so_target.num_buffers = num_buffers;
 
-   draw_set_mapped_so_buffers(lp->draw, map_buffers, num_buffers);
+   for (; i < llvmpipe->num_so_targets; i++) {
+      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
-llvmpipe_init_so_funcs(struct llvmpipe_context *llvmpipe)
+llvmpipe_init_so_funcs(struct llvmpipe_context *pipe)
 {
-#if 0
-   llvmpipe->pipe.create_stream_output_state =
-      llvmpipe_create_stream_output_state;
-   llvmpipe->pipe.bind_stream_output_state =
-      llvmpipe_bind_stream_output_state;
-   llvmpipe->pipe.delete_stream_output_state =
-      llvmpipe_delete_stream_output_state;
-
-   llvmpipe->pipe.set_stream_output_buffers =
-      llvmpipe_set_stream_output_buffers;
-#else
-   (void) llvmpipe_create_stream_output_state;
-   (void) llvmpipe_bind_stream_output_state;
-   (void) llvmpipe_delete_stream_output_state;
-   (void) llvmpipe_set_stream_output_buffers;
-#endif
+   pipe->pipe.create_stream_output_target = llvmpipe_create_so_target;
+   pipe->pipe.stream_output_target_destroy = llvmpipe_so_target_destroy;
+   pipe->pipe.set_stream_output_targets = llvmpipe_set_so_targets;
 }