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