1 /* $Id: t_imm_api.c,v 1.38 2002/12/05 11:49:46 keithw 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 if (IM
->Count
> IMM_MAXDATA
-8) {
131 _tnl_flush_immediate( ctx
, IM
);
132 IM
= TNL_CURRENT_IM(ctx
);
135 /* Check for and flush buffered vertices from internal operations.
137 if (IM
->SavedBeginState
) {
138 _tnl_flush_immediate( ctx
, IM
);
139 IM
= TNL_CURRENT_IM(ctx
);
140 IM
->BeginState
= IM
->SavedBeginState
;
141 IM
->SavedBeginState
= 0;
144 state
= IM
->BeginState
;
145 inflags
= state
& (VERT_BEGIN_0
|VERT_BEGIN_1
);
146 state
|= inflags
<< 2; /* set error conditions */
148 if (inflags
!= (VERT_BEGIN_0
|VERT_BEGIN_1
))
150 GLuint count
= IM
->Count
;
151 GLuint last
= IM
->LastPrimitive
;
153 state
|= (VERT_BEGIN_0
|VERT_BEGIN_1
);
154 IM
->Flag
[count
] |= VERT_BIT_BEGIN
;
155 IM
->Primitive
[count
] = mode
| PRIM_BEGIN
;
156 IM
->PrimitiveLength
[IM
->LastPrimitive
] = count
- IM
->LastPrimitive
;
157 IM
->LastPrimitive
= count
;
159 /* Not quite right. Need to use the fallback '_aa_ArrayElement'
160 * when not known to be inside begin/end and arrays are
163 if (IM
->FlushElt
== FLUSH_ELT_EAGER
) {
164 _tnl_translate_array_elts( ctx
, IM
, last
, count
);
168 ctx
->Driver
.NeedFlush
|= FLUSH_STORED_VERTICES
;
169 IM
->BeginState
= state
;
171 /* Update save_primitive now. Don't touch ExecPrimitive as this is
172 * updated in the replay of this cassette if we are in
173 * COMPILE_AND_EXECUTE mode.
175 if (ctx
->Driver
.CurrentSavePrimitive
== PRIM_UNKNOWN
)
176 ctx
->Driver
.CurrentSavePrimitive
= PRIM_INSIDE_UNKNOWN_PRIM
;
177 else if (ctx
->Driver
.CurrentSavePrimitive
== PRIM_OUTSIDE_BEGIN_END
)
178 ctx
->Driver
.CurrentSavePrimitive
= mode
;
183 _tnl_Begin( GLenum mode
)
185 GET_CURRENT_CONTEXT(ctx
);
186 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
187 ASSERT (!ctx
->CompileFlag
);
189 if (mode
> GL_POLYGON
) {
190 _mesa_error( ctx
, GL_INVALID_ENUM
, "_tnl_Begin(0x%x)", mode
);
194 if (ctx
->Driver
.CurrentExecPrimitive
!= PRIM_OUTSIDE_BEGIN_END
) {
195 _mesa_error( ctx
, GL_INVALID_OPERATION
, "_tnl_Begin" );
200 _mesa_update_state(ctx
);
203 struct immediate
*IM
= TNL_CURRENT_IM(ctx
);
204 if (IM
->Count
> IMM_MAXDATA
-8) {
205 _tnl_flush_immediate( ctx
, IM
);
206 IM
= TNL_CURRENT_IM(ctx
);
212 struct immediate
*IM
= TNL_CURRENT_IM(ctx
);
213 GLuint count
= IM
->Count
;
214 GLuint last
= IM
->LastPrimitive
;
216 if (IM
->Start
== IM
->Count
&&
217 tnl
->Driver
.NotifyBegin
&&
218 tnl
->Driver
.NotifyBegin( ctx
, mode
)) {
222 assert( (IM
->SavedBeginState
& (VERT_BEGIN_0
|VERT_BEGIN_1
)) == 0 );
223 assert( (IM
->BeginState
& (VERT_BEGIN_0
|VERT_BEGIN_1
)) == 0 );
225 /* Not quite right. Need to use the fallback '_aa_ArrayElement'
226 * when not known to be inside begin/end and arrays are
229 if (IM
->FlushElt
== FLUSH_ELT_EAGER
) {
230 _tnl_translate_array_elts( ctx
, IM
, last
, count
);
233 IM
->Flag
[count
] |= VERT_BIT_BEGIN
;
234 IM
->Primitive
[count
] = mode
| PRIM_BEGIN
;
235 IM
->PrimitiveLength
[last
] = count
- last
;
236 IM
->LastPrimitive
= count
;
237 IM
->BeginState
= (VERT_BEGIN_0
|VERT_BEGIN_1
);
239 /* _mesa_debug(ctx, "%s: %x\n", __FUNCTION__, IM->BeginState); */
241 ctx
->Driver
.NeedFlush
|= FLUSH_STORED_VERTICES
;
242 ctx
->Driver
.CurrentExecPrimitive
= mode
;
247 /* Function which allows operations like 'glRectf' to decompose to a
248 * begin/end object and vertices without worrying about what happens
249 * with display lists.
252 _tnl_hard_begin( GLcontext
*ctx
, GLenum p
)
254 /* _mesa_debug(ctx, "%s\n", __FUNCTION__); */
256 if (!ctx
->CompileFlag
) {
257 /* If not compiling, treat as a normal begin().
259 /* _mesa_debug(ctx, "%s: treating as glBegin\n", __FUNCTION__); */
264 /* Otherwise, need to do special processing to preserve the
265 * condition that these vertices will only be replayed outside
266 * future begin/end objects.
268 struct immediate
*IM
= TNL_CURRENT_IM(ctx
);
271 _mesa_update_state(ctx
);
273 if (IM
->Count
> IMM_MAXDATA
-8) {
274 _tnl_flush_immediate( ctx
, IM
);
275 IM
= TNL_CURRENT_IM(ctx
);
278 /* A lot depends on the degree to which the display list has
279 * constrained the possible begin/end states at this point:
281 switch (IM
->BeginState
& (VERT_BEGIN_0
|VERT_BEGIN_1
)) {
282 case VERT_BEGIN_0
|VERT_BEGIN_1
:
283 /* This is an immediate known to be inside a begin/end object.
285 ASSERT(ctx
->Driver
.CurrentSavePrimitive
<= GL_POLYGON
);
286 IM
->BeginState
|= (VERT_ERROR_1
|VERT_ERROR_0
);
291 /* This is a display-list immediate in an unknown begin/end
292 * state. Assert it is empty and convert it to a 'hard' one.
294 ASSERT(IM
->SavedBeginState
== 0);
295 ASSERT(ctx
->Driver
.CurrentSavePrimitive
== PRIM_UNKNOWN
);
297 /* Push current beginstate, to be restored later. Don't worry
298 * about raising errors.
300 IM
->SavedBeginState
= IM
->BeginState
;
305 /* Unless we have fallen through, this is an immediate known to
306 * be outside begin/end objects.
308 ASSERT(ctx
->Driver
.CurrentSavePrimitive
== PRIM_UNKNOWN
||
309 ctx
->Driver
.CurrentSavePrimitive
== PRIM_OUTSIDE_BEGIN_END
);
310 ASSERT (IM
->FlushElt
!= FLUSH_ELT_EAGER
);
312 IM
->BeginState
|= VERT_BEGIN_0
|VERT_BEGIN_1
;
313 IM
->Flag
[IM
->Count
] |= VERT_BIT_BEGIN
;
314 IM
->Primitive
[IM
->Count
] = p
| PRIM_BEGIN
;
315 IM
->PrimitiveLength
[IM
->LastPrimitive
] = IM
->Count
- IM
->LastPrimitive
;
316 IM
->LastPrimitive
= IM
->Count
;
318 /* This is necessary as this immediate will not be flushed in
319 * _tnl_end() -- we leave it active, hoping to pick up more
320 * vertices before the next state change.
322 ctx
->Driver
.NeedFlush
|= FLUSH_STORED_VERTICES
;
337 /* Both streams now outside begin/end.
339 * Leave SavedBeginState untouched -- attempt to gather several
340 * rects/arrays together in a single immediate struct.
343 _tnl_end( GLcontext
*ctx
)
345 struct immediate
*IM
= TNL_CURRENT_IM(ctx
);
346 GLuint state
= IM
->BeginState
;
347 GLuint inflags
= (~state
) & (VERT_BEGIN_0
|VERT_BEGIN_1
);
349 /* Not the case if vertices emitted without calling glBegin first:
351 /* assert( ctx->Driver.NeedFlush & FLUSH_STORED_VERTICES ); */
354 state
|= inflags
<< 2; /* errors */
356 if (inflags
!= (VERT_BEGIN_0
|VERT_BEGIN_1
))
358 GLuint count
= IM
->Count
;
359 GLuint last
= IM
->LastPrimitive
;
361 state
&= ~(VERT_BEGIN_0
|VERT_BEGIN_1
); /* update state */
362 IM
->Flag
[count
] |= VERT_BIT_END
;
363 IM
->Primitive
[last
] |= PRIM_END
;
364 IM
->PrimitiveLength
[last
] = count
- last
;
365 IM
->Primitive
[count
] = PRIM_OUTSIDE_BEGIN_END
; /* removes PRIM_BEGIN
366 * flag if length == 0
368 IM
->LastPrimitive
= count
;
370 if (IM
->FlushElt
== FLUSH_ELT_EAGER
) {
371 _tnl_translate_array_elts( ctx
, IM
, last
, count
);
375 IM
->BeginState
= state
;
377 if (!ctx
->CompileFlag
) {
378 if (ctx
->Driver
.CurrentExecPrimitive
== PRIM_OUTSIDE_BEGIN_END
)
379 _mesa_error( ctx
, GL_INVALID_OPERATION
, "_tnl_End" );
381 ctx
->Driver
.CurrentExecPrimitive
= PRIM_OUTSIDE_BEGIN_END
;
384 /* You can set this flag to get the old 'flush_vb on glEnd()'
387 if (MESA_DEBUG_FLAGS
& DEBUG_ALWAYS_FLUSH
)
388 _tnl_flush_immediate( ctx
, IM
);
394 GET_CURRENT_CONTEXT(ctx
);
398 /* Need to keep save primitive uptodate in COMPILE and
399 * COMPILE_AND_EXEC modes, need to keep exec primitive uptodate
402 if (ctx
->CompileFlag
)
403 ctx
->Driver
.CurrentSavePrimitive
= PRIM_OUTSIDE_BEGIN_END
;
407 #define COLOR( r, g, b, a ) \
410 GLuint count = IM->Count; \
411 GLfloat *color = IM->Attrib[VERT_ATTRIB_COLOR0][count]; \
412 IM->Flag[count] |= VERT_BIT_COLOR0; \
420 _tnl_Color3f( GLfloat red
, GLfloat green
, GLfloat blue
)
422 COLOR( red
, green
, blue
, 1.0 );
426 _tnl_Color3ub( GLubyte red
, GLubyte green
, GLubyte blue
)
428 COLOR(UBYTE_TO_FLOAT(red
),
429 UBYTE_TO_FLOAT(green
),
430 UBYTE_TO_FLOAT(blue
),
435 _tnl_Color4f( GLfloat red
, GLfloat green
, GLfloat blue
, GLfloat alpha
)
437 COLOR( red
, green
, blue
, alpha
);
441 _tnl_Color4ub( GLubyte red
, GLubyte green
, GLubyte blue
, GLubyte alpha
)
443 COLOR(UBYTE_TO_FLOAT(red
),
444 UBYTE_TO_FLOAT(green
),
445 UBYTE_TO_FLOAT(blue
),
446 UBYTE_TO_FLOAT(alpha
));
450 _tnl_Color3fv( const GLfloat
*v
)
452 COLOR( v
[0], v
[1], v
[2], 1.0 );
456 _tnl_Color3ubv( const GLubyte
*v
)
458 COLOR(UBYTE_TO_FLOAT(v
[0]),
459 UBYTE_TO_FLOAT(v
[1]),
460 UBYTE_TO_FLOAT(v
[2]),
465 _tnl_Color4fv( const GLfloat
*v
)
467 COLOR( v
[0], v
[1], v
[2], v
[3] );
471 _tnl_Color4ubv( const GLubyte
*v
)
473 COLOR(UBYTE_TO_FLOAT(v
[0]),
474 UBYTE_TO_FLOAT(v
[1]),
475 UBYTE_TO_FLOAT(v
[2]),
476 UBYTE_TO_FLOAT(v
[3]));
482 #define SECONDARY_COLOR( r, g, b ) \
487 IM->Flag[count] |= VERT_BIT_COLOR1; \
488 IM->Attrib[VERT_ATTRIB_COLOR1][count][0] = r; \
489 IM->Attrib[VERT_ATTRIB_COLOR1][count][1] = g; \
490 IM->Attrib[VERT_ATTRIB_COLOR1][count][2] = b; \
494 _tnl_SecondaryColor3fEXT( GLfloat red
, GLfloat green
, GLfloat blue
)
496 SECONDARY_COLOR( red
, green
, blue
);
500 _tnl_SecondaryColor3ubEXT( GLubyte red
, GLubyte green
, GLubyte blue
)
502 SECONDARY_COLOR(UBYTE_TO_FLOAT(red
),
503 UBYTE_TO_FLOAT(green
),
504 UBYTE_TO_FLOAT(blue
));
508 _tnl_SecondaryColor3fvEXT( const GLfloat
*v
)
510 SECONDARY_COLOR( v
[0], v
[1], v
[2] );
514 _tnl_SecondaryColor3ubvEXT( const GLubyte
*v
)
516 SECONDARY_COLOR(UBYTE_TO_FLOAT(v
[0]),
517 UBYTE_TO_FLOAT(v
[1]),
518 UBYTE_TO_FLOAT(v
[2]));
523 _tnl_EdgeFlag( GLboolean flag
)
528 IM
->EdgeFlag
[count
] = flag
;
529 IM
->Flag
[count
] |= VERT_BIT_EDGEFLAG
;
534 _tnl_EdgeFlagv( const GLboolean
*flag
)
539 IM
->EdgeFlag
[count
] = *flag
;
540 IM
->Flag
[count
] |= VERT_BIT_EDGEFLAG
;
545 _tnl_FogCoordfEXT( GLfloat f
)
550 IM
->Attrib
[VERT_ATTRIB_FOG
][count
][0] = f
; /*FogCoord[count] = f;*/
551 IM
->Flag
[count
] |= VERT_BIT_FOG
;
555 _tnl_FogCoordfvEXT( const GLfloat
*v
)
560 IM
->Attrib
[VERT_ATTRIB_FOG
][count
][0] = v
[0]; /*FogCoord[count] = v[0];*/
561 IM
->Flag
[count
] |= VERT_BIT_FOG
;
566 _tnl_Indexi( GLint c
)
571 IM
->Index
[count
] = c
;
572 IM
->Flag
[count
] |= VERT_BIT_INDEX
;
577 _tnl_Indexiv( const GLint
*c
)
582 IM
->Index
[count
] = *c
;
583 IM
->Flag
[count
] |= VERT_BIT_INDEX
;
587 #define NORMAL( x, y, z ) \
593 IM->Flag[count] |= VERT_BIT_NORMAL; \
594 normal = IM->Attrib[VERT_ATTRIB_NORMAL][count]; \
595 ASSIGN_3V(normal, x,y,z); \
598 #if defined(USE_IEEE)
599 #define NORMALF( x, y, z ) \
605 IM->Flag[count] |= VERT_BIT_NORMAL; \
606 normal = (fi_type *)IM->Attrib[VERT_ATTRIB_NORMAL][count]; \
607 normal[0].i = ((fi_type *)&(x))->i; \
608 normal[1].i = ((fi_type *)&(y))->i; \
609 normal[2].i = ((fi_type *)&(z))->i; \
612 #define NORMALF NORMAL
616 _tnl_Normal3f( GLfloat nx
, GLfloat ny
, GLfloat nz
)
623 _tnl_Normal3fv( const GLfloat
*v
)
625 NORMALF( v
[0], v
[1], v
[2] );
626 /* struct immediate *IM = (struct immediate *)(((GLcontext *) _glapi_Context)->swtnl_im); */
627 /* IM->Flag[IM->Count] = VERT_NORM; */
632 #define TEXCOORD1(s) \
638 IM->Flag[count] |= VERT_BIT_TEX0; \
639 tc = IM->Attrib[VERT_ATTRIB_TEX0][count]; \
640 ASSIGN_4V(tc,s,0,0,1); \
643 #define TEXCOORD2(s, t) \
649 IM->Flag[count] |= VERT_BIT_TEX0; \
650 tc = IM->Attrib[VERT_ATTRIB_TEX0][count]; \
651 ASSIGN_4V(tc, s, t, 0, 1); \
654 #define TEXCOORD3(s, t, u) \
660 IM->Flag[count] |= VERT_BIT_TEX0; \
661 IM->TexSize |= TEX_0_SIZE_3; \
662 tc = IM->Attrib[VERT_ATTRIB_TEX0][count]; \
663 ASSIGN_4V(tc, s, t, u, 1); \
666 #define TEXCOORD4(s, t, u, v) \
672 IM->Flag[count] |= VERT_BIT_TEX0; \
673 IM->TexSize |= TEX_0_SIZE_4; \
674 tc = IM->Attrib[VERT_ATTRIB_TEX0][count]; \
675 ASSIGN_4V(tc, s, t, u, v); \
678 #if defined(USE_IEEE)
679 #define TEXCOORD2F(s, t) \
685 IM->Flag[count] |= VERT_BIT_TEX0; \
686 tc = (fi_type *)IM->Attrib[VERT_ATTRIB_TEX0][count]; \
687 tc[0].i = ((fi_type *)&(s))->i; \
688 tc[1].i = ((fi_type *)&(t))->i; \
690 tc[3].i = IEEE_ONE; \
693 #define TEXCOORD2F TEXCOORD2
697 _tnl_TexCoord1f( GLfloat s
)
704 _tnl_TexCoord2f( GLfloat s
, GLfloat t
)
711 _tnl_TexCoord3f( GLfloat s
, GLfloat t
, GLfloat r
)
717 _tnl_TexCoord4f( GLfloat s
, GLfloat t
, GLfloat r
, GLfloat q
)
719 TEXCOORD4(s
, t
, r
, q
)
723 _tnl_TexCoord1fv( const GLfloat
*v
)
729 _tnl_TexCoord2fv( const GLfloat
*v
)
731 TEXCOORD2F(v
[0], v
[1]);
735 _tnl_TexCoord3fv( const GLfloat
*v
)
737 TEXCOORD3(v
[0], v
[1], v
[2]);
741 _tnl_TexCoord4fv( const GLfloat
*v
)
743 TEXCOORD4(v
[0], v
[1], v
[2], v
[3]);
748 /* KW: Run into bad problems in vertex copying if we don't fully pad
749 * the incoming vertices.
751 #define VERTEX2(IM, x,y) \
753 GLuint count = IM->Count++; \
754 GLfloat *dest = IM->Attrib[VERT_ATTRIB_POS][count]; \
755 IM->Flag[count] |= VERT_BIT_POS; \
756 ASSIGN_4V(dest, x, y, 0, 1); \
757 /* ASSERT(IM->Flag[IM->Count]==0); */ \
758 if (count == IMM_MAXDATA - 1) \
759 _tnl_flush_immediate( NULL, IM ); \
762 #define VERTEX3(IM,x,y,z) \
764 GLuint count = IM->Count++; \
765 GLfloat *dest = IM->Attrib[VERT_ATTRIB_POS][count]; \
766 IM->Flag[count] |= VERT_BITS_OBJ_23; \
767 ASSIGN_4V(dest, x, y, z, 1); \
768 /* ASSERT(IM->Flag[IM->Count]==0); */ \
769 if (count == IMM_MAXDATA - 1) \
770 _tnl_flush_immediate( NULL, IM ); \
773 #define VERTEX4(IM, x,y,z,w) \
775 GLuint count = IM->Count++; \
776 GLfloat *dest = IM->Attrib[VERT_ATTRIB_POS][count]; \
777 IM->Flag[count] |= VERT_BITS_OBJ_234; \
778 ASSIGN_4V(dest, x, y, z, w); \
779 if (count == IMM_MAXDATA - 1) \
780 _tnl_flush_immediate( NULL, IM ); \
783 #if defined(USE_IEEE)
784 #define VERTEX2F(IM, x, y) \
786 GLuint count = IM->Count++; \
787 fi_type *dest = (fi_type *)IM->Attrib[VERT_ATTRIB_POS][count]; \
788 IM->Flag[count] |= VERT_BIT_POS; \
789 dest[0].i = ((fi_type *)&(x))->i; \
790 dest[1].i = ((fi_type *)&(y))->i; \
792 dest[3].i = IEEE_ONE; \
793 /* ASSERT(IM->Flag[IM->Count]==0); */ \
794 if (count == IMM_MAXDATA - 1) \
795 _tnl_flush_immediate( NULL, IM ); \
798 #define VERTEX2F VERTEX2
801 #if defined(USE_IEEE)
802 #define VERTEX3F(IM, x, y, z) \
804 GLuint count = IM->Count++; \
805 fi_type *dest = (fi_type *)IM->Attrib[VERT_ATTRIB_POS][count]; \
806 IM->Flag[count] |= VERT_BITS_OBJ_23; \
807 dest[0].i = ((fi_type *)&(x))->i; \
808 dest[1].i = ((fi_type *)&(y))->i; \
809 dest[2].i = ((fi_type *)&(z))->i; \
810 dest[3].i = IEEE_ONE; \
811 /* ASSERT(IM->Flag[IM->Count]==0); */ \
812 if (count == IMM_MAXDATA - 1) \
813 _tnl_flush_immediate( NULL, IM ); \
816 #define VERTEX3F VERTEX3
819 #if defined(USE_IEEE)
820 #define VERTEX4F(IM, x, y, z, w) \
822 GLuint count = IM->Count++; \
823 fi_type *dest = (fi_type *)IM->Attrib[VERT_ATTRIB_POS][count]; \
824 IM->Flag[count] |= VERT_BITS_OBJ_234; \
825 dest[0].i = ((fi_type *)&(x))->i; \
826 dest[1].i = ((fi_type *)&(y))->i; \
827 dest[2].i = ((fi_type *)&(z))->i; \
828 dest[3].i = ((fi_type *)&(w))->i; \
829 if (count == IMM_MAXDATA - 1) \
830 _tnl_flush_immediate( NULL, IM ); \
833 #define VERTEX4F VERTEX4
839 _tnl_Vertex2f( GLfloat x
, GLfloat y
)
842 VERTEX2F( IM
, x
, y
);
846 _tnl_Vertex3f( GLfloat x
, GLfloat y
, GLfloat z
)
849 VERTEX3F( IM
, x
, y
, z
);
852 _tnl_Vertex4f( GLfloat x
, GLfloat y
, GLfloat z
, GLfloat w
)
855 VERTEX4F( IM
, x
, y
, z
, w
);
859 _tnl_Vertex2fv( const GLfloat
*v
)
862 VERTEX2F( IM
, v
[0], v
[1] );
866 _tnl_Vertex3fv( const GLfloat
*v
)
869 VERTEX3F( IM
, v
[0], v
[1], v
[2] );
873 _tnl_Vertex4fv( const GLfloat
*v
)
876 VERTEX4F( IM
, v
[0], v
[1], v
[2], v
[3] );
883 * GL_ARB_multitexture
885 * Note: the multitexture spec says that specifying an invalid target
886 * has undefined results and does not have to generate an error. Just
887 * don't crash. We no-op on invalid targets.
890 #define MAX_TARGET (GL_TEXTURE0_ARB + MAX_TEXTURE_UNITS)
892 #define MULTI_TEXCOORD1(target, s) \
895 GLuint texunit = target - GL_TEXTURE0_ARB; \
896 if (texunit < IM->MaxTextureUnits) { \
897 GLuint count = IM->Count; \
898 GLfloat *tc = IM->Attrib[VERT_ATTRIB_TEX0 + texunit][count]; \
899 ASSIGN_4V(tc, s, 0.0F, 0.0F, 1.0F); \
900 IM->Flag[count] |= VERT_BIT_TEX(texunit); \
904 #define MULTI_TEXCOORD2(target, s, t) \
907 GLuint texunit = target - GL_TEXTURE0_ARB; \
908 if (texunit < IM->MaxTextureUnits) { \
909 GLuint count = IM->Count; \
910 GLfloat *tc = IM->Attrib[VERT_ATTRIB_TEX0 + texunit][count]; \
911 ASSIGN_4V(tc, s, t, 0.0F, 1.0F); \
912 IM->Flag[count] |= VERT_BIT_TEX(texunit); \
916 #define MULTI_TEXCOORD3(target, s, t, u) \
919 GLuint texunit = target - GL_TEXTURE0_ARB; \
920 if (texunit < IM->MaxTextureUnits) { \
921 GLuint count = IM->Count; \
922 GLfloat *tc = IM->Attrib[VERT_ATTRIB_TEX0 + texunit][count]; \
923 ASSIGN_4V(tc, s, t, u, 1.0F); \
924 IM->Flag[count] |= VERT_BIT_TEX(texunit); \
925 IM->TexSize |= TEX_SIZE_3(texunit); \
929 #define MULTI_TEXCOORD4(target, s, t, u, v) \
932 GLuint texunit = target - GL_TEXTURE0_ARB; \
933 if (texunit < IM->MaxTextureUnits) { \
934 GLuint count = IM->Count; \
935 GLfloat *tc = IM->Attrib[VERT_ATTRIB_TEX0 + texunit][count]; \
936 ASSIGN_4V(tc, s, t, u, v); \
937 IM->Flag[count] |= VERT_BIT_TEX(texunit); \
938 IM->TexSize |= TEX_SIZE_4(texunit); \
942 #if defined(USE_IEEE)
943 #define MULTI_TEXCOORD2F(target, s, t) \
946 GLuint texunit = target - GL_TEXTURE0_ARB; \
947 if (texunit < IM->MaxTextureUnits) { \
948 GLuint count = IM->Count; \
949 fi_type *tc = (fi_type *)IM->Attrib[VERT_ATTRIB_TEX0 + texunit][count];\
950 IM->Flag[count] |= VERT_BIT_TEX(texunit); \
951 tc[0].i = ((fi_type *)&(s))->i; \
952 tc[1].i = ((fi_type *)&(t))->i; \
954 tc[3].i = IEEE_ONE; \
958 #define MULTI_TEXCOORD2F MULTI_TEXCOORD2
962 _tnl_MultiTexCoord1fARB(GLenum target
, GLfloat s
)
964 MULTI_TEXCOORD1( target
, s
);
968 _tnl_MultiTexCoord1fvARB(GLenum target
, const GLfloat
*v
)
970 MULTI_TEXCOORD1( target
, v
[0] );
974 _tnl_MultiTexCoord2fARB(GLenum target
, GLfloat s
, GLfloat t
)
976 MULTI_TEXCOORD2F( target
, s
, t
);
980 _tnl_MultiTexCoord2fvARB(GLenum target
, const GLfloat
*v
)
982 MULTI_TEXCOORD2F( target
, v
[0], v
[1] );
986 _tnl_MultiTexCoord3fARB(GLenum target
, GLfloat s
, GLfloat t
, GLfloat r
)
988 MULTI_TEXCOORD3( target
, s
, t
, r
);
992 _tnl_MultiTexCoord3fvARB(GLenum target
, const GLfloat
*v
)
994 MULTI_TEXCOORD3( target
, v
[0], v
[1], v
[2] );
998 _tnl_MultiTexCoord4fARB(GLenum target
, GLfloat s
, GLfloat t
, GLfloat r
, GLfloat q
)
1000 MULTI_TEXCOORD4( target
, s
, t
, r
, q
);
1004 _tnl_MultiTexCoord4fvARB(GLenum target
, const GLfloat
*v
)
1006 MULTI_TEXCOORD4( target
, v
[0], v
[1], v
[2], v
[3] );
1011 /* KW: Because the eval values don't become 'current', fixup will flow
1012 * through these vertices, and then evaluation will write on top
1013 * of the fixup results.
1015 * Note: using Obj to hold eval coord data.
1017 #define EVALCOORD1(IM, x) \
1019 GLuint count = IM->Count++; \
1020 GLfloat *dest = IM->Attrib[VERT_ATTRIB_POS][count]; \
1021 IM->Flag[count] |= VERT_BIT_EVAL_C1; \
1022 ASSIGN_4V(dest, x, 0, 0, 1); \
1023 if (count == IMM_MAXDATA-1) \
1024 _tnl_flush_immediate( NULL, IM ); \
1027 #define EVALCOORD2(IM, x, y) \
1029 GLuint count = IM->Count++; \
1030 GLfloat *dest = IM->Attrib[VERT_ATTRIB_POS][count]; \
1031 IM->Flag[count] |= VERT_BIT_EVAL_C2; \
1032 ASSIGN_4V(dest, x, y, 0, 1); \
1033 if (count == IMM_MAXDATA-1) \
1034 _tnl_flush_immediate( NULL, IM ); \
1037 #define EVALPOINT1(IM, x) \
1039 GLuint count = IM->Count++; \
1040 GLfloat *dest = IM->Attrib[VERT_ATTRIB_POS][count]; \
1041 IM->Flag[count] |= VERT_BIT_EVAL_P1; \
1042 ASSIGN_4V(dest, x, 0, 0, 1); \
1043 if (count == IMM_MAXDATA-1) \
1044 _tnl_flush_immediate( NULL, IM ); \
1047 #define EVALPOINT2(IM, x, y) \
1049 GLuint count = IM->Count++; \
1050 GLfloat *dest = IM->Attrib[VERT_ATTRIB_POS][count]; \
1051 IM->Flag[count] |= VERT_BIT_EVAL_P2; \
1052 ASSIGN_4V(dest, x, y, 0, 1); \
1053 if (count == IMM_MAXDATA-1) \
1054 _tnl_flush_immediate( NULL, IM ); \
1058 _tnl_EvalCoord1f( GLfloat u
)
1061 EVALCOORD1( IM
, u
);
1065 _tnl_EvalCoord1fv( const GLfloat
*u
)
1068 EVALCOORD1( IM
, (GLfloat
) *u
);
1072 _tnl_EvalCoord2f( GLfloat u
, GLfloat v
)
1075 EVALCOORD2( IM
, u
, v
);
1079 _tnl_EvalCoord2fv( const GLfloat
*u
)
1082 EVALCOORD2( IM
, u
[0], u
[1] );
1087 _tnl_EvalPoint1( GLint i
)
1090 EVALPOINT1( IM
, (GLfloat
) i
);
1095 _tnl_EvalPoint2( GLint i
, GLint j
)
1098 EVALPOINT2( IM
, (GLfloat
) i
, (GLfloat
) j
);
1102 /* Need to use the default array-elt outside begin/end for strict
1105 #define ARRAY_ELT( IM, i ) \
1107 GLuint count = IM->Count; \
1108 IM->Elt[count] = i; \
1109 IM->Flag[count] &= IM->ArrayEltFlags; \
1110 IM->Flag[count] |= VERT_BIT_ELT; \
1111 IM->FlushElt = IM->ArrayEltFlush; \
1112 IM->Count += IM->ArrayEltIncr; \
1113 if (IM->Count == IMM_MAXDATA) \
1114 _tnl_flush_immediate( NULL, IM ); \
1119 _tnl_ArrayElement( GLint i
)
1126 /* Internal functions. These are safe to use providing either:
1128 * - It is determined that a display list is not being compiled, or
1129 * if so that these commands won't be compiled into the list (see
1130 * t_eval.c for an example).
1132 * - _tnl_hard_begin() is used instead of _tnl_[bB]egin, and tested
1133 * for a GL_TRUE return value. See _tnl_Rectf, below.
1136 _tnl_eval_coord1f( GLcontext
*CC
, GLfloat u
)
1138 struct immediate
*i
= TNL_CURRENT_IM(CC
);
1143 _tnl_eval_coord2f( GLcontext
*CC
, GLfloat u
, GLfloat v
)
1145 struct immediate
*i
= TNL_CURRENT_IM(CC
);
1146 EVALCOORD2( i
, u
, v
);
1157 _tnl_VertexAttrib4fNV( GLuint index
, GLfloat x
, GLfloat y
, GLfloat z
, GLfloat w
)
1161 const GLuint count
= IM
->Count
;
1162 GLfloat
*attrib
= IM
->Attrib
[index
][count
];
1163 ASSIGN_4V(attrib
, x
, y
, z
, w
);
1164 IM
->Flag
[count
] |= (1 << index
);
1167 if (count
== IMM_MAXDATA
- 1)
1168 _tnl_flush_immediate( NULL
, IM
);
1172 GET_CURRENT_CONTEXT(ctx
);
1173 _mesa_error(ctx
, GL_INVALID_VALUE
, "glVertexAttribNV(index > 15)");
1178 _tnl_VertexAttrib4fvNV( GLuint index
, const GLfloat
*v
)
1182 const GLuint count
= IM
->Count
;
1183 GLfloat
*attrib
= IM
->Attrib
[index
][count
];
1185 IM
->Flag
[count
] |= (1 << index
);
1188 if (count
== IMM_MAXDATA
- 1)
1189 _tnl_flush_immediate( NULL
, IM
);
1193 GET_CURRENT_CONTEXT(ctx
);
1194 _mesa_error(ctx
, GL_INVALID_VALUE
, "glVertexAttribNV(index > 15)");
1199 /* Execute a glRectf() function. _tnl_hard_begin() ensures the check
1200 * on outside_begin_end is executed even in compiled lists. These
1201 * vertices can now participate in the same immediate as regular ones,
1202 * even in most display lists.
1205 _tnl_Rectf( GLfloat x1
, GLfloat y1
, GLfloat x2
, GLfloat y2
)
1207 GET_CURRENT_CONTEXT(ctx
);
1209 if (_tnl_hard_begin( ctx
, GL_QUADS
)) {
1210 glVertex2f( x1
, y1
);
1211 glVertex2f( x2
, y1
);
1212 glVertex2f( x2
, y2
);
1213 glVertex2f( x1
, y2
);
1219 _tnl_Materialfv( GLenum face
, GLenum pname
, const GLfloat
*params
)
1221 GET_CURRENT_CONTEXT(ctx
);
1222 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
1223 struct immediate
*IM
= TNL_CURRENT_IM(ctx
);
1224 GLuint count
= IM
->Count
;
1225 struct gl_material
*mat
;
1226 GLuint bitmask
= _mesa_material_bitmask(ctx
, face
, pname
, ~0, "Materialfv");
1231 if (MESA_VERBOSE
& VERBOSE_API
)
1232 _mesa_debug(ctx
, "_tnl_Materialfv\n");
1234 if (tnl
->IsolateMaterials
&&
1235 !(IM
->BeginState
& VERT_BEGIN_1
)) /* heuristic */
1237 _tnl_flush_immediate( ctx
, IM
);
1238 IM
= TNL_CURRENT_IM(ctx
);
1242 if (!(IM
->Flag
[count
] & VERT_BIT_MATERIAL
)) {
1243 if (!IM
->Material
) {
1244 IM
->Material
= (struct gl_material (*)[2])
1245 MALLOC( sizeof(struct gl_material
) * IMM_SIZE
* 2 );
1246 IM
->MaterialMask
= (GLuint
*) MALLOC( sizeof(GLuint
) * IMM_SIZE
);
1247 IM
->MaterialMask
[IM
->LastMaterial
] = 0;
1249 else if (IM
->MaterialOrMask
& ~bitmask
) {
1250 _mesa_copy_material_pairs( IM
->Material
[count
],
1251 IM
->Material
[IM
->LastMaterial
],
1252 IM
->MaterialOrMask
& ~bitmask
);
1255 IM
->Flag
[count
] |= VERT_BIT_MATERIAL
;
1256 IM
->MaterialMask
[count
] = 0;
1257 IM
->MaterialAndMask
&= IM
->MaterialMask
[IM
->LastMaterial
];
1258 IM
->LastMaterial
= count
;
1261 IM
->MaterialOrMask
|= bitmask
;
1262 IM
->MaterialMask
[count
] |= bitmask
;
1263 mat
= IM
->Material
[count
];
1265 if (bitmask
& FRONT_AMBIENT_BIT
) {
1266 COPY_4FV( mat
[0].Ambient
, params
);
1268 if (bitmask
& BACK_AMBIENT_BIT
) {
1269 COPY_4FV( mat
[1].Ambient
, params
);
1271 if (bitmask
& FRONT_DIFFUSE_BIT
) {
1272 COPY_4FV( mat
[0].Diffuse
, params
);
1274 if (bitmask
& BACK_DIFFUSE_BIT
) {
1275 COPY_4FV( mat
[1].Diffuse
, params
);
1277 if (bitmask
& FRONT_SPECULAR_BIT
) {
1278 COPY_4FV( mat
[0].Specular
, params
);
1280 if (bitmask
& BACK_SPECULAR_BIT
) {
1281 COPY_4FV( mat
[1].Specular
, params
);
1283 if (bitmask
& FRONT_EMISSION_BIT
) {
1284 COPY_4FV( mat
[0].Emission
, params
);
1286 if (bitmask
& BACK_EMISSION_BIT
) {
1287 COPY_4FV( mat
[1].Emission
, params
);
1289 if (bitmask
& FRONT_SHININESS_BIT
) {
1290 GLfloat shininess
= CLAMP( params
[0], 0.0F
, 128.0F
);
1291 mat
[0].Shininess
= shininess
;
1293 if (bitmask
& BACK_SHININESS_BIT
) {
1294 GLfloat shininess
= CLAMP( params
[0], 0.0F
, 128.0F
);
1295 mat
[1].Shininess
= shininess
;
1297 if (bitmask
& FRONT_INDEXES_BIT
) {
1298 mat
[0].AmbientIndex
= params
[0];
1299 mat
[0].DiffuseIndex
= params
[1];
1300 mat
[0].SpecularIndex
= params
[2];
1302 if (bitmask
& BACK_INDEXES_BIT
) {
1303 mat
[1].AmbientIndex
= params
[0];
1304 mat
[1].DiffuseIndex
= params
[1];
1305 mat
[1].SpecularIndex
= params
[2];
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
;