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