44bd4c4c338022e010e68f01c86633cb3e18352c
1 /* $Id: t_imm_fixup.c,v 1.4 2001/01/24 00:04:59 brianp Exp $ */
4 * Mesa 3-D graphics library
7 * Copyright (C) 1999-2000 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.
29 * Keith Whitwell <keithw@valinux.com>
45 #include "math/m_matrix.h"
46 #include "math/m_xform.h"
48 #include "t_context.h"
49 #include "t_imm_alloc.h"
50 #include "t_imm_debug.h"
51 #include "t_imm_fixup.h"
52 #include "t_pipeline.h"
57 fixup_4f( GLfloat data
[][4], GLuint flag
[], GLuint start
, GLuint match
)
62 if ((flag
[++i
] & match
) == 0) {
63 COPY_4FV(data
[i
], data
[i
-1]);
64 if (flag
[i
] & VERT_END_VB
) break;
70 fixup_3f( float data
[][3], GLuint flag
[], GLuint start
, GLuint match
)
75 if ((flag
[++i
] & match
) == 0) {
76 COPY_3V(data
[i
], data
[i
-1]);
77 if (flag
[i
] & VERT_END_VB
) break;
84 fixup_1ui( GLuint
*data
, GLuint flag
[], GLuint start
, GLuint match
)
89 if ((flag
[++i
] & match
) == 0) {
91 if (flag
[i
] & VERT_END_VB
) break;
99 fixup_1f( GLfloat
*data
, GLuint flag
[], GLuint start
, GLuint match
)
104 if ((flag
[++i
] & match
) == 0) {
106 if (flag
[i
] & VERT_END_VB
) break;
113 fixup_1ub( GLubyte
*data
, GLuint flag
[], GLuint start
, GLuint match
)
118 if ((flag
[++i
] & match
) == 0) {
120 if (flag
[i
] & VERT_END_VB
) break;
128 fixup_4chan( GLchan data
[][4], GLuint flag
[], GLuint start
, GLuint match
)
133 if ((flag
[++i
] & match
) == 0) {
134 COPY_CHAN4(data
[i
], data
[i
-1]);
135 if (flag
[i
] & VERT_END_VB
) break;
143 fixup_first_4f( GLfloat data
[][4], GLuint flag
[], GLuint match
,
144 GLuint start
, GLfloat
*dflt
)
147 match
|= VERT_END_VB
;
149 while ((flag
[++i
]&match
) == 0)
150 COPY_4FV(data
[i
], dflt
);
154 fixup_first_3f( GLfloat data
[][3], GLuint flag
[], GLuint match
,
155 GLuint start
, GLfloat
*dflt
)
158 match
|= VERT_END_VB
;
160 while ((flag
[++i
]&match
) == 0)
161 COPY_3FV(data
[i
], dflt
);
166 fixup_first_1ui( GLuint data
[], GLuint flag
[], GLuint match
,
167 GLuint start
, GLuint dflt
)
170 match
|= VERT_END_VB
;
172 while ((flag
[++i
]&match
) == 0)
177 fixup_first_1f( GLfloat data
[], GLuint flag
[], GLuint match
,
178 GLuint start
, GLfloat dflt
)
181 match
|= VERT_END_VB
;
183 while ((flag
[++i
]&match
) == 0)
189 fixup_first_1ub( GLubyte data
[], GLuint flag
[], GLuint match
,
190 GLuint start
, GLubyte dflt
)
193 match
|= VERT_END_VB
;
195 while ((flag
[++i
]&match
) == 0)
201 fixup_first_4chan( GLchan data
[][4], GLuint flag
[], GLuint match
,
202 GLuint start
, GLchan dflt
[4] )
205 match
|= VERT_END_VB
;
207 while ((flag
[++i
]&match
) == 0)
208 COPY_CHAN4(data
[i
], dflt
);
212 void _tnl_fixup_input( GLcontext
*ctx
, struct immediate
*IM
)
214 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
215 GLuint start
= IM
->CopyStart
;
216 GLuint andflag
= IM
->CopyAndFlag
;
217 GLuint orflag
= IM
->CopyOrFlag
;
220 IM
->CopyTexSize
= IM
->TexSize
;
222 /* fprintf(stderr, "Fixup input, Start: %u Count: %u LastData: %u\n", */
223 /* IM->Start, IM->Count, IM->LastData); */
224 /* _tnl_print_vert_flags("Orflag", orflag); */
225 /* _tnl_print_vert_flags("Andflag", andflag); */
228 fixup
= ~andflag
& VERT_FIXUP
;
230 if (!ctx
->CompileFlag
)
231 fixup
&= tnl
->pipeline
.inputs
;
233 if (!ctx
->ExecuteFlag
)
236 if ((orflag
& (VERT_OBJ
|VERT_EVAL_ANY
)) == 0)
240 GLuint copy
= fixup
& ~IM
->Flag
[start
];
243 /* Equivalent to a lazy copy-from-current when setting up the
246 if (ctx
->ExecuteFlag
&& copy
) {
247 /* _tnl_print_vert_flags("copy from current", copy); */
249 if (copy
& VERT_NORM
) {
250 COPY_3V( IM
->Normal
[start
], ctx
->Current
.Normal
);
253 if (copy
& VERT_RGBA
) {
254 COPY_CHAN4( IM
->Color
[start
], ctx
->Current
.Color
);
257 if (copy
& VERT_SPEC_RGB
)
258 COPY_CHAN4( IM
->SecondaryColor
[start
], ctx
->Current
.SecondaryColor
);
260 if (copy
& VERT_FOG_COORD
)
261 IM
->FogCoord
[start
] = ctx
->Current
.FogCoord
;
263 if (copy
& VERT_INDEX
)
264 IM
->Index
[start
] = ctx
->Current
.Index
;
266 if (copy
& VERT_EDGE
)
267 IM
->EdgeFlag
[start
] = ctx
->Current
.EdgeFlag
;
269 if (copy
& VERT_TEX_ANY
) {
271 for (i
= 0 ; i
< ctx
->Const
.MaxTextureUnits
; i
++) {
272 if (copy
& VERT_TEX(i
))
273 COPY_4FV( IM
->TexCoord
[i
][start
], ctx
->Current
.Texcoord
[i
] );
278 if (MESA_VERBOSE
&VERBOSE_IMMEDIATE
)
279 /* _tnl_print_vert_flags("fixup", fixup); */
281 if (fixup
& VERT_TEX_ANY
) {
283 for (i
= 0 ; i
< ctx
->Const
.MaxTextureUnits
; i
++) {
284 if (fixup
& VERT_TEX(i
)) {
285 if (orflag
& VERT_TEX(i
))
286 fixup_4f( IM
->TexCoord
[i
], IM
->Flag
, start
, VERT_TEX(i
) );
288 fixup_first_4f( IM
->TexCoord
[i
], IM
->Flag
, VERT_END_VB
, start
,
289 IM
->TexCoord
[i
][start
]);
295 if (fixup
& VERT_EDGE
) {
296 if (orflag
& VERT_EDGE
)
297 fixup_1ub( IM
->EdgeFlag
, IM
->Flag
, start
, VERT_EDGE
);
299 fixup_first_1ub( IM
->EdgeFlag
, IM
->Flag
, VERT_END_VB
, start
,
300 IM
->EdgeFlag
[start
] );
303 if (fixup
& VERT_INDEX
) {
304 if (orflag
& VERT_INDEX
)
305 fixup_1ui( IM
->Index
, IM
->Flag
, start
, VERT_INDEX
);
307 fixup_first_1ui( IM
->Index
, IM
->Flag
, VERT_END_VB
, start
, IM
->Index
[start
] );
310 if (fixup
& VERT_RGBA
) {
311 if (orflag
& VERT_RGBA
)
312 fixup_4chan( IM
->Color
, IM
->Flag
, start
, VERT_RGBA
);
314 fixup_first_4chan( IM
->Color
, IM
->Flag
, VERT_END_VB
, start
, IM
->Color
[start
] );
317 if (fixup
& VERT_SPEC_RGB
) {
318 if (orflag
& VERT_SPEC_RGB
)
319 fixup_4chan( IM
->SecondaryColor
, IM
->Flag
, start
, VERT_SPEC_RGB
);
321 fixup_first_4chan( IM
->SecondaryColor
, IM
->Flag
, VERT_END_VB
, start
,
322 IM
->SecondaryColor
[start
] );
325 if (fixup
& VERT_FOG_COORD
) {
326 if (orflag
& VERT_FOG_COORD
)
327 fixup_1f( IM
->FogCoord
, IM
->Flag
, start
, VERT_FOG_COORD
);
329 fixup_first_1f( IM
->FogCoord
, IM
->Flag
, VERT_END_VB
, start
,
330 IM
->FogCoord
[start
] );
333 if (fixup
& VERT_NORM
) {
334 if (orflag
& VERT_NORM
)
335 fixup_3f( IM
->Normal
, IM
->Flag
, start
, VERT_NORM
);
337 fixup_first_3f( IM
->Normal
, IM
->Flag
, VERT_END_VB
, start
,
341 /* Prune possible half-filled slot.
343 IM
->Flag
[IM
->LastData
+1] &= ~VERT_END_VB
;
344 IM
->Flag
[IM
->Count
] |= VERT_END_VB
;
351 static void copy_material( struct immediate
*next
,
352 struct immediate
*prev
,
353 GLuint dst
, GLuint src
)
355 if (next
->Material
== 0) {
356 next
->Material
= (GLmaterial (*)[2]) MALLOC( sizeof(GLmaterial
) *
358 next
->MaterialMask
= (GLuint
*) MALLOC( sizeof(GLuint
) * IMM_SIZE
);
361 next
->MaterialMask
[dst
] = prev
->MaterialMask
[src
];
362 MEMCPY(next
->Material
[dst
], prev
->Material
[src
], 2*sizeof(GLmaterial
));
367 /* Copy the untransformed data from the shared vertices of a primitive
368 * that wraps over two immediate structs. This is done prior to
369 * set_immediate so that prev and next may point to the same
370 * structure. In general it's difficult to avoid this copy on long
373 * Have to be careful with the transitions between display list
374 * replay, compile and normal execute modes.
376 static void copy_vertices( GLcontext
*ctx
,
377 struct immediate
*next
,
378 struct immediate
*prev
,
382 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
383 GLuint offset
= IMM_MAX_COPIED_VERTS
- count
;
386 next
->CopyStart
= next
->Start
- count
;
390 for (i
= 0 ; i
< count
; i
++)
392 GLuint src
= elts
[i
+offset
];
393 GLuint dst
= next
->CopyStart
+i
;
395 COPY_4FV( next
->Obj
[dst
], prev
->Obj
[src
] );
396 COPY_3FV( next
->Normal
[dst
], prev
->Normal
[src
] );
397 COPY_CHAN4( next
->Color
[dst
], prev
->Color
[src
] );
399 if (prev
->OrFlag
& VERT_TEX_ANY
) {
401 for (i
= 0 ; i
< prev
->MaxTextureUnits
; i
++) {
402 if (prev
->OrFlag
& VERT_TEX(i
))
403 COPY_4FV( next
->TexCoord
[i
][dst
], prev
->TexCoord
[i
][src
] );
407 if (prev
->Flag
[src
] & VERT_MATERIAL
)
408 copy_material(next
, prev
, dst
, src
);
410 next
->Elt
[dst
] = prev
->Elt
[src
];
411 next
->EdgeFlag
[dst
] = prev
->EdgeFlag
[src
];
412 next
->Index
[dst
] = prev
->Index
[src
];
413 COPY_CHAN4( next
->SecondaryColor
[dst
], prev
->SecondaryColor
[src
] );
414 next
->FogCoord
[dst
] = prev
->FogCoord
[src
];
415 next
->Flag
[dst
] = (prev
->CopyOrFlag
& VERT_FIXUP
);
416 next
->CopyOrFlag
|= prev
->Flag
[src
]; /* redundant for current_im */
417 next
->CopyAndFlag
&= prev
->Flag
[src
]; /* redundant for current_im */
420 /* Only needed when copying to a compiled cassette
422 if (next
->NormalLengths
) {
423 for (i
= 0 ; i
< count
; i
++)
425 GLuint src
= elts
[i
+offset
];
426 GLuint dst
= next
->CopyStart
+i
;
428 if (prev
->NormalLengths
)
429 next
->NormalLengths
[dst
] = prev
->NormalLengths
[src
];
431 next
->NormalLengths
[dst
] = 1.0/LEN_3FV(prev
->Normal
[src
]);
435 ASSERT(prev
== tnl
->ExecCopySource
);
437 if (--tnl
->ExecCopySource
->ref_count
== 0)
438 _tnl_free_immediate( tnl
->ExecCopySource
);
441 tnl
->ExecCopySource
= next
;
443 tnl
->ExecCopyElts
[0] = next
->Start
-3;
444 tnl
->ExecCopyElts
[1] = next
->Start
-2;
445 tnl
->ExecCopyElts
[2] = next
->Start
-1;
448 /* Copy vertices to an empty immediate struct.
450 void _tnl_copy_immediate_vertices( GLcontext
*ctx
, struct immediate
*IM
)
452 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
454 ASSERT(IM
== TNL_CURRENT_IM(ctx
));
455 ASSERT(IM
->Count
== IM
->Start
);
457 /* Need to push this in now as it won't be computed anywhere else/
459 IM
->TexSize
= tnl
->ExecCopyTexSize
;
461 /* A wrapped primitive. We may be copying into a revived
462 * display list immediate, or onto the front of a new execute-mode
465 copy_vertices( ctx
, IM
,
470 if (ctx
->Driver
.CurrentExecPrimitive
== GL_POLYGON
+1) {
471 /* Immediates are built by default to be correct in this state,
472 * and copying to the first slots of an immediate doesn't remove
475 ASSERT(tnl
->ExecCopyTexSize
== 0);
476 ASSERT(tnl
->ExecCopyCount
== 0);
477 ASSERT(IM
->CopyStart
== IM
->Start
);
480 /* Copy the primitive information:
482 IM
->Primitive
[IM
->CopyStart
] = (ctx
->Driver
.CurrentExecPrimitive
| PRIM_LAST
);
483 IM
->LastPrimitive
= IM
->CopyStart
;
485 IM
->Primitive
[IM
->CopyStart
] |= PRIM_PARITY
;
489 /* Revive a compiled immediate struct - propogate new 'Current'
490 * values. Often this is redundant because the current values were
491 * known and fixed up at compile time.
493 void _tnl_fixup_compiled_cassette( GLcontext
*ctx
, struct immediate
*IM
)
495 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
497 GLuint count
= IM
->Count
;
498 GLuint start
= IM
->Start
;
503 IM
->CopyOrFlag
= IM
->OrFlag
; /* redundant for current_im */
504 IM
->CopyAndFlag
= IM
->AndFlag
; /* redundant for current_im */
505 IM
->CopyTexSize
= IM
->TexSize
| tnl
->ExecCopyTexSize
;
507 copy_vertices( ctx
, IM
,
512 if (ctx
->Driver
.CurrentExecPrimitive
== GL_POLYGON
+1) {
513 ASSERT(tnl
->ExecCopyTexSize
== 0);
514 ASSERT(tnl
->ExecCopyCount
== 0);
515 ASSERT(IM
->CopyStart
== IM
->Start
);
518 fixup
= tnl
->pipeline
.inputs
& ~IM
->Flag
[start
] & VERT_FIXUP
;
521 if (fixup
& VERT_TEX_ANY
) {
523 for (i
= 0 ; i
< ctx
->Const
.MaxTextureUnits
; i
++) {
524 if (fixup
& VERT_TEX(i
))
525 fixup_first_4f( IM
->TexCoord
[i
], IM
->Flag
, VERT_TEX(i
), start
,
526 ctx
->Current
.Texcoord
[i
] );
530 if (fixup
& VERT_EDGE
)
531 fixup_first_1ub(IM
->EdgeFlag
, IM
->Flag
, VERT_EDGE
, start
,
532 ctx
->Current
.EdgeFlag
);
534 if (fixup
& VERT_INDEX
)
535 fixup_first_1ui(IM
->Index
, IM
->Flag
, VERT_INDEX
, start
,
536 ctx
->Current
.Index
);
538 if (fixup
& VERT_RGBA
)
539 fixup_first_4chan(IM
->Color
, IM
->Flag
, VERT_RGBA
, start
,
540 ctx
->Current
.Color
);
542 if (fixup
& VERT_SPEC_RGB
)
543 fixup_first_4chan(IM
->SecondaryColor
, IM
->Flag
, VERT_SPEC_RGB
, start
,
544 ctx
->Current
.SecondaryColor
);
546 if (fixup
& VERT_FOG_COORD
)
547 fixup_first_1f(IM
->FogCoord
, IM
->Flag
, VERT_FOG_COORD
, start
,
548 ctx
->Current
.FogCoord
);
550 if (fixup
& VERT_NORM
) {
551 fixup_first_3f(IM
->Normal
, IM
->Flag
, VERT_NORM
, start
,
552 ctx
->Current
.Normal
);
553 if (IM
->NormalLengths
)
554 fixup_first_1f(IM
->NormalLengths
, IM
->Flag
, VERT_NORM
, start
,
555 1.0F
/ (GLfloat
) LEN_3FV(ctx
->Current
.Normal
) );
560 /* Can potentially overwrite primitive details - need to save the
563 tnl
->DlistPrimitive
= IM
->Primitive
[IM
->Start
];
564 tnl
->DlistPrimitiveLength
= IM
->PrimitiveLength
[IM
->Start
];
565 tnl
->DlistLastPrimitive
= IM
->LastPrimitive
;
567 /* The first primitive may be different from what was recorded in
568 * the immediate struct. Consider an immediate that starts with a
569 * glBegin, compiled in a display list, which is called from within
570 * an existing Begin/End object.
572 if (ctx
->Driver
.CurrentExecPrimitive
== GL_POLYGON
+1) {
575 if (IM
->BeginState
& VERT_ERROR_1
)
576 gl_error( ctx
, GL_INVALID_OPERATION
, "begin/end");
578 for (i
= IM
->Start
; i
<= IM
->Count
; i
+= IM
->PrimitiveLength
[i
])
579 if (IM
->Flag
[i
] & (VERT_BEGIN
|VERT_END_VB
))
582 /* Would like to just ignore vertices upto this point. Can't
583 * set copystart because it might skip materials?
585 ASSERT(IM
->Start
== IM
->CopyStart
);
586 if (i
> IM
->CopyStart
) {
587 IM
->Primitive
[IM
->CopyStart
] = GL_POLYGON
+1;
588 IM
->PrimitiveLength
[IM
->CopyStart
] = i
- IM
->CopyStart
;
589 if (IM
->Flag
[i
] & VERT_END_VB
) {
590 IM
->Primitive
[IM
->CopyStart
] |= PRIM_LAST
;
591 IM
->LastPrimitive
= IM
->CopyStart
;
594 /* Shouldn't immediates be set up to have this structure *by default*?
599 if (IM
->BeginState
& VERT_ERROR_0
)
600 gl_error( ctx
, GL_INVALID_OPERATION
, "begin/end");
602 if (IM
->CopyStart
== IM
->Start
&&
603 IM
->Flag
[IM
->Start
] & (VERT_END
|VERT_END_VB
))
608 IM
->Primitive
[IM
->CopyStart
] = ctx
->Driver
.CurrentExecPrimitive
;
610 IM
->Primitive
[IM
->CopyStart
] |= PRIM_PARITY
;
613 for (i
= IM
->Start
; i
<= IM
->Count
; i
+= IM
->PrimitiveLength
[i
])
614 if (IM
->Flag
[i
] & (VERT_END
|VERT_END_VB
)) {
615 IM
->PrimitiveLength
[IM
->CopyStart
] = i
- IM
->CopyStart
;
616 if (IM
->Flag
[i
] & VERT_END_VB
) {
617 IM
->Primitive
[IM
->CopyStart
] |= PRIM_LAST
;
618 IM
->LastPrimitive
= IM
->CopyStart
;
620 if (IM
->Flag
[i
] & VERT_END
) {
621 IM
->Primitive
[IM
->CopyStart
] |= PRIM_END
;
628 if (IM
->Primitive
[IM
->LastPrimitive
] & PRIM_END
)
629 ctx
->Driver
.CurrentExecPrimitive
= GL_POLYGON
+1;
631 ctx
->Driver
.CurrentExecPrimitive
=
632 IM
->Primitive
[IM
->LastPrimitive
] & PRIM_MODE_MASK
;
636 /* Undo any changes potentially made to the immediate in the range
637 * IM->Start..IM->Count above.
639 void _tnl_restore_compiled_cassette( GLcontext
*ctx
, struct immediate
*IM
)
641 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
642 IM
->Primitive
[IM
->Start
] = tnl
->DlistPrimitive
;
643 IM
->PrimitiveLength
[IM
->Start
] = tnl
->DlistPrimitiveLength
;
651 static void copy_none( TNLcontext
*tnl
, GLuint start
, GLuint count
, GLuint ovf
)
653 (void) (start
&& ovf
&& tnl
&& count
);
656 static void copy_last( TNLcontext
*tnl
, GLuint start
, GLuint count
, GLuint ovf
)
658 (void) start
; (void) ovf
;
659 tnl
->ExecCopyCount
= 1;
660 tnl
->ExecCopyElts
[2] = count
-1;
663 static void copy_first_and_last( TNLcontext
*tnl
, GLuint start
, GLuint count
,
667 tnl
->ExecCopyCount
= 2;
668 tnl
->ExecCopyElts
[1] = start
;
669 tnl
->ExecCopyElts
[2] = count
-1;
672 static void copy_last_two( TNLcontext
*tnl
, GLuint start
, GLuint count
,
676 tnl
->ExecCopyCount
= 2+ovf
;
677 tnl
->ExecCopyElts
[0] = count
-3;
678 tnl
->ExecCopyElts
[1] = count
-2;
679 tnl
->ExecCopyElts
[2] = count
-1;
682 static void copy_overflow( TNLcontext
*tnl
, GLuint start
, GLuint count
,
686 tnl
->ExecCopyCount
= ovf
;
687 tnl
->ExecCopyElts
[0] = count
-3;
688 tnl
->ExecCopyElts
[1] = count
-2;
689 tnl
->ExecCopyElts
[2] = count
-1;
693 typedef void (*copy_func
)( TNLcontext
*tnl
, GLuint start
, GLuint count
,
696 static copy_func copy_tab
[GL_POLYGON
+2] =
715 /* Figure out what vertices need to be copied next time.
718 _tnl_get_exec_copy_verts( GLcontext
*ctx
, struct immediate
*IM
)
720 static const GLuint increment
[GL_POLYGON
+2] = { 1,2,1,1,3,1,1,4,2,1,1 };
721 static const GLuint intro
[GL_POLYGON
+2] = { 0,0,2,2,0,2,2,0,2,2,0 };
723 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
724 GLuint last
= IM
->LastPrimitive
;
725 GLuint prim
= ctx
->Driver
.CurrentExecPrimitive
;
726 GLuint pincr
= increment
[prim
];
727 GLuint pintro
= intro
[prim
];
731 if (tnl
->ExecCopySource
!= IM
) {
732 if (--tnl
->ExecCopySource
->ref_count
== 0)
733 _tnl_free_immediate( tnl
->ExecCopySource
);
735 tnl
->ExecCopySource
= IM
;
738 if (prim
== GL_POLYGON
+1) {
739 tnl
->ExecCopyCount
= 0;
740 tnl
->ExecCopyTexSize
= 0;
743 tnl
->ExecCopyCount
= 0;
744 tnl
->ExecCopyTexSize
= IM
->CopyTexSize
;
745 tnl
->ExecParity
= IM
->PrimitiveLength
[IM
->LastPrimitive
] & 1;
747 if (pincr
!= 1 && (IM
->Count
- last
- pintro
))
748 ovf
= (IM
->Count
- last
- pintro
) % pincr
;
750 if (last
< IM
->Count
)
751 copy_tab
[prim
]( tnl
, last
, IM
->Count
, ovf
);
756 /* If we receive evalcoords in an immediate struct for maps which
757 * don't have a vertex enabled, need to do an additional fixup, as
758 * those rows containing evalcoords must now be ignored. The
759 * evalcoords may still generate colors, normals, etc, so have to
760 * respect the relative order between calls to EvalCoord and Normal
763 * Generate the index list that will be used to render this immediate
766 * Finally, generate a new primitives list for rendering the indices.
769 void _tnl_fixup_purged_eval( GLcontext
*ctx
,
770 GLuint fixup
, GLuint purge
)
772 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
773 struct tnl_eval_store
*store
= &tnl
->eval
;
774 GLuint
*flags
= tnl
->vb
.Flag
;
775 GLuint i
, j
, nextprim
;
776 GLuint fixup_fence
= purge
|VERT_OBJ
;
777 GLuint good_index
= (VERT_EVAL_ANY
& ~purge
)|VERT_OBJ
;
778 GLuint prim_length
= 0, lastprim
= 0, nextprim
= 0;
780 if (fixup
& VERT_TEX0
)
781 fixup_4f( store
->TexCoord
, flags
, 0, VERT_TEX0
|fixup_fence
);
783 if (fixup
& VERT_INDEX
)
784 fixup_1ui( store
->Index
, flags
, 0, VERT_INDEX
|fixup_fence
);
786 if (fixup
& VERT_RGBA
)
787 fixup_4chan( store
->Color
, flags
, 0, VERT_RGBA
|fixup_fence
);
789 if (fixup
& VERT_NORM
)
790 fixup_3f( store
->Normal
, flags
, 0, VERT_NORM
|fixup_fence
);
792 for (i
= 0, j
= 0 ; i
< tnl
->vb
.Count
; i
++) {
793 if (flags
[i
] & good_index
) {
794 store
->Elts
[j
++] = i
;
798 VB
->PrimitiveLength
[lastprim
] = prim_length
;
799 VB
->Primitive
[j
] = VB
->Primitive
[i
];
800 nextprim
+= lastprimlen
;
802 lastprimlen
= VB
->PrimitiveLength
[i
];
806 VB
->Elts
= store
->Elts
;
808 /* What about copying??? No immediate exists with the right
809 * vertices in place...
811 if (tnl
->CurrentPrimitive
!= GL_POLYGON
+1) {