1bf215546Sopenharmony_ci/**************************************************************************
2bf215546Sopenharmony_ci *
3bf215546Sopenharmony_ci * Copyright 2010 VMware, Inc.
4bf215546Sopenharmony_ci * All Rights Reserved.
5bf215546Sopenharmony_ci *
6bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
7bf215546Sopenharmony_ci * copy of this software and associated documentation files (the
8bf215546Sopenharmony_ci * "Software"), to deal in the Software without restriction, including
9bf215546Sopenharmony_ci * without limitation the rights to use, copy, modify, merge, publish,
10bf215546Sopenharmony_ci * distribute, sub license, and/or sell copies of the Software, and to
11bf215546Sopenharmony_ci * permit persons to whom the Software is furnished to do so, subject to
12bf215546Sopenharmony_ci * the following conditions:
13bf215546Sopenharmony_ci *
14bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the
15bf215546Sopenharmony_ci * next paragraph) shall be included in all copies or substantial portions
16bf215546Sopenharmony_ci * of the Software.
17bf215546Sopenharmony_ci *
18bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19bf215546Sopenharmony_ci * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20bf215546Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21bf215546Sopenharmony_ci * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
22bf215546Sopenharmony_ci * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23bf215546Sopenharmony_ci * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24bf215546Sopenharmony_ci * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25bf215546Sopenharmony_ci *
26bf215546Sopenharmony_ci **************************************************************************/
27bf215546Sopenharmony_ci
28bf215546Sopenharmony_ci#include "lp_context.h"
29bf215546Sopenharmony_ci#include "lp_state.h"
30bf215546Sopenharmony_ci#include "lp_texture.h"
31bf215546Sopenharmony_ci
32bf215546Sopenharmony_ci#include "util/u_memory.h"
33bf215546Sopenharmony_ci#include "draw/draw_context.h"
34bf215546Sopenharmony_ci
35bf215546Sopenharmony_cistatic struct pipe_stream_output_target *
36bf215546Sopenharmony_cillvmpipe_create_so_target(struct pipe_context *pipe,
37bf215546Sopenharmony_ci                          struct pipe_resource *buffer,
38bf215546Sopenharmony_ci                          unsigned buffer_offset,
39bf215546Sopenharmony_ci                          unsigned buffer_size)
40bf215546Sopenharmony_ci{
41bf215546Sopenharmony_ci   struct draw_so_target *t;
42bf215546Sopenharmony_ci
43bf215546Sopenharmony_ci   t = CALLOC_STRUCT(draw_so_target);
44bf215546Sopenharmony_ci   if (!t)
45bf215546Sopenharmony_ci      return NULL;
46bf215546Sopenharmony_ci
47bf215546Sopenharmony_ci   t->target.context = pipe;
48bf215546Sopenharmony_ci   t->target.reference.count = 1;
49bf215546Sopenharmony_ci   pipe_resource_reference(&t->target.buffer, buffer);
50bf215546Sopenharmony_ci   t->target.buffer_offset = buffer_offset;
51bf215546Sopenharmony_ci   t->target.buffer_size = buffer_size;
52bf215546Sopenharmony_ci   return &t->target;
53bf215546Sopenharmony_ci}
54bf215546Sopenharmony_ci
55bf215546Sopenharmony_cistatic void
56bf215546Sopenharmony_cillvmpipe_so_target_destroy(struct pipe_context *pipe,
57bf215546Sopenharmony_ci                           struct pipe_stream_output_target *target)
58bf215546Sopenharmony_ci{
59bf215546Sopenharmony_ci   pipe_resource_reference(&target->buffer, NULL);
60bf215546Sopenharmony_ci   FREE(target);
61bf215546Sopenharmony_ci}
62bf215546Sopenharmony_ci
63bf215546Sopenharmony_cistatic uint32_t
64bf215546Sopenharmony_cillvmpipe_so_offset(struct pipe_stream_output_target *so_target)
65bf215546Sopenharmony_ci{
66bf215546Sopenharmony_ci   struct draw_so_target *target = (struct draw_so_target *)so_target;
67bf215546Sopenharmony_ci   return target->internal_offset;
68bf215546Sopenharmony_ci}
69bf215546Sopenharmony_ci
70bf215546Sopenharmony_cistatic void
71bf215546Sopenharmony_cillvmpipe_set_so_targets(struct pipe_context *pipe,
72bf215546Sopenharmony_ci                        unsigned num_targets,
73bf215546Sopenharmony_ci                        struct pipe_stream_output_target **targets,
74bf215546Sopenharmony_ci                        const unsigned *offsets)
75bf215546Sopenharmony_ci{
76bf215546Sopenharmony_ci   struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe);
77bf215546Sopenharmony_ci   int i;
78bf215546Sopenharmony_ci   for (i = 0; i < num_targets; i++) {
79bf215546Sopenharmony_ci      const boolean append = (offsets[i] == (unsigned)-1);
80bf215546Sopenharmony_ci      /*
81bf215546Sopenharmony_ci       * Warn if the so target was created in another context.
82bf215546Sopenharmony_ci       * XXX Not entirely sure if mesa/st may rely on this?
83bf215546Sopenharmony_ci       * Otherwise should just assert.
84bf215546Sopenharmony_ci       */
85bf215546Sopenharmony_ci      if (targets[i] && targets[i]->context != pipe) {
86bf215546Sopenharmony_ci         debug_printf("Illegal setting of so target with target %d created in "
87bf215546Sopenharmony_ci                       "another context\n", i);
88bf215546Sopenharmony_ci      }
89bf215546Sopenharmony_ci      pipe_so_target_reference((struct pipe_stream_output_target **)&llvmpipe->so_targets[i], targets[i]);
90bf215546Sopenharmony_ci      /* If we're not appending then lets set the internal
91bf215546Sopenharmony_ci         offset to what was requested */
92bf215546Sopenharmony_ci      if (!append && llvmpipe->so_targets[i]) {
93bf215546Sopenharmony_ci         llvmpipe->so_targets[i]->internal_offset = offsets[i];
94bf215546Sopenharmony_ci      }
95bf215546Sopenharmony_ci
96bf215546Sopenharmony_ci      if (targets[i]) {
97bf215546Sopenharmony_ci         void *buf = llvmpipe_resource(targets[i]->buffer)->data;
98bf215546Sopenharmony_ci         llvmpipe->so_targets[i]->mapping = buf;
99bf215546Sopenharmony_ci      }
100bf215546Sopenharmony_ci   }
101bf215546Sopenharmony_ci
102bf215546Sopenharmony_ci   for (; i < llvmpipe->num_so_targets; i++) {
103bf215546Sopenharmony_ci      pipe_so_target_reference((struct pipe_stream_output_target **)&llvmpipe->so_targets[i], NULL);
104bf215546Sopenharmony_ci   }
105bf215546Sopenharmony_ci   llvmpipe->num_so_targets = num_targets;
106bf215546Sopenharmony_ci
107bf215546Sopenharmony_ci   draw_set_mapped_so_targets(llvmpipe->draw, llvmpipe->num_so_targets,
108bf215546Sopenharmony_ci                              llvmpipe->so_targets);
109bf215546Sopenharmony_ci}
110bf215546Sopenharmony_ci
111bf215546Sopenharmony_civoid
112bf215546Sopenharmony_cillvmpipe_init_so_funcs(struct llvmpipe_context *pipe)
113bf215546Sopenharmony_ci{
114bf215546Sopenharmony_ci   pipe->pipe.create_stream_output_target = llvmpipe_create_so_target;
115bf215546Sopenharmony_ci   pipe->pipe.stream_output_target_destroy = llvmpipe_so_target_destroy;
116bf215546Sopenharmony_ci   pipe->pipe.set_stream_output_targets = llvmpipe_set_so_targets;
117bf215546Sopenharmony_ci   pipe->pipe.stream_output_target_offset = llvmpipe_so_offset;
118bf215546Sopenharmony_ci}
119