1 /* $Id: t_imm_api.c,v 1.35 2002/10/29 20:29:01 brianp Exp $ */
4 * Mesa 3-D graphics library
7 * Copyright (C) 1999-2001 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>
43 #include "t_context.h"
44 #include "t_imm_api.h"
45 #include "t_imm_elt.h"
46 #include "t_imm_exec.h"
47 #include "t_imm_dlist.h"
50 /* A cassette is full or flushed on a statechange.
52 void _tnl_flush_immediate( GLcontext
*ctx
, struct immediate
*IM
)
55 /* We were called by glVertex, glEvalCoord, glArrayElement, etc.
56 * The current context is corresponds to the IM structure.
58 GET_CURRENT_CONTEXT(context
);
62 if (MESA_VERBOSE
& VERBOSE_IMMEDIATE
)
63 _mesa_debug(ctx
, "_tnl_flush_immediate IM: %d compiling: %d\n",
64 IM
->id
, ctx
->CompileFlag
);
66 if (IM
->FlushElt
== FLUSH_ELT_EAGER
) {
67 _tnl_translate_array_elts( ctx
, IM
, IM
->LastPrimitive
, IM
->Count
);
70 /* Mark the last primitive:
72 IM
->PrimitiveLength
[IM
->LastPrimitive
] = IM
->Count
- IM
->LastPrimitive
;
73 IM
->Primitive
[IM
->LastPrimitive
] |= PRIM_LAST
;
76 _tnl_compile_cassette( ctx
, IM
);
78 _tnl_execute_cassette( ctx
, IM
);
82 /* Hook for ctx->Driver.FlushVertices:
84 void _tnl_flush_vertices( GLcontext
*ctx
, GLuint flags
)
86 struct immediate
*IM
= TNL_CURRENT_IM(ctx
);
88 if (MESA_VERBOSE
& VERBOSE_IMMEDIATE
)
90 "_tnl_flush_vertices flags %x IM(%d) %d..%d Flag[%d]: %x\n",
91 flags
, IM
->id
, IM
->Start
, IM
->Count
, IM
->Start
,
94 if (IM
->Flag
[IM
->Start
]) {
95 if ((flags
& FLUSH_UPDATE_CURRENT
) ||
96 IM
->Count
> IM
->Start
||
97 (IM
->Flag
[IM
->Start
] & (VERT_BIT_BEGIN
| VERT_BIT_END
))) {
98 _tnl_flush_immediate( ctx
, IM
);
105 _tnl_save_Begin( GLenum mode
)
107 GET_CURRENT_CONTEXT(ctx
);
108 struct immediate
*IM
= TNL_CURRENT_IM(ctx
);
109 GLuint inflags
, state
;
111 /* _mesa_debug(ctx, "%s: before: %x\n", __FUNCTION__, IM->BeginState); */
113 if (mode
> GL_POLYGON
) {
114 _mesa_compile_error( ctx
, GL_INVALID_ENUM
, "_tnl_Begin" );
119 _mesa_update_state(ctx
);
122 /* if only a very few slots left, might as well flush now
124 if (IM
->Count
> IMM_MAXDATA
-8) {
125 _tnl_flush_immediate( ctx
, IM
);
126 IM
= TNL_CURRENT_IM(ctx
);
130 /* Check for and flush buffered vertices from internal operations.
132 if (IM
->SavedBeginState
) {
133 _tnl_flush_immediate( ctx
, IM
);
134 IM
= TNL_CURRENT_IM(ctx
);
135 IM
->BeginState
= IM
->SavedBeginState
;
136 IM
->SavedBeginState
= 0;
139 state
= IM
->BeginState
;
140 inflags
= state
& (VERT_BEGIN_0
|VERT_BEGIN_1
);
141 state
|= inflags
<< 2; /* set error conditions */
143 if (inflags
!= (VERT_BEGIN_0
|VERT_BEGIN_1
))
145 GLuint count
= IM
->Count
;
146 GLuint last
= IM
->LastPrimitive
;
148 state
|= (VERT_BEGIN_0
|VERT_BEGIN_1
);
149 IM
->Flag
[count
] |= VERT_BIT_BEGIN
;
150 IM
->Primitive
[count
] = mode
| PRIM_BEGIN
;
151 IM
->PrimitiveLength
[IM
->LastPrimitive
] = count
- IM
->LastPrimitive
;
152 IM
->LastPrimitive
= count
;
154 /* Not quite right. Need to use the fallback '_aa_ArrayElement'
155 * when not known to be inside begin/end and arrays are
158 if (IM
->FlushElt
== FLUSH_ELT_EAGER
) {
159 _tnl_translate_array_elts( ctx
, IM
, last
, count
);
163 ctx
->Driver
.NeedFlush
|= FLUSH_STORED_VERTICES
;
164 IM
->BeginState
= state
;
166 /* Update save_primitive now. Don't touch ExecPrimitive as this is
167 * updated in the replay of this cassette if we are in
168 * COMPILE_AND_EXECUTE mode.
170 if (ctx
->Driver
.CurrentSavePrimitive
== PRIM_UNKNOWN
)
171 ctx
->Driver
.CurrentSavePrimitive
= PRIM_INSIDE_UNKNOWN_PRIM
;
172 else if (ctx
->Driver
.CurrentSavePrimitive
== PRIM_OUTSIDE_BEGIN_END
)
173 ctx
->Driver
.CurrentSavePrimitive
= mode
;
178 _tnl_Begin( GLenum mode
)
180 GET_CURRENT_CONTEXT(ctx
);
181 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
182 ASSERT (!ctx
->CompileFlag
);
184 if (mode
> GL_POLYGON
) {
185 _mesa_error( ctx
, GL_INVALID_ENUM
, "_tnl_Begin(0x%x)", mode
);
189 if (ctx
->Driver
.CurrentExecPrimitive
!= PRIM_OUTSIDE_BEGIN_END
) {
190 _mesa_error( ctx
, GL_INVALID_OPERATION
, "_tnl_Begin" );
195 _mesa_update_state(ctx
);
198 struct immediate
*IM
= TNL_CURRENT_IM(ctx
);
199 GLuint count
= IM
->Count
;
200 GLuint last
= IM
->LastPrimitive
;
202 if (IM
->Start
== IM
->Count
&&
203 tnl
->Driver
.NotifyBegin
&&
204 tnl
->Driver
.NotifyBegin( ctx
, mode
)) {
208 assert( IM
->SavedBeginState
== 0 );
209 assert( IM
->BeginState
== 0 );
211 /* Not quite right. Need to use the fallback '_aa_ArrayElement'
212 * when not known to be inside begin/end and arrays are
215 if (IM
->FlushElt
== FLUSH_ELT_EAGER
) {
216 _tnl_translate_array_elts( ctx
, IM
, last
, count
);
219 IM
->Flag
[count
] |= VERT_BIT_BEGIN
;
220 IM
->Primitive
[count
] = mode
| PRIM_BEGIN
;
221 IM
->PrimitiveLength
[last
] = count
- last
;
222 IM
->LastPrimitive
= count
;
223 IM
->BeginState
= (VERT_BEGIN_0
|VERT_BEGIN_1
);
225 /* _mesa_debug(ctx, "%s: %x\n", __FUNCTION__, IM->BeginState); */
227 ctx
->Driver
.NeedFlush
|= FLUSH_STORED_VERTICES
;
228 ctx
->Driver
.CurrentExecPrimitive
= mode
;
233 /* Function which allows operations like 'glRectf' to decompose to a
234 * begin/end object and vertices without worrying about what happens
235 * with display lists.
238 _tnl_hard_begin( GLcontext
*ctx
, GLenum p
)
240 /* _mesa_debug(ctx, "%s\n", __FUNCTION__); */
242 if (!ctx
->CompileFlag
) {
243 /* If not compiling, treat as a normal begin().
245 /* _mesa_debug(ctx, "%s: treating as glBegin\n", __FUNCTION__); */
250 /* Otherwise, need to do special processing to preserve the
251 * condition that these vertices will only be replayed outside
252 * future begin/end objects.
254 struct immediate
*IM
= TNL_CURRENT_IM(ctx
);
257 _mesa_update_state(ctx
);
259 if (IM
->Count
> IMM_MAXDATA
-8) {
260 _tnl_flush_immediate( ctx
, IM
);
261 IM
= TNL_CURRENT_IM(ctx
);
264 /* A lot depends on the degree to which the display list has
265 * constrained the possible begin/end states at this point:
267 switch (IM
->BeginState
& (VERT_BEGIN_0
|VERT_BEGIN_1
)) {
268 case VERT_BEGIN_0
|VERT_BEGIN_1
:
269 /* This is an immediate known to be inside a begin/end object.
271 ASSERT(ctx
->Driver
.CurrentSavePrimitive
<= GL_POLYGON
);
272 IM
->BeginState
|= (VERT_ERROR_1
|VERT_ERROR_0
);
277 /* This is a display-list immediate in an unknown begin/end
278 * state. Assert it is empty and convert it to a 'hard' one.
280 ASSERT(IM
->SavedBeginState
== 0);
281 ASSERT(ctx
->Driver
.CurrentSavePrimitive
== PRIM_UNKNOWN
);
283 /* Push current beginstate, to be restored later. Don't worry
284 * about raising errors.
286 IM
->SavedBeginState
= IM
->BeginState
;
291 /* Unless we have fallen through, this is an immediate known to
292 * be outside begin/end objects.
294 ASSERT(ctx
->Driver
.CurrentSavePrimitive
== PRIM_UNKNOWN
||
295 ctx
->Driver
.CurrentSavePrimitive
== PRIM_OUTSIDE_BEGIN_END
);
296 ASSERT (IM
->FlushElt
!= FLUSH_ELT_EAGER
);
298 IM
->BeginState
|= VERT_BEGIN_0
|VERT_BEGIN_1
;
299 IM
->Flag
[IM
->Count
] |= VERT_BIT_BEGIN
;
300 IM
->Primitive
[IM
->Count
] = p
| PRIM_BEGIN
;
301 IM
->PrimitiveLength
[IM
->LastPrimitive
] = IM
->Count
- IM
->LastPrimitive
;
302 IM
->LastPrimitive
= IM
->Count
;
304 /* This is necessary as this immediate will not be flushed in
305 * _tnl_end() -- we leave it active, hoping to pick up more
306 * vertices before the next state change.
308 ctx
->Driver
.NeedFlush
|= FLUSH_STORED_VERTICES
;
323 /* Both streams now outside begin/end.
325 * Leave SavedBeginState untouched -- attempt to gather several
326 * rects/arrays together in a single immediate struct.
329 _tnl_end( GLcontext
*ctx
)
331 struct immediate
*IM
= TNL_CURRENT_IM(ctx
);
332 GLuint state
= IM
->BeginState
;
333 GLuint inflags
= (~state
) & (VERT_BEGIN_0
|VERT_BEGIN_1
);
335 assert( ctx
->Driver
.NeedFlush
& FLUSH_STORED_VERTICES
);
337 state
|= inflags
<< 2; /* errors */
339 if (inflags
!= (VERT_BEGIN_0
|VERT_BEGIN_1
))
341 GLuint count
= IM
->Count
;
342 GLuint last
= IM
->LastPrimitive
;
344 state
&= ~(VERT_BEGIN_0
|VERT_BEGIN_1
); /* update state */
345 IM
->Flag
[count
] |= VERT_BIT_END
;
346 IM
->Primitive
[last
] |= PRIM_END
;
347 IM
->PrimitiveLength
[last
] = count
- last
;
348 IM
->Primitive
[count
] = PRIM_OUTSIDE_BEGIN_END
; /* removes PRIM_BEGIN
349 * flag if length == 0
351 IM
->LastPrimitive
= count
;
353 if (IM
->FlushElt
== FLUSH_ELT_EAGER
) {
354 _tnl_translate_array_elts( ctx
, IM
, last
, count
);
358 IM
->BeginState
= state
;
360 if (!ctx
->CompileFlag
) {
361 if (ctx
->Driver
.CurrentExecPrimitive
== PRIM_OUTSIDE_BEGIN_END
)
362 _mesa_error( ctx
, GL_INVALID_OPERATION
, "_tnl_End" );
364 ctx
->Driver
.CurrentExecPrimitive
= PRIM_OUTSIDE_BEGIN_END
;
367 /* You can set this flag to get the old 'flush_vb on glEnd()'
370 if (MESA_DEBUG_FLAGS
& DEBUG_ALWAYS_FLUSH
)
371 _tnl_flush_immediate( ctx
, IM
);
377 GET_CURRENT_CONTEXT(ctx
);
381 /* Need to keep save primitive uptodate in COMPILE and
382 * COMPILE_AND_EXEC modes, need to keep exec primitive uptodate
385 if (ctx
->CompileFlag
)
386 ctx
->Driver
.CurrentSavePrimitive
= PRIM_OUTSIDE_BEGIN_END
;
390 #define COLOR( r, g, b, a ) \
393 GLuint count = IM->Count; \
394 GLfloat *color = IM->Attrib[VERT_ATTRIB_COLOR0][count]; \
395 IM->Flag[count] |= VERT_BIT_COLOR0; \
403 _tnl_Color3f( GLfloat red
, GLfloat green
, GLfloat blue
)
405 COLOR( red
, green
, blue
, 1.0 );
409 _tnl_Color3ub( GLubyte red
, GLubyte green
, GLubyte blue
)
411 COLOR(UBYTE_TO_FLOAT(red
),
412 UBYTE_TO_FLOAT(green
),
413 UBYTE_TO_FLOAT(blue
),
418 _tnl_Color4f( GLfloat red
, GLfloat green
, GLfloat blue
, GLfloat alpha
)
420 COLOR( red
, green
, blue
, alpha
);
424 _tnl_Color4ub( GLubyte red
, GLubyte green
, GLubyte blue
, GLubyte alpha
)
426 COLOR(UBYTE_TO_FLOAT(red
),
427 UBYTE_TO_FLOAT(green
),
428 UBYTE_TO_FLOAT(blue
),
429 UBYTE_TO_FLOAT(alpha
));
433 _tnl_Color3fv( const GLfloat
*v
)
435 COLOR( v
[0], v
[1], v
[2], 1.0 );
439 _tnl_Color3ubv( const GLubyte
*v
)
441 COLOR(UBYTE_TO_FLOAT(v
[0]),
442 UBYTE_TO_FLOAT(v
[1]),
443 UBYTE_TO_FLOAT(v
[2]),
448 _tnl_Color4fv( const GLfloat
*v
)
450 COLOR( v
[0], v
[1], v
[2], v
[3] );
454 _tnl_Color4ubv( const GLubyte
*v
)
456 COLOR(UBYTE_TO_FLOAT(v
[0]),
457 UBYTE_TO_FLOAT(v
[1]),
458 UBYTE_TO_FLOAT(v
[2]),
459 UBYTE_TO_FLOAT(v
[3]));
465 #define SECONDARY_COLOR( r, g, b ) \
470 IM->Flag[count] |= VERT_BIT_COLOR1; \
471 IM->Attrib[VERT_ATTRIB_COLOR1][count][0] = r; \
472 IM->Attrib[VERT_ATTRIB_COLOR1][count][1] = g; \
473 IM->Attrib[VERT_ATTRIB_COLOR1][count][2] = b; \
477 _tnl_SecondaryColor3fEXT( GLfloat red
, GLfloat green
, GLfloat blue
)
479 SECONDARY_COLOR( red
, green
, blue
);
483 _tnl_SecondaryColor3ubEXT( GLubyte red
, GLubyte green
, GLubyte blue
)
485 SECONDARY_COLOR(UBYTE_TO_FLOAT(red
),
486 UBYTE_TO_FLOAT(green
),
487 UBYTE_TO_FLOAT(blue
));
491 _tnl_SecondaryColor3fvEXT( const GLfloat
*v
)
493 SECONDARY_COLOR( v
[0], v
[1], v
[2] );
497 _tnl_SecondaryColor3ubvEXT( const GLubyte
*v
)
499 SECONDARY_COLOR(UBYTE_TO_FLOAT(v
[0]),
500 UBYTE_TO_FLOAT(v
[1]),
501 UBYTE_TO_FLOAT(v
[2]));
506 _tnl_EdgeFlag( GLboolean flag
)
511 IM
->EdgeFlag
[count
] = flag
;
512 IM
->Flag
[count
] |= VERT_BIT_EDGEFLAG
;
517 _tnl_EdgeFlagv( const GLboolean
*flag
)
522 IM
->EdgeFlag
[count
] = *flag
;
523 IM
->Flag
[count
] |= VERT_BIT_EDGEFLAG
;
528 _tnl_FogCoordfEXT( GLfloat f
)
533 IM
->Attrib
[VERT_ATTRIB_FOG
][count
][0] = f
; /*FogCoord[count] = f;*/
534 IM
->Flag
[count
] |= VERT_BIT_FOG
;
538 _tnl_FogCoordfvEXT( const GLfloat
*v
)
543 IM
->Attrib
[VERT_ATTRIB_FOG
][count
][0] = v
[0]; /*FogCoord[count] = v[0];*/
544 IM
->Flag
[count
] |= VERT_BIT_FOG
;
549 _tnl_Indexi( GLint c
)
554 IM
->Index
[count
] = c
;
555 IM
->Flag
[count
] |= VERT_BIT_INDEX
;
560 _tnl_Indexiv( const GLint
*c
)
565 IM
->Index
[count
] = *c
;
566 IM
->Flag
[count
] |= VERT_BIT_INDEX
;
570 #define NORMAL( x, y, z ) \
576 IM->Flag[count] |= VERT_BIT_NORMAL; \
577 normal = IM->Attrib[VERT_ATTRIB_NORMAL][count]; \
578 ASSIGN_3V(normal, x,y,z); \
581 #if defined(USE_IEEE)
582 #define NORMALF( x, y, z ) \
588 IM->Flag[count] |= VERT_BIT_NORMAL; \
589 normal = (fi_type *)IM->Attrib[VERT_ATTRIB_NORMAL][count]; \
590 normal[0].i = ((fi_type *)&(x))->i; \
591 normal[1].i = ((fi_type *)&(y))->i; \
592 normal[2].i = ((fi_type *)&(z))->i; \
595 #define NORMALF NORMAL
599 _tnl_Normal3f( GLfloat nx
, GLfloat ny
, GLfloat nz
)
606 _tnl_Normal3fv( const GLfloat
*v
)
608 NORMALF( v
[0], v
[1], v
[2] );
609 /* struct immediate *IM = (struct immediate *)(((GLcontext *) _glapi_Context)->swtnl_im); */
610 /* IM->Flag[IM->Count] = VERT_NORM; */
615 #define TEXCOORD1(s) \
621 IM->Flag[count] |= VERT_BIT_TEX0; \
622 tc = IM->Attrib[VERT_ATTRIB_TEX0][count]; \
623 ASSIGN_4V(tc,s,0,0,1); \
626 #define TEXCOORD2(s, t) \
632 IM->Flag[count] |= VERT_BIT_TEX0; \
633 tc = IM->Attrib[VERT_ATTRIB_TEX0][count]; \
634 ASSIGN_4V(tc, s, t, 0, 1); \
637 #define TEXCOORD3(s, t, u) \
643 IM->Flag[count] |= VERT_BIT_TEX0; \
644 IM->TexSize |= TEX_0_SIZE_3; \
645 tc = IM->Attrib[VERT_ATTRIB_TEX0][count]; \
646 ASSIGN_4V(tc, s, t, u, 1); \
649 #define TEXCOORD4(s, t, u, v) \
655 IM->Flag[count] |= VERT_BIT_TEX0; \
656 IM->TexSize |= TEX_0_SIZE_4; \
657 tc = IM->Attrib[VERT_ATTRIB_TEX0][count]; \
658 ASSIGN_4V(tc, s, t, u, v); \
661 #if defined(USE_IEEE)
662 #define TEXCOORD2F(s, t) \
668 IM->Flag[count] |= VERT_BIT_TEX0; \
669 tc = (fi_type *)IM->Attrib[VERT_ATTRIB_TEX0][count]; \
670 tc[0].i = ((fi_type *)&(s))->i; \
671 tc[1].i = ((fi_type *)&(t))->i; \
673 tc[3].i = IEEE_ONE; \
676 #define TEXCOORD2F TEXCOORD2
680 _tnl_TexCoord1f( GLfloat s
)
687 _tnl_TexCoord2f( GLfloat s
, GLfloat t
)
694 _tnl_TexCoord3f( GLfloat s
, GLfloat t
, GLfloat r
)
700 _tnl_TexCoord4f( GLfloat s
, GLfloat t
, GLfloat r
, GLfloat q
)
702 TEXCOORD4(s
, t
, r
, q
)
706 _tnl_TexCoord1fv( const GLfloat
*v
)
712 _tnl_TexCoord2fv( const GLfloat
*v
)
714 TEXCOORD2F(v
[0], v
[1]);
718 _tnl_TexCoord3fv( const GLfloat
*v
)
720 TEXCOORD3(v
[0], v
[1], v
[2]);
724 _tnl_TexCoord4fv( const GLfloat
*v
)
726 TEXCOORD4(v
[0], v
[1], v
[2], v
[3]);
731 /* KW: Run into bad problems in vertex copying if we don't fully pad
732 * the incoming vertices.
734 #define VERTEX2(IM, x,y) \
736 GLuint count = IM->Count++; \
737 GLfloat *dest = IM->Attrib[VERT_ATTRIB_POS][count]; \
738 IM->Flag[count] |= VERT_BIT_POS; \
739 ASSIGN_4V(dest, x, y, 0, 1); \
740 /* ASSERT(IM->Flag[IM->Count]==0); */ \
741 if (count == IMM_MAXDATA - 1) \
742 _tnl_flush_immediate( NULL, IM ); \
745 #define VERTEX3(IM,x,y,z) \
747 GLuint count = IM->Count++; \
748 GLfloat *dest = IM->Attrib[VERT_ATTRIB_POS][count]; \
749 IM->Flag[count] |= VERT_BITS_OBJ_23; \
750 ASSIGN_4V(dest, x, y, z, 1); \
751 /* ASSERT(IM->Flag[IM->Count]==0); */ \
752 if (count == IMM_MAXDATA - 1) \
753 _tnl_flush_immediate( NULL, IM ); \
756 #define VERTEX4(IM, x,y,z,w) \
758 GLuint count = IM->Count++; \
759 GLfloat *dest = IM->Attrib[VERT_ATTRIB_POS][count]; \
760 IM->Flag[count] |= VERT_BITS_OBJ_234; \
761 ASSIGN_4V(dest, x, y, z, w); \
762 if (count == IMM_MAXDATA - 1) \
763 _tnl_flush_immediate( NULL, IM ); \
766 #if defined(USE_IEEE)
767 #define VERTEX2F(IM, x, y) \
769 GLuint count = IM->Count++; \
770 fi_type *dest = (fi_type *)IM->Attrib[VERT_ATTRIB_POS][count]; \
771 IM->Flag[count] |= VERT_BIT_POS; \
772 dest[0].i = ((fi_type *)&(x))->i; \
773 dest[1].i = ((fi_type *)&(y))->i; \
775 dest[3].i = IEEE_ONE; \
776 /* ASSERT(IM->Flag[IM->Count]==0); */ \
777 if (count == IMM_MAXDATA - 1) \
778 _tnl_flush_immediate( NULL, IM ); \
781 #define VERTEX2F VERTEX2
784 #if defined(USE_IEEE)
785 #define VERTEX3F(IM, x, y, z) \
787 GLuint count = IM->Count++; \
788 fi_type *dest = (fi_type *)IM->Attrib[VERT_ATTRIB_POS][count]; \
789 IM->Flag[count] |= VERT_BITS_OBJ_23; \
790 dest[0].i = ((fi_type *)&(x))->i; \
791 dest[1].i = ((fi_type *)&(y))->i; \
792 dest[2].i = ((fi_type *)&(z))->i; \
793 dest[3].i = IEEE_ONE; \
794 /* ASSERT(IM->Flag[IM->Count]==0); */ \
795 if (count == IMM_MAXDATA - 1) \
796 _tnl_flush_immediate( NULL, IM ); \
799 #define VERTEX3F VERTEX3
802 #if defined(USE_IEEE)
803 #define VERTEX4F(IM, x, y, z, w) \
805 GLuint count = IM->Count++; \
806 fi_type *dest = (fi_type *)IM->Attrib[VERT_ATTRIB_POS][count]; \
807 IM->Flag[count] |= VERT_BITS_OBJ_234; \
808 dest[0].i = ((fi_type *)&(x))->i; \
809 dest[1].i = ((fi_type *)&(y))->i; \
810 dest[2].i = ((fi_type *)&(z))->i; \
811 dest[3].i = ((fi_type *)&(w))->i; \
812 if (count == IMM_MAXDATA - 1) \
813 _tnl_flush_immediate( NULL, IM ); \
816 #define VERTEX4F VERTEX4
822 _tnl_Vertex2f( GLfloat x
, GLfloat y
)
825 VERTEX2F( IM
, x
, y
);
829 _tnl_Vertex3f( GLfloat x
, GLfloat y
, GLfloat z
)
832 VERTEX3F( IM
, x
, y
, z
);
835 _tnl_Vertex4f( GLfloat x
, GLfloat y
, GLfloat z
, GLfloat w
)
838 VERTEX4F( IM
, x
, y
, z
, w
);
842 _tnl_Vertex2fv( const GLfloat
*v
)
845 VERTEX2F( IM
, v
[0], v
[1] );
849 _tnl_Vertex3fv( const GLfloat
*v
)
852 VERTEX3F( IM
, v
[0], v
[1], v
[2] );
856 _tnl_Vertex4fv( const GLfloat
*v
)
859 VERTEX4F( IM
, v
[0], v
[1], v
[2], v
[3] );
866 * GL_ARB_multitexture
868 * Note: the multitexture spec says that specifying an invalid target
869 * has undefined results and does not have to generate an error. Just
870 * don't crash. We no-op on invalid targets.
873 #define MAX_TARGET (GL_TEXTURE0_ARB + MAX_TEXTURE_UNITS)
875 #define MULTI_TEXCOORD1(target, s) \
878 GLuint texunit = target - GL_TEXTURE0_ARB; \
879 if (texunit < IM->MaxTextureUnits) { \
880 GLuint count = IM->Count; \
881 GLfloat *tc = IM->Attrib[VERT_ATTRIB_TEX0 + texunit][count]; \
882 ASSIGN_4V(tc, s, 0.0F, 0.0F, 1.0F); \
883 IM->Flag[count] |= VERT_BIT_TEX(texunit); \
887 #define MULTI_TEXCOORD2(target, s, t) \
890 GLuint texunit = target - GL_TEXTURE0_ARB; \
891 if (texunit < IM->MaxTextureUnits) { \
892 GLuint count = IM->Count; \
893 GLfloat *tc = IM->Attrib[VERT_ATTRIB_TEX0 + texunit][count]; \
894 ASSIGN_4V(tc, s, t, 0.0F, 1.0F); \
895 IM->Flag[count] |= VERT_BIT_TEX(texunit); \
899 #define MULTI_TEXCOORD3(target, s, t, u) \
902 GLuint texunit = target - GL_TEXTURE0_ARB; \
903 if (texunit < IM->MaxTextureUnits) { \
904 GLuint count = IM->Count; \
905 GLfloat *tc = IM->Attrib[VERT_ATTRIB_TEX0 + texunit][count]; \
906 ASSIGN_4V(tc, s, t, u, 1.0F); \
907 IM->Flag[count] |= VERT_BIT_TEX(texunit); \
908 IM->TexSize |= TEX_SIZE_3(texunit); \
912 #define MULTI_TEXCOORD4(target, s, t, u, v) \
915 GLuint texunit = target - GL_TEXTURE0_ARB; \
916 if (texunit < IM->MaxTextureUnits) { \
917 GLuint count = IM->Count; \
918 GLfloat *tc = IM->Attrib[VERT_ATTRIB_TEX0 + texunit][count]; \
919 ASSIGN_4V(tc, s, t, u, v); \
920 IM->Flag[count] |= VERT_BIT_TEX(texunit); \
921 IM->TexSize |= TEX_SIZE_4(texunit); \
925 #if defined(USE_IEEE)
926 #define MULTI_TEXCOORD2F(target, s, t) \
929 GLuint texunit = target - GL_TEXTURE0_ARB; \
930 if (texunit < IM->MaxTextureUnits) { \
931 GLuint count = IM->Count; \
932 fi_type *tc = (fi_type *)IM->Attrib[VERT_ATTRIB_TEX0 + texunit][count];\
933 IM->Flag[count] |= VERT_BIT_TEX(texunit); \
934 tc[0].i = ((fi_type *)&(s))->i; \
935 tc[1].i = ((fi_type *)&(t))->i; \
937 tc[3].i = IEEE_ONE; \
941 #define MULTI_TEXCOORD2F MULTI_TEXCOORD2
945 _tnl_MultiTexCoord1fARB(GLenum target
, GLfloat s
)
947 MULTI_TEXCOORD1( target
, s
);
951 _tnl_MultiTexCoord1fvARB(GLenum target
, const GLfloat
*v
)
953 MULTI_TEXCOORD1( target
, v
[0] );
957 _tnl_MultiTexCoord2fARB(GLenum target
, GLfloat s
, GLfloat t
)
959 MULTI_TEXCOORD2F( target
, s
, t
);
963 _tnl_MultiTexCoord2fvARB(GLenum target
, const GLfloat
*v
)
965 MULTI_TEXCOORD2F( target
, v
[0], v
[1] );
969 _tnl_MultiTexCoord3fARB(GLenum target
, GLfloat s
, GLfloat t
, GLfloat r
)
971 MULTI_TEXCOORD3( target
, s
, t
, r
);
975 _tnl_MultiTexCoord3fvARB(GLenum target
, const GLfloat
*v
)
977 MULTI_TEXCOORD3( target
, v
[0], v
[1], v
[2] );
981 _tnl_MultiTexCoord4fARB(GLenum target
, GLfloat s
, GLfloat t
, GLfloat r
, GLfloat q
)
983 MULTI_TEXCOORD4( target
, s
, t
, r
, q
);
987 _tnl_MultiTexCoord4fvARB(GLenum target
, const GLfloat
*v
)
989 MULTI_TEXCOORD4( target
, v
[0], v
[1], v
[2], v
[3] );
994 /* KW: Because the eval values don't become 'current', fixup will flow
995 * through these vertices, and then evaluation will write on top
996 * of the fixup results.
998 * Note: using Obj to hold eval coord data.
1000 #define EVALCOORD1(IM, x) \
1002 GLuint count = IM->Count++; \
1003 GLfloat *dest = IM->Attrib[VERT_ATTRIB_POS][count]; \
1004 IM->Flag[count] |= VERT_BIT_EVAL_C1; \
1005 ASSIGN_4V(dest, x, 0, 0, 1); \
1006 if (count == IMM_MAXDATA-1) \
1007 _tnl_flush_immediate( NULL, IM ); \
1010 #define EVALCOORD2(IM, x, y) \
1012 GLuint count = IM->Count++; \
1013 GLfloat *dest = IM->Attrib[VERT_ATTRIB_POS][count]; \
1014 IM->Flag[count] |= VERT_BIT_EVAL_C2; \
1015 ASSIGN_4V(dest, x, y, 0, 1); \
1016 if (count == IMM_MAXDATA-1) \
1017 _tnl_flush_immediate( NULL, IM ); \
1020 #define EVALPOINT1(IM, x) \
1022 GLuint count = IM->Count++; \
1023 GLfloat *dest = IM->Attrib[VERT_ATTRIB_POS][count]; \
1024 IM->Flag[count] |= VERT_BIT_EVAL_P1; \
1025 ASSIGN_4V(dest, x, 0, 0, 1); \
1026 if (count == IMM_MAXDATA-1) \
1027 _tnl_flush_immediate( NULL, IM ); \
1030 #define EVALPOINT2(IM, x, y) \
1032 GLuint count = IM->Count++; \
1033 GLfloat *dest = IM->Attrib[VERT_ATTRIB_POS][count]; \
1034 IM->Flag[count] |= VERT_BIT_EVAL_P2; \
1035 ASSIGN_4V(dest, x, y, 0, 1); \
1036 if (count == IMM_MAXDATA-1) \
1037 _tnl_flush_immediate( NULL, IM ); \
1041 _tnl_EvalCoord1f( GLfloat u
)
1044 EVALCOORD1( IM
, u
);
1048 _tnl_EvalCoord1fv( const GLfloat
*u
)
1051 EVALCOORD1( IM
, (GLfloat
) *u
);
1055 _tnl_EvalCoord2f( GLfloat u
, GLfloat v
)
1058 EVALCOORD2( IM
, u
, v
);
1062 _tnl_EvalCoord2fv( const GLfloat
*u
)
1065 EVALCOORD2( IM
, u
[0], u
[1] );
1070 _tnl_EvalPoint1( GLint i
)
1073 EVALPOINT1( IM
, (GLfloat
) i
);
1078 _tnl_EvalPoint2( GLint i
, GLint j
)
1081 EVALPOINT2( IM
, (GLfloat
) i
, (GLfloat
) j
);
1085 /* Need to use the default array-elt outside begin/end for strict
1088 #define ARRAY_ELT( IM, i ) \
1090 GLuint count = IM->Count; \
1091 IM->Elt[count] = i; \
1092 IM->Flag[count] &= IM->ArrayEltFlags; \
1093 IM->Flag[count] |= VERT_BIT_ELT; \
1094 IM->FlushElt = IM->ArrayEltFlush; \
1095 IM->Count += IM->ArrayEltIncr; \
1096 if (IM->Count == IMM_MAXDATA) \
1097 _tnl_flush_immediate( NULL, IM ); \
1102 _tnl_ArrayElement( GLint i
)
1109 /* Internal functions. These are safe to use providing either:
1111 * - It is determined that a display list is not being compiled, or
1112 * if so that these commands won't be compiled into the list (see
1113 * t_eval.c for an example).
1115 * - _tnl_hard_begin() is used instead of _tnl_[bB]egin, and tested
1116 * for a GL_TRUE return value. See _tnl_Rectf, below.
1119 _tnl_eval_coord1f( GLcontext
*CC
, GLfloat u
)
1121 struct immediate
*i
= TNL_CURRENT_IM(CC
);
1126 _tnl_eval_coord2f( GLcontext
*CC
, GLfloat u
, GLfloat v
)
1128 struct immediate
*i
= TNL_CURRENT_IM(CC
);
1129 EVALCOORD2( i
, u
, v
);
1140 _tnl_VertexAttrib4fNV( GLuint index
, GLfloat x
, GLfloat y
, GLfloat z
, GLfloat w
)
1144 const GLuint count
= IM
->Count
;
1145 GLfloat
*attrib
= IM
->Attrib
[index
][count
];
1146 ASSIGN_4V(attrib
, x
, y
, z
, w
);
1147 IM
->Flag
[count
] |= (1 << index
);
1150 if (count
== IMM_MAXDATA
- 1)
1151 _tnl_flush_immediate( NULL
, IM
);
1155 GET_CURRENT_CONTEXT(ctx
);
1156 _mesa_error(ctx
, GL_INVALID_VALUE
, "glVertexAttribNV(index > 15)");
1161 _tnl_VertexAttrib4fvNV( GLuint index
, const GLfloat
*v
)
1165 const GLuint count
= IM
->Count
;
1166 GLfloat
*attrib
= IM
->Attrib
[index
][count
];
1168 IM
->Flag
[count
] |= (1 << index
);
1171 if (count
== IMM_MAXDATA
- 1)
1172 _tnl_flush_immediate( NULL
, IM
);
1176 GET_CURRENT_CONTEXT(ctx
);
1177 _mesa_error(ctx
, GL_INVALID_VALUE
, "glVertexAttribNV(index > 15)");
1182 /* Execute a glRectf() function. _tnl_hard_begin() ensures the check
1183 * on outside_begin_end is executed even in compiled lists. These
1184 * vertices can now participate in the same immediate as regular ones,
1185 * even in most display lists.
1188 _tnl_Rectf( GLfloat x1
, GLfloat y1
, GLfloat x2
, GLfloat y2
)
1190 GET_CURRENT_CONTEXT(ctx
);
1192 if (_tnl_hard_begin( ctx
, GL_QUADS
)) {
1193 glVertex2f( x1
, y1
);
1194 glVertex2f( x2
, y1
);
1195 glVertex2f( x2
, y2
);
1196 glVertex2f( x1
, y2
);
1202 _tnl_Materialfv( GLenum face
, GLenum pname
, const GLfloat
*params
)
1204 GET_CURRENT_CONTEXT(ctx
);
1205 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
1206 struct immediate
*IM
= TNL_CURRENT_IM(ctx
);
1207 GLuint count
= IM
->Count
;
1208 struct gl_material
*mat
;
1209 GLuint bitmask
= _mesa_material_bitmask(ctx
, face
, pname
, ~0, "Materialfv");
1214 if (MESA_VERBOSE
& VERBOSE_API
)
1215 _mesa_debug(ctx
, "_tnl_Materialfv\n");
1217 if (tnl
->IsolateMaterials
&&
1218 !(IM
->BeginState
& VERT_BEGIN_1
)) /* heuristic */
1220 _tnl_flush_immediate( ctx
, IM
);
1221 IM
= TNL_CURRENT_IM(ctx
);
1225 if (!(IM
->Flag
[count
] & VERT_BIT_MATERIAL
)) {
1226 if (!IM
->Material
) {
1227 IM
->Material
= (struct gl_material (*)[2])
1228 MALLOC( sizeof(struct gl_material
) * IMM_SIZE
* 2 );
1229 IM
->MaterialMask
= (GLuint
*) MALLOC( sizeof(GLuint
) * IMM_SIZE
);
1230 IM
->MaterialMask
[IM
->LastMaterial
] = 0;
1232 else if (IM
->MaterialOrMask
& ~bitmask
) {
1233 _mesa_copy_material_pairs( IM
->Material
[count
],
1234 IM
->Material
[IM
->LastMaterial
],
1235 IM
->MaterialOrMask
& ~bitmask
);
1238 IM
->Flag
[count
] |= VERT_BIT_MATERIAL
;
1239 IM
->MaterialMask
[count
] = 0;
1240 IM
->MaterialAndMask
&= IM
->MaterialMask
[IM
->LastMaterial
];
1241 IM
->LastMaterial
= count
;
1244 IM
->MaterialOrMask
|= bitmask
;
1245 IM
->MaterialMask
[count
] |= bitmask
;
1246 mat
= IM
->Material
[count
];
1248 if (bitmask
& FRONT_AMBIENT_BIT
) {
1249 COPY_4FV( mat
[0].Ambient
, params
);
1251 if (bitmask
& BACK_AMBIENT_BIT
) {
1252 COPY_4FV( mat
[1].Ambient
, params
);
1254 if (bitmask
& FRONT_DIFFUSE_BIT
) {
1255 COPY_4FV( mat
[0].Diffuse
, params
);
1257 if (bitmask
& BACK_DIFFUSE_BIT
) {
1258 COPY_4FV( mat
[1].Diffuse
, params
);
1260 if (bitmask
& FRONT_SPECULAR_BIT
) {
1261 COPY_4FV( mat
[0].Specular
, params
);
1263 if (bitmask
& BACK_SPECULAR_BIT
) {
1264 COPY_4FV( mat
[1].Specular
, params
);
1266 if (bitmask
& FRONT_EMISSION_BIT
) {
1267 COPY_4FV( mat
[0].Emission
, params
);
1269 if (bitmask
& BACK_EMISSION_BIT
) {
1270 COPY_4FV( mat
[1].Emission
, params
);
1272 if (bitmask
& FRONT_SHININESS_BIT
) {
1273 GLfloat shininess
= CLAMP( params
[0], 0.0F
, 128.0F
);
1274 mat
[0].Shininess
= shininess
;
1276 if (bitmask
& BACK_SHININESS_BIT
) {
1277 GLfloat shininess
= CLAMP( params
[0], 0.0F
, 128.0F
);
1278 mat
[1].Shininess
= shininess
;
1280 if (bitmask
& FRONT_INDEXES_BIT
) {
1281 mat
[0].AmbientIndex
= params
[0];
1282 mat
[0].DiffuseIndex
= params
[1];
1283 mat
[0].SpecularIndex
= params
[2];
1285 if (bitmask
& BACK_INDEXES_BIT
) {
1286 mat
[1].AmbientIndex
= params
[0];
1287 mat
[1].DiffuseIndex
= params
[1];
1288 mat
[1].SpecularIndex
= params
[2];
1291 if (tnl
->IsolateMaterials
&&
1292 !(IM
->BeginState
& VERT_BEGIN_1
)) /* heuristic */
1294 _tnl_flush_immediate( ctx
, IM
);
1298 void _tnl_imm_vtxfmt_init( GLcontext
*ctx
)
1300 GLvertexformat
*vfmt
= &(TNL_CONTEXT(ctx
)->vtxfmt
);
1302 /* All begin/end operations are handled by this vertex format:
1304 vfmt
->ArrayElement
= _tnl_ArrayElement
;
1305 vfmt
->Begin
= _tnl_Begin
;
1306 vfmt
->Color3f
= _tnl_Color3f
;
1307 vfmt
->Color3fv
= _tnl_Color3fv
;
1308 vfmt
->Color3ub
= _tnl_Color3ub
;
1309 vfmt
->Color3ubv
= _tnl_Color3ubv
;
1310 vfmt
->Color4f
= _tnl_Color4f
;
1311 vfmt
->Color4fv
= _tnl_Color4fv
;
1312 vfmt
->Color4ub
= _tnl_Color4ub
;
1313 vfmt
->Color4ubv
= _tnl_Color4ubv
;
1314 vfmt
->EdgeFlag
= _tnl_EdgeFlag
;
1315 vfmt
->EdgeFlagv
= _tnl_EdgeFlagv
;
1316 vfmt
->End
= _tnl_End
;
1317 vfmt
->EvalCoord1f
= _tnl_EvalCoord1f
;
1318 vfmt
->EvalCoord1fv
= _tnl_EvalCoord1fv
;
1319 vfmt
->EvalCoord2f
= _tnl_EvalCoord2f
;
1320 vfmt
->EvalCoord2fv
= _tnl_EvalCoord2fv
;
1321 vfmt
->EvalPoint1
= _tnl_EvalPoint1
;
1322 vfmt
->EvalPoint2
= _tnl_EvalPoint2
;
1323 vfmt
->FogCoordfEXT
= _tnl_FogCoordfEXT
;
1324 vfmt
->FogCoordfvEXT
= _tnl_FogCoordfvEXT
;
1325 vfmt
->Indexi
= _tnl_Indexi
;
1326 vfmt
->Indexiv
= _tnl_Indexiv
;
1327 vfmt
->Materialfv
= _tnl_Materialfv
;
1328 vfmt
->MultiTexCoord1fARB
= _tnl_MultiTexCoord1fARB
;
1329 vfmt
->MultiTexCoord1fvARB
= _tnl_MultiTexCoord1fvARB
;
1330 vfmt
->MultiTexCoord2fARB
= _tnl_MultiTexCoord2fARB
;
1331 vfmt
->MultiTexCoord2fvARB
= _tnl_MultiTexCoord2fvARB
;
1332 vfmt
->MultiTexCoord3fARB
= _tnl_MultiTexCoord3fARB
;
1333 vfmt
->MultiTexCoord3fvARB
= _tnl_MultiTexCoord3fvARB
;
1334 vfmt
->MultiTexCoord4fARB
= _tnl_MultiTexCoord4fARB
;
1335 vfmt
->MultiTexCoord4fvARB
= _tnl_MultiTexCoord4fvARB
;
1336 vfmt
->Normal3f
= _tnl_Normal3f
;
1337 vfmt
->Normal3fv
= _tnl_Normal3fv
;
1338 vfmt
->SecondaryColor3fEXT
= _tnl_SecondaryColor3fEXT
;
1339 vfmt
->SecondaryColor3fvEXT
= _tnl_SecondaryColor3fvEXT
;
1340 vfmt
->SecondaryColor3ubEXT
= _tnl_SecondaryColor3ubEXT
;
1341 vfmt
->SecondaryColor3ubvEXT
= _tnl_SecondaryColor3ubvEXT
;
1342 vfmt
->TexCoord1f
= _tnl_TexCoord1f
;
1343 vfmt
->TexCoord1fv
= _tnl_TexCoord1fv
;
1344 vfmt
->TexCoord2f
= _tnl_TexCoord2f
;
1345 vfmt
->TexCoord2fv
= _tnl_TexCoord2fv
;
1346 vfmt
->TexCoord3f
= _tnl_TexCoord3f
;
1347 vfmt
->TexCoord3fv
= _tnl_TexCoord3fv
;
1348 vfmt
->TexCoord4f
= _tnl_TexCoord4f
;
1349 vfmt
->TexCoord4fv
= _tnl_TexCoord4fv
;
1350 vfmt
->Vertex2f
= _tnl_Vertex2f
;
1351 vfmt
->Vertex2fv
= _tnl_Vertex2fv
;
1352 vfmt
->Vertex3f
= _tnl_Vertex3f
;
1353 vfmt
->Vertex3fv
= _tnl_Vertex3fv
;
1354 vfmt
->Vertex4f
= _tnl_Vertex4f
;
1355 vfmt
->Vertex4fv
= _tnl_Vertex4fv
;
1356 vfmt
->VertexAttrib4fNV
= _tnl_VertexAttrib4fNV
;
1357 vfmt
->VertexAttrib4fvNV
= _tnl_VertexAttrib4fvNV
;
1359 /* Outside begin/end functions (from t_varray.c, t_eval.c, ...):
1361 vfmt
->Rectf
= _tnl_Rectf
;
1363 /* Just use the core function:
1365 vfmt
->CallList
= _mesa_CallList
;
1367 vfmt
->prefer_float_colors
= GL_FALSE
;