source: branches/swt/src/opengl/mesa/vbxform.c

Last change on this file was 3598, checked in by jeroen, 26 years ago

* empty log message *

File size: 29.7 KB
Line 
1/* $Id: vbxform.c,v 1.3 2000-05-23 20:41:03 jeroen Exp $ */
2
3/*
4 * Mesa 3-D graphics library
5 * Version: 3.1
6 *
7 * Copyright (C) 1999 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
29#ifdef PC_HEADER
30#include "all.h"
31#else
32#include "glheader.h"
33#include "types.h"
34#include "context.h"
35#include "cva.h"
36#include "clip.h"
37#include "eval.h"
38#include "enums.h"
39#include "dlist.h"
40#include "fog.h"
41#include "light.h"
42#include "macros.h"
43#include "matrix.h"
44#include "mmath.h"
45#include "pipeline.h"
46#include "shade.h"
47#include "texture.h"
48#include "varray.h"
49#include "vb.h"
50#include "vbcull.h"
51#include "vbfill.h"
52#include "vbrender.h"
53#include "vbxform.h"
54#include "xform.h"
55#include "mem.h"
56#include "state.h"
57#endif
58
59
60void gl_maybe_transform_vb( struct immediate *IM )
61{
62 GLcontext *ctx = IM->backref;
63
64 if (ctx->NewState)
65 gl_update_state(ctx);
66
67 if (IM->FlushElt) {
68 gl_exec_array_elements( ctx, IM, IM->LastPrimitive, IM->Count );
69 IM->FlushElt = 0;
70 }
71
72 gl_compute_orflag( IM );
73
74 if (ctx->ExecuteFlag)
75 gl_cva_compile_cassette( ctx, IM );
76 else
77 gl_fixup_input( ctx, IM );
78
79 if (ctx->CompileFlag)
80 gl_compile_cassette( ctx );
81 else
82 gl_reset_input( ctx );
83}
84
85
86void gl_flush_vb( GLcontext *ctx, const char *where )
87{
88 struct immediate *IM = ctx->input;
89
90 if (MESA_VERBOSE&VERBOSE_PIPELINE)
91 fprintf(stderr, "gl_flush_vb: %s\n", where);
92
93 gl_maybe_transform_vb( IM );
94}
95
96/* Drivers can call this inside their swapbuffers routines:
97 */
98void gl_internal_flush( GLcontext *ctx )
99{
100 FLUSH_VB( ctx, "internal flush" );
101}
102
103
104#define RESET_VEC(v, t, s, c) (v.start = t v.data[s], v.count = c)
105
106/*
107 *
108 */
109void gl_reset_vb( struct vertex_buffer *VB )
110{
111 GLuint copy;
112 GLuint dst;
113 GLuint start;
114 struct immediate *IM = VB->IM;
115 GLubyte clipor = VB->ClipOrMask;
116
117 if (!VB->CullDone)
118 gl_fast_copy_vb( VB );
119
120 copy = VB->CopyCount;
121 start = 3-copy;
122
123 VB->CopyStart = start;
124 VB->ClipOrMask = 0;
125 VB->ClipAndMask = CLIP_ALL_BITS;
126
127 if (IM)
128 {
129 if (VB->Count != IM->Count && 0) {
130 fprintf(stderr, "Trying to copy vertices in the middle of an IM (%d/%d)!!\n",
131 VB->Count, IM->Count);
132 }
133 else if (VB->pipeline->copy_transformed_data) {
134
135 for (dst = start ; dst < VB_START ; dst++)
136 {
137 GLuint src = VB->Copy[dst];
138
139 if (MESA_VERBOSE&VERBOSE_IMMEDIATE)
140 fprintf(stderr, "copying vertex %u to %u\n", src, dst);
141
142 COPY_4FV( VB->Clip.data[dst], VEC_ELT(VB->ClipPtr, GLfloat, src) );
143 COPY_4FV( VB->Win.data[dst], VB->Win.data[src] );
144
145 VB->UserClipMask[dst] = VB->UserClipMask[src];
146 VB->ClipMask[dst] = (GLubyte) (VB->ClipMask[src] & ~CLIP_CULLED_BIT);
147 VB->ClipAndMask &= VB->ClipMask[dst];
148 VB->ClipOrMask |= VB->ClipMask[dst];
149 VB->ClipMask[src] = 0; /* hack for bounds_cull_vb */
150
151 COPY_4UBV( IM->Color[dst], IM->Color[src] );
152 COPY_4UBV( VB->Spec[0][dst], VB->Spec[0][src] );
153 COPY_4UBV( VB->Spec[1][dst], VB->Spec[1][src] );
154 COPY_4UBV( VB->BColor.data[dst], VB->BColor.data[src] );
155 IM->Index[dst] = IM->Index[src];
156 VB->BIndex.data[dst] = VB->BIndex.data[src];
157
158 if (VB->TexCoordPtr[0] == &IM->v.TexCoord[0])
159 COPY_4FV( IM->TexCoord[0][dst], IM->TexCoord[0][src] );
160
161 if (VB->TexCoordPtr[1] == &IM->v.TexCoord[1])
162 COPY_4FV( IM->TexCoord[1][dst], IM->TexCoord[1][src] );
163
164 IM->Elt[dst] = IM->Elt[src];
165 VB->SavedOrFlag |= IM->Flag[src];
166 }
167 }
168
169 VB->CullDone = 0;
170 }
171
172 if (clipor & CLIP_USER_BIT)
173 MEMSET(VB->UserClipMask + VB->Start, 0, VB->Count);
174
175 VB->NormCullStart = 0;
176 VB->Parity = (VB->LastPrimitive^VB->Count)&1;
177 VB->PurgeFlags = 0;
178 VB->EarlyCull = 1;
179 VB->Culled = 0;
180 VB->BoundsPtr = 0;
181 VB->NormalLengthPtr = 0;
182 VB->Indirect = 0;
183 VB->Culled = 0;
184}
185
186
187
188
189/* Copy the untransformed parts of the overlapping vertices from one
190 * immediate struct to another (or possibly the same one).
191 *
192 * Only copy those elements which are genuinely untransformed. Others
193 * are done in gl_reset_vb.
194 */
195void gl_copy_prev_vertices( struct vertex_buffer *VB,
196 struct immediate *prev,
197 struct immediate *next )
198{
199 GLuint dst;
200 GLuint flags = VB->pipeline->inputs;
201
202 if (MESA_VERBOSE&VERBOSE_CULL)
203 fprintf(stderr, "copy prev vertices im: prev %d next %d copystart %d\n",
204 prev->id, next->id, VB->CopyStart);
205
206 /* VB_START is correct as vertex copying is only required when an
207 * IM wraps, which means that the next VB must start at VB_START.
208 */
209 for (dst = VB->CopyStart ; dst < VB_START ; dst++)
210 {
211 GLuint src = VB->Copy[dst];
212
213 if (MESA_VERBOSE&VERBOSE_CULL)
214 fprintf(stderr, "copy_prev: copy %d to %d\n", src, dst );
215
216 COPY_4FV( next->Obj[dst], prev->Obj[src] );
217
218 if ((flags&VERT_TEX0_ANY) && VB->TexCoordPtr[0] == &prev->v.TexCoord[0])
219 COPY_4FV( next->TexCoord[0][dst], prev->TexCoord[0][src] );
220
221 if ((flags&VERT_TEX1_ANY) && VB->TexCoordPtr[1] == &prev->v.TexCoord[1])
222 COPY_4FV( next->TexCoord[1][dst], prev->TexCoord[1][src] );
223
224 COPY_4UBV( next->Color[dst], prev->Color[src] );
225 next->Index[dst] = prev->Index[src];
226 next->EdgeFlag[dst] = prev->EdgeFlag[src];
227
228 next->Elt[dst] = prev->Elt[src];
229 VB->SavedOrFlag |= prev->Flag[src];
230 }
231}
232
233
234
235void RESET_IMMEDIATE( GLcontext *ctx )
236{
237 if (ctx->VB->prev_buffer != ctx->VB->IM) {
238 /* Should only get here if we are trying to use the internal
239 * interfaces, eg gl_Vertex3f(), gl_Begin() from inside a
240 * display list. In this case, it is necessary to pull the
241 * current values into the ctx->VB.store buffer, because this
242 * may not have been done.
243 */
244 FLUSH_VB( ctx, "RESET_IMMEDIATE" );
245 gl_reset_input( ctx );
246 }
247}
248
249
250/* Called to initialize new buffers, and to recycle old ones.
251 */
252void gl_reset_input( GLcontext *ctx )
253{
254 struct immediate *IM = ctx->input;
255
256 MEMSET(IM->Flag, 0, sizeof(GLuint) * (IM->Count+2));
257 IM->Start = VB_START;
258 IM->Count = VB_START;
259
260 IM->Primitive[IM->Start] = ctx->Current.Primitive;
261 IM->LastPrimitive = IM->Start;
262 IM->BeginState = VERT_BEGIN_0;
263 IM->OrFlag = 0;
264 IM->AndFlag = ~0U;
265
266 if (0)
267 fprintf(stderr,
268 "in reset_input(IM %d), BeginState is %x, setting prim[%d] to %s\n",
269 IM->id,
270 VERT_BEGIN_0,
271 IM->Start, gl_lookup_enum_by_nr(ctx->Current.Primitive));
272
273 IM->ArrayAndFlags = ~ctx->Array.Flags;
274 IM->ArrayIncr = ctx->Array.Vertex.Enabled;
275 IM->ArrayEltFlush = !(ctx->CompileCVAFlag);
276}
277
278
279/* Preserves size information as well.
280 */
281static void
282fixup_4f( GLfloat data[][4], GLuint flag[], GLuint start, GLuint match )
283{
284 GLuint i = start;
285
286 for (;;) {
287 if ((flag[++i] & match) == 0) {
288 COPY_4FV(data[i], data[i-1]);
289 flag[i] |= (flag[i-1] & match);
290 if (flag[i] & VERT_END_VB) break;
291 }
292 }
293}
294
295
296
297/* Only needed for buffers with eval coords.
298 */
299static void
300fixup_3f( float data[][3], GLuint flag[], GLuint start, GLuint match )
301{
302 GLuint i = start;
303
304 for (;;) {
305 if ((flag[++i] & match) == 0) {
306 COPY_3V(data[i], data[i-1]);
307 flag[i] |= match;
308 if (flag[i] & VERT_END_VB) break;
309 }
310 }
311}
312
313
314static void
315fixup_1ui( GLuint *data, GLuint flag[], GLuint start, GLuint match )
316{
317 GLuint i = start;
318
319 for (;;) {
320 if ((flag[++i] & match) == 0) {
321 data[i] = data[i-1];
322 if (flag[i] & VERT_END_VB) break;
323 }
324 }
325 flag[i] |= match;
326}
327
328static void
329fixup_1ub( GLubyte *data, GLuint flag[], GLuint start, GLuint match )
330{
331 GLuint i = start;
332
333 for (;;) {
334 if ((flag[++i] & match) == 0) {
335 data[i] = data[i-1];
336 if (flag[i] & VERT_END_VB) break;
337 }
338 }
339 flag[i] |= match;
340}
341
342
343static void
344fixup_4ub( GLubyte data[][4], GLuint flag[], GLuint start, GLuint match )
345{
346 GLuint i = start;
347
348 for (;;) {
349 if ((flag[++i] & match) == 0) {
350 COPY_4UBV(data[i], data[i-1]);
351 if (flag[i] & VERT_END_VB) break;
352 }
353 }
354 flag[i] |= match;
355}
356
357
358/* Do this instead of fixup for shared normals.
359 */
360static void
361find_last_3f( float data[][3], GLuint flag[], GLuint match, GLuint count )
362{
363 int i = count;
364
365 do {
366 if ((flag[--i] & match) != 0) {
367 COPY_3V(data[count], data[i]);
368 return;
369 }
370 } while (i >= 0);
371
372 /* To reach this point excercises a bug that seems only to exist on
373 * dec alpha installations. I want to leave this print statement
374 * enabled on the 3.3 branch so that we are reminded to track down
375 * the problem.
376 */
377 fprintf(stderr,
378 "didn't find VERT_NORM in find_last_3f"
379 "(Dec alpha problem?)\n");
380}
381
382static void
383fixup_first_4v( GLfloat data[][4], GLuint flag[], GLuint match,
384 GLuint start, GLfloat *dflt )
385{
386 GLuint i = start-1;
387 match |= VERT_END_VB;
388
389 while ((flag[++i]&match) == 0)
390 COPY_4FV(data[i], dflt);
391}
392
393
394static void
395fixup_first_1ui( GLuint data[], GLuint flag[], GLuint match,
396 GLuint start, GLuint dflt )
397{
398 GLuint i = start-1;
399 match |= VERT_END_VB;
400
401 while ((flag[++i]&match) == 0)
402 data[i] = dflt;
403}
404
405
406static void
407fixup_first_1ub( GLubyte data[], GLuint flag[], GLuint match,
408 GLuint start, GLubyte dflt )
409{
410 GLuint i = start-1;
411 match |= VERT_END_VB;
412
413 while ((flag[++i]&match) == 0)
414 data[i] = dflt;
415}
416
417
418static void
419fixup_first_4ub( GLubyte data[][4], GLuint flag[], GLuint match,
420 GLuint start, GLubyte dflt[4] )
421{
422 GLuint i = start-1;
423 match |= VERT_END_VB;
424
425 while ((flag[++i]&match) == 0)
426 COPY_4UBV(data[i], dflt);
427}
428
429
430
431
432static GLuint vertex_sizes[16] = { 0,
433 1,
434 2, 2,
435 3, 3, 3, 3,
436 4, 4, 4, 4, 4, 4, 4, 4 };
437
438
439
440GLuint gl_texcoord_size( GLuint flag, GLuint unit )
441{
442 flag >>= VERT_TEX0_SHIFT + unit * NR_TEXSIZE_BITS;
443 return vertex_sizes[flag & 0xf];
444}
445
446
447static void set_vec_sizes( struct immediate *IM, GLuint orflag )
448{
449 GLuint i;
450
451 if (orflag & VERT_OBJ_ANY) {
452 GLuint szflag = orflag & VERT_OBJ_234;
453 IM->v.Obj.size = vertex_sizes[szflag<<1];
454 }
455
456 for (i = 0 ; i < MAX_TEXTURE_UNITS ; i++) {
457 if (orflag & VERT_TEX_ANY(i)) {
458 GLuint szflag = ((orflag>>(VERT_TEX0_SHIFT+i*NR_TEXSIZE_BITS))
459 & 0xf);
460 IM->v.TexCoord[i].size = vertex_sizes[szflag];
461 }
462 }
463}
464
465
466void gl_compute_orflag( struct immediate *IM )
467{
468 GLuint count = IM->Count;
469 GLuint orflag = 0;
470 GLuint andflag = ~0U;
471 GLuint i;
472
473 IM->LastData = count-1;
474
475/* fprintf(stderr, "In gl_compute_orflag, start %d count %d\n", IM->Start, IM->Count); */
476/* gl_print_vert_flags("initial andflag", andflag); */
477
478 /* Compute the flags for the whole buffer, even if
479 */
480 for (i = IM->Start ; i < count ; i++) {
481 andflag &= IM->Flag[i];
482 orflag |= IM->Flag[i];
483 }
484
485 if (IM->Flag[i] & VERT_DATA) {
486 IM->LastData++;
487/* andflag &= IM->Flag[i]; */
488 orflag |= IM->Flag[i];
489 }
490
491/* gl_print_vert_flags("final andflag", andflag); */
492
493 IM->Flag[IM->LastData+1] |= VERT_END_VB;
494 IM->AndFlag = andflag;
495 IM->OrFlag = orflag;
496}
497
498void gl_fixup_input( GLcontext *ctx, struct immediate *IM )
499{
500 GLuint count = IM->Count;
501 GLuint start = IM->Start;
502 GLuint fixup, diff;
503 GLuint andflag = IM->AndFlag;
504 GLuint orflag = IM->OrFlag;
505
506 IM->Primitive[count] = IM->Primitive[IM->LastPrimitive];
507 IM->NextPrimitive[IM->LastPrimitive] = count;
508 IM->NextPrimitive[count] = count+1;
509
510 if (MESA_VERBOSE&VERBOSE_IMMEDIATE)
511 {
512 fprintf(stderr, "Start: %u Count: %u LastData: %u\n",
513 IM->Start, IM->Count, IM->LastData);
514 gl_print_vert_flags("Orflag", orflag);
515 gl_print_vert_flags("Andflag", andflag);
516 }
517
518 /* Array elements modify the current state - must do this before
519 * fixup.
520 */
521 if (ctx->CompileCVAFlag && !(andflag & VERT_ELT))
522 gl_rescue_cva( ctx, IM );
523
524 if (orflag & VERT_ELT)
525 {
526 orflag = IM->OrFlag;
527 andflag = IM->AndFlag;
528 start = IM->Start;
529 }
530
531 fixup = ~andflag & VERT_FIXUP;
532
533 if (!ctx->CompileFlag)
534 fixup &= ctx->CVA.elt.inputs;
535
536 if (!ctx->ExecuteFlag)
537 fixup &= orflag;
538
539 if (ctx->CompileCVAFlag)
540 fixup &= ~ctx->CVA.pre.outputs;
541
542 if ((orflag & (VERT_OBJ_ANY|VERT_EVAL_ANY)) == 0)
543 fixup = 0;
544
545 if (fixup)
546 {
547
548 if (ctx->ExecuteFlag && (fixup & ~IM->Flag[start])) {
549 GLuint copy = fixup & ~IM->Flag[start];
550
551 if (copy & VERT_NORM)
552 COPY_3V( IM->Normal[start], ctx->Current.Normal );
553
554 if (copy & VERT_RGBA)
555 COPY_4UBV( IM->Color[start], ctx->Current.ByteColor);
556
557 if (copy & VERT_INDEX)
558 IM->Index[start] = ctx->Current.Index;
559
560 if (copy & VERT_EDGE)
561 IM->EdgeFlag[start] = ctx->Current.EdgeFlag;
562
563 if (copy & VERT_TEX0_ANY)
564 COPY_4FV( IM->TexCoord[0][start], ctx->Current.Texcoord[0] );
565
566 if (copy & VERT_TEX1_ANY)
567 COPY_4FV( IM->TexCoord[1][start], ctx->Current.Texcoord[1] );
568 }
569
570
571 if (MESA_VERBOSE&VERBOSE_IMMEDIATE)
572 gl_print_vert_flags("fixup", fixup);
573
574 if (fixup & VERT_TEX0_ANY) {
575 if (orflag & VERT_TEX0_ANY)
576 fixup_4f( IM->TexCoord[0], IM->Flag, start, VERT_TEX0_1234 );
577 else
578 fixup_first_4v( IM->TexCoord[0], IM->Flag, 0, start,
579 IM->TexCoord[0][start]);
580 }
581
582 if (fixup & VERT_TEX1_ANY) {
583 if (orflag & VERT_TEX1_ANY)
584 fixup_4f( IM->TexCoord[1], IM->Flag, start, VERT_TEX1_1234 );
585 else
586 fixup_first_4v( IM->TexCoord[1], IM->Flag, 0, start,
587 IM->TexCoord[1][start] );
588 }
589
590 if (fixup & VERT_EDGE) {
591 if (orflag & VERT_EDGE)
592 fixup_1ub( IM->EdgeFlag, IM->Flag, start, VERT_EDGE );
593 else
594 fixup_first_1ub( IM->EdgeFlag, IM->Flag, 0, start,
595 IM->EdgeFlag[start] );
596 }
597
598 if (fixup & VERT_INDEX) {
599 if (orflag & VERT_INDEX)
600 fixup_1ui( IM->Index, IM->Flag, start, VERT_INDEX );
601 else
602 fixup_first_1ui( IM->Index, IM->Flag, 0, start, IM->Index[start] );
603 }
604
605 if (fixup & VERT_RGBA) {
606 if (orflag & VERT_RGBA)
607 fixup_4ub( IM->Color, IM->Flag, start, VERT_RGBA );
608 else
609 fixup_first_4ub( IM->Color, IM->Flag, 0, start, IM->Color[start] );
610 }
611
612 if (fixup & VERT_NORM) {
613 /* Only eval cannot use the Flag member to find valid normals:
614 */
615 if (IM->OrFlag & VERT_EVAL_ANY)
616 fixup_3f( IM->Normal, IM->Flag, start, VERT_NORM );
617 else {
618 /* Copy-to-current requires a valid normal in the last slot:
619 */
620 if ((IM->OrFlag & VERT_NORM) &&
621 !(IM->Flag[IM->LastData] & VERT_NORM))
622 find_last_3f( IM->Normal, IM->Flag, VERT_NORM, IM->LastData );
623 }
624 }
625 }
626
627 diff = count - start;
628 IM->v.Obj.count = diff;
629 IM->v.Normal.count = diff;
630 IM->v.TexCoord[0].count = diff;
631 IM->v.TexCoord[1].count = diff;
632 IM->v.EdgeFlag.count = diff;
633 IM->v.Color.count = diff;
634 IM->v.Index.count = diff;
635
636 /* Prune possible half-filled slot.
637 */
638 IM->Flag[IM->LastData+1] &= ~VERT_END_VB;
639 IM->Flag[IM->Count] |= VERT_END_VB;
640}
641
642
643static void calc_normal_lengths( GLfloat *dest,
644 CONST GLfloat (*data)[3],
645 const GLuint *flags,
646 GLuint count )
647{
648 GLuint i;
649
650 for (i = 0 ; i < count ; i++ )
651 if (flags[i] & VERT_NORM) {
652 GLfloat tmp = (GLfloat) LEN_3FV( data[i] );
653 dest[i] = 0;
654 if (tmp > 0)
655 dest[i] = 1.0F / tmp;
656 }
657}
658
659
660/* Revive a compiled immediate struct - propogate new 'Current'
661 * values. Often this is redundant because the current values were
662 * known and fixed up at compile time.
663 */
664void gl_fixup_cassette( GLcontext *ctx, struct immediate *IM )
665{
666 GLuint fixup;
667 GLuint count = IM->Count;
668 GLuint start = IM->Start;
669
670 if (count == start)
671 return;
672
673 if (ctx->NewState)
674 gl_update_state( ctx );
675
676
677 if (ctx->Transform.Normalize && IM->LastCalcedLength < IM->Count) {
678 GLuint start = IM->LastCalcedLength;
679
680 if (!IM->NormalLengths)
681 IM->NormalLengths = (GLfloat *)MALLOC(sizeof(GLfloat) * VB_SIZE);
682
683 calc_normal_lengths( IM->NormalLengths + start,
684 (const GLfloat (*)[3])(IM->Normal + start),
685 IM->Flag + start,
686 IM->Count - start);
687
688 IM->LastCalcedLength = IM->Count;
689 }
690
691 fixup = ctx->CVA.elt.inputs & ~IM->AndFlag & VERT_FIXUP;
692
693 if (fixup) {
694
695 if (MESA_VERBOSE & VERBOSE_IMMEDIATE) {
696 fprintf(stderr, "start: %d count: %d\n", start, count);
697 gl_print_vert_flags("fixup_cassette", fixup);
698 }
699
700 if (fixup & VERT_TEX0_ANY)
701 fixup_first_4v( IM->TexCoord[0], IM->Flag, VERT_TEX0_ANY, start,
702 ctx->Current.Texcoord[0] );
703
704 if (fixup & VERT_TEX1_ANY)
705 fixup_first_4v( IM->TexCoord[1], IM->Flag, VERT_TEX1_ANY, start,
706 ctx->Current.Texcoord[1] );
707
708 if (fixup & VERT_EDGE)
709 fixup_first_1ub(IM->EdgeFlag, IM->Flag, VERT_EDGE, start,
710 ctx->Current.EdgeFlag );
711
712 if (fixup & VERT_INDEX)
713 fixup_first_1ui(IM->Index, IM->Flag, VERT_INDEX, start,
714 ctx->Current.Index );
715
716 if (fixup & VERT_RGBA)
717 fixup_first_4ub(IM->Color, IM->Flag, VERT_RGBA, start,
718 ctx->Current.ByteColor );
719
720 if ((fixup & VERT_NORM) && !(IM->Flag[start] & VERT_NORM)) {
721 COPY_3V(IM->Normal[start], ctx->Current.Normal);
722 if (ctx->Transform.Normalize)
723 IM->NormalLengths[start] = 1.0F / (GLfloat) LEN_3FV(ctx->Current.Normal);
724 }
725 }
726}
727
728
729
730static void fixup_primitives( struct vertex_buffer *VB, struct immediate *IM )
731{
732 static GLuint increment[GL_POLYGON+2] = { 1,2,1,1,3,1,1,4,2,1,1 };
733 static GLuint intro[GL_POLYGON+2] = { 0,0,2,2,0,2,2,0,2,2,0 };
734 GLcontext *ctx = VB->ctx;
735 const GLuint *flags = IM->Flag;
736 const GLuint *in_prim = IM->Primitive;
737 const GLuint *in_nextprim = IM->NextPrimitive;
738 GLuint *out_prim = VB->IM->Primitive;
739 GLuint *out_nextprim = VB->IM->NextPrimitive;
740 GLuint count = VB->Count;
741 GLuint start = VB->Start;
742 GLuint in, out, last;
743 GLuint incr, prim;
744 GLuint transition;
745 GLuint interesting;
746 GLuint err;
747
748/* printf("IM: %d VB->Count %d VB->Start %d current prim: %d\n", IM->id, VB->Count, VB->Start, ctx->Current.Primitive); */
749
750 if (ctx->Current.Primitive == GL_POLYGON+1) {
751 transition = VERT_BEGIN;
752 err = IM->BeginState & VERT_ERROR_1;
753 } else {
754 transition = VERT_END;
755 err = IM->BeginState & VERT_ERROR_0;
756 }
757
758 if (err) {
759 /* Occurred somewhere inside the vb. Don't know/care where/why.
760 */
761 gl_error( ctx, GL_INVALID_OPERATION, "begin/end");
762 }
763
764 interesting = transition | VERT_END_VB;
765
766
767 for (in = start ; in <= count ; in = in_nextprim[in])
768 if (flags[in] & interesting)
769 break;
770
771 out = VB->CopyStart;
772
773 if (in == out) {
774 out_nextprim[out] = in_nextprim[in];
775 out_prim[out] = in_prim[in];
776 last = IM->LastPrimitive;
777 } else if (flags[in] & transition) {
778 out_nextprim[out] = in;
779 out_prim[out] = ctx->Current.Primitive;
780 out = in;
781 last = IM->LastPrimitive;
782 } else {
783 out_nextprim[out] = in;
784 out_prim[out] = ctx->Current.Primitive;
785 in++;
786 last = out;
787 }
788
789 for ( ; in <= count ; in = in_nextprim[in] ) {
790 out_prim[in] = in_prim[in];
791 out_nextprim[in] = in_nextprim[in];
792 }
793
794
795 VB->Primitive = out_prim;
796 VB->NextPrimitive = out_nextprim;
797 VB->LastPrimitive = last;
798 prim = ctx->Current.Primitive = (GLenum) out_prim[last];
799
800
801 /* Calculate whether the primitive finished on a 'good number' of
802 * vertices, or whether there are overflowing vertices we have to
803 * copy to the next buffer (in addition to the normal ones required
804 * by a continuing primitive).
805 *
806 * Note that GL_POLYGON+1, ie outside begin/end, has increment 1.
807 */
808
809 incr = increment[prim];
810
811 if (incr != 1 && (count - last - intro[prim]))
812 VB->Ovf = (count - last - intro[prim]) % incr;
813 else
814 VB->Ovf = 0;
815
816 if (0)
817 fprintf(stderr, "prim: %s count %u last %u incr %u ovf: %u\n",
818 gl_prim_name[prim], count, last, incr, VB->Ovf);
819}
820
821
822void gl_copy_to_current( GLcontext *ctx, struct immediate *IM )
823{
824 GLuint count = IM->LastData;
825 GLuint flag = IM->OrFlag;
826 GLuint mask = 0;
827
828 if (MESA_VERBOSE&VERBOSE_IMMEDIATE)
829 gl_print_vert_flags("copy to current", flag);
830
831 if (flag & VERT_NORM)
832 COPY_3FV( ctx->Current.Normal, IM->Normal[count]);
833
834 if (flag & VERT_INDEX)
835 ctx->Current.Index = IM->Index[count];
836
837 if (flag & VERT_EDGE)
838 ctx->Current.EdgeFlag = IM->EdgeFlag[count];
839
840 if (flag & VERT_RGBA)
841 COPY_4UBV(ctx->Current.ByteColor, IM->Color[count]);
842
843 if (flag & VERT_TEX0_ANY) {
844 mask |= VERT_TEX0_1234;
845 COPY_4FV( ctx->Current.Texcoord[0], IM->TexCoord[0][count]);
846 }
847
848 if (flag & VERT_TEX1_ANY) {
849 mask |= VERT_TEX1_1234;
850 COPY_4FV( ctx->Current.Texcoord[1], IM->TexCoord[1][count]);
851 }
852
853 /* Save the texcoord size information as well.
854 */
855 ctx->Current.Flag &= ~mask;
856 ctx->Current.Flag |= IM->Flag[count] & mask;
857}
858
859
860void gl_execute_cassette( GLcontext *ctx, struct immediate *IM )
861{
862 struct vertex_buffer *VB = ctx->VB;
863 struct immediate *prev = VB->prev_buffer;
864 GLuint vec_start, diff;
865
866 IM->ref_count++;
867
868 if (prev != IM || IM != VB->IM) {
869 gl_copy_prev_vertices( VB, VB->prev_buffer, IM );
870 }
871
872 if (! --prev->ref_count )
873 gl_immediate_free( prev );
874
875 VB->prev_buffer = IM;
876 VB->Start = IM->Start;
877 VB->Count = IM->Count;
878 VB->Flag = IM->Flag;
879 VB->OrFlag = IM->OrFlag | VB->SavedOrFlag;
880 VB->EltPtr = &IM->v.Elt;
881 VB->MaterialMask = IM->MaterialMask;
882 VB->Material = IM->Material;
883 VB->CullMode = (GLubyte) ((IM->AndFlag & VERT_NORM) ? 0 : COMPACTED_NORMALS);
884 VB->ObjPtr = &IM->v.Obj;
885 VB->NormalPtr = &IM->v.Normal;
886 VB->ColorPtr = &IM->v.Color;
887 VB->Color[0] = VB->Color[1] = VB->ColorPtr;
888 VB->IndexPtr = &IM->v.Index;
889 VB->EdgeFlagPtr = &IM->v.EdgeFlag;
890 VB->TexCoordPtr[0] = &IM->v.TexCoord[0];
891 VB->TexCoordPtr[1] = &IM->v.TexCoord[1];
892/* VB->BoundsPtr = IM->Bounds; */
893 VB->NormalLengthPtr = IM->NormalLengths;
894 VB->IndirectCount = VB->Count;
895 VB->SavedOrFlag = 0;
896
897 if (IM->Start != VB_START)
898 VB->CopyStart = IM->Start;
899
900 vec_start = IM->Start;
901 if (vec_start == VB_START && VB->pipeline->replay_copied_vertices)
902 vec_start = VB->CopyStart;
903
904 if (MESA_VERBOSE&VERBOSE_IMMEDIATE)
905 fprintf(stderr, "reseting vectors to %d/%d .. %d\n", vec_start, IM->Start, IM->Count);
906
907 VB->LastPrimitive = IM->Start;
908
909 diff = IM->Count - vec_start;
910
911 RESET_VEC(IM->v.Obj, (GLfloat *), vec_start, diff);
912 RESET_VEC(IM->v.Normal, (GLfloat *), vec_start, diff);
913 RESET_VEC(IM->v.TexCoord[0], (GLfloat *), vec_start, diff);
914 RESET_VEC(IM->v.TexCoord[1], (GLfloat *), vec_start, diff);
915 RESET_VEC(IM->v.Index, &, vec_start, diff);
916 RESET_VEC(IM->v.Elt, &, vec_start, diff);
917 RESET_VEC(IM->v.EdgeFlag, &, vec_start, diff);
918 RESET_VEC(IM->v.Color, (GLubyte *), vec_start, diff);
919 RESET_VEC(VB->Clip, (GLfloat *), vec_start, diff);
920 RESET_VEC(VB->Eye, (GLfloat *), vec_start, diff);
921 RESET_VEC(VB->Win, (GLfloat *), vec_start, diff);
922 RESET_VEC(VB->BColor, (GLubyte *), vec_start, diff);
923 RESET_VEC(VB->BIndex, &, vec_start, diff);
924
925 if (IM != VB->IM) {
926 RESET_VEC(VB->IM->v.Obj, (GLfloat *), vec_start, diff);
927 RESET_VEC(VB->IM->v.Normal, (GLfloat *), vec_start, diff);
928 RESET_VEC(VB->IM->v.TexCoord[0], (GLfloat *), vec_start, diff);
929 RESET_VEC(VB->IM->v.TexCoord[1], (GLfloat *), vec_start, diff);
930 RESET_VEC(VB->IM->v.Index, &, vec_start, diff);
931 RESET_VEC(VB->IM->v.Elt, &, vec_start, diff);
932 RESET_VEC(VB->IM->v.EdgeFlag, &, vec_start, diff);
933 RESET_VEC(VB->IM->v.Color, (GLubyte *), vec_start, diff);
934 }
935
936 gl_copy_to_current( ctx, IM );
937
938 set_vec_sizes( IM, VB->OrFlag );
939
940 if (MESA_VERBOSE&VERBOSE_IMMEDIATE)
941 fprintf(stderr,
942 "executing cassette, rows %u tc0->size == %u tc1->size == %u\n",
943 VB->Count,
944 VB->TexCoordPtr[0]->size,
945 VB->TexCoordPtr[1]->size);
946
947 if (MESA_VERBOSE&VERBOSE_IMMEDIATE)
948 gl_print_cassette( IM );
949
950
951 if (IM->OrFlag & VERT_EVAL_ANY)
952 gl_eval_vb( VB );
953
954 if (IM->Count > IM->Start || (IM->Flag[IM->Start] & (VERT_END|VERT_BEGIN)))
955 fixup_primitives( VB, IM );
956
957 if (VB->IndirectCount > IM->Start)
958 gl_run_pipeline( VB );
959 else
960 gl_update_materials( VB );
961
962 /* This is unfortunate:
963 */
964 if (VB->pipeline->replay_copied_vertices) {
965 if (!VB->CullDone)
966 gl_fast_copy_vb( VB );
967
968 gl_copy_prev_vertices( VB, VB->prev_buffer, IM );
969 }
970
971 gl_reset_vb( VB );
972}
973
974void gl_print_cassette( struct immediate *IM )
975{
976 gl_print_cassette_flags( IM, IM->Flag );
977}
978
979void gl_print_cassette_flags( struct immediate *IM, GLuint *flags )
980{
981 GLuint i;
982 GLuint andflag = IM->AndFlag;
983 GLuint orflag = IM->OrFlag;
984 GLuint state = IM->BeginState;
985 GLuint req = ~0;
986 static const char *tplate[5] = { "%s ",
987 "%s: %f ",
988 "%s: %f %f ",
989 "%s: %f %f %f ",
990 "%s: %f %f %f %f " };
991
992 fprintf(stderr, "Cassette id %d, %u rows.\n", IM->id, IM->Count - IM->Start);
993
994 gl_print_vert_flags("Contains at least one", orflag);
995
996 if (IM->Count != IM->Start)
997 {
998 gl_print_vert_flags("Contains a full complement of", andflag);
999
1000 fprintf(stderr, "Final begin/end state %s/%s, errors %s/%s\n",
1001 (state & VERT_BEGIN_0) ? "in" : "out",
1002 (state & VERT_BEGIN_1) ? "in" : "out",
1003 (state & VERT_ERROR_0) ? "y" : "n",
1004 (state & VERT_ERROR_1) ? "y" : "n");
1005
1006 fprintf(stderr, "Obj size: %u, TexCoord0 size: %u, TexCoord1 size: %u\n",
1007 IM->v.Obj.size,
1008 IM->v.TexCoord[0].size,
1009 IM->v.TexCoord[1].size);
1010 }
1011
1012 for (i = IM->Start ; i <= IM->Count ; i++) {
1013 fprintf(stderr, "%u: ", i);
1014 if (req & VERT_OBJ_ANY) {
1015 if (flags[i] & VERT_EVAL_C1)
1016 fprintf(stderr, "EvalCoord %f ", IM->Obj[i][0]);
1017 else if (flags[i] & VERT_EVAL_P1)
1018 fprintf(stderr, "EvalPoint %.0f ", IM->Obj[i][0]);
1019 else if (flags[i] & VERT_EVAL_C2)
1020 fprintf(stderr, "EvalCoord %f %f ", IM->Obj[i][0], IM->Obj[i][1]);
1021 else if (flags[i] & VERT_EVAL_P2)
1022 fprintf(stderr, "EvalPoint %.0f %.0f ", IM->Obj[i][0], IM->Obj[i][1]);
1023 else if (i < IM->Count && (flags[i]&VERT_OBJ_234)) {
1024 fprintf(stderr, "(%x) ", flags[i] & VERT_OBJ_234);
1025 fprintf(stderr, tplate[vertex_sizes[(flags[i]&VERT_OBJ_234)<<1]],
1026 "Obj",
1027 IM->Obj[i][0], IM->Obj[i][1], IM->Obj[i][2], IM->Obj[i][3]);
1028 }
1029 }
1030
1031 if (req & flags[i] & VERT_ELT)
1032 fprintf(stderr, " Elt %u\t", IM->Elt[i]);
1033
1034 if (req & flags[i] & VERT_NORM)
1035 fprintf(stderr, " Norm %f %f %f ",
1036 IM->Normal[i][0], IM->Normal[i][1], IM->Normal[i][2]);
1037
1038 if (req & flags[i] & VERT_TEX0_ANY)
1039 fprintf(stderr, tplate[vertex_sizes[(flags[i]>>VERT_TEX0_SHIFT)&7]],
1040 "TC0",
1041 IM->TexCoord[0][i][0], IM->TexCoord[0][i][1],
1042 IM->TexCoord[0][i][2], IM->TexCoord[0][i][2]);
1043
1044
1045 if (req & flags[i] & VERT_TEX1_ANY)
1046 fprintf(stderr, tplate[vertex_sizes[(flags[i]>>(VERT_TEX0_SHIFT+4))&7]],
1047 "TC1",
1048 IM->TexCoord[1][i][0], IM->TexCoord[1][i][1],
1049 IM->TexCoord[1][i][2], IM->TexCoord[1][i][2]);
1050
1051 if (req & flags[i] & VERT_RGBA)
1052 fprintf(stderr, " Rgba %d %d %d %d ",
1053 IM->Color[i][0], IM->Color[i][1],
1054 IM->Color[i][2], IM->Color[i][3]);
1055
1056 if (req & flags[i] & VERT_INDEX)
1057 fprintf(stderr, " Index %u ", IM->Index[i]);
1058
1059 if (req & flags[i] & VERT_EDGE)
1060 fprintf(stderr, " Edgeflag %d ", IM->EdgeFlag[i]);
1061
1062 if (req & flags[i] & VERT_MATERIAL)
1063 fprintf(stderr, " Material ");
1064
1065
1066 /* The order of these two is not easily knowable, but this is
1067 * the usually correct way to look at them.
1068 */
1069 if (req & flags[i] & VERT_END)
1070 fprintf(stderr, " END ");
1071
1072 if (req & flags[i] & VERT_BEGIN)
1073 fprintf(stderr, " BEGIN(%s) ", gl_prim_name[IM->Primitive[i]]);
1074
1075 fprintf(stderr, "\n");
1076 }
1077}
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
Note: See TracBrowser for help on using the repository browser.