1 /* $Id: t_vb_render.c,v 1.7 2001/01/08 04:09:42 keithw Exp $ */
4 * Mesa 3-D graphics library
7 * Copyright (C) 1999-2000 Brian Paul All Rights Reserved.
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:
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
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.
27 * Keith Whitwell <keithw@valinux.com>
32 * Render whole vertex buffers, including projection of vertices from
33 * clip space and clipping of primitives.
35 * This file makes calls to project vertices and to the point, line
36 * and triangle rasterizers via the function pointers:
38 * context->Driver.BuildProjectedVertices()
40 * context->Driver.PointsFunc()
41 * context->Driver.LineFunc()
42 * context->Driver.TriangleFunc()
43 * context->Driver.QuadFunc()
45 * context->Driver.RenderTabVerts[]
46 * context->Driver.RenderTabElts[]
48 * None of these may be null.
60 #include "math/m_matrix.h"
61 #include "math/m_xform.h"
63 #include "t_pipeline.h"
67 typedef void (*clip_line_func
)( GLcontext
*ctx
,
71 typedef void (*clip_poly_func
)( GLcontext
*ctx
,
72 GLuint n
, GLuint vlist
[],
78 struct render_stage_data
{
80 /* Clipping functions for current state.
82 interp_func interp
; /* Clip interpolation function */
83 copy_pv_func copypv
; /* Flatshade fixup function */
84 GLuint _ClipInputs
; /* Inputs referenced by interpfunc */
87 #define RENDER_STAGE_DATA(stage) ((struct render_stage_data *)stage->private)
90 /**********************************************************************/
91 /* Interpolate between pairs of vertices */
92 /**********************************************************************/
95 #define LINTERP_SZ( t, vec, to, a, b, 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] ); \
108 #define LINTERP_RGBA(nr, t, out, a, b) { \
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); \
120 #define LINTERP_RGBA(nr, t, out, a, b) { \
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]; \
127 for (n = 0 ; n < nr ; n++) \
128 Ob[n] = (GLubyte) (Ib[n] + ((ti * (Jb[n] - Ib[n]))/256)); \
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
144 static interp_func interp_tab
[MAX_INTERP
];
145 static copy_pv_func copy_tab
[MAX_INTERP
];
149 #define NAME interp_none
150 #include "t_vb_interptmp.h"
152 #define IND (INTERP_FOG)
153 #define NAME interp_FOG
154 #include "t_vb_interptmp.h"
156 #define IND (INTERP_TEX)
157 #define NAME interp_TEX
158 #include "t_vb_interptmp.h"
160 #define IND (INTERP_FOG|INTERP_TEX)
161 #define NAME interp_FOG_TEX
162 #include "t_vb_interptmp.h"
164 #define IND (INTERP_EDGE)
165 #define NAME interp_EDGE
166 #include "t_vb_interptmp.h"
168 #define IND (INTERP_FOG|INTERP_EDGE)
169 #define NAME interp_FOG_EDGE
170 #include "t_vb_interptmp.h"
172 #define IND (INTERP_TEX|INTERP_EDGE)
173 #define NAME interp_TEX_EDGE
174 #include "t_vb_interptmp.h"
176 #define IND (INTERP_FOG|INTERP_TEX|INTERP_EDGE)
177 #define NAME interp_FOG_TEX_EDGE
178 #include "t_vb_interptmp.h"
180 #define IND (INTERP_RGBA)
181 #define NAME interp_RGBA
182 #include "t_vb_interptmp.h"
184 #define IND (INTERP_RGBA|INTERP_SPEC)
185 #define NAME interp_RGBA_SPEC
186 #include "t_vb_interptmp.h"
188 #define IND (INTERP_RGBA|INTERP_FOG)
189 #define NAME interp_RGBA_FOG
190 #include "t_vb_interptmp.h"
192 #define IND (INTERP_RGBA|INTERP_SPEC|INTERP_FOG)
193 #define NAME interp_RGBA_SPEC_FOG
194 #include "t_vb_interptmp.h"
196 #define IND (INTERP_RGBA|INTERP_TEX)
197 #define NAME interp_RGBA_TEX
198 #include "t_vb_interptmp.h"
200 #define IND (INTERP_RGBA|INTERP_SPEC|INTERP_TEX)
201 #define NAME interp_RGBA_SPEC_TEX
202 #include "t_vb_interptmp.h"
204 #define IND (INTERP_RGBA|INTERP_FOG|INTERP_TEX)
205 #define NAME interp_RGBA_FOG_TEX
206 #include "t_vb_interptmp.h"
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"
212 #define IND (INTERP_INDEX)
213 #define NAME interp_INDEX
214 #include "t_vb_interptmp.h"
216 #define IND (INTERP_FOG|INTERP_INDEX)
217 #define NAME interp_FOG_INDEX
218 #include "t_vb_interptmp.h"
220 #define IND (INTERP_TEX|INTERP_INDEX)
221 #define NAME interp_TEX_INDEX
222 #include "t_vb_interptmp.h"
224 #define IND (INTERP_FOG|INTERP_TEX|INTERP_INDEX)
225 #define NAME interp_FOG_TEX_INDEX
226 #include "t_vb_interptmp.h"
228 #define IND (INTERP_RGBA|INTERP_EDGE)
229 #define NAME interp_RGBA_EDGE
230 #include "t_vb_interptmp.h"
232 #define IND (INTERP_RGBA|INTERP_SPEC|INTERP_EDGE)
233 #define NAME interp_RGBA_SPEC_EDGE
234 #include "t_vb_interptmp.h"
236 #define IND (INTERP_RGBA|INTERP_FOG|INTERP_EDGE)
237 #define NAME interp_RGBA_FOG_EDGE
238 #include "t_vb_interptmp.h"
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"
244 #define IND (INTERP_RGBA|INTERP_TEX|INTERP_EDGE)
245 #define NAME interp_RGBA_TEX_EDGE
246 #include "t_vb_interptmp.h"
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"
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"
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"
260 #define IND (INTERP_INDEX|INTERP_EDGE)
261 #define NAME interp_INDEX_EDGE
262 #include "t_vb_interptmp.h"
264 #define IND (INTERP_FOG|INTERP_INDEX|INTERP_EDGE)
265 #define NAME interp_FOG_INDEX_EDGE
266 #include "t_vb_interptmp.h"
268 #define IND (INTERP_TEX|INTERP_INDEX|INTERP_EDGE)
269 #define NAME interp_TEX_INDEX_EDGE
270 #include "t_vb_interptmp.h"
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"
277 #define IND (INTERP_RGBA)
278 #define NAME copy_RGBA
279 #include "t_vb_flattmp.h"
281 #define IND (INTERP_RGBA|INTERP_SPEC)
282 #define NAME copy_RGBA_SPEC
283 #include "t_vb_flattmp.h"
285 #define IND (INTERP_INDEX)
286 #define NAME copy_INDEX
287 #include "t_vb_flattmp.h"
292 static void interp_invalid( GLcontext
*ctx
,
294 GLuint dst
, GLuint in
, GLuint out
,
297 (void)(ctx
&& t
&& in
&& out
&& boundary
);
298 fprintf(stderr
, "Invalid interpolation function in t_vbrender.c\n");
301 static void copy_invalid( GLcontext
*ctx
, GLuint dst
, GLuint src
)
303 (void)(ctx
&& dst
&& src
);
304 fprintf(stderr
, "Invalid copy function in t_vbrender.c\n");
308 static void interp_init( void )
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.
316 for (i
= 0 ; i
< Elements(interp_tab
) ; i
++) {
317 interp_tab
[i
] = interp_invalid
;
318 copy_tab
[i
] = copy_invalid
;
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
;
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
;
362 copy_tab
[INTERP_RGBA
] = copy_RGBA
;
363 copy_tab
[INTERP_RGBA
|INTERP_SPEC
] = copy_RGBA_SPEC
;
364 copy_tab
[INTERP_INDEX
] = copy_INDEX
;
369 /**********************************************************************/
370 /* Clip single primitives */
371 /**********************************************************************/
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))
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?
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]
391 #include "t_vb_cliptmp.h"
394 #define Z(i) coord[i][2]
395 #define Y(i) coord[i][1]
396 #define X(i) coord[i][0]
399 #include "t_vb_cliptmp.h"
403 #define Y(i) coord[i][1]
404 #define X(i) coord[i][0]
407 #include "t_vb_cliptmp.h"
409 static clip_poly_func clip_poly_tab
[5] = {
417 static clip_line_func clip_line_tab
[5] = {
426 /**********************************************************************/
427 /* Clip and render whole begin/end objects */
428 /**********************************************************************/
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
435 /* Vertices, with the possibility of clipping.
437 #define RENDER_POINTS( start, count ) \
438 ctx->Driver.PointsFunc( ctx, start, count )
440 #define RENDER_LINE( v1, v2 ) \
442 GLubyte c1 = mask[v1], c2 = mask[v2]; \
443 GLubyte ormask = c1|c2; \
445 LineFunc( ctx, v1, v2 ); \
446 else if (!(c1 & c2 & 0x3f)) \
447 clip_line_tab[sz]( ctx, v1, v2, ormask ); \
450 #define RENDER_TRI( v1, v2, v3 ) \
452 GLubyte c1 = mask[v1], c2 = mask[v2], c3 = mask[v3]; \
453 GLubyte ormask = c1|c2|c3; \
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 ); \
463 #define RENDER_QUAD( v1, v2, v3, v4 ) \
465 GLubyte c1 = mask[v1], c2 = mask[v2]; \
466 GLubyte c3 = mask[v3], c4 = mask[v4]; \
467 GLubyte ormask = c1|c2|c3|c4; \
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 ); \
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;
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"
498 /* Elts, with the possibility of clipping.
502 #define ELT(x) elt[x]
503 #define TAG(x) clip_##x##_elts
504 #include "t_vb_rendertmp.h"
507 /**********************************************************************/
508 /* Render whole begin/end objects */
509 /**********************************************************************/
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
516 /* Vertices, no clipping.
518 #define RENDER_POINTS( start, count ) \
519 ctx->Driver.PointsFunc( ctx, start, count )
521 #define RENDER_LINE( v1, v2 ) \
522 LineFunc( ctx, v1, v2 )
524 #define RENDER_TRI( v1, v2, v3 ) \
525 TriangleFunc( ctx, v1, v2, v3 )
527 #define RENDER_QUAD( v1, v2, v3, v4 ) \
528 QuadFunc( ctx, v1, v2, v3, v4 )
530 #define TAG(x) _tnl_##x##_verts
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); \
541 #define RESET_STIPPLE ctx->Driver.ResetLineStipple( ctx )
542 #define RESET_OCCLUSION ctx->OcclusionResult = GL_TRUE;
543 #define RENDER_TAB_QUALIFIER
544 #define PRESERVE_VB_DEFS
545 #include "t_vb_rendertmp.h"
548 /* Elts, no clipping.
551 #define TAG(x) _tnl_##x##_elts
552 #define ELT(x) elt[x]
553 #include "t_vb_rendertmp.h"
558 /**********************************************************************/
559 /* Clip and render whole vertex buffers */
560 /**********************************************************************/
563 static GLboolean
run_render( GLcontext
*ctx
,
564 struct gl_pipeline_stage
*stage
)
566 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
567 struct vertex_buffer
*VB
= &tnl
->vb
;
568 GLuint new_inputs
= stage
->changed_inputs
;
572 VB
->interpfunc
= RENDER_STAGE_DATA(stage
)->interp
;
573 VB
->copypvfunc
= RENDER_STAGE_DATA(stage
)->copypv
;
575 /* Allow the drivers to lock before projected verts are built so
576 * that window coordinates are guarenteed not to change before
579 if (ctx
->Driver
.RenderStart
)
580 ctx
->Driver
.RenderStart( ctx
);
582 if (VB
->ClipOrMask
) {
583 tab
= VB
->Elts
? clip_render_tab_elts
: clip_render_tab_verts
;
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
);
591 tab
= VB
->Elts
? ctx
->Driver
.RenderTabElts
: ctx
->Driver
.RenderTabVerts
;
594 ctx
->Driver
.BuildProjectedVertices( ctx
, 0, VB
->Count
, new_inputs
);
598 GLuint i
, length
, flags
= 0;
599 for (i
= 0 ; !(flags
& PRIM_LAST
) ; i
+= length
)
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);
606 tab
[flags
& PRIM_MODE_MASK
]( ctx
, i
, i
+ length
, flags
);
608 } while (ctx
->Driver
.MultipassFunc
&&
609 ctx
->Driver
.MultipassFunc( ctx
, ++pass
));
611 if (ctx
->Driver
.RenderFinish
)
612 ctx
->Driver
.RenderFinish( ctx
);
614 return GL_FALSE
; /* finished the pipe */
618 /**********************************************************************/
619 /* Render pipeline stage */
620 /**********************************************************************/
624 /* Quite a bit of work involved in finding out the inputs for the
625 * render stage. This function also identifies which vertex
626 * interpolation function to use, as these are essentially the same
629 static void check_render( GLcontext
*ctx
, struct gl_pipeline_stage
*stage
)
631 struct render_stage_data
*store
= RENDER_STAGE_DATA(stage
);
634 GLuint inputs
= VERT_CLIP
;
637 if (ctx
->Visual
.RGBAflag
)
639 interp
|= INTERP_RGBA
;
642 if (ctx
->_TriangleCaps
& DD_SEPERATE_SPECULAR
) {
643 interp
|= INTERP_SPEC
;
644 inputs
|= VERT_SPEC_RGB
;
647 if (ctx
->Texture
._ReallyEnabled
) {
648 interp
|= INTERP_TEX
;
650 for (i
= 0 ; i
< ctx
->Const
.MaxTextureUnits
; i
++) {
651 if (ctx
->Texture
.Unit
[i
]._ReallyEnabled
)
652 inputs
|= VERT_TEX(i
);
658 interp
|= INTERP_INDEX
;
659 inputs
|= VERT_INDEX
;
662 if (ctx
->Point
._Attenuated
)
663 inputs
|= VERT_POINT_SIZE
;
665 /* How do drivers turn this off?
667 if (ctx
->Fog
.Enabled
) {
668 interp
|= INTERP_FOG
;
669 inputs
|= VERT_FOG_COORD
;
672 if (ctx
->_TriangleCaps
& DD_TRI_UNFILLED
) {
674 interp
|= INTERP_EDGE
;
677 if (ctx
->RenderMode
==GL_FEEDBACK
) {
678 interp
|= INTERP_TEX
;
679 inputs
|= VERT_TEX_ANY
;
682 if (ctx
->_TriangleCaps
& DD_FLATSHADE
) {
683 copy
= interp
& (INTERP_RGBA
|INTERP_SPEC
|INTERP_INDEX
);
687 store
->copypv
= copy_tab
[copy
];
688 store
->interp
= interp_tab
[interp
];
689 stage
->inputs
= inputs
;
693 /* Called the first time stage->check() is invoked.
695 static void alloc_render_data( GLcontext
*ctx
,
696 struct gl_pipeline_stage
*stage
)
698 struct render_stage_data
*store
;
699 static GLboolean first_time
= 1;
706 stage
->private = MALLOC(sizeof(*store
));
712 stage
->check
= check_render
;
713 stage
->check( ctx
, stage
);
718 static void dtr( struct gl_pipeline_stage
*stage
)
720 struct render_stage_data
*store
= RENDER_STAGE_DATA(stage
);
728 const struct gl_pipeline_stage _tnl_render_stage
=
732 _DD_NEW_SEPERATE_SPECULAR
|
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 */