Updates required for building the SciTech SNAP version of Mesa. This includes:
[mesa.git] / src / mesa / tnl / t_imm_api.c
1 /*
2 * Mesa 3-D graphics library
3 * Version: 5.1
4 *
5 * Copyright (C) 1999-2002 Brian Paul All Rights Reserved.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 *
24 * Authors:
25 * Keith Whitwell <keith@tungstengraphics.com>
26 */
27
28
29
30 #include "glheader.h"
31 #include "context.h"
32 #include "dlist.h"
33 #include "enums.h"
34 #include "light.h"
35 #include "imports.h"
36 #include "state.h"
37 #include "colormac.h"
38 #include "macros.h"
39 #include "vtxfmt.h"
40
41 #include "t_context.h"
42 #include "t_imm_api.h"
43 #include "t_imm_elt.h"
44 #include "t_imm_exec.h"
45 #include "t_imm_dlist.h"
46
47
48 /* A cassette is full or flushed on a statechange.
49 */
50 void _tnl_flush_immediate( GLcontext *ctx, struct immediate *IM )
51 {
52 if (!ctx) {
53 /* We were called by glVertex, glEvalCoord, glArrayElement, etc.
54 * The current context is corresponds to the IM structure.
55 */
56 GET_CURRENT_CONTEXT(context);
57 ctx = context;
58 }
59
60 if (MESA_VERBOSE & VERBOSE_IMMEDIATE)
61 _mesa_debug(ctx, "_tnl_flush_immediate IM: %d compiling: %d\n",
62 IM->id, ctx->CompileFlag);
63
64 if (IM->FlushElt == FLUSH_ELT_EAGER) {
65 _tnl_translate_array_elts( ctx, IM, IM->LastPrimitive, IM->Count );
66 }
67
68 /* Mark the last primitive:
69 */
70 IM->PrimitiveLength[IM->LastPrimitive] = IM->Count - IM->LastPrimitive;
71 IM->Primitive[IM->LastPrimitive] |= PRIM_LAST;
72
73 if (ctx->CompileFlag)
74 _tnl_compile_cassette( ctx, IM );
75 else
76 _tnl_execute_cassette( ctx, IM );
77 }
78
79
80 /* Hook for ctx->Driver.FlushVertices:
81 */
82 void _tnl_flush_vertices( GLcontext *ctx, GLuint flags )
83 {
84 struct immediate *IM = TNL_CURRENT_IM(ctx);
85
86 if (MESA_VERBOSE & VERBOSE_IMMEDIATE)
87 _mesa_debug(ctx,
88 "_tnl_flush_vertices flags %x IM(%d) %d..%d Flag[%d]: %x\n",
89 flags, IM->id, IM->Start, IM->Count, IM->Start,
90 IM->Flag[IM->Start]);
91
92 if (IM->Flag[IM->Start]) {
93 if ((flags & FLUSH_UPDATE_CURRENT) ||
94 IM->Count > IM->Start ||
95 (IM->Flag[IM->Start] & (VERT_BIT_BEGIN | VERT_BIT_END))) {
96 _tnl_flush_immediate( ctx, IM );
97 }
98 }
99 }
100
101
102 void
103 _tnl_save_Begin( GLenum mode )
104 {
105 GET_CURRENT_CONTEXT(ctx);
106 struct immediate *IM = TNL_CURRENT_IM(ctx);
107 GLuint inflags, state;
108
109 /* _mesa_debug(ctx, "%s: before: %x\n", __FUNCTION__, IM->BeginState); */
110
111 if (mode > GL_POLYGON) {
112 _mesa_compile_error( ctx, GL_INVALID_ENUM, "_tnl_Begin" );
113 return;
114 }
115
116 if (ctx->NewState)
117 _mesa_update_state(ctx);
118
119 #if 000
120 /* if only a very few slots left, might as well flush now
121 */
122 if (IM->Count > IMM_MAXDATA-8) {
123 _tnl_flush_immediate( ctx, IM );
124 IM = TNL_CURRENT_IM(ctx);
125 }
126 #endif
127
128 if (IM->Count > IMM_MAXDATA-8) {
129 _tnl_flush_immediate( ctx, IM );
130 IM = TNL_CURRENT_IM(ctx);
131 }
132
133 /* Check for and flush buffered vertices from internal operations.
134 */
135 if (IM->SavedBeginState) {
136 _tnl_flush_immediate( ctx, IM );
137 IM = TNL_CURRENT_IM(ctx);
138 IM->BeginState = IM->SavedBeginState;
139 IM->SavedBeginState = 0;
140 }
141
142 state = IM->BeginState;
143 inflags = state & (VERT_BEGIN_0|VERT_BEGIN_1);
144 state |= inflags << 2; /* set error conditions */
145
146 if (inflags != (VERT_BEGIN_0|VERT_BEGIN_1))
147 {
148 GLuint count = IM->Count;
149 GLuint last = IM->LastPrimitive;
150
151 state |= (VERT_BEGIN_0|VERT_BEGIN_1);
152 IM->Flag[count] |= VERT_BIT_BEGIN;
153 IM->Primitive[count] = mode | PRIM_BEGIN;
154 IM->PrimitiveLength[IM->LastPrimitive] = count - IM->LastPrimitive;
155 IM->LastPrimitive = count;
156
157 /* Not quite right. Need to use the fallback '_aa_ArrayElement'
158 * when not known to be inside begin/end and arrays are
159 * unlocked.
160 */
161 if (IM->FlushElt == FLUSH_ELT_EAGER) {
162 _tnl_translate_array_elts( ctx, IM, last, count );
163 }
164 }
165
166 ctx->Driver.NeedFlush |= FLUSH_STORED_VERTICES;
167 IM->BeginState = state;
168
169 /* Update save_primitive now. Don't touch ExecPrimitive as this is
170 * updated in the replay of this cassette if we are in
171 * COMPILE_AND_EXECUTE mode.
172 */
173 if (ctx->Driver.CurrentSavePrimitive == PRIM_UNKNOWN)
174 ctx->Driver.CurrentSavePrimitive = PRIM_INSIDE_UNKNOWN_PRIM;
175 else if (ctx->Driver.CurrentSavePrimitive == PRIM_OUTSIDE_BEGIN_END)
176 ctx->Driver.CurrentSavePrimitive = mode;
177 }
178
179
180 void
181 _tnl_Begin( GLenum mode )
182 {
183 GET_CURRENT_CONTEXT(ctx);
184 TNLcontext *tnl = TNL_CONTEXT(ctx);
185 ASSERT (!ctx->CompileFlag);
186
187 if (mode > GL_POLYGON) {
188 _mesa_error( ctx, GL_INVALID_ENUM, "_tnl_Begin(0x%x)", mode );
189 return;
190 }
191
192 if (ctx->Driver.CurrentExecPrimitive != PRIM_OUTSIDE_BEGIN_END) {
193 _mesa_error( ctx, GL_INVALID_OPERATION, "_tnl_Begin" );
194 return;
195 }
196
197 if (ctx->NewState)
198 _mesa_update_state(ctx);
199
200 {
201 struct immediate *IM = TNL_CURRENT_IM(ctx);
202 if (IM->Count > IMM_MAXDATA-8) {
203 _tnl_flush_immediate( ctx, IM );
204 IM = TNL_CURRENT_IM(ctx);
205 }
206 }
207
208
209 {
210 struct immediate *IM = TNL_CURRENT_IM(ctx);
211 GLuint count = IM->Count;
212 GLuint last = IM->LastPrimitive;
213
214 if (IM->Start == IM->Count &&
215 tnl->Driver.NotifyBegin &&
216 tnl->Driver.NotifyBegin( ctx, mode )) {
217 return;
218 }
219
220 assert( (IM->SavedBeginState & (VERT_BEGIN_0|VERT_BEGIN_1)) == 0 );
221 assert( (IM->BeginState & (VERT_BEGIN_0|VERT_BEGIN_1)) == 0 );
222
223 /* Not quite right. Need to use the fallback '_aa_ArrayElement'
224 * when not known to be inside begin/end and arrays are
225 * unlocked.
226 */
227 if (IM->FlushElt == FLUSH_ELT_EAGER) {
228 _tnl_translate_array_elts( ctx, IM, last, count );
229 }
230
231 IM->Flag[count] |= VERT_BIT_BEGIN;
232 IM->Primitive[count] = mode | PRIM_BEGIN;
233 IM->PrimitiveLength[last] = count - last;
234 IM->LastPrimitive = count;
235 IM->BeginState = (VERT_BEGIN_0|VERT_BEGIN_1);
236
237 /* _mesa_debug(ctx, "%s: %x\n", __FUNCTION__, IM->BeginState); */
238
239 ctx->Driver.NeedFlush |= FLUSH_STORED_VERTICES;
240 ctx->Driver.CurrentExecPrimitive = mode;
241 }
242 }
243
244
245 /* Function which allows operations like 'glRectf' to decompose to a
246 * begin/end object and vertices without worrying about what happens
247 * with display lists.
248 */
249 GLboolean
250 _tnl_hard_begin( GLcontext *ctx, GLenum p )
251 {
252 /* _mesa_debug(ctx, "%s\n", __FUNCTION__); */
253
254 if (!ctx->CompileFlag) {
255 /* If not compiling, treat as a normal begin().
256 */
257 /* _mesa_debug(ctx, "%s: treating as glBegin\n", __FUNCTION__); */
258 glBegin( p );
259 return GL_TRUE;
260 }
261 else {
262 /* Otherwise, need to do special processing to preserve the
263 * condition that these vertices will only be replayed outside
264 * future begin/end objects.
265 */
266 struct immediate *IM = TNL_CURRENT_IM(ctx);
267
268 if (ctx->NewState)
269 _mesa_update_state(ctx);
270
271 if (IM->Count > IMM_MAXDATA-8) {
272 _tnl_flush_immediate( ctx, IM );
273 IM = TNL_CURRENT_IM(ctx);
274 }
275
276 /* A lot depends on the degree to which the display list has
277 * constrained the possible begin/end states at this point:
278 */
279 switch (IM->BeginState & (VERT_BEGIN_0|VERT_BEGIN_1)) {
280 case VERT_BEGIN_0|VERT_BEGIN_1:
281 /* This is an immediate known to be inside a begin/end object.
282 */
283 ASSERT(ctx->Driver.CurrentSavePrimitive <= GL_POLYGON);
284 IM->BeginState |= (VERT_ERROR_1|VERT_ERROR_0);
285 return GL_FALSE;
286
287 case VERT_BEGIN_0:
288 case VERT_BEGIN_1:
289 /* This is a display-list immediate in an unknown begin/end
290 * state. Assert it is empty and convert it to a 'hard' one.
291 */
292 ASSERT(IM->SavedBeginState == 0);
293 ASSERT(ctx->Driver.CurrentSavePrimitive == PRIM_UNKNOWN);
294
295 /* Push current beginstate, to be restored later. Don't worry
296 * about raising errors.
297 */
298 IM->SavedBeginState = IM->BeginState;
299
300 /* FALLTHROUGH */
301
302 case 0:
303 /* Unless we have fallen through, this is an immediate known to
304 * be outside begin/end objects.
305 */
306 ASSERT(ctx->Driver.CurrentSavePrimitive == PRIM_UNKNOWN ||
307 ctx->Driver.CurrentSavePrimitive == PRIM_OUTSIDE_BEGIN_END);
308 ASSERT (IM->FlushElt != FLUSH_ELT_EAGER);
309
310 IM->BeginState |= VERT_BEGIN_0|VERT_BEGIN_1;
311 IM->Flag[IM->Count] |= VERT_BIT_BEGIN;
312 IM->Primitive[IM->Count] = p | PRIM_BEGIN;
313 IM->PrimitiveLength[IM->LastPrimitive] = IM->Count - IM->LastPrimitive;
314 IM->LastPrimitive = IM->Count;
315
316 /* This is necessary as this immediate will not be flushed in
317 * _tnl_end() -- we leave it active, hoping to pick up more
318 * vertices before the next state change.
319 */
320 ctx->Driver.NeedFlush |= FLUSH_STORED_VERTICES;
321 return GL_TRUE;
322
323 default:
324 assert (0);
325 return GL_TRUE;
326 }
327 }
328 }
329
330
331 /* Both streams now outside begin/end.
332 *
333 * Leave SavedBeginState untouched -- attempt to gather several
334 * rects/arrays together in a single immediate struct.
335 */
336 void
337 _tnl_end_ctx( GLcontext *ctx )
338 {
339 struct immediate *IM = TNL_CURRENT_IM(ctx);
340 GLuint state = IM->BeginState;
341 GLuint inflags = (~state) & (VERT_BEGIN_0|VERT_BEGIN_1);
342
343 /* Not the case if vertices emitted without calling glBegin first:
344 */
345 /* assert( ctx->Driver.NeedFlush & FLUSH_STORED_VERTICES ); */
346
347
348 state |= inflags << 2; /* errors */
349
350 if (inflags != (VERT_BEGIN_0|VERT_BEGIN_1))
351 {
352 GLuint count = IM->Count;
353 GLuint last = IM->LastPrimitive;
354
355 state &= ~(VERT_BEGIN_0|VERT_BEGIN_1); /* update state */
356 IM->Flag[count] |= VERT_BIT_END;
357 IM->Primitive[last] |= PRIM_END;
358 IM->PrimitiveLength[last] = count - last;
359 IM->Primitive[count] = PRIM_OUTSIDE_BEGIN_END; /* removes PRIM_BEGIN
360 * flag if length == 0
361 */
362 IM->LastPrimitive = count;
363
364 if (IM->FlushElt == FLUSH_ELT_EAGER) {
365 _tnl_translate_array_elts( ctx, IM, last, count );
366 }
367 }
368
369 IM->BeginState = state;
370
371 if (!ctx->CompileFlag) {
372 if (ctx->Driver.CurrentExecPrimitive == PRIM_OUTSIDE_BEGIN_END)
373 _mesa_error( ctx, GL_INVALID_OPERATION, "_tnl_End" );
374 else
375 ctx->Driver.CurrentExecPrimitive = PRIM_OUTSIDE_BEGIN_END;
376 }
377
378 /* You can set this flag to get the old 'flush_vb on glEnd()'
379 * behaviour.
380 */
381 if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH)
382 _tnl_flush_immediate( ctx, IM );
383 }
384
385 void
386 _tnl_End(void)
387 {
388 GET_CURRENT_CONTEXT(ctx);
389
390 _tnl_end_ctx( ctx );
391
392 /* Need to keep save primitive uptodate in COMPILE and
393 * COMPILE_AND_EXEC modes, need to keep exec primitive uptodate
394 * otherwise.
395 */
396 if (ctx->CompileFlag)
397 ctx->Driver.CurrentSavePrimitive = PRIM_OUTSIDE_BEGIN_END;
398 }
399
400
401 /* If the given vertex attribute array hasn't been allocated yet,
402 * allocate it now.
403 */
404 #define CHECK_ATTRIB_ARRAY(IM, ATTR) \
405 if (!IM->Attrib[ATTR]) { \
406 IM->Attrib[ATTR] = \
407 (GLfloat (*)[4]) _mesa_malloc(IMM_SIZE * 4 * sizeof(GLfloat)); \
408 if (!IM->Attrib[ATTR]) { \
409 GET_CURRENT_CONTEXT(ctx); \
410 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glVertex/Normal/etc"); \
411 return; \
412 } \
413 }
414
415
416 #define COLOR( r, g, b, a ) \
417 { \
418 GET_IMMEDIATE; \
419 GLuint count = IM->Count; \
420 GLfloat *color; \
421 CHECK_ATTRIB_ARRAY(IM, VERT_ATTRIB_COLOR0); \
422 color = IM->Attrib[VERT_ATTRIB_COLOR0][count]; \
423 color[0] = r; \
424 color[1] = g; \
425 color[2] = b; \
426 color[3] = a; \
427 IM->Flag[count] |= VERT_BIT_COLOR0; \
428 }
429
430 static void
431 _tnl_Color3f( GLfloat red, GLfloat green, GLfloat blue )
432 {
433 COLOR( red, green, blue, 1.0 );
434 }
435
436 static void
437 _tnl_Color3ub( GLubyte red, GLubyte green, GLubyte blue )
438 {
439 COLOR(UBYTE_TO_FLOAT(red),
440 UBYTE_TO_FLOAT(green),
441 UBYTE_TO_FLOAT(blue),
442 1.0);
443 }
444
445 static void
446 _tnl_Color4f( GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha )
447 {
448 COLOR( red, green, blue, alpha );
449 }
450
451 static void
452 _tnl_Color4ub( GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha )
453 {
454 COLOR(UBYTE_TO_FLOAT(red),
455 UBYTE_TO_FLOAT(green),
456 UBYTE_TO_FLOAT(blue),
457 UBYTE_TO_FLOAT(alpha));
458 }
459
460 static void
461 _tnl_Color3fv( const GLfloat *v )
462 {
463 COLOR( v[0], v[1], v[2], 1.0 );
464 }
465
466 static void
467 _tnl_Color3ubv( const GLubyte *v )
468 {
469 COLOR(UBYTE_TO_FLOAT(v[0]),
470 UBYTE_TO_FLOAT(v[1]),
471 UBYTE_TO_FLOAT(v[2]),
472 1.0 );
473 }
474
475 static void
476 _tnl_Color4fv( const GLfloat *v )
477 {
478 COLOR( v[0], v[1], v[2], v[3] );
479 }
480
481 static void
482 _tnl_Color4ubv( const GLubyte *v)
483 {
484 COLOR(UBYTE_TO_FLOAT(v[0]),
485 UBYTE_TO_FLOAT(v[1]),
486 UBYTE_TO_FLOAT(v[2]),
487 UBYTE_TO_FLOAT(v[3]));
488 }
489
490
491
492 #define SECONDARY_COLOR( r, g, b ) \
493 { \
494 GET_IMMEDIATE; \
495 GLuint count = IM->Count; \
496 GLfloat *color; \
497 CHECK_ATTRIB_ARRAY(IM, VERT_ATTRIB_COLOR1); \
498 color = IM->Attrib[VERT_ATTRIB_COLOR1][count]; \
499 color[0] = r; \
500 color[1] = g; \
501 color[2] = b; \
502 IM->Flag[count] |= VERT_BIT_COLOR1; \
503 }
504
505 static void
506 _tnl_SecondaryColor3fEXT( GLfloat red, GLfloat green, GLfloat blue )
507 {
508 SECONDARY_COLOR( red, green, blue );
509 }
510
511 static void
512 _tnl_SecondaryColor3ubEXT( GLubyte red, GLubyte green, GLubyte blue )
513 {
514 SECONDARY_COLOR(UBYTE_TO_FLOAT(red),
515 UBYTE_TO_FLOAT(green),
516 UBYTE_TO_FLOAT(blue));
517 }
518
519 static void
520 _tnl_SecondaryColor3fvEXT( const GLfloat *v )
521 {
522 SECONDARY_COLOR( v[0], v[1], v[2] );
523 }
524
525 static void
526 _tnl_SecondaryColor3ubvEXT( const GLubyte *v )
527 {
528 SECONDARY_COLOR(UBYTE_TO_FLOAT(v[0]),
529 UBYTE_TO_FLOAT(v[1]),
530 UBYTE_TO_FLOAT(v[2]));
531 }
532
533
534 static void
535 _tnl_EdgeFlag( GLboolean flag )
536 {
537 GLuint count;
538 GET_IMMEDIATE;
539 count = IM->Count;
540 IM->EdgeFlag[count] = flag;
541 IM->Flag[count] |= VERT_BIT_EDGEFLAG;
542 }
543
544
545 static void
546 _tnl_EdgeFlagv( const GLboolean *flag )
547 {
548 GLuint count;
549 GET_IMMEDIATE;
550 count = IM->Count;
551 IM->EdgeFlag[count] = *flag;
552 IM->Flag[count] |= VERT_BIT_EDGEFLAG;
553 }
554
555
556 static void
557 _tnl_FogCoordfEXT( GLfloat f )
558 {
559 GET_IMMEDIATE;
560 GLuint count = IM->Count;
561 CHECK_ATTRIB_ARRAY(IM, VERT_ATTRIB_FOG);
562 IM->Attrib[VERT_ATTRIB_FOG][count][0] = f;
563 IM->Flag[count] |= VERT_BIT_FOG;
564 }
565
566 static void
567 _tnl_FogCoordfvEXT( const GLfloat *v )
568 {
569 GET_IMMEDIATE;
570 GLuint count = IM->Count;
571 CHECK_ATTRIB_ARRAY(IM, VERT_ATTRIB_FOG);
572 IM->Attrib[VERT_ATTRIB_FOG][count][0] = v[0];
573 IM->Flag[count] |= VERT_BIT_FOG;
574 }
575
576
577 static void
578 _tnl_Indexi( GLint c )
579 {
580 GLuint count;
581 GET_IMMEDIATE;
582 count = IM->Count;
583 IM->Index[count] = c;
584 IM->Flag[count] |= VERT_BIT_INDEX;
585 }
586
587
588 static void
589 _tnl_Indexiv( const GLint *c )
590 {
591 GLuint count;
592 GET_IMMEDIATE;
593 count = IM->Count;
594 IM->Index[count] = *c;
595 IM->Flag[count] |= VERT_BIT_INDEX;
596 }
597
598
599 #define NORMAL( x, y, z ) \
600 { \
601 GET_IMMEDIATE; \
602 GLuint count = IM->Count; \
603 GLfloat *normal; \
604 CHECK_ATTRIB_ARRAY(IM, VERT_ATTRIB_NORMAL); \
605 normal = IM->Attrib[VERT_ATTRIB_NORMAL][count]; \
606 ASSIGN_3V(normal, x,y,z); \
607 IM->Flag[count] |= VERT_BIT_NORMAL; \
608 }
609
610 #if defined(USE_IEEE_foo)
611 #define NORMALF( x, y, z ) \
612 { \
613 GET_IMMEDIATE; \
614 GLuint count = IM->Count; \
615 fi_type *normal; \
616 CHECK_ATTRIB_ARRAY(IM, VERT_ATTRIB_NORMAL); \
617 normal = (fi_type *)IM->Attrib[VERT_ATTRIB_NORMAL][count]; \
618 normal[0].i = ((fi_type *)&(x))->i; \
619 normal[1].i = ((fi_type *)&(y))->i; \
620 normal[2].i = ((fi_type *)&(z))->i; \
621 IM->Flag[count] |= VERT_BIT_NORMAL; \
622 }
623 #else
624 #define NORMALF NORMAL
625 #endif
626
627 static void
628 _tnl_Normal3f( GLfloat nx, GLfloat ny, GLfloat nz )
629 {
630 NORMALF(nx, ny, nz);
631 }
632
633
634 static void
635 _tnl_Normal3fv( const GLfloat *v )
636 {
637 NORMALF( v[0], v[1], v[2] );
638 }
639
640
641
642 #define TEXCOORD1(s) \
643 { \
644 GET_IMMEDIATE; \
645 GLuint count = IM->Count; \
646 GLfloat *tc; \
647 IM->Flag[count] |= VERT_BIT_TEX0; \
648 CHECK_ATTRIB_ARRAY(IM, VERT_ATTRIB_TEX0); \
649 tc = IM->Attrib[VERT_ATTRIB_TEX0][count]; \
650 ASSIGN_4V(tc,s,0,0,1); \
651 }
652
653 #define TEXCOORD2(s, t) \
654 { \
655 GET_IMMEDIATE; \
656 GLuint count = IM->Count; \
657 GLfloat *tc; \
658 IM->Flag[count] |= VERT_BIT_TEX0; \
659 CHECK_ATTRIB_ARRAY(IM, VERT_ATTRIB_TEX0); \
660 tc = IM->Attrib[VERT_ATTRIB_TEX0][count]; \
661 ASSIGN_4V(tc, s, t, 0, 1); \
662 }
663
664 #define TEXCOORD3(s, t, u) \
665 { \
666 GET_IMMEDIATE; \
667 GLuint count = IM->Count; \
668 GLfloat *tc; \
669 IM->Flag[count] |= VERT_BIT_TEX0; \
670 IM->TexSize |= TEX_0_SIZE_3; \
671 CHECK_ATTRIB_ARRAY(IM, VERT_ATTRIB_TEX0); \
672 tc = IM->Attrib[VERT_ATTRIB_TEX0][count]; \
673 ASSIGN_4V(tc, s, t, u, 1); \
674 }
675
676 #define TEXCOORD4(s, t, u, v) \
677 { \
678 GET_IMMEDIATE; \
679 GLuint count = IM->Count; \
680 GLfloat *tc; \
681 IM->Flag[count] |= VERT_BIT_TEX0; \
682 IM->TexSize |= TEX_0_SIZE_4; \
683 CHECK_ATTRIB_ARRAY(IM, VERT_ATTRIB_TEX0); \
684 tc = IM->Attrib[VERT_ATTRIB_TEX0][count]; \
685 ASSIGN_4V(tc, s, t, u, v); \
686 }
687
688 #if defined(USE_IEEE)
689 #define TEXCOORD2F(s, t) \
690 { \
691 GET_IMMEDIATE; \
692 GLuint count = IM->Count; \
693 fi_type *tc; \
694 IM->Flag[count] |= VERT_BIT_TEX0; \
695 CHECK_ATTRIB_ARRAY(IM, VERT_ATTRIB_TEX0); \
696 tc = (fi_type *)IM->Attrib[VERT_ATTRIB_TEX0][count]; \
697 tc[0].i = ((fi_type *)&(s))->i; \
698 tc[1].i = ((fi_type *)&(t))->i; \
699 tc[2].i = 0; \
700 tc[3].i = IEEE_ONE; \
701 }
702 #else
703 #define TEXCOORD2F TEXCOORD2
704 #endif
705
706 static void
707 _tnl_TexCoord1f( GLfloat s )
708 {
709 TEXCOORD1(s);
710 }
711
712
713 static void
714 _tnl_TexCoord2f( GLfloat s, GLfloat t )
715 {
716 TEXCOORD2F(s, t);
717 }
718
719
720 static void
721 _tnl_TexCoord3f( GLfloat s, GLfloat t, GLfloat r )
722 {
723 TEXCOORD3(s, t, r);
724 }
725
726 static void
727 _tnl_TexCoord4f( GLfloat s, GLfloat t, GLfloat r, GLfloat q )
728 {
729 TEXCOORD4(s, t, r, q)
730 }
731
732 static void
733 _tnl_TexCoord1fv( const GLfloat *v )
734 {
735 TEXCOORD1(v[0]);
736 }
737
738 static void
739 _tnl_TexCoord2fv( const GLfloat *v )
740 {
741 TEXCOORD2F(v[0], v[1]);
742 }
743
744 static void
745 _tnl_TexCoord3fv( const GLfloat *v )
746 {
747 TEXCOORD3(v[0], v[1], v[2]);
748 }
749
750 static void
751 _tnl_TexCoord4fv( const GLfloat *v )
752 {
753 TEXCOORD4(v[0], v[1], v[2], v[3]);
754 }
755
756
757
758 /* KW: Run into bad problems in vertex copying if we don't fully pad
759 * the incoming vertices.
760 */
761 #define VERTEX2(IM, x,y) \
762 { \
763 GLuint count = IM->Count++; \
764 GLfloat *dest = IM->Attrib[VERT_ATTRIB_POS][count]; \
765 IM->Flag[count] |= VERT_BIT_POS; \
766 ASSIGN_4V(dest, x, y, 0, 1); \
767 /*ASSERT(IM->Flag[IM->Count]==0);*/ \
768 if (count == IMM_MAXDATA - 1) \
769 _tnl_flush_immediate( NULL, IM ); \
770 }
771
772 #define VERTEX3(IM,x,y,z) \
773 { \
774 GLuint count = IM->Count++; \
775 GLfloat *dest = IM->Attrib[VERT_ATTRIB_POS][count]; \
776 IM->Flag[count] |= VERT_BITS_OBJ_23; \
777 ASSIGN_4V(dest, x, y, z, 1); \
778 /*ASSERT(IM->Flag[IM->Count]==0);*/ \
779 if (count == IMM_MAXDATA - 1) \
780 _tnl_flush_immediate( NULL, IM ); \
781 }
782
783 #define VERTEX4(IM, x,y,z,w) \
784 { \
785 GLuint count = IM->Count++; \
786 GLfloat *dest = IM->Attrib[VERT_ATTRIB_POS][count]; \
787 IM->Flag[count] |= VERT_BITS_OBJ_234; \
788 ASSIGN_4V(dest, x, y, z, w); \
789 if (count == IMM_MAXDATA - 1) \
790 _tnl_flush_immediate( NULL, IM ); \
791 }
792
793 #if defined(USE_IEEE)
794 #define VERTEX2F(IM, x, y) \
795 { \
796 GLuint count = IM->Count++; \
797 fi_type *dest = (fi_type *)IM->Attrib[VERT_ATTRIB_POS][count]; \
798 IM->Flag[count] |= VERT_BIT_POS; \
799 dest[0].i = ((fi_type *)&(x))->i; \
800 dest[1].i = ((fi_type *)&(y))->i; \
801 dest[2].i = 0; \
802 dest[3].i = IEEE_ONE; \
803 /*ASSERT(IM->Flag[IM->Count]==0);*/ \
804 if (count == IMM_MAXDATA - 1) \
805 _tnl_flush_immediate( NULL, IM ); \
806 }
807 #else
808 #define VERTEX2F VERTEX2
809 #endif
810
811 #if defined(USE_IEEE)
812 #define VERTEX3F(IM, x, y, z) \
813 { \
814 GLuint count = IM->Count++; \
815 fi_type *dest = (fi_type *)IM->Attrib[VERT_ATTRIB_POS][count]; \
816 IM->Flag[count] |= VERT_BITS_OBJ_23; \
817 dest[0].i = ((fi_type *)&(x))->i; \
818 dest[1].i = ((fi_type *)&(y))->i; \
819 dest[2].i = ((fi_type *)&(z))->i; \
820 dest[3].i = IEEE_ONE; \
821 /*ASSERT(IM->Flag[IM->Count]==0);*/ \
822 if (count == IMM_MAXDATA - 1) \
823 _tnl_flush_immediate( NULL, IM ); \
824 }
825 #else
826 #define VERTEX3F VERTEX3
827 #endif
828
829 #if defined(USE_IEEE)
830 #define VERTEX4F(IM, x, y, z, w) \
831 { \
832 GLuint count = IM->Count++; \
833 fi_type *dest = (fi_type *)IM->Attrib[VERT_ATTRIB_POS][count]; \
834 IM->Flag[count] |= VERT_BITS_OBJ_234; \
835 dest[0].i = ((fi_type *)&(x))->i; \
836 dest[1].i = ((fi_type *)&(y))->i; \
837 dest[2].i = ((fi_type *)&(z))->i; \
838 dest[3].i = ((fi_type *)&(w))->i; \
839 if (count == IMM_MAXDATA - 1) \
840 _tnl_flush_immediate( NULL, IM ); \
841 }
842 #else
843 #define VERTEX4F VERTEX4
844 #endif
845
846
847
848 static void
849 _tnl_Vertex2f( GLfloat x, GLfloat y )
850 {
851 GET_IMMEDIATE;
852 VERTEX2F( IM, x, y );
853 }
854
855 static void
856 _tnl_Vertex3f( GLfloat x, GLfloat y, GLfloat z )
857 {
858 GET_IMMEDIATE;
859 VERTEX3F( IM, x, y, z );
860 }
861 static void
862 _tnl_Vertex4f( GLfloat x, GLfloat y, GLfloat z, GLfloat w )
863 {
864 GET_IMMEDIATE;
865 VERTEX4F( IM, x, y, z, w );
866 }
867
868 static void
869 _tnl_Vertex2fv( const GLfloat *v )
870 {
871 GET_IMMEDIATE;
872 VERTEX2F( IM, v[0], v[1] );
873 }
874
875 static void
876 _tnl_Vertex3fv( const GLfloat *v )
877 {
878 GET_IMMEDIATE;
879 VERTEX3F( IM, v[0], v[1], v[2] );
880 }
881
882 static void
883 _tnl_Vertex4fv( const GLfloat *v )
884 {
885 GET_IMMEDIATE;
886 VERTEX4F( IM, v[0], v[1], v[2], v[3] );
887 }
888
889
890
891
892 /*
893 * GL_ARB_multitexture
894 *
895 * Note: the multitexture spec says that specifying an invalid target
896 * has undefined results and does not have to generate an error. Just
897 * don't crash. We no-op on invalid targets.
898 */
899
900 #define MAX_TARGET (GL_TEXTURE0_ARB + MAX_TEXTURE_COORD_UNITS)
901
902 #define MULTI_TEXCOORD1(target, s) \
903 { \
904 GET_IMMEDIATE; \
905 const GLuint texunit = target - GL_TEXTURE0_ARB; \
906 if (texunit < IM->MaxTextureUnits) { \
907 const GLuint count = IM->Count; \
908 GLfloat *tc; \
909 CHECK_ATTRIB_ARRAY(IM, VERT_ATTRIB_TEX0 + texunit); \
910 tc = IM->Attrib[VERT_ATTRIB_TEX0 + texunit][count]; \
911 ASSIGN_4V(tc, s, 0.0F, 0.0F, 1.0F); \
912 IM->Flag[count] |= VERT_BIT_TEX(texunit); \
913 } \
914 }
915
916 #define MULTI_TEXCOORD2(target, s, t) \
917 { \
918 GET_IMMEDIATE; \
919 const GLuint texunit = target - GL_TEXTURE0_ARB; \
920 if (texunit < IM->MaxTextureUnits) { \
921 const GLuint count = IM->Count; \
922 GLfloat *tc; \
923 CHECK_ATTRIB_ARRAY(IM, VERT_ATTRIB_TEX0 + texunit); \
924 tc = IM->Attrib[VERT_ATTRIB_TEX0 + texunit][count]; \
925 ASSIGN_4V(tc, s, t, 0.0F, 1.0F); \
926 IM->Flag[count] |= VERT_BIT_TEX(texunit); \
927 } \
928 }
929
930 #define MULTI_TEXCOORD3(target, s, t, u) \
931 { \
932 GET_IMMEDIATE; \
933 const GLuint texunit = target - GL_TEXTURE0_ARB; \
934 if (texunit < IM->MaxTextureUnits) { \
935 const GLuint count = IM->Count; \
936 GLfloat *tc; \
937 CHECK_ATTRIB_ARRAY(IM, VERT_ATTRIB_TEX0 + texunit); \
938 tc = IM->Attrib[VERT_ATTRIB_TEX0 + texunit][count]; \
939 ASSIGN_4V(tc, s, t, u, 1.0F); \
940 IM->Flag[count] |= VERT_BIT_TEX(texunit); \
941 IM->TexSize |= TEX_SIZE_3(texunit); \
942 } \
943 }
944
945 #define MULTI_TEXCOORD4(target, s, t, u, v) \
946 { \
947 GET_IMMEDIATE; \
948 const GLuint texunit = target - GL_TEXTURE0_ARB; \
949 if (texunit < IM->MaxTextureUnits) { \
950 const GLuint count = IM->Count; \
951 GLfloat *tc; \
952 CHECK_ATTRIB_ARRAY(IM, VERT_ATTRIB_TEX0 + texunit); \
953 tc = IM->Attrib[VERT_ATTRIB_TEX0 + texunit][count]; \
954 ASSIGN_4V(tc, s, t, u, v); \
955 IM->Flag[count] |= VERT_BIT_TEX(texunit); \
956 IM->TexSize |= TEX_SIZE_4(texunit); \
957 } \
958 }
959
960 #if defined(USE_IEEE)
961 #define MULTI_TEXCOORD2F(target, s, t) \
962 { \
963 GET_IMMEDIATE; \
964 const GLuint texunit = target - GL_TEXTURE0_ARB; \
965 if (texunit < IM->MaxTextureUnits) { \
966 const GLuint count = IM->Count; \
967 fi_type *tc; \
968 CHECK_ATTRIB_ARRAY(IM, VERT_ATTRIB_TEX0 + texunit); \
969 tc = (fi_type *)IM->Attrib[VERT_ATTRIB_TEX0 + texunit][count]; \
970 IM->Flag[count] |= VERT_BIT_TEX(texunit); \
971 tc[0].i = ((fi_type *)&(s))->i; \
972 tc[1].i = ((fi_type *)&(t))->i; \
973 tc[2].i = 0; \
974 tc[3].i = IEEE_ONE; \
975 } \
976 }
977 #else
978 #define MULTI_TEXCOORD2F MULTI_TEXCOORD2
979 #endif
980
981 static void
982 _tnl_MultiTexCoord1fARB(GLenum target, GLfloat s)
983 {
984 MULTI_TEXCOORD1( target, s );
985 }
986
987 static void
988 _tnl_MultiTexCoord1fvARB(GLenum target, const GLfloat *v)
989 {
990 MULTI_TEXCOORD1( target, v[0] );
991 }
992
993 static void
994 _tnl_MultiTexCoord2fARB(GLenum target, GLfloat s, GLfloat t)
995 {
996 MULTI_TEXCOORD2F( target, s, t );
997 }
998
999 static void
1000 _tnl_MultiTexCoord2fvARB(GLenum target, const GLfloat *v)
1001 {
1002 MULTI_TEXCOORD2F( target, v[0], v[1] );
1003 }
1004
1005 static void
1006 _tnl_MultiTexCoord3fARB(GLenum target, GLfloat s, GLfloat t, GLfloat r)
1007 {
1008 MULTI_TEXCOORD3( target, s, t, r );
1009 }
1010
1011 static void
1012 _tnl_MultiTexCoord3fvARB(GLenum target, const GLfloat *v)
1013 {
1014 MULTI_TEXCOORD3( target, v[0], v[1], v[2] );
1015 }
1016
1017 static void
1018 _tnl_MultiTexCoord4fARB(GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q)
1019 {
1020 MULTI_TEXCOORD4( target, s, t, r, q );
1021 }
1022
1023 static void
1024 _tnl_MultiTexCoord4fvARB(GLenum target, const GLfloat *v)
1025 {
1026 MULTI_TEXCOORD4( target, v[0], v[1], v[2], v[3] );
1027 }
1028
1029
1030
1031 /* KW: Because the eval values don't become 'current', fixup will flow
1032 * through these vertices, and then evaluation will write on top
1033 * of the fixup results.
1034 *
1035 * Note: using Obj to hold eval coord data.
1036 */
1037 #define EVALCOORD1(IM, x) \
1038 { \
1039 const GLuint count = IM->Count++; \
1040 GLfloat *dest; \
1041 CHECK_ATTRIB_ARRAY(IM, VERT_ATTRIB_POS); \
1042 dest = IM->Attrib[VERT_ATTRIB_POS][count]; \
1043 IM->Flag[count] |= VERT_BIT_EVAL_C1; \
1044 ASSIGN_4V(dest, x, 0, 0, 1); \
1045 if (count == IMM_MAXDATA-1) \
1046 _tnl_flush_immediate( NULL, IM ); \
1047 }
1048
1049 #define EVALCOORD2(IM, x, y) \
1050 { \
1051 const GLuint count = IM->Count++; \
1052 GLfloat *dest; \
1053 CHECK_ATTRIB_ARRAY(IM, VERT_ATTRIB_POS); \
1054 dest = IM->Attrib[VERT_ATTRIB_POS][count]; \
1055 IM->Flag[count] |= VERT_BIT_EVAL_C2; \
1056 ASSIGN_4V(dest, x, y, 0, 1); \
1057 if (count == IMM_MAXDATA-1) \
1058 _tnl_flush_immediate( NULL, IM ); \
1059 }
1060
1061 #define EVALPOINT1(IM, x) \
1062 { \
1063 const GLuint count = IM->Count++; \
1064 GLfloat *dest; \
1065 CHECK_ATTRIB_ARRAY(IM, VERT_ATTRIB_POS); \
1066 dest = IM->Attrib[VERT_ATTRIB_POS][count]; \
1067 IM->Flag[count] |= VERT_BIT_EVAL_P1; \
1068 ASSIGN_4V(dest, x, 0, 0, 1); \
1069 if (count == IMM_MAXDATA-1) \
1070 _tnl_flush_immediate( NULL, IM ); \
1071 }
1072
1073 #define EVALPOINT2(IM, x, y) \
1074 { \
1075 const GLuint count = IM->Count++; \
1076 GLfloat *dest; \
1077 CHECK_ATTRIB_ARRAY(IM, VERT_ATTRIB_POS); \
1078 dest = IM->Attrib[VERT_ATTRIB_POS][count]; \
1079 IM->Flag[count] |= VERT_BIT_EVAL_P2; \
1080 ASSIGN_4V(dest, x, y, 0, 1); \
1081 if (count == IMM_MAXDATA-1) \
1082 _tnl_flush_immediate( NULL, IM ); \
1083 }
1084
1085 static void
1086 _tnl_EvalCoord1f( GLfloat u )
1087 {
1088 GET_IMMEDIATE;
1089 EVALCOORD1( IM, u );
1090 }
1091
1092 static void
1093 _tnl_EvalCoord1fv( const GLfloat *u )
1094 {
1095 GET_IMMEDIATE;
1096 EVALCOORD1( IM, (GLfloat) *u );
1097 }
1098
1099 static void
1100 _tnl_EvalCoord2f( GLfloat u, GLfloat v )
1101 {
1102 GET_IMMEDIATE;
1103 EVALCOORD2( IM, u, v );
1104 }
1105
1106 static void
1107 _tnl_EvalCoord2fv( const GLfloat *u )
1108 {
1109 GET_IMMEDIATE;
1110 EVALCOORD2( IM, u[0], u[1] );
1111 }
1112
1113
1114 static void
1115 _tnl_EvalPoint1( GLint i )
1116 {
1117 GET_IMMEDIATE;
1118 EVALPOINT1( IM, (GLfloat) i );
1119 }
1120
1121
1122 static void
1123 _tnl_EvalPoint2( GLint i, GLint j )
1124 {
1125 GET_IMMEDIATE;
1126 EVALPOINT2( IM, (GLfloat) i, (GLfloat) j );
1127 }
1128
1129
1130 /* Need to use the default array-elt outside begin/end for strict
1131 * conformance.
1132 */
1133 #define ARRAY_ELT( IM, i ) \
1134 { \
1135 GLuint count = IM->Count; \
1136 IM->Elt[count] = i; \
1137 IM->Flag[count] &= IM->ArrayEltFlags; \
1138 IM->Flag[count] |= VERT_BIT_ELT; \
1139 IM->FlushElt = IM->ArrayEltFlush; \
1140 IM->Count += IM->ArrayEltIncr; \
1141 if (IM->Count == IMM_MAXDATA) \
1142 _tnl_flush_immediate( NULL, IM ); \
1143 }
1144
1145
1146 static void
1147 _tnl_ArrayElement( GLint i )
1148 {
1149 GET_IMMEDIATE;
1150 ARRAY_ELT( IM, i );
1151 }
1152
1153
1154 /* Internal functions. These are safe to use providing either:
1155 *
1156 * - It is determined that a display list is not being compiled, or
1157 * if so that these commands won't be compiled into the list (see
1158 * t_eval.c for an example).
1159 *
1160 * - _tnl_hard_begin() is used instead of _tnl_[bB]egin, and tested
1161 * for a GL_TRUE return value. See _tnl_Rectf, below.
1162 */
1163 void
1164 _tnl_eval_coord1f( GLcontext *CC, GLfloat u )
1165 {
1166 struct immediate *i = TNL_CURRENT_IM(CC);
1167 EVALCOORD1( i, u );
1168 }
1169
1170 void
1171 _tnl_eval_coord2f( GLcontext *CC, GLfloat u, GLfloat v )
1172 {
1173 struct immediate *i = TNL_CURRENT_IM(CC);
1174 EVALCOORD2( i, u, v );
1175 }
1176
1177
1178
1179
1180 /*
1181 * NV_vertex_program
1182 */
1183
1184 static void
1185 _tnl_VertexAttrib4fNV( GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w )
1186 {
1187 if (index < VERT_ATTRIB_MAX) {
1188 GET_IMMEDIATE;
1189 const GLuint count = IM->Count;
1190 GLfloat *attrib;
1191 CHECK_ATTRIB_ARRAY(IM, index);
1192 attrib = IM->Attrib[index][count];
1193 ASSIGN_4V(attrib, x, y, z, w);
1194 IM->Flag[count] |= (1 << index);
1195 if (index == 0) {
1196 IM->Count++;
1197 if (count == IMM_MAXDATA - 1)
1198 _tnl_flush_immediate( NULL, IM );
1199 }
1200 }
1201 else {
1202 GET_CURRENT_CONTEXT(ctx);
1203 _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribNV(index > 15)");
1204 }
1205 }
1206
1207 static void
1208 _tnl_VertexAttrib4fvNV( GLuint index, const GLfloat *v )
1209 {
1210 if (index < VERT_ATTRIB_MAX) {
1211 GET_IMMEDIATE;
1212 const GLuint count = IM->Count;
1213 GLfloat *attrib;
1214 CHECK_ATTRIB_ARRAY(IM, index);
1215 attrib = IM->Attrib[index][count];
1216 COPY_4V(attrib, v);
1217 IM->Flag[count] |= (1 << index);
1218 if (index == 0) {
1219 IM->Count++;
1220 if (count == IMM_MAXDATA - 1)
1221 _tnl_flush_immediate( NULL, IM );
1222 }
1223 }
1224 else {
1225 GET_CURRENT_CONTEXT(ctx);
1226 _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribNV(index > 15)");
1227 }
1228 }
1229
1230
1231 /* Execute a glRectf() function. _tnl_hard_begin() ensures the check
1232 * on outside_begin_end is executed even in compiled lists. These
1233 * vertices can now participate in the same immediate as regular ones,
1234 * even in most display lists.
1235 */
1236 static void
1237 _tnl_Rectf( GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2 )
1238 {
1239 GET_CURRENT_CONTEXT(ctx);
1240
1241 if (_tnl_hard_begin( ctx, GL_QUADS )) {
1242 glVertex2f( x1, y1 );
1243 glVertex2f( x2, y1 );
1244 glVertex2f( x2, y2 );
1245 glVertex2f( x1, y2 );
1246 glEnd();
1247 }
1248 }
1249
1250 static void
1251 _tnl_Materialfv( GLenum face, GLenum pname, const GLfloat *params )
1252 {
1253 GET_CURRENT_CONTEXT(ctx);
1254 TNLcontext *tnl = TNL_CONTEXT(ctx);
1255 struct immediate *IM = TNL_CURRENT_IM(ctx);
1256 GLuint count = IM->Count;
1257 struct gl_material *mat;
1258 GLuint bitmask = _mesa_material_bitmask(ctx, face, pname, ~0, "Materialfv");
1259 int i, nr;
1260
1261 if (bitmask == 0)
1262 return;
1263
1264 if (MESA_VERBOSE & VERBOSE_API)
1265 _mesa_debug(ctx, "_tnl_Materialfv\n");
1266
1267 if (tnl->IsolateMaterials &&
1268 !(IM->BeginState & VERT_BEGIN_1)) /* heuristic */
1269 {
1270 _tnl_flush_immediate( ctx, IM );
1271 IM = TNL_CURRENT_IM(ctx);
1272 count = IM->Count;
1273 }
1274
1275 if (!(IM->Flag[count] & VERT_BIT_MATERIAL)) {
1276 if (!IM->Material) {
1277 IM->Material = (struct gl_material *)
1278 MALLOC( sizeof(struct gl_material) * IMM_SIZE );
1279 IM->MaterialMask = (GLuint *) MALLOC( sizeof(GLuint) * IMM_SIZE );
1280 IM->MaterialMask[IM->LastMaterial] = 0;
1281 }
1282 else if (IM->MaterialOrMask & ~bitmask) {
1283 _mesa_copy_materials( &IM->Material[count],
1284 &IM->Material[IM->LastMaterial],
1285 IM->MaterialOrMask & ~bitmask );
1286 }
1287
1288 IM->Flag[count] |= VERT_BIT_MATERIAL;
1289 IM->MaterialMask[count] = 0;
1290 IM->MaterialAndMask &= IM->MaterialMask[IM->LastMaterial];
1291 IM->LastMaterial = count;
1292 }
1293
1294 IM->MaterialOrMask |= bitmask;
1295 IM->MaterialMask[count] |= bitmask;
1296 mat = &IM->Material[count];
1297
1298 switch (face) {
1299 case GL_SHININESS: nr = 1; break;
1300 case GL_COLOR_INDEXES: nr = 3; break;
1301 default: nr = 4 ; break;
1302 }
1303
1304 for (i = 0 ; i < MAT_ATTRIB_MAX ; i++)
1305 if (bitmask & (1<<i))
1306 COPY_SZ_4V( mat->Attrib[i], nr, params );
1307
1308 if (tnl->IsolateMaterials &&
1309 !(IM->BeginState & VERT_BEGIN_1)) /* heuristic */
1310 {
1311 _tnl_flush_immediate( ctx, IM );
1312 }
1313 }
1314
1315 void _tnl_imm_vtxfmt_init( GLcontext *ctx )
1316 {
1317 GLvertexformat *vfmt = &(TNL_CONTEXT(ctx)->vtxfmt);
1318
1319 /* All begin/end operations are handled by this vertex format:
1320 */
1321 vfmt->ArrayElement = _tnl_ArrayElement;
1322 vfmt->Begin = _tnl_Begin;
1323 vfmt->Color3f = _tnl_Color3f;
1324 vfmt->Color3fv = _tnl_Color3fv;
1325 vfmt->Color3ub = _tnl_Color3ub;
1326 vfmt->Color3ubv = _tnl_Color3ubv;
1327 vfmt->Color4f = _tnl_Color4f;
1328 vfmt->Color4fv = _tnl_Color4fv;
1329 vfmt->Color4ub = _tnl_Color4ub;
1330 vfmt->Color4ubv = _tnl_Color4ubv;
1331 vfmt->EdgeFlag = _tnl_EdgeFlag;
1332 vfmt->EdgeFlagv = _tnl_EdgeFlagv;
1333 vfmt->End = _tnl_End;
1334 vfmt->EvalCoord1f = _tnl_EvalCoord1f;
1335 vfmt->EvalCoord1fv = _tnl_EvalCoord1fv;
1336 vfmt->EvalCoord2f = _tnl_EvalCoord2f;
1337 vfmt->EvalCoord2fv = _tnl_EvalCoord2fv;
1338 vfmt->EvalPoint1 = _tnl_EvalPoint1;
1339 vfmt->EvalPoint2 = _tnl_EvalPoint2;
1340 vfmt->FogCoordfEXT = _tnl_FogCoordfEXT;
1341 vfmt->FogCoordfvEXT = _tnl_FogCoordfvEXT;
1342 vfmt->Indexi = _tnl_Indexi;
1343 vfmt->Indexiv = _tnl_Indexiv;
1344 vfmt->Materialfv = _tnl_Materialfv;
1345 vfmt->MultiTexCoord1fARB = _tnl_MultiTexCoord1fARB;
1346 vfmt->MultiTexCoord1fvARB = _tnl_MultiTexCoord1fvARB;
1347 vfmt->MultiTexCoord2fARB = _tnl_MultiTexCoord2fARB;
1348 vfmt->MultiTexCoord2fvARB = _tnl_MultiTexCoord2fvARB;
1349 vfmt->MultiTexCoord3fARB = _tnl_MultiTexCoord3fARB;
1350 vfmt->MultiTexCoord3fvARB = _tnl_MultiTexCoord3fvARB;
1351 vfmt->MultiTexCoord4fARB = _tnl_MultiTexCoord4fARB;
1352 vfmt->MultiTexCoord4fvARB = _tnl_MultiTexCoord4fvARB;
1353 vfmt->Normal3f = _tnl_Normal3f;
1354 vfmt->Normal3fv = _tnl_Normal3fv;
1355 vfmt->SecondaryColor3fEXT = _tnl_SecondaryColor3fEXT;
1356 vfmt->SecondaryColor3fvEXT = _tnl_SecondaryColor3fvEXT;
1357 vfmt->SecondaryColor3ubEXT = _tnl_SecondaryColor3ubEXT;
1358 vfmt->SecondaryColor3ubvEXT = _tnl_SecondaryColor3ubvEXT;
1359 vfmt->TexCoord1f = _tnl_TexCoord1f;
1360 vfmt->TexCoord1fv = _tnl_TexCoord1fv;
1361 vfmt->TexCoord2f = _tnl_TexCoord2f;
1362 vfmt->TexCoord2fv = _tnl_TexCoord2fv;
1363 vfmt->TexCoord3f = _tnl_TexCoord3f;
1364 vfmt->TexCoord3fv = _tnl_TexCoord3fv;
1365 vfmt->TexCoord4f = _tnl_TexCoord4f;
1366 vfmt->TexCoord4fv = _tnl_TexCoord4fv;
1367 vfmt->Vertex2f = _tnl_Vertex2f;
1368 vfmt->Vertex2fv = _tnl_Vertex2fv;
1369 vfmt->Vertex3f = _tnl_Vertex3f;
1370 vfmt->Vertex3fv = _tnl_Vertex3fv;
1371 vfmt->Vertex4f = _tnl_Vertex4f;
1372 vfmt->Vertex4fv = _tnl_Vertex4fv;
1373 vfmt->VertexAttrib4fNV = _tnl_VertexAttrib4fNV;
1374 vfmt->VertexAttrib4fvNV = _tnl_VertexAttrib4fvNV;
1375
1376 /* Outside begin/end functions (from t_varray.c, t_eval.c, ...):
1377 */
1378 vfmt->Rectf = _tnl_Rectf;
1379
1380 /* Just use the core function:
1381 */
1382 vfmt->CallList = _mesa_CallList;
1383
1384 vfmt->prefer_float_colors = GL_FALSE;
1385 }