3 * Mesa 3-D graphics library
6 * Copyright (C) 1999-2000 Brian Paul All Rights Reserved.
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
15 * The above copyright notice and this permission notice shall be included
16 * in all copies or substantial portions of the Software.
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
22 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 * Keith Whitwell <keith@precisioninsight.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( struct immediate
*IM
)
52 GLcontext
*ctx
= IM
->backref
;
55 _tnl_compile_cassette( ctx
, IM
);
57 _tnl_execute_cassette( ctx
, IM
);
61 void _tnl_flush_vertices( GLcontext
*ctx
, GLuint flags
)
63 struct immediate
*IM
= TNL_CURRENT_IM(ctx
);
65 if (IM
->Flag
[IM
->Start
])
66 if ((flags
& FLUSH_UPDATE_CURRENT
) || IM
->Count
> IM
->Start
)
67 _tnl_flush_immediate( IM
);
72 _tnl_begin( GLcontext
*ctx
, GLenum p
)
74 struct immediate
*IM
= TNL_CURRENT_IM(ctx
);
75 GLuint inflags
, state
;
77 if (MESA_VERBOSE
&VERBOSE_API
)
78 fprintf(stderr
, "glBegin(IM %d) %s\n", IM
->id
, gl_lookup_enum_by_nr(p
));
83 /* if only a very few slots left, might as well flush now
85 if (IM
->Count
> IMM_MAXDATA
-8) {
86 _tnl_flush_immediate( IM
);
87 IM
= TNL_CURRENT_IM(ctx
);
90 /* Check for and flush buffered vertices from internal operations.
92 if (IM
->SavedBeginState
) {
93 _tnl_flush_immediate( IM
);
94 IM
= TNL_CURRENT_IM(ctx
);
95 IM
->BeginState
= IM
->SavedBeginState
;
96 IM
->SavedBeginState
= 0;
99 state
= IM
->BeginState
;
100 inflags
= state
& (VERT_BEGIN_0
|VERT_BEGIN_1
);
101 state
|= inflags
<< 2; /* set error conditions */
103 if (inflags
!= (VERT_BEGIN_0
|VERT_BEGIN_1
))
105 GLuint count
= IM
->Count
;
106 GLuint last
= IM
->LastPrimitive
;
108 ASSERT(IM
->Primitive
[IM
->LastPrimitive
] & PRIM_LAST
);
110 state
|= (VERT_BEGIN_0
|VERT_BEGIN_1
);
111 IM
->Flag
[count
] |= VERT_BEGIN
;
112 IM
->Primitive
[IM
->LastPrimitive
] &= ~PRIM_LAST
;
113 IM
->Primitive
[count
] = p
| PRIM_BEGIN
| PRIM_LAST
;
114 IM
->PrimitiveLength
[IM
->LastPrimitive
] = count
- IM
->LastPrimitive
;
115 IM
->LastPrimitive
= count
;
117 /* Not quite right. Need to use the fallback '_aa_ArrayElement'
118 * when not known to be inside begin/end and arrays are unlocked.
121 _tnl_translate_array_elts( ctx
, IM
, last
, count
);
126 ctx
->Driver
.NeedFlush
|= FLUSH_STORED_VERTICES
;
127 IM
->BeginState
= state
;
133 _tnl_Begin( GLenum mode
)
135 GET_CURRENT_CONTEXT(ctx
);
137 if (mode
> GL_POLYGON
) {
138 _mesa_compile_error( ctx
, GL_INVALID_ENUM
, "glBegin" );
142 _tnl_begin(ctx
, mode
);
144 /* If compiling update SavePrimitive now.
146 * In compile_and_exec mode, exec_primitive will be updated when
147 * the cassette is finished.
149 * If not compiling, update exec_primitive now.
151 if (ctx
->CompileFlag
) {
152 if (ctx
->Driver
.CurrentSavePrimitive
== PRIM_UNKNOWN
)
153 ctx
->Driver
.CurrentSavePrimitive
= PRIM_INSIDE_UNKNOWN_PRIM
;
154 else if (ctx
->Driver
.CurrentSavePrimitive
== PRIM_OUTSIDE_BEGIN_END
)
155 ctx
->Driver
.CurrentSavePrimitive
= mode
;
157 else if (ctx
->Driver
.CurrentExecPrimitive
== PRIM_OUTSIDE_BEGIN_END
)
158 ctx
->Driver
.CurrentExecPrimitive
= mode
;
163 _tnl_hard_begin( GLcontext
*ctx
, GLenum p
)
165 struct immediate
*IM
= TNL_CURRENT_IM(ctx
);
169 gl_update_state(ctx
);
171 /* If not compiling, treat as a normal begin().
173 if (!ctx
->CompileFlag
) {
174 _tnl_begin( ctx
, p
);
176 /* Set this for the duration:
178 ctx
->Driver
.CurrentExecPrimitive
= p
;
182 if (IM
->Count
> IMM_MAXDATA
-8) {
183 _tnl_flush_immediate( IM
);
184 IM
= TNL_CURRENT_IM(ctx
);
187 switch (IM
->BeginState
& (VERT_BEGIN_0
|VERT_BEGIN_1
)) {
188 case VERT_BEGIN_0
|VERT_BEGIN_1
:
189 /* This is an immediate known to be inside a begin/end object.
191 IM
->BeginState
|= (VERT_ERROR_1
|VERT_ERROR_0
);
196 /* This is a display-list immediate in an unknown begin/end
197 * state. Assert it is empty and conviert it to a 'hard' one.
199 ASSERT (IM
->SavedBeginState
== 0);
201 /* ASSERT (ctx->Driver.CurrentSavePrimitive >= GL_POLYGON+1); */
203 /* Push current beginstate, to be restored later. Don't worry
204 * about raising errors.
206 IM
->SavedBeginState
= IM
->BeginState
;
210 /* Unless we have fallen through, this is an immediate known to
211 * be outside begin/end objects.
214 IM
->BeginState
|= VERT_BEGIN_0
|VERT_BEGIN_1
;
218 last
= IM
->LastPrimitive
;
220 ASSERT(IM
->Primitive
[IM
->LastPrimitive
] & PRIM_LAST
);
222 IM
->Flag
[count
] |= VERT_BEGIN
;
223 IM
->Primitive
[last
] &= ~PRIM_LAST
;
224 IM
->Primitive
[count
] = p
| PRIM_BEGIN
| PRIM_LAST
;
225 IM
->PrimitiveLength
[last
] = count
- last
;
226 IM
->LastPrimitive
= count
;
228 ASSERT (!IM
->FlushElt
);
230 /* This is necessary as this immediate will not be flushed in
231 * _tnl_end() -- we leave it active, hoping to pick up more
232 * vertices before the next state change.
234 ctx
->Driver
.NeedFlush
|= FLUSH_STORED_VERTICES
;
246 /* Need to do this to get the correct begin/end error behaviour from
247 * functions like ColorPointerEXT which are still active in
248 * SAVE_AND_EXEC modes.
251 _tnl_save_Begin( GLenum mode
)
253 GET_CURRENT_CONTEXT(ctx
);
255 if (mode
> GL_POLYGON
) {
256 _mesa_compile_error( ctx
, GL_INVALID_ENUM
, "glBegin" );
260 if (ctx
->ExecuteFlag
) {
261 /* Preserve vtxfmt invarient:
264 gl_update_state( ctx
);
266 /* Slot in geomexec: No need to call setdispatch as we know
267 * CurrentDispatch is Save.
269 ASSERT(ctx
->CurrentDispatch
== ctx
->Save
);
272 _tnl_begin( ctx
, mode
);
278 /* Note the continuation of a partially completed primitive. For
279 * driver t&l fallbacks between begin/end primitives. Has basically
280 * the same effects as a primitive wrapping onto a second immediate
283 * ==> Can actually call this from _tnl_wakeup_exec, taking mode from
284 * ctx->Driver.CurrentExecPrimitive.
287 void _tnl_fallback_begin( GLcontext
*ctx
, GLenum mode
)
289 struct immediate
*IM
= TNL_CURRENT_IM(ctx
);
290 ASSERT( IM
->Count
== IM
->Start
);
291 ASSERT( IM
->Flag
[IM
->Start
] == 0 );
292 ASSERT( mode
< GL_POLYGON
+1 );
293 _tnl_begin( ctx
, mode
);
294 IM
->Primitive
[IM
->Start
] &= ~PRIM_BEGIN
;
299 /* Both streams now outside begin/end.
301 * Leave SavedBeginState untouched -- attempt to gather several
302 * rects/arrays together in a single immediate struct.
305 _tnl_end( GLcontext
*ctx
)
307 struct immediate
*IM
= TNL_CURRENT_IM(ctx
);
308 GLuint state
= IM
->BeginState
;
309 GLuint inflags
= (~state
) & (VERT_BEGIN_0
|VERT_BEGIN_1
);
311 state
|= inflags
<< 2; /* errors */
313 if (inflags
!= (VERT_BEGIN_0
|VERT_BEGIN_1
))
315 GLuint count
= IM
->Count
;
316 GLuint last
= IM
->LastPrimitive
;
318 ASSERT(IM
->Primitive
[IM
->LastPrimitive
] & PRIM_LAST
);
320 state
&= ~(VERT_BEGIN_0
|VERT_BEGIN_1
); /* update state */
321 IM
->Flag
[count
] |= VERT_END
;
322 IM
->Primitive
[last
] |= PRIM_END
;
323 IM
->Primitive
[last
] &= ~PRIM_LAST
;
324 IM
->PrimitiveLength
[last
] = count
- last
;
325 IM
->Primitive
[count
] = (GL_POLYGON
+1) | PRIM_LAST
;
326 IM
->LastPrimitive
= count
;
329 _tnl_translate_array_elts( ctx
, IM
, last
, count
);
333 /* ctx->Driver.NeedFlush |= FLUSH_STORED_VERTICES; */
336 IM
->BeginState
= state
;
338 if (!ctx
->CompileFlag
)
339 ctx
->Driver
.CurrentExecPrimitive
= PRIM_OUTSIDE_BEGIN_END
;
342 /* You can set this flag to get the old 'flush_vb on glEnd()'
345 if ((MESA_DEBUG_FLAGS
&DEBUG_ALWAYS_FLUSH
))
346 _tnl_flush_immediate( IM
);
352 GET_CURRENT_CONTEXT(ctx
);
355 /* Need to keep save primitive uptodate in COMPILE and
356 * COMPILE_AND_EXEC modes, need to keep exec primitive uptodate
359 if (ctx
->CompileFlag
)
360 ctx
->Driver
.CurrentSavePrimitive
= PRIM_OUTSIDE_BEGIN_END
;
364 #define COLOR( IM, r, g, b, a ) \
366 GLuint count = IM->Count; \
367 IM->Flag[count] |= VERT_RGBA; \
368 IM->Color[count][0] = r; \
369 IM->Color[count][1] = g; \
370 IM->Color[count][2] = b; \
371 IM->Color[count][3] = a; \
374 #define COLORV( IM, v ) \
376 GLuint count = IM->Count; \
377 IM->Flag[count] |= VERT_RGBA; \
378 COPY_CHAN4(IM->Color[count], v); \
383 _tnl_Color3f( GLfloat red
, GLfloat green
, GLfloat blue
)
387 UNCLAMPED_FLOAT_TO_CHAN(col
[0], red
);
388 UNCLAMPED_FLOAT_TO_CHAN(col
[1], green
);
389 UNCLAMPED_FLOAT_TO_CHAN(col
[2], blue
);
396 _tnl_Color3ub( GLubyte red
, GLubyte green
, GLubyte blue
)
400 COLOR( IM
, red
, green
, blue
, CHAN_MAX
);
405 UBYTE_TO_CHAN(green
),
415 _tnl_Color4f( GLfloat red
, GLfloat green
, GLfloat blue
, GLfloat alpha
)
419 UNCLAMPED_FLOAT_TO_CHAN(col
[0], red
);
420 UNCLAMPED_FLOAT_TO_CHAN(col
[1], green
);
421 UNCLAMPED_FLOAT_TO_CHAN(col
[2], blue
);
422 UNCLAMPED_FLOAT_TO_CHAN(col
[3], alpha
);
427 _tnl_Color4ub( GLubyte red
, GLubyte green
, GLubyte blue
, GLubyte alpha
)
432 UBYTE_TO_CHAN(green
),
434 UBYTE_TO_CHAN(alpha
));
439 _tnl_Color3fv( const GLfloat
*v
)
443 UNCLAMPED_FLOAT_TO_CHAN(col
[0], v
[0]);
444 UNCLAMPED_FLOAT_TO_CHAN(col
[1], v
[1]);
445 UNCLAMPED_FLOAT_TO_CHAN(col
[2], v
[2]);
453 _tnl_Color3ubv( const GLubyte
*v
)
464 _tnl_Color4fv( const GLfloat
*v
)
468 UNCLAMPED_FLOAT_TO_CHAN(col
[0], v
[0]);
469 UNCLAMPED_FLOAT_TO_CHAN(col
[1], v
[1]);
470 UNCLAMPED_FLOAT_TO_CHAN(col
[2], v
[2]);
471 UNCLAMPED_FLOAT_TO_CHAN(col
[3], v
[3]);
478 _tnl_Color4ubv( const GLubyte
*v
)
485 UBYTE_TO_CHAN(v
[3]));
491 #define SECONDARY_COLOR( IM, r, g, b ) \
493 GLuint count = IM->Count; \
494 IM->Flag[count] |= VERT_SPEC_RGB; \
495 IM->SecondaryColor[count][0] = r; \
496 IM->SecondaryColor[count][1] = g; \
497 IM->SecondaryColor[count][2] = b; \
500 #define SECONDARY_COLORV( IM, v ) \
502 GLuint count = IM->Count; \
503 IM->Flag[count] |= VERT_SPEC_RGB; \
504 IM->SecondaryColor[count][0] = v[0]; \
505 IM->SecondaryColor[count][1] = v[1]; \
506 IM->SecondaryColor[count][2] = v[2]; \
513 _tnl_SecondaryColor3fEXT( GLfloat red
, GLfloat green
, GLfloat blue
)
517 UNCLAMPED_FLOAT_TO_CHAN(col
[0], red
);
518 UNCLAMPED_FLOAT_TO_CHAN(col
[1], green
);
519 UNCLAMPED_FLOAT_TO_CHAN(col
[2], blue
);
520 SECONDARY_COLORV( IM
, col
);
526 _tnl_SecondaryColor3ubEXT( GLubyte red
, GLubyte green
, GLubyte blue
)
531 UBYTE_TO_CHAN(green
),
532 UBYTE_TO_CHAN(blue
));
539 _tnl_SecondaryColor3fvEXT( const GLfloat
*v
)
543 UNCLAMPED_FLOAT_TO_CHAN(col
[0], v
[0]);
544 UNCLAMPED_FLOAT_TO_CHAN(col
[1], v
[1]);
545 UNCLAMPED_FLOAT_TO_CHAN(col
[2], v
[2]);
546 SECONDARY_COLORV( IM
, col
);
552 _tnl_SecondaryColor3ubvEXT( const GLubyte
*v
)
558 UBYTE_TO_CHAN(v
[2]));
565 _tnl_EdgeFlag( GLboolean flag
)
570 IM
->EdgeFlag
[count
] = flag
;
571 IM
->Flag
[count
] |= VERT_EDGE
;
576 _tnl_EdgeFlagv( const GLboolean
*flag
)
581 IM
->EdgeFlag
[count
] = *flag
;
582 IM
->Flag
[count
] |= VERT_EDGE
;
587 _tnl_FogCoordfEXT( GLfloat f
)
592 IM
->FogCoord
[count
] = f
;
593 IM
->Flag
[count
] |= VERT_FOG_COORD
;
597 _tnl_FogCoordfvEXT( const GLfloat
*v
)
602 IM
->FogCoord
[count
] = v
[0];
603 IM
->Flag
[count
] |= VERT_FOG_COORD
;
608 _tnl_Indexi( GLint c
)
613 IM
->Index
[count
] = c
;
614 IM
->Flag
[count
] |= VERT_INDEX
;
619 _tnl_Indexiv( const GLint
*c
)
624 IM
->Index
[count
] = *c
;
625 IM
->Flag
[count
] |= VERT_INDEX
;
629 #define NORMAL( x, y, z ) \
635 IM->Flag[count] |= VERT_NORM; \
636 normal = IM->Normal[count]; \
637 ASSIGN_3V(normal, x,y,z); \
640 #if defined(USE_IEEE)
641 #define NORMALF( x, y, z ) \
647 IM->Flag[count] |= VERT_NORM; \
648 normal = (GLint *)IM->Normal[count]; \
649 ASSIGN_3V(normal, *(int*)&(x), *(int*)&(y), *(int*)&(z)); \
652 #define NORMALF NORMAL
656 _tnl_Normal3f( GLfloat nx
, GLfloat ny
, GLfloat nz
)
663 _tnl_Normal3fv( const GLfloat
*v
)
665 NORMALF( v
[0], v
[1], v
[2] );
670 #define TEXCOORD1(s) \
676 IM->Flag[count] |= VERT_TEX0; \
677 tc = IM->TexCoord0[count]; \
678 ASSIGN_4V(tc,s,0,0,1); \
681 #define TEXCOORD2(s,t) \
687 IM->Flag[count] |= VERT_TEX0; \
688 tc = IM->TexCoord0[count]; \
689 ASSIGN_4V(tc, s,t,0,1); \
692 #define TEXCOORD3(s,t,u) \
698 IM->Flag[count] |= VERT_TEX0; \
699 IM->TexSize |= TEX_0_SIZE_3; \
700 tc = IM->TexCoord0[count]; \
701 ASSIGN_4V(tc, s,t,u,1); \
704 #define TEXCOORD4(s,t,u,v) \
710 IM->Flag[count] |= VERT_TEX0; \
711 IM->TexSize |= TEX_0_SIZE_4; \
712 tc = IM->TexCoord0[count]; \
713 ASSIGN_4V(tc, s,t,u,v); \
716 #if defined(USE_IEEE)
717 #define TEXCOORD2F(s,t) \
723 IM->Flag[count] |= VERT_TEX0; \
724 tc = (GLint *)IM->TexCoord0[count]; \
725 tc[0] = *(GLint *)&(s); \
726 tc[1] = *(GLint *)&(t); \
731 #define TEXCOORD2F TEXCOORD2
735 _tnl_TexCoord1f( GLfloat s
)
742 _tnl_TexCoord2f( GLfloat s
, GLfloat t
)
749 _tnl_TexCoord3f( GLfloat s
, GLfloat t
, GLfloat r
)
755 _tnl_TexCoord4f( GLfloat s
, GLfloat t
, GLfloat r
, GLfloat q
)
761 _tnl_TexCoord1fv( const GLfloat
*v
)
767 _tnl_TexCoord2fv( const GLfloat
*v
)
769 TEXCOORD2F(v
[0],v
[1]);
773 _tnl_TexCoord3fv( const GLfloat
*v
)
775 TEXCOORD3(v
[0],v
[1],v
[2]);
779 _tnl_TexCoord4fv( const GLfloat
*v
)
781 TEXCOORD4(v
[0],v
[1],v
[2],v
[3]);
786 /* KW: Run into bad problems in vertex copying if we don't fully pad
787 * the incoming vertices.
789 #define VERTEX2(IM, x,y) \
791 GLuint count = IM->Count++; \
792 GLfloat *dest = IM->Obj[count]; \
793 IM->Flag[count] |= VERT_OBJ; \
794 ASSIGN_4V(dest, x, y, 0, 1); \
795 /* ASSERT(IM->Flag[IM->Count]==0); */\
796 if (count == IMM_MAXDATA - 1) \
797 _tnl_flush_immediate( IM ); \
800 #define VERTEX3(IM,x,y,z) \
802 GLuint count = IM->Count++; \
803 GLfloat *dest = IM->Obj[count]; \
804 IM->Flag[count] |= VERT_OBJ_23; \
805 ASSIGN_4V(dest, x, y, z, 1); \
806 /* ASSERT(IM->Flag[IM->Count]==0); */ \
807 if (count == IMM_MAXDATA - 1) \
808 _tnl_flush_immediate( IM ); \
811 #define VERTEX4(IM, x,y,z,w) \
813 GLuint count = IM->Count++; \
814 GLfloat *dest = IM->Obj[count]; \
815 IM->Flag[count] |= VERT_OBJ_234; \
816 ASSIGN_4V(dest, x, y, z, w); \
817 if (count == IMM_MAXDATA - 1) \
818 _tnl_flush_immediate( IM ); \
821 #if defined(USE_IEEE)
822 #define VERTEX2F(IM, x, y) \
824 GLuint count = IM->Count++; \
825 GLint *dest = (GLint *)IM->Obj[count]; \
826 IM->Flag[count] |= VERT_OBJ; \
827 dest[0] = *(GLint *)&(x); \
828 dest[1] = *(GLint *)&(y); \
830 dest[3] = IEEE_ONE; \
831 /* ASSERT(IM->Flag[IM->Count]==0); */ \
832 if (count == IMM_MAXDATA - 1) \
833 _tnl_flush_immediate( IM ); \
836 #define VERTEX2F VERTEX2
839 #if defined(USE_IEEE)
840 #define VERTEX3F(IM, x, y, z) \
842 GLuint count = IM->Count++; \
843 GLint *dest = (GLint *)IM->Obj[count]; \
844 IM->Flag[count] |= VERT_OBJ_23; \
845 dest[0] = *(GLint *)&(x); \
846 dest[1] = *(GLint *)&(y); \
847 dest[2] = *(GLint *)&(z); \
848 dest[3] = IEEE_ONE; \
849 /* ASSERT(IM->Flag[IM->Count]==0); */ \
850 if (count == IMM_MAXDATA - 1) \
851 _tnl_flush_immediate( IM ); \
854 #define VERTEX3F VERTEX3
857 #if defined(USE_IEEE)
858 #define VERTEX4F(IM, x, y, z, w) \
860 GLuint count = IM->Count++; \
861 GLint *dest = (GLint *)IM->Obj[count]; \
862 IM->Flag[count] |= VERT_OBJ_234; \
863 dest[0] = *(GLint *)&(x); \
864 dest[1] = *(GLint *)&(y); \
865 dest[2] = *(GLint *)&(z); \
866 dest[3] = *(GLint *)&(w); \
867 if (count == IMM_MAXDATA - 1) \
868 _tnl_flush_immediate( IM ); \
871 #define VERTEX4F VERTEX4
877 _tnl_Vertex2f( GLfloat x
, GLfloat y
)
880 VERTEX2F( IM
, x
, y
);
884 _tnl_Vertex3f( GLfloat x
, GLfloat y
, GLfloat z
)
887 VERTEX3F( IM
, x
, y
, z
);
890 _tnl_Vertex4f( GLfloat x
, GLfloat y
, GLfloat z
, GLfloat w
)
893 VERTEX4F( IM
, x
, y
, z
, w
);
897 _tnl_Vertex2fv( const GLfloat
*v
)
900 VERTEX2F( IM
, v
[0], v
[1] );
904 _tnl_Vertex3fv( const GLfloat
*v
)
907 VERTEX3F( IM
, v
[0], v
[1], v
[2] );
911 _tnl_Vertex4fv( const GLfloat
*v
)
914 VERTEX4F( IM
, v
[0], v
[1], v
[2], v
[3] );
921 * GL_ARB_multitexture
923 * Note: the multitexture spec says that specifying an invalid target
924 * has undefined results and does not have to generate an error. Just
925 * don't crash. We no-op on invalid targets.
928 #define MAX_TARGET (GL_TEXTURE0_ARB + MAX_TEXTURE_UNITS)
930 #define MULTI_TEXCOORD1(target, s) \
933 GLuint texunit = target - GL_TEXTURE0_ARB; \
934 if (texunit < IM->MaxTextureUnits) { \
935 GLuint count = IM->Count; \
936 GLfloat *tc = IM->TexCoord[texunit][count]; \
937 ASSIGN_4V(tc, s, 0.0F, 0.0F, 1.0F); \
938 IM->Flag[count] |= VERT_TEX(texunit); \
942 #define MULTI_TEXCOORD2(target, s, t) \
945 GLuint texunit = target - GL_TEXTURE0_ARB; \
946 if (texunit < IM->MaxTextureUnits) { \
947 GLuint count = IM->Count; \
948 GLfloat *tc = IM->TexCoord[texunit][count]; \
949 ASSIGN_4V(tc, s, t, 0.0F, 1.0F); \
950 IM->Flag[count] |= VERT_TEX(texunit); \
954 #define MULTI_TEXCOORD3(target, s, t, u) \
957 GLuint texunit = target - GL_TEXTURE0_ARB; \
958 if (texunit < IM->MaxTextureUnits) { \
959 GLuint count = IM->Count; \
960 GLfloat *tc = IM->TexCoord[texunit][count]; \
961 ASSIGN_4V(tc, s, t, u, 1.0F); \
962 IM->Flag[count] |= VERT_TEX(texunit); \
963 IM->TexSize |= TEX_SIZE_3(texunit); \
967 #define MULTI_TEXCOORD4(target, s, t, u, v) \
970 GLuint texunit = target - GL_TEXTURE0_ARB; \
971 if (texunit < IM->MaxTextureUnits) { \
972 GLuint count = IM->Count; \
973 GLfloat *tc = IM->TexCoord[texunit][count]; \
974 ASSIGN_4V(tc, s, t, u, v); \
975 IM->Flag[count] |= VERT_TEX(texunit); \
976 IM->TexSize |= TEX_SIZE_4(texunit); \
980 #if defined(USE_IEEE)
981 #define MULTI_TEXCOORD2F(target, s, t) \
984 GLuint texunit = target - GL_TEXTURE0_ARB; \
985 if (texunit < IM->MaxTextureUnits) { \
986 GLuint count = IM->Count; \
987 GLint *tc = (GLint *)IM->TexCoord[texunit][count]; \
988 IM->Flag[count] |= VERT_TEX(texunit); \
989 tc[0] = *(int *)&(s); \
990 tc[1] = *(int *)&(t); \
996 #define MULTI_TEXCOORD2F MULTI_TEXCOORD2
1000 _tnl_MultiTexCoord1fARB(GLenum target
, GLfloat s
)
1002 MULTI_TEXCOORD1( target
, s
);
1006 _tnl_MultiTexCoord1fvARB(GLenum target
, const GLfloat
*v
)
1008 MULTI_TEXCOORD1( target
, v
[0] );
1012 _tnl_MultiTexCoord2fARB(GLenum target
, GLfloat s
, GLfloat t
)
1014 MULTI_TEXCOORD2F( target
, s
, t
);
1018 _tnl_MultiTexCoord2fvARB(GLenum target
, const GLfloat
*v
)
1020 MULTI_TEXCOORD2F( target
, v
[0], v
[1] );
1024 _tnl_MultiTexCoord3fARB(GLenum target
, GLfloat s
, GLfloat t
, GLfloat r
)
1026 MULTI_TEXCOORD3( target
, s
, t
, r
);
1030 _tnl_MultiTexCoord3fvARB(GLenum target
, const GLfloat
*v
)
1032 MULTI_TEXCOORD3( target
, v
[0], v
[1], v
[2] );
1036 _tnl_MultiTexCoord4fARB(GLenum target
, GLfloat s
, GLfloat t
, GLfloat r
, GLfloat q
)
1038 MULTI_TEXCOORD4( target
, s
, t
, r
, q
);
1042 _tnl_MultiTexCoord4fvARB(GLenum target
, const GLfloat
*v
)
1044 MULTI_TEXCOORD4( target
, v
[0], v
[1], v
[2], v
[3] );
1049 /* KW: Because the eval values don't become 'current', fixup will flow
1050 * through these vertices, and then evaluation will write on top
1051 * of the fixup results.
1053 * Note: using Obj to hold eval coord data.
1055 #define EVALCOORD1(IM, x) \
1057 GLuint count = IM->Count++; \
1058 IM->Flag[count] |= VERT_EVAL_C1; \
1059 ASSIGN_4V(IM->Obj[count], x, 0, 0, 1); \
1060 if (count == IMM_MAXDATA-1) \
1061 _tnl_flush_immediate( IM ); \
1064 #define EVALCOORD2(IM, x, y) \
1066 GLuint count = IM->Count++; \
1067 IM->Flag[count] |= VERT_EVAL_C2; \
1068 ASSIGN_4V(IM->Obj[count], x, y, 0, 1); \
1069 if (count == IMM_MAXDATA-1) \
1070 _tnl_flush_immediate( IM ); \
1073 #define EVALPOINT1(IM, x) \
1075 GLuint count = IM->Count++; \
1076 IM->Flag[count] |= VERT_EVAL_P1; \
1077 ASSIGN_4V(IM->Obj[count], x, 0, 0, 1); \
1078 if (count == IMM_MAXDATA-1) \
1079 _tnl_flush_immediate( IM ); \
1082 #define EVALPOINT2(IM, x, y) \
1084 GLuint count = IM->Count++; \
1085 IM->Flag[count] |= VERT_EVAL_P2; \
1086 ASSIGN_4V(IM->Obj[count], x, y, 0, 1); \
1087 if (count == IMM_MAXDATA-1) \
1088 _tnl_flush_immediate( IM ); \
1092 _tnl_EvalCoord1f( GLfloat u
)
1095 EVALCOORD1( IM
, u
);
1099 _tnl_EvalCoord1fv( const GLfloat
*u
)
1102 EVALCOORD1( IM
, (GLfloat
) *u
);
1106 _tnl_EvalCoord2f( GLfloat u
, GLfloat v
)
1109 EVALCOORD2( IM
, u
, v
);
1113 _tnl_EvalCoord2fv( const GLfloat
*u
)
1116 EVALCOORD2( IM
, u
[0], u
[1] );
1121 _tnl_EvalPoint1( GLint i
)
1124 EVALPOINT1( IM
, i
);
1129 _tnl_EvalPoint2( GLint i
, GLint j
)
1132 EVALPOINT2( IM
, i
, j
);
1136 /* Need to use the default array-elt outside begin/end for strict
1139 #define ARRAY_ELT( IM, i ) \
1141 GLuint count = IM->Count; \
1142 IM->Elt[count] = i; \
1143 IM->Flag[count] &= IM->ArrayEltFlags; \
1144 IM->Flag[count] |= VERT_ELT; \
1145 IM->FlushElt |= IM->ArrayEltFlush; \
1146 IM->Count += IM->ArrayEltIncr; \
1147 if (IM->Count == IMM_MAXDATA) \
1148 _tnl_flush_immediate( IM ); \
1153 _tnl_ArrayElement( GLint i
)
1160 /* Internal functions. These are safe to use providing either:
1162 * - It is determined that a display list is not being compiled, or
1163 * if so that these commands won't be compiled into the list (see
1164 * t_eval.c for an example).
1166 * - _tnl_hard_begin() is used instead of _tnl_[bB]egin, and tested
1167 * for a GL_TRUE return value. See _tnl_Rectf, below.
1170 _tnl_eval_coord1f( GLcontext
*CC
, GLfloat u
)
1172 struct immediate
*i
= TNL_CURRENT_IM(CC
);
1177 _tnl_eval_coord2f( GLcontext
*CC
, GLfloat u
, GLfloat v
)
1179 struct immediate
*i
= TNL_CURRENT_IM(CC
);
1180 EVALCOORD2( i
, u
, v
);
1184 _tnl_array_element( GLcontext
*CC
, GLint i
)
1186 struct immediate
*im
= TNL_CURRENT_IM(CC
);
1191 _tnl_vertex2f( GLcontext
*ctx
, GLfloat x
, GLfloat y
)
1193 struct immediate
*im
= TNL_CURRENT_IM(ctx
);
1194 VERTEX2( im
, x
, y
);
1201 /* Execute a glRectf() function. _tnl_hard_begin() ensures the check
1202 * on outside_begin_end is executed even in compiled lists. These
1203 * vertices can now participate in the same VB as regular ones, even
1204 * in most display lists.
1207 _tnl_Rectf( GLfloat x1
, GLfloat y1
, GLfloat x2
, GLfloat y2
)
1209 GET_CURRENT_CONTEXT(ctx
);
1211 if (_tnl_hard_begin( ctx
, GL_QUADS
)) {
1212 _tnl_vertex2f( ctx
, x1
, y1
);
1213 _tnl_vertex2f( ctx
, x2
, y1
);
1214 _tnl_vertex2f( ctx
, x2
, y2
);
1215 _tnl_vertex2f( ctx
, x1
, y2
);
1221 _tnl_Materialfv( GLenum face
, GLenum pname
, const GLfloat
*params
)
1223 GET_CURRENT_CONTEXT(ctx
);
1224 struct immediate
*IM
= TNL_CURRENT_IM(ctx
);
1225 GLuint count
= IM
->Count
;
1226 struct gl_material
*mat
;
1227 GLuint bitmask
= gl_material_bitmask( ctx
, face
, pname
, ~0, "Materialfv" );
1232 if (!IM
->Material
) {
1233 IM
->Material
= (GLmaterial (*)[2]) MALLOC( sizeof(GLmaterial
) *
1235 IM
->MaterialMask
= (GLuint
*) MALLOC( sizeof(GLuint
) * IMM_SIZE
);
1238 if (!(IM
->Flag
[count
] & VERT_MATERIAL
)) {
1239 IM
->Flag
[count
] |= VERT_MATERIAL
;
1240 IM
->MaterialMask
[count
] = 0;
1243 IM
->MaterialMask
[count
] |= bitmask
;
1244 mat
= IM
->Material
[count
];
1246 if (bitmask
& FRONT_AMBIENT_BIT
) {
1247 COPY_4FV( mat
[0].Ambient
, params
);
1249 if (bitmask
& BACK_AMBIENT_BIT
) {
1250 COPY_4FV( mat
[1].Ambient
, params
);
1252 if (bitmask
& FRONT_DIFFUSE_BIT
) {
1253 COPY_4FV( mat
[0].Diffuse
, params
);
1255 if (bitmask
& BACK_DIFFUSE_BIT
) {
1256 COPY_4FV( mat
[1].Diffuse
, params
);
1258 if (bitmask
& FRONT_SPECULAR_BIT
) {
1259 COPY_4FV( mat
[0].Specular
, params
);
1261 if (bitmask
& BACK_SPECULAR_BIT
) {
1262 COPY_4FV( mat
[1].Specular
, params
);
1264 if (bitmask
& FRONT_EMISSION_BIT
) {
1265 COPY_4FV( mat
[0].Emission
, params
);
1267 if (bitmask
& BACK_EMISSION_BIT
) {
1268 COPY_4FV( mat
[1].Emission
, params
);
1270 if (bitmask
& FRONT_SHININESS_BIT
) {
1271 GLfloat shininess
= CLAMP( params
[0], 0.0F
, 128.0F
);
1272 mat
[0].Shininess
= shininess
;
1274 if (bitmask
& BACK_SHININESS_BIT
) {
1275 GLfloat shininess
= CLAMP( params
[0], 0.0F
, 128.0F
);
1276 mat
[1].Shininess
= shininess
;
1278 if (bitmask
& FRONT_INDEXES_BIT
) {
1279 mat
[0].AmbientIndex
= params
[0];
1280 mat
[0].DiffuseIndex
= params
[1];
1281 mat
[0].SpecularIndex
= params
[2];
1283 if (bitmask
& BACK_INDEXES_BIT
) {
1284 mat
[1].AmbientIndex
= params
[0];
1285 mat
[1].DiffuseIndex
= params
[1];
1286 mat
[1].SpecularIndex
= params
[2];
1290 void _tnl_imm_vtxfmt_init( GLcontext
*ctx
)
1292 GLvertexformat
*vfmt
= &(TNL_CONTEXT(ctx
)->vtxfmt
);
1294 /* All begin/end operations are handled by this vertex format:
1296 vfmt
->ArrayElement
= _tnl_ArrayElement
;
1297 vfmt
->Begin
= _tnl_Begin
;
1298 vfmt
->Color3f
= _tnl_Color3f
;
1299 vfmt
->Color3fv
= _tnl_Color3fv
;
1300 vfmt
->Color3ub
= _tnl_Color3ub
;
1301 vfmt
->Color3ubv
= _tnl_Color3ubv
;
1302 vfmt
->Color4f
= _tnl_Color4f
;
1303 vfmt
->Color4fv
= _tnl_Color4fv
;
1304 vfmt
->Color4ub
= _tnl_Color4ub
;
1305 vfmt
->Color4ubv
= _tnl_Color4ubv
;
1306 vfmt
->EdgeFlag
= _tnl_EdgeFlag
;
1307 vfmt
->EdgeFlagv
= _tnl_EdgeFlagv
;
1308 vfmt
->End
= _tnl_End
;
1309 vfmt
->EvalCoord1f
= _tnl_EvalCoord1f
;
1310 vfmt
->EvalCoord1fv
= _tnl_EvalCoord1fv
;
1311 vfmt
->EvalCoord2f
= _tnl_EvalCoord2f
;
1312 vfmt
->EvalCoord2fv
= _tnl_EvalCoord2fv
;
1313 vfmt
->EvalPoint1
= _tnl_EvalPoint1
;
1314 vfmt
->EvalPoint2
= _tnl_EvalPoint2
;
1315 vfmt
->FogCoordfEXT
= _tnl_FogCoordfEXT
;
1316 vfmt
->FogCoordfvEXT
= _tnl_FogCoordfvEXT
;
1317 vfmt
->Indexi
= _tnl_Indexi
;
1318 vfmt
->Indexiv
= _tnl_Indexiv
;
1319 vfmt
->Materialfv
= _tnl_Materialfv
;
1320 vfmt
->MultiTexCoord1fARB
= _tnl_MultiTexCoord1fARB
;
1321 vfmt
->MultiTexCoord1fvARB
= _tnl_MultiTexCoord1fvARB
;
1322 vfmt
->MultiTexCoord2fARB
= _tnl_MultiTexCoord2fARB
;
1323 vfmt
->MultiTexCoord2fvARB
= _tnl_MultiTexCoord2fvARB
;
1324 vfmt
->MultiTexCoord3fARB
= _tnl_MultiTexCoord3fARB
;
1325 vfmt
->MultiTexCoord3fvARB
= _tnl_MultiTexCoord3fvARB
;
1326 vfmt
->MultiTexCoord4fARB
= _tnl_MultiTexCoord4fARB
;
1327 vfmt
->MultiTexCoord4fvARB
= _tnl_MultiTexCoord4fvARB
;
1328 vfmt
->Normal3f
= _tnl_Normal3f
;
1329 vfmt
->Normal3fv
= _tnl_Normal3fv
;
1330 vfmt
->SecondaryColor3fEXT
= _tnl_SecondaryColor3fEXT
;
1331 vfmt
->SecondaryColor3fvEXT
= _tnl_SecondaryColor3fvEXT
;
1332 vfmt
->SecondaryColor3ubEXT
= _tnl_SecondaryColor3ubEXT
;
1333 vfmt
->SecondaryColor3ubvEXT
= _tnl_SecondaryColor3ubvEXT
;
1334 vfmt
->TexCoord1f
= _tnl_TexCoord1f
;
1335 vfmt
->TexCoord1fv
= _tnl_TexCoord1fv
;
1336 vfmt
->TexCoord2f
= _tnl_TexCoord2f
;
1337 vfmt
->TexCoord2fv
= _tnl_TexCoord2fv
;
1338 vfmt
->TexCoord3f
= _tnl_TexCoord3f
;
1339 vfmt
->TexCoord3fv
= _tnl_TexCoord3fv
;
1340 vfmt
->TexCoord4f
= _tnl_TexCoord4f
;
1341 vfmt
->TexCoord4fv
= _tnl_TexCoord4fv
;
1342 vfmt
->Vertex2f
= _tnl_Vertex2f
;
1343 vfmt
->Vertex2fv
= _tnl_Vertex2fv
;
1344 vfmt
->Vertex3f
= _tnl_Vertex3f
;
1345 vfmt
->Vertex3fv
= _tnl_Vertex3fv
;
1346 vfmt
->Vertex4f
= _tnl_Vertex4f
;
1347 vfmt
->Vertex4fv
= _tnl_Vertex4fv
;
1349 /* Outside begin/end functions (from t_varray.c, t_eval.c, ...):
1351 vfmt
->Rectf
= _tnl_Rectf
;
1353 /* Just use the core function:
1355 vfmt
->CallList
= _mesa_CallList
;
1357 vfmt
->prefer_float_colors
= GL_FALSE
;