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