fdfeff566a144d5e987930b218274b4c016e6964
[mesa.git] / src / mesa / tnl / t_imm_fixup.c
1 /* $Id: t_imm_fixup.c,v 1.20 2001/06/04 16:09:28 keithw Exp $ */
2
3 /*
4 * Mesa 3-D graphics library
5 * Version: 3.5
6 *
7 * Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
8 *
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:
15 *
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
18 *
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.
25 */
26
27 /*
28 * Authors:
29 * Keith Whitwell <keithw@valinux.com>
30 */
31
32
33 #include "glheader.h"
34 #include "context.h"
35 #include "enums.h"
36 #include "dlist.h"
37 #include "colormac.h"
38 #include "light.h"
39 #include "macros.h"
40 #include "mem.h"
41 #include "mmath.h"
42 #include "state.h"
43 #include "mtypes.h"
44
45 #include "math/m_matrix.h"
46 #include "math/m_xform.h"
47
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"
54
55
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 };
58
59 void
60 _tnl_fixup_4f( GLfloat data[][4], GLuint flag[], GLuint start, GLuint match )
61 {
62 GLuint i = start;
63
64 for (;;) {
65 if ((flag[++i] & match) == 0) {
66 COPY_4FV(data[i], data[i-1]);
67 if (flag[i] & VERT_END_VB) break;
68 }
69 }
70 }
71
72 void
73 _tnl_fixup_3f( float data[][3], GLuint flag[], GLuint start, GLuint match )
74 {
75 GLuint i = start;
76
77 for (;;) {
78 if ((flag[++i] & match) == 0) {
79 COPY_3V(data[i], data[i-1]);
80 if (flag[i] & VERT_END_VB) break;
81 }
82 }
83 }
84
85
86 void
87 _tnl_fixup_1ui( GLuint *data, GLuint flag[], GLuint start, GLuint match )
88 {
89 GLuint i = start;
90
91 for (;;) {
92 if ((flag[++i] & match) == 0) {
93 data[i] = data[i-1];
94 if (flag[i] & VERT_END_VB) break;
95 }
96 }
97 flag[i] |= match;
98 }
99
100
101 void
102 _tnl_fixup_1f( GLfloat *data, GLuint flag[], GLuint start, GLuint match )
103 {
104 GLuint i = start;
105
106 for (;;) {
107 if ((flag[++i] & match) == 0) {
108 data[i] = data[i-1];
109 if (flag[i] & VERT_END_VB) break;
110 }
111 }
112 flag[i] |= match;
113 }
114
115 void
116 _tnl_fixup_1ub( GLubyte *data, GLuint flag[], GLuint start, GLuint match )
117 {
118 GLuint i = start;
119
120 for (;;) {
121 if ((flag[++i] & match) == 0) {
122 data[i] = data[i-1];
123 if (flag[i] & VERT_END_VB) break;
124 }
125 }
126 flag[i] |= match;
127 }
128
129
130 static void
131 fixup_first_4f( GLfloat data[][4], GLuint flag[], GLuint match,
132 GLuint start, GLfloat *dflt )
133 {
134 GLuint i = start-1;
135 match |= VERT_END_VB;
136
137 while ((flag[++i]&match) == 0)
138 COPY_4FV(data[i], dflt);
139 }
140
141 static void
142 fixup_first_3f( GLfloat data[][3], GLuint flag[], GLuint match,
143 GLuint start, GLfloat *dflt )
144 {
145 GLuint i = start-1;
146 match |= VERT_END_VB;
147
148 while ((flag[++i]&match) == 0)
149 COPY_3FV(data[i], dflt);
150 }
151
152
153 static void
154 fixup_first_1ui( GLuint data[], GLuint flag[], GLuint match,
155 GLuint start, GLuint dflt )
156 {
157 GLuint i = start-1;
158 match |= VERT_END_VB;
159
160 while ((flag[++i]&match) == 0)
161 data[i] = dflt;
162 }
163
164 static void
165 fixup_first_1f( GLfloat data[], GLuint flag[], GLuint match,
166 GLuint start, GLfloat dflt )
167 {
168 GLuint i = start-1;
169 match |= VERT_END_VB;
170
171 while ((flag[++i]&match) == 0)
172 data[i] = dflt;
173 }
174
175
176 static void
177 fixup_first_1ub( GLubyte data[], GLuint flag[], GLuint match,
178 GLuint start, GLubyte dflt )
179 {
180 GLuint i = start-1;
181 match |= VERT_END_VB;
182
183 while ((flag[++i]&match) == 0)
184 data[i] = dflt;
185 }
186
187
188 void _tnl_fixup_input( GLcontext *ctx, struct immediate *IM )
189 {
190 TNLcontext *tnl = TNL_CONTEXT(ctx);
191 GLuint start = IM->CopyStart;
192 GLuint andflag = IM->CopyAndFlag;
193 GLuint orflag = IM->CopyOrFlag;
194 GLuint fixup;
195
196 IM->CopyTexSize = IM->TexSize;
197
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); */
202
203
204 fixup = ~andflag & VERT_FIXUP;
205
206 if (!ctx->CompileFlag)
207 fixup &= tnl->pipeline.inputs;
208
209 if (!ctx->ExecuteFlag)
210 fixup &= orflag;
211
212 if ((orflag & (VERT_OBJ|VERT_EVAL_ANY)) == 0)
213 fixup = 0;
214
215 if (fixup) {
216 GLuint copy = fixup & ~IM->Flag[start];
217
218
219 /* Equivalent to a lazy copy-from-current when setting up the
220 * immediate.
221 */
222 if (ctx->ExecuteFlag && copy) {
223
224 if (MESA_VERBOSE&VERBOSE_IMMEDIATE)
225 _tnl_print_vert_flags("copy from current", copy);
226
227 if (copy & VERT_NORM) {
228 COPY_3V( IM->Normal[start], ctx->Current.Normal );
229 }
230
231 if (copy & VERT_RGBA) {
232 COPY_4FV( IM->Color[start], ctx->Current.Color);
233 }
234
235 if (copy & VERT_SPEC_RGB)
236 COPY_4FV( IM->SecondaryColor[start], ctx->Current.SecondaryColor);
237
238 if (copy & VERT_FOG_COORD)
239 IM->FogCoord[start] = ctx->Current.FogCoord;
240
241 if (copy & VERT_INDEX)
242 IM->Index[start] = ctx->Current.Index;
243
244 if (copy & VERT_EDGE)
245 IM->EdgeFlag[start] = ctx->Current.EdgeFlag;
246
247 if (copy & VERT_TEX_ANY) {
248 GLuint i;
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] );
252 }
253 }
254 }
255
256 if (MESA_VERBOSE&VERBOSE_IMMEDIATE)
257 _tnl_print_vert_flags("fixup", fixup);
258
259 if (fixup & VERT_TEX_ANY) {
260 GLuint i;
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,
265 VERT_TEX(i) );
266 else
267 fixup_first_4f( IM->TexCoord[i], IM->Flag, VERT_END_VB, start,
268 IM->TexCoord[i][start]);
269 }
270 }
271 }
272
273
274 if (fixup & VERT_EDGE) {
275 if (orflag & VERT_EDGE)
276 _tnl_fixup_1ub( IM->EdgeFlag, IM->Flag, start, VERT_EDGE );
277 else
278 fixup_first_1ub( IM->EdgeFlag, IM->Flag, VERT_END_VB, start,
279 IM->EdgeFlag[start] );
280 }
281
282 if (fixup & VERT_INDEX) {
283 if (orflag & VERT_INDEX)
284 _tnl_fixup_1ui( IM->Index, IM->Flag, start, VERT_INDEX );
285 else
286 fixup_first_1ui( IM->Index, IM->Flag, VERT_END_VB, start,
287 IM->Index[start] );
288 }
289
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)
295 */
296 }
297
298 if (fixup & VERT_SPEC_RGB) {
299 if (orflag & VERT_SPEC_RGB)
300 _tnl_fixup_4f( IM->SecondaryColor, IM->Flag, start,
301 VERT_SPEC_RGB );
302 else
303 fixup_first_4f( IM->SecondaryColor, IM->Flag, VERT_END_VB, start,
304 IM->SecondaryColor[start] );
305 }
306
307 if (fixup & VERT_FOG_COORD) {
308 if (orflag & VERT_FOG_COORD)
309 _tnl_fixup_1f( IM->FogCoord, IM->Flag, start, VERT_FOG_COORD );
310 else
311 fixup_first_1f( IM->FogCoord, IM->Flag, VERT_END_VB, start,
312 IM->FogCoord[start] );
313 }
314
315 if (fixup & VERT_NORM) {
316 if (orflag & VERT_NORM)
317 _tnl_fixup_3f( IM->Normal, IM->Flag, start, VERT_NORM );
318 else
319 fixup_first_3f( IM->Normal, IM->Flag, VERT_END_VB, start,
320 IM->Normal[start] );
321 }
322 }
323
324 /* Prune possible half-filled slot.
325 */
326 IM->Flag[IM->LastData+1] &= ~VERT_END_VB;
327 IM->Flag[IM->Count] |= VERT_END_VB;
328
329
330 /* Materials:
331 */
332 if (IM->MaterialOrMask & ~IM->MaterialAndMask) {
333 GLuint vulnerable = IM->MaterialOrMask;
334 GLuint i = IM->Start;
335
336 do {
337 while (!(IM->Flag[i] & VERT_MATERIAL))
338 i++;
339
340 vulnerable &= ~IM->MaterialMask[i];
341 _mesa_copy_material_pairs( IM->Material[i],
342 ctx->Light.Material,
343 vulnerable );
344
345
346 } while (vulnerable);
347 }
348 }
349
350
351
352
353 static void copy_material( struct immediate *next,
354 struct immediate *prev,
355 GLuint dst, GLuint src )
356 {
357 if (next->Material == 0) {
358 next->Material = (GLmaterial (*)[2]) MALLOC( sizeof(GLmaterial) *
359 IMM_SIZE * 2 );
360 next->MaterialMask = (GLuint *) MALLOC( sizeof(GLuint) * IMM_SIZE );
361 }
362
363 next->MaterialMask[dst] = prev->MaterialOrMask;
364 MEMCPY(next->Material[dst], prev->Material[src], 2*sizeof(GLmaterial));
365 }
366
367 static GLboolean is_fan_like[GL_POLYGON+1] = {
368 GL_FALSE,
369 GL_FALSE,
370 GL_TRUE, /* line loop */
371 GL_FALSE,
372 GL_FALSE,
373 GL_FALSE,
374 GL_TRUE, /* tri fan */
375 GL_FALSE,
376 GL_FALSE,
377 GL_TRUE /* polygon */
378 };
379
380
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
385 * primitives.
386 *
387 * Have to be careful with the transitions between display list
388 * replay, compile and normal execute modes.
389 */
390 void _tnl_copy_immediate_vertices( GLcontext *ctx, struct immediate *next )
391 {
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;
398 GLuint i;
399
400 if (!prev) {
401 ASSERT(tnl->ExecCopyCount == 0);
402 return;
403 }
404
405 next->CopyStart = next->Start - count;
406
407 if ((prev->CopyOrFlag & VERT_DATA) == VERT_ELT &&
408 ctx->Array.LockCount &&
409 ctx->Array.Vertex.Enabled)
410 {
411 /* Copy Elt values only
412 */
413 for (i = 0 ; i < count ; i++)
414 {
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;
419 }
420 next->CopyOrFlag |= VERT_ELT;
421 next->CopyAndFlag &= VERT_ELT;
422 }
423 else {
424 /* prev->CopyOrFlag is hacked to include values generated by eval:
425 */
426 GLuint copy = tnl->pipeline.inputs & prev->CopyOrFlag;
427 GLuint flag;
428
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);
434 }
435 else {
436 /* Don't let an early 'glColor', etc. poison the elt path.
437 */
438 next->CopyAndFlag &= (prev->OrFlag & VERT_FIXUP);
439 flag = (prev->OrFlag & VERT_FIXUP);
440 }
441
442
443 /* Copy whole vertices
444 */
445 for (i = 0 ; i < count ; i++)
446 {
447 GLuint src = elts[i+offset];
448 GLuint isrc = src - prev->CopyStart;
449 GLuint dst = next->CopyStart+i;
450
451 /* Values subject to eval must be copied out of the 'inputs'
452 * struct. (Copied rows should not be evaluated twice).
453 *
454 * Note these pointers are null when inactive.
455 */
456 COPY_4FV( next->Obj[dst], inputs->Obj.data[isrc] );
457
458 if (copy & VERT_NORM)
459 COPY_3FV( next->Normal[dst], inputs->Normal.data[isrc] );
460
461 if (copy & VERT_RGBA)
462 COPY_4FV( next->Color[dst],
463 ((GLfloat (*)[4])inputs->Color.Ptr)[isrc] );
464
465 if (copy & VERT_INDEX)
466 next->Index[dst] = inputs->Index.data[isrc];
467
468 if (copy & VERT_TEX_ANY) {
469 GLuint i;
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] );
474 }
475 }
476
477 /* Remaining values should be the same in the 'input' struct and the
478 * original immediate.
479 */
480 if (copy & (VERT_ELT|VERT_EDGE|VERT_SPEC_RGB|VERT_FOG_COORD|
481 VERT_MATERIAL)) {
482
483 if (prev->Flag[src] & VERT_MATERIAL)
484 copy_material(next, prev, dst, src);
485
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];
490 }
491
492 next->Flag[dst] = flag;
493 next->OrFlag |= prev->Flag[src]; /* for non-fanlike prims,
494 otherwise redundant */
495 }
496 }
497
498 if (--tnl->ExecCopySource->ref_count == 0)
499 _tnl_free_immediate( tnl->ExecCopySource );
500
501 tnl->ExecCopySource = 0;
502 tnl->ExecCopyCount = 0;
503 }
504
505
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.
509 */
510 void _tnl_fixup_compiled_cassette( GLcontext *ctx, struct immediate *IM )
511 {
512 TNLcontext *tnl = TNL_CONTEXT(ctx);
513 GLuint fixup;
514 GLuint count = IM->Count;
515 GLuint start = IM->Start;
516
517 if (count == start)
518 return;
519
520 IM->CopyOrFlag = IM->OrFlag;
521 IM->CopyAndFlag = IM->AndFlag;
522 IM->CopyTexSize = IM->TexSize | tnl->ExecCopyTexSize;
523
524 _tnl_copy_immediate_vertices( ctx, IM );
525
526 if (ctx->Driver.CurrentExecPrimitive == GL_POLYGON+1) {
527 ASSERT(IM->CopyStart == IM->Start);
528 }
529
530 /* Naked array elements can be copied into the first cassette in a
531 * display list. Need to translate them away:
532 */
533 if (IM->CopyOrFlag & VERT_ELT) {
534 ASSERT(IM->CopyStart < IM->Start);
535 _tnl_translate_array_elts( ctx, IM, IM->CopyStart, IM->Start );
536 }
537
538 fixup = tnl->pipeline.inputs & ~IM->Flag[start] & VERT_FIXUP;
539
540 if (fixup) {
541 if (fixup & VERT_TEX_ANY) {
542 GLuint i;
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] );
547 }
548 }
549
550 if (fixup & VERT_EDGE)
551 fixup_first_1ub(IM->EdgeFlag, IM->Flag, VERT_EDGE, start,
552 ctx->Current.EdgeFlag );
553
554 if (fixup & VERT_INDEX)
555 fixup_first_1ui(IM->Index, IM->Flag, VERT_INDEX, start,
556 ctx->Current.Index );
557
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 );
562
563 if (fixup & VERT_SPEC_RGB)
564 fixup_first_4f(IM->SecondaryColor, IM->Flag, VERT_SPEC_RGB, start,
565 ctx->Current.SecondaryColor );
566
567 if (fixup & VERT_FOG_COORD)
568 fixup_first_1f(IM->FogCoord, IM->Flag, VERT_FOG_COORD, start,
569 ctx->Current.FogCoord );
570
571 if (fixup & VERT_NORM) {
572 fixup_first_3f(IM->Normal, IM->Flag, VERT_NORM, start,
573 ctx->Current.Normal );
574 }
575 }
576
577 /* Materials:
578 */
579 if (IM->MaterialOrMask & ~IM->MaterialAndMask) {
580 GLuint vulnerable = IM->MaterialOrMask;
581 GLuint i = IM->Start;
582
583 do {
584 while (!(IM->Flag[i] & VERT_MATERIAL))
585 i++;
586
587 vulnerable &= ~IM->MaterialMask[i];
588 _mesa_copy_material_pairs( IM->Material[i],
589 ctx->Light.Material,
590 vulnerable );
591
592
593 } while (vulnerable);
594 }
595 }
596
597
598
599
600
601
602 static void copy_none( TNLcontext *tnl, GLuint start, GLuint count, GLuint ovf)
603 {
604 (void) (start && ovf && tnl && count);
605 }
606
607 static void copy_last( TNLcontext *tnl, GLuint start, GLuint count, GLuint ovf)
608 {
609 (void) start; (void) ovf;
610 tnl->ExecCopyCount = 1;
611 tnl->ExecCopyElts[2] = count-1;
612 }
613
614 static void copy_first_and_last( TNLcontext *tnl, GLuint start, GLuint count,
615 GLuint ovf)
616 {
617 (void) ovf;
618 tnl->ExecCopyCount = 2;
619 tnl->ExecCopyElts[1] = start;
620 tnl->ExecCopyElts[2] = count-1;
621 }
622
623 static void copy_last_two( TNLcontext *tnl, GLuint start, GLuint count,
624 GLuint ovf )
625 {
626 (void) start;
627 tnl->ExecCopyCount = 2+ovf;
628 tnl->ExecCopyElts[0] = count-3;
629 tnl->ExecCopyElts[1] = count-2;
630 tnl->ExecCopyElts[2] = count-1;
631 }
632
633 static void copy_overflow( TNLcontext *tnl, GLuint start, GLuint count,
634 GLuint ovf )
635 {
636 (void) start;
637 tnl->ExecCopyCount = ovf;
638 tnl->ExecCopyElts[0] = count-3;
639 tnl->ExecCopyElts[1] = count-2;
640 tnl->ExecCopyElts[2] = count-1;
641 }
642
643
644 typedef void (*copy_func)( TNLcontext *tnl, GLuint start, GLuint count,
645 GLuint ovf );
646
647 static copy_func copy_tab[GL_POLYGON+2] =
648 {
649 copy_none,
650 copy_overflow,
651 copy_first_and_last,
652 copy_last,
653 copy_overflow,
654 copy_last_two,
655 copy_first_and_last,
656 copy_overflow,
657 copy_last_two,
658 copy_first_and_last,
659 copy_none
660 };
661
662
663
664
665
666 /* Figure out what vertices need to be copied next time.
667 */
668 void
669 _tnl_get_exec_copy_verts( GLcontext *ctx, struct immediate *IM )
670 {
671
672 TNLcontext *tnl = TNL_CONTEXT(ctx);
673 GLuint last = IM->LastPrimitive;
674 GLuint prim = ctx->Driver.CurrentExecPrimitive;
675 GLuint pincr = increment[prim];
676 GLuint pintro = intro[prim];
677 GLuint ovf = 0;
678
679 /* fprintf(stderr, "_tnl_get_exec_copy_verts %s\n", */
680 /* _mesa_lookup_enum_by_nr(prim)); */
681
682 ASSERT(tnl->ExecCopySource == 0);
683
684 if (prim == GL_POLYGON+1) {
685 tnl->ExecCopyCount = 0;
686 tnl->ExecCopyTexSize = 0;
687 tnl->ExecParity = 0;
688 } else {
689 /* Remember this immediate as the one to copy from.
690 */
691 IM->ref_count++;
692 tnl->ExecCopySource = IM;
693 tnl->ExecCopyCount = 0;
694 tnl->ExecCopyTexSize = IM->CopyTexSize;
695 tnl->ExecParity = IM->PrimitiveLength[IM->LastPrimitive] & 1;
696
697 if (pincr != 1 && (IM->Count - last - pintro))
698 ovf = (IM->Count - last - pintro) % pincr;
699
700 if (last < IM->Count)
701 copy_tab[prim]( tnl, last, IM->Count, ovf );
702 }
703 }
704
705
706 /* Recalculate ExecCopyElts, ExecParity, etc.
707 */
708 void
709 _tnl_get_purged_copy_verts( GLcontext *ctx, struct immediate *IM )
710 {
711 TNLcontext *tnl = TNL_CONTEXT(ctx);
712
713 if (ctx->Driver.CurrentExecPrimitive != GL_POLYGON+1) {
714 GLuint last = IM->LastPrimitive;
715 GLenum prim = IM->Primitive[last];
716 GLuint pincr = increment[prim];
717 GLuint pintro = intro[prim];
718 GLuint ovf = 0, i;
719
720 tnl->ExecCopyCount = 0;
721 tnl->ExecParity = IM->PrimitiveLength[last] & 1;
722
723 if (pincr != 1 && (IM->Count - last - pintro))
724 ovf = (IM->Count - last - pintro) % pincr;
725
726 if (last < IM->Count)
727 copy_tab[prim]( tnl, last, IM->Count, ovf );
728
729 for (i = 0 ; i < tnl->ExecCopyCount ; i++)
730 tnl->ExecCopyElts[i] = IM->Elt[tnl->ExecCopyElts[i]];
731 }
732 }
733
734
735 void _tnl_upgrade_current_data( GLcontext *ctx,
736 GLuint required,
737 GLuint flags )
738 {
739 TNLcontext *tnl = TNL_CONTEXT(ctx);
740 struct vertex_buffer *VB = &tnl->vb;
741 struct immediate *IM = (struct immediate *)VB->import_source;
742
743 ASSERT(IM);
744
745 /* _tnl_print_vert_flags("_tnl_upgrade_client_data", required); */
746
747 if ((required & VERT_RGBA) && (VB->ColorPtr[0]->Flags & CA_CLIENT_DATA)) {
748 struct gl_client_array *tmp = &tnl->imm_inputs.Color;
749 GLuint start = IM->CopyStart;
750
751 tmp->Ptr = IM->Color + start;
752 tmp->StrideB = 4 * sizeof(GLfloat);
753 tmp->Flags = 0;
754
755 COPY_4FV( IM->Color[start], ctx->Current.Color);
756
757 ASSERT(IM->Flag[IM->LastData+1] & VERT_END_VB);
758
759 fixup_first_4f( IM->Color, IM->Flag, VERT_END_VB, start,
760 IM->Color[start] );
761
762 VB->importable_data &= ~VERT_RGBA;
763 }
764 }
765