cb252023238e0337b6442a49a3c805dbe631f573
[mesa.git] / src / gallium / auxiliary / draw / draw_decompose_tmp.h
1 /*
2 * Mesa 3-D graphics library
3 * Version: 7.9
4 *
5 * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
6 * Copyright (C) 2010 LunarG Inc.
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice shall be included
16 * in all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24 * DEALINGS IN THE SOFTWARE.
25 *
26 * Authors:
27 * Keith Whitwell <keith@tungstengraphics.com>
28 * Chia-I Wu <olv@lunarg.com>
29 */
30
31 /* these macros are optional */
32 #ifndef LOCAL_VARS
33 #define LOCAL_VARS do {} while (0)
34 #endif
35 #ifndef FUNC_ENTER
36 #define FUNC_ENTER do {} while (0)
37 #endif
38 #ifndef FUNC_EXIT
39 #define FUNC_EXIT do {} while (0)
40 #endif
41 #ifndef LINE_ADJ
42 #define LINE_ADJ(flags, a0, i0, i1, a1) LINE(flags, i0, i1)
43 #endif
44 #ifndef TRIANGLE_ADJ
45 #define TRIANGLE_ADJ(flags, i0, a0, i1, a1, i2, a2) TRIANGLE(flags, i0, i1, i2)
46 #endif
47
48 static void
49 FUNC(FUNC_VARS)
50 {
51 unsigned idx[6], i;
52 ushort flags;
53 LOCAL_VARS;
54
55 FUNC_ENTER;
56
57 /* prim, count, and last_vertex_last should have been defined */
58 if (0) {
59 debug_printf("%s: prim 0x%x, count %d, last_vertex_last %d\n",
60 __FUNCTION__, prim, count, last_vertex_last);
61 }
62
63 switch (prim) {
64 case PIPE_PRIM_POINTS:
65 for (i = 0; i < count; i++) {
66 idx[0] = GET_ELT(i);
67 POINT(idx[0]);
68 }
69 break;
70
71 case PIPE_PRIM_LINES:
72 flags = DRAW_PIPE_RESET_STIPPLE;
73 for (i = 0; i + 1 < count; i += 2) {
74 idx[0] = GET_ELT(i);
75 idx[1] = GET_ELT(i + 1);
76 LINE(flags, idx[0], idx[1]);
77 }
78 break;
79
80 case PIPE_PRIM_LINE_LOOP:
81 case PIPE_PRIM_LINE_STRIP:
82 if (count >= 2) {
83 flags = DRAW_PIPE_RESET_STIPPLE;
84 idx[1] = GET_ELT(0);
85 idx[2] = idx[1];
86
87 for (i = 1; i < count; i++, flags = 0) {
88 idx[0] = idx[1];
89 idx[1] = GET_ELT(i);
90 LINE(flags, idx[0], idx[1]);
91 }
92 /* close the loop */
93 if (prim == PIPE_PRIM_LINE_LOOP)
94 LINE(flags, idx[1], idx[2]);
95 }
96 break;
97
98 case PIPE_PRIM_TRIANGLES:
99 flags = DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL;
100 for (i = 0; i + 2 < count; i += 3) {
101 idx[0] = GET_ELT(i);
102 idx[1] = GET_ELT(i + 1);
103 idx[2] = GET_ELT(i + 2);
104 TRIANGLE(flags, idx[0], idx[1], idx[2]);
105 }
106 break;
107
108 case PIPE_PRIM_TRIANGLE_STRIP:
109 if (count >= 3) {
110 flags = DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL;
111 idx[1] = GET_ELT(0);
112 idx[2] = GET_ELT(1);
113
114 if (last_vertex_last) {
115 for (i = 0; i + 2 < count; i++) {
116 idx[0] = idx[1];
117 idx[1] = idx[2];
118 idx[2] = GET_ELT(i + 2);
119 /* always emit idx[2] last */
120 if (i & 1)
121 TRIANGLE(flags, idx[1], idx[0], idx[2]);
122 else
123 TRIANGLE(flags, idx[0], idx[1], idx[2]);
124 }
125 }
126 else {
127 for (i = 0; i + 2 < count; i++) {
128 idx[0] = idx[1];
129 idx[1] = idx[2];
130 idx[2] = GET_ELT(i + 2);
131 /* always emit idx[0] first */
132 if (i & 1)
133 TRIANGLE(flags, idx[0], idx[2], idx[1]);
134 else
135 TRIANGLE(flags, idx[0], idx[1], idx[2]);
136 }
137 }
138 }
139 break;
140
141 case PIPE_PRIM_TRIANGLE_FAN:
142 if (count >= 3) {
143 flags = DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL;
144 idx[0] = GET_ELT(0);
145 idx[2] = GET_ELT(1);
146
147 /* idx[0] is neither the first nor the last vertex */
148 if (last_vertex_last) {
149 for (i = 0; i + 2 < count; i++) {
150 idx[1] = idx[2];
151 idx[2] = GET_ELT(i + 2);
152 /* always emit idx[2] last */
153 TRIANGLE(flags, idx[0], idx[1], idx[2]);
154 }
155 }
156 else {
157 for (i = 0; i + 2 < count; i++) {
158 idx[1] = idx[2];
159 idx[2] = GET_ELT(i + 2);
160 /* always emit idx[1] first */
161 TRIANGLE(flags, idx[1], idx[2], idx[0]);
162 }
163 }
164 }
165 break;
166
167 case PIPE_PRIM_QUADS:
168 if (last_vertex_last) {
169 for (i = 0; i + 3 < count; i += 4) {
170 idx[0] = GET_ELT(i);
171 idx[1] = GET_ELT(i + 1);
172 idx[2] = GET_ELT(i + 2);
173 idx[3] = GET_ELT(i + 3);
174
175 flags = DRAW_PIPE_RESET_STIPPLE |
176 DRAW_PIPE_EDGE_FLAG_0 |
177 DRAW_PIPE_EDGE_FLAG_2;
178 /* always emit idx[3] last */
179 TRIANGLE(flags, idx[0], idx[1], idx[3]);
180
181 flags = DRAW_PIPE_EDGE_FLAG_0 |
182 DRAW_PIPE_EDGE_FLAG_1;
183 TRIANGLE(flags, idx[1], idx[2], idx[3]);
184 }
185 }
186 else {
187 for (i = 0; i + 3 < count; i += 4) {
188 idx[0] = GET_ELT(i);
189 idx[1] = GET_ELT(i + 1);
190 idx[2] = GET_ELT(i + 2);
191 idx[3] = GET_ELT(i + 3);
192
193 flags = DRAW_PIPE_RESET_STIPPLE |
194 DRAW_PIPE_EDGE_FLAG_0 |
195 DRAW_PIPE_EDGE_FLAG_1;
196 /* XXX should always emit idx[0] first */
197 /* always emit idx[3] first */
198 TRIANGLE(flags, idx[3], idx[0], idx[1]);
199
200 flags = DRAW_PIPE_EDGE_FLAG_1 |
201 DRAW_PIPE_EDGE_FLAG_2;
202 TRIANGLE(flags, idx[3], idx[1], idx[2]);
203 }
204 }
205 break;
206
207 case PIPE_PRIM_QUAD_STRIP:
208 if (count >= 4) {
209 idx[2] = GET_ELT(0);
210 idx[3] = GET_ELT(1);
211
212 if (last_vertex_last) {
213 for (i = 0; i + 3 < count; i += 2) {
214 idx[0] = idx[2];
215 idx[1] = idx[3];
216 idx[2] = GET_ELT(i + 2);
217 idx[3] = GET_ELT(i + 3);
218
219 /* always emit idx[3] last */
220 flags = DRAW_PIPE_RESET_STIPPLE |
221 DRAW_PIPE_EDGE_FLAG_0 |
222 DRAW_PIPE_EDGE_FLAG_2;
223 TRIANGLE(flags, idx[2], idx[0], idx[3]);
224
225 flags = DRAW_PIPE_EDGE_FLAG_0 |
226 DRAW_PIPE_EDGE_FLAG_1;
227 TRIANGLE(flags, idx[0], idx[1], idx[3]);
228 }
229 }
230 else {
231 for (i = 0; i + 3 < count; i += 2) {
232 idx[0] = idx[2];
233 idx[1] = idx[3];
234 idx[2] = GET_ELT(i + 2);
235 idx[3] = GET_ELT(i + 3);
236
237 flags = DRAW_PIPE_RESET_STIPPLE |
238 DRAW_PIPE_EDGE_FLAG_0 |
239 DRAW_PIPE_EDGE_FLAG_1;
240 /* XXX should always emit idx[0] first */
241 /* always emit idx[3] first */
242 TRIANGLE(flags, idx[3], idx[2], idx[0]);
243
244 flags = DRAW_PIPE_EDGE_FLAG_1 |
245 DRAW_PIPE_EDGE_FLAG_2;
246 TRIANGLE(flags, idx[3], idx[0], idx[1]);
247 }
248 }
249 }
250 break;
251
252 case PIPE_PRIM_POLYGON:
253 if (count >= 3) {
254 ushort edge_next, edge_finish;
255
256 if (last_vertex_last) {
257 flags = (DRAW_PIPE_RESET_STIPPLE |
258 DRAW_PIPE_EDGE_FLAG_2 |
259 DRAW_PIPE_EDGE_FLAG_0);
260 edge_next = DRAW_PIPE_EDGE_FLAG_0;
261 edge_finish = DRAW_PIPE_EDGE_FLAG_1;
262 }
263 else {
264 flags = (DRAW_PIPE_RESET_STIPPLE |
265 DRAW_PIPE_EDGE_FLAG_0 |
266 DRAW_PIPE_EDGE_FLAG_1);
267 edge_next = DRAW_PIPE_EDGE_FLAG_1;
268 edge_finish = DRAW_PIPE_EDGE_FLAG_2;
269 }
270
271 idx[0] = GET_ELT(0);
272 idx[2] = GET_ELT(1);
273
274 for (i = 0; i + 2 < count; i++, flags = edge_next) {
275 idx[1] = idx[2];
276 idx[2] = GET_ELT(i + 2);
277
278 if (i + 3 == count)
279 flags |= edge_finish;
280
281 /* idx[0] is both the first and the last vertex */
282 if (last_vertex_last)
283 TRIANGLE(flags, idx[1], idx[2], idx[0]);
284 else
285 TRIANGLE(flags, idx[0], idx[1], idx[2]);
286 }
287 }
288 break;
289
290 case PIPE_PRIM_LINES_ADJACENCY:
291 flags = DRAW_PIPE_RESET_STIPPLE;
292 for (i = 0; i + 3 < count; i += 4) {
293 idx[0] = GET_ELT(i);
294 idx[1] = GET_ELT(i + 1);
295 idx[2] = GET_ELT(i + 2);
296 idx[3] = GET_ELT(i + 3);
297 LINE_ADJ(flags, idx[0], idx[1], idx[2], idx[3]);
298 }
299 break;
300
301 case PIPE_PRIM_LINE_STRIP_ADJACENCY:
302 if (count >= 4) {
303 flags = DRAW_PIPE_RESET_STIPPLE;
304 idx[1] = GET_ELT(0);
305 idx[2] = GET_ELT(1);
306 idx[3] = GET_ELT(2);
307
308 for (i = 1; i + 2 < count; i++, flags = 0) {
309 idx[0] = idx[1];
310 idx[1] = idx[2];
311 idx[2] = idx[3];
312 idx[3] = GET_ELT(i + 2);
313 LINE_ADJ(flags, idx[0], idx[1], idx[2], idx[3]);
314 }
315 }
316 break;
317
318 case PIPE_PRIM_TRIANGLES_ADJACENCY:
319 flags = DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL;
320 for (i = 0; i + 5 < count; i += 6) {
321 idx[0] = GET_ELT(i);
322 idx[1] = GET_ELT(i + 1);
323 idx[2] = GET_ELT(i + 2);
324 idx[3] = GET_ELT(i + 3);
325 idx[4] = GET_ELT(i + 4);
326 idx[5] = GET_ELT(i + 5);
327 TRIANGLE_ADJ(flags, idx[0], idx[1], idx[2], idx[3], idx[4], idx[5]);
328 }
329 break;
330
331 case PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY:
332 if (count >= 6) {
333 flags = DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL;
334 idx[0] = GET_ELT(1);
335 idx[2] = GET_ELT(0);
336 idx[4] = GET_ELT(2);
337 idx[3] = GET_ELT(4);
338
339 /*
340 * The vertices of the i-th triangle are stored in
341 * idx[0,2,4] = { 2*i, 2*i+2, 2*i+4 };
342 *
343 * The adjacent vertices are stored in
344 * idx[1,3,5] = { 2*i-2, 2*i+6, 2*i+3 }.
345 *
346 * However, there are two exceptions:
347 *
348 * For the first triangle, idx[1] = 1;
349 * For the last triangle, idx[3] = 2*i+5.
350 */
351 if (last_vertex_last) {
352 for (i = 0; i + 5 < count; i += 2) {
353 idx[1] = idx[0];
354
355 idx[0] = idx[2];
356 idx[2] = idx[4];
357 idx[4] = idx[3];
358
359 idx[3] = GET_ELT(i + ((i + 7 < count) ? 6 : 5));
360 idx[5] = GET_ELT(i + 3);
361
362 /*
363 * alternate the first two vertices (idx[0] and idx[2]) and the
364 * corresponding adjacent vertices (idx[3] and idx[5]) to have
365 * the correct orientation
366 */
367 if (i & 2) {
368 TRIANGLE_ADJ(flags,
369 idx[2], idx[1], idx[0], idx[5], idx[4], idx[3]);
370 }
371 else {
372 TRIANGLE_ADJ(flags,
373 idx[0], idx[1], idx[2], idx[3], idx[4], idx[5]);
374 }
375 }
376 }
377 else {
378 for (i = 0; i + 5 < count; i += 2) {
379 idx[1] = idx[0];
380
381 idx[0] = idx[2];
382 idx[2] = idx[4];
383 idx[4] = idx[3];
384
385 idx[3] = GET_ELT(i + ((i + 7 < count) ? 6 : 5));
386 idx[5] = GET_ELT(i + 3);
387
388 /*
389 * alternate the last two vertices (idx[2] and idx[4]) and the
390 * corresponding adjacent vertices (idx[1] and idx[5]) to have
391 * the correct orientation
392 */
393 if (i & 2) {
394 TRIANGLE_ADJ(flags,
395 idx[0], idx[5], idx[4], idx[3], idx[2], idx[1]);
396 }
397 else {
398 TRIANGLE_ADJ(flags,
399 idx[0], idx[1], idx[2], idx[3], idx[4], idx[5]);
400 }
401 }
402 }
403 }
404 break;
405
406 default:
407 assert(0);
408 break;
409 }
410
411 FUNC_EXIT;
412 }
413
414 #undef LOCAL_VARS
415 #undef FUNC_ENTER
416 #undef FUNC_EXIT
417 #undef LINE_ADJ
418 #undef TRIANGLE_ADJ
419
420 #undef FUNC
421 #undef FUNC_VARS
422 #undef GET_ELT
423 #undef POINT
424 #undef LINE
425 #undef TRIANGLE