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