vertex program check-in
[mesa.git] / src / mesa / tnl / t_imm_fixup.c
1 /* $Id: t_imm_fixup.c,v 1.29 2001/12/14 02:51:45 brianp 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_imm_exec.h"
54 #include "t_pipeline.h"
55
56
57 static const GLuint increment[GL_POLYGON+2] = { 1,2,1,1,3,1,1,4,2,1,1 };
58 static const GLuint intro[GL_POLYGON+2] = { 0,0,2,2,0,2,2,0,2,2,0 };
59
60 void
61 _tnl_fixup_4f( GLfloat data[][4], GLuint flag[], GLuint start, GLuint match )
62 {
63 GLuint i = start;
64
65 for (;;) {
66 if ((flag[++i] & match) == 0) {
67 COPY_4FV(data[i], data[i-1]);
68 if (flag[i] & VERT_END_VB) break;
69 }
70 }
71 }
72
73 void
74 _tnl_fixup_3f( float data[][3], GLuint flag[], GLuint start, GLuint match )
75 {
76 GLuint i = start;
77
78
79 for (;;) {
80 if ((flag[++i] & match) == 0) {
81 /* fprintf(stderr, "_tnl_fixup_3f copy to %p values %f %f %f\n", */
82 /* data[i], */
83 /* data[i-1][0], */
84 /* data[i-1][1], */
85 /* data[i-1][2]); */
86 COPY_3V(data[i], data[i-1]);
87 if (flag[i] & VERT_END_VB) break;
88 }
89 }
90 }
91
92
93 void
94 _tnl_fixup_1ui( GLuint *data, GLuint flag[], GLuint start, GLuint match )
95 {
96 GLuint i = start;
97
98 for (;;) {
99 if ((flag[++i] & match) == 0) {
100 data[i] = data[i-1];
101 if (flag[i] & VERT_END_VB) break;
102 }
103 }
104 flag[i] |= match;
105 }
106
107
108 void
109 _tnl_fixup_1f( GLfloat *data, GLuint flag[], GLuint start, GLuint match )
110 {
111 GLuint i = start;
112
113 for (;;) {
114 if ((flag[++i] & match) == 0) {
115 data[i] = data[i-1];
116 if (flag[i] & VERT_END_VB) break;
117 }
118 }
119 flag[i] |= match;
120 }
121
122 void
123 _tnl_fixup_1ub( GLubyte *data, GLuint flag[], GLuint start, GLuint match )
124 {
125 GLuint i = start;
126
127 for (;;) {
128 if ((flag[++i] & match) == 0) {
129 data[i] = data[i-1];
130 if (flag[i] & VERT_END_VB) break;
131 }
132 }
133 flag[i] |= match;
134 }
135
136
137 static void
138 fixup_first_4f( GLfloat data[][4], GLuint flag[], GLuint match,
139 GLuint start, GLfloat *dflt )
140 {
141 GLuint i = start-1;
142 match |= VERT_END_VB;
143
144 while ((flag[++i]&match) == 0)
145 COPY_4FV(data[i], dflt);
146 }
147
148 static void
149 fixup_first_3f( GLfloat data[][3], GLuint flag[], GLuint match,
150 GLuint start, GLfloat *dflt )
151 {
152 GLuint i = start-1;
153 match |= VERT_END_VB;
154
155 /* fprintf(stderr, "fixup_first_3f default: %f %f %f start: %d\n", */
156 /* dflt[0], dflt[1], dflt[2], start); */
157
158 while ((flag[++i]&match) == 0)
159 COPY_3FV(data[i], dflt);
160 }
161
162
163 static void
164 fixup_first_1ui( GLuint data[], GLuint flag[], GLuint match,
165 GLuint start, GLuint dflt )
166 {
167 GLuint i = start-1;
168 match |= VERT_END_VB;
169
170 while ((flag[++i]&match) == 0)
171 data[i] = dflt;
172 }
173
174 static void
175 fixup_first_1f( GLfloat data[], GLuint flag[], GLuint match,
176 GLuint start, GLfloat dflt )
177 {
178 GLuint i = start-1;
179 match |= VERT_END_VB;
180
181 while ((flag[++i]&match) == 0)
182 data[i] = dflt;
183 }
184
185
186 static void
187 fixup_first_1ub( GLubyte data[], GLuint flag[], GLuint match,
188 GLuint start, GLubyte dflt )
189 {
190 GLuint i = start-1;
191 match |= VERT_END_VB;
192
193 while ((flag[++i]&match) == 0)
194 data[i] = dflt;
195 }
196
197 /*
198 * Copy vertex attributes from the ctx->Current group into the immediate
199 * struct at the given position according to copyMask.
200 */
201 static void copy_from_current( GLcontext *ctx, struct immediate *IM,
202 GLuint pos, GLuint copyMask )
203 {
204 if (MESA_VERBOSE&VERBOSE_IMMEDIATE)
205 _tnl_print_vert_flags("copy from current", copyMask);
206
207 if (copyMask & VERT_NORMAL_BIT) {
208 COPY_3V(IM->Normal[pos], ctx->Current.Attrib[VERT_ATTRIB_NORMAL]);
209 }
210
211 if (copyMask & VERT_COLOR0_BIT) {
212 COPY_4FV( IM->Color[pos], ctx->Current.Attrib[VERT_ATTRIB_COLOR0]);
213 }
214
215 if (copyMask & VERT_COLOR1_BIT)
216 COPY_4FV( IM->SecondaryColor[pos], ctx->Current.Attrib[VERT_ATTRIB_COLOR1]);
217
218 if (copyMask & VERT_FOG_BIT)
219 IM->FogCoord[pos] = ctx->Current.Attrib[VERT_ATTRIB_FOG][0];
220
221 if (copyMask & VERT_INDEX_BIT)
222 IM->Index[pos] = ctx->Current.Index;
223
224 if (copyMask & VERT_EDGEFLAG_BIT)
225 IM->EdgeFlag[pos] = ctx->Current.EdgeFlag;
226
227 if (copyMask & VERT_TEX_ANY) {
228 GLuint i;
229 for (i = 0 ; i < ctx->Const.MaxTextureUnits ; i++) {
230 if (copyMask & VERT_TEX(i))
231 COPY_4FV(IM->TexCoord[i][pos], ctx->Current.Attrib[VERT_ATTRIB_TEX0 + i]);
232 }
233 }
234 }
235
236
237 void _tnl_fixup_input( GLcontext *ctx, struct immediate *IM )
238 {
239 TNLcontext *tnl = TNL_CONTEXT(ctx);
240 GLuint start = IM->CopyStart;
241 GLuint andflag = IM->CopyAndFlag;
242 GLuint orflag = IM->CopyOrFlag | IM->Evaluated;
243 GLuint fixup;
244
245 IM->CopyTexSize = IM->TexSize;
246
247 /* fprintf(stderr, "Fixup input, Start: %u Count: %u LastData: %u\n", */
248 /* IM->Start, IM->Count, IM->LastData); */
249 /* _tnl_print_vert_flags("Orflag", orflag); */
250 /* _tnl_print_vert_flags("Andflag", andflag); */
251
252
253 fixup = ~andflag & VERT_FIXUP;
254
255 if (!ctx->CompileFlag)
256 fixup &= tnl->pipeline.inputs;
257
258 if (!ctx->ExecuteFlag)
259 fixup &= orflag;
260
261 if ((orflag & (VERT_OBJ_BIT|VERT_EVAL_ANY)) == 0)
262 fixup = 0;
263
264 if (fixup) {
265 GLuint copy = fixup & ~IM->Flag[start];
266
267
268 /* Equivalent to a lazy copy-from-current when setting up the
269 * immediate.
270 */
271 if (ctx->ExecuteFlag && copy)
272 copy_from_current( ctx, IM, start, copy );
273
274 if (MESA_VERBOSE&VERBOSE_IMMEDIATE)
275 _tnl_print_vert_flags("fixup", fixup);
276
277 if (fixup & VERT_TEX_ANY) {
278 GLuint i;
279 for (i = 0 ; i < ctx->Const.MaxTextureUnits ; i++) {
280 if (fixup & VERT_TEX(i)) {
281 if (orflag & VERT_TEX(i))
282 _tnl_fixup_4f( IM->TexCoord[i], IM->Flag, start,
283 VERT_TEX(i) );
284 else
285 fixup_first_4f( IM->TexCoord[i], IM->Flag, VERT_END_VB, start,
286 IM->TexCoord[i][start]);
287 }
288 }
289 }
290
291
292 if (fixup & VERT_EDGEFLAG_BIT) {
293 if (orflag & VERT_EDGEFLAG_BIT)
294 _tnl_fixup_1ub( IM->EdgeFlag, IM->Flag, start, VERT_EDGEFLAG_BIT );
295 else
296 fixup_first_1ub( IM->EdgeFlag, IM->Flag, VERT_END_VB, start,
297 IM->EdgeFlag[start] );
298 }
299
300 if (fixup & VERT_INDEX_BIT) {
301 if (orflag & VERT_INDEX_BIT)
302 _tnl_fixup_1ui( IM->Index, IM->Flag, start, VERT_INDEX_BIT );
303 else
304 fixup_first_1ui( IM->Index, IM->Flag, VERT_END_VB, start,
305 IM->Index[start] );
306 }
307
308 if (fixup & VERT_COLOR0_BIT) {
309 if (orflag & VERT_COLOR0_BIT)
310 _tnl_fixup_4f( IM->Color, IM->Flag, start, VERT_COLOR0_BIT );
311 /* No need for else case as the drivers understand stride
312 * zero here. (TODO - propogate this)
313 */
314 }
315
316 if (fixup & VERT_COLOR1_BIT) {
317 if (orflag & VERT_COLOR1_BIT)
318 _tnl_fixup_4f( IM->SecondaryColor, IM->Flag, start,
319 VERT_COLOR1_BIT );
320 else
321 fixup_first_4f( IM->SecondaryColor, IM->Flag, VERT_END_VB, start,
322 IM->SecondaryColor[start] );
323 }
324
325 if (fixup & VERT_FOG_BIT) {
326 if (orflag & VERT_FOG_BIT)
327 _tnl_fixup_1f( IM->FogCoord, IM->Flag, start, VERT_FOG_BIT );
328 else
329 fixup_first_1f( IM->FogCoord, IM->Flag, VERT_END_VB, start,
330 IM->FogCoord[start] );
331 }
332
333 if (fixup & VERT_NORMAL_BIT) {
334 if (orflag & VERT_NORMAL_BIT)
335 _tnl_fixup_3f( IM->Normal, IM->Flag, start, VERT_NORMAL_BIT );
336 else
337 fixup_first_3f( IM->Normal, IM->Flag, VERT_END_VB, start,
338 IM->Normal[start] );
339 }
340 }
341
342 /* Prune possible half-filled slot.
343 */
344 IM->Flag[IM->LastData+1] &= ~VERT_END_VB;
345 IM->Flag[IM->Count] |= VERT_END_VB;
346
347
348 /* Materials:
349 */
350 if (IM->MaterialOrMask & ~IM->MaterialAndMask) {
351 GLuint vulnerable = IM->MaterialOrMask;
352 GLuint i = IM->Start;
353
354 do {
355 while (!(IM->Flag[i] & VERT_MATERIAL))
356 i++;
357
358 vulnerable &= ~IM->MaterialMask[i];
359 _mesa_copy_material_pairs( IM->Material[i],
360 ctx->Light.Material,
361 vulnerable );
362
363
364 } while (vulnerable);
365 }
366 }
367
368
369
370
371 static void copy_material( struct immediate *next,
372 struct immediate *prev,
373 GLuint dst, GLuint src )
374 {
375 if (next->Material == 0) {
376 next->Material = (GLmaterial (*)[2]) MALLOC( sizeof(GLmaterial) *
377 IMM_SIZE * 2 );
378 next->MaterialMask = (GLuint *) MALLOC( sizeof(GLuint) * IMM_SIZE );
379 }
380
381 next->MaterialMask[dst] = prev->MaterialOrMask;
382 MEMCPY(next->Material[dst], prev->Material[src], 2*sizeof(GLmaterial));
383 }
384
385 static GLboolean is_fan_like[GL_POLYGON+1] = {
386 GL_FALSE,
387 GL_FALSE,
388 GL_TRUE, /* line loop */
389 GL_FALSE,
390 GL_FALSE,
391 GL_FALSE,
392 GL_TRUE, /* tri fan */
393 GL_FALSE,
394 GL_FALSE,
395 GL_TRUE /* polygon */
396 };
397
398
399 /* Copy the untransformed data from the shared vertices of a primitive
400 * that wraps over two immediate structs. This is done prior to
401 * set_immediate so that prev and next may point to the same
402 * structure. In general it's difficult to avoid this copy on long
403 * primitives.
404 *
405 * Have to be careful with the transitions between display list
406 * replay, compile and normal execute modes.
407 */
408 void _tnl_copy_immediate_vertices( GLcontext *ctx, struct immediate *next )
409 {
410 TNLcontext *tnl = TNL_CONTEXT(ctx);
411 struct immediate *prev = tnl->ExecCopySource;
412 struct vertex_arrays *inputs = &tnl->imm_inputs;
413 GLuint count = tnl->ExecCopyCount;
414 GLuint *elts = tnl->ExecCopyElts;
415 GLuint offset = IMM_MAX_COPIED_VERTS - count;
416 GLuint i;
417
418 if (!prev) {
419 ASSERT(tnl->ExecCopyCount == 0);
420 return;
421 }
422
423 next->CopyStart = next->Start - count;
424 printf("%s() CopyStart = %d\n", __FUNCTION__, next->CopyStart);
425
426 if ((prev->CopyOrFlag & VERT_DATA) == VERT_ELT &&
427 ctx->Array.LockCount &&
428 ctx->Array.Vertex.Enabled)
429 {
430 /* Copy Elt values only
431 */
432 for (i = 0 ; i < count ; i++)
433 {
434 GLuint src = elts[i+offset];
435 GLuint dst = next->CopyStart+i;
436 next->Elt[dst] = prev->Elt[src];
437 next->Flag[dst] = VERT_ELT;
438 }
439 /* fprintf(stderr, "ADDING VERT_ELT!\n"); */
440 next->CopyOrFlag |= VERT_ELT;
441 next->CopyAndFlag &= VERT_ELT;
442 }
443 else {
444 GLuint copy = tnl->pipeline.inputs & (prev->CopyOrFlag|prev->Evaluated);
445 GLuint flag;
446
447 if (is_fan_like[ctx->Driver.CurrentExecPrimitive]) {
448 flag = ((prev->CopyOrFlag|prev->Evaluated) & VERT_FIXUP);
449 next->CopyOrFlag |= flag;
450 }
451 else {
452 /* Don't let an early 'glColor', etc. poison the elt path.
453 */
454 flag = ((prev->OrFlag|prev->Evaluated) & VERT_FIXUP);
455 }
456
457 next->TexSize |= tnl->ExecCopyTexSize;
458 next->CopyAndFlag &= flag;
459
460
461 /* _tnl_print_vert_flags("copy vertex components", copy); */
462 /* _tnl_print_vert_flags("prev copyorflag", prev->CopyOrFlag); */
463 /* _tnl_print_vert_flags("flag", flag); */
464
465 /* Copy whole vertices
466 */
467 for (i = 0 ; i < count ; i++)
468 {
469 GLuint src = elts[i+offset];
470 GLuint isrc = src - prev->CopyStart;
471 GLuint dst = next->CopyStart+i;
472
473 /* Values subject to eval must be copied out of the 'inputs'
474 * struct. (Copied rows should not be evaluated twice).
475 *
476 * Note these pointers are null when inactive.
477 */
478 COPY_4FV( next->Obj[dst], inputs->Obj.data[isrc] );
479
480 if (copy & VERT_NORMAL_BIT) {
481 /* fprintf(stderr, "copy vert norm %d to %d (%p): %f %f %f\n", */
482 /* isrc, dst, */
483 /* next->Normal[dst], */
484 /* inputs->Normal.data[isrc][0], */
485 /* inputs->Normal.data[isrc][1], */
486 /* inputs->Normal.data[isrc][2]); */
487 COPY_3FV( next->Normal[dst], inputs->Normal.data[isrc] );
488 }
489
490 if (copy & VERT_COLOR0_BIT)
491 COPY_4FV( next->Color[dst],
492 ((GLfloat (*)[4])inputs->Color.Ptr)[isrc] );
493
494 if (copy & VERT_INDEX_BIT)
495 next->Index[dst] = inputs->Index.data[isrc];
496
497 if (copy & VERT_TEX_ANY) {
498 GLuint i;
499 for (i = 0 ; i < prev->MaxTextureUnits ; i++) {
500 if (copy & VERT_TEX(i))
501 COPY_4FV( next->TexCoord[i][dst],
502 inputs->TexCoord[i].data[isrc] );
503 }
504 }
505
506 /* Remaining values should be the same in the 'input' struct and the
507 * original immediate.
508 */
509 if (copy & (VERT_ELT|VERT_EDGEFLAG_BIT|VERT_COLOR1_BIT|VERT_FOG_BIT|
510 VERT_MATERIAL)) {
511
512 if (prev->Flag[src] & VERT_MATERIAL)
513 copy_material(next, prev, dst, src);
514
515 next->Elt[dst] = prev->Elt[src];
516 next->EdgeFlag[dst] = prev->EdgeFlag[src];
517 COPY_4FV( next->SecondaryColor[dst], prev->SecondaryColor[src] );
518 next->FogCoord[dst] = prev->FogCoord[src];
519 }
520
521 next->Flag[dst] = flag;
522 next->CopyOrFlag |= prev->Flag[src] & (VERT_FIXUP|
523 VERT_MATERIAL|
524 VERT_OBJ_BIT);
525 }
526 }
527
528 if (--tnl->ExecCopySource->ref_count == 0)
529 _tnl_free_immediate( tnl->ExecCopySource );
530
531 tnl->ExecCopySource = 0;
532 tnl->ExecCopyCount = 0;
533 }
534
535
536
537 /* Revive a compiled immediate struct - propogate new 'Current'
538 * values. Often this is redundant because the current values were
539 * known and fixed up at compile time (or in the first execution of
540 * the cassette).
541 */
542 void _tnl_fixup_compiled_cassette( GLcontext *ctx, struct immediate *IM )
543 {
544 TNLcontext *tnl = TNL_CONTEXT(ctx);
545 GLuint fixup;
546 GLuint start = IM->Start;
547
548 /* fprintf(stderr, "%s\n", __FUNCTION__); */
549
550 IM->Evaluated = 0;
551 IM->CopyOrFlag = IM->OrFlag;
552 IM->CopyAndFlag = IM->AndFlag;
553 IM->CopyTexSize = IM->TexSize | tnl->ExecCopyTexSize;
554
555 _tnl_copy_immediate_vertices( ctx, IM );
556
557 if (ctx->Driver.CurrentExecPrimitive == GL_POLYGON+1) {
558 ASSERT(IM->CopyStart == IM->Start);
559 }
560
561 /* Naked array elements can be copied into the first cassette in a
562 * display list. Need to translate them away:
563 */
564 if (IM->CopyOrFlag & VERT_ELT) {
565 GLuint copy = tnl->pipeline.inputs & ~ctx->Array._Enabled;
566 GLuint i;
567
568 ASSERT(IM->CopyStart < IM->Start);
569
570 _tnl_translate_array_elts( ctx, IM, IM->CopyStart, IM->Start );
571
572 for (i = IM->CopyStart ; i < IM->Start ; i++)
573 copy_from_current( ctx, IM, i, copy );
574
575 _tnl_copy_to_current( ctx, IM, ctx->Array._Enabled, IM->Start );
576 }
577
578 fixup = tnl->pipeline.inputs & ~IM->Flag[start] & VERT_FIXUP;
579
580 /* _tnl_print_vert_flags("fixup compiled", fixup); */
581
582 if (fixup) {
583 if (fixup & VERT_TEX_ANY) {
584 GLuint i;
585 for (i = 0 ; i < ctx->Const.MaxTextureUnits ; i++) {
586 if (fixup & VERT_TEX(i))
587 fixup_first_4f( IM->TexCoord[i], IM->Flag, VERT_TEX(i), start,
588 ctx->Current.Attrib[VERT_ATTRIB_TEX0 + i] );
589 }
590 }
591
592 if (fixup & VERT_EDGEFLAG_BIT)
593 fixup_first_1ub(IM->EdgeFlag, IM->Flag, VERT_EDGEFLAG_BIT, start,
594 ctx->Current.EdgeFlag );
595
596 if (fixup & VERT_INDEX_BIT)
597 fixup_first_1ui(IM->Index, IM->Flag, VERT_INDEX_BIT, start,
598 ctx->Current.Index );
599
600 if (fixup & VERT_COLOR0_BIT) {
601 if (IM->CopyOrFlag & VERT_COLOR0_BIT)
602 fixup_first_4f(IM->Color, IM->Flag, VERT_COLOR0_BIT, start,
603 ctx->Current.Attrib[VERT_ATTRIB_COLOR0] );
604 else
605 fixup &= ~VERT_COLOR0_BIT;
606 }
607
608 if (fixup & VERT_COLOR1_BIT)
609 fixup_first_4f(IM->SecondaryColor, IM->Flag, VERT_COLOR1_BIT, start,
610 ctx->Current.Attrib[VERT_ATTRIB_COLOR1] );
611
612 if (fixup & VERT_FOG_BIT)
613 fixup_first_1f(IM->FogCoord, IM->Flag, VERT_FOG_BIT, start,
614 ctx->Current.Attrib[VERT_ATTRIB_FOG][0] );
615
616 if (fixup & VERT_NORMAL_BIT) {
617 fixup_first_3f(IM->Normal, IM->Flag, VERT_NORMAL_BIT, start,
618 ctx->Current.Attrib[VERT_ATTRIB_NORMAL] );
619 }
620
621 IM->CopyOrFlag |= fixup;
622 }
623
624
625 /* Materials:
626 */
627 if (IM->MaterialOrMask & ~IM->MaterialAndMask) {
628 GLuint vulnerable = IM->MaterialOrMask;
629 GLuint i = IM->Start;
630
631 do {
632 while (!(IM->Flag[i] & VERT_MATERIAL))
633 i++;
634
635 vulnerable &= ~IM->MaterialMask[i];
636 _mesa_copy_material_pairs( IM->Material[i],
637 ctx->Light.Material,
638 vulnerable );
639
640
641 } while (vulnerable);
642 }
643 }
644
645
646
647
648
649
650 static void copy_none( TNLcontext *tnl, GLuint start, GLuint count, GLuint ovf)
651 {
652 (void) (start && ovf && tnl && count);
653 }
654
655 static void copy_last( TNLcontext *tnl, GLuint start, GLuint count, GLuint ovf)
656 {
657 (void) start; (void) ovf;
658 tnl->ExecCopyCount = 1;
659 tnl->ExecCopyElts[2] = count-1;
660 }
661
662 static void copy_first_and_last( TNLcontext *tnl, GLuint start, GLuint count,
663 GLuint ovf)
664 {
665 (void) ovf;
666 tnl->ExecCopyCount = 2;
667 tnl->ExecCopyElts[1] = start;
668 tnl->ExecCopyElts[2] = count-1;
669 }
670
671 static void copy_last_two( TNLcontext *tnl, GLuint start, GLuint count,
672 GLuint ovf )
673 {
674 (void) start;
675 tnl->ExecCopyCount = 2+ovf;
676 tnl->ExecCopyElts[0] = count-3;
677 tnl->ExecCopyElts[1] = count-2;
678 tnl->ExecCopyElts[2] = count-1;
679 }
680
681 static void copy_overflow( TNLcontext *tnl, GLuint start, GLuint count,
682 GLuint ovf )
683 {
684 (void) start;
685 tnl->ExecCopyCount = ovf;
686 tnl->ExecCopyElts[0] = count-3;
687 tnl->ExecCopyElts[1] = count-2;
688 tnl->ExecCopyElts[2] = count-1;
689 }
690
691
692 typedef void (*copy_func)( TNLcontext *tnl, GLuint start, GLuint count,
693 GLuint ovf );
694
695 static copy_func copy_tab[GL_POLYGON+2] =
696 {
697 copy_none,
698 copy_overflow,
699 copy_first_and_last,
700 copy_last,
701 copy_overflow,
702 copy_last_two,
703 copy_first_and_last,
704 copy_overflow,
705 copy_last_two,
706 copy_first_and_last,
707 copy_none
708 };
709
710
711
712
713
714 /* Figure out what vertices need to be copied next time.
715 */
716 void
717 _tnl_get_exec_copy_verts( GLcontext *ctx, struct immediate *IM )
718 {
719
720 TNLcontext *tnl = TNL_CONTEXT(ctx);
721 GLuint last = IM->LastPrimitive;
722 GLuint prim = ctx->Driver.CurrentExecPrimitive;
723 GLuint pincr = increment[prim];
724 GLuint pintro = intro[prim];
725 GLuint ovf = 0;
726
727 /* fprintf(stderr, "_tnl_get_exec_copy_verts %s\n", */
728 /* _mesa_lookup_enum_by_nr(prim)); */
729
730 ASSERT(tnl->ExecCopySource == 0);
731
732 if (prim == GL_POLYGON+1) {
733 tnl->ExecCopyCount = 0;
734 tnl->ExecCopyTexSize = 0;
735 tnl->ExecParity = 0;
736 } else {
737 /* Remember this immediate as the one to copy from.
738 */
739 IM->ref_count++;
740 tnl->ExecCopySource = IM;
741 tnl->ExecCopyCount = 0;
742 tnl->ExecCopyTexSize = IM->CopyTexSize;
743
744 if (IM->LastPrimitive != IM->CopyStart)
745 tnl->ExecParity = 0;
746
747 tnl->ExecParity ^= IM->PrimitiveLength[IM->LastPrimitive] & 1;
748
749
750 if (pincr != 1 && (IM->Count - last - pintro))
751 ovf = (IM->Count - last - pintro) % pincr;
752
753 if (last < IM->Count)
754 copy_tab[prim]( tnl, last, IM->Count, ovf );
755 }
756 }
757
758
759 /* Recalculate ExecCopyElts, ExecParity, etc.
760 */
761 void
762 _tnl_get_purged_copy_verts( GLcontext *ctx, struct immediate *IM )
763 {
764 TNLcontext *tnl = TNL_CONTEXT(ctx);
765
766 if (ctx->Driver.CurrentExecPrimitive != GL_POLYGON+1) {
767 GLuint last = IM->LastPrimitive;
768 GLenum prim = IM->Primitive[last];
769 GLuint pincr = increment[prim];
770 GLuint pintro = intro[prim];
771 GLuint ovf = 0, i;
772
773 tnl->ExecCopyCount = 0;
774 if (IM->LastPrimitive != IM->CopyStart)
775 tnl->ExecParity = 0;
776
777 tnl->ExecParity ^= IM->PrimitiveLength[IM->LastPrimitive] & 1;
778
779 if (pincr != 1 && (IM->Count - last - pintro))
780 ovf = (IM->Count - last - pintro) % pincr;
781
782 if (last < IM->Count)
783 copy_tab[prim]( tnl, last, IM->Count, ovf );
784
785 for (i = 0 ; i < tnl->ExecCopyCount ; i++)
786 tnl->ExecCopyElts[i] = IM->Elt[tnl->ExecCopyElts[i]];
787 }
788 }
789
790
791 void _tnl_upgrade_current_data( GLcontext *ctx,
792 GLuint required,
793 GLuint flags )
794 {
795 TNLcontext *tnl = TNL_CONTEXT(ctx);
796 struct vertex_buffer *VB = &tnl->vb;
797 struct immediate *IM = (struct immediate *)VB->import_source;
798
799 ASSERT(IM);
800
801 /* _tnl_print_vert_flags("_tnl_upgrade_client_data", required); */
802
803 if ((required & VERT_COLOR0_BIT) && (VB->ColorPtr[0]->Flags & CA_CLIENT_DATA)) {
804 struct gl_client_array *tmp = &tnl->imm_inputs.Color;
805 GLuint start = IM->CopyStart;
806
807 tmp->Ptr = IM->Color + start;
808 tmp->StrideB = 4 * sizeof(GLfloat);
809 tmp->Flags = 0;
810
811 COPY_4FV( IM->Color[start], ctx->Current.Attrib[VERT_ATTRIB_COLOR0]);
812
813 /*
814 ASSERT(IM->Flag[IM->LastData+1] & VERT_END_VB);
815 */
816
817 fixup_first_4f( IM->Color, IM->Flag, VERT_END_VB, start,
818 IM->Color[start] );
819
820 VB->importable_data &= ~VERT_COLOR0_BIT;
821 }
822 }
823