2 * Mesa 3-D graphics library
4 * Copyright 2008 VMware, Inc.
5 * Copyright (C) 2010 LunarG Inc.
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23 * DEALINGS IN THE SOFTWARE.
26 * Keith Whitwell <keithw@vmware.com>
27 * Chia-I Wu <olv@lunarg.com>
30 /* these macros are optional */
35 #define FUNC_ENTER do {} while (0)
38 #define FUNC_EXIT do {} while (0)
41 #define LINE_ADJ(flags, a0, i0, i1, a1) LINE(flags, i0, i1)
44 #define TRIANGLE_ADJ(flags, i0, a0, i1, a1, i2, a2) TRIANGLE(flags, i0, i1, i2)
56 /* prim, prim_flags, count, and last_vertex_last should have been defined */
58 debug_printf("%s: prim 0x%x, prim_flags 0x%x, count %d, last_vertex_last %d\n",
59 __FUNCTION__
, prim
, prim_flags
, count
, last_vertex_last
);
63 case PIPE_PRIM_POINTS
:
64 for (i
= 0; i
< count
; i
++) {
71 flags
= DRAW_PIPE_RESET_STIPPLE
;
72 for (i
= 0; i
+ 1 < count
; i
+= 2) {
74 idx
[1] = GET_ELT(i
+ 1);
75 LINE(flags
, idx
[0], idx
[1]);
79 case PIPE_PRIM_LINE_LOOP
:
80 case PIPE_PRIM_LINE_STRIP
:
82 flags
= (prim_flags
& DRAW_SPLIT_BEFORE
) ? 0 : DRAW_PIPE_RESET_STIPPLE
;
86 for (i
= 1; i
< count
; i
++, flags
= 0) {
89 LINE(flags
, idx
[0], idx
[1]);
92 if (prim
== PIPE_PRIM_LINE_LOOP
&& !prim_flags
)
93 LINE(flags
, idx
[1], idx
[2]);
97 case PIPE_PRIM_TRIANGLES
:
98 flags
= DRAW_PIPE_RESET_STIPPLE
| DRAW_PIPE_EDGE_FLAG_ALL
;
99 for (i
= 0; i
+ 2 < count
; i
+= 3) {
101 idx
[1] = GET_ELT(i
+ 1);
102 idx
[2] = GET_ELT(i
+ 2);
103 TRIANGLE(flags
, idx
[0], idx
[1], idx
[2]);
107 case PIPE_PRIM_TRIANGLE_STRIP
:
109 flags
= DRAW_PIPE_RESET_STIPPLE
| DRAW_PIPE_EDGE_FLAG_ALL
;
113 if (last_vertex_last
) {
114 for (i
= 0; i
+ 2 < count
; i
++) {
117 idx
[2] = GET_ELT(i
+ 2);
118 /* always emit idx[2] last */
120 TRIANGLE(flags
, idx
[1], idx
[0], idx
[2]);
122 TRIANGLE(flags
, idx
[0], idx
[1], idx
[2]);
126 for (i
= 0; i
+ 2 < count
; i
++) {
129 idx
[2] = GET_ELT(i
+ 2);
130 /* always emit idx[0] first */
132 TRIANGLE(flags
, idx
[0], idx
[2], idx
[1]);
134 TRIANGLE(flags
, idx
[0], idx
[1], idx
[2]);
140 case PIPE_PRIM_TRIANGLE_FAN
:
142 flags
= DRAW_PIPE_RESET_STIPPLE
| DRAW_PIPE_EDGE_FLAG_ALL
;
146 /* idx[0] is neither the first nor the last vertex */
147 if (last_vertex_last
) {
148 for (i
= 0; i
+ 2 < count
; i
++) {
150 idx
[2] = GET_ELT(i
+ 2);
151 /* always emit idx[2] last */
152 TRIANGLE(flags
, idx
[0], idx
[1], idx
[2]);
156 for (i
= 0; i
+ 2 < count
; i
++) {
158 idx
[2] = GET_ELT(i
+ 2);
159 /* always emit idx[1] first */
160 TRIANGLE(flags
, idx
[1], idx
[2], idx
[0]);
166 case PIPE_PRIM_QUADS
:
167 if (last_vertex_last
) {
168 for (i
= 0; i
+ 3 < count
; i
+= 4) {
170 idx
[1] = GET_ELT(i
+ 1);
171 idx
[2] = GET_ELT(i
+ 2);
172 idx
[3] = GET_ELT(i
+ 3);
174 flags
= DRAW_PIPE_RESET_STIPPLE
|
175 DRAW_PIPE_EDGE_FLAG_0
|
176 DRAW_PIPE_EDGE_FLAG_2
;
177 /* always emit idx[3] last */
178 TRIANGLE(flags
, idx
[0], idx
[1], idx
[3]);
180 flags
= DRAW_PIPE_EDGE_FLAG_0
|
181 DRAW_PIPE_EDGE_FLAG_1
;
182 TRIANGLE(flags
, idx
[1], idx
[2], idx
[3]);
186 for (i
= 0; i
+ 3 < count
; i
+= 4) {
188 idx
[1] = GET_ELT(i
+ 1);
189 idx
[2] = GET_ELT(i
+ 2);
190 idx
[3] = GET_ELT(i
+ 3);
192 flags
= DRAW_PIPE_RESET_STIPPLE
|
193 DRAW_PIPE_EDGE_FLAG_0
|
194 DRAW_PIPE_EDGE_FLAG_1
;
195 /* always emit idx[3] / idx[0] first */
196 if (quads_flatshade_last
)
197 TRIANGLE(flags
, idx
[3], idx
[0], idx
[1]);
199 TRIANGLE(flags
, idx
[0], idx
[1], idx
[2]);
201 flags
= DRAW_PIPE_EDGE_FLAG_1
|
202 DRAW_PIPE_EDGE_FLAG_2
;
203 if (quads_flatshade_last
)
204 TRIANGLE(flags
, idx
[3], idx
[1], idx
[2]);
206 TRIANGLE(flags
, idx
[0], idx
[2], idx
[3]);
211 case PIPE_PRIM_QUAD_STRIP
:
216 if (last_vertex_last
) {
217 for (i
= 0; i
+ 3 < count
; i
+= 2) {
220 idx
[2] = GET_ELT(i
+ 2);
221 idx
[3] = GET_ELT(i
+ 3);
223 /* always emit idx[3] last */
224 flags
= DRAW_PIPE_RESET_STIPPLE
|
225 DRAW_PIPE_EDGE_FLAG_0
|
226 DRAW_PIPE_EDGE_FLAG_2
;
227 TRIANGLE(flags
, idx
[2], idx
[0], idx
[3]);
229 flags
= DRAW_PIPE_EDGE_FLAG_0
|
230 DRAW_PIPE_EDGE_FLAG_1
;
231 TRIANGLE(flags
, idx
[0], idx
[1], idx
[3]);
235 for (i
= 0; i
+ 3 < count
; i
+= 2) {
238 idx
[2] = GET_ELT(i
+ 2);
239 idx
[3] = GET_ELT(i
+ 3);
241 flags
= DRAW_PIPE_RESET_STIPPLE
|
242 DRAW_PIPE_EDGE_FLAG_0
|
243 DRAW_PIPE_EDGE_FLAG_1
;
244 /* always emit idx[3] / idx[0 first */
245 if (quads_flatshade_last
)
246 TRIANGLE(flags
, idx
[3], idx
[2], idx
[0]);
248 TRIANGLE(flags
, idx
[0], idx
[3], idx
[2]);
250 flags
= DRAW_PIPE_EDGE_FLAG_1
|
251 DRAW_PIPE_EDGE_FLAG_2
;
252 if (quads_flatshade_last
)
253 TRIANGLE(flags
, idx
[3], idx
[0], idx
[1]);
255 TRIANGLE(flags
, idx
[0], idx
[1], idx
[3]);
261 case PIPE_PRIM_POLYGON
:
263 ushort edge_next
, edge_finish
;
265 if (last_vertex_last
) {
266 flags
= (DRAW_PIPE_RESET_STIPPLE
|
267 DRAW_PIPE_EDGE_FLAG_0
);
268 if (!(prim_flags
& DRAW_SPLIT_BEFORE
))
269 flags
|= DRAW_PIPE_EDGE_FLAG_2
;
271 edge_next
= DRAW_PIPE_EDGE_FLAG_0
;
273 (prim_flags
& DRAW_SPLIT_AFTER
) ? 0 : DRAW_PIPE_EDGE_FLAG_1
;
276 flags
= (DRAW_PIPE_RESET_STIPPLE
|
277 DRAW_PIPE_EDGE_FLAG_1
);
278 if (!(prim_flags
& DRAW_SPLIT_BEFORE
))
279 flags
|= DRAW_PIPE_EDGE_FLAG_0
;
281 edge_next
= DRAW_PIPE_EDGE_FLAG_1
;
283 (prim_flags
& DRAW_SPLIT_AFTER
) ? 0 : DRAW_PIPE_EDGE_FLAG_2
;
289 for (i
= 0; i
+ 2 < count
; i
++, flags
= edge_next
) {
291 idx
[2] = GET_ELT(i
+ 2);
294 flags
|= edge_finish
;
296 /* idx[0] is both the first and the last vertex */
297 if (last_vertex_last
)
298 TRIANGLE(flags
, idx
[1], idx
[2], idx
[0]);
300 TRIANGLE(flags
, idx
[0], idx
[1], idx
[2]);
305 case PIPE_PRIM_LINES_ADJACENCY
:
306 flags
= DRAW_PIPE_RESET_STIPPLE
;
307 for (i
= 0; i
+ 3 < count
; i
+= 4) {
309 idx
[1] = GET_ELT(i
+ 1);
310 idx
[2] = GET_ELT(i
+ 2);
311 idx
[3] = GET_ELT(i
+ 3);
312 LINE_ADJ(flags
, idx
[0], idx
[1], idx
[2], idx
[3]);
316 case PIPE_PRIM_LINE_STRIP_ADJACENCY
:
318 flags
= (prim_flags
& DRAW_SPLIT_BEFORE
) ? 0 : DRAW_PIPE_RESET_STIPPLE
;
323 for (i
= 1; i
+ 2 < count
; i
++, flags
= 0) {
327 idx
[3] = GET_ELT(i
+ 2);
328 LINE_ADJ(flags
, idx
[0], idx
[1], idx
[2], idx
[3]);
333 case PIPE_PRIM_TRIANGLES_ADJACENCY
:
334 flags
= DRAW_PIPE_RESET_STIPPLE
| DRAW_PIPE_EDGE_FLAG_ALL
;
335 for (i
= 0; i
+ 5 < count
; i
+= 6) {
337 idx
[1] = GET_ELT(i
+ 1);
338 idx
[2] = GET_ELT(i
+ 2);
339 idx
[3] = GET_ELT(i
+ 3);
340 idx
[4] = GET_ELT(i
+ 4);
341 idx
[5] = GET_ELT(i
+ 5);
342 TRIANGLE_ADJ(flags
, idx
[0], idx
[1], idx
[2], idx
[3], idx
[4], idx
[5]);
346 case PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY
:
348 flags
= DRAW_PIPE_RESET_STIPPLE
| DRAW_PIPE_EDGE_FLAG_ALL
;
355 * The vertices of the i-th triangle are stored in
356 * idx[0,2,4] = { 2*i, 2*i+2, 2*i+4 };
358 * The adjacent vertices are stored in
359 * idx[1,3,5] = { 2*i-2, 2*i+6, 2*i+3 }.
361 * However, there are two exceptions:
363 * For the first triangle, idx[1] = 1;
364 * For the last triangle, idx[3] = 2*i+5.
366 if (last_vertex_last
) {
367 for (i
= 0; i
+ 5 < count
; i
+= 2) {
374 idx
[3] = GET_ELT(i
+ ((i
+ 7 < count
) ? 6 : 5));
375 idx
[5] = GET_ELT(i
+ 3);
378 * alternate the first two vertices (idx[0] and idx[2]) and the
379 * corresponding adjacent vertices (idx[3] and idx[5]) to have
380 * the correct orientation
384 idx
[2], idx
[1], idx
[0], idx
[5], idx
[4], idx
[3]);
388 idx
[0], idx
[1], idx
[2], idx
[3], idx
[4], idx
[5]);
393 for (i
= 0; i
+ 5 < count
; i
+= 2) {
400 idx
[3] = GET_ELT(i
+ ((i
+ 7 < count
) ? 6 : 5));
401 idx
[5] = GET_ELT(i
+ 3);
404 * alternate the last two vertices (idx[2] and idx[4]) and the
405 * corresponding adjacent vertices (idx[1] and idx[5]) to have
406 * the correct orientation
410 idx
[0], idx
[5], idx
[4], idx
[3], idx
[2], idx
[1]);
414 idx
[0], idx
[1], idx
[2], idx
[3], idx
[4], idx
[5]);