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 /* XXX should always emit idx[0] first */
197 /* always emit idx[3] first */
198 TRIANGLE(flags, idx[3], idx[0], idx[1]);
200 flags = DRAW_PIPE_EDGE_FLAG_1 |
201 DRAW_PIPE_EDGE_FLAG_2;
202 TRIANGLE(flags, idx[3], idx[1], idx[2]);
207 case PIPE_PRIM_QUAD_STRIP:
212 if (last_vertex_last) {
213 for (i = 0; i + 3 < count; i += 2) {
216 idx[2] = GET_ELT(i + 2);
217 idx[3] = GET_ELT(i + 3);
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]);
225 flags = DRAW_PIPE_EDGE_FLAG_0 |
226 DRAW_PIPE_EDGE_FLAG_1;
227 TRIANGLE(flags, idx[0], idx[1], idx[3]);
231 for (i = 0; i + 3 < count; i += 2) {
234 idx[2] = GET_ELT(i + 2);
235 idx[3] = GET_ELT(i + 3);
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]);
244 flags = DRAW_PIPE_EDGE_FLAG_1 |
245 DRAW_PIPE_EDGE_FLAG_2;
246 TRIANGLE(flags, idx[3], idx[0], idx[1]);
252 case PIPE_PRIM_POLYGON:
254 ushort edge_next, edge_finish;
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;
262 edge_next = DRAW_PIPE_EDGE_FLAG_0;
264 (prim_flags & DRAW_SPLIT_AFTER) ? 0 : DRAW_PIPE_EDGE_FLAG_1;
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;
272 edge_next = DRAW_PIPE_EDGE_FLAG_1;
274 (prim_flags & DRAW_SPLIT_AFTER) ? 0 : DRAW_PIPE_EDGE_FLAG_2;
280 for (i = 0; i + 2 < count; i++, flags = edge_next) {
282 idx[2] = GET_ELT(i + 2);
285 flags |= edge_finish;
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]);
291 TRIANGLE(flags, idx[0], idx[1], idx[2]);
296 case PIPE_PRIM_LINES_ADJACENCY:
297 flags = DRAW_PIPE_RESET_STIPPLE;
298 for (i = 0; i + 3 < count; i += 4) {
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]);
307 case PIPE_PRIM_LINE_STRIP_ADJACENCY:
309 flags = (prim_flags & DRAW_SPLIT_BEFORE) ? 0 : DRAW_PIPE_RESET_STIPPLE;
314 for (i = 1; i + 2 < count; i++, flags = 0) {
318 idx[3] = GET_ELT(i + 2);
319 LINE_ADJ(flags, idx[0], idx[1], idx[2], idx[3]);
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) {
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]);
337 case PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY:
339 flags = DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL;
346 * The vertices of the i-th triangle are stored in
347 * idx[0,2,4] = { 2*i, 2*i+2, 2*i+4 };
349 * The adjacent vertices are stored in
350 * idx[1,3,5] = { 2*i-2, 2*i+6, 2*i+3 }.
352 * However, there are two exceptions:
354 * For the first triangle, idx[1] = 1;
355 * For the last triangle, idx[3] = 2*i+5.
357 if (last_vertex_last) {
358 for (i = 0; i + 5 < count; i += 2) {
365 idx[3] = GET_ELT(i + ((i + 7 < count) ? 6 : 5));
366 idx[5] = GET_ELT(i + 3);
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
375 idx[2], idx[1], idx[0], idx[5], idx[4], idx[3]);
379 idx[0], idx[1], idx[2], idx[3], idx[4], idx[5]);
384 for (i = 0; i + 5 < count; i += 2) {
391 idx[3] = GET_ELT(i + ((i + 7 < count) ? 6 : 5));
392 idx[5] = GET_ELT(i + 3);
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
401 idx[0], idx[5], idx[4], idx[3], idx[2], idx[1]);
405 idx[0], idx[1], idx[2], idx[3], idx[4], idx[5]);