bfb1d3064276658ee2e611e3d292efee5b98604c
1 /* $Id: t_imm_fixup.c,v 1.11 2001/04/26 14:53:48 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"
55 static const GLuint increment
[GL_POLYGON
+2] = { 1,2,1,1,3,1,1,4,2,1,1 };
56 static const GLuint intro
[GL_POLYGON
+2] = { 0,0,2,2,0,2,2,0,2,2,0 };
59 _tnl_fixup_4f( GLfloat data
[][4], GLuint flag
[], GLuint start
, GLuint match
)
64 if ((flag
[++i
] & match
) == 0) {
65 COPY_4FV(data
[i
], data
[i
-1]);
66 if (flag
[i
] & VERT_END_VB
) break;
72 _tnl_fixup_3f( float data
[][3], GLuint flag
[], GLuint start
, GLuint match
)
77 if ((flag
[++i
] & match
) == 0) {
78 COPY_3V(data
[i
], data
[i
-1]);
79 if (flag
[i
] & VERT_END_VB
) break;
86 _tnl_fixup_1ui( GLuint
*data
, GLuint flag
[], GLuint start
, GLuint match
)
91 if ((flag
[++i
] & match
) == 0) {
93 if (flag
[i
] & VERT_END_VB
) break;
101 _tnl_fixup_1f( GLfloat
*data
, GLuint flag
[], GLuint start
, GLuint match
)
106 if ((flag
[++i
] & match
) == 0) {
108 if (flag
[i
] & VERT_END_VB
) break;
115 _tnl_fixup_1ub( GLubyte
*data
, GLuint flag
[], GLuint start
, GLuint match
)
120 if ((flag
[++i
] & match
) == 0) {
122 if (flag
[i
] & VERT_END_VB
) break;
130 _tnl_fixup_4chan( GLchan data
[][4], GLuint flag
[], GLuint start
, GLuint match
)
135 if ((flag
[++i
] & match
) == 0) {
136 COPY_CHAN4(data
[i
], data
[i
-1]);
137 if (flag
[i
] & VERT_END_VB
) break;
145 fixup_first_4f( GLfloat data
[][4], GLuint flag
[], GLuint match
,
146 GLuint start
, GLfloat
*dflt
)
149 match
|= VERT_END_VB
;
151 while ((flag
[++i
]&match
) == 0)
152 COPY_4FV(data
[i
], dflt
);
156 fixup_first_3f( GLfloat data
[][3], GLuint flag
[], GLuint match
,
157 GLuint start
, GLfloat
*dflt
)
160 match
|= VERT_END_VB
;
162 while ((flag
[++i
]&match
) == 0)
163 COPY_3FV(data
[i
], dflt
);
168 fixup_first_1ui( GLuint data
[], GLuint flag
[], GLuint match
,
169 GLuint start
, GLuint dflt
)
172 match
|= VERT_END_VB
;
174 while ((flag
[++i
]&match
) == 0)
179 fixup_first_1f( GLfloat data
[], GLuint flag
[], GLuint match
,
180 GLuint start
, GLfloat dflt
)
183 match
|= VERT_END_VB
;
185 while ((flag
[++i
]&match
) == 0)
191 fixup_first_1ub( GLubyte data
[], GLuint flag
[], GLuint match
,
192 GLuint start
, GLubyte dflt
)
195 match
|= VERT_END_VB
;
197 while ((flag
[++i
]&match
) == 0)
203 fixup_first_4chan( GLchan data
[][4], GLuint flag
[], GLuint match
,
204 GLuint start
, GLchan dflt
[4] )
207 match
|= VERT_END_VB
;
209 while ((flag
[++i
]&match
) == 0)
210 COPY_CHAN4(data
[i
], dflt
);
214 void _tnl_fixup_input( GLcontext
*ctx
, struct immediate
*IM
)
216 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
217 GLuint start
= IM
->CopyStart
;
218 GLuint andflag
= IM
->CopyAndFlag
;
219 GLuint orflag
= IM
->CopyOrFlag
;
222 IM
->CopyTexSize
= IM
->TexSize
;
224 /* fprintf(stderr, "Fixup input, Start: %u Count: %u LastData: %u\n", */
225 /* IM->Start, IM->Count, IM->LastData); */
226 /* _tnl_print_vert_flags("Orflag", orflag); */
227 /* _tnl_print_vert_flags("Andflag", andflag); */
230 fixup
= ~andflag
& VERT_FIXUP
;
232 if (!ctx
->CompileFlag
)
233 fixup
&= tnl
->pipeline
.inputs
;
235 if (!ctx
->ExecuteFlag
)
238 if ((orflag
& (VERT_OBJ
|VERT_EVAL_ANY
)) == 0)
242 GLuint copy
= fixup
& ~IM
->Flag
[start
];
245 /* Equivalent to a lazy copy-from-current when setting up the
248 if (ctx
->ExecuteFlag
&& copy
) {
250 if (MESA_VERBOSE
&VERBOSE_IMMEDIATE
)
251 _tnl_print_vert_flags("copy from current", copy
);
253 if (copy
& VERT_NORM
) {
254 COPY_3V( IM
->Normal
[start
], ctx
->Current
.Normal
);
257 if (copy
& VERT_RGBA
) {
258 COPY_CHAN4( IM
->Color
[start
], ctx
->Current
.Color
);
261 if (copy
& VERT_SPEC_RGB
)
262 COPY_CHAN4( IM
->SecondaryColor
[start
], ctx
->Current
.SecondaryColor
);
264 if (copy
& VERT_FOG_COORD
)
265 IM
->FogCoord
[start
] = ctx
->Current
.FogCoord
;
267 if (copy
& VERT_INDEX
)
268 IM
->Index
[start
] = ctx
->Current
.Index
;
270 if (copy
& VERT_EDGE
)
271 IM
->EdgeFlag
[start
] = ctx
->Current
.EdgeFlag
;
273 if (copy
& VERT_TEX_ANY
) {
275 for (i
= 0 ; i
< ctx
->Const
.MaxTextureUnits
; i
++) {
276 if (copy
& VERT_TEX(i
))
277 COPY_4FV( IM
->TexCoord
[i
][start
], ctx
->Current
.Texcoord
[i
] );
282 if (MESA_VERBOSE
&VERBOSE_IMMEDIATE
)
283 _tnl_print_vert_flags("fixup", fixup
);
285 if (fixup
& VERT_TEX_ANY
) {
287 for (i
= 0 ; i
< ctx
->Const
.MaxTextureUnits
; i
++) {
288 if (fixup
& VERT_TEX(i
)) {
289 if (orflag
& VERT_TEX(i
))
290 _tnl_fixup_4f( IM
->TexCoord
[i
], IM
->Flag
, start
,
293 fixup_first_4f( IM
->TexCoord
[i
], IM
->Flag
, VERT_END_VB
, start
,
294 IM
->TexCoord
[i
][start
]);
300 if (fixup
& VERT_EDGE
) {
301 if (orflag
& VERT_EDGE
)
302 _tnl_fixup_1ub( IM
->EdgeFlag
, IM
->Flag
, start
, VERT_EDGE
);
304 fixup_first_1ub( IM
->EdgeFlag
, IM
->Flag
, VERT_END_VB
, start
,
305 IM
->EdgeFlag
[start
] );
308 if (fixup
& VERT_INDEX
) {
309 if (orflag
& VERT_INDEX
)
310 _tnl_fixup_1ui( IM
->Index
, IM
->Flag
, start
, VERT_INDEX
);
312 fixup_first_1ui( IM
->Index
, IM
->Flag
, VERT_END_VB
, start
,
316 if (fixup
& VERT_RGBA
) {
317 if (orflag
& VERT_RGBA
)
318 _tnl_fixup_4chan( IM
->Color
, IM
->Flag
, start
, VERT_RGBA
);
320 fixup_first_4chan( IM
->Color
, IM
->Flag
, VERT_END_VB
, start
,
324 if (fixup
& VERT_SPEC_RGB
) {
325 if (orflag
& VERT_SPEC_RGB
)
326 _tnl_fixup_4chan( IM
->SecondaryColor
, IM
->Flag
, start
,
329 fixup_first_4chan( IM
->SecondaryColor
, IM
->Flag
, VERT_END_VB
, start
,
330 IM
->SecondaryColor
[start
] );
333 if (fixup
& VERT_FOG_COORD
) {
334 if (orflag
& VERT_FOG_COORD
)
335 _tnl_fixup_1f( IM
->FogCoord
, IM
->Flag
, start
, VERT_FOG_COORD
);
337 fixup_first_1f( IM
->FogCoord
, IM
->Flag
, VERT_END_VB
, start
,
338 IM
->FogCoord
[start
] );
341 if (fixup
& VERT_NORM
) {
342 if (orflag
& VERT_NORM
)
343 _tnl_fixup_3f( IM
->Normal
, IM
->Flag
, start
, VERT_NORM
);
345 fixup_first_3f( IM
->Normal
, IM
->Flag
, VERT_END_VB
, start
,
350 /* Prune possible half-filled slot.
352 IM
->Flag
[IM
->LastData
+1] &= ~VERT_END_VB
;
353 IM
->Flag
[IM
->Count
] |= VERT_END_VB
;
358 if (IM
->MaterialOrMask
& ~IM
->MaterialAndMask
) {
359 GLuint vulnerable
= IM
->MaterialOrMask
;
360 GLuint i
= IM
->Start
;
363 while (!(IM
->Flag
[i
] & VERT_MATERIAL
))
366 vulnerable
&= ~IM
->MaterialMask
[i
];
367 _mesa_copy_material_pairs( IM
->Material
[i
],
372 } while (vulnerable
);
379 static void copy_material( struct immediate
*next
,
380 struct immediate
*prev
,
381 GLuint dst
, GLuint src
)
383 if (next
->Material
== 0) {
384 next
->Material
= (GLmaterial (*)[2]) MALLOC( sizeof(GLmaterial
) *
386 next
->MaterialMask
= (GLuint
*) MALLOC( sizeof(GLuint
) * IMM_SIZE
);
389 next
->MaterialMask
[dst
] = prev
->MaterialOrMask
;
390 MEMCPY(next
->Material
[dst
], prev
->Material
[src
], 2*sizeof(GLmaterial
));
395 /* Copy the untransformed data from the shared vertices of a primitive
396 * that wraps over two immediate structs. This is done prior to
397 * set_immediate so that prev and next may point to the same
398 * structure. In general it's difficult to avoid this copy on long
401 * Have to be careful with the transitions between display list
402 * replay, compile and normal execute modes.
404 static void copy_vertices( GLcontext
*ctx
,
405 struct immediate
*next
,
406 struct immediate
*prev
,
410 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
411 GLuint offset
= IMM_MAX_COPIED_VERTS
- count
;
414 next
->CopyStart
= next
->Start
- count
;
418 for (i
= 0 ; i
< count
; i
++)
420 GLuint src
= elts
[i
+offset
];
421 GLuint dst
= next
->CopyStart
+i
;
423 COPY_4FV( next
->Obj
[dst
], prev
->Obj
[src
] );
424 COPY_3FV( next
->Normal
[dst
], prev
->Normal
[src
] );
425 COPY_CHAN4( next
->Color
[dst
], prev
->Color
[src
] );
427 if (prev
->OrFlag
& VERT_TEX_ANY
) {
429 for (i
= 0 ; i
< prev
->MaxTextureUnits
; i
++) {
430 if (prev
->OrFlag
& VERT_TEX(i
))
431 COPY_4FV( next
->TexCoord
[i
][dst
], prev
->TexCoord
[i
][src
] );
435 if (prev
->Flag
[src
] & VERT_MATERIAL
)
436 copy_material(next
, prev
, dst
, src
);
438 next
->Elt
[dst
] = prev
->Elt
[src
];
439 next
->EdgeFlag
[dst
] = prev
->EdgeFlag
[src
];
440 next
->Index
[dst
] = prev
->Index
[src
];
441 COPY_CHAN4( next
->SecondaryColor
[dst
], prev
->SecondaryColor
[src
] );
442 next
->FogCoord
[dst
] = prev
->FogCoord
[src
];
443 next
->Flag
[dst
] = (prev
->CopyOrFlag
& VERT_FIXUP
);
444 next
->CopyOrFlag
|= prev
->Flag
[src
]; /* redundant for current_im */
445 next
->CopyAndFlag
&= prev
->Flag
[src
]; /* redundant for current_im */
449 ASSERT(prev
== tnl
->ExecCopySource
);
451 if (--tnl
->ExecCopySource
->ref_count
== 0)
452 _tnl_free_immediate( tnl
->ExecCopySource
);
455 tnl
->ExecCopySource
= next
;
457 tnl
->ExecCopyElts
[0] = next
->Start
-3;
458 tnl
->ExecCopyElts
[1] = next
->Start
-2;
459 tnl
->ExecCopyElts
[2] = next
->Start
-1;
462 /* Copy vertices to an empty immediate struct.
464 void _tnl_copy_immediate_vertices( GLcontext
*ctx
, struct immediate
*IM
)
466 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
468 ASSERT(IM
== TNL_CURRENT_IM(ctx
));
469 ASSERT(IM
->Count
== IM
->Start
);
471 /* Need to push this in now as it won't be computed anywhere else/
473 IM
->TexSize
= tnl
->ExecCopyTexSize
;
475 /* A wrapped primitive. We may be copying into a revived
476 * display list immediate, or onto the front of a new execute-mode
479 copy_vertices( ctx
, IM
,
484 if (ctx
->Driver
.CurrentExecPrimitive
== GL_POLYGON
+1) {
485 /* Immediates are built by default to be correct in this state,
486 * and copying to the first slots of an immediate doesn't remove
489 ASSERT(tnl
->ExecCopyTexSize
== 0);
490 ASSERT(tnl
->ExecCopyCount
== 0);
491 ASSERT(IM
->CopyStart
== IM
->Start
);
494 /* Copy the primitive information:
496 IM
->Primitive
[IM
->CopyStart
] = (ctx
->Driver
.CurrentExecPrimitive
| PRIM_LAST
);
497 IM
->LastPrimitive
= IM
->CopyStart
;
499 IM
->Primitive
[IM
->CopyStart
] |= PRIM_PARITY
;
503 /* Revive a compiled immediate struct - propogate new 'Current'
504 * values. Often this is redundant because the current values were
505 * known and fixed up at compile time.
507 void _tnl_fixup_compiled_cassette( GLcontext
*ctx
, struct immediate
*IM
)
509 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
511 GLuint count
= IM
->Count
;
512 GLuint start
= IM
->Start
;
517 IM
->CopyOrFlag
= IM
->OrFlag
; /* redundant for current_im */
518 IM
->CopyAndFlag
= IM
->AndFlag
; /* redundant for current_im */
519 IM
->CopyTexSize
= IM
->TexSize
| tnl
->ExecCopyTexSize
;
521 copy_vertices( ctx
, IM
,
526 if (ctx
->Driver
.CurrentExecPrimitive
== GL_POLYGON
+1) {
527 ASSERT(tnl
->ExecCopyTexSize
== 0);
528 ASSERT(tnl
->ExecCopyCount
== 0);
529 ASSERT(IM
->CopyStart
== IM
->Start
);
532 fixup
= tnl
->pipeline
.inputs
& ~IM
->Flag
[start
] & VERT_FIXUP
;
535 if (fixup
& VERT_TEX_ANY
) {
537 for (i
= 0 ; i
< ctx
->Const
.MaxTextureUnits
; i
++) {
538 if (fixup
& VERT_TEX(i
))
539 fixup_first_4f( IM
->TexCoord
[i
], IM
->Flag
, VERT_TEX(i
), start
,
540 ctx
->Current
.Texcoord
[i
] );
544 if (fixup
& VERT_EDGE
)
545 fixup_first_1ub(IM
->EdgeFlag
, IM
->Flag
, VERT_EDGE
, start
,
546 ctx
->Current
.EdgeFlag
);
548 if (fixup
& VERT_INDEX
)
549 fixup_first_1ui(IM
->Index
, IM
->Flag
, VERT_INDEX
, start
,
550 ctx
->Current
.Index
);
552 if (fixup
& VERT_RGBA
)
553 fixup_first_4chan(IM
->Color
, IM
->Flag
, VERT_RGBA
, start
,
554 ctx
->Current
.Color
);
556 if (fixup
& VERT_SPEC_RGB
)
557 fixup_first_4chan(IM
->SecondaryColor
, IM
->Flag
, VERT_SPEC_RGB
, start
,
558 ctx
->Current
.SecondaryColor
);
560 if (fixup
& VERT_FOG_COORD
)
561 fixup_first_1f(IM
->FogCoord
, IM
->Flag
, VERT_FOG_COORD
, start
,
562 ctx
->Current
.FogCoord
);
564 if (fixup
& VERT_NORM
) {
565 fixup_first_3f(IM
->Normal
, IM
->Flag
, VERT_NORM
, start
,
566 ctx
->Current
.Normal
);
572 if (IM
->MaterialOrMask
& ~IM
->MaterialAndMask
) {
573 GLuint vulnerable
= IM
->MaterialOrMask
;
574 GLuint i
= IM
->Start
;
577 while (!(IM
->Flag
[i
] & VERT_MATERIAL
))
580 vulnerable
&= ~IM
->MaterialMask
[i
];
581 _mesa_copy_material_pairs( IM
->Material
[i
],
586 } while (vulnerable
);
589 /* Can potentially overwrite primitive details - need to save the
592 tnl
->DlistPrimitive
= IM
->Primitive
[IM
->Start
];
593 tnl
->DlistPrimitiveLength
= IM
->PrimitiveLength
[IM
->Start
];
594 tnl
->DlistLastPrimitive
= IM
->LastPrimitive
;
596 /* The first primitive may be different from what was recorded in
597 * the immediate struct. Consider an immediate that starts with a
598 * glBegin, compiled in a display list, which is called from within
599 * an existing Begin/End object.
601 if (ctx
->Driver
.CurrentExecPrimitive
== GL_POLYGON
+1) {
604 if (IM
->BeginState
& VERT_ERROR_1
)
605 _mesa_error( ctx
, GL_INVALID_OPERATION
, "glBegin/glEnd");
607 for (i
= IM
->Start
; i
<= IM
->Count
; i
+= IM
->PrimitiveLength
[i
])
608 if (IM
->Flag
[i
] & (VERT_BEGIN
|VERT_END_VB
))
611 /* Would like to just ignore vertices upto this point. Can't
612 * set copystart because it might skip materials?
614 ASSERT(IM
->Start
== IM
->CopyStart
);
615 if (i
> IM
->CopyStart
) {
616 IM
->Primitive
[IM
->CopyStart
] = GL_POLYGON
+1;
617 IM
->PrimitiveLength
[IM
->CopyStart
] = i
- IM
->CopyStart
;
618 if (IM
->Flag
[i
] & VERT_END_VB
) {
619 IM
->Primitive
[IM
->CopyStart
] |= PRIM_LAST
;
620 IM
->LastPrimitive
= IM
->CopyStart
;
623 /* Shouldn't immediates be set up to have this structure *by default*?
628 if (IM
->BeginState
& VERT_ERROR_0
)
629 _mesa_error( ctx
, GL_INVALID_OPERATION
, "glBegin/glEnd");
631 if (IM
->CopyStart
== IM
->Start
&&
632 IM
->Flag
[IM
->Start
] & (VERT_END
|VERT_END_VB
))
637 IM
->Primitive
[IM
->CopyStart
] = ctx
->Driver
.CurrentExecPrimitive
;
639 IM
->Primitive
[IM
->CopyStart
] |= PRIM_PARITY
;
642 for (i
= IM
->Start
; i
<= IM
->Count
; i
+= IM
->PrimitiveLength
[i
])
643 if (IM
->Flag
[i
] & (VERT_END
|VERT_END_VB
)) {
644 IM
->PrimitiveLength
[IM
->CopyStart
] = i
- IM
->CopyStart
;
645 if (IM
->Flag
[i
] & VERT_END_VB
) {
646 IM
->Primitive
[IM
->CopyStart
] |= PRIM_LAST
;
647 IM
->LastPrimitive
= IM
->CopyStart
;
649 if (IM
->Flag
[i
] & VERT_END
) {
650 IM
->Primitive
[IM
->CopyStart
] |= PRIM_END
;
657 if (IM
->Primitive
[IM
->LastPrimitive
] & PRIM_END
)
658 ctx
->Driver
.CurrentExecPrimitive
= GL_POLYGON
+1;
660 ctx
->Driver
.CurrentExecPrimitive
=
661 IM
->Primitive
[IM
->LastPrimitive
] & PRIM_MODE_MASK
;
665 /* Undo any changes potentially made to the immediate in the range
666 * IM->Start..IM->Count above.
668 void _tnl_restore_compiled_cassette( GLcontext
*ctx
, struct immediate
*IM
)
670 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
671 IM
->Primitive
[IM
->Start
] = tnl
->DlistPrimitive
;
672 IM
->PrimitiveLength
[IM
->Start
] = tnl
->DlistPrimitiveLength
;
680 static void copy_none( TNLcontext
*tnl
, GLuint start
, GLuint count
, GLuint ovf
)
682 (void) (start
&& ovf
&& tnl
&& count
);
685 static void copy_last( TNLcontext
*tnl
, GLuint start
, GLuint count
, GLuint ovf
)
687 (void) start
; (void) ovf
;
688 tnl
->ExecCopyCount
= 1;
689 tnl
->ExecCopyElts
[2] = count
-1;
692 static void copy_first_and_last( TNLcontext
*tnl
, GLuint start
, GLuint count
,
696 tnl
->ExecCopyCount
= 2;
697 tnl
->ExecCopyElts
[1] = start
;
698 tnl
->ExecCopyElts
[2] = count
-1;
701 static void copy_last_two( TNLcontext
*tnl
, GLuint start
, GLuint count
,
705 tnl
->ExecCopyCount
= 2+ovf
;
706 tnl
->ExecCopyElts
[0] = count
-3;
707 tnl
->ExecCopyElts
[1] = count
-2;
708 tnl
->ExecCopyElts
[2] = count
-1;
711 static void copy_overflow( TNLcontext
*tnl
, GLuint start
, GLuint count
,
715 tnl
->ExecCopyCount
= ovf
;
716 tnl
->ExecCopyElts
[0] = count
-3;
717 tnl
->ExecCopyElts
[1] = count
-2;
718 tnl
->ExecCopyElts
[2] = count
-1;
722 typedef void (*copy_func
)( TNLcontext
*tnl
, GLuint start
, GLuint count
,
725 static copy_func copy_tab
[GL_POLYGON
+2] =
744 /* Figure out what vertices need to be copied next time.
747 _tnl_get_exec_copy_verts( GLcontext
*ctx
, struct immediate
*IM
)
750 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
751 GLuint last
= IM
->LastPrimitive
;
752 GLuint prim
= ctx
->Driver
.CurrentExecPrimitive
;
753 GLuint pincr
= increment
[prim
];
754 GLuint pintro
= intro
[prim
];
758 if (tnl
->ExecCopySource
!= IM
) {
759 if (--tnl
->ExecCopySource
->ref_count
== 0)
760 _tnl_free_immediate( tnl
->ExecCopySource
);
762 tnl
->ExecCopySource
= IM
;
765 if (prim
== GL_POLYGON
+1) {
766 tnl
->ExecCopyCount
= 0;
767 tnl
->ExecCopyTexSize
= 0;
770 tnl
->ExecCopyCount
= 0;
771 tnl
->ExecCopyTexSize
= IM
->CopyTexSize
;
772 tnl
->ExecParity
= IM
->PrimitiveLength
[IM
->LastPrimitive
] & 1;
774 if (pincr
!= 1 && (IM
->Count
- last
- pintro
))
775 ovf
= (IM
->Count
- last
- pintro
) % pincr
;
777 if (last
< IM
->Count
)
778 copy_tab
[prim
]( tnl
, last
, IM
->Count
, ovf
);
785 void _tnl_fixup_purged_eval( GLcontext
*ctx
, struct immediate
*IM
)
787 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
789 /* Recalculate ExecCopyElts, ExecParity, etc. These don't need the
790 * post-eval values, so using the original immediate is fine, but
791 * copied vertices will need to be re-evaluated.
793 if (tnl
->CurrentPrimitive
!= GL_POLYGON
+1) {
794 GLuint last
= IM
->LastPrimitive
;
795 GLenum prim
= IM
->Primitive
[last
];
796 GLuint pincr
= increment
[prim
];
797 GLuint pintro
= intro
[prim
];
800 tnl
->ExecCopyCount
= 0;
801 tnl
->ExecParity
= IM
->PrimitiveLength
[last
] & 1;
803 if (pincr
!= 1 && (IM
->Count
- last
- pintro
))
804 ovf
= (IM
->Count
- last
- pintro
) % pincr
;
806 if (last
< IM
->Count
)
807 copy_tab
[prim
]( tnl
, last
, IM
->Count
, ovf
);
809 for (i
= 0 ; i
< tnl
->ExecCopyCount
; i
++)
810 tnl
->ExecCopyElts
[i
] = IM
->Elt
[tnl
->ExecCopyElts
[i
]];