Replaced struct gl_visual with struct __GLcontextModesRec from glcore.h.
[mesa.git] / src / mesa / tnl / t_vb_render.c
1 /* $Id: t_vb_render.c,v 1.11 2001/01/23 23:39:37 brianp Exp $ */
2
3 /*
4 * Mesa 3-D graphics library
5 * Version: 3.5
6 *
7 * Copyright (C) 1999-2001 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 /*
32 * Render whole vertex buffers, including projection of vertices from
33 * clip space and clipping of primitives.
34 *
35 * This file makes calls to project vertices and to the point, line
36 * and triangle rasterizers via the function pointers:
37 *
38 * context->Driver.BuildProjectedVertices()
39 *
40 * context->Driver.PointsFunc()
41 * context->Driver.LineFunc()
42 * context->Driver.TriangleFunc()
43 * context->Driver.QuadFunc()
44 *
45 * context->Driver.RenderTabVerts[]
46 * context->Driver.RenderTabElts[]
47 *
48 * None of these may be null.
49 */
50
51
52 #include "glheader.h"
53 #include "context.h"
54 #include "colormac.h"
55 #include "macros.h"
56 #include "mem.h"
57 #include "mtypes.h"
58 #include "mmath.h"
59
60 #include "math/m_matrix.h"
61 #include "math/m_xform.h"
62
63 #include "t_pipeline.h"
64
65
66
67 typedef void (*clip_line_func)( GLcontext *ctx,
68 GLuint i, GLuint j,
69 GLubyte mask);
70
71 typedef void (*clip_poly_func)( GLcontext *ctx,
72 GLuint n, GLuint vlist[],
73 GLubyte mask );
74
75
76
77
78 struct render_stage_data {
79
80 /* Clipping functions for current state.
81 */
82 interp_func interp; /* Clip interpolation function */
83 copy_pv_func copypv; /* Flatshade fixup function */
84 GLuint _ClipInputs; /* Inputs referenced by interpfunc */
85 };
86
87 #define RENDER_STAGE_DATA(stage) ((struct render_stage_data *)stage->private)
88
89
90 /**********************************************************************/
91 /* Interpolate between pairs of vertices */
92 /**********************************************************************/
93
94
95 #define LINTERP_SZ( t, vec, to, a, b, sz ) \
96 do { \
97 switch (sz) { \
98 case 4: vec[to][3] = LINTERP( t, vec[a][3], vec[b][3] ); \
99 case 3: vec[to][2] = LINTERP( t, vec[a][2], vec[b][2] ); \
100 case 2: vec[to][1] = LINTERP( t, vec[a][1], vec[b][1] ); \
101 case 1: vec[to][0] = LINTERP( t, vec[a][0], vec[b][0] ); \
102 } \
103 } while(0)
104
105
106 #if 1
107
108 #define LINTERP_RGBA(nr, t, out, a, b) { \
109 int i; \
110 for (i = 0; i < nr; i++) { \
111 GLfloat fa = CHAN_TO_FLOAT(a[i]); \
112 GLfloat fb = CHAN_TO_FLOAT(b[i]); \
113 GLfloat fo = LINTERP(t, fa, fb); \
114 CLAMPED_FLOAT_TO_CHAN(out[i], fo); \
115 } \
116 }
117
118 #else
119
120 #define LINTERP_RGBA(nr, t, out, a, b) { \
121 int n; \
122 const GLuint ti = FloatToInt(t*256.0F); \
123 const GLubyte *Ib = (const GLubyte *)&a[0]; \
124 const GLubyte *Jb = (const GLubyte *)&b[0]; \
125 GLubyte *Ob = (GLubyte *)&out[0]; \
126 \
127 for (n = 0 ; n < nr ; n++) \
128 Ob[n] = (GLubyte) (Ib[n] + ((ti * (Jb[n] - Ib[n]))/256)); \
129 }
130
131 #endif
132
133
134
135
136 #define INTERP_RGBA 0x1
137 #define INTERP_TEX 0x2
138 #define INTERP_INDEX 0x4
139 #define INTERP_SPEC 0x8
140 #define INTERP_FOG 0x10
141 #define INTERP_EDGE 0x20
142 #define MAX_INTERP 0x40
143
144 static interp_func interp_tab[MAX_INTERP];
145 static copy_pv_func copy_tab[MAX_INTERP];
146
147
148 #define IND (0)
149 #define NAME interp_none
150 #include "t_vb_interptmp.h"
151
152 #define IND (INTERP_FOG)
153 #define NAME interp_FOG
154 #include "t_vb_interptmp.h"
155
156 #define IND (INTERP_TEX)
157 #define NAME interp_TEX
158 #include "t_vb_interptmp.h"
159
160 #define IND (INTERP_FOG|INTERP_TEX)
161 #define NAME interp_FOG_TEX
162 #include "t_vb_interptmp.h"
163
164 #define IND (INTERP_EDGE)
165 #define NAME interp_EDGE
166 #include "t_vb_interptmp.h"
167
168 #define IND (INTERP_FOG|INTERP_EDGE)
169 #define NAME interp_FOG_EDGE
170 #include "t_vb_interptmp.h"
171
172 #define IND (INTERP_TEX|INTERP_EDGE)
173 #define NAME interp_TEX_EDGE
174 #include "t_vb_interptmp.h"
175
176 #define IND (INTERP_FOG|INTERP_TEX|INTERP_EDGE)
177 #define NAME interp_FOG_TEX_EDGE
178 #include "t_vb_interptmp.h"
179
180 #define IND (INTERP_RGBA)
181 #define NAME interp_RGBA
182 #include "t_vb_interptmp.h"
183
184 #define IND (INTERP_RGBA|INTERP_SPEC)
185 #define NAME interp_RGBA_SPEC
186 #include "t_vb_interptmp.h"
187
188 #define IND (INTERP_RGBA|INTERP_FOG)
189 #define NAME interp_RGBA_FOG
190 #include "t_vb_interptmp.h"
191
192 #define IND (INTERP_RGBA|INTERP_SPEC|INTERP_FOG)
193 #define NAME interp_RGBA_SPEC_FOG
194 #include "t_vb_interptmp.h"
195
196 #define IND (INTERP_RGBA|INTERP_TEX)
197 #define NAME interp_RGBA_TEX
198 #include "t_vb_interptmp.h"
199
200 #define IND (INTERP_RGBA|INTERP_SPEC|INTERP_TEX)
201 #define NAME interp_RGBA_SPEC_TEX
202 #include "t_vb_interptmp.h"
203
204 #define IND (INTERP_RGBA|INTERP_FOG|INTERP_TEX)
205 #define NAME interp_RGBA_FOG_TEX
206 #include "t_vb_interptmp.h"
207
208 #define IND (INTERP_RGBA|INTERP_SPEC|INTERP_FOG|INTERP_TEX)
209 #define NAME interp_RGBA_SPEC_FOG_TEX
210 #include "t_vb_interptmp.h"
211
212 #define IND (INTERP_INDEX)
213 #define NAME interp_INDEX
214 #include "t_vb_interptmp.h"
215
216 #define IND (INTERP_FOG|INTERP_INDEX)
217 #define NAME interp_FOG_INDEX
218 #include "t_vb_interptmp.h"
219
220 #define IND (INTERP_TEX|INTERP_INDEX)
221 #define NAME interp_TEX_INDEX
222 #include "t_vb_interptmp.h"
223
224 #define IND (INTERP_FOG|INTERP_TEX|INTERP_INDEX)
225 #define NAME interp_FOG_TEX_INDEX
226 #include "t_vb_interptmp.h"
227
228 #define IND (INTERP_RGBA|INTERP_EDGE)
229 #define NAME interp_RGBA_EDGE
230 #include "t_vb_interptmp.h"
231
232 #define IND (INTERP_RGBA|INTERP_SPEC|INTERP_EDGE)
233 #define NAME interp_RGBA_SPEC_EDGE
234 #include "t_vb_interptmp.h"
235
236 #define IND (INTERP_RGBA|INTERP_FOG|INTERP_EDGE)
237 #define NAME interp_RGBA_FOG_EDGE
238 #include "t_vb_interptmp.h"
239
240 #define IND (INTERP_RGBA|INTERP_SPEC|INTERP_FOG|INTERP_EDGE)
241 #define NAME interp_RGBA_SPEC_FOG_EDGE
242 #include "t_vb_interptmp.h"
243
244 #define IND (INTERP_RGBA|INTERP_TEX|INTERP_EDGE)
245 #define NAME interp_RGBA_TEX_EDGE
246 #include "t_vb_interptmp.h"
247
248 #define IND (INTERP_RGBA|INTERP_SPEC|INTERP_TEX|INTERP_EDGE)
249 #define NAME interp_RGBA_SPEC_TEX_EDGE
250 #include "t_vb_interptmp.h"
251
252 #define IND (INTERP_RGBA|INTERP_FOG|INTERP_TEX|INTERP_EDGE)
253 #define NAME interp_RGBA_FOG_TEX_EDGE
254 #include "t_vb_interptmp.h"
255
256 #define IND (INTERP_RGBA|INTERP_SPEC|INTERP_FOG|INTERP_TEX|INTERP_EDGE)
257 #define NAME interp_RGBA_SPEC_FOG_TEX_EDGE
258 #include "t_vb_interptmp.h"
259
260 #define IND (INTERP_INDEX|INTERP_EDGE)
261 #define NAME interp_INDEX_EDGE
262 #include "t_vb_interptmp.h"
263
264 #define IND (INTERP_FOG|INTERP_INDEX|INTERP_EDGE)
265 #define NAME interp_FOG_INDEX_EDGE
266 #include "t_vb_interptmp.h"
267
268 #define IND (INTERP_TEX|INTERP_INDEX|INTERP_EDGE)
269 #define NAME interp_TEX_INDEX_EDGE
270 #include "t_vb_interptmp.h"
271
272 #define IND (INTERP_FOG|INTERP_TEX|INTERP_INDEX|INTERP_EDGE)
273 #define NAME interp_FOG_TEX_INDEX_EDGE
274 #include "t_vb_interptmp.h"
275
276
277 #define IND (INTERP_RGBA)
278 #define NAME copy_RGBA
279 #include "t_vb_flattmp.h"
280
281 #define IND (INTERP_RGBA|INTERP_SPEC)
282 #define NAME copy_RGBA_SPEC
283 #include "t_vb_flattmp.h"
284
285 #define IND (INTERP_INDEX)
286 #define NAME copy_INDEX
287 #include "t_vb_flattmp.h"
288
289
290
291
292 static void interp_invalid( GLcontext *ctx,
293 GLfloat t,
294 GLuint dst, GLuint in, GLuint out,
295 GLboolean boundary )
296 {
297 (void)(ctx && t && in && out && boundary);
298 fprintf(stderr, "Invalid interpolation function in t_vbrender.c\n");
299 }
300
301 static void copy_invalid( GLcontext *ctx, GLuint dst, GLuint src )
302 {
303 (void)(ctx && dst && src);
304 fprintf(stderr, "Invalid copy function in t_vbrender.c\n");
305 }
306
307
308 static void interp_init( void )
309 {
310 GLuint i;
311
312 /* Use the maximal function as the default. I don't believe any of
313 * the non-implemented combinations are reachable, but this gives
314 * some safety from crashes.
315 */
316 for (i = 0 ; i < Elements(interp_tab) ; i++) {
317 interp_tab[i] = interp_invalid;
318 copy_tab[i] = copy_invalid;
319 }
320
321 interp_tab[0] = interp_none;
322 interp_tab[INTERP_FOG] = interp_FOG;
323 interp_tab[INTERP_TEX] = interp_TEX;
324 interp_tab[INTERP_FOG|INTERP_TEX] = interp_FOG_TEX;
325 interp_tab[INTERP_EDGE] = interp_EDGE;
326 interp_tab[INTERP_FOG|INTERP_EDGE] = interp_FOG_EDGE;
327 interp_tab[INTERP_TEX|INTERP_EDGE] = interp_TEX_EDGE;
328 interp_tab[INTERP_FOG|INTERP_TEX|INTERP_EDGE] = interp_FOG_TEX_EDGE;
329
330 interp_tab[INTERP_RGBA] = interp_RGBA;
331 interp_tab[INTERP_RGBA|INTERP_SPEC] = interp_RGBA_SPEC;
332 interp_tab[INTERP_RGBA|INTERP_FOG] = interp_RGBA_FOG;
333 interp_tab[INTERP_RGBA|INTERP_SPEC|INTERP_FOG] = interp_RGBA_SPEC_FOG;
334 interp_tab[INTERP_RGBA|INTERP_TEX] = interp_RGBA_TEX;
335 interp_tab[INTERP_RGBA|INTERP_SPEC|INTERP_TEX] = interp_RGBA_SPEC_TEX;
336 interp_tab[INTERP_RGBA|INTERP_FOG|INTERP_TEX] = interp_RGBA_FOG_TEX;
337 interp_tab[INTERP_RGBA|INTERP_SPEC|INTERP_FOG|INTERP_TEX] =
338 interp_RGBA_SPEC_FOG_TEX;
339 interp_tab[INTERP_INDEX] = interp_INDEX;
340 interp_tab[INTERP_FOG|INTERP_INDEX] = interp_FOG_INDEX;
341 interp_tab[INTERP_TEX|INTERP_INDEX] = interp_TEX_INDEX;
342 interp_tab[INTERP_FOG|INTERP_TEX|INTERP_INDEX] = interp_FOG_TEX_INDEX;
343 interp_tab[INTERP_RGBA|INTERP_EDGE] = interp_RGBA_EDGE;
344 interp_tab[INTERP_RGBA|INTERP_SPEC|INTERP_EDGE] = interp_RGBA_SPEC_EDGE;
345 interp_tab[INTERP_RGBA|INTERP_FOG|INTERP_EDGE] = interp_RGBA_FOG_EDGE;
346 interp_tab[INTERP_RGBA|INTERP_SPEC|INTERP_FOG|INTERP_EDGE] =
347 interp_RGBA_SPEC_FOG_EDGE;
348 interp_tab[INTERP_RGBA|INTERP_TEX|INTERP_EDGE] = interp_RGBA_TEX_EDGE;
349 interp_tab[INTERP_RGBA|INTERP_SPEC|INTERP_TEX|INTERP_EDGE] =
350 interp_RGBA_SPEC_TEX_EDGE;
351 interp_tab[INTERP_RGBA|INTERP_FOG|INTERP_TEX|INTERP_EDGE] =
352 interp_RGBA_FOG_TEX_EDGE;
353 interp_tab[INTERP_RGBA|INTERP_SPEC|INTERP_FOG|INTERP_TEX|INTERP_EDGE] =
354 interp_RGBA_SPEC_FOG_TEX_EDGE;
355 interp_tab[INTERP_INDEX|INTERP_EDGE] = interp_INDEX_EDGE;
356 interp_tab[INTERP_FOG|INTERP_INDEX|INTERP_EDGE] = interp_FOG_INDEX_EDGE;
357 interp_tab[INTERP_TEX|INTERP_INDEX|INTERP_EDGE] = interp_TEX_INDEX_EDGE;
358 interp_tab[INTERP_FOG|INTERP_TEX|INTERP_INDEX|INTERP_EDGE] =
359 interp_FOG_TEX_INDEX_EDGE;
360
361
362 copy_tab[INTERP_RGBA] = copy_RGBA;
363 copy_tab[INTERP_RGBA|INTERP_SPEC] = copy_RGBA_SPEC;
364 copy_tab[INTERP_INDEX] = copy_INDEX;
365
366 }
367
368
369 /**********************************************************************/
370 /* Clip single primitives */
371 /**********************************************************************/
372
373
374 #if defined(USE_IEEE)
375 #define NEGATIVE(x) ((*(GLuint *)&x) & (1<<31))
376 #define DIFFERENT_SIGNS(x,y) (((*(GLuint *)&x)^(*(GLuint *)&y)) & (1<<31))
377 #else
378 #define NEGATIVE(x) (x < 0)
379 #define DIFFERENT_SIGNS(x,y) (x * y <= 0 && x - y != 0)
380 /* Could just use (x*y<0) except for the flatshading requirements.
381 * Maybe there's a better way?
382 */
383 #endif
384
385 #define W(i) coord[i][3]
386 #define Z(i) coord[i][2]
387 #define Y(i) coord[i][1]
388 #define X(i) coord[i][0]
389 #define SIZE 4
390 #define TAG(x) x##_4
391 #include "t_vb_cliptmp.h"
392
393 #define W(i) 1.0
394 #define Z(i) coord[i][2]
395 #define Y(i) coord[i][1]
396 #define X(i) coord[i][0]
397 #define SIZE 3
398 #define TAG(x) x##_3
399 #include "t_vb_cliptmp.h"
400
401 #define W(i) 1.0
402 #define Z(i) 0.0
403 #define Y(i) coord[i][1]
404 #define X(i) coord[i][0]
405 #define SIZE 2
406 #define TAG(x) x##_2
407 #include "t_vb_cliptmp.h"
408
409 static clip_poly_func clip_poly_tab[5] = {
410 0,
411 0,
412 clip_polygon_2,
413 clip_polygon_3,
414 clip_polygon_4
415 };
416
417 static clip_line_func clip_line_tab[5] = {
418 0,
419 0,
420 clip_line_2,
421 clip_line_3,
422 clip_line_4
423 };
424
425
426 /**********************************************************************/
427 /* Clip and render whole begin/end objects */
428 /**********************************************************************/
429
430 #define NEED_EDGEFLAG_SETUP (ctx->_TriangleCaps & DD_TRI_UNFILLED)
431 #define EDGEFLAG_GET(idx) VB->EdgeFlag[idx]
432 #define EDGEFLAG_SET(idx, val) VB->EdgeFlag[idx] = val
433
434
435 /* Vertices, with the possibility of clipping.
436 */
437 #define RENDER_POINTS( start, count ) \
438 ctx->Driver.PointsFunc( ctx, start, count )
439
440 #define RENDER_LINE( v1, v2 ) \
441 do { \
442 GLubyte c1 = mask[v1], c2 = mask[v2]; \
443 GLubyte ormask = c1|c2; \
444 if (!ormask) \
445 LineFunc( ctx, v1, v2 ); \
446 else if (!(c1 & c2 & 0x3f)) \
447 clip_line_tab[sz]( ctx, v1, v2, ormask ); \
448 } while (0)
449
450 #define RENDER_TRI( v1, v2, v3 ) \
451 do { \
452 GLubyte c1 = mask[v1], c2 = mask[v2], c3 = mask[v3]; \
453 GLubyte ormask = c1|c2|c3; \
454 if (!ormask) \
455 TriangleFunc( ctx, v1, v2, v3 ); \
456 else if (!(c1 & c2 & c3 & 0x3f)) { \
457 GLuint vlist[MAX_CLIPPED_VERTICES]; \
458 ASSIGN_3V(vlist, v3, v1, v2 ); \
459 clip_poly_tab[sz]( ctx, 3, vlist, ormask ); \
460 } \
461 } while (0)
462
463 #define RENDER_QUAD( v1, v2, v3, v4 ) \
464 do { \
465 GLubyte c1 = mask[v1], c2 = mask[v2]; \
466 GLubyte c3 = mask[v3], c4 = mask[v4]; \
467 GLubyte ormask = c1|c2|c3|c4; \
468 if (!ormask) \
469 QuadFunc( ctx, v1, v2, v3, v4 ); \
470 else if (!(c1 & c2 & c3 & c4 & 0x3f)) { \
471 GLuint vlist[MAX_CLIPPED_VERTICES]; \
472 ASSIGN_4V(vlist, v4, v1, v2, v3 ); \
473 clip_poly_tab[sz]( ctx, 4, vlist, ormask ); \
474 } \
475 } while (0)
476
477
478 #define LOCAL_VARS \
479 struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; \
480 const GLuint * const elt = VB->Elts; \
481 const GLubyte *mask = VB->ClipMask; \
482 const GLuint sz = VB->ClipPtr->size; \
483 const line_func LineFunc = ctx->Driver.LineFunc; \
484 const triangle_func TriangleFunc = ctx->Driver.TriangleFunc; \
485 const quad_func QuadFunc = ctx->Driver.QuadFunc; \
486 (void) (LineFunc && TriangleFunc && QuadFunc); \
487 (void) elt; (void) mask; (void) sz;
488
489 #define TAG(x) clip_##x##_verts
490 #define INIT(x) ctx->Driver.RenderPrimitive( ctx, x )
491 #define RESET_STIPPLE ctx->Driver.ResetLineStipple( ctx )
492 #define RESET_OCCLUSION ctx->OcclusionResult = GL_TRUE;
493 #define PRESERVE_VB_DEFS
494 #include "t_vb_rendertmp.h"
495
496
497
498 /* Elts, with the possibility of clipping.
499 */
500 #undef ELT
501 #undef TAG
502 #define ELT(x) elt[x]
503 #define TAG(x) clip_##x##_elts
504 #include "t_vb_rendertmp.h"
505
506
507 /**********************************************************************/
508 /* Render whole begin/end objects */
509 /**********************************************************************/
510
511 #define NEED_EDGEFLAG_SETUP (ctx->_TriangleCaps & DD_TRI_UNFILLED)
512 #define EDGEFLAG_GET(idx) VB->EdgeFlag[idx]
513 #define EDGEFLAG_SET(idx, val) VB->EdgeFlag[idx] = val
514
515
516 /* Vertices, no clipping.
517 */
518 #define RENDER_POINTS( start, count ) \
519 ctx->Driver.PointsFunc( ctx, start, count )
520
521 #define RENDER_LINE( v1, v2 ) \
522 LineFunc( ctx, v1, v2 )
523
524 #define RENDER_TRI( v1, v2, v3 ) \
525 TriangleFunc( ctx, v1, v2, v3 )
526
527 #define RENDER_QUAD( v1, v2, v3, v4 ) \
528 QuadFunc( ctx, v1, v2, v3, v4 )
529
530 #define TAG(x) _tnl_##x##_verts
531
532 #define LOCAL_VARS \
533 struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; \
534 const GLuint * const elt = VB->Elts; \
535 const line_func LineFunc = ctx->Driver.LineFunc; \
536 const triangle_func TriangleFunc = ctx->Driver.TriangleFunc; \
537 const quad_func QuadFunc = ctx->Driver.QuadFunc; \
538 (void) (LineFunc && TriangleFunc && QuadFunc); \
539 (void) elt;
540
541 #define RESET_STIPPLE ctx->Driver.ResetLineStipple( ctx )
542 #define RESET_OCCLUSION ctx->OcclusionResult = GL_TRUE;
543 #define INIT(x) ctx->Driver.RenderPrimitive( ctx, x )
544 #define RENDER_TAB_QUALIFIER
545 #define PRESERVE_VB_DEFS
546 #include "t_vb_rendertmp.h"
547
548
549 /* Elts, no clipping.
550 */
551 #undef ELT
552 #define TAG(x) _tnl_##x##_elts
553 #define ELT(x) elt[x]
554 #include "t_vb_rendertmp.h"
555
556
557
558
559 /**********************************************************************/
560 /* Clip and render whole vertex buffers */
561 /**********************************************************************/
562
563
564 static GLboolean run_render( GLcontext *ctx,
565 struct gl_pipeline_stage *stage )
566 {
567 TNLcontext *tnl = TNL_CONTEXT(ctx);
568 struct vertex_buffer *VB = &tnl->vb;
569 GLuint new_inputs = stage->changed_inputs;
570 render_func *tab;
571 GLint pass = 0;
572
573 VB->interpfunc = RENDER_STAGE_DATA(stage)->interp;
574 VB->copypvfunc = RENDER_STAGE_DATA(stage)->copypv;
575
576 /* Allow the drivers to lock before projected verts are built so
577 * that window coordinates are guarenteed not to change before
578 * rendering.
579 */
580 ctx->Driver.RenderStart( ctx );
581
582 if (VB->ClipOrMask) {
583 tab = VB->Elts ? clip_render_tab_elts : clip_render_tab_verts;
584
585 if (new_inputs & VB->importable_data)
586 VB->import_data( ctx,
587 new_inputs & VB->importable_data,
588 VEC_NOT_WRITEABLE|VEC_BAD_STRIDE);
589 }
590 else {
591 tab = VB->Elts ? ctx->Driver.RenderTabElts : ctx->Driver.RenderTabVerts;
592 }
593
594 ctx->Driver.BuildProjectedVertices( ctx, 0, VB->Count, new_inputs );
595
596 do
597 {
598 GLuint i, length, flags = 0;
599 for (i = 0 ; !(flags & PRIM_LAST) ; i += length)
600 {
601 flags = VB->Primitive[i];
602 length= VB->PrimitiveLength[i];
603 ASSERT(length || (flags & PRIM_LAST));
604 ASSERT((flags & PRIM_MODE_MASK) <= GL_POLYGON+1);
605 /* fprintf(stderr, "Render %s %d..%d\n", */
606 /* _mesa_prim_name[flags&PRIM_MODE_MASK], i, i+length); */
607 if (length)
608 tab[flags & PRIM_MODE_MASK]( ctx, i, i + length, flags );
609 }
610 } while (ctx->Driver.MultipassFunc &&
611 ctx->Driver.MultipassFunc( ctx, ++pass ));
612
613
614 ctx->Driver.RenderFinish( ctx );
615 return GL_FALSE; /* finished the pipe */
616 }
617
618
619 /**********************************************************************/
620 /* Render pipeline stage */
621 /**********************************************************************/
622
623
624
625 /* Quite a bit of work involved in finding out the inputs for the
626 * render stage. This function also identifies which vertex
627 * interpolation function to use, as these are essentially the same
628 * question.
629 */
630 static void check_render( GLcontext *ctx, struct gl_pipeline_stage *stage )
631 {
632 struct render_stage_data *store = RENDER_STAGE_DATA(stage);
633 GLuint interp = 0;
634 GLuint copy = 0;
635 GLuint inputs = VERT_CLIP;
636 GLuint i;
637
638 if (ctx->Visual.rgbMode) {
639 interp |= INTERP_RGBA;
640 inputs |= VERT_RGBA;
641
642 if (ctx->_TriangleCaps & DD_SEPERATE_SPECULAR) {
643 interp |= INTERP_SPEC;
644 inputs |= VERT_SPEC_RGB;
645 }
646
647 if (ctx->Texture._ReallyEnabled) {
648 interp |= INTERP_TEX;
649
650 for (i = 0 ; i < ctx->Const.MaxTextureUnits ; i++) {
651 if (ctx->Texture.Unit[i]._ReallyEnabled)
652 inputs |= VERT_TEX(i);
653 }
654 }
655 }
656 else
657 {
658 interp |= INTERP_INDEX;
659 inputs |= VERT_INDEX;
660 }
661
662 if (ctx->Point._Attenuated)
663 inputs |= VERT_POINT_SIZE;
664
665 /* How do drivers turn this off?
666 */
667 if (ctx->Fog.Enabled) {
668 interp |= INTERP_FOG;
669 inputs |= VERT_FOG_COORD;
670 }
671
672 if (ctx->_TriangleCaps & DD_TRI_UNFILLED) {
673 inputs |= VERT_EDGE;
674 interp |= INTERP_EDGE;
675 }
676
677 if (ctx->RenderMode==GL_FEEDBACK) {
678 interp |= INTERP_TEX;
679 inputs |= VERT_TEX_ANY;
680 }
681
682 if (ctx->_TriangleCaps & DD_FLATSHADE) {
683 copy = interp & (INTERP_RGBA|INTERP_SPEC|INTERP_INDEX);
684 interp &= ~copy;
685 }
686
687 store->copypv = copy_tab[copy];
688 store->interp = interp_tab[interp];
689 stage->inputs = inputs;
690 }
691
692
693 /* Called the first time stage->check() is invoked.
694 */
695 static void alloc_render_data( GLcontext *ctx,
696 struct gl_pipeline_stage *stage )
697 {
698 struct render_stage_data *store;
699 static GLboolean first_time = 1;
700
701 if (first_time) {
702 interp_init();
703 first_time = 0;
704 }
705
706 stage->private = MALLOC(sizeof(*store));
707 if (!stage->private)
708 return;
709
710 /* Now do the check.
711 */
712 stage->check = check_render;
713 stage->check( ctx, stage );
714 }
715
716
717
718 static void dtr( struct gl_pipeline_stage *stage )
719 {
720 struct render_stage_data *store = RENDER_STAGE_DATA(stage);
721 if (store) {
722 FREE( store );
723 stage->private = 0;
724 }
725 }
726
727
728 const struct gl_pipeline_stage _tnl_render_stage =
729 {
730 "render",
731 (_NEW_BUFFERS |
732 _DD_NEW_SEPERATE_SPECULAR |
733 _DD_NEW_FLATSHADE |
734 _NEW_TEXTURE|
735 _NEW_LIGHT|
736 _NEW_POINT|
737 _NEW_FOG|
738 _DD_NEW_TRI_UNFILLED |
739 _NEW_RENDERMODE), /* re-check (new inputs, interp function) */
740 0, /* re-run (always runs) */
741 GL_TRUE, /* active */
742 0, 0, /* inputs (set in check_render), outputs */
743 0, 0, /* changed_inputs, private */
744 dtr, /* destructor */
745 alloc_render_data, /* check - initially set to alloc data */
746 run_render /* run */
747 };