1 /* $Id: t_imm_dlist.c,v 1.47 2003/03/28 01:39:05 brianp Exp $ */
4 * Mesa 3-D graphics library
7 * Copyright (C) 1999-2003 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 <keith@tungstengraphics.com>
39 #include "t_context.h"
40 #include "t_imm_api.h"
41 #include "t_imm_elt.h"
42 #include "t_imm_alloc.h"
43 #include "t_imm_dlist.h"
44 #include "t_imm_debug.h"
45 #include "t_imm_exec.h"
46 #include "t_imm_fixup.h"
47 #include "t_pipeline.h"
54 GLuint SavedBeginState
;
61 GLuint MaterialOrMask
;
62 GLuint MaterialAndMask
;
65 static void execute_compiled_cassette( GLcontext
*ctx
, void *data
);
66 static void loopback_compiled_cassette( GLcontext
*ctx
, struct immediate
*IM
);
70 build_normal_lengths( struct immediate
*IM
)
74 GLfloat (*data
)[4] = IM
->Attrib
[VERT_ATTRIB_NORMAL
] + IM
->Start
;
75 GLfloat
*dest
= IM
->NormalLengthPtr
;
76 GLuint
*flags
= IM
->Flag
+ IM
->Start
;
77 GLuint count
= IM
->Count
- IM
->Start
;
80 dest
= IM
->NormalLengthPtr
= (GLfloat
*) ALIGN_MALLOC( IMM_SIZE
*sizeof(GLfloat
), 32 );
85 len
= (GLfloat
) LEN_3FV( data
[0] );
86 if (len
> 0.0F
) len
= 1.0F
/ len
;
88 for (i
= 0 ; i
< count
; ) {
90 if (flags
[++i
] & VERT_BIT_NORMAL
) {
91 len
= (GLfloat
) LEN_3FV( data
[i
] );
92 if (len
> 0.0F
) len
= 1.0F
/ len
;
99 fixup_normal_lengths( struct immediate
*IM
)
102 GLfloat len
= 1.0F
; /* just to silence warnings */
103 GLfloat (*data
)[4] = IM
->Attrib
[VERT_ATTRIB_NORMAL
];
104 GLfloat
*dest
= IM
->NormalLengthPtr
;
105 GLuint
*flags
= IM
->Flag
;
107 for (i
= IM
->CopyStart
; i
<= IM
->Start
; i
++) {
108 len
= (GLfloat
) LEN_3FV( data
[i
] );
109 if (len
> 0.0F
) len
= 1.0F
/ len
;
114 while (!(flags
[i
] & (VERT_BIT_NORMAL
|VERT_BIT_END_VB
))) {
123 /* Insert the active immediate struct onto the display list currently
127 _tnl_compile_cassette( GLcontext
*ctx
, struct immediate
*IM
)
129 struct immediate
*im
= TNL_CURRENT_IM(ctx
);
130 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
131 TNLvertexcassette
*node
;
132 GLuint new_beginstate
;
134 if (MESA_VERBOSE
& VERBOSE_DISPLAY_LIST
)
135 _mesa_debug(ctx
, "_tnl_compiled_cassette IM: %d\n", IM
->id
);
138 ASSERT (IM
->FlushElt
== FLUSH_ELT_LAZY
);
139 _tnl_translate_array_elts( ctx
, IM
, IM
->Start
, IM
->Count
);
142 _tnl_compute_orflag( IM
, IM
->Start
);
144 /* Need to clear this flag, or fixup gets confused. (The
145 * array-elements have been translated away by now, so it's ok to
148 IM
->OrFlag
&= ~VERT_BIT_ELT
;
149 IM
->AndFlag
&= ~VERT_BIT_ELT
;
151 _tnl_fixup_input( ctx
, IM
);
153 /* Allocate space for this structure in the display list currently
156 node
= (TNLvertexcassette
*)
157 _mesa_alloc_instruction(ctx
,
158 tnl
->opcode_vertex_cassette
,
159 sizeof(TNLvertexcassette
));
163 node
->IM
= im
; im
->ref_count
++;
164 node
->Start
= im
->Start
;
165 node
->Count
= im
->Count
;
166 node
->BeginState
= im
->BeginState
;
167 node
->SavedBeginState
= im
->SavedBeginState
;
168 node
->OrFlag
= im
->OrFlag
;
169 node
->TexSize
= im
->TexSize
;
170 node
->AndFlag
= im
->AndFlag
;
171 node
->LastData
= im
->LastData
;
172 node
->LastPrimitive
= im
->LastPrimitive
;
173 node
->LastMaterial
= im
->LastMaterial
;
174 node
->MaterialOrMask
= im
->MaterialOrMask
;
175 node
->MaterialAndMask
= im
->MaterialAndMask
;
177 if (tnl
->CalcDListNormalLengths
) {
178 build_normal_lengths( im
);
181 if (ctx
->ExecuteFlag
) {
182 execute_compiled_cassette( ctx
, (void *)node
);
185 /* Discard any errors raised in the last cassette.
187 new_beginstate
= node
->BeginState
& (VERT_BEGIN_0
|VERT_BEGIN_1
);
189 /* Decide whether this immediate struct is full, or can be used for
190 * the next batch of vertices as well.
192 if (im
->Count
> IMM_MAXDATA
- 16) {
195 struct immediate
*new_im
= _tnl_alloc_immediate(ctx
);
197 im
->ref_count
--; /* remove CURRENT_IM reference */
198 ASSERT(im
->ref_count
> 0); /* it is compiled into a display list */
199 SET_IMMEDIATE( ctx
, new_im
);
200 _tnl_reset_compile_input( ctx
, IMM_MAX_COPIED_VERTS
,
201 new_beginstate
, node
->SavedBeginState
);
203 /* Still some room in the current immediate.
205 _tnl_reset_compile_input( ctx
, im
->Count
+1+IMM_MAX_COPIED_VERTS
,
206 new_beginstate
, node
->SavedBeginState
);
212 fixup_compiled_primitives( GLcontext
*ctx
, struct immediate
*IM
)
214 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
216 /* Can potentially overwrite primitive details - need to save the
219 tnl
->DlistPrimitive
= IM
->Primitive
[IM
->Start
];
220 tnl
->DlistPrimitiveLength
= IM
->PrimitiveLength
[IM
->Start
];
221 tnl
->DlistLastPrimitive
= IM
->LastPrimitive
;
223 /* The first primitive may be different from what was recorded in
224 * the immediate struct. Consider an immediate that starts with a
225 * glBegin, compiled in a display list, which is called from within
226 * an existing Begin/End object.
228 if (ctx
->Driver
.CurrentExecPrimitive
== GL_POLYGON
+1) {
231 if (IM
->BeginState
& VERT_ERROR_1
)
232 _mesa_error( ctx
, GL_INVALID_OPERATION
, "glBegin/glEnd");
234 for (i
= IM
->Start
; i
<= IM
->Count
; i
+= IM
->PrimitiveLength
[i
])
235 if (IM
->Flag
[i
] & (VERT_BIT_BEGIN
|VERT_BIT_END_VB
))
238 /* Would like to just ignore vertices upto this point. Can't
239 * set copystart because it might skip materials?
241 ASSERT(IM
->Start
== IM
->CopyStart
);
242 if (i
> IM
->CopyStart
|| !(IM
->Flag
[IM
->Start
] & VERT_BIT_BEGIN
)) {
243 IM
->Primitive
[IM
->CopyStart
] = GL_POLYGON
+1;
244 IM
->PrimitiveLength
[IM
->CopyStart
] = i
- IM
->CopyStart
;
245 if (IM
->Flag
[i
] & VERT_BIT_END_VB
) {
246 IM
->Primitive
[IM
->CopyStart
] |= PRIM_LAST
;
247 IM
->LastPrimitive
= IM
->CopyStart
;
254 if (IM
->BeginState
& VERT_ERROR_0
)
255 _mesa_error( ctx
, GL_INVALID_OPERATION
, "glBegin/glEnd");
257 if (IM
->CopyStart
== IM
->Start
&&
258 IM
->Flag
[IM
->Start
] & (VERT_BIT_END
| VERT_BIT_END_VB
))
264 IM
->Primitive
[IM
->CopyStart
] = ctx
->Driver
.CurrentExecPrimitive
;
266 IM
->Primitive
[IM
->CopyStart
] |= PRIM_PARITY
;
268 /* one of these should be true, else we'll be in an infinite loop
270 ASSERT(IM
->PrimitiveLength
[IM
->Start
] > 0 ||
271 IM
->Flag
[IM
->Start
] & (VERT_BIT_END
| VERT_BIT_END_VB
));
273 for (i
= IM
->Start
; i
<= IM
->Count
; i
+= IM
->PrimitiveLength
[i
]) {
274 if (IM
->Flag
[i
] & (VERT_BIT_END
| VERT_BIT_END_VB
)) {
275 IM
->PrimitiveLength
[IM
->CopyStart
] = i
- IM
->CopyStart
;
276 if (IM
->Flag
[i
] & VERT_BIT_END_VB
) {
277 IM
->Primitive
[IM
->CopyStart
] |= PRIM_LAST
;
278 IM
->LastPrimitive
= IM
->CopyStart
;
280 if (IM
->Flag
[i
] & VERT_BIT_END
) {
281 IM
->Primitive
[IM
->CopyStart
] |= PRIM_END
;
291 /* Undo any changes potentially made to the immediate in the range
292 * IM->Start..IM->Count above.
295 restore_compiled_primitives( GLcontext
*ctx
, struct immediate
*IM
)
297 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
298 IM
->Primitive
[IM
->Start
] = tnl
->DlistPrimitive
;
299 IM
->PrimitiveLength
[IM
->Start
] = tnl
->DlistPrimitiveLength
;
304 execute_compiled_cassette( GLcontext
*ctx
, void *data
)
306 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
307 TNLvertexcassette
*node
= (TNLvertexcassette
*)data
;
308 struct immediate
*IM
= node
->IM
;
310 /* _mesa_debug("%s\n", __FUNCTION__); */
312 IM
->Start
= node
->Start
;
313 IM
->CopyStart
= node
->Start
;
314 IM
->Count
= node
->Count
;
315 IM
->BeginState
= node
->BeginState
;
316 IM
->SavedBeginState
= node
->SavedBeginState
;
317 IM
->OrFlag
= node
->OrFlag
;
318 IM
->TexSize
= node
->TexSize
;
319 IM
->AndFlag
= node
->AndFlag
;
320 IM
->LastData
= node
->LastData
;
321 IM
->LastPrimitive
= node
->LastPrimitive
;
322 IM
->LastMaterial
= node
->LastMaterial
;
323 IM
->MaterialOrMask
= node
->MaterialOrMask
;
324 IM
->MaterialAndMask
= node
->MaterialAndMask
;
326 if ((MESA_VERBOSE
& VERBOSE_DISPLAY_LIST
) &&
327 (MESA_VERBOSE
& VERBOSE_IMMEDIATE
))
328 _tnl_print_cassette( IM
);
330 if (MESA_VERBOSE
& VERBOSE_DISPLAY_LIST
) {
331 _mesa_debug(ctx
, "Run cassette %d, rows %d..%d, beginstate %x ",
332 IM
->id
, IM
->Start
, IM
->Count
, IM
->BeginState
);
333 _tnl_print_vert_flags("orflag", IM
->OrFlag
);
337 /* Need to respect 'HardBeginEnd' even if the commands are looped
338 * back to a driver tnl module.
340 if (IM
->SavedBeginState
) {
341 if (ctx
->Driver
.CurrentExecPrimitive
== GL_POLYGON
+1)
342 tnl
->ReplayHardBeginEnd
= 1;
343 if (!tnl
->ReplayHardBeginEnd
) {
344 /* This is a user error. Whatever operation (like glRectf)
345 * decomposed to this hard begin/end pair is now being run
346 * inside a begin/end object -- illegally. Reject it and
349 _mesa_error(ctx
, GL_INVALID_OPERATION
, "hard replay");
354 if (tnl
->LoopbackDListCassettes
) {
355 /* (tnl->IsolateMaterials && (IM->OrFlag & VERT_MATERIAL)) ) { */
356 fixup_compiled_primitives( ctx
, IM
);
357 loopback_compiled_cassette( ctx
, IM
);
358 restore_compiled_primitives( ctx
, IM
);
362 _mesa_update_state(ctx
);
364 if (tnl
->pipeline
.build_state_changes
)
365 _tnl_validate_pipeline( ctx
);
367 _tnl_fixup_compiled_cassette( ctx
, IM
);
368 fixup_compiled_primitives( ctx
, IM
);
370 if (IM
->Primitive
[IM
->LastPrimitive
] & PRIM_END
)
371 ctx
->Driver
.CurrentExecPrimitive
= GL_POLYGON
+1;
372 else if ((IM
->Primitive
[IM
->LastPrimitive
] & PRIM_BEGIN
) ||
373 (IM
->Primitive
[IM
->LastPrimitive
] & PRIM_MODE_MASK
) ==
374 PRIM_OUTSIDE_BEGIN_END
) {
375 ctx
->Driver
.CurrentExecPrimitive
=
376 IM
->Primitive
[IM
->LastPrimitive
] & PRIM_MODE_MASK
;
379 _tnl_get_exec_copy_verts( ctx
, IM
);
381 if (IM
->NormalLengthPtr
)
382 fixup_normal_lengths( IM
);
384 if (IM
->Count
== IM
->Start
)
385 _tnl_copy_to_current( ctx
, IM
, IM
->OrFlag
, IM
->LastData
);
387 /* _tnl_print_cassette( IM ); */
388 _tnl_run_cassette( ctx
, IM
);
391 restore_compiled_primitives( ctx
, IM
);
394 if (ctx
->Driver
.CurrentExecPrimitive
== GL_POLYGON
+1)
395 tnl
->ReplayHardBeginEnd
= 0;
400 destroy_compiled_cassette( GLcontext
*ctx
, void *data
)
402 TNLvertexcassette
*node
= (TNLvertexcassette
*)data
;
404 if ( --node
->IM
->ref_count
== 0 )
405 _tnl_free_immediate( ctx
, node
->IM
);
410 print_compiled_cassette( GLcontext
*ctx
, void *data
)
412 TNLvertexcassette
*node
= (TNLvertexcassette
*)data
;
413 struct immediate
*IM
= node
->IM
;
415 _mesa_debug(ctx
, "TNL-VERTEX-CASSETTE, id %u, rows %u..%u\n",
416 node
->IM
->id
, node
->Start
, node
->Count
);
418 IM
->Start
= node
->Start
;
419 IM
->CopyStart
= node
->Start
;
420 IM
->Count
= node
->Count
;
421 IM
->BeginState
= node
->BeginState
;
422 IM
->OrFlag
= node
->OrFlag
;
423 IM
->TexSize
= node
->TexSize
;
424 IM
->AndFlag
= node
->AndFlag
;
425 IM
->LastData
= node
->LastData
;
426 IM
->LastPrimitive
= node
->LastPrimitive
;
427 IM
->LastMaterial
= node
->LastMaterial
;
428 IM
->MaterialOrMask
= node
->MaterialOrMask
;
429 IM
->MaterialAndMask
= node
->MaterialAndMask
;
431 _tnl_print_cassette( node
->IM
);
436 _tnl_BeginCallList( GLcontext
*ctx
, GLuint list
)
440 FLUSH_CURRENT(ctx
, 0);
444 /* Called at the tail of a CallList. Make current immediate aware of
445 * any new to-be-copied vertices.
448 _tnl_EndCallList( GLcontext
*ctx
)
450 GLuint beginstate
= 0;
452 if (ctx
->Driver
.CurrentExecPrimitive
!= PRIM_OUTSIDE_BEGIN_END
)
453 beginstate
= VERT_BEGIN_0
|VERT_BEGIN_1
;
455 _tnl_reset_exec_input( ctx
, TNL_CURRENT_IM(ctx
)->Start
, beginstate
, 0 );
460 _tnl_EndList( GLcontext
*ctx
)
462 struct immediate
*IM
= TNL_CURRENT_IM(ctx
);
467 /* outside begin/end, even in COMPILE_AND_EXEC,
468 * so no vertices to copy, right?
470 ASSERT(TNL_CONTEXT(ctx
)->ExecCopyCount
== 0);
472 /* If this one isn't free, get a clean one. (Otherwise we'll be
473 * using one that's already half full).
475 if (IM
->ref_count
!= 0)
476 IM
= _tnl_alloc_immediate( ctx
);
478 ASSERT(IM
->ref_count
== 0);
480 SET_IMMEDIATE( ctx
, IM
);
483 _tnl_reset_exec_input( ctx
, IMM_MAX_COPIED_VERTS
, 0, 0 );
488 _tnl_NewList( GLcontext
*ctx
, GLuint list
, GLenum mode
)
490 struct immediate
*IM
= TNL_CURRENT_IM(ctx
);
492 /* Use the installed immediate struct. No vertices in the current
493 * immediate, no copied vertices in the system.
495 ASSERT(TNL_CURRENT_IM(ctx
));
496 ASSERT(TNL_CURRENT_IM(ctx
)->Start
== IMM_MAX_COPIED_VERTS
);
497 ASSERT(TNL_CURRENT_IM(ctx
)->Start
== TNL_CURRENT_IM(ctx
)->Count
);
498 ASSERT(TNL_CONTEXT(ctx
)->ExecCopyCount
== 0);
500 /* Set current Begin/End state to unknown:
502 IM
->BeginState
= VERT_BEGIN_0
;
503 ctx
->Driver
.CurrentSavePrimitive
= PRIM_UNKNOWN
;
508 _tnl_dlist_init( GLcontext
*ctx
)
510 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
512 tnl
->opcode_vertex_cassette
=
513 _mesa_alloc_opcode( ctx
,
514 sizeof(TNLvertexcassette
),
515 execute_compiled_cassette
,
516 destroy_compiled_cassette
,
517 print_compiled_cassette
);
522 * Call glMaterialfv for the attributes specified by bitmask, using the
523 * material colors in src.
526 emit_material( const struct gl_material
*src
, GLuint bitmask
)
528 if (bitmask
& FRONT_EMISSION_BIT
)
529 glMaterialfv( GL_FRONT
, GL_EMISSION
, src
[0].Emission
);
531 if (bitmask
& BACK_EMISSION_BIT
)
532 glMaterialfv( GL_BACK
, GL_EMISSION
, src
[1].Emission
);
534 if (bitmask
& FRONT_AMBIENT_BIT
)
535 glMaterialfv( GL_FRONT
, GL_AMBIENT
, src
[0].Ambient
);
537 if (bitmask
& BACK_AMBIENT_BIT
)
538 glMaterialfv( GL_BACK
, GL_AMBIENT
, src
[1].Ambient
);
540 if (bitmask
& FRONT_DIFFUSE_BIT
)
541 glMaterialfv( GL_FRONT
, GL_DIFFUSE
, src
[0].Diffuse
);
543 if (bitmask
& BACK_DIFFUSE_BIT
)
544 glMaterialfv( GL_BACK
, GL_DIFFUSE
, src
[1].Diffuse
);
546 if (bitmask
& FRONT_SPECULAR_BIT
)
547 glMaterialfv( GL_FRONT
, GL_SPECULAR
, src
[0].Specular
);
549 if (bitmask
& BACK_SPECULAR_BIT
)
550 glMaterialfv( GL_BACK
, GL_SPECULAR
, src
[1].Specular
);
552 if (bitmask
& FRONT_SHININESS_BIT
)
553 glMaterialfv( GL_FRONT
, GL_SHININESS
, &src
[0].Shininess
);
555 if (bitmask
& BACK_SHININESS_BIT
)
556 glMaterialfv( GL_BACK
, GL_SHININESS
, &src
[1].Shininess
);
558 if (bitmask
& FRONT_INDEXES_BIT
) {
560 ind
[0] = src
[0].AmbientIndex
;
561 ind
[1] = src
[0].DiffuseIndex
;
562 ind
[2] = src
[0].SpecularIndex
;
563 glMaterialfv( GL_FRONT
, GL_COLOR_INDEXES
, ind
);
566 if (bitmask
& BACK_INDEXES_BIT
) {
568 ind
[0] = src
[1].AmbientIndex
;
569 ind
[1] = src
[1].DiffuseIndex
;
570 ind
[2] = src
[1].SpecularIndex
;
571 glMaterialfv( GL_BACK
, GL_COLOR_INDEXES
, ind
);
576 /* Low-performance helper function to allow driver-supplied tnl
577 * modules to process tnl display lists. This is primarily supplied
578 * to avoid fallbacks if CallList is invoked inside a Begin/End pair.
579 * For higher performance, drivers should fallback to tnl (if outside
580 * begin/end), or (for tnl hardware) implement their own display list
584 loopback_compiled_cassette( GLcontext
*ctx
, struct immediate
*IM
)
586 const GLuint
*flags
= IM
->Flag
;
587 const GLuint orflag
= IM
->OrFlag
;
588 void (GLAPIENTRY
*vertex
)( const GLfloat
* );
589 void (GLAPIENTRY
*texcoordfv
[MAX_TEXTURE_COORD_UNITS
])( GLenum
, const GLfloat
* );
590 GLuint i
, j
, p
, length
, prim
= 0, maxtex
= 0;
592 if (orflag
& VERT_BITS_OBJ_234
)
593 vertex
= (void (GLAPIENTRY
*)(const GLfloat
*)) glVertex4fv
;
595 vertex
= (void (GLAPIENTRY
*)(const GLfloat
*)) glVertex3fv
;
597 if (orflag
& VERT_BITS_TEX_ANY
) {
598 for (j
= 0 ; j
< ctx
->Const
.MaxTextureUnits
; j
++) {
599 if (orflag
& VERT_BIT_TEX(j
)) {
601 if ((IM
->TexSize
& TEX_SIZE_4(j
)) == TEX_SIZE_4(j
))
602 texcoordfv
[j
] = glMultiTexCoord4fvARB
;
603 else if (IM
->TexSize
& TEX_SIZE_3(j
))
604 texcoordfv
[j
] = glMultiTexCoord3fvARB
;
606 texcoordfv
[j
] = glMultiTexCoord2fvARB
;
611 for (p
= IM
->Start
; !(prim
& PRIM_LAST
) ; p
+= length
)
613 prim
= IM
->Primitive
[p
];
614 length
= IM
->PrimitiveLength
[p
];
615 ASSERT(length
|| (prim
& PRIM_LAST
));
616 ASSERT((prim
& PRIM_MODE_MASK
) <= GL_POLYGON
+1);
618 if (prim
& PRIM_BEGIN
) {
619 glBegin(prim
& PRIM_MODE_MASK
);
622 for ( i
= p
; i
<= p
+length
; i
++) {
623 if (flags
[i
] & VERT_BITS_TEX_ANY
) {
625 for (k
= 0 ; k
< maxtex
; k
++) {
626 if (flags
[i
] & VERT_BIT_TEX(k
)) {
627 texcoordfv
[k
]( GL_TEXTURE0_ARB
+ k
,
628 IM
->Attrib
[VERT_ATTRIB_TEX0
+ k
][i
] );
633 if (flags
[i
] & VERT_BIT_NORMAL
)
634 glNormal3fv(IM
->Attrib
[VERT_ATTRIB_NORMAL
][i
]);
636 if (flags
[i
] & VERT_BIT_COLOR0
)
637 glColor4fv( IM
->Attrib
[VERT_ATTRIB_COLOR0
][i
] );
639 if (flags
[i
] & VERT_BIT_COLOR1
)
640 _glapi_Dispatch
->SecondaryColor3fvEXT( IM
->Attrib
[VERT_ATTRIB_COLOR1
][i
] );
642 if (flags
[i
] & VERT_BIT_FOG
)
643 _glapi_Dispatch
->FogCoordfEXT( IM
->Attrib
[VERT_ATTRIB_FOG
][i
][0] );
645 if (flags
[i
] & VERT_BIT_INDEX
)
646 glIndexi( IM
->Index
[i
] );
648 if (flags
[i
] & VERT_BIT_EDGEFLAG
)
649 glEdgeFlag( IM
->EdgeFlag
[i
] );
651 if (flags
[i
] & VERT_BIT_MATERIAL
)
652 emit_material( IM
->Material
[i
], IM
->MaterialMask
[i
] );
654 if (flags
[i
]&VERT_BITS_OBJ_234
)
655 vertex( IM
->Attrib
[VERT_ATTRIB_POS
][i
] );
656 else if (flags
[i
] & VERT_BIT_EVAL_C1
)
657 glEvalCoord1f( IM
->Attrib
[VERT_ATTRIB_POS
][i
][0] );
658 else if (flags
[i
] & VERT_BIT_EVAL_P1
)
659 glEvalPoint1( (GLint
) IM
->Attrib
[VERT_ATTRIB_POS
][i
][0] );
660 else if (flags
[i
] & VERT_BIT_EVAL_C2
)
661 glEvalCoord2f( IM
->Attrib
[VERT_ATTRIB_POS
][i
][0],
662 IM
->Attrib
[VERT_ATTRIB_POS
][i
][1] );
663 else if (flags
[i
] & VERT_BIT_EVAL_P2
)
664 glEvalPoint2( (GLint
) IM
->Attrib
[VERT_ATTRIB_POS
][i
][0],
665 (GLint
) IM
->Attrib
[VERT_ATTRIB_POS
][i
][1] );
668 if (prim
& PRIM_END
) {