more GLAPIENTRY fixes (Karl Schultz)
[mesa.git] / src / mesa / tnl / t_imm_dlist.c
1 /* $Id: t_imm_dlist.c,v 1.26 2001/07/27 19:09:58 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 * Authors:
27 * Keith Whitwell <keithw@valinux.com>
28 */
29
30
31 #include "glheader.h"
32 #include "context.h"
33 #include "dlist.h"
34 #include "debug.h"
35 #include "mmath.h"
36 #include "mem.h"
37 #include "state.h"
38
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"
48
49 typedef struct {
50 struct immediate *IM;
51 GLuint Start;
52 GLuint Count;
53 GLuint BeginState;
54 GLuint SavedBeginState;
55 GLuint OrFlag;
56 GLuint AndFlag;
57 GLuint TexSize;
58 GLuint LastData;
59 GLuint LastPrimitive;
60 GLuint LastMaterial;
61 GLuint MaterialOrMask;
62 GLuint MaterialAndMask;
63 } TNLvertexcassette;
64
65 static void execute_compiled_cassette( GLcontext *ctx, void *data );
66 static void loopback_compiled_cassette( GLcontext *ctx, struct immediate *IM );
67
68
69 static void build_normal_lengths( struct immediate *IM )
70 {
71 GLuint i;
72 GLfloat len;
73 GLfloat (*data)[3] = IM->Normal + IM->Start;
74 GLfloat *dest = IM->NormalLengthPtr;
75 GLuint *flags = IM->Flag + IM->Start;
76 GLuint count = IM->Count - IM->Start;
77
78 if (!dest) {
79 dest = IM->NormalLengthPtr = ALIGN_MALLOC( IMM_SIZE*sizeof(GLfloat), 32 );
80 if (!dest) return;
81 }
82 dest += IM->Start;
83
84 len = (GLfloat) LEN_3FV( data[0] );
85 if (len > 0.0) len = 1.0/len;
86
87 for (i = 0 ; i < count ; ) {
88 dest[i] = len;
89 if (flags[++i] & VERT_NORM) {
90 len = (GLfloat) LEN_3FV( data[i] );
91 if (len > 0.0) len = 1.0/len;
92 }
93 }
94 }
95
96 static void fixup_normal_lengths( struct immediate *IM )
97 {
98 GLuint i;
99 GLfloat len = 1.0; /* just to silence warnings */
100 GLfloat (*data)[3] = IM->Normal;
101 GLfloat *dest = IM->NormalLengthPtr;
102 GLuint *flags = IM->Flag;
103
104 for (i = IM->CopyStart ; i <= IM->Start ; i++) {
105 len = (GLfloat) LEN_3FV( data[i] );
106 if (len > 0.0) len = 1.0/len;
107 dest[i] = len;
108 }
109
110 while (!(flags[i] & (VERT_NORM|VERT_END_VB))) {
111 dest[i] = len;
112 i++;
113 }
114 }
115
116
117
118 /* Insert the active immediate struct onto the display list currently
119 * being built.
120 */
121 void
122 _tnl_compile_cassette( GLcontext *ctx, struct immediate *IM )
123 {
124 struct immediate *im = TNL_CURRENT_IM(ctx);
125 TNLcontext *tnl = TNL_CONTEXT(ctx);
126 TNLvertexcassette *node;
127 GLuint new_beginstate;
128
129 if (IM->FlushElt) {
130 ASSERT (IM->FlushElt == FLUSH_ELT_LAZY);
131 _tnl_translate_array_elts( ctx, IM, IM->Start, IM->Count );
132 }
133
134 _tnl_compute_orflag( IM, IM->Start );
135
136 /* Need to clear this flag, or fixup gets confused. (The
137 * array-elements have been translated away by now, so it's ok to
138 * remove it.)
139 */
140 IM->OrFlag &= ~VERT_ELT;
141 IM->AndFlag &= ~VERT_ELT;
142
143 _tnl_fixup_input( ctx, IM );
144
145 node = (TNLvertexcassette *)
146 _mesa_alloc_instruction(ctx,
147 tnl->opcode_vertex_cassette,
148 sizeof(TNLvertexcassette));
149 if (!node)
150 return;
151
152 node->IM = im; im->ref_count++;
153 node->Start = im->Start;
154 node->Count = im->Count;
155 node->BeginState = im->BeginState;
156 node->SavedBeginState = im->SavedBeginState;
157 node->OrFlag = im->OrFlag;
158 node->TexSize = im->TexSize;
159 node->AndFlag = im->AndFlag;
160 node->LastData = im->LastData;
161 node->LastPrimitive = im->LastPrimitive;
162 node->LastMaterial = im->LastMaterial;
163 node->MaterialOrMask = im->MaterialOrMask;
164 node->MaterialAndMask = im->MaterialAndMask;
165
166 if (tnl->CalcDListNormalLengths) {
167 build_normal_lengths( im );
168 }
169
170 if (ctx->ExecuteFlag) {
171 execute_compiled_cassette( ctx, (void *)node );
172 }
173
174 /* Discard any errors raised in the last cassette.
175 */
176 new_beginstate = node->BeginState & (VERT_BEGIN_0|VERT_BEGIN_1);
177
178 /* Decide whether this immediate struct is full, or can be used for
179 * the next batch of vertices as well.
180 */
181 if (im->Count > IMM_MAXDATA - 16) {
182 /* Call it full...
183 */
184 struct immediate *new_im = _tnl_alloc_immediate(ctx);
185 new_im->ref_count++;
186 im->ref_count--; /* remove CURRENT_IM reference */
187 ASSERT(im->ref_count > 0); /* it is compiled into a display list */
188 SET_IMMEDIATE( ctx, new_im );
189 _tnl_reset_compile_input( ctx, IMM_MAX_COPIED_VERTS,
190 new_beginstate, node->SavedBeginState );
191 } else {
192 /* Still some room in the current immediate.
193 */
194 _tnl_reset_compile_input( ctx, im->Count+1+IMM_MAX_COPIED_VERTS,
195 new_beginstate, node->SavedBeginState);
196 }
197 }
198
199
200 static void fixup_compiled_primitives( GLcontext *ctx, struct immediate *IM )
201 {
202 TNLcontext *tnl = TNL_CONTEXT(ctx);
203
204 /* Can potentially overwrite primitive details - need to save the
205 * first slot:
206 */
207 tnl->DlistPrimitive = IM->Primitive[IM->Start];
208 tnl->DlistPrimitiveLength = IM->PrimitiveLength[IM->Start];
209 tnl->DlistLastPrimitive = IM->LastPrimitive;
210
211 /* The first primitive may be different from what was recorded in
212 * the immediate struct. Consider an immediate that starts with a
213 * glBegin, compiled in a display list, which is called from within
214 * an existing Begin/End object.
215 */
216 if (ctx->Driver.CurrentExecPrimitive == GL_POLYGON+1) {
217 GLuint i;
218
219 if (IM->BeginState & VERT_ERROR_1)
220 _mesa_error( ctx, GL_INVALID_OPERATION, "glBegin/glEnd");
221
222 for (i = IM->Start ; i <= IM->Count ; i += IM->PrimitiveLength[i])
223 if (IM->Flag[i] & (VERT_BEGIN|VERT_END_VB))
224 break;
225
226 /* Would like to just ignore vertices upto this point. Can't
227 * set copystart because it might skip materials?
228 */
229 ASSERT(IM->Start == IM->CopyStart);
230 if (i > IM->CopyStart) {
231 IM->Primitive[IM->CopyStart] = GL_POLYGON+1;
232 IM->PrimitiveLength[IM->CopyStart] = i - IM->CopyStart;
233 if (IM->Flag[i] & VERT_END_VB) {
234 IM->Primitive[IM->CopyStart] |= PRIM_LAST;
235 IM->LastPrimitive = IM->CopyStart;
236 }
237 }
238 } else {
239 GLuint i;
240
241 if (IM->BeginState & VERT_ERROR_0)
242 _mesa_error( ctx, GL_INVALID_OPERATION, "glBegin/glEnd");
243
244 if (IM->CopyStart == IM->Start &&
245 IM->Flag[IM->Start] & (VERT_END|VERT_END_VB))
246 {
247 }
248 else
249 {
250 IM->Primitive[IM->CopyStart] = ctx->Driver.CurrentExecPrimitive;
251 if (tnl->ExecParity)
252 IM->Primitive[IM->CopyStart] |= PRIM_PARITY;
253
254 /* one of these should be true, else we'll be in an infinite loop
255 */
256 ASSERT(IM->PrimitiveLength[IM->Start] > 0 ||
257 IM->Flag[IM->Start] & (VERT_END|VERT_END_VB));
258
259 for (i = IM->Start ; i <= IM->Count ; i += IM->PrimitiveLength[i])
260 if (IM->Flag[i] & (VERT_END|VERT_END_VB)) {
261 IM->PrimitiveLength[IM->CopyStart] = i - IM->CopyStart;
262 if (IM->Flag[i] & VERT_END_VB) {
263 IM->Primitive[IM->CopyStart] |= PRIM_LAST;
264 IM->LastPrimitive = IM->CopyStart;
265 }
266 if (IM->Flag[i] & VERT_END) {
267 IM->Primitive[IM->CopyStart] |= PRIM_END;
268 }
269 break;
270 }
271 }
272 }
273 }
274
275 /* Undo any changes potentially made to the immediate in the range
276 * IM->Start..IM->Count above.
277 */
278 static void restore_compiled_primitives( GLcontext *ctx, struct immediate *IM )
279 {
280 TNLcontext *tnl = TNL_CONTEXT(ctx);
281 IM->Primitive[IM->Start] = tnl->DlistPrimitive;
282 IM->PrimitiveLength[IM->Start] = tnl->DlistPrimitiveLength;
283 }
284
285
286
287 static void
288 execute_compiled_cassette( GLcontext *ctx, void *data )
289 {
290 TNLcontext *tnl = TNL_CONTEXT(ctx);
291 TNLvertexcassette *node = (TNLvertexcassette *)data;
292 struct immediate *IM = node->IM;
293
294 /* fprintf(stderr, "%s\n", __FUNCTION__); */
295
296 IM->Start = node->Start;
297 IM->CopyStart = node->Start;
298 IM->Count = node->Count;
299 IM->BeginState = node->BeginState;
300 IM->SavedBeginState = node->SavedBeginState;
301 IM->OrFlag = node->OrFlag;
302 IM->TexSize = node->TexSize;
303 IM->AndFlag = node->AndFlag;
304 IM->LastData = node->LastData;
305 IM->LastPrimitive = node->LastPrimitive;
306 IM->LastMaterial = node->LastMaterial;
307 IM->MaterialOrMask = node->MaterialOrMask;
308 IM->MaterialAndMask = node->MaterialAndMask;
309
310 if ((MESA_VERBOSE & VERBOSE_DISPLAY_LIST) &&
311 (MESA_VERBOSE & VERBOSE_IMMEDIATE))
312 _tnl_print_cassette( IM );
313
314 if (MESA_VERBOSE & VERBOSE_DISPLAY_LIST) {
315 fprintf(stderr, "Run cassette %d, rows %d..%d, beginstate %x ",
316 IM->id,
317 IM->Start, IM->Count, IM->BeginState);
318 _tnl_print_vert_flags("orflag", IM->OrFlag);
319 }
320
321
322 /* Need to respect 'HardBeginEnd' even if the commands are looped
323 * back to a driver tnl module.
324 */
325 if (IM->SavedBeginState) {
326 if (ctx->Driver.CurrentExecPrimitive == GL_POLYGON+1)
327 tnl->ReplayHardBeginEnd = 1;
328 if (!tnl->ReplayHardBeginEnd) {
329 /* This is a user error. Whatever operation (like glRectf)
330 * decomposed to this hard begin/end pair is now being run
331 * inside a begin/end object -- illegally. Reject it and
332 * raise an error.
333 */
334 _mesa_error(ctx, GL_INVALID_OPERATION, "hard replay");
335 return;
336 }
337 }
338
339 if (tnl->LoopbackDListCassettes) {
340 fixup_compiled_primitives( ctx, IM );
341 loopback_compiled_cassette( ctx, IM );
342 restore_compiled_primitives( ctx, IM );
343 }
344 else {
345 if (ctx->NewState)
346 _mesa_update_state(ctx);
347
348 if (tnl->pipeline.build_state_changes)
349 _tnl_validate_pipeline( ctx );
350
351 _tnl_fixup_compiled_cassette( ctx, IM );
352 fixup_compiled_primitives( ctx, IM );
353
354 if (IM->Primitive[IM->LastPrimitive] & PRIM_END)
355 ctx->Driver.CurrentExecPrimitive = GL_POLYGON+1;
356 else if ((IM->Primitive[IM->LastPrimitive] & PRIM_BEGIN) ||
357 (IM->Primitive[IM->LastPrimitive] & PRIM_MODE_MASK) ==
358 PRIM_OUTSIDE_BEGIN_END) {
359 ctx->Driver.CurrentExecPrimitive =
360 IM->Primitive[IM->LastPrimitive] & PRIM_MODE_MASK;
361 }
362
363 _tnl_get_exec_copy_verts( ctx, IM );
364
365 if (IM->NormalLengthPtr)
366 fixup_normal_lengths( IM );
367
368 if (IM->Count == IM->Start)
369 _tnl_copy_to_current( ctx, IM, IM->OrFlag );
370 else
371 _tnl_run_cassette( ctx, IM );
372
373 restore_compiled_primitives( ctx, IM );
374 }
375
376 if (ctx->Driver.CurrentExecPrimitive == GL_POLYGON+1)
377 tnl->ReplayHardBeginEnd = 0;
378 }
379
380 static void
381 destroy_compiled_cassette( GLcontext *ctx, void *data )
382 {
383 TNLvertexcassette *node = (TNLvertexcassette *)data;
384
385 if ( --node->IM->ref_count == 0 )
386 _tnl_free_immediate( node->IM );
387 }
388
389
390 static void
391 print_compiled_cassette( GLcontext *ctx, void *data )
392 {
393 TNLvertexcassette *node = (TNLvertexcassette *)data;
394 struct immediate *IM = node->IM;
395
396 fprintf(stderr, "TNL-VERTEX-CASSETTE, id %u, rows %u..%u\n",
397 node->IM->id, node->Start, node->Count);
398
399 IM->Start = node->Start;
400 IM->CopyStart = node->Start;
401 IM->Count = node->Count;
402 IM->BeginState = node->BeginState;
403 IM->OrFlag = node->OrFlag;
404 IM->TexSize = node->TexSize;
405 IM->AndFlag = node->AndFlag;
406 IM->LastData = node->LastData;
407 IM->LastPrimitive = node->LastPrimitive;
408 IM->LastMaterial = node->LastMaterial;
409 IM->MaterialOrMask = node->MaterialOrMask;
410 IM->MaterialAndMask = node->MaterialAndMask;
411
412 _tnl_print_cassette( node->IM );
413 }
414
415 void
416 _tnl_BeginCallList( GLcontext *ctx, GLuint list )
417 {
418 (void) ctx;
419 (void) list;
420 FLUSH_CURRENT(ctx, 0);
421 }
422
423
424 /* Called at the tail of a CallList. Nothing to do.
425 */
426 void
427 _tnl_EndCallList( GLcontext *ctx )
428 {
429 (void) ctx;
430 }
431
432
433 void
434 _tnl_EndList( GLcontext *ctx )
435 {
436 struct immediate *IM = TNL_CURRENT_IM(ctx);
437
438 ctx->swtnl_im = 0;
439 IM->ref_count--;
440
441 /* outside begin/end, even in COMPILE_AND_EXEC,
442 * so no vertices to copy, right?
443 */
444 ASSERT(TNL_CONTEXT(ctx)->ExecCopyCount == 0);
445
446 /* If this one isn't free, get a clean one. (Otherwise we'll be
447 * using one that's already half full).
448 */
449 if (IM->ref_count != 0)
450 IM = _tnl_alloc_immediate( ctx );
451
452 ASSERT(IM->ref_count == 0);
453
454 SET_IMMEDIATE( ctx, IM );
455 IM->ref_count++;
456
457 _tnl_reset_exec_input( ctx, IMM_MAX_COPIED_VERTS, 0, 0 );
458 }
459
460
461 void
462 _tnl_NewList( GLcontext *ctx, GLuint list, GLenum mode )
463 {
464 struct immediate *IM = TNL_CURRENT_IM(ctx);
465
466 /* Use the installed immediate struct. No vertices in the current
467 * immediate, no copied vertices in the system.
468 */
469 ASSERT(TNL_CURRENT_IM(ctx));
470 ASSERT(TNL_CURRENT_IM(ctx)->Start == IMM_MAX_COPIED_VERTS);
471 ASSERT(TNL_CURRENT_IM(ctx)->Start == TNL_CURRENT_IM(ctx)->Count);
472 ASSERT(TNL_CONTEXT(ctx)->ExecCopyCount == 0);
473
474 /* Set current Begin/End state to unknown:
475 */
476 IM->BeginState = VERT_BEGIN_0;
477 ctx->Driver.CurrentSavePrimitive = PRIM_UNKNOWN;
478 }
479
480
481 void
482 _tnl_dlist_init( GLcontext *ctx )
483 {
484 TNLcontext *tnl = TNL_CONTEXT(ctx);
485
486 tnl->opcode_vertex_cassette =
487 _mesa_alloc_opcode( ctx,
488 sizeof(TNLvertexcassette),
489 execute_compiled_cassette,
490 destroy_compiled_cassette,
491 print_compiled_cassette );
492 }
493
494
495 static void emit_material( struct gl_material *src, GLuint bitmask )
496 {
497 if (bitmask & FRONT_EMISSION_BIT)
498 glMaterialfv( GL_FRONT, GL_EMISSION, src[0].Emission );
499
500 if (bitmask & BACK_EMISSION_BIT)
501 glMaterialfv( GL_BACK, GL_EMISSION, src[1].Emission );
502
503 if (bitmask & FRONT_AMBIENT_BIT)
504 glMaterialfv( GL_FRONT, GL_AMBIENT, src[0].Ambient );
505
506 if (bitmask & BACK_AMBIENT_BIT)
507 glMaterialfv( GL_BACK, GL_AMBIENT, src[1].Ambient );
508
509 if (bitmask & FRONT_DIFFUSE_BIT)
510 glMaterialfv( GL_FRONT, GL_DIFFUSE, src[0].Diffuse );
511
512 if (bitmask & BACK_DIFFUSE_BIT)
513 glMaterialfv( GL_BACK, GL_DIFFUSE, src[1].Diffuse );
514
515 if (bitmask & FRONT_SPECULAR_BIT)
516 glMaterialfv( GL_FRONT, GL_SPECULAR, src[0].Specular );
517
518 if (bitmask & BACK_SPECULAR_BIT)
519 glMaterialfv( GL_BACK, GL_SPECULAR, src[1].Specular );
520
521 if (bitmask & FRONT_SHININESS_BIT)
522 glMaterialfv( GL_FRONT, GL_SHININESS, &src[0].Shininess );
523
524 if (bitmask & BACK_SHININESS_BIT)
525 glMaterialfv( GL_BACK, GL_SHININESS, &src[1].Shininess );
526
527 if (bitmask & FRONT_INDEXES_BIT) {
528 GLfloat ind[3];
529 ind[0] = src[0].AmbientIndex;
530 ind[1] = src[0].DiffuseIndex;
531 ind[2] = src[0].SpecularIndex;
532 glMaterialfv( GL_FRONT, GL_COLOR_INDEXES, ind );
533 }
534
535 if (bitmask & BACK_INDEXES_BIT) {
536 GLfloat ind[3];
537 ind[0] = src[1].AmbientIndex;
538 ind[1] = src[1].DiffuseIndex;
539 ind[2] = src[1].SpecularIndex;
540 glMaterialfv( GL_BACK, GL_COLOR_INDEXES, ind );
541 }
542 }
543
544
545 /* Low-performance helper function to allow driver-supplied tnl
546 * modules to process tnl display lists. This is primarily supplied
547 * to avoid fallbacks if CallList is invoked inside a Begin/End pair.
548 * For higher performance, drivers should fallback to tnl (if outside
549 * begin/end), or (for tnl hardware) implement their own display list
550 * mechanism.
551 */
552 static void loopback_compiled_cassette( GLcontext *ctx, struct immediate *IM )
553 {
554 GLuint i;
555 GLuint *flags = IM->Flag;
556 GLuint orflag = IM->OrFlag;
557 GLuint j;
558 void (GLAPIENTRY *vertex)( const GLfloat * );
559 void (GLAPIENTRY *texcoordfv[MAX_TEXTURE_UNITS])( GLenum, const GLfloat * );
560 GLuint maxtex = 0;
561 GLuint p, length, prim = 0;
562
563 if (orflag & VERT_OBJ_234)
564 vertex = (void (GLAPIENTRY *)(const GLfloat *)) glVertex4fv;
565 else
566 vertex = (void (GLAPIENTRY *)(const GLfloat *)) glVertex3fv;
567
568 if (orflag & VERT_TEX_ANY) {
569 for (j = 0 ; j < ctx->Const.MaxTextureUnits ; j++) {
570 if (orflag & VERT_TEX(j)) {
571 maxtex = j+1;
572 if ((IM->TexSize & TEX_SIZE_4(j)) == TEX_SIZE_4(j))
573 texcoordfv[j] = glMultiTexCoord4fvARB;
574 else if (IM->TexSize & TEX_SIZE_3(j))
575 texcoordfv[j] = glMultiTexCoord3fvARB;
576 else
577 texcoordfv[j] = glMultiTexCoord2fvARB;
578 }
579 }
580 }
581
582 for (p = IM->Start ; !(prim & PRIM_LAST) ; p += length)
583 {
584 prim = IM->Primitive[p];
585 length= IM->PrimitiveLength[p];
586 ASSERT(length || (prim & PRIM_LAST));
587 ASSERT((prim & PRIM_MODE_MASK) <= GL_POLYGON+1);
588
589 if (prim & PRIM_BEGIN) {
590 /* fprintf(stderr, "begin %s\n", _mesa_prim_name[prim&PRIM_MODE_MASK]); */
591 glBegin(prim & PRIM_MODE_MASK);
592 }
593
594 for ( i = p ; i <= p+length ; i++) {
595 if (flags[i] & VERT_TEX_ANY) {
596 GLuint k;
597 for (k = 0 ; k < maxtex ; k++) {
598 if (flags[i] & VERT_TEX(k)) {
599 texcoordfv[k]( GL_TEXTURE0_ARB + k, IM->TexCoord[k][i] );
600 }
601 }
602 }
603
604 if (flags[i] & VERT_NORM) {
605 /* fprintf(stderr, "normal %d: %f %f %f\n", i, */
606 /* IM->Normal[i][0], IM->Normal[i][1], IM->Normal[i][2]); */
607 glNormal3fv(IM->Normal[i]);
608 }
609
610 if (flags[i] & VERT_RGBA) {
611 /* fprintf(stderr, "color %d: %f %f %f\n", i, */
612 /* IM->Color[i][0], IM->Color[i][1], IM->Color[i][2]); */
613 glColor4fv( IM->Color[i] );
614 }
615
616 if (flags[i] & VERT_SPEC_RGB)
617 glSecondaryColor3fvEXT( IM->SecondaryColor[i] );
618
619 if (flags[i] & VERT_FOG_COORD)
620 glFogCoordfEXT( IM->FogCoord[i] );
621
622 if (flags[i] & VERT_INDEX)
623 glIndexi( IM->Index[i] );
624
625 if (flags[i] & VERT_EDGE)
626 glEdgeFlag( IM->EdgeFlag[i] );
627
628 if (flags[i] & VERT_MATERIAL)
629 emit_material( IM->Material[i], IM->MaterialMask[i] );
630
631 if (flags[i]&VERT_OBJ_234) {
632 /* fprintf(stderr, "vertex %d: %f %f %f\n", i, */
633 /* IM->Obj[i][0], IM->Obj[i][1], IM->Obj[i][2]); */
634 vertex( IM->Obj[i] );
635 }
636 else if (flags[i] & VERT_EVAL_C1)
637 glEvalCoord1f(IM->Obj[i][0]);
638 else if (flags[i] & VERT_EVAL_P1)
639 glEvalPoint1(IM->Obj[i][0]);
640 else if (flags[i] & VERT_EVAL_C2)
641 glEvalCoord2f( IM->Obj[i][0], IM->Obj[i][1]);
642 else if (flags[i] & VERT_EVAL_P2)
643 glEvalPoint2( IM->Obj[i][0], IM->Obj[i][1]);
644 }
645
646 if (prim & PRIM_END) {
647 /* fprintf(stderr, "end\n"); */
648 glEnd();
649 }
650 }
651 }