ea51850e21c6eb259b660b926aad1778fc16bb6d
1 /* $Id: t_imm_fixup.c,v 1.17 2001/05/14 09:00:51 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_elt.h"
52 #include "t_imm_fixup.h"
53 #include "t_pipeline.h"
56 static const GLuint increment
[GL_POLYGON
+2] = { 1,2,1,1,3,1,1,4,2,1,1 };
57 static const GLuint intro
[GL_POLYGON
+2] = { 0,0,2,2,0,2,2,0,2,2,0 };
60 _tnl_fixup_4f( GLfloat data
[][4], GLuint flag
[], GLuint start
, GLuint match
)
65 if ((flag
[++i
] & match
) == 0) {
66 COPY_4FV(data
[i
], data
[i
-1]);
67 if (flag
[i
] & VERT_END_VB
) break;
73 _tnl_fixup_3f( float data
[][3], GLuint flag
[], GLuint start
, GLuint match
)
78 if ((flag
[++i
] & match
) == 0) {
79 COPY_3V(data
[i
], data
[i
-1]);
80 if (flag
[i
] & VERT_END_VB
) break;
87 _tnl_fixup_1ui( GLuint
*data
, GLuint flag
[], GLuint start
, GLuint match
)
92 if ((flag
[++i
] & match
) == 0) {
94 if (flag
[i
] & VERT_END_VB
) break;
102 _tnl_fixup_1f( GLfloat
*data
, GLuint flag
[], GLuint start
, GLuint match
)
107 if ((flag
[++i
] & match
) == 0) {
109 if (flag
[i
] & VERT_END_VB
) break;
116 _tnl_fixup_1ub( GLubyte
*data
, GLuint flag
[], GLuint start
, GLuint match
)
121 if ((flag
[++i
] & match
) == 0) {
123 if (flag
[i
] & VERT_END_VB
) break;
131 fixup_first_4f( GLfloat data
[][4], GLuint flag
[], GLuint match
,
132 GLuint start
, GLfloat
*dflt
)
135 match
|= VERT_END_VB
;
137 while ((flag
[++i
]&match
) == 0)
138 COPY_4FV(data
[i
], dflt
);
142 fixup_first_3f( GLfloat data
[][3], GLuint flag
[], GLuint match
,
143 GLuint start
, GLfloat
*dflt
)
146 match
|= VERT_END_VB
;
148 while ((flag
[++i
]&match
) == 0)
149 COPY_3FV(data
[i
], dflt
);
154 fixup_first_1ui( GLuint data
[], GLuint flag
[], GLuint match
,
155 GLuint start
, GLuint dflt
)
158 match
|= VERT_END_VB
;
160 while ((flag
[++i
]&match
) == 0)
165 fixup_first_1f( GLfloat data
[], GLuint flag
[], GLuint match
,
166 GLuint start
, GLfloat dflt
)
169 match
|= VERT_END_VB
;
171 while ((flag
[++i
]&match
) == 0)
177 fixup_first_1ub( GLubyte data
[], GLuint flag
[], GLuint match
,
178 GLuint start
, GLubyte dflt
)
181 match
|= VERT_END_VB
;
183 while ((flag
[++i
]&match
) == 0)
188 void _tnl_fixup_input( GLcontext
*ctx
, struct immediate
*IM
)
190 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
191 GLuint start
= IM
->CopyStart
;
192 GLuint andflag
= IM
->CopyAndFlag
;
193 GLuint orflag
= IM
->CopyOrFlag
;
196 IM
->CopyTexSize
= IM
->TexSize
;
198 /* fprintf(stderr, "Fixup input, Start: %u Count: %u LastData: %u\n", */
199 /* IM->Start, IM->Count, IM->LastData); */
200 /* _tnl_print_vert_flags("Orflag", orflag); */
201 /* _tnl_print_vert_flags("Andflag", andflag); */
204 fixup
= ~andflag
& VERT_FIXUP
;
206 if (!ctx
->CompileFlag
)
207 fixup
&= tnl
->pipeline
.inputs
;
209 if (!ctx
->ExecuteFlag
)
212 if ((orflag
& (VERT_OBJ
|VERT_EVAL_ANY
)) == 0)
216 GLuint copy
= fixup
& ~IM
->Flag
[start
];
219 /* Equivalent to a lazy copy-from-current when setting up the
222 if (ctx
->ExecuteFlag
&& copy
) {
224 if (MESA_VERBOSE
&VERBOSE_IMMEDIATE
)
225 _tnl_print_vert_flags("copy from current", copy
);
227 if (copy
& VERT_NORM
) {
228 COPY_3V( IM
->Normal
[start
], ctx
->Current
.Normal
);
231 if (copy
& VERT_RGBA
) {
232 COPY_4FV( IM
->Color
[start
], ctx
->Current
.Color
);
235 if (copy
& VERT_SPEC_RGB
)
236 COPY_4FV( IM
->SecondaryColor
[start
], ctx
->Current
.SecondaryColor
);
238 if (copy
& VERT_FOG_COORD
)
239 IM
->FogCoord
[start
] = ctx
->Current
.FogCoord
;
241 if (copy
& VERT_INDEX
)
242 IM
->Index
[start
] = ctx
->Current
.Index
;
244 if (copy
& VERT_EDGE
)
245 IM
->EdgeFlag
[start
] = ctx
->Current
.EdgeFlag
;
247 if (copy
& VERT_TEX_ANY
) {
249 for (i
= 0 ; i
< ctx
->Const
.MaxTextureUnits
; i
++) {
250 if (copy
& VERT_TEX(i
))
251 COPY_4FV( IM
->TexCoord
[i
][start
], ctx
->Current
.Texcoord
[i
] );
256 if (MESA_VERBOSE
&VERBOSE_IMMEDIATE
)
257 _tnl_print_vert_flags("fixup", fixup
);
259 if (fixup
& VERT_TEX_ANY
) {
261 for (i
= 0 ; i
< ctx
->Const
.MaxTextureUnits
; i
++) {
262 if (fixup
& VERT_TEX(i
)) {
263 if (orflag
& VERT_TEX(i
))
264 _tnl_fixup_4f( IM
->TexCoord
[i
], IM
->Flag
, start
,
267 fixup_first_4f( IM
->TexCoord
[i
], IM
->Flag
, VERT_END_VB
, start
,
268 IM
->TexCoord
[i
][start
]);
274 if (fixup
& VERT_EDGE
) {
275 if (orflag
& VERT_EDGE
)
276 _tnl_fixup_1ub( IM
->EdgeFlag
, IM
->Flag
, start
, VERT_EDGE
);
278 fixup_first_1ub( IM
->EdgeFlag
, IM
->Flag
, VERT_END_VB
, start
,
279 IM
->EdgeFlag
[start
] );
282 if (fixup
& VERT_INDEX
) {
283 if (orflag
& VERT_INDEX
)
284 _tnl_fixup_1ui( IM
->Index
, IM
->Flag
, start
, VERT_INDEX
);
286 fixup_first_1ui( IM
->Index
, IM
->Flag
, VERT_END_VB
, start
,
290 if (fixup
& VERT_RGBA
) {
291 if (orflag
& VERT_RGBA
)
292 _tnl_fixup_4f( IM
->Color
, IM
->Flag
, start
, VERT_RGBA
);
293 /* No need for else case as the drivers understand stride
294 * zero here. (TODO - propogate this)
298 if (fixup
& VERT_SPEC_RGB
) {
299 if (orflag
& VERT_SPEC_RGB
)
300 _tnl_fixup_4f( IM
->SecondaryColor
, IM
->Flag
, start
,
303 fixup_first_4f( IM
->SecondaryColor
, IM
->Flag
, VERT_END_VB
, start
,
304 IM
->SecondaryColor
[start
] );
307 if (fixup
& VERT_FOG_COORD
) {
308 if (orflag
& VERT_FOG_COORD
)
309 _tnl_fixup_1f( IM
->FogCoord
, IM
->Flag
, start
, VERT_FOG_COORD
);
311 fixup_first_1f( IM
->FogCoord
, IM
->Flag
, VERT_END_VB
, start
,
312 IM
->FogCoord
[start
] );
315 if (fixup
& VERT_NORM
) {
316 if (orflag
& VERT_NORM
)
317 _tnl_fixup_3f( IM
->Normal
, IM
->Flag
, start
, VERT_NORM
);
319 fixup_first_3f( IM
->Normal
, IM
->Flag
, VERT_END_VB
, start
,
324 /* Prune possible half-filled slot.
326 IM
->Flag
[IM
->LastData
+1] &= ~VERT_END_VB
;
327 IM
->Flag
[IM
->Count
] |= VERT_END_VB
;
332 if (IM
->MaterialOrMask
& ~IM
->MaterialAndMask
) {
333 GLuint vulnerable
= IM
->MaterialOrMask
;
334 GLuint i
= IM
->Start
;
337 while (!(IM
->Flag
[i
] & VERT_MATERIAL
))
340 vulnerable
&= ~IM
->MaterialMask
[i
];
341 _mesa_copy_material_pairs( IM
->Material
[i
],
346 } while (vulnerable
);
353 static void copy_material( struct immediate
*next
,
354 struct immediate
*prev
,
355 GLuint dst
, GLuint src
)
357 if (next
->Material
== 0) {
358 next
->Material
= (GLmaterial (*)[2]) MALLOC( sizeof(GLmaterial
) *
360 next
->MaterialMask
= (GLuint
*) MALLOC( sizeof(GLuint
) * IMM_SIZE
);
363 next
->MaterialMask
[dst
] = prev
->MaterialOrMask
;
364 MEMCPY(next
->Material
[dst
], prev
->Material
[src
], 2*sizeof(GLmaterial
));
367 static GLboolean is_fan_like
[GL_POLYGON
+1] = {
371 GL_TRUE
, /* line loop */
374 GL_TRUE
, /* tri fan */
377 GL_TRUE
/* polygon */
381 /* Copy the untransformed data from the shared vertices of a primitive
382 * that wraps over two immediate structs. This is done prior to
383 * set_immediate so that prev and next may point to the same
384 * structure. In general it's difficult to avoid this copy on long
387 * Have to be careful with the transitions between display list
388 * replay, compile and normal execute modes.
390 void _tnl_copy_immediate_vertices( GLcontext
*ctx
, struct immediate
*next
)
392 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
393 struct immediate
*prev
= tnl
->ExecCopySource
;
394 struct vertex_arrays
*inputs
= &tnl
->imm_inputs
;
395 GLuint count
= tnl
->ExecCopyCount
;
396 GLuint
*elts
= tnl
->ExecCopyElts
;
397 GLuint offset
= IMM_MAX_COPIED_VERTS
- count
;
401 ASSERT(tnl
->ExecCopyCount
== 0);
405 next
->CopyStart
= next
->Start
- count
;
407 if ((prev
->CopyOrFlag
& VERT_DATA
) == VERT_ELT
&&
408 ctx
->Array
.LockCount
&&
409 ctx
->Array
.Vertex
.Enabled
)
411 /* Copy Elt values only
413 for (i
= 0 ; i
< count
; i
++)
415 GLuint src
= elts
[i
+offset
];
416 GLuint dst
= next
->CopyStart
+i
;
417 next
->Elt
[dst
] = prev
->Elt
[src
];
418 next
->Flag
[dst
] = VERT_ELT
;
420 next
->CopyOrFlag
|= VERT_ELT
;
421 next
->CopyAndFlag
&= VERT_ELT
;
424 /* prev->CopyOrFlag is hacked to include values generated by eval:
426 GLuint copy
= tnl
->pipeline
.inputs
& prev
->CopyOrFlag
;
429 if (is_fan_like
[ctx
->Driver
.CurrentExecPrimitive
]) {
430 next
->TexSize
|= tnl
->ExecCopyTexSize
;
431 next
->CopyOrFlag
|= (prev
->CopyOrFlag
& VERT_FIXUP
);
432 next
->CopyAndFlag
&= (prev
->CopyOrFlag
& VERT_FIXUP
);
433 flag
= (prev
->CopyOrFlag
& VERT_FIXUP
);
436 /* Don't let an early 'glColor', etc. poison the elt path.
438 next
->CopyAndFlag
&= (prev
->OrFlag
& VERT_FIXUP
);
439 flag
= (prev
->OrFlag
& VERT_FIXUP
);
443 /* Copy whole vertices
445 for (i
= 0 ; i
< count
; i
++)
447 GLuint src
= elts
[i
+offset
];
448 GLuint isrc
= src
- prev
->CopyStart
;
449 GLuint dst
= next
->CopyStart
+i
;
451 /* Values subject to eval must be copied out of the 'inputs'
452 * struct. (Copied rows should not be evaluated twice).
454 * Note these pointers are null when inactive.
456 COPY_4FV( next
->Obj
[dst
], inputs
->Obj
.data
[isrc
] );
458 if (copy
& VERT_NORM
)
459 COPY_3FV( next
->Normal
[dst
], inputs
->Normal
.data
[isrc
] );
461 if (copy
& VERT_RGBA
)
462 COPY_4FV( next
->Color
[dst
],
463 ((GLfloat (*)[4])inputs
->Color
.Ptr
)[isrc
] );
465 if (copy
& VERT_INDEX
)
466 next
->Index
[dst
] = inputs
->Index
.data
[isrc
];
468 if (copy
& VERT_TEX_ANY
) {
470 for (i
= 0 ; i
< prev
->MaxTextureUnits
; i
++) {
471 if (copy
& VERT_TEX(i
))
472 COPY_4FV( next
->TexCoord
[i
][dst
],
473 inputs
->TexCoord
[i
].data
[isrc
] );
477 /* Remaining values should be the same in the 'input' struct and the
478 * original immediate.
480 if (copy
& (VERT_ELT
|VERT_EDGE
|VERT_SPEC_RGB
|VERT_FOG_COORD
|
483 if (prev
->Flag
[src
] & VERT_MATERIAL
)
484 copy_material(next
, prev
, dst
, src
);
486 next
->Elt
[dst
] = prev
->Elt
[src
];
487 next
->EdgeFlag
[dst
] = prev
->EdgeFlag
[src
];
488 COPY_4FV( next
->SecondaryColor
[dst
], prev
->SecondaryColor
[src
] );
489 next
->FogCoord
[dst
] = prev
->FogCoord
[src
];
492 next
->Flag
[dst
] = flag
;
493 next
->OrFlag
|= prev
->Flag
[src
]; /* for non-fanlike prims,
494 otherwise redundant */
498 if (--tnl
->ExecCopySource
->ref_count
== 0)
499 _tnl_free_immediate( tnl
->ExecCopySource
);
501 tnl
->ExecCopySource
= 0;
502 tnl
->ExecCopyCount
= 0;
506 /* Revive a compiled immediate struct - propogate new 'Current'
507 * values. Often this is redundant because the current values were
508 * known and fixed up at compile time.
510 void _tnl_fixup_compiled_cassette( GLcontext
*ctx
, struct immediate
*IM
)
512 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
514 GLuint count
= IM
->Count
;
515 GLuint start
= IM
->Start
;
520 IM
->CopyOrFlag
= IM
->OrFlag
;
521 IM
->CopyAndFlag
= IM
->AndFlag
;
522 IM
->CopyTexSize
= IM
->TexSize
| tnl
->ExecCopyTexSize
;
524 _tnl_copy_immediate_vertices( ctx
, IM
);
526 if (ctx
->Driver
.CurrentExecPrimitive
== GL_POLYGON
+1) {
527 ASSERT(IM
->CopyStart
== IM
->Start
);
530 /* Naked array elements can be copied into the first cassette in a
531 * display list. Need to translate them away:
533 if (IM
->CopyOrFlag
& VERT_ELT
) {
534 ASSERT(IM
->CopyStart
< IM
->Start
);
535 _tnl_translate_array_elts( ctx
, IM
, IM
->CopyStart
, IM
->Start
);
538 fixup
= tnl
->pipeline
.inputs
& ~IM
->Flag
[start
] & VERT_FIXUP
;
541 if (fixup
& VERT_TEX_ANY
) {
543 for (i
= 0 ; i
< ctx
->Const
.MaxTextureUnits
; i
++) {
544 if (fixup
& VERT_TEX(i
))
545 fixup_first_4f( IM
->TexCoord
[i
], IM
->Flag
, VERT_TEX(i
), start
,
546 ctx
->Current
.Texcoord
[i
] );
550 if (fixup
& VERT_EDGE
)
551 fixup_first_1ub(IM
->EdgeFlag
, IM
->Flag
, VERT_EDGE
, start
,
552 ctx
->Current
.EdgeFlag
);
554 if (fixup
& VERT_INDEX
)
555 fixup_first_1ui(IM
->Index
, IM
->Flag
, VERT_INDEX
, start
,
556 ctx
->Current
.Index
);
558 if (fixup
& VERT_RGBA
)
559 if (IM
->CopyOrFlag
& VERT_RGBA
)
560 fixup_first_4f(IM
->Color
, IM
->Flag
, VERT_RGBA
, start
,
561 ctx
->Current
.Color
);
563 if (fixup
& VERT_SPEC_RGB
)
564 fixup_first_4f(IM
->SecondaryColor
, IM
->Flag
, VERT_SPEC_RGB
, start
,
565 ctx
->Current
.SecondaryColor
);
567 if (fixup
& VERT_FOG_COORD
)
568 fixup_first_1f(IM
->FogCoord
, IM
->Flag
, VERT_FOG_COORD
, start
,
569 ctx
->Current
.FogCoord
);
571 if (fixup
& VERT_NORM
) {
572 fixup_first_3f(IM
->Normal
, IM
->Flag
, VERT_NORM
, start
,
573 ctx
->Current
.Normal
);
579 if (IM
->MaterialOrMask
& ~IM
->MaterialAndMask
) {
580 GLuint vulnerable
= IM
->MaterialOrMask
;
581 GLuint i
= IM
->Start
;
584 while (!(IM
->Flag
[i
] & VERT_MATERIAL
))
587 vulnerable
&= ~IM
->MaterialMask
[i
];
588 _mesa_copy_material_pairs( IM
->Material
[i
],
593 } while (vulnerable
);
596 /* Can potentially overwrite primitive details - need to save the
599 tnl
->DlistPrimitive
= IM
->Primitive
[IM
->Start
];
600 tnl
->DlistPrimitiveLength
= IM
->PrimitiveLength
[IM
->Start
];
601 tnl
->DlistLastPrimitive
= IM
->LastPrimitive
;
603 /* The first primitive may be different from what was recorded in
604 * the immediate struct. Consider an immediate that starts with a
605 * glBegin, compiled in a display list, which is called from within
606 * an existing Begin/End object.
608 if (ctx
->Driver
.CurrentExecPrimitive
== GL_POLYGON
+1) {
611 if (IM
->BeginState
& VERT_ERROR_1
)
612 _mesa_error( ctx
, GL_INVALID_OPERATION
, "glBegin/glEnd");
614 for (i
= IM
->Start
; i
<= IM
->Count
; i
+= IM
->PrimitiveLength
[i
])
615 if (IM
->Flag
[i
] & (VERT_BEGIN
|VERT_END_VB
))
618 /* Would like to just ignore vertices upto this point. Can't
619 * set copystart because it might skip materials?
621 ASSERT(IM
->Start
== IM
->CopyStart
);
622 if (i
> IM
->CopyStart
) {
623 IM
->Primitive
[IM
->CopyStart
] = GL_POLYGON
+1;
624 IM
->PrimitiveLength
[IM
->CopyStart
] = i
- IM
->CopyStart
;
625 if (IM
->Flag
[i
] & VERT_END_VB
) {
626 IM
->Primitive
[IM
->CopyStart
] |= PRIM_LAST
;
627 IM
->LastPrimitive
= IM
->CopyStart
;
633 if (IM
->BeginState
& VERT_ERROR_0
)
634 _mesa_error( ctx
, GL_INVALID_OPERATION
, "glBegin/glEnd");
636 if (IM
->CopyStart
== IM
->Start
&&
637 IM
->Flag
[IM
->Start
] & (VERT_END
|VERT_END_VB
))
642 IM
->Primitive
[IM
->CopyStart
] = ctx
->Driver
.CurrentExecPrimitive
;
644 IM
->Primitive
[IM
->CopyStart
] |= PRIM_PARITY
;
646 /* one of these should be true, else we'll be in an infinite loop */
647 assert(IM
->PrimitiveLength
[IM
->Start
] > 0 ||
648 IM
->Flag
[IM
->Start
] & (VERT_END
|VERT_END_VB
));
649 for (i
= IM
->Start
; i
<= IM
->Count
; i
+= IM
->PrimitiveLength
[i
])
650 if (IM
->Flag
[i
] & (VERT_END
|VERT_END_VB
)) {
651 IM
->PrimitiveLength
[IM
->CopyStart
] = i
- IM
->CopyStart
;
652 if (IM
->Flag
[i
] & VERT_END_VB
) {
653 IM
->Primitive
[IM
->CopyStart
] |= PRIM_LAST
;
654 IM
->LastPrimitive
= IM
->CopyStart
;
656 if (IM
->Flag
[i
] & VERT_END
) {
657 IM
->Primitive
[IM
->CopyStart
] |= PRIM_END
;
664 if (IM
->Primitive
[IM
->LastPrimitive
] & PRIM_END
)
665 ctx
->Driver
.CurrentExecPrimitive
= GL_POLYGON
+1;
667 ctx
->Driver
.CurrentExecPrimitive
=
668 IM
->Primitive
[IM
->LastPrimitive
] & PRIM_MODE_MASK
;
670 /* fprintf(stderr, "setting cep %x in %s\n", */
671 /* ctx->Driver.CurrentExecPrimitive, __FUNCTION__); */
672 /* fprintf(stderr, "%s lastprim %d: %x\n", __FUNCTION__, */
673 /* IM->LastPrimitive, IM->Primitive[IM->LastPrimitive]); */
677 /* Undo any changes potentially made to the immediate in the range
678 * IM->Start..IM->Count above.
680 void _tnl_restore_compiled_cassette( GLcontext
*ctx
, struct immediate
*IM
)
682 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
683 IM
->Primitive
[IM
->Start
] = tnl
->DlistPrimitive
;
684 IM
->PrimitiveLength
[IM
->Start
] = tnl
->DlistPrimitiveLength
;
692 static void copy_none( TNLcontext
*tnl
, GLuint start
, GLuint count
, GLuint ovf
)
694 (void) (start
&& ovf
&& tnl
&& count
);
697 static void copy_last( TNLcontext
*tnl
, GLuint start
, GLuint count
, GLuint ovf
)
699 (void) start
; (void) ovf
;
700 tnl
->ExecCopyCount
= 1;
701 tnl
->ExecCopyElts
[2] = count
-1;
704 static void copy_first_and_last( TNLcontext
*tnl
, GLuint start
, GLuint count
,
708 tnl
->ExecCopyCount
= 2;
709 tnl
->ExecCopyElts
[1] = start
;
710 tnl
->ExecCopyElts
[2] = count
-1;
713 static void copy_last_two( TNLcontext
*tnl
, GLuint start
, GLuint count
,
717 tnl
->ExecCopyCount
= 2+ovf
;
718 tnl
->ExecCopyElts
[0] = count
-3;
719 tnl
->ExecCopyElts
[1] = count
-2;
720 tnl
->ExecCopyElts
[2] = count
-1;
723 static void copy_overflow( TNLcontext
*tnl
, GLuint start
, GLuint count
,
727 tnl
->ExecCopyCount
= ovf
;
728 tnl
->ExecCopyElts
[0] = count
-3;
729 tnl
->ExecCopyElts
[1] = count
-2;
730 tnl
->ExecCopyElts
[2] = count
-1;
734 typedef void (*copy_func
)( TNLcontext
*tnl
, GLuint start
, GLuint count
,
737 static copy_func copy_tab
[GL_POLYGON
+2] =
756 /* Figure out what vertices need to be copied next time.
759 _tnl_get_exec_copy_verts( GLcontext
*ctx
, struct immediate
*IM
)
762 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
763 GLuint last
= IM
->LastPrimitive
;
764 GLuint prim
= ctx
->Driver
.CurrentExecPrimitive
;
765 GLuint pincr
= increment
[prim
];
766 GLuint pintro
= intro
[prim
];
769 /* fprintf(stderr, "_tnl_get_exec_copy_verts %s\n", */
770 /* _mesa_lookup_enum_by_nr(prim)); */
772 ASSERT(tnl
->ExecCopySource
== 0);
774 if (prim
== GL_POLYGON
+1) {
775 tnl
->ExecCopyCount
= 0;
776 tnl
->ExecCopyTexSize
= 0;
779 /* Remember this immediate as the one to copy from.
782 tnl
->ExecCopySource
= IM
;
783 tnl
->ExecCopyCount
= 0;
784 tnl
->ExecCopyTexSize
= IM
->CopyTexSize
;
785 tnl
->ExecParity
= IM
->PrimitiveLength
[IM
->LastPrimitive
] & 1;
787 if (pincr
!= 1 && (IM
->Count
- last
- pintro
))
788 ovf
= (IM
->Count
- last
- pintro
) % pincr
;
790 if (last
< IM
->Count
)
791 copy_tab
[prim
]( tnl
, last
, IM
->Count
, ovf
);
796 /* Recalculate ExecCopyElts, ExecParity, etc.
799 _tnl_get_purged_copy_verts( GLcontext
*ctx
, struct immediate
*IM
)
801 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
803 if (ctx
->Driver
.CurrentExecPrimitive
!= GL_POLYGON
+1) {
804 GLuint last
= IM
->LastPrimitive
;
805 GLenum prim
= IM
->Primitive
[last
];
806 GLuint pincr
= increment
[prim
];
807 GLuint pintro
= intro
[prim
];
810 tnl
->ExecCopyCount
= 0;
811 tnl
->ExecParity
= IM
->PrimitiveLength
[last
] & 1;
813 if (pincr
!= 1 && (IM
->Count
- last
- pintro
))
814 ovf
= (IM
->Count
- last
- pintro
) % pincr
;
816 if (last
< IM
->Count
)
817 copy_tab
[prim
]( tnl
, last
, IM
->Count
, ovf
);
819 for (i
= 0 ; i
< tnl
->ExecCopyCount
; i
++)
820 tnl
->ExecCopyElts
[i
] = IM
->Elt
[tnl
->ExecCopyElts
[i
]];
825 void _tnl_upgrade_current_data( GLcontext
*ctx
,
829 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
830 struct immediate
*IM
= TNL_CURRENT_IM(ctx
); /* hmmm */
831 struct vertex_buffer
*VB
= &tnl
->vb
;
835 /* _tnl_print_vert_flags("_tnl_upgrade_client_data", required); */
837 if ((required
& VERT_RGBA
) && (VB
->ColorPtr
[0]->Flags
& CA_CLIENT_DATA
)) {
838 struct gl_client_array
*tmp
= &tnl
->imm_inputs
.Color
;
839 GLuint start
= IM
->CopyStart
;
841 tmp
->Ptr
= IM
->Color
+ start
;
842 tmp
->StrideB
= 4 * sizeof(GLfloat
);
845 COPY_4FV( IM
->Color
[start
], ctx
->Current
.Color
);
846 fixup_first_4f( IM
->Color
, IM
->Flag
, VERT_END_VB
, start
,
849 VB
->importable_data
&= ~VERT_RGBA
;