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