indices: add comments, assertions in u_indices.c file
[mesa.git] / src / gallium / auxiliary / indices / u_indices.c
1 /*
2 * Copyright 2009 VMware, Inc.
3 * All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * on the rights to use, copy, modify, merge, publish, distribute, sub
9 * license, and/or sell copies of the Software, and to permit persons to whom
10 * the Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice (including the next
13 * paragraph) shall be included in all copies or substantial portions of the
14 * Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
19 * VMWARE AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
20 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
21 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
22 * USE OR OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25 #include "u_indices.h"
26 #include "u_indices_priv.h"
27
28 static void translate_memcpy_ushort( const void *in,
29 unsigned start,
30 unsigned nr,
31 void *out )
32 {
33 memcpy(out, &((short *)in)[start], nr*sizeof(short));
34 }
35
36 static void translate_memcpy_uint( const void *in,
37 unsigned start,
38 unsigned nr,
39 void *out )
40 {
41 memcpy(out, &((int *)in)[start], nr*sizeof(int));
42 }
43
44
45 /**
46 * Translate indexes when a driver can't support certain types
47 * of drawing. Example include:
48 * - Translate 1-byte indexes into 2-byte indexes
49 * - Translate PIPE_PRIM_QUADS into PIPE_PRIM_TRIANGLES when the hardware
50 * doesn't support the former.
51 * - Translate from first provoking vertex to last provoking vertex and
52 * vice versa.
53 *
54 * \param hw_mask mask of (1 << PIPE_PRIM_x) flags indicating which types
55 * of primitives are supported by the hardware.
56 * \param prim incoming PIPE_PRIM_x
57 * \param in_index_size bytes per index value (1, 2 or 4)
58 * \param nr number of incoming vertices
59 * \param in_pv incoming provoking vertex convention (PV_FIRST or PV_LAST)
60 * \param out_pv desired provoking vertex convention (PV_FIRST or PV_LAST)
61 * \param out_prim returns new PIPE_PRIM_x we'll translate to
62 * \param out_index_size returns bytes per new index value (2 or 4)
63 * \param out_nr returns number of new vertices
64 * \param out_translate returns the translation function to use by the caller
65 */
66 int u_index_translator( unsigned hw_mask,
67 unsigned prim,
68 unsigned in_index_size,
69 unsigned nr,
70 unsigned in_pv,
71 unsigned out_pv,
72 unsigned *out_prim,
73 unsigned *out_index_size,
74 unsigned *out_nr,
75 u_translate_func *out_translate )
76 {
77 unsigned in_idx;
78 unsigned out_idx;
79 int ret = U_TRANSLATE_NORMAL;
80
81 assert(in_index_size == 1 ||
82 in_index_size == 2 ||
83 in_index_size == 4);
84
85 u_index_init();
86
87 in_idx = in_size_idx(in_index_size);
88 *out_index_size = (in_index_size == 4) ? 4 : 2;
89 out_idx = out_size_idx(*out_index_size);
90
91 if ((hw_mask & (1<<prim)) &&
92 in_index_size == *out_index_size &&
93 in_pv == out_pv)
94 {
95 /* Index translation not really needed */
96 if (in_index_size == 4)
97 *out_translate = translate_memcpy_uint;
98 else
99 *out_translate = translate_memcpy_ushort;
100
101 *out_prim = prim;
102 *out_nr = nr;
103
104 return U_TRANSLATE_MEMCPY;
105 }
106 else {
107 switch (prim) {
108 case PIPE_PRIM_POINTS:
109 *out_translate = translate[in_idx][out_idx][in_pv][out_pv][prim];
110 *out_prim = PIPE_PRIM_POINTS;
111 *out_nr = nr;
112 break;
113
114 case PIPE_PRIM_LINES:
115 *out_translate = translate[in_idx][out_idx][in_pv][out_pv][prim];
116 *out_prim = PIPE_PRIM_LINES;
117 *out_nr = nr;
118 break;
119
120 case PIPE_PRIM_LINE_STRIP:
121 *out_translate = translate[in_idx][out_idx][in_pv][out_pv][prim];
122 *out_prim = PIPE_PRIM_LINES;
123 *out_nr = (nr - 1) * 2;
124 break;
125
126 case PIPE_PRIM_LINE_LOOP:
127 *out_translate = translate[in_idx][out_idx][in_pv][out_pv][prim];
128 *out_prim = PIPE_PRIM_LINES;
129 *out_nr = nr * 2;
130 break;
131
132 case PIPE_PRIM_TRIANGLES:
133 *out_translate = translate[in_idx][out_idx][in_pv][out_pv][prim];
134 *out_prim = PIPE_PRIM_TRIANGLES;
135 *out_nr = nr;
136 break;
137
138 case PIPE_PRIM_TRIANGLE_STRIP:
139 *out_translate = translate[in_idx][out_idx][in_pv][out_pv][prim];
140 *out_prim = PIPE_PRIM_TRIANGLES;
141 *out_nr = (nr - 2) * 3;
142 break;
143
144 case PIPE_PRIM_TRIANGLE_FAN:
145 *out_translate = translate[in_idx][out_idx][in_pv][out_pv][prim];
146 *out_prim = PIPE_PRIM_TRIANGLES;
147 *out_nr = (nr - 2) * 3;
148 break;
149
150 case PIPE_PRIM_QUADS:
151 *out_translate = translate[in_idx][out_idx][in_pv][out_pv][prim];
152 *out_prim = PIPE_PRIM_TRIANGLES;
153 *out_nr = (nr / 4) * 6;
154 break;
155
156 case PIPE_PRIM_QUAD_STRIP:
157 *out_translate = translate[in_idx][out_idx][in_pv][out_pv][prim];
158 *out_prim = PIPE_PRIM_TRIANGLES;
159 *out_nr = (nr - 2) * 3;
160 break;
161
162 case PIPE_PRIM_POLYGON:
163 *out_translate = translate[in_idx][out_idx][in_pv][out_pv][prim];
164 *out_prim = PIPE_PRIM_TRIANGLES;
165 *out_nr = (nr - 2) * 3;
166 break;
167
168 default:
169 assert(0);
170 *out_translate = translate[in_idx][out_idx][in_pv][out_pv][prim];
171 *out_prim = PIPE_PRIM_POINTS;
172 *out_nr = nr;
173 return U_TRANSLATE_ERROR;
174 }
175 }
176
177 return ret;
178 }
179
180
181 /**
182 * If a driver does not support a particular gallium primitive type
183 * (such as PIPE_PRIM_QUAD_STRIP) this function can be used to help
184 * convert the primitive into a simpler type (like PIPE_PRIM_TRIANGLES).
185 *
186 * The generator functions generates a number of ushort or uint indexes
187 * for drawing the new type of primitive.
188 *
189 * \param hw_mask a bitmask of (1 << PIPE_PRIM_x) values that indicates
190 * kind of primitives are supported by the driver.
191 * \param prim the PIPE_PRIM_x that the user wants to draw
192 * \param start index of first vertex to draw
193 * \param nr number of vertices to draw
194 * \param in_pv user's provoking vertex (PV_FIRST/LAST)
195 * \param out_pv desired proking vertex for the hardware (PV_FIRST/LAST)
196 * \param out_prim returns the new primitive type for the driver
197 * \param out_index_size returns OUT_USHORT or OUT_UINT
198 * \param out_nr returns new number of vertices to draw
199 * \param out_generate returns pointer to the generator function
200 */
201 int u_index_generator( unsigned hw_mask,
202 unsigned prim,
203 unsigned start,
204 unsigned nr,
205 unsigned in_pv,
206 unsigned out_pv,
207 unsigned *out_prim,
208 unsigned *out_index_size,
209 unsigned *out_nr,
210 u_generate_func *out_generate )
211
212 {
213 unsigned out_idx;
214
215 u_index_init();
216
217 *out_index_size = ((start + nr) > 0xfffe) ? 4 : 2;
218 out_idx = out_size_idx(*out_index_size);
219
220 if ((hw_mask & (1<<prim)) &&
221 (in_pv == out_pv)) {
222
223 *out_generate = generate[out_idx][in_pv][out_pv][PIPE_PRIM_POINTS];
224 *out_prim = prim;
225 *out_nr = nr;
226 return U_GENERATE_LINEAR;
227 }
228 else {
229 switch (prim) {
230 case PIPE_PRIM_POINTS:
231 *out_generate = generate[out_idx][in_pv][out_pv][prim];
232 *out_prim = PIPE_PRIM_POINTS;
233 *out_nr = nr;
234 return U_GENERATE_REUSABLE;
235
236 case PIPE_PRIM_LINES:
237 *out_generate = generate[out_idx][in_pv][out_pv][prim];
238 *out_prim = PIPE_PRIM_LINES;
239 *out_nr = nr;
240 return U_GENERATE_REUSABLE;
241
242 case PIPE_PRIM_LINE_STRIP:
243 *out_generate = generate[out_idx][in_pv][out_pv][prim];
244 *out_prim = PIPE_PRIM_LINES;
245 *out_nr = (nr - 1) * 2;
246 return U_GENERATE_REUSABLE;
247
248 case PIPE_PRIM_LINE_LOOP:
249 *out_generate = generate[out_idx][in_pv][out_pv][prim];
250 *out_prim = PIPE_PRIM_LINES;
251 *out_nr = nr * 2;
252 return U_GENERATE_ONE_OFF;
253
254 case PIPE_PRIM_TRIANGLES:
255 *out_generate = generate[out_idx][in_pv][out_pv][prim];
256 *out_prim = PIPE_PRIM_TRIANGLES;
257 *out_nr = nr;
258 return U_GENERATE_REUSABLE;
259
260 case PIPE_PRIM_TRIANGLE_STRIP:
261 *out_generate = generate[out_idx][in_pv][out_pv][prim];
262 *out_prim = PIPE_PRIM_TRIANGLES;
263 *out_nr = (nr - 2) * 3;
264 return U_GENERATE_REUSABLE;
265
266 case PIPE_PRIM_TRIANGLE_FAN:
267 *out_generate = generate[out_idx][in_pv][out_pv][prim];
268 *out_prim = PIPE_PRIM_TRIANGLES;
269 *out_nr = (nr - 2) * 3;
270 return U_GENERATE_REUSABLE;
271
272 case PIPE_PRIM_QUADS:
273 *out_generate = generate[out_idx][in_pv][out_pv][prim];
274 *out_prim = PIPE_PRIM_TRIANGLES;
275 *out_nr = (nr / 4) * 6;
276 return U_GENERATE_REUSABLE;
277
278 case PIPE_PRIM_QUAD_STRIP:
279 *out_generate = generate[out_idx][in_pv][out_pv][prim];
280 *out_prim = PIPE_PRIM_TRIANGLES;
281 *out_nr = (nr - 2) * 3;
282 return U_GENERATE_REUSABLE;
283
284 case PIPE_PRIM_POLYGON:
285 *out_generate = generate[out_idx][in_pv][out_pv][prim];
286 *out_prim = PIPE_PRIM_TRIANGLES;
287 *out_nr = (nr - 2) * 3;
288 return U_GENERATE_REUSABLE;
289
290 default:
291 assert(0);
292 *out_generate = generate[out_idx][in_pv][out_pv][PIPE_PRIM_POINTS];
293 *out_prim = PIPE_PRIM_POINTS;
294 *out_nr = nr;
295 return U_TRANSLATE_ERROR;
296 }
297 }
298 }