3
* Mesa 3-D graphics library
6
* Copyright (C) 1999-2001 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 <keithw@valinux.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;
54
if (MESA_VERBOSE & VERBOSE_IMMEDIATE)
55
fprintf(stderr, "_tnl_flush_immediate IM: %d compiling: %d\n",
56
IM->id, ctx->CompileFlag);
58
if (IM->FlushElt == FLUSH_ELT_EAGER) {
59
_tnl_translate_array_elts( ctx, IM, IM->LastPrimitive, IM->Count );
62
/* Mark the last primitive:
64
IM->PrimitiveLength[IM->LastPrimitive] = IM->Count - IM->LastPrimitive;
65
IM->Primitive[IM->LastPrimitive] |= PRIM_LAST;
68
_tnl_compile_cassette( ctx, IM );
70
_tnl_execute_cassette( ctx, IM );
74
/* Hook for ctx->Driver.FlushVertices:
76
void _tnl_flush_vertices( GLcontext *ctx, GLuint flags )
78
struct immediate *IM = TNL_CURRENT_IM(ctx);
80
if (MESA_VERBOSE & VERBOSE_IMMEDIATE)
82
"_tnl_flush_vertices flags %x IM(%d) %d..%d Flag[%d]: %x\n",
83
flags, IM->id, IM->Start, IM->Count, IM->Start,
86
if (IM->Flag[IM->Start])
87
if ((flags & FLUSH_UPDATE_CURRENT) ||
88
IM->Count > IM->Start ||
89
(IM->Flag[IM->Start] & (VERT_BEGIN|VERT_END)))
90
_tnl_flush_immediate( IM );
97
_tnl_save_Begin( GLenum mode )
99
GET_CURRENT_CONTEXT(ctx);
100
struct immediate *IM = TNL_CURRENT_IM(ctx);
101
GLuint inflags, state;
103
/* fprintf(stderr, "%s: before: %x\n", __FUNCTION__, IM->BeginState); */
105
if (mode > GL_POLYGON) {
106
_mesa_compile_error( ctx, GL_INVALID_ENUM, "_tnl_Begin" );
111
_mesa_update_state(ctx);
113
if (IM->Count > IMM_MAXDATA-8) {
114
_tnl_flush_immediate( IM );
115
IM = TNL_CURRENT_IM(ctx);
118
/* Check for and flush buffered vertices from internal operations.
120
if (IM->SavedBeginState) {
121
_tnl_flush_immediate( IM );
122
IM = TNL_CURRENT_IM(ctx);
123
IM->BeginState = IM->SavedBeginState;
124
IM->SavedBeginState = 0;
127
state = IM->BeginState;
128
inflags = state & (VERT_BEGIN_0|VERT_BEGIN_1);
129
state |= inflags << 2; /* set error conditions */
131
if (inflags != (VERT_BEGIN_0|VERT_BEGIN_1))
133
GLuint count = IM->Count;
134
GLuint last = IM->LastPrimitive;
136
state |= (VERT_BEGIN_0|VERT_BEGIN_1);
137
IM->Flag[count] |= VERT_BEGIN;
138
IM->Primitive[count] = mode | PRIM_BEGIN;
139
IM->PrimitiveLength[IM->LastPrimitive] = count - IM->LastPrimitive;
140
IM->LastPrimitive = count;
142
/* Not quite right. Need to use the fallback '_aa_ArrayElement'
143
* when not known to be inside begin/end and arrays are
146
if (IM->FlushElt == FLUSH_ELT_EAGER) {
147
_tnl_translate_array_elts( ctx, IM, last, count );
151
ctx->Driver.NeedFlush |= FLUSH_STORED_VERTICES;
152
IM->BeginState = state;
154
/* Update save_primitive now. Don't touch ExecPrimitive as this is
155
* updated in the replay of this cassette if we are in
156
* COMPILE_AND_EXECUTE mode.
158
if (ctx->Driver.CurrentSavePrimitive == PRIM_UNKNOWN)
159
ctx->Driver.CurrentSavePrimitive = PRIM_INSIDE_UNKNOWN_PRIM;
160
else if (ctx->Driver.CurrentSavePrimitive == PRIM_OUTSIDE_BEGIN_END)
161
ctx->Driver.CurrentSavePrimitive = mode;
166
_tnl_Begin( GLenum mode )
168
GET_CURRENT_CONTEXT(ctx);
169
TNLcontext *tnl = TNL_CONTEXT(ctx);
170
ASSERT (!ctx->CompileFlag);
172
if (mode > GL_POLYGON) {
173
_mesa_error( ctx, GL_INVALID_ENUM, "_tnl_Begin" );
177
if (ctx->Driver.CurrentExecPrimitive != PRIM_OUTSIDE_BEGIN_END) {
178
_mesa_error( ctx, GL_INVALID_OPERATION, "_tnl_Begin" );
183
_mesa_update_state(ctx);
186
struct immediate *IM = TNL_CURRENT_IM(ctx);
187
if (IM->Count > IMM_MAXDATA-8) {
188
_tnl_flush_immediate( IM );
189
IM = TNL_CURRENT_IM(ctx);
195
struct immediate *IM = TNL_CURRENT_IM(ctx);
196
GLuint count = IM->Count;
197
GLuint last = IM->LastPrimitive;
199
if (IM->Start == IM->Count &&
200
tnl->Driver.NotifyBegin &&
201
tnl->Driver.NotifyBegin( ctx, mode )) {
205
assert( (IM->SavedBeginState & (VERT_BEGIN_0|VERT_BEGIN_1)) == 0 );
206
assert( (IM->BeginState & (VERT_BEGIN_0|VERT_BEGIN_1)) == 0 );
208
/* Not quite right. Need to use the fallback '_aa_ArrayElement'
209
* when not known to be inside begin/end and arrays are
212
if (IM->FlushElt == FLUSH_ELT_EAGER) {
213
_tnl_translate_array_elts( ctx, IM, last, count );
216
IM->Flag[count] |= VERT_BEGIN;
217
IM->Primitive[count] = mode | PRIM_BEGIN;
218
IM->PrimitiveLength[last] = count - last;
219
IM->LastPrimitive = count;
220
IM->BeginState = (VERT_BEGIN_0|VERT_BEGIN_1);
222
ctx->Driver.NeedFlush |= FLUSH_STORED_VERTICES;
223
ctx->Driver.CurrentExecPrimitive = mode;
228
/* Function which allows operations like 'glRectf' to decompose to a
229
* begin/end object and vertices without worrying about what happens
230
* with display lists.
233
_tnl_hard_begin( GLcontext *ctx, GLenum p )
235
/* fprintf(stderr, "%s\n", __FUNCTION__); */
237
if (!ctx->CompileFlag) {
238
/* If not compiling, treat as a normal begin().
240
/* fprintf(stderr, "%s: treating as glBegin\n", __FUNCTION__); */
245
/* Otherwise, need to do special processing to preserve the
246
* condition that these vertices will only be replayed outside
247
* future begin/end objects.
249
struct immediate *IM = TNL_CURRENT_IM(ctx);
252
_mesa_update_state(ctx);
254
if (IM->Count > IMM_MAXDATA-8) {
255
_tnl_flush_immediate( IM );
256
IM = TNL_CURRENT_IM(ctx);
259
/* A lot depends on the degree to which the display list has
260
* constrained the possible begin/end states at this point:
262
switch (IM->BeginState & (VERT_BEGIN_0|VERT_BEGIN_1)) {
263
case VERT_BEGIN_0|VERT_BEGIN_1:
264
/* This is an immediate known to be inside a begin/end object.
266
ASSERT(ctx->Driver.CurrentSavePrimitive <= GL_POLYGON);
267
IM->BeginState |= (VERT_ERROR_1|VERT_ERROR_0);
272
/* This is a display-list immediate in an unknown begin/end
273
* state. Assert it is empty and convert it to a 'hard' one.
275
ASSERT(IM->SavedBeginState == 0);
276
ASSERT(ctx->Driver.CurrentSavePrimitive == PRIM_UNKNOWN);
278
/* Push current beginstate, to be restored later. Don't worry
279
* about raising errors.
281
IM->SavedBeginState = IM->BeginState;
286
/* Unless we have fallen through, this is an immediate known to
287
* be outside begin/end objects.
289
ASSERT(ctx->Driver.CurrentSavePrimitive == PRIM_UNKNOWN ||
290
ctx->Driver.CurrentSavePrimitive == PRIM_OUTSIDE_BEGIN_END);
291
ASSERT (IM->FlushElt != FLUSH_ELT_EAGER);
293
IM->BeginState |= VERT_BEGIN_0|VERT_BEGIN_1;
294
IM->Flag[IM->Count] |= VERT_BEGIN;
295
IM->Primitive[IM->Count] = p | PRIM_BEGIN;
296
IM->PrimitiveLength[IM->LastPrimitive] = IM->Count - IM->LastPrimitive;
297
IM->LastPrimitive = IM->Count;
299
/* This is necessary as this immediate will not be flushed in
300
* _tnl_end() -- we leave it active, hoping to pick up more
301
* vertices before the next state change.
303
ctx->Driver.NeedFlush |= FLUSH_STORED_VERTICES;
318
/* Both streams now outside begin/end.
320
* Leave SavedBeginState untouched -- attempt to gather several
321
* rects/arrays together in a single immediate struct.
324
_tnl_end( GLcontext *ctx )
326
struct immediate *IM = TNL_CURRENT_IM(ctx);
327
GLuint state = IM->BeginState;
328
GLuint inflags = (~state) & (VERT_BEGIN_0|VERT_BEGIN_1);
330
/* Not the case if vertices emitted without calling glBegin first:
332
/* assert( ctx->Driver.NeedFlush & FLUSH_STORED_VERTICES ); */
335
state |= inflags << 2; /* errors */
337
if (inflags != (VERT_BEGIN_0|VERT_BEGIN_1))
339
GLuint count = IM->Count;
340
GLuint last = IM->LastPrimitive;
342
state &= ~(VERT_BEGIN_0|VERT_BEGIN_1); /* update state */
343
IM->Flag[count] |= VERT_END;
344
IM->Primitive[last] |= PRIM_END;
345
IM->PrimitiveLength[last] = count - last;
346
IM->Primitive[count] = PRIM_OUTSIDE_BEGIN_END; /* removes PRIM_BEGIN
347
* flag if length == 0
349
IM->LastPrimitive = count;
351
if (IM->FlushElt == FLUSH_ELT_EAGER) {
352
_tnl_translate_array_elts( ctx, IM, last, count );
356
IM->BeginState = state;
358
/* Only update CurrentExecPrimitive if not compiling. If we are in
359
* COMPILE_AND_EXECUTE mode, it will be done on replay of this
362
if (!ctx->CompileFlag) {
363
if (ctx->Driver.CurrentExecPrimitive == PRIM_OUTSIDE_BEGIN_END)
364
_mesa_error( ctx, GL_INVALID_OPERATION, "_tnl_End" );
366
ctx->Driver.CurrentExecPrimitive = PRIM_OUTSIDE_BEGIN_END;
369
/* You can set this flag to get the old 'flush_vb on glEnd()'
372
if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH)
373
_tnl_flush_immediate( IM );
379
GET_CURRENT_CONTEXT(ctx);
382
/* Need to keep save primitive uptodate in COMPILE and
383
* COMPILE_AND_EXEC modes, need to keep exec primitive uptodate
386
if (ctx->CompileFlag)
387
ctx->Driver.CurrentSavePrimitive = PRIM_OUTSIDE_BEGIN_END;
391
#define COLOR( IM, r, g, b, a ) \
393
GLuint count = IM->Count; \
394
IM->Flag[count] |= VERT_RGBA; \
395
IM->Color[count][0] = r; \
396
IM->Color[count][1] = g; \
397
IM->Color[count][2] = b; \
398
IM->Color[count][3] = a; \
402
_tnl_Color3f( GLfloat red, GLfloat green, GLfloat blue )
405
COLOR( IM, red, green, blue, 1.0 );
409
_tnl_Color3ub( GLubyte red, GLubyte green, GLubyte blue )
414
UBYTE_TO_FLOAT(green),
415
UBYTE_TO_FLOAT(blue),
420
_tnl_Color4f( GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha )
423
COLOR( IM, red, green, blue, alpha );
427
_tnl_Color4ub( GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha )
432
UBYTE_TO_FLOAT(green),
433
UBYTE_TO_FLOAT(blue),
434
UBYTE_TO_FLOAT(alpha));
438
_tnl_Color3fv( const GLfloat *v )
441
COLOR( IM, v[0], v[1], v[2], 1.0 );
445
_tnl_Color3ubv( const GLubyte *v )
449
UBYTE_TO_FLOAT(v[0]),
450
UBYTE_TO_FLOAT(v[1]),
451
UBYTE_TO_FLOAT(v[2]),
456
_tnl_Color4fv( const GLfloat *v )
459
COLOR( IM, v[0], v[1], v[2], v[3] );
463
_tnl_Color4ubv( const GLubyte *v)
467
UBYTE_TO_FLOAT(v[0]),
468
UBYTE_TO_FLOAT(v[1]),
469
UBYTE_TO_FLOAT(v[2]),
470
UBYTE_TO_FLOAT(v[3]));
476
#define SECONDARY_COLOR( IM, r, g, b ) \
478
GLuint count = IM->Count; \
479
IM->Flag[count] |= VERT_SPEC_RGB; \
480
IM->SecondaryColor[count][0] = r; \
481
IM->SecondaryColor[count][1] = g; \
482
IM->SecondaryColor[count][2] = b; \
486
_tnl_SecondaryColor3fEXT( GLfloat red, GLfloat green, GLfloat blue )
489
SECONDARY_COLOR( IM, red, green, blue );
493
_tnl_SecondaryColor3ubEXT( GLubyte red, GLubyte green, GLubyte blue )
498
UBYTE_TO_FLOAT(green),
499
UBYTE_TO_FLOAT(blue));
503
_tnl_SecondaryColor3fvEXT( const GLfloat *v )
506
SECONDARY_COLOR( IM, v[0], v[1], v[2] );
510
_tnl_SecondaryColor3ubvEXT( const GLubyte *v )
514
UBYTE_TO_FLOAT(v[0]),
515
UBYTE_TO_FLOAT(v[1]),
516
UBYTE_TO_FLOAT(v[2]));
523
_tnl_EdgeFlag( GLboolean flag )
528
IM->EdgeFlag[count] = flag;
529
IM->Flag[count] |= VERT_EDGE;
534
_tnl_EdgeFlagv( const GLboolean *flag )
539
IM->EdgeFlag[count] = *flag;
540
IM->Flag[count] |= VERT_EDGE;
545
_tnl_FogCoordfEXT( GLfloat f )
550
IM->FogCoord[count] = f;
551
IM->Flag[count] |= VERT_FOG_COORD;
555
_tnl_FogCoordfvEXT( const GLfloat *v )
560
IM->FogCoord[count] = v[0];
561
IM->Flag[count] |= VERT_FOG_COORD;
566
_tnl_Indexi( GLint c )
571
IM->Index[count] = c;
572
IM->Flag[count] |= VERT_INDEX;
577
_tnl_Indexiv( const GLint *c )
582
IM->Index[count] = *c;
583
IM->Flag[count] |= VERT_INDEX;
587
#define NORMAL( x, y, z ) \
593
IM->Flag[count] |= VERT_NORM; \
594
normal = IM->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_NORM; \
606
normal = (fi_type *)IM->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_TEX0; \
639
tc = IM->TexCoord0[count]; \
640
ASSIGN_4V(tc,s,0,0,1); \
643
#define TEXCOORD2(s,t) \
649
IM->Flag[count] |= VERT_TEX0; \
650
tc = IM->TexCoord0[count]; \
651
ASSIGN_4V(tc, s,t,0,1); \
654
#define TEXCOORD3(s,t,u) \
660
IM->Flag[count] |= VERT_TEX0; \
661
IM->TexSize |= TEX_0_SIZE_3; \
662
tc = IM->TexCoord0[count]; \
663
ASSIGN_4V(tc, s,t,u,1); \
666
#define TEXCOORD4(s,t,u,v) \
672
IM->Flag[count] |= VERT_TEX0; \
673
IM->TexSize |= TEX_0_SIZE_4; \
674
tc = IM->TexCoord0[count]; \
675
ASSIGN_4V(tc, s,t,u,v); \
678
#if defined(USE_IEEE)
679
#define TEXCOORD2F(s,t) \
685
IM->Flag[count] |= VERT_TEX0; \
686
tc = (fi_type *)IM->TexCoord0[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 )
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->Obj[count]; \
755
IM->Flag[count] |= VERT_OBJ; \
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( IM ); \
762
#define VERTEX3(IM,x,y,z) \
764
GLuint count = IM->Count++; \
765
GLfloat *dest = IM->Obj[count]; \
766
IM->Flag[count] |= VERT_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( IM ); \
773
#define VERTEX4(IM, x,y,z,w) \
775
GLuint count = IM->Count++; \
776
GLfloat *dest = IM->Obj[count]; \
777
IM->Flag[count] |= VERT_OBJ_234; \
778
ASSIGN_4V(dest, x, y, z, w); \
779
if (count == IMM_MAXDATA - 1) \
780
_tnl_flush_immediate( IM ); \
783
#if defined(USE_IEEE)
784
#define VERTEX2F(IM, x, y) \
786
GLuint count = IM->Count++; \
787
fi_type *dest = (fi_type *)IM->Obj[count]; \
788
IM->Flag[count] |= VERT_OBJ; \
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( 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->Obj[count]; \
806
IM->Flag[count] |= VERT_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( 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->Obj[count]; \
824
IM->Flag[count] |= VERT_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( 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->TexCoord[texunit][count]; \
899
ASSIGN_4V(tc, s, 0.0F, 0.0F, 1.0F); \
900
IM->Flag[count] |= VERT_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->TexCoord[texunit][count]; \
911
ASSIGN_4V(tc, s, t, 0.0F, 1.0F); \
912
IM->Flag[count] |= VERT_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->TexCoord[texunit][count]; \
923
ASSIGN_4V(tc, s, t, u, 1.0F); \
924
IM->Flag[count] |= VERT_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->TexCoord[texunit][count]; \
936
ASSIGN_4V(tc, s, t, u, v); \
937
IM->Flag[count] |= VERT_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->TexCoord[texunit][count]; \
950
IM->Flag[count] |= VERT_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
IM->Flag[count] |= VERT_EVAL_C1; \
1021
ASSIGN_4V(IM->Obj[count], x, 0, 0, 1); \
1022
if (count == IMM_MAXDATA-1) \
1023
_tnl_flush_immediate( IM ); \
1026
#define EVALCOORD2(IM, x, y) \
1028
GLuint count = IM->Count++; \
1029
IM->Flag[count] |= VERT_EVAL_C2; \
1030
ASSIGN_4V(IM->Obj[count], x, y, 0, 1); \
1031
if (count == IMM_MAXDATA-1) \
1032
_tnl_flush_immediate( IM ); \
1035
#define EVALPOINT1(IM, x) \
1037
GLuint count = IM->Count++; \
1038
IM->Flag[count] |= VERT_EVAL_P1; \
1039
ASSIGN_4V(IM->Obj[count], x, 0, 0, 1); \
1040
if (count == IMM_MAXDATA-1) \
1041
_tnl_flush_immediate( IM ); \
1044
#define EVALPOINT2(IM, x, y) \
1046
GLuint count = IM->Count++; \
1047
IM->Flag[count] |= VERT_EVAL_P2; \
1048
ASSIGN_4V(IM->Obj[count], x, y, 0, 1); \
1049
if (count == IMM_MAXDATA-1) \
1050
_tnl_flush_immediate( IM ); \
1054
_tnl_EvalCoord1f( GLfloat u )
1057
EVALCOORD1( IM, u );
1061
_tnl_EvalCoord1fv( const GLfloat *u )
1064
EVALCOORD1( IM, (GLfloat) *u );
1068
_tnl_EvalCoord2f( GLfloat u, GLfloat v )
1071
EVALCOORD2( IM, u, v );
1075
_tnl_EvalCoord2fv( const GLfloat *u )
1078
EVALCOORD2( IM, u[0], u[1] );
1083
_tnl_EvalPoint1( GLint i )
1086
EVALPOINT1( IM, (GLfloat) i );
1091
_tnl_EvalPoint2( GLint i, GLint j )
1094
EVALPOINT2( IM, (GLfloat) i, (GLfloat) j );
1098
/* Need to use the default array-elt outside begin/end for strict
1101
#define ARRAY_ELT( IM, i ) \
1103
GLuint count = IM->Count; \
1104
IM->Elt[count] = i; \
1105
IM->Flag[count] &= IM->ArrayEltFlags; \
1106
IM->Flag[count] |= VERT_ELT; \
1107
IM->FlushElt = IM->ArrayEltFlush; \
1108
IM->Count += IM->ArrayEltIncr; \
1109
if (IM->Count == IMM_MAXDATA) \
1110
_tnl_flush_immediate( IM ); \
1115
_tnl_ArrayElement( GLint i )
1122
/* Internal functions. These are safe to use providing either:
1124
* - It is determined that a display list is not being compiled, or
1125
* if so that these commands won't be compiled into the list (see
1126
* t_eval.c for an example).
1128
* - _tnl_hard_begin() is used instead of _tnl_[bB]egin, and tested
1129
* for a GL_TRUE return value. See _tnl_Rectf, below.
1132
_tnl_eval_coord1f( GLcontext *CC, GLfloat u )
1134
struct immediate *i = TNL_CURRENT_IM(CC);
1139
_tnl_eval_coord2f( GLcontext *CC, GLfloat u, GLfloat v )
1141
struct immediate *i = TNL_CURRENT_IM(CC);
1142
EVALCOORD2( i, u, v );
1150
/* Execute a glRectf() function. _tnl_hard_begin() ensures the check
1151
* on outside_begin_end is executed even in compiled lists. These
1152
* vertices can now participate in the same immediate as regular ones,
1153
* even in most display lists.
1156
_tnl_Rectf( GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2 )
1158
GET_CURRENT_CONTEXT(ctx);
1160
if (_tnl_hard_begin( ctx, GL_QUADS )) {
1161
glVertex2f( x1, y1 );
1162
glVertex2f( x2, y1 );
1163
glVertex2f( x2, y2 );
1164
glVertex2f( x1, y2 );
1170
_tnl_Materialfv( GLenum face, GLenum pname, const GLfloat *params )
1172
GET_CURRENT_CONTEXT(ctx);
1173
TNLcontext *tnl = TNL_CONTEXT(ctx);
1174
struct immediate *IM = TNL_CURRENT_IM(ctx);
1175
GLuint count = IM->Count;
1176
struct gl_material *mat;
1177
GLuint bitmask = _mesa_material_bitmask(ctx, face, pname, ~0, "Materialfv");
1182
if (MESA_VERBOSE & VERBOSE_API)
1183
fprintf(stderr, "_tnl_Materialfv\n");
1185
if (tnl->IsolateMaterials &&
1186
!(IM->BeginState & VERT_BEGIN_1)) /* heuristic */
1188
_tnl_flush_immediate( IM );
1189
IM = TNL_CURRENT_IM(ctx);
1193
if (!(IM->Flag[count] & VERT_MATERIAL)) {
1194
if (!IM->Material) {
1195
IM->Material = (GLmaterial (*)[2]) MALLOC( sizeof(GLmaterial) *
1197
IM->MaterialMask = (GLuint *) MALLOC( sizeof(GLuint) * IMM_SIZE );
1198
IM->MaterialMask[IM->LastMaterial] = 0;
1200
else if (IM->MaterialOrMask & ~bitmask) {
1201
_mesa_copy_material_pairs( IM->Material[count],
1202
IM->Material[IM->LastMaterial],
1203
IM->MaterialOrMask & ~bitmask );
1206
IM->Flag[count] |= VERT_MATERIAL;
1207
IM->MaterialMask[count] = 0;
1208
IM->MaterialAndMask &= IM->MaterialMask[IM->LastMaterial];
1209
IM->LastMaterial = count;
1212
IM->MaterialOrMask |= bitmask;
1213
IM->MaterialMask[count] |= bitmask;
1214
mat = IM->Material[count];
1216
if (bitmask & FRONT_AMBIENT_BIT) {
1217
COPY_4FV( mat[0].Ambient, params );
1219
if (bitmask & BACK_AMBIENT_BIT) {
1220
COPY_4FV( mat[1].Ambient, params );
1222
if (bitmask & FRONT_DIFFUSE_BIT) {
1223
COPY_4FV( mat[0].Diffuse, params );
1225
if (bitmask & BACK_DIFFUSE_BIT) {
1226
COPY_4FV( mat[1].Diffuse, params );
1228
if (bitmask & FRONT_SPECULAR_BIT) {
1229
COPY_4FV( mat[0].Specular, params );
1231
if (bitmask & BACK_SPECULAR_BIT) {
1232
COPY_4FV( mat[1].Specular, params );
1234
if (bitmask & FRONT_EMISSION_BIT) {
1235
COPY_4FV( mat[0].Emission, params );
1237
if (bitmask & BACK_EMISSION_BIT) {
1238
COPY_4FV( mat[1].Emission, params );
1240
if (bitmask & FRONT_SHININESS_BIT) {
1241
GLfloat shininess = CLAMP( params[0], 0.0F, 128.0F );
1242
mat[0].Shininess = shininess;
1244
if (bitmask & BACK_SHININESS_BIT) {
1245
GLfloat shininess = CLAMP( params[0], 0.0F, 128.0F );
1246
mat[1].Shininess = shininess;
1248
if (bitmask & FRONT_INDEXES_BIT) {
1249
mat[0].AmbientIndex = params[0];
1250
mat[0].DiffuseIndex = params[1];
1251
mat[0].SpecularIndex = params[2];
1253
if (bitmask & BACK_INDEXES_BIT) {
1254
mat[1].AmbientIndex = params[0];
1255
mat[1].DiffuseIndex = params[1];
1256
mat[1].SpecularIndex = params[2];
1259
if (tnl->IsolateMaterials &&
1260
!(IM->BeginState & VERT_BEGIN_1)) /* heuristic */
1262
_tnl_flush_immediate( IM );
1266
void _tnl_imm_vtxfmt_init( GLcontext *ctx )
1268
GLvertexformat *vfmt = &(TNL_CONTEXT(ctx)->vtxfmt);
1270
/* All begin/end operations are handled by this vertex format:
1272
vfmt->ArrayElement = _tnl_ArrayElement;
1273
vfmt->Begin = _tnl_Begin;
1274
vfmt->Color3f = _tnl_Color3f;
1275
vfmt->Color3fv = _tnl_Color3fv;
1276
vfmt->Color3ub = _tnl_Color3ub;
1277
vfmt->Color3ubv = _tnl_Color3ubv;
1278
vfmt->Color4f = _tnl_Color4f;
1279
vfmt->Color4fv = _tnl_Color4fv;
1280
vfmt->Color4ub = _tnl_Color4ub;
1281
vfmt->Color4ubv = _tnl_Color4ubv;
1282
vfmt->EdgeFlag = _tnl_EdgeFlag;
1283
vfmt->EdgeFlagv = _tnl_EdgeFlagv;
1284
vfmt->End = _tnl_End;
1285
vfmt->EvalCoord1f = _tnl_EvalCoord1f;
1286
vfmt->EvalCoord1fv = _tnl_EvalCoord1fv;
1287
vfmt->EvalCoord2f = _tnl_EvalCoord2f;
1288
vfmt->EvalCoord2fv = _tnl_EvalCoord2fv;
1289
vfmt->EvalPoint1 = _tnl_EvalPoint1;
1290
vfmt->EvalPoint2 = _tnl_EvalPoint2;
1291
vfmt->FogCoordfEXT = _tnl_FogCoordfEXT;
1292
vfmt->FogCoordfvEXT = _tnl_FogCoordfvEXT;
1293
vfmt->Indexi = _tnl_Indexi;
1294
vfmt->Indexiv = _tnl_Indexiv;
1295
vfmt->Materialfv = _tnl_Materialfv;
1296
vfmt->MultiTexCoord1fARB = _tnl_MultiTexCoord1fARB;
1297
vfmt->MultiTexCoord1fvARB = _tnl_MultiTexCoord1fvARB;
1298
vfmt->MultiTexCoord2fARB = _tnl_MultiTexCoord2fARB;
1299
vfmt->MultiTexCoord2fvARB = _tnl_MultiTexCoord2fvARB;
1300
vfmt->MultiTexCoord3fARB = _tnl_MultiTexCoord3fARB;
1301
vfmt->MultiTexCoord3fvARB = _tnl_MultiTexCoord3fvARB;
1302
vfmt->MultiTexCoord4fARB = _tnl_MultiTexCoord4fARB;
1303
vfmt->MultiTexCoord4fvARB = _tnl_MultiTexCoord4fvARB;
1304
vfmt->Normal3f = _tnl_Normal3f;
1305
vfmt->Normal3fv = _tnl_Normal3fv;
1306
vfmt->SecondaryColor3fEXT = _tnl_SecondaryColor3fEXT;
1307
vfmt->SecondaryColor3fvEXT = _tnl_SecondaryColor3fvEXT;
1308
vfmt->SecondaryColor3ubEXT = _tnl_SecondaryColor3ubEXT;
1309
vfmt->SecondaryColor3ubvEXT = _tnl_SecondaryColor3ubvEXT;
1310
vfmt->TexCoord1f = _tnl_TexCoord1f;
1311
vfmt->TexCoord1fv = _tnl_TexCoord1fv;
1312
vfmt->TexCoord2f = _tnl_TexCoord2f;
1313
vfmt->TexCoord2fv = _tnl_TexCoord2fv;
1314
vfmt->TexCoord3f = _tnl_TexCoord3f;
1315
vfmt->TexCoord3fv = _tnl_TexCoord3fv;
1316
vfmt->TexCoord4f = _tnl_TexCoord4f;
1317
vfmt->TexCoord4fv = _tnl_TexCoord4fv;
1318
vfmt->Vertex2f = _tnl_Vertex2f;
1319
vfmt->Vertex2fv = _tnl_Vertex2fv;
1320
vfmt->Vertex3f = _tnl_Vertex3f;
1321
vfmt->Vertex3fv = _tnl_Vertex3fv;
1322
vfmt->Vertex4f = _tnl_Vertex4f;
1323
vfmt->Vertex4fv = _tnl_Vertex4fv;
1325
/* Outside begin/end functions (from t_varray.c, t_eval.c, ...):
1327
vfmt->Rectf = _tnl_Rectf;
1329
/* Just use the core function:
1331
vfmt->CallList = _mesa_CallList;
1333
vfmt->prefer_float_colors = GL_FALSE;