tgsi/ureg: make the dst register match the src indirection
[mesa.git] / src / gallium / auxiliary / draw / draw_prim_assembler.c
1 /**************************************************************************
2 *
3 * Copyright 2013 VMware, Inc.
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 **************************************************************************/
27
28 #include "draw_prim_assembler.h"
29
30 #include "util/u_debug.h"
31 #include "util/u_memory.h"
32 #include "util/u_prim.h"
33
34 #include "pipe/p_defines.h"
35
36 struct draw_assembler
37 {
38 struct draw_context *draw;
39
40 struct draw_prim_info *output_prims;
41 struct draw_vertex_info *output_verts;
42
43 const struct draw_prim_info *input_prims;
44 const struct draw_vertex_info *input_verts;
45 };
46
47 boolean
48 draw_prim_assembler_is_required(const struct draw_context *draw,
49 const struct draw_prim_info *prim_info,
50 const struct draw_vertex_info *vert_info)
51 {
52 switch (prim_info->prim) {
53 case PIPE_PRIM_LINES_ADJACENCY:
54 case PIPE_PRIM_LINE_STRIP_ADJACENCY:
55 case PIPE_PRIM_TRIANGLES_ADJACENCY:
56 case PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY:
57 return TRUE;
58 default:
59 return FALSE;
60 }
61 }
62
63 /*
64 * Copy the vertex header along with its data from the current
65 * vertex buffer into a buffer holding vertices arranged
66 * into decomposed primitives (i.e. buffer without the
67 * adjacency vertices)
68 */
69 static void
70 copy_verts(struct draw_assembler *asmblr,
71 unsigned *indices, unsigned num_indices)
72 {
73 unsigned i;
74
75 char *output = (char*)asmblr->output_verts->verts;
76 const char *input = (const char*)asmblr->input_verts->verts;
77
78 for (i = 0; i < num_indices; ++i) {
79 unsigned idx = indices[i];
80 unsigned output_offset =
81 asmblr->output_verts->count * asmblr->output_verts->stride;
82 unsigned input_offset = asmblr->input_verts->stride * idx;
83 memcpy(output + output_offset, input + input_offset,
84 asmblr->input_verts->vertex_size);
85 asmblr->output_verts->count += 1;
86 }
87 }
88
89 static void
90 prim_point(struct draw_assembler *asmblr,
91 unsigned idx)
92 {
93 unsigned indices[1];
94
95 indices[0] = idx;
96
97 copy_verts(asmblr, indices, 1);
98 }
99
100 static void
101 prim_line(struct draw_assembler *asmblr,
102 unsigned i0, unsigned i1)
103 {
104 unsigned indices[2];
105
106 indices[0] = i0;
107 indices[1] = i1;
108
109 copy_verts(asmblr, indices, 2);
110 }
111
112 static void
113 prim_line_adj(struct draw_assembler *asmblr,
114 unsigned i0, unsigned i1, unsigned i2, unsigned i3)
115 {
116 unsigned indices[2];
117
118 indices[0] = i1;
119 indices[1] = i2;
120
121 copy_verts(asmblr, indices, 2);
122 }
123
124 static void
125 prim_tri(struct draw_assembler *asmblr,
126 unsigned i0, unsigned i1, unsigned i2)
127 {
128 unsigned indices[3];
129
130 indices[0] = i0;
131 indices[1] = i1;
132 indices[2] = i2;
133
134 copy_verts(asmblr, indices, 3);
135 }
136
137 static void
138 prim_tri_adj(struct draw_assembler *asmblr,
139 unsigned i0, unsigned i1, unsigned i2,
140 unsigned i3, unsigned i4, unsigned i5)
141 {
142 unsigned indices[3];
143
144 indices[0] = i0;
145 indices[1] = i2;
146 indices[2] = i4;
147
148 copy_verts(asmblr, indices, 3);
149 }
150
151
152
153 #define FUNC assembler_run_linear
154 #define GET_ELT(idx) (start + (idx))
155 #include "draw_prim_assembler_tmp.h"
156
157 #define FUNC assembler_run_elts
158 #define LOCAL_VARS const ushort *elts = input_prims->elts;
159 #define GET_ELT(idx) (elts[start + (idx)])
160 #include "draw_prim_assembler_tmp.h"
161
162
163
164 /*
165 * Primitive assembler breaks up adjacency primitives and assembles
166 * the base primitives they represent, e.g. vertices forming
167 * PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY
168 * become vertices forming PIPE_PRIM_TRIANGLES
169 * This is needed because specification says that the adjacency
170 * primitives are only visible in the geometry shader so we need
171 * to get rid of them so that the rest of the pipeline can
172 * process the inputs.
173 */
174 void
175 draw_prim_assembler_run(struct draw_context *draw,
176 const struct draw_prim_info *input_prims,
177 const struct draw_vertex_info *input_verts,
178 struct draw_prim_info *output_prims,
179 struct draw_vertex_info *output_verts)
180 {
181 struct draw_assembler asmblr;
182 unsigned start, i;
183 unsigned assembled_prim = u_assembled_prim(input_prims->prim);
184 unsigned max_primitives = u_decomposed_prims_for_vertices(
185 input_prims->prim, input_prims->count);
186 unsigned max_verts = u_vertices_per_prim(assembled_prim) * max_primitives;
187
188 asmblr.draw = draw;
189 asmblr.output_prims = output_prims;
190 asmblr.output_verts = output_verts;
191 asmblr.input_prims = input_prims;
192 asmblr.input_verts = input_verts;
193
194 output_prims->linear = TRUE;
195 output_prims->elts = NULL;
196 output_prims->start = 0;
197 output_prims->prim = u_assembled_prim(input_prims->prim);
198 output_prims->flags = 0x0;
199 output_prims->primitive_lengths = MALLOC(sizeof(unsigned));
200 output_prims->primitive_lengths[0] = 0;
201 output_prims->primitive_count = 1;
202
203 output_verts->vertex_size = input_verts->vertex_size;
204 output_verts->stride = input_verts->stride;
205 output_verts->verts = (struct vertex_header*)MALLOC(
206 input_verts->vertex_size * max_verts);
207 output_verts->count = 0;
208
209
210 for (start = i = 0; i < input_prims->primitive_count;
211 start += input_prims->primitive_lengths[i], i++)
212 {
213 unsigned count = input_prims->primitive_lengths[i];
214 if (input_prims->linear) {
215 assembler_run_linear(&asmblr, input_prims, input_verts,
216 start, count);
217 } else {
218 assembler_run_elts(&asmblr, input_prims, input_verts,
219 start, count);
220 }
221 }
222
223 output_prims->primitive_lengths[0] = output_verts->count;
224 output_prims->count = output_verts->count;
225 }