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