1 /*
2 * Mesa 3-D graphics library
3 * Version: 6.5
4 *
5 * Copyright (C) 1999-2005 Brian Paul All Rights Reserved.
6 *
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:
13 *
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 *
24 * Authors:
25 * Keith Whitwell <keith@tungstengraphics.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 (void) flags;
128
129 INIT(GL_LINE_LOOP);
130
131 if (start+1 < count) {
132 if (TEST_PRIM_BEGIN(flags)) {
133 RESET_STIPPLE;
134 if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT)
135 RENDER_LINE( ELT(start), ELT(start+1) );
136 else
137 RENDER_LINE( ELT(start+1), ELT(start) );
138 }
139
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 if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT)
149 RENDER_LINE( ELT(count-1), ELT(start) );
150 else
151 RENDER_LINE( ELT(start), ELT(count-1) );
152 }
153 }
154
155 POSTFIX;
156 }
157
158
TAG(render_triangles)159 static void TAG(render_triangles)( struct gl_context *ctx,
160 GLuint start,
161 GLuint count,
162 GLuint flags )
163 {
164 GLuint j;
165 LOCAL_VARS;
166 (void) flags;
167
168 INIT(GL_TRIANGLES);
169 if (NEED_EDGEFLAG_SETUP) {
170 for (j=start+2; j<count; j+=3) {
171 /* Leave the edgeflags as supplied by the user.
172 */
173 RESET_STIPPLE;
174 if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT)
175 RENDER_TRI( ELT(j-2), ELT(j-1), ELT(j) );
176 else
177 RENDER_TRI( ELT(j-1), ELT(j), ELT(j-2) );
178 }
179 } else {
180 for (j=start+2; j<count; j+=3) {
181 if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT)
182 RENDER_TRI( ELT(j-2), ELT(j-1), ELT(j) );
183 else
184 RENDER_TRI( ELT(j-1), ELT(j), ELT(j-2) );
185 }
186 }
187 POSTFIX;
188 }
189
190
191
TAG(render_tri_strip)192 static void TAG(render_tri_strip)( struct gl_context *ctx,
193 GLuint start,
194 GLuint count,
195 GLuint flags )
196 {
197 GLuint j;
198 GLuint parity = 0;
199 LOCAL_VARS;
200
201 INIT(GL_TRIANGLE_STRIP);
202 if (NEED_EDGEFLAG_SETUP) {
203 for (j=start+2;j<count;j++,parity^=1) {
204 GLuint ej2, ej1, ej;
205 GLboolean ef2, ef1, ef;
206 if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT) {
207 ej2 = ELT(j-2+parity);
208 ej1 = ELT(j-1-parity);
209 ej = ELT(j);
210 }
211 else {
212 ej2 = ELT(j-1+parity);
213 ej1 = ELT(j-parity);
214 ej = ELT(j-2);
215 }
216 ef2 = EDGEFLAG_GET( ej2 );
217 ef1 = EDGEFLAG_GET( ej1 );
218 ef = EDGEFLAG_GET( ej );
219 if (TEST_PRIM_BEGIN(flags)) {
220 RESET_STIPPLE;
221 }
222 EDGEFLAG_SET( ej2, GL_TRUE );
223 EDGEFLAG_SET( ej1, GL_TRUE );
224 EDGEFLAG_SET( ej, GL_TRUE );
225 RENDER_TRI( ej2, ej1, ej );
226 EDGEFLAG_SET( ej2, ef2 );
227 EDGEFLAG_SET( ej1, ef1 );
228 EDGEFLAG_SET( ej, ef );
229 }
230 } else {
231 for (j=start+2; j<count ; j++, parity^=1) {
232 if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT)
233 RENDER_TRI( ELT(j-2+parity), ELT(j-1-parity), ELT(j) );
234 else
235 RENDER_TRI( ELT(j-1+parity), ELT(j-parity), ELT(j-2) );
236 }
237 }
238 POSTFIX;
239 }
240
241
TAG(render_tri_fan)242 static void TAG(render_tri_fan)( struct gl_context *ctx,
243 GLuint start,
244 GLuint count,
245 GLuint flags )
246 {
247 GLuint j;
248 LOCAL_VARS;
249 (void) flags;
250
251 INIT(GL_TRIANGLE_FAN);
252 if (NEED_EDGEFLAG_SETUP) {
253 for (j=start+2;j<count;j++) {
254 /* For trifans, all edges are boundary.
255 */
256 GLuint ejs = ELT(start);
257 GLuint ej1 = ELT(j-1);
258 GLuint ej = ELT(j);
259 GLboolean efs = EDGEFLAG_GET( ejs );
260 GLboolean ef1 = EDGEFLAG_GET( ej1 );
261 GLboolean ef = EDGEFLAG_GET( ej );
262 if (TEST_PRIM_BEGIN(flags)) {
263 RESET_STIPPLE;
264 }
265 EDGEFLAG_SET( ejs, GL_TRUE );
266 EDGEFLAG_SET( ej1, GL_TRUE );
267 EDGEFLAG_SET( ej, GL_TRUE );
268 if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT)
269 RENDER_TRI( ejs, ej1, ej);
270 else
271 RENDER_TRI( ej, ejs, ej1);
272 EDGEFLAG_SET( ejs, efs );
273 EDGEFLAG_SET( ej1, ef1 );
274 EDGEFLAG_SET( ej, ef );
275 }
276 } else {
277 for (j=start+2;j<count;j++) {
278 if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT)
279 RENDER_TRI( ELT(start), ELT(j-1), ELT(j) );
280 else
281 RENDER_TRI( ELT(j), ELT(start), ELT(j-1) );
282 }
283 }
284
285 POSTFIX;
286 }
287
288
TAG(render_poly)289 static void TAG(render_poly)( struct gl_context *ctx,
290 GLuint start,
291 GLuint count,
292 GLuint flags )
293 {
294 GLuint j = start+2;
295 LOCAL_VARS;
296 (void) flags;
297
298 INIT(GL_POLYGON);
299 if (NEED_EDGEFLAG_SETUP) {
300 GLboolean efstart = EDGEFLAG_GET( ELT(start) );
301 GLboolean efcount = EDGEFLAG_GET( ELT(count-1) );
302
303 /* If the primitive does not begin here, the first edge
304 * is non-boundary.
305 */
306 if (!TEST_PRIM_BEGIN(flags))
307 EDGEFLAG_SET( ELT(start), GL_FALSE );
308 else {
309 RESET_STIPPLE;
310 }
311
312 /* If the primitive does not end here, the final edge is
313 * non-boundary.
314 */
315 if (!TEST_PRIM_END(flags))
316 EDGEFLAG_SET( ELT(count-1), GL_FALSE );
317
318 /* Draw the first triangles (possibly zero)
319 */
320 if (j+1<count) {
321 GLboolean ef = EDGEFLAG_GET( ELT(j) );
322 EDGEFLAG_SET( ELT(j), GL_FALSE );
323 RENDER_TRI( ELT(j-1), ELT(j), ELT(start) );
324 EDGEFLAG_SET( ELT(j), ef );
325 j++;
326
327 /* Don't render the first edge again:
328 */
329 EDGEFLAG_SET( ELT(start), GL_FALSE );
330
331 for (;j+1<count;j++) {
332 GLboolean efj = EDGEFLAG_GET( ELT(j) );
333 EDGEFLAG_SET( ELT(j), GL_FALSE );
334 RENDER_TRI( ELT(j-1), ELT(j), ELT(start) );
335 EDGEFLAG_SET( ELT(j), efj );
336 }
337 }
338
339 /* Draw the last or only triangle
340 */
341 if (j < count)
342 RENDER_TRI( ELT(j-1), ELT(j), ELT(start) );
343
344 /* Restore the first and last edgeflags:
345 */
346 EDGEFLAG_SET( ELT(count-1), efcount );
347 EDGEFLAG_SET( ELT(start), efstart );
348
349 }
350 else {
351 for (j=start+2;j<count;j++) {
352 RENDER_TRI( ELT(j-1), ELT(j), ELT(start) );
353 }
354 }
355 POSTFIX;
356 }
357
TAG(render_quads)358 static void TAG(render_quads)( struct gl_context *ctx,
359 GLuint start,
360 GLuint count,
361 GLuint flags )
362 {
363 GLuint j;
364 LOCAL_VARS;
365 (void) flags;
366
367 INIT(GL_QUADS);
368 if (NEED_EDGEFLAG_SETUP) {
369 for (j=start+3; j<count; j+=4) {
370 /* Use user-specified edgeflags for quads.
371 */
372 RESET_STIPPLE;
373 if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT ||
374 !ctx->Const.QuadsFollowProvokingVertexConvention)
375 RENDER_QUAD( ELT(j-3), ELT(j-2), ELT(j-1), ELT(j) );
376 else
377 RENDER_QUAD( ELT(j-2), ELT(j-1), ELT(j), ELT(j-3) );
378 }
379 } else {
380 for (j=start+3; j<count; j+=4) {
381 if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT ||
382 !ctx->Const.QuadsFollowProvokingVertexConvention)
383 RENDER_QUAD( ELT(j-3), ELT(j-2), ELT(j-1), ELT(j) );
384 else
385 RENDER_QUAD( ELT(j-2), ELT(j-1), ELT(j), ELT(j-3) );
386 }
387 }
388 POSTFIX;
389 }
390
TAG(render_quad_strip)391 static void TAG(render_quad_strip)( struct gl_context *ctx,
392 GLuint start,
393 GLuint count,
394 GLuint flags )
395 {
396 GLuint j;
397 LOCAL_VARS;
398 (void) flags;
399
400 INIT(GL_QUAD_STRIP);
401 if (NEED_EDGEFLAG_SETUP) {
402 for (j=start+3;j<count;j+=2) {
403 /* All edges are boundary. Set edgeflags to 1, draw the
404 * quad, and restore them to the original values.
405 */
406 GLboolean ef3 = EDGEFLAG_GET( ELT(j-3) );
407 GLboolean ef2 = EDGEFLAG_GET( ELT(j-2) );
408 GLboolean ef1 = EDGEFLAG_GET( ELT(j-1) );
409 GLboolean ef = EDGEFLAG_GET( ELT(j) );
410 if (TEST_PRIM_BEGIN(flags)) {
411 RESET_STIPPLE;
412 }
413 EDGEFLAG_SET( ELT(j-3), GL_TRUE );
414 EDGEFLAG_SET( ELT(j-2), GL_TRUE );
415 EDGEFLAG_SET( ELT(j-1), GL_TRUE );
416 EDGEFLAG_SET( ELT(j), GL_TRUE );
417 if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT ||
418 !ctx->Const.QuadsFollowProvokingVertexConvention)
419 RENDER_QUAD( ELT(j-1), ELT(j-3), ELT(j-2), ELT(j) );
420 else
421 RENDER_QUAD( ELT(j-2), ELT(j), ELT(j-1), ELT(j-3) );
422 EDGEFLAG_SET( ELT(j-3), ef3 );
423 EDGEFLAG_SET( ELT(j-2), ef2 );
424 EDGEFLAG_SET( ELT(j-1), ef1 );
425 EDGEFLAG_SET( ELT(j), ef );
426 }
427 } else {
428 for (j=start+3;j<count;j+=2) {
429 if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT ||
430 !ctx->Const.QuadsFollowProvokingVertexConvention)
431 RENDER_QUAD( ELT(j-1), ELT(j-3), ELT(j-2), ELT(j) );
432 else
433 RENDER_QUAD( ELT(j-2), ELT(j), ELT(j-1), ELT(j-3) );
434 }
435 }
436 POSTFIX;
437 }
438
TAG(render_noop)439 static void TAG(render_noop)( struct gl_context *ctx,
440 GLuint start,
441 GLuint count,
442 GLuint flags )
443 {
444 (void)(ctx && start && count && flags);
445 }
446
447 RENDER_TAB_QUALIFIER void (*TAG(render_tab)[GL_POLYGON+2])(struct gl_context *,
448 GLuint,
449 GLuint,
450 GLuint) =
451 {
452 TAG(render_points),
453 TAG(render_lines),
454 TAG(render_line_loop),
455 TAG(render_line_strip),
456 TAG(render_triangles),
457 TAG(render_tri_strip),
458 TAG(render_tri_fan),
459 TAG(render_quads),
460 TAG(render_quad_strip),
461 TAG(render_poly),
462 TAG(render_noop),
463 };
464
465
466
467 #ifndef PRESERVE_VB_DEFS
468 #undef RENDER_TRI
469 #undef RENDER_QUAD
470 #undef RENDER_LINE
471 #undef RENDER_POINTS
472 #undef LOCAL_VARS
473 #undef INIT
474 #undef POSTFIX
475 #undef RESET_STIPPLE
476 #undef DBG
477 #undef ELT
478 #undef RENDER_TAB_QUALIFIER
479 #endif
480
481 #ifndef PRESERVE_TAG
482 #undef TAG
483 #endif
484
485 #undef PRESERVE_VB_DEFS
486 #undef PRESERVE_TAG
487