1 /*
2 * Mesa 3-D graphics library
3 *
4 * Copyright (C) 1999-2005 Brian Paul All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included
14 * in all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 * OTHER DEALINGS IN THE SOFTWARE.
23 *
24 * Authors:
25 * Keith Whitwell <keithw@vmware.com>
26 */
27
28
29 #ifndef POSTFIX
30 #define POSTFIX
31 #endif
32
33 #ifndef INIT
34 #define INIT(x)
35 #endif
36
37 #ifndef NEED_EDGEFLAG_SETUP
38 #define NEED_EDGEFLAG_SETUP 0
39 #define EDGEFLAG_GET(a) 0
40 #define EDGEFLAG_SET(a,b) (void)b
41 #endif
42
43 #ifndef RESET_STIPPLE
44 #define RESET_STIPPLE
45 #endif
46
47 #ifndef TEST_PRIM_END
48 #define TEST_PRIM_END(prim) (flags & PRIM_END)
49 #define TEST_PRIM_BEGIN(prim) (flags & PRIM_BEGIN)
50 #endif
51
52 #ifndef ELT
53 #define ELT(x) x
54 #endif
55
56 #ifndef RENDER_TAB_QUALIFIER
57 #define RENDER_TAB_QUALIFIER static
58 #endif
59
TAG(render_points)60 static void TAG(render_points)( struct gl_context *ctx,
61 GLuint start,
62 GLuint count,
63 GLuint flags )
64 {
65 LOCAL_VARS;
66 (void) flags;
67
68 INIT(GL_POINTS);
69 RENDER_POINTS( start, count );
70 POSTFIX;
71 }
72
TAG(render_lines)73 static void TAG(render_lines)( struct gl_context *ctx,
74 GLuint start,
75 GLuint count,
76 GLuint flags )
77 {
78 GLuint j;
79 LOCAL_VARS;
80 (void) flags;
81
82 INIT(GL_LINES);
83 for (j=start+1; j<count; j+=2 ) {
84 RESET_STIPPLE;
85 if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT)
86 RENDER_LINE( ELT(j-1), ELT(j) );
87 else
88 RENDER_LINE( ELT(j), ELT(j-1) );
89 }
90 POSTFIX;
91 }
92
93
TAG(render_line_strip)94 static void TAG(render_line_strip)( struct gl_context *ctx,
95 GLuint start,
96 GLuint count,
97 GLuint flags )
98 {
99 GLuint j;
100 LOCAL_VARS;
101 (void) flags;
102
103 INIT(GL_LINE_STRIP);
104
105 if (TEST_PRIM_BEGIN(flags)) {
106 RESET_STIPPLE;
107 }
108
109 for (j=start+1; j<count; j++ ) {
110 if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT)
111 RENDER_LINE( ELT(j-1), ELT(j) );
112 else
113 RENDER_LINE( ELT(j), ELT(j-1) );
114 }
115 POSTFIX;
116 }
117
118
TAG(render_line_loop)119 static void TAG(render_line_loop)( struct gl_context *ctx,
120 GLuint start,
121 GLuint count,
122 GLuint flags )
123 {
124 GLuint i;
125 LOCAL_VARS;
126
127 INIT(GL_LINE_LOOP);
128
129 if (start+1 < count) {
130 if (TEST_PRIM_BEGIN(flags)) {
131 RESET_STIPPLE;
132 /* draw the first line from v[0] to v[1] */
133 if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT)
134 RENDER_LINE( ELT(start), ELT(start+1) );
135 else
136 RENDER_LINE( ELT(start+1), ELT(start) );
137 }
138
139 /* draw lines from v[1] to v[n-1] */
140 for ( i = start+2 ; i < count ; i++) {
141 if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT)
142 RENDER_LINE( ELT(i-1), ELT(i) );
143 else
144 RENDER_LINE( ELT(i), ELT(i-1) );
145 }
146
147 if ( TEST_PRIM_END(flags)) {
148 /* draw final line from v[n-1] to v[0] (the very first vertex) */
149 if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT)
150 RENDER_LINE( ELT(count-1), ELT(start) );
151 else
152 RENDER_LINE( ELT(start), ELT(count-1) );
153 }
154 }
155
156 POSTFIX;
157 }
158
159
TAG(render_triangles)160 static void TAG(render_triangles)( struct gl_context *ctx,
161 GLuint start,
162 GLuint count,
163 GLuint flags )
164 {
165 GLuint j;
166 LOCAL_VARS;
167 (void) flags;
168
169 INIT(GL_TRIANGLES);
170 if (NEED_EDGEFLAG_SETUP) {
171 for (j=start+2; j<count; j+=3) {
172 /* Leave the edgeflags as supplied by the user.
173 */
174 RESET_STIPPLE;
175 if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT)
176 RENDER_TRI( ELT(j-2), ELT(j-1), ELT(j) );
177 else
178 RENDER_TRI( ELT(j-1), ELT(j), ELT(j-2) );
179 }
180 } else {
181 for (j=start+2; j<count; j+=3) {
182 if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT)
183 RENDER_TRI( ELT(j-2), ELT(j-1), ELT(j) );
184 else
185 RENDER_TRI( ELT(j-1), ELT(j), ELT(j-2) );
186 }
187 }
188 POSTFIX;
189 }
190
191
192
TAG(render_tri_strip)193 static void TAG(render_tri_strip)( struct gl_context *ctx,
194 GLuint start,
195 GLuint count,
196 GLuint flags )
197 {
198 GLuint j;
199 GLuint parity = 0;
200 LOCAL_VARS;
201
202 INIT(GL_TRIANGLE_STRIP);
203 if (NEED_EDGEFLAG_SETUP) {
204 for (j=start+2;j<count;j++,parity^=1) {
205 GLuint ej2, ej1, ej;
206 GLboolean ef2, ef1, ef;
207 if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT) {
208 ej2 = ELT(j-2+parity);
209 ej1 = ELT(j-1-parity);
210 ej = ELT(j);
211 }
212 else {
213 ej2 = ELT(j-1+parity);
214 ej1 = ELT(j-parity);
215 ej = ELT(j-2);
216 }
217 ef2 = EDGEFLAG_GET( ej2 );
218 ef1 = EDGEFLAG_GET( ej1 );
219 ef = EDGEFLAG_GET( ej );
220 if (TEST_PRIM_BEGIN(flags)) {
221 RESET_STIPPLE;
222 }
223 EDGEFLAG_SET( ej2, GL_TRUE );
224 EDGEFLAG_SET( ej1, GL_TRUE );
225 EDGEFLAG_SET( ej, GL_TRUE );
226 RENDER_TRI( ej2, ej1, ej );
227 EDGEFLAG_SET( ej2, ef2 );
228 EDGEFLAG_SET( ej1, ef1 );
229 EDGEFLAG_SET( ej, ef );
230 }
231 } else {
232 for (j=start+2; j<count ; j++, parity^=1) {
233 if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT)
234 RENDER_TRI( ELT(j-2+parity), ELT(j-1-parity), ELT(j) );
235 else
236 RENDER_TRI( ELT(j-1+parity), ELT(j-parity), ELT(j-2) );
237 }
238 }
239 POSTFIX;
240 }
241
242
TAG(render_tri_fan)243 static void TAG(render_tri_fan)( struct gl_context *ctx,
244 GLuint start,
245 GLuint count,
246 GLuint flags )
247 {
248 GLuint j;
249 LOCAL_VARS;
250 (void) flags;
251
252 INIT(GL_TRIANGLE_FAN);
253 if (NEED_EDGEFLAG_SETUP) {
254 for (j=start+2;j<count;j++) {
255 /* For trifans, all edges are boundary.
256 */
257 GLuint ejs = ELT(start);
258 GLuint ej1 = ELT(j-1);
259 GLuint ej = ELT(j);
260 GLboolean efs = EDGEFLAG_GET( ejs );
261 GLboolean ef1 = EDGEFLAG_GET( ej1 );
262 GLboolean ef = EDGEFLAG_GET( ej );
263 if (TEST_PRIM_BEGIN(flags)) {
264 RESET_STIPPLE;
265 }
266 EDGEFLAG_SET( ejs, GL_TRUE );
267 EDGEFLAG_SET( ej1, GL_TRUE );
268 EDGEFLAG_SET( ej, GL_TRUE );
269 if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT)
270 RENDER_TRI( ejs, ej1, ej);
271 else
272 RENDER_TRI( ej, ejs, ej1);
273 EDGEFLAG_SET( ejs, efs );
274 EDGEFLAG_SET( ej1, ef1 );
275 EDGEFLAG_SET( ej, ef );
276 }
277 } else {
278 for (j=start+2;j<count;j++) {
279 if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT)
280 RENDER_TRI( ELT(start), ELT(j-1), ELT(j) );
281 else
282 RENDER_TRI( ELT(j), ELT(start), ELT(j-1) );
283 }
284 }
285
286 POSTFIX;
287 }
288
289
TAG(render_poly)290 static void TAG(render_poly)( struct gl_context *ctx,
291 GLuint start,
292 GLuint count,
293 GLuint flags )
294 {
295 GLuint j = start+2;
296 LOCAL_VARS;
297 (void) flags;
298
299 INIT(GL_POLYGON);
300 if (NEED_EDGEFLAG_SETUP) {
301 GLboolean efstart = EDGEFLAG_GET( ELT(start) );
302 GLboolean efcount = EDGEFLAG_GET( ELT(count-1) );
303
304 /* If the primitive does not begin here, the first edge
305 * is non-boundary.
306 */
307 if (!TEST_PRIM_BEGIN(flags))
308 EDGEFLAG_SET( ELT(start), GL_FALSE );
309 else {
310 RESET_STIPPLE;
311 }
312
313 /* If the primitive does not end here, the final edge is
314 * non-boundary.
315 */
316 if (!TEST_PRIM_END(flags))
317 EDGEFLAG_SET( ELT(count-1), GL_FALSE );
318
319 /* Draw the first triangles (possibly zero)
320 */
321 if (j+1<count) {
322 GLboolean ef = EDGEFLAG_GET( ELT(j) );
323 EDGEFLAG_SET( ELT(j), GL_FALSE );
324 RENDER_TRI( ELT(j-1), ELT(j), ELT(start) );
325 EDGEFLAG_SET( ELT(j), ef );
326 j++;
327
328 /* Don't render the first edge again:
329 */
330 EDGEFLAG_SET( ELT(start), GL_FALSE );
331
332 for (;j+1<count;j++) {
333 GLboolean efj = EDGEFLAG_GET( ELT(j) );
334 EDGEFLAG_SET( ELT(j), GL_FALSE );
335 RENDER_TRI( ELT(j-1), ELT(j), ELT(start) );
336 EDGEFLAG_SET( ELT(j), efj );
337 }
338 }
339
340 /* Draw the last or only triangle
341 */
342 if (j < count)
343 RENDER_TRI( ELT(j-1), ELT(j), ELT(start) );
344
345 /* Restore the first and last edgeflags:
346 */
347 EDGEFLAG_SET( ELT(count-1), efcount );
348 EDGEFLAG_SET( ELT(start), efstart );
349
350 }
351 else {
352 for (j=start+2;j<count;j++) {
353 RENDER_TRI( ELT(j-1), ELT(j), ELT(start) );
354 }
355 }
356 POSTFIX;
357 }
358
TAG(render_quads)359 static void TAG(render_quads)( struct gl_context *ctx,
360 GLuint start,
361 GLuint count,
362 GLuint flags )
363 {
364 GLuint j;
365 LOCAL_VARS;
366 (void) flags;
367
368 INIT(GL_QUADS);
369 if (NEED_EDGEFLAG_SETUP) {
370 for (j=start+3; j<count; j+=4) {
371 /* Use user-specified edgeflags for quads.
372 */
373 RESET_STIPPLE;
374 if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT ||
375 !ctx->Const.QuadsFollowProvokingVertexConvention)
376 RENDER_QUAD( ELT(j-3), ELT(j-2), ELT(j-1), ELT(j) );
377 else
378 RENDER_QUAD( ELT(j-2), ELT(j-1), ELT(j), ELT(j-3) );
379 }
380 } else {
381 for (j=start+3; j<count; j+=4) {
382 if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT ||
383 !ctx->Const.QuadsFollowProvokingVertexConvention)
384 RENDER_QUAD( ELT(j-3), ELT(j-2), ELT(j-1), ELT(j) );
385 else
386 RENDER_QUAD( ELT(j-2), ELT(j-1), ELT(j), ELT(j-3) );
387 }
388 }
389 POSTFIX;
390 }
391
TAG(render_quad_strip)392 static void TAG(render_quad_strip)( struct gl_context *ctx,
393 GLuint start,
394 GLuint count,
395 GLuint flags )
396 {
397 GLuint j;
398 LOCAL_VARS;
399 (void) flags;
400
401 INIT(GL_QUAD_STRIP);
402 if (NEED_EDGEFLAG_SETUP) {
403 for (j=start+3;j<count;j+=2) {
404 /* All edges are boundary. Set edgeflags to 1, draw the
405 * quad, and restore them to the original values.
406 */
407 GLboolean ef3 = EDGEFLAG_GET( ELT(j-3) );
408 GLboolean ef2 = EDGEFLAG_GET( ELT(j-2) );
409 GLboolean ef1 = EDGEFLAG_GET( ELT(j-1) );
410 GLboolean ef = EDGEFLAG_GET( ELT(j) );
411 if (TEST_PRIM_BEGIN(flags)) {
412 RESET_STIPPLE;
413 }
414 EDGEFLAG_SET( ELT(j-3), GL_TRUE );
415 EDGEFLAG_SET( ELT(j-2), GL_TRUE );
416 EDGEFLAG_SET( ELT(j-1), GL_TRUE );
417 EDGEFLAG_SET( ELT(j), GL_TRUE );
418 if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT ||
419 !ctx->Const.QuadsFollowProvokingVertexConvention)
420 RENDER_QUAD( ELT(j-1), ELT(j-3), ELT(j-2), ELT(j) );
421 else
422 RENDER_QUAD( ELT(j-2), ELT(j), ELT(j-1), ELT(j-3) );
423 EDGEFLAG_SET( ELT(j-3), ef3 );
424 EDGEFLAG_SET( ELT(j-2), ef2 );
425 EDGEFLAG_SET( ELT(j-1), ef1 );
426 EDGEFLAG_SET( ELT(j), ef );
427 }
428 } else {
429 for (j=start+3;j<count;j+=2) {
430 if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT ||
431 !ctx->Const.QuadsFollowProvokingVertexConvention)
432 RENDER_QUAD( ELT(j-1), ELT(j-3), ELT(j-2), ELT(j) );
433 else
434 RENDER_QUAD( ELT(j-2), ELT(j), ELT(j-1), ELT(j-3) );
435 }
436 }
437 POSTFIX;
438 }
439
TAG(render_noop)440 static void TAG(render_noop)( struct gl_context *ctx,
441 GLuint start,
442 GLuint count,
443 GLuint flags )
444 {
445 (void)(ctx && start && count && flags);
446 }
447
448 RENDER_TAB_QUALIFIER void (*TAG(render_tab)[GL_POLYGON+2])(struct gl_context *,
449 GLuint,
450 GLuint,
451 GLuint) =
452 {
453 TAG(render_points),
454 TAG(render_lines),
455 TAG(render_line_loop),
456 TAG(render_line_strip),
457 TAG(render_triangles),
458 TAG(render_tri_strip),
459 TAG(render_tri_fan),
460 TAG(render_quads),
461 TAG(render_quad_strip),
462 TAG(render_poly),
463 TAG(render_noop),
464 };
465
466
467
468 #ifndef PRESERVE_VB_DEFS
469 #undef RENDER_TRI
470 #undef RENDER_QUAD
471 #undef RENDER_LINE
472 #undef RENDER_POINTS
473 #undef LOCAL_VARS
474 #undef INIT
475 #undef POSTFIX
476 #undef RESET_STIPPLE
477 #undef DBG
478 #undef ELT
479 #undef RENDER_TAB_QUALIFIER
480 #endif
481
482 #ifndef PRESERVE_TAG
483 #undef TAG
484 #endif
485
486 #undef PRESERVE_VB_DEFS
487 #undef PRESERVE_TAG
488