1 /* $Id: t_imm_fixup.c,v 1.10 2001/04/09 14:47:34 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.
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
) {
248 if (MESA_VERBOSE
&VERBOSE_IMMEDIATE
)
249 _tnl_print_vert_flags("copy from current", copy
);
251 if (copy
& VERT_NORM
) {
252 COPY_3V( IM
->Normal
[start
], ctx
->Current
.Normal
);
255 if (copy
& VERT_RGBA
) {
256 COPY_CHAN4( IM
->Color
[start
], ctx
->Current
.Color
);
259 if (copy
& VERT_SPEC_RGB
)
260 COPY_CHAN4( IM
->SecondaryColor
[start
], ctx
->Current
.SecondaryColor
);
262 if (copy
& VERT_FOG_COORD
)
263 IM
->FogCoord
[start
] = ctx
->Current
.FogCoord
;
265 if (copy
& VERT_INDEX
)
266 IM
->Index
[start
] = ctx
->Current
.Index
;
268 if (copy
& VERT_EDGE
)
269 IM
->EdgeFlag
[start
] = ctx
->Current
.EdgeFlag
;
271 if (copy
& VERT_TEX_ANY
) {
273 for (i
= 0 ; i
< ctx
->Const
.MaxTextureUnits
; i
++) {
274 if (copy
& VERT_TEX(i
))
275 COPY_4FV( IM
->TexCoord
[i
][start
], ctx
->Current
.Texcoord
[i
] );
280 if (MESA_VERBOSE
&VERBOSE_IMMEDIATE
)
281 _tnl_print_vert_flags("fixup", fixup
);
283 if (fixup
& VERT_TEX_ANY
) {
285 for (i
= 0 ; i
< ctx
->Const
.MaxTextureUnits
; i
++) {
286 if (fixup
& VERT_TEX(i
)) {
287 if (orflag
& VERT_TEX(i
))
288 fixup_4f( IM
->TexCoord
[i
], IM
->Flag
, start
, VERT_TEX(i
) );
290 fixup_first_4f( IM
->TexCoord
[i
], IM
->Flag
, VERT_END_VB
, start
,
291 IM
->TexCoord
[i
][start
]);
297 if (fixup
& VERT_EDGE
) {
298 if (orflag
& VERT_EDGE
)
299 fixup_1ub( IM
->EdgeFlag
, IM
->Flag
, start
, VERT_EDGE
);
301 fixup_first_1ub( IM
->EdgeFlag
, IM
->Flag
, VERT_END_VB
, start
,
302 IM
->EdgeFlag
[start
] );
305 if (fixup
& VERT_INDEX
) {
306 if (orflag
& VERT_INDEX
)
307 fixup_1ui( IM
->Index
, IM
->Flag
, start
, VERT_INDEX
);
309 fixup_first_1ui( IM
->Index
, IM
->Flag
, VERT_END_VB
, start
,
313 if (fixup
& VERT_RGBA
) {
314 if (orflag
& VERT_RGBA
)
315 fixup_4chan( IM
->Color
, IM
->Flag
, start
, VERT_RGBA
);
317 fixup_first_4chan( IM
->Color
, IM
->Flag
, VERT_END_VB
, start
,
321 if (fixup
& VERT_SPEC_RGB
) {
322 if (orflag
& VERT_SPEC_RGB
)
323 fixup_4chan( IM
->SecondaryColor
, IM
->Flag
, start
, VERT_SPEC_RGB
);
325 fixup_first_4chan( IM
->SecondaryColor
, IM
->Flag
, VERT_END_VB
, start
,
326 IM
->SecondaryColor
[start
] );
329 if (fixup
& VERT_FOG_COORD
) {
330 if (orflag
& VERT_FOG_COORD
)
331 fixup_1f( IM
->FogCoord
, IM
->Flag
, start
, VERT_FOG_COORD
);
333 fixup_first_1f( IM
->FogCoord
, IM
->Flag
, VERT_END_VB
, start
,
334 IM
->FogCoord
[start
] );
337 if (fixup
& VERT_NORM
) {
338 if (orflag
& VERT_NORM
)
339 fixup_3f( IM
->Normal
, IM
->Flag
, start
, VERT_NORM
);
341 fixup_first_3f( IM
->Normal
, IM
->Flag
, VERT_END_VB
, start
,
346 /* Prune possible half-filled slot.
348 IM
->Flag
[IM
->LastData
+1] &= ~VERT_END_VB
;
349 IM
->Flag
[IM
->Count
] |= VERT_END_VB
;
354 if (IM
->MaterialOrMask
& ~IM
->MaterialAndMask
) {
355 GLuint vulnerable
= IM
->MaterialOrMask
;
356 GLuint i
= IM
->Start
;
359 while (!(IM
->Flag
[i
] & VERT_MATERIAL
))
362 vulnerable
&= ~IM
->MaterialMask
[i
];
363 _mesa_copy_material_pairs( IM
->Material
[i
],
368 } while (vulnerable
);
375 static void copy_material( struct immediate
*next
,
376 struct immediate
*prev
,
377 GLuint dst
, GLuint src
)
379 if (next
->Material
== 0) {
380 next
->Material
= (GLmaterial (*)[2]) MALLOC( sizeof(GLmaterial
) *
382 next
->MaterialMask
= (GLuint
*) MALLOC( sizeof(GLuint
) * IMM_SIZE
);
385 next
->MaterialMask
[dst
] = prev
->MaterialOrMask
;
386 MEMCPY(next
->Material
[dst
], prev
->Material
[src
], 2*sizeof(GLmaterial
));
391 /* Copy the untransformed data from the shared vertices of a primitive
392 * that wraps over two immediate structs. This is done prior to
393 * set_immediate so that prev and next may point to the same
394 * structure. In general it's difficult to avoid this copy on long
397 * Have to be careful with the transitions between display list
398 * replay, compile and normal execute modes.
400 static void copy_vertices( GLcontext
*ctx
,
401 struct immediate
*next
,
402 struct immediate
*prev
,
406 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
407 GLuint offset
= IMM_MAX_COPIED_VERTS
- count
;
410 next
->CopyStart
= next
->Start
- count
;
414 for (i
= 0 ; i
< count
; i
++)
416 GLuint src
= elts
[i
+offset
];
417 GLuint dst
= next
->CopyStart
+i
;
419 COPY_4FV( next
->Obj
[dst
], prev
->Obj
[src
] );
420 COPY_3FV( next
->Normal
[dst
], prev
->Normal
[src
] );
421 COPY_CHAN4( next
->Color
[dst
], prev
->Color
[src
] );
423 if (prev
->OrFlag
& VERT_TEX_ANY
) {
425 for (i
= 0 ; i
< prev
->MaxTextureUnits
; i
++) {
426 if (prev
->OrFlag
& VERT_TEX(i
))
427 COPY_4FV( next
->TexCoord
[i
][dst
], prev
->TexCoord
[i
][src
] );
431 if (prev
->Flag
[src
] & VERT_MATERIAL
)
432 copy_material(next
, prev
, dst
, src
);
434 next
->Elt
[dst
] = prev
->Elt
[src
];
435 next
->EdgeFlag
[dst
] = prev
->EdgeFlag
[src
];
436 next
->Index
[dst
] = prev
->Index
[src
];
437 COPY_CHAN4( next
->SecondaryColor
[dst
], prev
->SecondaryColor
[src
] );
438 next
->FogCoord
[dst
] = prev
->FogCoord
[src
];
439 next
->Flag
[dst
] = (prev
->CopyOrFlag
& VERT_FIXUP
);
440 next
->CopyOrFlag
|= prev
->Flag
[src
]; /* redundant for current_im */
441 next
->CopyAndFlag
&= prev
->Flag
[src
]; /* redundant for current_im */
445 ASSERT(prev
== tnl
->ExecCopySource
);
447 if (--tnl
->ExecCopySource
->ref_count
== 0)
448 _tnl_free_immediate( tnl
->ExecCopySource
);
451 tnl
->ExecCopySource
= next
;
453 tnl
->ExecCopyElts
[0] = next
->Start
-3;
454 tnl
->ExecCopyElts
[1] = next
->Start
-2;
455 tnl
->ExecCopyElts
[2] = next
->Start
-1;
458 /* Copy vertices to an empty immediate struct.
460 void _tnl_copy_immediate_vertices( GLcontext
*ctx
, struct immediate
*IM
)
462 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
464 ASSERT(IM
== TNL_CURRENT_IM(ctx
));
465 ASSERT(IM
->Count
== IM
->Start
);
467 /* Need to push this in now as it won't be computed anywhere else/
469 IM
->TexSize
= tnl
->ExecCopyTexSize
;
471 /* A wrapped primitive. We may be copying into a revived
472 * display list immediate, or onto the front of a new execute-mode
475 copy_vertices( ctx
, IM
,
480 if (ctx
->Driver
.CurrentExecPrimitive
== GL_POLYGON
+1) {
481 /* Immediates are built by default to be correct in this state,
482 * and copying to the first slots of an immediate doesn't remove
485 ASSERT(tnl
->ExecCopyTexSize
== 0);
486 ASSERT(tnl
->ExecCopyCount
== 0);
487 ASSERT(IM
->CopyStart
== IM
->Start
);
490 /* Copy the primitive information:
492 IM
->Primitive
[IM
->CopyStart
] = (ctx
->Driver
.CurrentExecPrimitive
| PRIM_LAST
);
493 IM
->LastPrimitive
= IM
->CopyStart
;
495 IM
->Primitive
[IM
->CopyStart
] |= PRIM_PARITY
;
499 /* Revive a compiled immediate struct - propogate new 'Current'
500 * values. Often this is redundant because the current values were
501 * known and fixed up at compile time.
503 void _tnl_fixup_compiled_cassette( GLcontext
*ctx
, struct immediate
*IM
)
505 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
507 GLuint count
= IM
->Count
;
508 GLuint start
= IM
->Start
;
513 IM
->CopyOrFlag
= IM
->OrFlag
; /* redundant for current_im */
514 IM
->CopyAndFlag
= IM
->AndFlag
; /* redundant for current_im */
515 IM
->CopyTexSize
= IM
->TexSize
| tnl
->ExecCopyTexSize
;
517 copy_vertices( ctx
, IM
,
522 if (ctx
->Driver
.CurrentExecPrimitive
== GL_POLYGON
+1) {
523 ASSERT(tnl
->ExecCopyTexSize
== 0);
524 ASSERT(tnl
->ExecCopyCount
== 0);
525 ASSERT(IM
->CopyStart
== IM
->Start
);
528 fixup
= tnl
->pipeline
.inputs
& ~IM
->Flag
[start
] & VERT_FIXUP
;
531 if (fixup
& VERT_TEX_ANY
) {
533 for (i
= 0 ; i
< ctx
->Const
.MaxTextureUnits
; i
++) {
534 if (fixup
& VERT_TEX(i
))
535 fixup_first_4f( IM
->TexCoord
[i
], IM
->Flag
, VERT_TEX(i
), start
,
536 ctx
->Current
.Texcoord
[i
] );
540 if (fixup
& VERT_EDGE
)
541 fixup_first_1ub(IM
->EdgeFlag
, IM
->Flag
, VERT_EDGE
, start
,
542 ctx
->Current
.EdgeFlag
);
544 if (fixup
& VERT_INDEX
)
545 fixup_first_1ui(IM
->Index
, IM
->Flag
, VERT_INDEX
, start
,
546 ctx
->Current
.Index
);
548 if (fixup
& VERT_RGBA
)
549 fixup_first_4chan(IM
->Color
, IM
->Flag
, VERT_RGBA
, start
,
550 ctx
->Current
.Color
);
552 if (fixup
& VERT_SPEC_RGB
)
553 fixup_first_4chan(IM
->SecondaryColor
, IM
->Flag
, VERT_SPEC_RGB
, start
,
554 ctx
->Current
.SecondaryColor
);
556 if (fixup
& VERT_FOG_COORD
)
557 fixup_first_1f(IM
->FogCoord
, IM
->Flag
, VERT_FOG_COORD
, start
,
558 ctx
->Current
.FogCoord
);
560 if (fixup
& VERT_NORM
) {
561 fixup_first_3f(IM
->Normal
, IM
->Flag
, VERT_NORM
, start
,
562 ctx
->Current
.Normal
);
568 if (IM
->MaterialOrMask
& ~IM
->MaterialAndMask
) {
569 GLuint vulnerable
= IM
->MaterialOrMask
;
570 GLuint i
= IM
->Start
;
573 while (!(IM
->Flag
[i
] & VERT_MATERIAL
))
576 vulnerable
&= ~IM
->MaterialMask
[i
];
577 _mesa_copy_material_pairs( IM
->Material
[i
],
582 } while (vulnerable
);
585 /* Can potentially overwrite primitive details - need to save the
588 tnl
->DlistPrimitive
= IM
->Primitive
[IM
->Start
];
589 tnl
->DlistPrimitiveLength
= IM
->PrimitiveLength
[IM
->Start
];
590 tnl
->DlistLastPrimitive
= IM
->LastPrimitive
;
592 /* The first primitive may be different from what was recorded in
593 * the immediate struct. Consider an immediate that starts with a
594 * glBegin, compiled in a display list, which is called from within
595 * an existing Begin/End object.
597 if (ctx
->Driver
.CurrentExecPrimitive
== GL_POLYGON
+1) {
600 if (IM
->BeginState
& VERT_ERROR_1
)
601 _mesa_error( ctx
, GL_INVALID_OPERATION
, "glBegin/glEnd");
603 for (i
= IM
->Start
; i
<= IM
->Count
; i
+= IM
->PrimitiveLength
[i
])
604 if (IM
->Flag
[i
] & (VERT_BEGIN
|VERT_END_VB
))
607 /* Would like to just ignore vertices upto this point. Can't
608 * set copystart because it might skip materials?
610 ASSERT(IM
->Start
== IM
->CopyStart
);
611 if (i
> IM
->CopyStart
) {
612 IM
->Primitive
[IM
->CopyStart
] = GL_POLYGON
+1;
613 IM
->PrimitiveLength
[IM
->CopyStart
] = i
- IM
->CopyStart
;
614 if (IM
->Flag
[i
] & VERT_END_VB
) {
615 IM
->Primitive
[IM
->CopyStart
] |= PRIM_LAST
;
616 IM
->LastPrimitive
= IM
->CopyStart
;
619 /* Shouldn't immediates be set up to have this structure *by default*?
624 if (IM
->BeginState
& VERT_ERROR_0
)
625 _mesa_error( ctx
, GL_INVALID_OPERATION
, "glBegin/glEnd");
627 if (IM
->CopyStart
== IM
->Start
&&
628 IM
->Flag
[IM
->Start
] & (VERT_END
|VERT_END_VB
))
633 IM
->Primitive
[IM
->CopyStart
] = ctx
->Driver
.CurrentExecPrimitive
;
635 IM
->Primitive
[IM
->CopyStart
] |= PRIM_PARITY
;
638 for (i
= IM
->Start
; i
<= IM
->Count
; i
+= IM
->PrimitiveLength
[i
])
639 if (IM
->Flag
[i
] & (VERT_END
|VERT_END_VB
)) {
640 IM
->PrimitiveLength
[IM
->CopyStart
] = i
- IM
->CopyStart
;
641 if (IM
->Flag
[i
] & VERT_END_VB
) {
642 IM
->Primitive
[IM
->CopyStart
] |= PRIM_LAST
;
643 IM
->LastPrimitive
= IM
->CopyStart
;
645 if (IM
->Flag
[i
] & VERT_END
) {
646 IM
->Primitive
[IM
->CopyStart
] |= PRIM_END
;
653 if (IM
->Primitive
[IM
->LastPrimitive
] & PRIM_END
)
654 ctx
->Driver
.CurrentExecPrimitive
= GL_POLYGON
+1;
656 ctx
->Driver
.CurrentExecPrimitive
=
657 IM
->Primitive
[IM
->LastPrimitive
] & PRIM_MODE_MASK
;
661 /* Undo any changes potentially made to the immediate in the range
662 * IM->Start..IM->Count above.
664 void _tnl_restore_compiled_cassette( GLcontext
*ctx
, struct immediate
*IM
)
666 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
667 IM
->Primitive
[IM
->Start
] = tnl
->DlistPrimitive
;
668 IM
->PrimitiveLength
[IM
->Start
] = tnl
->DlistPrimitiveLength
;
676 static void copy_none( TNLcontext
*tnl
, GLuint start
, GLuint count
, GLuint ovf
)
678 (void) (start
&& ovf
&& tnl
&& count
);
681 static void copy_last( TNLcontext
*tnl
, GLuint start
, GLuint count
, GLuint ovf
)
683 (void) start
; (void) ovf
;
684 tnl
->ExecCopyCount
= 1;
685 tnl
->ExecCopyElts
[2] = count
-1;
688 static void copy_first_and_last( TNLcontext
*tnl
, GLuint start
, GLuint count
,
692 tnl
->ExecCopyCount
= 2;
693 tnl
->ExecCopyElts
[1] = start
;
694 tnl
->ExecCopyElts
[2] = count
-1;
697 static void copy_last_two( TNLcontext
*tnl
, GLuint start
, GLuint count
,
701 tnl
->ExecCopyCount
= 2+ovf
;
702 tnl
->ExecCopyElts
[0] = count
-3;
703 tnl
->ExecCopyElts
[1] = count
-2;
704 tnl
->ExecCopyElts
[2] = count
-1;
707 static void copy_overflow( TNLcontext
*tnl
, GLuint start
, GLuint count
,
711 tnl
->ExecCopyCount
= ovf
;
712 tnl
->ExecCopyElts
[0] = count
-3;
713 tnl
->ExecCopyElts
[1] = count
-2;
714 tnl
->ExecCopyElts
[2] = count
-1;
718 typedef void (*copy_func
)( TNLcontext
*tnl
, GLuint start
, GLuint count
,
721 static copy_func copy_tab
[GL_POLYGON
+2] =
740 /* Figure out what vertices need to be copied next time.
743 _tnl_get_exec_copy_verts( GLcontext
*ctx
, struct immediate
*IM
)
745 static const GLuint increment
[GL_POLYGON
+2] = { 1,2,1,1,3,1,1,4,2,1,1 };
746 static const GLuint intro
[GL_POLYGON
+2] = { 0,0,2,2,0,2,2,0,2,2,0 };
748 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
749 GLuint last
= IM
->LastPrimitive
;
750 GLuint prim
= ctx
->Driver
.CurrentExecPrimitive
;
751 GLuint pincr
= increment
[prim
];
752 GLuint pintro
= intro
[prim
];
756 if (tnl
->ExecCopySource
!= IM
) {
757 if (--tnl
->ExecCopySource
->ref_count
== 0)
758 _tnl_free_immediate( tnl
->ExecCopySource
);
760 tnl
->ExecCopySource
= IM
;
763 if (prim
== GL_POLYGON
+1) {
764 tnl
->ExecCopyCount
= 0;
765 tnl
->ExecCopyTexSize
= 0;
768 tnl
->ExecCopyCount
= 0;
769 tnl
->ExecCopyTexSize
= IM
->CopyTexSize
;
770 tnl
->ExecParity
= IM
->PrimitiveLength
[IM
->LastPrimitive
] & 1;
772 if (pincr
!= 1 && (IM
->Count
- last
- pintro
))
773 ovf
= (IM
->Count
- last
- pintro
) % pincr
;
775 if (last
< IM
->Count
)
776 copy_tab
[prim
]( tnl
, last
, IM
->Count
, ovf
);
781 /* If we receive evalcoords in an immediate struct for maps which
782 * don't have a vertex enabled, need to do an additional fixup, as
783 * those rows containing evalcoords must now be ignored. The
784 * evalcoords may still generate colors, normals, etc, so have to
785 * respect the relative order between calls to EvalCoord and Normal
788 * Generate the index list that will be used to render this immediate
791 * Finally, generate a new primitives list for rendering the indices.
794 void _tnl_fixup_purged_eval( GLcontext
*ctx
,
795 GLuint fixup
, GLuint purge
)
797 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
798 struct tnl_eval_store
*store
= &tnl
->eval
;
799 GLuint
*flags
= tnl
->vb
.Flag
;
800 GLuint i
, j
, nextprim
;
801 GLuint fixup_fence
= purge
|VERT_OBJ
;
802 GLuint good_index
= (VERT_EVAL_ANY
& ~purge
)|VERT_OBJ
;
803 GLuint prim_length
= 0, lastprim
= 0, nextprim
= 0;
805 if (fixup
& VERT_TEX0
)
806 fixup_4f( store
->TexCoord
, flags
, 0, VERT_TEX0
|fixup_fence
);
808 if (fixup
& VERT_INDEX
)
809 fixup_1ui( store
->Index
, flags
, 0, VERT_INDEX
|fixup_fence
);
811 if (fixup
& VERT_RGBA
)
812 fixup_4chan( store
->Color
, flags
, 0, VERT_RGBA
|fixup_fence
);
814 if (fixup
& VERT_NORM
)
815 fixup_3f( store
->Normal
, flags
, 0, VERT_NORM
|fixup_fence
);
817 for (i
= 0, j
= 0 ; i
< tnl
->vb
.Count
; i
++) {
818 if (flags
[i
] & good_index
) {
819 store
->Elts
[j
++] = i
;
823 VB
->PrimitiveLength
[lastprim
] = prim_length
;
824 VB
->Primitive
[j
] = VB
->Primitive
[i
];
825 nextprim
+= lastprimlen
;
827 lastprimlen
= VB
->PrimitiveLength
[i
];
831 VB
->Elts
= store
->Elts
;
833 /* What about copying??? No immediate exists with the right
834 * vertices in place...
836 if (tnl
->CurrentPrimitive
!= GL_POLYGON
+1) {