Tizen 2.0 Release
[profile/ivi/osmesa.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
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, prim_flags, count, and last_vertex_last should have been defined */
58    if (0) {
59       debug_printf("%s: prim 0x%x, prim_flags 0x%x, count %d, last_vertex_last %d\n",
60             __FUNCTION__, prim, prim_flags, 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 = (prim_flags & DRAW_SPLIT_BEFORE) ? 0 : 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 && !prim_flags)
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_0);
259             if (!(prim_flags & DRAW_SPLIT_BEFORE))
260                flags |= DRAW_PIPE_EDGE_FLAG_2;
261
262             edge_next = DRAW_PIPE_EDGE_FLAG_0;
263             edge_finish =
264                (prim_flags & DRAW_SPLIT_AFTER) ? 0 : DRAW_PIPE_EDGE_FLAG_1;
265          }
266          else {
267             flags = (DRAW_PIPE_RESET_STIPPLE |
268                      DRAW_PIPE_EDGE_FLAG_1);
269             if (!(prim_flags & DRAW_SPLIT_BEFORE))
270                flags |= DRAW_PIPE_EDGE_FLAG_0;
271
272             edge_next = DRAW_PIPE_EDGE_FLAG_1;
273             edge_finish =
274                (prim_flags & DRAW_SPLIT_AFTER) ? 0 : DRAW_PIPE_EDGE_FLAG_2;
275          }
276
277          idx[0] = GET_ELT(0);
278          idx[2] = GET_ELT(1);
279
280          for (i = 0; i + 2 < count; i++, flags = edge_next) {
281             idx[1] = idx[2];
282             idx[2] = GET_ELT(i + 2);
283
284             if (i + 3 == count)
285                flags |= edge_finish;
286
287             /* idx[0] is both the first and the last vertex */
288             if (last_vertex_last)
289                TRIANGLE(flags, idx[1], idx[2], idx[0]);
290             else
291                TRIANGLE(flags, idx[0], idx[1], idx[2]);
292          }
293       }
294       break;
295
296    case PIPE_PRIM_LINES_ADJACENCY:
297       flags = DRAW_PIPE_RESET_STIPPLE;
298       for (i = 0; i + 3 < count; i += 4) {
299          idx[0] = GET_ELT(i);
300          idx[1] = GET_ELT(i + 1);
301          idx[2] = GET_ELT(i + 2);
302          idx[3] = GET_ELT(i + 3);
303          LINE_ADJ(flags, idx[0], idx[1], idx[2], idx[3]);
304       }
305       break;
306
307    case PIPE_PRIM_LINE_STRIP_ADJACENCY:
308       if (count >= 4) {
309          flags = (prim_flags & DRAW_SPLIT_BEFORE) ? 0 : DRAW_PIPE_RESET_STIPPLE;
310          idx[1] = GET_ELT(0);
311          idx[2] = GET_ELT(1);
312          idx[3] = GET_ELT(2);
313
314          for (i = 1; i + 2 < count; i++, flags = 0) {
315             idx[0] = idx[1];
316             idx[1] = idx[2];
317             idx[2] = idx[3];
318             idx[3] = GET_ELT(i + 2);
319             LINE_ADJ(flags, idx[0], idx[1], idx[2], idx[3]);
320          }
321       }
322       break;
323
324    case PIPE_PRIM_TRIANGLES_ADJACENCY:
325       flags = DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL;
326       for (i = 0; i + 5 < count; i += 6) {
327          idx[0] = GET_ELT(i);
328          idx[1] = GET_ELT(i + 1);
329          idx[2] = GET_ELT(i + 2);
330          idx[3] = GET_ELT(i + 3);
331          idx[4] = GET_ELT(i + 4);
332          idx[5] = GET_ELT(i + 5);
333          TRIANGLE_ADJ(flags, idx[0], idx[1], idx[2], idx[3], idx[4], idx[5]);
334       }
335       break;
336
337    case PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY:
338       if (count >= 6) {
339          flags = DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL;
340          idx[0] = GET_ELT(1);
341          idx[2] = GET_ELT(0);
342          idx[4] = GET_ELT(2);
343          idx[3] = GET_ELT(4);
344
345          /*
346           * The vertices of the i-th triangle are stored in
347           * idx[0,2,4] = { 2*i, 2*i+2, 2*i+4 };
348           *
349           * The adjacent vertices are stored in
350           * idx[1,3,5] = { 2*i-2, 2*i+6, 2*i+3 }.
351           *
352           * However, there are two exceptions:
353           *
354           * For the first triangle, idx[1] = 1;
355           * For the  last triangle, idx[3] = 2*i+5.
356           */
357          if (last_vertex_last) {
358             for (i = 0; i + 5 < count; i += 2) {
359                idx[1] = idx[0];
360
361                idx[0] = idx[2];
362                idx[2] = idx[4];
363                idx[4] = idx[3];
364
365                idx[3] = GET_ELT(i + ((i + 7 < count) ? 6 : 5));
366                idx[5] = GET_ELT(i + 3);
367
368                /*
369                 * alternate the first two vertices (idx[0] and idx[2]) and the
370                 * corresponding adjacent vertices (idx[3] and idx[5]) to have
371                 * the correct orientation
372                 */
373                if (i & 2) {
374                   TRIANGLE_ADJ(flags,
375                         idx[2], idx[1], idx[0], idx[5], idx[4], idx[3]);
376                }
377                else {
378                   TRIANGLE_ADJ(flags,
379                         idx[0], idx[1], idx[2], idx[3], idx[4], idx[5]);
380                }
381             }
382          }
383          else {
384             for (i = 0; i + 5 < count; i += 2) {
385                idx[1] = idx[0];
386
387                idx[0] = idx[2];
388                idx[2] = idx[4];
389                idx[4] = idx[3];
390
391                idx[3] = GET_ELT(i + ((i + 7 < count) ? 6 : 5));
392                idx[5] = GET_ELT(i + 3);
393
394                /*
395                 * alternate the last two vertices (idx[2] and idx[4]) and the
396                 * corresponding adjacent vertices (idx[1] and idx[5]) to have
397                 * the correct orientation
398                 */
399                if (i & 2) {
400                   TRIANGLE_ADJ(flags,
401                         idx[0], idx[5], idx[4], idx[3], idx[2], idx[1]);
402                }
403                else {
404                   TRIANGLE_ADJ(flags,
405                         idx[0], idx[1], idx[2], idx[3], idx[4], idx[5]);
406                }
407             }
408          }
409       }
410       break;
411
412    default:
413       assert(0);
414       break;
415    }
416
417    FUNC_EXIT;
418 }
419
420 #undef LOCAL_VARS
421 #undef FUNC_ENTER
422 #undef FUNC_EXIT
423 #undef LINE_ADJ
424 #undef TRIANGLE_ADJ
425
426 #undef FUNC
427 #undef FUNC_VARS
428 #undef GET_ELT
429 #undef POINT
430 #undef LINE
431 #undef TRIANGLE