2 * Mesa 3-D graphics library
5 * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
6 * Copyright (C) 2010 LunarG Inc.
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:
15 * The above copyright notice and this permission notice shall be included
16 * in all copies or substantial portions of the Software.
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.
27 * Keith Whitwell <keith@tungstengraphics.com>
28 * Chia-I Wu <olv@lunarg.com>
31 /* these macros are optional */
36 #define FUNC_ENTER do {} while (0)
39 #define FUNC_EXIT do {} while (0)
42 #define LINE_ADJ(flags, a0, i0, i1, a1) LINE(flags, i0, i1)
45 #define TRIANGLE_ADJ(flags, i0, a0, i1, a1, i2, a2) TRIANGLE(flags, i0, i1, i2)
57 /* prim, prim_flags, count, and last_vertex_last should have been defined */
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
);
64 case PIPE_PRIM_POINTS
:
65 for (i
= 0; i
< count
; i
++) {
72 flags
= DRAW_PIPE_RESET_STIPPLE
;
73 for (i
= 0; i
+ 1 < count
; i
+= 2) {
75 idx
[1] = GET_ELT(i
+ 1);
76 LINE(flags
, idx
[0], idx
[1]);
80 case PIPE_PRIM_LINE_LOOP
:
81 case PIPE_PRIM_LINE_STRIP
:
83 flags
= (prim_flags
& DRAW_SPLIT_BEFORE
) ? 0 : DRAW_PIPE_RESET_STIPPLE
;
87 for (i
= 1; i
< count
; i
++, flags
= 0) {
90 LINE(flags
, idx
[0], idx
[1]);
93 if (prim
== PIPE_PRIM_LINE_LOOP
&& !prim_flags
)
94 LINE(flags
, idx
[1], idx
[2]);
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) {
102 idx
[1] = GET_ELT(i
+ 1);
103 idx
[2] = GET_ELT(i
+ 2);
104 TRIANGLE(flags
, idx
[0], idx
[1], idx
[2]);
108 case PIPE_PRIM_TRIANGLE_STRIP
:
110 flags
= DRAW_PIPE_RESET_STIPPLE
| DRAW_PIPE_EDGE_FLAG_ALL
;
114 if (last_vertex_last
) {
115 for (i
= 0; i
+ 2 < count
; i
++) {
118 idx
[2] = GET_ELT(i
+ 2);
119 /* always emit idx[2] last */
121 TRIANGLE(flags
, idx
[1], idx
[0], idx
[2]);
123 TRIANGLE(flags
, idx
[0], idx
[1], idx
[2]);
127 for (i
= 0; i
+ 2 < count
; i
++) {
130 idx
[2] = GET_ELT(i
+ 2);
131 /* always emit idx[0] first */
133 TRIANGLE(flags
, idx
[0], idx
[2], idx
[1]);
135 TRIANGLE(flags
, idx
[0], idx
[1], idx
[2]);
141 case PIPE_PRIM_TRIANGLE_FAN
:
143 flags
= DRAW_PIPE_RESET_STIPPLE
| DRAW_PIPE_EDGE_FLAG_ALL
;
147 /* idx[0] is neither the first nor the last vertex */
148 if (last_vertex_last
) {
149 for (i
= 0; i
+ 2 < count
; i
++) {
151 idx
[2] = GET_ELT(i
+ 2);
152 /* always emit idx[2] last */
153 TRIANGLE(flags
, idx
[0], idx
[1], idx
[2]);
157 for (i
= 0; i
+ 2 < count
; i
++) {
159 idx
[2] = GET_ELT(i
+ 2);
160 /* always emit idx[1] first */
161 TRIANGLE(flags
, idx
[1], idx
[2], idx
[0]);
167 case PIPE_PRIM_QUADS
:
168 if (last_vertex_last
) {
169 for (i
= 0; i
+ 3 < count
; i
+= 4) {
171 idx
[1] = GET_ELT(i
+ 1);
172 idx
[2] = GET_ELT(i
+ 2);
173 idx
[3] = GET_ELT(i
+ 3);
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]);
181 flags
= DRAW_PIPE_EDGE_FLAG_0
|
182 DRAW_PIPE_EDGE_FLAG_1
;
183 TRIANGLE(flags
, idx
[1], idx
[2], idx
[3]);
187 for (i
= 0; i
+ 3 < count
; i
+= 4) {
189 idx
[1] = GET_ELT(i
+ 1);
190 idx
[2] = GET_ELT(i
+ 2);
191 idx
[3] = GET_ELT(i
+ 3);
193 flags
= DRAW_PIPE_RESET_STIPPLE
|
194 DRAW_PIPE_EDGE_FLAG_0
|
195 DRAW_PIPE_EDGE_FLAG_1
;
196 /* always emit idx[3] / idx[0] first */
197 if (quads_flatshade_last
)
198 TRIANGLE(flags
, idx
[3], idx
[0], idx
[1]);
200 TRIANGLE(flags
, idx
[0], idx
[1], idx
[2]);
202 flags
= DRAW_PIPE_EDGE_FLAG_1
|
203 DRAW_PIPE_EDGE_FLAG_2
;
204 if (quads_flatshade_last
)
205 TRIANGLE(flags
, idx
[3], idx
[1], idx
[2]);
207 TRIANGLE(flags
, idx
[0], idx
[2], idx
[3]);
212 case PIPE_PRIM_QUAD_STRIP
:
217 if (last_vertex_last
) {
218 for (i
= 0; i
+ 3 < count
; i
+= 2) {
221 idx
[2] = GET_ELT(i
+ 2);
222 idx
[3] = GET_ELT(i
+ 3);
224 /* always emit idx[3] last */
225 flags
= DRAW_PIPE_RESET_STIPPLE
|
226 DRAW_PIPE_EDGE_FLAG_0
|
227 DRAW_PIPE_EDGE_FLAG_2
;
228 TRIANGLE(flags
, idx
[2], idx
[0], idx
[3]);
230 flags
= DRAW_PIPE_EDGE_FLAG_0
|
231 DRAW_PIPE_EDGE_FLAG_1
;
232 TRIANGLE(flags
, idx
[0], idx
[1], idx
[3]);
236 for (i
= 0; i
+ 3 < count
; i
+= 2) {
239 idx
[2] = GET_ELT(i
+ 2);
240 idx
[3] = GET_ELT(i
+ 3);
242 flags
= DRAW_PIPE_RESET_STIPPLE
|
243 DRAW_PIPE_EDGE_FLAG_0
|
244 DRAW_PIPE_EDGE_FLAG_1
;
245 /* always emit idx[3] / idx[0 first */
246 if (quads_flatshade_last
)
247 TRIANGLE(flags
, idx
[3], idx
[2], idx
[0]);
249 TRIANGLE(flags
, idx
[0], idx
[3], idx
[2]);
251 flags
= DRAW_PIPE_EDGE_FLAG_1
|
252 DRAW_PIPE_EDGE_FLAG_2
;
253 if (quads_flatshade_last
)
254 TRIANGLE(flags
, idx
[3], idx
[0], idx
[1]);
256 TRIANGLE(flags
, idx
[0], idx
[1], idx
[3]);
262 case PIPE_PRIM_POLYGON
:
264 ushort edge_next
, edge_finish
;
266 if (last_vertex_last
) {
267 flags
= (DRAW_PIPE_RESET_STIPPLE
|
268 DRAW_PIPE_EDGE_FLAG_0
);
269 if (!(prim_flags
& DRAW_SPLIT_BEFORE
))
270 flags
|= DRAW_PIPE_EDGE_FLAG_2
;
272 edge_next
= DRAW_PIPE_EDGE_FLAG_0
;
274 (prim_flags
& DRAW_SPLIT_AFTER
) ? 0 : DRAW_PIPE_EDGE_FLAG_1
;
277 flags
= (DRAW_PIPE_RESET_STIPPLE
|
278 DRAW_PIPE_EDGE_FLAG_1
);
279 if (!(prim_flags
& DRAW_SPLIT_BEFORE
))
280 flags
|= DRAW_PIPE_EDGE_FLAG_0
;
282 edge_next
= DRAW_PIPE_EDGE_FLAG_1
;
284 (prim_flags
& DRAW_SPLIT_AFTER
) ? 0 : DRAW_PIPE_EDGE_FLAG_2
;
290 for (i
= 0; i
+ 2 < count
; i
++, flags
= edge_next
) {
292 idx
[2] = GET_ELT(i
+ 2);
295 flags
|= edge_finish
;
297 /* idx[0] is both the first and the last vertex */
298 if (last_vertex_last
)
299 TRIANGLE(flags
, idx
[1], idx
[2], idx
[0]);
301 TRIANGLE(flags
, idx
[0], idx
[1], idx
[2]);
306 case PIPE_PRIM_LINES_ADJACENCY
:
307 flags
= DRAW_PIPE_RESET_STIPPLE
;
308 for (i
= 0; i
+ 3 < count
; i
+= 4) {
310 idx
[1] = GET_ELT(i
+ 1);
311 idx
[2] = GET_ELT(i
+ 2);
312 idx
[3] = GET_ELT(i
+ 3);
313 LINE_ADJ(flags
, idx
[0], idx
[1], idx
[2], idx
[3]);
317 case PIPE_PRIM_LINE_STRIP_ADJACENCY
:
319 flags
= (prim_flags
& DRAW_SPLIT_BEFORE
) ? 0 : DRAW_PIPE_RESET_STIPPLE
;
324 for (i
= 1; i
+ 2 < count
; i
++, flags
= 0) {
328 idx
[3] = GET_ELT(i
+ 2);
329 LINE_ADJ(flags
, idx
[0], idx
[1], idx
[2], idx
[3]);
334 case PIPE_PRIM_TRIANGLES_ADJACENCY
:
335 flags
= DRAW_PIPE_RESET_STIPPLE
| DRAW_PIPE_EDGE_FLAG_ALL
;
336 for (i
= 0; i
+ 5 < count
; i
+= 6) {
338 idx
[1] = GET_ELT(i
+ 1);
339 idx
[2] = GET_ELT(i
+ 2);
340 idx
[3] = GET_ELT(i
+ 3);
341 idx
[4] = GET_ELT(i
+ 4);
342 idx
[5] = GET_ELT(i
+ 5);
343 TRIANGLE_ADJ(flags
, idx
[0], idx
[1], idx
[2], idx
[3], idx
[4], idx
[5]);
347 case PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY
:
349 flags
= DRAW_PIPE_RESET_STIPPLE
| DRAW_PIPE_EDGE_FLAG_ALL
;
356 * The vertices of the i-th triangle are stored in
357 * idx[0,2,4] = { 2*i, 2*i+2, 2*i+4 };
359 * The adjacent vertices are stored in
360 * idx[1,3,5] = { 2*i-2, 2*i+6, 2*i+3 }.
362 * However, there are two exceptions:
364 * For the first triangle, idx[1] = 1;
365 * For the last triangle, idx[3] = 2*i+5.
367 if (last_vertex_last
) {
368 for (i
= 0; i
+ 5 < count
; i
+= 2) {
375 idx
[3] = GET_ELT(i
+ ((i
+ 7 < count
) ? 6 : 5));
376 idx
[5] = GET_ELT(i
+ 3);
379 * alternate the first two vertices (idx[0] and idx[2]) and the
380 * corresponding adjacent vertices (idx[3] and idx[5]) to have
381 * the correct orientation
385 idx
[2], idx
[1], idx
[0], idx
[5], idx
[4], idx
[3]);
389 idx
[0], idx
[1], idx
[2], idx
[3], idx
[4], idx
[5]);
394 for (i
= 0; i
+ 5 < count
; i
+= 2) {
401 idx
[3] = GET_ELT(i
+ ((i
+ 7 < count
) ? 6 : 5));
402 idx
[5] = GET_ELT(i
+ 3);
405 * alternate the last two vertices (idx[2] and idx[4]) and the
406 * corresponding adjacent vertices (idx[1] and idx[5]) to have
407 * the correct orientation
411 idx
[0], idx
[5], idx
[4], idx
[3], idx
[2], idx
[1]);
415 idx
[0], idx
[1], idx
[2], idx
[3], idx
[4], idx
[5]);