Perform fixup on material values
[mesa.git] / src / mesa / tnl / t_imm_fixup.c
1 /* $Id: t_imm_fixup.c,v 1.10 2001/04/09 14:47:34 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_fixup.h"
52 #include "t_pipeline.h"
53
54
55
56 static void
57 fixup_4f( GLfloat data[][4], GLuint flag[], GLuint start, GLuint match )
58 {
59 GLuint i = start;
60
61 for (;;) {
62 if ((flag[++i] & match) == 0) {
63 COPY_4FV(data[i], data[i-1]);
64 if (flag[i] & VERT_END_VB) break;
65 }
66 }
67 }
68
69 static void
70 fixup_3f( float data[][3], GLuint flag[], GLuint start, GLuint match )
71 {
72 GLuint i = start;
73
74 for (;;) {
75 if ((flag[++i] & match) == 0) {
76 COPY_3V(data[i], data[i-1]);
77 if (flag[i] & VERT_END_VB) break;
78 }
79 }
80 }
81
82
83 static void
84 fixup_1ui( GLuint *data, GLuint flag[], GLuint start, GLuint match )
85 {
86 GLuint i = start;
87
88 for (;;) {
89 if ((flag[++i] & match) == 0) {
90 data[i] = data[i-1];
91 if (flag[i] & VERT_END_VB) break;
92 }
93 }
94 flag[i] |= match;
95 }
96
97
98 static void
99 fixup_1f( GLfloat *data, GLuint flag[], GLuint start, GLuint match )
100 {
101 GLuint i = start;
102
103 for (;;) {
104 if ((flag[++i] & match) == 0) {
105 data[i] = data[i-1];
106 if (flag[i] & VERT_END_VB) break;
107 }
108 }
109 flag[i] |= match;
110 }
111
112 static void
113 fixup_1ub( GLubyte *data, GLuint flag[], GLuint start, GLuint match )
114 {
115 GLuint i = start;
116
117 for (;;) {
118 if ((flag[++i] & match) == 0) {
119 data[i] = data[i-1];
120 if (flag[i] & VERT_END_VB) break;
121 }
122 }
123 flag[i] |= match;
124 }
125
126
127 static void
128 fixup_4chan( GLchan data[][4], GLuint flag[], GLuint start, GLuint match )
129 {
130 GLuint i = start;
131
132 for (;;) {
133 if ((flag[++i] & match) == 0) {
134 COPY_CHAN4(data[i], data[i-1]);
135 if (flag[i] & VERT_END_VB) break;
136 }
137 }
138 flag[i] |= match;
139 }
140
141
142 static void
143 fixup_first_4f( GLfloat data[][4], GLuint flag[], GLuint match,
144 GLuint start, GLfloat *dflt )
145 {
146 GLuint i = start-1;
147 match |= VERT_END_VB;
148
149 while ((flag[++i]&match) == 0)
150 COPY_4FV(data[i], dflt);
151 }
152
153 static void
154 fixup_first_3f( GLfloat data[][3], GLuint flag[], GLuint match,
155 GLuint start, GLfloat *dflt )
156 {
157 GLuint i = start-1;
158 match |= VERT_END_VB;
159
160 while ((flag[++i]&match) == 0)
161 COPY_3FV(data[i], dflt);
162 }
163
164
165 static void
166 fixup_first_1ui( GLuint data[], GLuint flag[], GLuint match,
167 GLuint start, GLuint dflt )
168 {
169 GLuint i = start-1;
170 match |= VERT_END_VB;
171
172 while ((flag[++i]&match) == 0)
173 data[i] = dflt;
174 }
175
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_END_VB;
182
183 while ((flag[++i]&match) == 0)
184 data[i] = dflt;
185 }
186
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_END_VB;
194
195 while ((flag[++i]&match) == 0)
196 data[i] = dflt;
197 }
198
199
200 static void
201 fixup_first_4chan( GLchan data[][4], GLuint flag[], GLuint match,
202 GLuint start, GLchan dflt[4] )
203 {
204 GLuint i = start-1;
205 match |= VERT_END_VB;
206
207 while ((flag[++i]&match) == 0)
208 COPY_CHAN4(data[i], dflt);
209 }
210
211
212 void _tnl_fixup_input( GLcontext *ctx, struct immediate *IM )
213 {
214 TNLcontext *tnl = TNL_CONTEXT(ctx);
215 GLuint start = IM->CopyStart;
216 GLuint andflag = IM->CopyAndFlag;
217 GLuint orflag = IM->CopyOrFlag;
218 GLuint fixup;
219
220 IM->CopyTexSize = IM->TexSize;
221
222 /* fprintf(stderr, "Fixup input, Start: %u Count: %u LastData: %u\n", */
223 /* IM->Start, IM->Count, IM->LastData); */
224 /* _tnl_print_vert_flags("Orflag", orflag); */
225 /* _tnl_print_vert_flags("Andflag", andflag); */
226
227
228 fixup = ~andflag & VERT_FIXUP;
229
230 if (!ctx->CompileFlag)
231 fixup &= tnl->pipeline.inputs;
232
233 if (!ctx->ExecuteFlag)
234 fixup &= orflag;
235
236 if ((orflag & (VERT_OBJ|VERT_EVAL_ANY)) == 0)
237 fixup = 0;
238
239 if (fixup) {
240 GLuint copy = fixup & ~IM->Flag[start];
241
242
243 /* Equivalent to a lazy copy-from-current when setting up the
244 * immediate.
245 */
246 if (ctx->ExecuteFlag && copy) {
247
248 if (MESA_VERBOSE&VERBOSE_IMMEDIATE)
249 _tnl_print_vert_flags("copy from current", copy);
250
251 if (copy & VERT_NORM) {
252 COPY_3V( IM->Normal[start], ctx->Current.Normal );
253 }
254
255 if (copy & VERT_RGBA) {
256 COPY_CHAN4( IM->Color[start], ctx->Current.Color);
257 }
258
259 if (copy & VERT_SPEC_RGB)
260 COPY_CHAN4( IM->SecondaryColor[start], ctx->Current.SecondaryColor);
261
262 if (copy & VERT_FOG_COORD)
263 IM->FogCoord[start] = ctx->Current.FogCoord;
264
265 if (copy & VERT_INDEX)
266 IM->Index[start] = ctx->Current.Index;
267
268 if (copy & VERT_EDGE)
269 IM->EdgeFlag[start] = ctx->Current.EdgeFlag;
270
271 if (copy & VERT_TEX_ANY) {
272 GLuint i;
273 for (i = 0 ; i < ctx->Const.MaxTextureUnits ; i++) {
274 if (copy & VERT_TEX(i))
275 COPY_4FV( IM->TexCoord[i][start], ctx->Current.Texcoord[i] );
276 }
277 }
278 }
279
280 if (MESA_VERBOSE&VERBOSE_IMMEDIATE)
281 _tnl_print_vert_flags("fixup", fixup);
282
283 if (fixup & VERT_TEX_ANY) {
284 GLuint i;
285 for (i = 0 ; i < ctx->Const.MaxTextureUnits ; i++) {
286 if (fixup & VERT_TEX(i)) {
287 if (orflag & VERT_TEX(i))
288 fixup_4f( IM->TexCoord[i], IM->Flag, start, VERT_TEX(i) );
289 else
290 fixup_first_4f( IM->TexCoord[i], IM->Flag, VERT_END_VB, start,
291 IM->TexCoord[i][start]);
292 }
293 }
294 }
295
296
297 if (fixup & VERT_EDGE) {
298 if (orflag & VERT_EDGE)
299 fixup_1ub( IM->EdgeFlag, IM->Flag, start, VERT_EDGE );
300 else
301 fixup_first_1ub( IM->EdgeFlag, IM->Flag, VERT_END_VB, start,
302 IM->EdgeFlag[start] );
303 }
304
305 if (fixup & VERT_INDEX) {
306 if (orflag & VERT_INDEX)
307 fixup_1ui( IM->Index, IM->Flag, start, VERT_INDEX );
308 else
309 fixup_first_1ui( IM->Index, IM->Flag, VERT_END_VB, start,
310 IM->Index[start] );
311 }
312
313 if (fixup & VERT_RGBA) {
314 if (orflag & VERT_RGBA)
315 fixup_4chan( IM->Color, IM->Flag, start, VERT_RGBA );
316 else
317 fixup_first_4chan( IM->Color, IM->Flag, VERT_END_VB, start,
318 IM->Color[start] );
319 }
320
321 if (fixup & VERT_SPEC_RGB) {
322 if (orflag & VERT_SPEC_RGB)
323 fixup_4chan( IM->SecondaryColor, IM->Flag, start, VERT_SPEC_RGB );
324 else
325 fixup_first_4chan( IM->SecondaryColor, IM->Flag, VERT_END_VB, start,
326 IM->SecondaryColor[start] );
327 }
328
329 if (fixup & VERT_FOG_COORD) {
330 if (orflag & VERT_FOG_COORD)
331 fixup_1f( IM->FogCoord, IM->Flag, start, VERT_FOG_COORD );
332 else
333 fixup_first_1f( IM->FogCoord, IM->Flag, VERT_END_VB, start,
334 IM->FogCoord[start] );
335 }
336
337 if (fixup & VERT_NORM) {
338 if (orflag & VERT_NORM)
339 fixup_3f( IM->Normal, IM->Flag, start, VERT_NORM );
340 else
341 fixup_first_3f( IM->Normal, IM->Flag, VERT_END_VB, start,
342 IM->Normal[start] );
343 }
344 }
345
346 /* Prune possible half-filled slot.
347 */
348 IM->Flag[IM->LastData+1] &= ~VERT_END_VB;
349 IM->Flag[IM->Count] |= VERT_END_VB;
350
351
352 /* Materials:
353 */
354 if (IM->MaterialOrMask & ~IM->MaterialAndMask) {
355 GLuint vulnerable = IM->MaterialOrMask;
356 GLuint i = IM->Start;
357
358 do {
359 while (!(IM->Flag[i] & VERT_MATERIAL))
360 i++;
361
362 vulnerable &= ~IM->MaterialMask[i];
363 _mesa_copy_material_pairs( IM->Material[i],
364 ctx->Light.Material,
365 vulnerable );
366
367
368 } while (vulnerable);
369 }
370 }
371
372
373
374
375 static void copy_material( struct immediate *next,
376 struct immediate *prev,
377 GLuint dst, GLuint src )
378 {
379 if (next->Material == 0) {
380 next->Material = (GLmaterial (*)[2]) MALLOC( sizeof(GLmaterial) *
381 IMM_SIZE * 2 );
382 next->MaterialMask = (GLuint *) MALLOC( sizeof(GLuint) * IMM_SIZE );
383 }
384
385 next->MaterialMask[dst] = prev->MaterialOrMask;
386 MEMCPY(next->Material[dst], prev->Material[src], 2*sizeof(GLmaterial));
387 }
388
389
390
391 /* Copy the untransformed data from the shared vertices of a primitive
392 * that wraps over two immediate structs. This is done prior to
393 * set_immediate so that prev and next may point to the same
394 * structure. In general it's difficult to avoid this copy on long
395 * primitives.
396 *
397 * Have to be careful with the transitions between display list
398 * replay, compile and normal execute modes.
399 */
400 static void copy_vertices( GLcontext *ctx,
401 struct immediate *next,
402 struct immediate *prev,
403 GLuint count,
404 GLuint *elts )
405 {
406 TNLcontext *tnl = TNL_CONTEXT(ctx);
407 GLuint offset = IMM_MAX_COPIED_VERTS - count;
408 GLuint i;
409
410 next->CopyStart = next->Start - count;
411
412 /* Copy the vertices
413 */
414 for (i = 0 ; i < count ; i++)
415 {
416 GLuint src = elts[i+offset];
417 GLuint dst = next->CopyStart+i;
418
419 COPY_4FV( next->Obj[dst], prev->Obj[src] );
420 COPY_3FV( next->Normal[dst], prev->Normal[src] );
421 COPY_CHAN4( next->Color[dst], prev->Color[src] );
422
423 if (prev->OrFlag & VERT_TEX_ANY) {
424 GLuint i;
425 for (i = 0 ; i < prev->MaxTextureUnits ; i++) {
426 if (prev->OrFlag & VERT_TEX(i))
427 COPY_4FV( next->TexCoord[i][dst], prev->TexCoord[i][src] );
428 }
429 }
430
431 if (prev->Flag[src] & VERT_MATERIAL)
432 copy_material(next, prev, dst, src);
433
434 next->Elt[dst] = prev->Elt[src];
435 next->EdgeFlag[dst] = prev->EdgeFlag[src];
436 next->Index[dst] = prev->Index[src];
437 COPY_CHAN4( next->SecondaryColor[dst], prev->SecondaryColor[src] );
438 next->FogCoord[dst] = prev->FogCoord[src];
439 next->Flag[dst] = (prev->CopyOrFlag & VERT_FIXUP);
440 next->CopyOrFlag |= prev->Flag[src]; /* redundant for current_im */
441 next->CopyAndFlag &= prev->Flag[src]; /* redundant for current_im */
442 }
443
444
445 ASSERT(prev == tnl->ExecCopySource);
446
447 if (--tnl->ExecCopySource->ref_count == 0)
448 _tnl_free_immediate( tnl->ExecCopySource );
449
450 next->ref_count++;
451 tnl->ExecCopySource = next;
452
453 tnl->ExecCopyElts[0] = next->Start-3;
454 tnl->ExecCopyElts[1] = next->Start-2;
455 tnl->ExecCopyElts[2] = next->Start-1;
456 }
457
458 /* Copy vertices to an empty immediate struct.
459 */
460 void _tnl_copy_immediate_vertices( GLcontext *ctx, struct immediate *IM )
461 {
462 TNLcontext *tnl = TNL_CONTEXT(ctx);
463
464 ASSERT(IM == TNL_CURRENT_IM(ctx));
465 ASSERT(IM->Count == IM->Start);
466
467 /* Need to push this in now as it won't be computed anywhere else/
468 */
469 IM->TexSize = tnl->ExecCopyTexSize;
470
471 /* A wrapped primitive. We may be copying into a revived
472 * display list immediate, or onto the front of a new execute-mode
473 * immediate.
474 */
475 copy_vertices( ctx, IM,
476 tnl->ExecCopySource,
477 tnl->ExecCopyCount,
478 tnl->ExecCopyElts );
479
480 if (ctx->Driver.CurrentExecPrimitive == GL_POLYGON+1) {
481 /* Immediates are built by default to be correct in this state,
482 * and copying to the first slots of an immediate doesn't remove
483 * this property.
484 */
485 ASSERT(tnl->ExecCopyTexSize == 0);
486 ASSERT(tnl->ExecCopyCount == 0);
487 ASSERT(IM->CopyStart == IM->Start);
488 }
489
490 /* Copy the primitive information:
491 */
492 IM->Primitive[IM->CopyStart] = (ctx->Driver.CurrentExecPrimitive | PRIM_LAST);
493 IM->LastPrimitive = IM->CopyStart;
494 if (tnl->ExecParity)
495 IM->Primitive[IM->CopyStart] |= PRIM_PARITY;
496 }
497
498
499 /* Revive a compiled immediate struct - propogate new 'Current'
500 * values. Often this is redundant because the current values were
501 * known and fixed up at compile time.
502 */
503 void _tnl_fixup_compiled_cassette( GLcontext *ctx, struct immediate *IM )
504 {
505 TNLcontext *tnl = TNL_CONTEXT(ctx);
506 GLuint fixup;
507 GLuint count = IM->Count;
508 GLuint start = IM->Start;
509
510 if (count == start)
511 return;
512
513 IM->CopyOrFlag = IM->OrFlag; /* redundant for current_im */
514 IM->CopyAndFlag = IM->AndFlag; /* redundant for current_im */
515 IM->CopyTexSize = IM->TexSize | tnl->ExecCopyTexSize;
516
517 copy_vertices( ctx, IM,
518 tnl->ExecCopySource,
519 tnl->ExecCopyCount,
520 tnl->ExecCopyElts );
521
522 if (ctx->Driver.CurrentExecPrimitive == GL_POLYGON+1) {
523 ASSERT(tnl->ExecCopyTexSize == 0);
524 ASSERT(tnl->ExecCopyCount == 0);
525 ASSERT(IM->CopyStart == IM->Start);
526 }
527
528 fixup = tnl->pipeline.inputs & ~IM->Flag[start] & VERT_FIXUP;
529
530 if (fixup) {
531 if (fixup & VERT_TEX_ANY) {
532 GLuint i;
533 for (i = 0 ; i < ctx->Const.MaxTextureUnits ; i++) {
534 if (fixup & VERT_TEX(i))
535 fixup_first_4f( IM->TexCoord[i], IM->Flag, VERT_TEX(i), start,
536 ctx->Current.Texcoord[i] );
537 }
538 }
539
540 if (fixup & VERT_EDGE)
541 fixup_first_1ub(IM->EdgeFlag, IM->Flag, VERT_EDGE, start,
542 ctx->Current.EdgeFlag );
543
544 if (fixup & VERT_INDEX)
545 fixup_first_1ui(IM->Index, IM->Flag, VERT_INDEX, start,
546 ctx->Current.Index );
547
548 if (fixup & VERT_RGBA)
549 fixup_first_4chan(IM->Color, IM->Flag, VERT_RGBA, start,
550 ctx->Current.Color );
551
552 if (fixup & VERT_SPEC_RGB)
553 fixup_first_4chan(IM->SecondaryColor, IM->Flag, VERT_SPEC_RGB, start,
554 ctx->Current.SecondaryColor );
555
556 if (fixup & VERT_FOG_COORD)
557 fixup_first_1f(IM->FogCoord, IM->Flag, VERT_FOG_COORD, start,
558 ctx->Current.FogCoord );
559
560 if (fixup & VERT_NORM) {
561 fixup_first_3f(IM->Normal, IM->Flag, VERT_NORM, start,
562 ctx->Current.Normal );
563 }
564 }
565
566 /* Materials:
567 */
568 if (IM->MaterialOrMask & ~IM->MaterialAndMask) {
569 GLuint vulnerable = IM->MaterialOrMask;
570 GLuint i = IM->Start;
571
572 do {
573 while (!(IM->Flag[i] & VERT_MATERIAL))
574 i++;
575
576 vulnerable &= ~IM->MaterialMask[i];
577 _mesa_copy_material_pairs( IM->Material[i],
578 ctx->Light.Material,
579 vulnerable );
580
581
582 } while (vulnerable);
583 }
584
585 /* Can potentially overwrite primitive details - need to save the
586 * first slot:
587 */
588 tnl->DlistPrimitive = IM->Primitive[IM->Start];
589 tnl->DlistPrimitiveLength = IM->PrimitiveLength[IM->Start];
590 tnl->DlistLastPrimitive = IM->LastPrimitive;
591
592 /* The first primitive may be different from what was recorded in
593 * the immediate struct. Consider an immediate that starts with a
594 * glBegin, compiled in a display list, which is called from within
595 * an existing Begin/End object.
596 */
597 if (ctx->Driver.CurrentExecPrimitive == GL_POLYGON+1) {
598 GLuint i;
599
600 if (IM->BeginState & VERT_ERROR_1)
601 _mesa_error( ctx, GL_INVALID_OPERATION, "glBegin/glEnd");
602
603 for (i = IM->Start ; i <= IM->Count ; i += IM->PrimitiveLength[i])
604 if (IM->Flag[i] & (VERT_BEGIN|VERT_END_VB))
605 break;
606
607 /* Would like to just ignore vertices upto this point. Can't
608 * set copystart because it might skip materials?
609 */
610 ASSERT(IM->Start == IM->CopyStart);
611 if (i > IM->CopyStart) {
612 IM->Primitive[IM->CopyStart] = GL_POLYGON+1;
613 IM->PrimitiveLength[IM->CopyStart] = i - IM->CopyStart;
614 if (IM->Flag[i] & VERT_END_VB) {
615 IM->Primitive[IM->CopyStart] |= PRIM_LAST;
616 IM->LastPrimitive = IM->CopyStart;
617 }
618 }
619 /* Shouldn't immediates be set up to have this structure *by default*?
620 */
621 } else {
622 GLuint i;
623
624 if (IM->BeginState & VERT_ERROR_0)
625 _mesa_error( ctx, GL_INVALID_OPERATION, "glBegin/glEnd");
626
627 if (IM->CopyStart == IM->Start &&
628 IM->Flag[IM->Start] & (VERT_END|VERT_END_VB))
629 {
630 }
631 else
632 {
633 IM->Primitive[IM->CopyStart] = ctx->Driver.CurrentExecPrimitive;
634 if (tnl->ExecParity)
635 IM->Primitive[IM->CopyStart] |= PRIM_PARITY;
636
637
638 for (i = IM->Start ; i <= IM->Count ; i += IM->PrimitiveLength[i])
639 if (IM->Flag[i] & (VERT_END|VERT_END_VB)) {
640 IM->PrimitiveLength[IM->CopyStart] = i - IM->CopyStart;
641 if (IM->Flag[i] & VERT_END_VB) {
642 IM->Primitive[IM->CopyStart] |= PRIM_LAST;
643 IM->LastPrimitive = IM->CopyStart;
644 }
645 if (IM->Flag[i] & VERT_END) {
646 IM->Primitive[IM->CopyStart] |= PRIM_END;
647 }
648 break;
649 }
650 }
651 }
652
653 if (IM->Primitive[IM->LastPrimitive] & PRIM_END)
654 ctx->Driver.CurrentExecPrimitive = GL_POLYGON+1;
655 else
656 ctx->Driver.CurrentExecPrimitive =
657 IM->Primitive[IM->LastPrimitive] & PRIM_MODE_MASK;
658 }
659
660
661 /* Undo any changes potentially made to the immediate in the range
662 * IM->Start..IM->Count above.
663 */
664 void _tnl_restore_compiled_cassette( GLcontext *ctx, struct immediate *IM )
665 {
666 TNLcontext *tnl = TNL_CONTEXT(ctx);
667 IM->Primitive[IM->Start] = tnl->DlistPrimitive;
668 IM->PrimitiveLength[IM->Start] = tnl->DlistPrimitiveLength;
669 }
670
671
672
673
674
675
676 static void copy_none( TNLcontext *tnl, GLuint start, GLuint count, GLuint ovf)
677 {
678 (void) (start && ovf && tnl && count);
679 }
680
681 static void copy_last( TNLcontext *tnl, GLuint start, GLuint count, GLuint ovf)
682 {
683 (void) start; (void) ovf;
684 tnl->ExecCopyCount = 1;
685 tnl->ExecCopyElts[2] = count-1;
686 }
687
688 static void copy_first_and_last( TNLcontext *tnl, GLuint start, GLuint count,
689 GLuint ovf)
690 {
691 (void) ovf;
692 tnl->ExecCopyCount = 2;
693 tnl->ExecCopyElts[1] = start;
694 tnl->ExecCopyElts[2] = count-1;
695 }
696
697 static void copy_last_two( TNLcontext *tnl, GLuint start, GLuint count,
698 GLuint ovf )
699 {
700 (void) start;
701 tnl->ExecCopyCount = 2+ovf;
702 tnl->ExecCopyElts[0] = count-3;
703 tnl->ExecCopyElts[1] = count-2;
704 tnl->ExecCopyElts[2] = count-1;
705 }
706
707 static void copy_overflow( TNLcontext *tnl, GLuint start, GLuint count,
708 GLuint ovf )
709 {
710 (void) start;
711 tnl->ExecCopyCount = ovf;
712 tnl->ExecCopyElts[0] = count-3;
713 tnl->ExecCopyElts[1] = count-2;
714 tnl->ExecCopyElts[2] = count-1;
715 }
716
717
718 typedef void (*copy_func)( TNLcontext *tnl, GLuint start, GLuint count,
719 GLuint ovf );
720
721 static copy_func copy_tab[GL_POLYGON+2] =
722 {
723 copy_none,
724 copy_overflow,
725 copy_first_and_last,
726 copy_last,
727 copy_overflow,
728 copy_last_two,
729 copy_first_and_last,
730 copy_overflow,
731 copy_last_two,
732 copy_first_and_last,
733 copy_none
734 };
735
736
737
738
739
740 /* Figure out what vertices need to be copied next time.
741 */
742 void
743 _tnl_get_exec_copy_verts( GLcontext *ctx, struct immediate *IM )
744 {
745 static const GLuint increment[GL_POLYGON+2] = { 1,2,1,1,3,1,1,4,2,1,1 };
746 static const GLuint intro[GL_POLYGON+2] = { 0,0,2,2,0,2,2,0,2,2,0 };
747
748 TNLcontext *tnl = TNL_CONTEXT(ctx);
749 GLuint last = IM->LastPrimitive;
750 GLuint prim = ctx->Driver.CurrentExecPrimitive;
751 GLuint pincr = increment[prim];
752 GLuint pintro = intro[prim];
753 GLuint ovf = 0;
754
755
756 if (tnl->ExecCopySource != IM) {
757 if (--tnl->ExecCopySource->ref_count == 0)
758 _tnl_free_immediate( tnl->ExecCopySource );
759 IM->ref_count++;
760 tnl->ExecCopySource = IM;
761 }
762
763 if (prim == GL_POLYGON+1) {
764 tnl->ExecCopyCount = 0;
765 tnl->ExecCopyTexSize = 0;
766 tnl->ExecParity = 0;
767 } else {
768 tnl->ExecCopyCount = 0;
769 tnl->ExecCopyTexSize = IM->CopyTexSize;
770 tnl->ExecParity = IM->PrimitiveLength[IM->LastPrimitive] & 1;
771
772 if (pincr != 1 && (IM->Count - last - pintro))
773 ovf = (IM->Count - last - pintro) % pincr;
774
775 if (last < IM->Count)
776 copy_tab[prim]( tnl, last, IM->Count, ovf );
777 }
778 }
779
780
781 /* If we receive evalcoords in an immediate struct for maps which
782 * don't have a vertex enabled, need to do an additional fixup, as
783 * those rows containing evalcoords must now be ignored. The
784 * evalcoords may still generate colors, normals, etc, so have to
785 * respect the relative order between calls to EvalCoord and Normal
786 * etc.
787 *
788 * Generate the index list that will be used to render this immediate
789 * struct.
790 *
791 * Finally, generate a new primitives list for rendering the indices.
792 */
793 #if 0
794 void _tnl_fixup_purged_eval( GLcontext *ctx,
795 GLuint fixup, GLuint purge )
796 {
797 TNLcontext *tnl = TNL_CONTEXT(ctx);
798 struct tnl_eval_store *store = &tnl->eval;
799 GLuint *flags = tnl->vb.Flag;
800 GLuint i, j, nextprim;
801 GLuint fixup_fence = purge|VERT_OBJ;
802 GLuint good_index = (VERT_EVAL_ANY & ~purge)|VERT_OBJ;
803 GLuint prim_length = 0, lastprim = 0, nextprim = 0;
804
805 if (fixup & VERT_TEX0)
806 fixup_4f( store->TexCoord, flags, 0, VERT_TEX0|fixup_fence );
807
808 if (fixup & VERT_INDEX)
809 fixup_1ui( store->Index, flags, 0, VERT_INDEX|fixup_fence );
810
811 if (fixup & VERT_RGBA)
812 fixup_4chan( store->Color, flags, 0, VERT_RGBA|fixup_fence );
813
814 if (fixup & VERT_NORM)
815 fixup_3f( store->Normal, flags, 0, VERT_NORM|fixup_fence );
816
817 for (i = 0, j = 0 ; i < tnl->vb.Count ; i++) {
818 if (flags[i] & good_index) {
819 store->Elts[j++] = i;
820 prim_length++;
821 }
822 if (i == nextprim) {
823 VB->PrimitiveLength[lastprim] = prim_length;
824 VB->Primitive[j] = VB->Primitive[i];
825 nextprim += lastprimlen;
826 lastprim = i;
827 lastprimlen = VB->PrimitiveLength[i];
828 }
829 }
830
831 VB->Elts = store->Elts;
832
833 /* What about copying??? No immediate exists with the right
834 * vertices in place...
835 */
836 if (tnl->CurrentPrimitive != GL_POLYGON+1) {
837 }
838 }
839 #endif