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