t_vb_rendertmp.h revision 7117f1b4
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
60static void TAG(render_points)( GLcontext *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
73static void TAG(render_lines)( GLcontext *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      RENDER_LINE( ELT(j-1), ELT(j) );
86   }
87   POSTFIX;
88}
89
90
91static void TAG(render_line_strip)( GLcontext *ctx,
92				    GLuint start,
93				    GLuint count,
94				    GLuint flags )
95{
96   GLuint j;
97   LOCAL_VARS;
98   (void) flags;
99
100   INIT(GL_LINE_STRIP);
101
102   if (TEST_PRIM_BEGIN(flags)) {
103      RESET_STIPPLE;
104   }
105
106   for (j=start+1; j<count; j++ )
107      RENDER_LINE( ELT(j-1), ELT(j) );
108
109   POSTFIX;
110}
111
112
113static void TAG(render_line_loop)( GLcontext *ctx,
114				   GLuint start,
115				   GLuint count,
116				   GLuint flags )
117{
118   GLuint i;
119   LOCAL_VARS;
120
121   (void) flags;
122
123   INIT(GL_LINE_LOOP);
124
125   if (start+1 < count) {
126      if (TEST_PRIM_BEGIN(flags)) {
127	 RESET_STIPPLE;
128	 RENDER_LINE( ELT(start), ELT(start+1) );
129      }
130
131      for ( i = start+2 ; i < count ; i++) {
132	 RENDER_LINE( ELT(i-1), ELT(i) );
133      }
134
135      if ( TEST_PRIM_END(flags)) {
136	 RENDER_LINE( ELT(count-1), ELT(start) );
137      }
138   }
139
140   POSTFIX;
141}
142
143
144static void TAG(render_triangles)( GLcontext *ctx,
145				   GLuint start,
146				   GLuint count,
147				   GLuint flags )
148{
149   GLuint j;
150   LOCAL_VARS;
151   (void) flags;
152
153   INIT(GL_TRIANGLES);
154   if (NEED_EDGEFLAG_SETUP) {
155      for (j=start+2; j<count; j+=3) {
156	 /* Leave the edgeflags as supplied by the user.
157	  */
158	 RESET_STIPPLE;
159	 RENDER_TRI( ELT(j-2), ELT(j-1), ELT(j) );
160      }
161   } else {
162      for (j=start+2; j<count; j+=3) {
163	 RENDER_TRI( ELT(j-2), ELT(j-1), ELT(j) );
164      }
165   }
166   POSTFIX;
167}
168
169
170
171static void TAG(render_tri_strip)( GLcontext *ctx,
172				   GLuint start,
173				   GLuint count,
174				   GLuint flags )
175{
176   GLuint j;
177   GLuint parity = 0;
178   LOCAL_VARS;
179
180   INIT(GL_TRIANGLE_STRIP);
181   if (NEED_EDGEFLAG_SETUP) {
182      for (j=start+2;j<count;j++,parity^=1) {
183	 GLuint ej2 = ELT(j-2+parity);
184	 GLuint ej1 = ELT(j-1-parity);
185	 GLuint ej = ELT(j);
186	 GLboolean ef2 = EDGEFLAG_GET( ej2 );
187	 GLboolean ef1 = EDGEFLAG_GET( ej1 );
188	 GLboolean ef = EDGEFLAG_GET( ej );
189	 if (TEST_PRIM_BEGIN(flags)) {
190	    RESET_STIPPLE;
191	 }
192	 EDGEFLAG_SET( ej2, GL_TRUE );
193	 EDGEFLAG_SET( ej1, GL_TRUE );
194	 EDGEFLAG_SET( ej, GL_TRUE );
195	 RENDER_TRI( ej2, ej1, ej );
196	 EDGEFLAG_SET( ej2, ef2 );
197	 EDGEFLAG_SET( ej1, ef1 );
198	 EDGEFLAG_SET( ej, ef );
199      }
200   } else {
201      for (j=start+2; j<count ; j++, parity^=1) {
202	 RENDER_TRI( ELT(j-2+parity), ELT(j-1-parity), ELT(j) );
203      }
204   }
205   POSTFIX;
206}
207
208
209static void TAG(render_tri_fan)( GLcontext *ctx,
210				 GLuint start,
211				 GLuint count,
212				 GLuint flags )
213{
214   GLuint j;
215   LOCAL_VARS;
216   (void) flags;
217
218   INIT(GL_TRIANGLE_FAN);
219   if (NEED_EDGEFLAG_SETUP) {
220      for (j=start+2;j<count;j++) {
221	 /* For trifans, all edges are boundary.
222	  */
223	 GLuint ejs = ELT(start);
224	 GLuint ej1 = ELT(j-1);
225	 GLuint ej = ELT(j);
226	 GLboolean efs = EDGEFLAG_GET( ejs );
227	 GLboolean ef1 = EDGEFLAG_GET( ej1 );
228	 GLboolean ef = EDGEFLAG_GET( ej );
229	 if (TEST_PRIM_BEGIN(flags)) {
230	    RESET_STIPPLE;
231	 }
232	 EDGEFLAG_SET( ejs, GL_TRUE );
233	 EDGEFLAG_SET( ej1, GL_TRUE );
234	 EDGEFLAG_SET( ej, GL_TRUE );
235	 RENDER_TRI( ejs, ej1, ej);
236	 EDGEFLAG_SET( ejs, efs );
237	 EDGEFLAG_SET( ej1, ef1 );
238	 EDGEFLAG_SET( ej, ef );
239      }
240   } else {
241      for (j=start+2;j<count;j++) {
242	 RENDER_TRI( ELT(start), ELT(j-1), ELT(j) );
243      }
244   }
245
246   POSTFIX;
247}
248
249
250static void TAG(render_poly)( GLcontext *ctx,
251			      GLuint start,
252			      GLuint count,
253			      GLuint flags )
254{
255   GLuint j = start+2;
256   LOCAL_VARS;
257   (void) flags;
258
259   INIT(GL_POLYGON);
260   if (NEED_EDGEFLAG_SETUP) {
261      GLboolean efstart = EDGEFLAG_GET( ELT(start) );
262      GLboolean efcount = EDGEFLAG_GET( ELT(count-1) );
263
264      /* If the primitive does not begin here, the first edge
265       * is non-boundary.
266       */
267      if (!TEST_PRIM_BEGIN(flags))
268	 EDGEFLAG_SET( ELT(start), GL_FALSE );
269      else {
270	 RESET_STIPPLE;
271      }
272
273      /* If the primitive does not end here, the final edge is
274       * non-boundary.
275       */
276      if (!TEST_PRIM_END(flags))
277	 EDGEFLAG_SET( ELT(count-1), GL_FALSE );
278
279      /* Draw the first triangles (possibly zero)
280       */
281      if (j+1<count) {
282	 GLboolean ef = EDGEFLAG_GET( ELT(j) );
283	 EDGEFLAG_SET( ELT(j), GL_FALSE );
284	 RENDER_TRI( ELT(j-1), ELT(j), ELT(start) );
285	 EDGEFLAG_SET( ELT(j), ef );
286	 j++;
287
288	 /* Don't render the first edge again:
289	  */
290	 EDGEFLAG_SET( ELT(start), GL_FALSE );
291
292	 for (;j+1<count;j++) {
293	    GLboolean efj = EDGEFLAG_GET( ELT(j) );
294	    EDGEFLAG_SET( ELT(j), GL_FALSE );
295	    RENDER_TRI( ELT(j-1), ELT(j), ELT(start) );
296	    EDGEFLAG_SET( ELT(j), efj );
297	 }
298      }
299
300      /* Draw the last or only triangle
301       */
302      if (j < count)
303	 RENDER_TRI( ELT(j-1), ELT(j), ELT(start) );
304
305      /* Restore the first and last edgeflags:
306       */
307      EDGEFLAG_SET( ELT(count-1), efcount );
308      EDGEFLAG_SET( ELT(start), efstart );
309
310   }
311   else {
312      for (j=start+2;j<count;j++) {
313	 RENDER_TRI( ELT(j-1), ELT(j), ELT(start) );
314      }
315   }
316   POSTFIX;
317}
318
319static void TAG(render_quads)( GLcontext *ctx,
320			       GLuint start,
321			       GLuint count,
322			       GLuint flags )
323{
324   GLuint j;
325   LOCAL_VARS;
326   (void) flags;
327
328   INIT(GL_QUADS);
329   if (NEED_EDGEFLAG_SETUP) {
330      for (j=start+3; j<count; j+=4) {
331	 /* Use user-specified edgeflags for quads.
332	  */
333	 RESET_STIPPLE;
334	 RENDER_QUAD( ELT(j-3), ELT(j-2), ELT(j-1), ELT(j) );
335      }
336   } else {
337      for (j=start+3; j<count; j+=4) {
338	 RENDER_QUAD( ELT(j-3), ELT(j-2), ELT(j-1), ELT(j) );
339      }
340   }
341   POSTFIX;
342}
343
344static void TAG(render_quad_strip)( GLcontext *ctx,
345				    GLuint start,
346				    GLuint count,
347				    GLuint flags )
348{
349   GLuint j;
350   LOCAL_VARS;
351   (void) flags;
352
353   INIT(GL_QUAD_STRIP);
354   if (NEED_EDGEFLAG_SETUP) {
355      for (j=start+3;j<count;j+=2) {
356	 /* All edges are boundary.  Set edgeflags to 1, draw the
357	  * quad, and restore them to the original values.
358	  */
359	 GLboolean ef3 = EDGEFLAG_GET( ELT(j-3) );
360	 GLboolean ef2 = EDGEFLAG_GET( ELT(j-2) );
361	 GLboolean ef1 = EDGEFLAG_GET( ELT(j-1) );
362	 GLboolean ef = EDGEFLAG_GET( ELT(j) );
363	 if (TEST_PRIM_BEGIN(flags)) {
364	    RESET_STIPPLE;
365	 }
366	 EDGEFLAG_SET( ELT(j-3), GL_TRUE );
367	 EDGEFLAG_SET( ELT(j-2), GL_TRUE );
368	 EDGEFLAG_SET( ELT(j-1), GL_TRUE );
369	 EDGEFLAG_SET( ELT(j), GL_TRUE );
370	 RENDER_QUAD( ELT(j-1), ELT(j-3), ELT(j-2), ELT(j) );
371	 EDGEFLAG_SET( ELT(j-3), ef3 );
372	 EDGEFLAG_SET( ELT(j-2), ef2 );
373	 EDGEFLAG_SET( ELT(j-1), ef1 );
374	 EDGEFLAG_SET( ELT(j), ef );
375      }
376   } else {
377      for (j=start+3;j<count;j+=2) {
378	 RENDER_QUAD( ELT(j-1), ELT(j-3), ELT(j-2), ELT(j) );
379      }
380   }
381   POSTFIX;
382}
383
384static void TAG(render_noop)( GLcontext *ctx,
385			      GLuint start,
386			      GLuint count,
387			      GLuint flags )
388{
389   (void)(ctx && start && count && flags);
390}
391
392RENDER_TAB_QUALIFIER void (*TAG(render_tab)[GL_POLYGON+2])(GLcontext *,
393							   GLuint,
394							   GLuint,
395							   GLuint) =
396{
397   TAG(render_points),
398   TAG(render_lines),
399   TAG(render_line_loop),
400   TAG(render_line_strip),
401   TAG(render_triangles),
402   TAG(render_tri_strip),
403   TAG(render_tri_fan),
404   TAG(render_quads),
405   TAG(render_quad_strip),
406   TAG(render_poly),
407   TAG(render_noop),
408};
409
410
411
412#ifndef PRESERVE_VB_DEFS
413#undef RENDER_TRI
414#undef RENDER_QUAD
415#undef RENDER_LINE
416#undef RENDER_POINTS
417#undef LOCAL_VARS
418#undef INIT
419#undef POSTFIX
420#undef RESET_STIPPLE
421#undef DBG
422#undef ELT
423#undef RENDER_TAB_QUALIFIER
424#endif
425
426#ifndef PRESERVE_TAG
427#undef TAG
428#endif
429
430#undef PRESERVE_VB_DEFS
431#undef PRESERVE_TAG
432