2 * Mesa 3-D graphics library
5 * Copyright (C) 1999-2002 Brian Paul All Rights Reserved.
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:
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
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.
25 * Keith Whitwell <keith@tungstengraphics.com>
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"
48 /* A cassette is full or flushed on a statechange.
50 void _tnl_flush_immediate( GLcontext
*ctx
, struct immediate
*IM
)
53 /* We were called by glVertex, glEvalCoord, glArrayElement, etc.
54 * The current context is corresponds to the IM structure.
56 GET_CURRENT_CONTEXT(context
);
60 if (MESA_VERBOSE
& VERBOSE_IMMEDIATE
)
61 _mesa_debug(ctx
, "_tnl_flush_immediate IM: %d compiling: %d\n",
62 IM
->id
, ctx
->CompileFlag
);
64 if (IM
->FlushElt
== FLUSH_ELT_EAGER
) {
65 _tnl_translate_array_elts( ctx
, IM
, IM
->LastPrimitive
, IM
->Count
);
68 /* Mark the last primitive:
70 IM
->PrimitiveLength
[IM
->LastPrimitive
] = IM
->Count
- IM
->LastPrimitive
;
71 IM
->Primitive
[IM
->LastPrimitive
] |= PRIM_LAST
;
74 _tnl_compile_cassette( ctx
, IM
);
76 _tnl_execute_cassette( ctx
, IM
);
80 /* Hook for ctx->Driver.FlushVertices:
82 void _tnl_flush_vertices( GLcontext
*ctx
, GLuint flags
)
84 struct immediate
*IM
= TNL_CURRENT_IM(ctx
);
86 if (MESA_VERBOSE
& VERBOSE_IMMEDIATE
)
88 "_tnl_flush_vertices flags %x IM(%d) %d..%d Flag[%d]: %x\n",
89 flags
, IM
->id
, IM
->Start
, IM
->Count
, IM
->Start
,
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
);
103 _tnl_save_Begin( GLenum mode
)
105 GET_CURRENT_CONTEXT(ctx
);
106 struct immediate
*IM
= TNL_CURRENT_IM(ctx
);
107 GLuint inflags
, state
;
109 /* _mesa_debug(ctx, "%s: before: %x\n", __FUNCTION__, IM->BeginState); */
111 if (mode
> GL_POLYGON
) {
112 _mesa_compile_error( ctx
, GL_INVALID_ENUM
, "_tnl_Begin" );
117 _mesa_update_state(ctx
);
120 /* if only a very few slots left, might as well flush now
122 if (IM
->Count
> IMM_MAXDATA
-8) {
123 _tnl_flush_immediate( ctx
, IM
);
124 IM
= TNL_CURRENT_IM(ctx
);
128 if (IM
->Count
> IMM_MAXDATA
-8) {
129 _tnl_flush_immediate( ctx
, IM
);
130 IM
= TNL_CURRENT_IM(ctx
);
133 /* Check for and flush buffered vertices from internal operations.
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;
142 state
= IM
->BeginState
;
143 inflags
= state
& (VERT_BEGIN_0
|VERT_BEGIN_1
);
144 state
|= inflags
<< 2; /* set error conditions */
146 if (inflags
!= (VERT_BEGIN_0
|VERT_BEGIN_1
))
148 GLuint count
= IM
->Count
;
149 GLuint last
= IM
->LastPrimitive
;
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
;
157 /* Not quite right. Need to use the fallback '_aa_ArrayElement'
158 * when not known to be inside begin/end and arrays are
161 if (IM
->FlushElt
== FLUSH_ELT_EAGER
) {
162 _tnl_translate_array_elts( ctx
, IM
, last
, count
);
166 ctx
->Driver
.NeedFlush
|= FLUSH_STORED_VERTICES
;
167 IM
->BeginState
= state
;
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.
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
;
181 _tnl_Begin( GLenum mode
)
183 GET_CURRENT_CONTEXT(ctx
);
184 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
185 ASSERT (!ctx
->CompileFlag
);
187 if (mode
> GL_POLYGON
) {
188 _mesa_error( ctx
, GL_INVALID_ENUM
, "_tnl_Begin(0x%x)", mode
);
192 if (ctx
->Driver
.CurrentExecPrimitive
!= PRIM_OUTSIDE_BEGIN_END
) {
193 _mesa_error( ctx
, GL_INVALID_OPERATION
, "_tnl_Begin" );
198 _mesa_update_state(ctx
);
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
);
210 struct immediate
*IM
= TNL_CURRENT_IM(ctx
);
211 GLuint count
= IM
->Count
;
212 GLuint last
= IM
->LastPrimitive
;
214 if (IM
->Start
== IM
->Count
&&
215 tnl
->Driver
.NotifyBegin
&&
216 tnl
->Driver
.NotifyBegin( ctx
, mode
)) {
220 assert( (IM
->SavedBeginState
& (VERT_BEGIN_0
|VERT_BEGIN_1
)) == 0 );
221 assert( (IM
->BeginState
& (VERT_BEGIN_0
|VERT_BEGIN_1
)) == 0 );
223 /* Not quite right. Need to use the fallback '_aa_ArrayElement'
224 * when not known to be inside begin/end and arrays are
227 if (IM
->FlushElt
== FLUSH_ELT_EAGER
) {
228 _tnl_translate_array_elts( ctx
, IM
, last
, count
);
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
);
237 /* _mesa_debug(ctx, "%s: %x\n", __FUNCTION__, IM->BeginState); */
239 ctx
->Driver
.NeedFlush
|= FLUSH_STORED_VERTICES
;
240 ctx
->Driver
.CurrentExecPrimitive
= mode
;
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.
250 _tnl_hard_begin( GLcontext
*ctx
, GLenum p
)
252 /* _mesa_debug(ctx, "%s\n", __FUNCTION__); */
254 if (!ctx
->CompileFlag
) {
255 /* If not compiling, treat as a normal begin().
257 /* _mesa_debug(ctx, "%s: treating as glBegin\n", __FUNCTION__); */
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.
266 struct immediate
*IM
= TNL_CURRENT_IM(ctx
);
269 _mesa_update_state(ctx
);
271 if (IM
->Count
> IMM_MAXDATA
-8) {
272 _tnl_flush_immediate( ctx
, IM
);
273 IM
= TNL_CURRENT_IM(ctx
);
276 /* A lot depends on the degree to which the display list has
277 * constrained the possible begin/end states at this point:
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.
283 ASSERT(ctx
->Driver
.CurrentSavePrimitive
<= GL_POLYGON
);
284 IM
->BeginState
|= (VERT_ERROR_1
|VERT_ERROR_0
);
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.
292 ASSERT(IM
->SavedBeginState
== 0);
293 ASSERT(ctx
->Driver
.CurrentSavePrimitive
== PRIM_UNKNOWN
);
295 /* Push current beginstate, to be restored later. Don't worry
296 * about raising errors.
298 IM
->SavedBeginState
= IM
->BeginState
;
303 /* Unless we have fallen through, this is an immediate known to
304 * be outside begin/end objects.
306 ASSERT(ctx
->Driver
.CurrentSavePrimitive
== PRIM_UNKNOWN
||
307 ctx
->Driver
.CurrentSavePrimitive
== PRIM_OUTSIDE_BEGIN_END
);
308 ASSERT (IM
->FlushElt
!= FLUSH_ELT_EAGER
);
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
;
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.
320 ctx
->Driver
.NeedFlush
|= FLUSH_STORED_VERTICES
;
331 /* Both streams now outside begin/end.
333 * Leave SavedBeginState untouched -- attempt to gather several
334 * rects/arrays together in a single immediate struct.
337 _tnl_end_ctx( GLcontext
*ctx
)
339 struct immediate
*IM
= TNL_CURRENT_IM(ctx
);
340 GLuint state
= IM
->BeginState
;
341 GLuint inflags
= (~state
) & (VERT_BEGIN_0
|VERT_BEGIN_1
);
343 /* Not the case if vertices emitted without calling glBegin first:
345 /* assert( ctx->Driver.NeedFlush & FLUSH_STORED_VERTICES ); */
348 state
|= inflags
<< 2; /* errors */
350 if (inflags
!= (VERT_BEGIN_0
|VERT_BEGIN_1
))
352 GLuint count
= IM
->Count
;
353 GLuint last
= IM
->LastPrimitive
;
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
362 IM
->LastPrimitive
= count
;
364 if (IM
->FlushElt
== FLUSH_ELT_EAGER
) {
365 _tnl_translate_array_elts( ctx
, IM
, last
, count
);
369 IM
->BeginState
= state
;
371 if (!ctx
->CompileFlag
) {
372 if (ctx
->Driver
.CurrentExecPrimitive
== PRIM_OUTSIDE_BEGIN_END
)
373 _mesa_error( ctx
, GL_INVALID_OPERATION
, "_tnl_End" );
375 ctx
->Driver
.CurrentExecPrimitive
= PRIM_OUTSIDE_BEGIN_END
;
378 /* You can set this flag to get the old 'flush_vb on glEnd()'
381 if (MESA_DEBUG_FLAGS
& DEBUG_ALWAYS_FLUSH
)
382 _tnl_flush_immediate( ctx
, IM
);
388 GET_CURRENT_CONTEXT(ctx
);
392 /* Need to keep save primitive uptodate in COMPILE and
393 * COMPILE_AND_EXEC modes, need to keep exec primitive uptodate
396 if (ctx
->CompileFlag
)
397 ctx
->Driver
.CurrentSavePrimitive
= PRIM_OUTSIDE_BEGIN_END
;
401 /* If the given vertex attribute array hasn't been allocated yet,
404 #define CHECK_ATTRIB_ARRAY(IM, ATTR) \
405 if (!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"); \
416 #define COLOR( r, g, b, a ) \
419 GLuint count = IM->Count; \
421 CHECK_ATTRIB_ARRAY(IM, VERT_ATTRIB_COLOR0); \
422 color = IM->Attrib[VERT_ATTRIB_COLOR0][count]; \
427 IM->Flag[count] |= VERT_BIT_COLOR0; \
431 _tnl_Color3f( GLfloat red
, GLfloat green
, GLfloat blue
)
433 COLOR( red
, green
, blue
, 1.0 );
437 _tnl_Color3ub( GLubyte red
, GLubyte green
, GLubyte blue
)
439 COLOR(UBYTE_TO_FLOAT(red
),
440 UBYTE_TO_FLOAT(green
),
441 UBYTE_TO_FLOAT(blue
),
446 _tnl_Color4f( GLfloat red
, GLfloat green
, GLfloat blue
, GLfloat alpha
)
448 COLOR( red
, green
, blue
, alpha
);
452 _tnl_Color4ub( GLubyte red
, GLubyte green
, GLubyte blue
, GLubyte alpha
)
454 COLOR(UBYTE_TO_FLOAT(red
),
455 UBYTE_TO_FLOAT(green
),
456 UBYTE_TO_FLOAT(blue
),
457 UBYTE_TO_FLOAT(alpha
));
461 _tnl_Color3fv( const GLfloat
*v
)
463 COLOR( v
[0], v
[1], v
[2], 1.0 );
467 _tnl_Color3ubv( const GLubyte
*v
)
469 COLOR(UBYTE_TO_FLOAT(v
[0]),
470 UBYTE_TO_FLOAT(v
[1]),
471 UBYTE_TO_FLOAT(v
[2]),
476 _tnl_Color4fv( const GLfloat
*v
)
478 COLOR( v
[0], v
[1], v
[2], v
[3] );
482 _tnl_Color4ubv( const GLubyte
*v
)
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]));
492 #define SECONDARY_COLOR( r, g, b ) \
495 GLuint count = IM->Count; \
497 CHECK_ATTRIB_ARRAY(IM, VERT_ATTRIB_COLOR1); \
498 color = IM->Attrib[VERT_ATTRIB_COLOR1][count]; \
502 IM->Flag[count] |= VERT_BIT_COLOR1; \
506 _tnl_SecondaryColor3fEXT( GLfloat red
, GLfloat green
, GLfloat blue
)
508 SECONDARY_COLOR( red
, green
, blue
);
512 _tnl_SecondaryColor3ubEXT( GLubyte red
, GLubyte green
, GLubyte blue
)
514 SECONDARY_COLOR(UBYTE_TO_FLOAT(red
),
515 UBYTE_TO_FLOAT(green
),
516 UBYTE_TO_FLOAT(blue
));
520 _tnl_SecondaryColor3fvEXT( const GLfloat
*v
)
522 SECONDARY_COLOR( v
[0], v
[1], v
[2] );
526 _tnl_SecondaryColor3ubvEXT( const GLubyte
*v
)
528 SECONDARY_COLOR(UBYTE_TO_FLOAT(v
[0]),
529 UBYTE_TO_FLOAT(v
[1]),
530 UBYTE_TO_FLOAT(v
[2]));
535 _tnl_EdgeFlag( GLboolean flag
)
540 IM
->EdgeFlag
[count
] = flag
;
541 IM
->Flag
[count
] |= VERT_BIT_EDGEFLAG
;
546 _tnl_EdgeFlagv( const GLboolean
*flag
)
551 IM
->EdgeFlag
[count
] = *flag
;
552 IM
->Flag
[count
] |= VERT_BIT_EDGEFLAG
;
557 _tnl_FogCoordfEXT( GLfloat f
)
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
;
567 _tnl_FogCoordfvEXT( const GLfloat
*v
)
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
;
578 _tnl_Indexi( GLint c
)
583 IM
->Index
[count
] = c
;
584 IM
->Flag
[count
] |= VERT_BIT_INDEX
;
589 _tnl_Indexiv( const GLint
*c
)
594 IM
->Index
[count
] = *c
;
595 IM
->Flag
[count
] |= VERT_BIT_INDEX
;
599 #define NORMAL( x, y, z ) \
602 GLuint count = IM->Count; \
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; \
610 #if defined(USE_IEEE_foo)
611 #define NORMALF( x, y, z ) \
614 GLuint count = IM->Count; \
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; \
624 #define NORMALF NORMAL
628 _tnl_Normal3f( GLfloat nx
, GLfloat ny
, GLfloat nz
)
635 _tnl_Normal3fv( const GLfloat
*v
)
637 NORMALF( v
[0], v
[1], v
[2] );
642 #define TEXCOORD1(s) \
645 GLuint count = IM->Count; \
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); \
653 #define TEXCOORD2(s, t) \
656 GLuint count = IM->Count; \
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); \
664 #define TEXCOORD3(s, t, u) \
667 GLuint count = IM->Count; \
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); \
676 #define TEXCOORD4(s, t, u, v) \
679 GLuint count = IM->Count; \
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); \
688 #if defined(USE_IEEE)
689 #define TEXCOORD2F(s, t) \
692 GLuint count = IM->Count; \
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; \
700 tc[3].i = IEEE_ONE; \
703 #define TEXCOORD2F TEXCOORD2
707 _tnl_TexCoord1f( GLfloat s
)
714 _tnl_TexCoord2f( GLfloat s
, GLfloat t
)
721 _tnl_TexCoord3f( GLfloat s
, GLfloat t
, GLfloat r
)
727 _tnl_TexCoord4f( GLfloat s
, GLfloat t
, GLfloat r
, GLfloat q
)
729 TEXCOORD4(s
, t
, r
, q
)
733 _tnl_TexCoord1fv( const GLfloat
*v
)
739 _tnl_TexCoord2fv( const GLfloat
*v
)
741 TEXCOORD2F(v
[0], v
[1]);
745 _tnl_TexCoord3fv( const GLfloat
*v
)
747 TEXCOORD3(v
[0], v
[1], v
[2]);
751 _tnl_TexCoord4fv( const GLfloat
*v
)
753 TEXCOORD4(v
[0], v
[1], v
[2], v
[3]);
758 /* KW: Run into bad problems in vertex copying if we don't fully pad
759 * the incoming vertices.
761 #define VERTEX2(IM, x,y) \
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 ); \
772 #define VERTEX3(IM,x,y,z) \
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 ); \
783 #define VERTEX4(IM, x,y,z,w) \
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 ); \
793 #if defined(USE_IEEE)
794 #define VERTEX2F(IM, x, y) \
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; \
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 ); \
808 #define VERTEX2F VERTEX2
811 #if defined(USE_IEEE)
812 #define VERTEX3F(IM, x, y, z) \
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 ); \
826 #define VERTEX3F VERTEX3
829 #if defined(USE_IEEE)
830 #define VERTEX4F(IM, x, y, z, w) \
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 ); \
843 #define VERTEX4F VERTEX4
849 _tnl_Vertex2f( GLfloat x
, GLfloat y
)
852 VERTEX2F( IM
, x
, y
);
856 _tnl_Vertex3f( GLfloat x
, GLfloat y
, GLfloat z
)
859 VERTEX3F( IM
, x
, y
, z
);
862 _tnl_Vertex4f( GLfloat x
, GLfloat y
, GLfloat z
, GLfloat w
)
865 VERTEX4F( IM
, x
, y
, z
, w
);
869 _tnl_Vertex2fv( const GLfloat
*v
)
872 VERTEX2F( IM
, v
[0], v
[1] );
876 _tnl_Vertex3fv( const GLfloat
*v
)
879 VERTEX3F( IM
, v
[0], v
[1], v
[2] );
883 _tnl_Vertex4fv( const GLfloat
*v
)
886 VERTEX4F( IM
, v
[0], v
[1], v
[2], v
[3] );
893 * GL_ARB_multitexture
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.
900 #define MAX_TARGET (GL_TEXTURE0_ARB + MAX_TEXTURE_COORD_UNITS)
902 #define MULTI_TEXCOORD1(target, s) \
905 const GLuint texunit = target - GL_TEXTURE0_ARB; \
906 if (texunit < IM->MaxTextureUnits) { \
907 const GLuint count = IM->Count; \
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); \
916 #define MULTI_TEXCOORD2(target, s, t) \
919 const GLuint texunit = target - GL_TEXTURE0_ARB; \
920 if (texunit < IM->MaxTextureUnits) { \
921 const GLuint count = IM->Count; \
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); \
930 #define MULTI_TEXCOORD3(target, s, t, u) \
933 const GLuint texunit = target - GL_TEXTURE0_ARB; \
934 if (texunit < IM->MaxTextureUnits) { \
935 const GLuint count = IM->Count; \
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); \
945 #define MULTI_TEXCOORD4(target, s, t, u, v) \
948 const GLuint texunit = target - GL_TEXTURE0_ARB; \
949 if (texunit < IM->MaxTextureUnits) { \
950 const GLuint count = IM->Count; \
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); \
960 #if defined(USE_IEEE)
961 #define MULTI_TEXCOORD2F(target, s, t) \
964 const GLuint texunit = target - GL_TEXTURE0_ARB; \
965 if (texunit < IM->MaxTextureUnits) { \
966 const GLuint count = IM->Count; \
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; \
974 tc[3].i = IEEE_ONE; \
978 #define MULTI_TEXCOORD2F MULTI_TEXCOORD2
982 _tnl_MultiTexCoord1fARB(GLenum target
, GLfloat s
)
984 MULTI_TEXCOORD1( target
, s
);
988 _tnl_MultiTexCoord1fvARB(GLenum target
, const GLfloat
*v
)
990 MULTI_TEXCOORD1( target
, v
[0] );
994 _tnl_MultiTexCoord2fARB(GLenum target
, GLfloat s
, GLfloat t
)
996 MULTI_TEXCOORD2F( target
, s
, t
);
1000 _tnl_MultiTexCoord2fvARB(GLenum target
, const GLfloat
*v
)
1002 MULTI_TEXCOORD2F( target
, v
[0], v
[1] );
1006 _tnl_MultiTexCoord3fARB(GLenum target
, GLfloat s
, GLfloat t
, GLfloat r
)
1008 MULTI_TEXCOORD3( target
, s
, t
, r
);
1012 _tnl_MultiTexCoord3fvARB(GLenum target
, const GLfloat
*v
)
1014 MULTI_TEXCOORD3( target
, v
[0], v
[1], v
[2] );
1018 _tnl_MultiTexCoord4fARB(GLenum target
, GLfloat s
, GLfloat t
, GLfloat r
, GLfloat q
)
1020 MULTI_TEXCOORD4( target
, s
, t
, r
, q
);
1024 _tnl_MultiTexCoord4fvARB(GLenum target
, const GLfloat
*v
)
1026 MULTI_TEXCOORD4( target
, v
[0], v
[1], v
[2], v
[3] );
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.
1035 * Note: using Obj to hold eval coord data.
1037 #define EVALCOORD1(IM, x) \
1039 const GLuint count = IM->Count++; \
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 ); \
1049 #define EVALCOORD2(IM, x, y) \
1051 const GLuint count = IM->Count++; \
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 ); \
1061 #define EVALPOINT1(IM, x) \
1063 const GLuint count = IM->Count++; \
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 ); \
1073 #define EVALPOINT2(IM, x, y) \
1075 const GLuint count = IM->Count++; \
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 ); \
1086 _tnl_EvalCoord1f( GLfloat u
)
1089 EVALCOORD1( IM
, u
);
1093 _tnl_EvalCoord1fv( const GLfloat
*u
)
1096 EVALCOORD1( IM
, (GLfloat
) *u
);
1100 _tnl_EvalCoord2f( GLfloat u
, GLfloat v
)
1103 EVALCOORD2( IM
, u
, v
);
1107 _tnl_EvalCoord2fv( const GLfloat
*u
)
1110 EVALCOORD2( IM
, u
[0], u
[1] );
1115 _tnl_EvalPoint1( GLint i
)
1118 EVALPOINT1( IM
, (GLfloat
) i
);
1123 _tnl_EvalPoint2( GLint i
, GLint j
)
1126 EVALPOINT2( IM
, (GLfloat
) i
, (GLfloat
) j
);
1130 /* Need to use the default array-elt outside begin/end for strict
1133 #define ARRAY_ELT( IM, i ) \
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 ); \
1147 _tnl_ArrayElement( GLint i
)
1154 /* Internal functions. These are safe to use providing either:
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).
1160 * - _tnl_hard_begin() is used instead of _tnl_[bB]egin, and tested
1161 * for a GL_TRUE return value. See _tnl_Rectf, below.
1164 _tnl_eval_coord1f( GLcontext
*CC
, GLfloat u
)
1166 struct immediate
*i
= TNL_CURRENT_IM(CC
);
1171 _tnl_eval_coord2f( GLcontext
*CC
, GLfloat u
, GLfloat v
)
1173 struct immediate
*i
= TNL_CURRENT_IM(CC
);
1174 EVALCOORD2( i
, u
, v
);
1185 _tnl_VertexAttrib4fNV( GLuint index
, GLfloat x
, GLfloat y
, GLfloat z
, GLfloat w
)
1187 if (index
< VERT_ATTRIB_MAX
) {
1189 const GLuint count
= IM
->Count
;
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
);
1197 if (count
== IMM_MAXDATA
- 1)
1198 _tnl_flush_immediate( NULL
, IM
);
1202 GET_CURRENT_CONTEXT(ctx
);
1203 _mesa_error(ctx
, GL_INVALID_VALUE
, "glVertexAttribNV(index > 15)");
1208 _tnl_VertexAttrib4fvNV( GLuint index
, const GLfloat
*v
)
1210 if (index
< VERT_ATTRIB_MAX
) {
1212 const GLuint count
= IM
->Count
;
1214 CHECK_ATTRIB_ARRAY(IM
, index
);
1215 attrib
= IM
->Attrib
[index
][count
];
1217 IM
->Flag
[count
] |= (1 << index
);
1220 if (count
== IMM_MAXDATA
- 1)
1221 _tnl_flush_immediate( NULL
, IM
);
1225 GET_CURRENT_CONTEXT(ctx
);
1226 _mesa_error(ctx
, GL_INVALID_VALUE
, "glVertexAttribNV(index > 15)");
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.
1237 _tnl_Rectf( GLfloat x1
, GLfloat y1
, GLfloat x2
, GLfloat y2
)
1239 GET_CURRENT_CONTEXT(ctx
);
1241 if (_tnl_hard_begin( ctx
, GL_QUADS
)) {
1242 glVertex2f( x1
, y1
);
1243 glVertex2f( x2
, y1
);
1244 glVertex2f( x2
, y2
);
1245 glVertex2f( x1
, y2
);
1251 _tnl_Materialfv( GLenum face
, GLenum pname
, const GLfloat
*params
)
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");
1264 if (MESA_VERBOSE
& VERBOSE_API
)
1265 _mesa_debug(ctx
, "_tnl_Materialfv\n");
1267 if (tnl
->IsolateMaterials
&&
1268 !(IM
->BeginState
& VERT_BEGIN_1
)) /* heuristic */
1270 _tnl_flush_immediate( ctx
, IM
);
1271 IM
= TNL_CURRENT_IM(ctx
);
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;
1282 else if (IM
->MaterialOrMask
& ~bitmask
) {
1283 _mesa_copy_materials( &IM
->Material
[count
],
1284 &IM
->Material
[IM
->LastMaterial
],
1285 IM
->MaterialOrMask
& ~bitmask
);
1288 IM
->Flag
[count
] |= VERT_BIT_MATERIAL
;
1289 IM
->MaterialMask
[count
] = 0;
1290 IM
->MaterialAndMask
&= IM
->MaterialMask
[IM
->LastMaterial
];
1291 IM
->LastMaterial
= count
;
1294 IM
->MaterialOrMask
|= bitmask
;
1295 IM
->MaterialMask
[count
] |= bitmask
;
1296 mat
= &IM
->Material
[count
];
1299 case GL_SHININESS
: nr
= 1; break;
1300 case GL_COLOR_INDEXES
: nr
= 3; break;
1301 default: nr
= 4 ; break;
1304 for (i
= 0 ; i
< MAT_ATTRIB_MAX
; i
++)
1305 if (bitmask
& (1<<i
))
1306 COPY_SZ_4V( mat
->Attrib
[i
], nr
, params
);
1308 if (tnl
->IsolateMaterials
&&
1309 !(IM
->BeginState
& VERT_BEGIN_1
)) /* heuristic */
1311 _tnl_flush_immediate( ctx
, IM
);
1315 void _tnl_imm_vtxfmt_init( GLcontext
*ctx
)
1317 GLvertexformat
*vfmt
= &(TNL_CONTEXT(ctx
)->vtxfmt
);
1319 /* All begin/end operations are handled by this vertex format:
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
;
1376 /* Outside begin/end functions (from t_varray.c, t_eval.c, ...):
1378 vfmt
->Rectf
= _tnl_Rectf
;
1380 /* Just use the core function:
1382 vfmt
->CallList
= _mesa_CallList
;
1384 vfmt
->prefer_float_colors
= GL_FALSE
;