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