further tweak to dlist change
[mesa.git] / src / mesa / tnl / t_imm_fixup.c
index 530058528111e4bc5c1d90d254e1c096173c57b5..ce593343a9093fdd9e71d7fcc58d9caa62d0bdb8 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: t_imm_fixup.c,v 1.16 2001/05/11 15:53:06 keithw Exp $ */
+/* $Id: t_imm_fixup.c,v 1.28 2001/12/03 17:47:04 keithw Exp $ */
 
 /*
  * Mesa 3-D graphics library
@@ -50,6 +50,7 @@
 #include "t_imm_debug.h"
 #include "t_imm_elt.h"
 #include "t_imm_fixup.h"
+#include "t_imm_exec.h"
 #include "t_pipeline.h"
 
 
@@ -74,8 +75,14 @@ _tnl_fixup_3f( float data[][3], GLuint flag[], GLuint start, GLuint match )
 {
    GLuint i = start;
 
+
    for (;;) {
       if ((flag[++i] & match) == 0) {
+/*      fprintf(stderr, "_tnl_fixup_3f copy to %p values %f %f %f\n", */
+/*              data[i],  */
+/*              data[i-1][0], */
+/*              data[i-1][1], */
+/*              data[i-1][2]); */
         COPY_3V(data[i], data[i-1]);
         if (flag[i] & VERT_END_VB) break;
       }
@@ -145,6 +152,9 @@ fixup_first_3f( GLfloat data[][3], GLuint flag[], GLuint match,
    GLuint i = start-1;
    match |= VERT_END_VB;
 
+/*     fprintf(stderr, "fixup_first_3f default: %f %f %f start: %d\n", */
+/*        dflt[0], dflt[1], dflt[2], start);  */
+
    while ((flag[++i]&match) == 0)
       COPY_3FV(data[i], dflt);
 }
@@ -184,13 +194,48 @@ fixup_first_1ub( GLubyte data[], GLuint flag[], GLuint match,
       data[i] = dflt;
 }
 
+static void copy_from_current( GLcontext *ctx, struct immediate *IM, 
+                             GLuint start, GLuint copy )
+{
+   if (MESA_VERBOSE&VERBOSE_IMMEDIATE)
+      _tnl_print_vert_flags("copy from current", copy); 
+
+   if (copy & VERT_NORM) {
+      COPY_3V( IM->Normal[start], ctx->Current.Normal );
+   }
+
+   if (copy & VERT_RGBA) {
+      COPY_4FV( IM->Color[start], ctx->Current.Color);
+   }
+
+   if (copy & VERT_SPEC_RGB)
+      COPY_4FV( IM->SecondaryColor[start], ctx->Current.SecondaryColor);
+
+   if (copy & VERT_FOG_COORD)
+      IM->FogCoord[start] = ctx->Current.FogCoord;
+
+   if (copy & VERT_INDEX)
+      IM->Index[start] = ctx->Current.Index;
+
+   if (copy & VERT_EDGE)
+      IM->EdgeFlag[start] = ctx->Current.EdgeFlag;
+
+   if (copy & VERT_TEX_ANY) {
+      GLuint i;
+      for (i = 0 ; i < ctx->Const.MaxTextureUnits ; i++) {
+        if (copy & VERT_TEX(i))
+           COPY_4FV( IM->TexCoord[i][start], ctx->Current.Texcoord[i] );
+      }
+   }
+}
+
 
 void _tnl_fixup_input( GLcontext *ctx, struct immediate *IM )
 {
    TNLcontext *tnl = TNL_CONTEXT(ctx);
    GLuint start = IM->CopyStart;
    GLuint andflag = IM->CopyAndFlag;
-   GLuint orflag = IM->CopyOrFlag;
+   GLuint orflag = IM->CopyOrFlag | IM->Evaluated;
    GLuint fixup;
 
    IM->CopyTexSize = IM->TexSize;
@@ -219,39 +264,8 @@ void _tnl_fixup_input( GLcontext *ctx, struct immediate *IM )
       /* Equivalent to a lazy copy-from-current when setting up the
        * immediate.
        */
-      if (ctx->ExecuteFlag && copy) {
-
-        if (MESA_VERBOSE&VERBOSE_IMMEDIATE)
-           _tnl_print_vert_flags("copy from current", copy); 
-
-        if (copy & VERT_NORM) {
-           COPY_3V( IM->Normal[start], ctx->Current.Normal );
-        }
-
-        if (copy & VERT_RGBA) {
-           COPY_4FV( IM->Color[start], ctx->Current.Color);
-        }
-
-        if (copy & VERT_SPEC_RGB)
-           COPY_4FV( IM->SecondaryColor[start], ctx->Current.SecondaryColor);
-
-        if (copy & VERT_FOG_COORD)
-           IM->FogCoord[start] = ctx->Current.FogCoord;
-
-        if (copy & VERT_INDEX)
-           IM->Index[start] = ctx->Current.Index;
-
-        if (copy & VERT_EDGE)
-           IM->EdgeFlag[start] = ctx->Current.EdgeFlag;
-
-        if (copy & VERT_TEX_ANY) {
-           GLuint i;
-           for (i = 0 ; i < ctx->Const.MaxTextureUnits ; i++) {
-              if (copy & VERT_TEX(i))
-                 COPY_4FV( IM->TexCoord[i][start], ctx->Current.Texcoord[i] );
-           }
-        }
-      }
+      if (ctx->ExecuteFlag && copy) 
+        copy_from_current( ctx, IM, start, copy );
 
       if (MESA_VERBOSE&VERBOSE_IMMEDIATE)
         _tnl_print_vert_flags("fixup", fixup); 
@@ -364,6 +378,18 @@ static void copy_material( struct immediate *next,
    MEMCPY(next->Material[dst], prev->Material[src], 2*sizeof(GLmaterial));
 }
 
+static GLboolean is_fan_like[GL_POLYGON+1] = {
+   GL_FALSE,
+   GL_FALSE,
+   GL_TRUE,                    /* line loop */
+   GL_FALSE,
+   GL_FALSE,
+   GL_FALSE,
+   GL_TRUE,                    /* tri fan */
+   GL_FALSE,
+   GL_FALSE,
+   GL_TRUE                     /* polygon */
+};
 
 
 /* Copy the untransformed data from the shared vertices of a primitive
@@ -405,15 +431,31 @@ void _tnl_copy_immediate_vertices( GLcontext *ctx, struct immediate *next )
         next->Elt[dst] = prev->Elt[src];
         next->Flag[dst] = VERT_ELT;
       }
+/*        fprintf(stderr, "ADDING VERT_ELT!\n"); */
       next->CopyOrFlag |= VERT_ELT;
       next->CopyAndFlag &= VERT_ELT;
    }
    else {
-      /* prev->CopyOrFlag is hacked to include values generated by eval:
-       */
-      GLuint copy = tnl->pipeline.inputs & prev->CopyOrFlag;
-          
+      GLuint copy = tnl->pipeline.inputs & (prev->CopyOrFlag|prev->Evaluated);
+      GLuint flag;
+
+      if (is_fan_like[ctx->Driver.CurrentExecPrimitive]) {
+        flag = ((prev->CopyOrFlag|prev->Evaluated) & VERT_FIXUP);
+        next->CopyOrFlag |= flag;
+      } 
+      else {
+        /* Don't let an early 'glColor', etc. poison the elt path.
+         */
+        flag = ((prev->OrFlag|prev->Evaluated) & VERT_FIXUP);
+      }
+
       next->TexSize |= tnl->ExecCopyTexSize;
+      next->CopyAndFlag &= flag;
+        
+
+/*        _tnl_print_vert_flags("copy vertex components", copy); */
+/*        _tnl_print_vert_flags("prev copyorflag", prev->CopyOrFlag); */
+/*        _tnl_print_vert_flags("flag", flag); */
 
       /* Copy whole vertices
        */
@@ -430,8 +472,15 @@ void _tnl_copy_immediate_vertices( GLcontext *ctx, struct immediate *next )
          */
         COPY_4FV( next->Obj[dst], inputs->Obj.data[isrc] );
 
-        if (copy & VERT_NORM) 
+        if (copy & VERT_NORM) {
+/*         fprintf(stderr, "copy vert norm %d to %d (%p): %f %f %f\n", */
+/*                 isrc, dst,  */
+/*                 next->Normal[dst], */
+/*                 inputs->Normal.data[isrc][0], */
+/*                 inputs->Normal.data[isrc][1], */
+/*                 inputs->Normal.data[isrc][2]); */
            COPY_3FV( next->Normal[dst], inputs->Normal.data[isrc] );
+        }
 
         if (copy & VERT_RGBA)
            COPY_4FV( next->Color[dst], 
@@ -464,11 +513,11 @@ void _tnl_copy_immediate_vertices( GLcontext *ctx, struct immediate *next )
            next->FogCoord[dst] = prev->FogCoord[src];
         }
 
-        next->Flag[dst] = (prev->CopyOrFlag & VERT_FIXUP);
+        next->Flag[dst] = flag;
+        next->CopyOrFlag |= prev->Flag[src] & (VERT_FIXUP|
+                                               VERT_MATERIAL|
+                                               VERT_OBJ);
       }
-
-      next->CopyOrFlag |= (prev->CopyOrFlag & VERT_FIXUP);
-      next->CopyAndFlag &= (prev->CopyOrFlag & VERT_FIXUP);
    }
 
    if (--tnl->ExecCopySource->ref_count == 0)
@@ -479,20 +528,21 @@ void _tnl_copy_immediate_vertices( GLcontext *ctx, struct immediate *next )
 }
 
 
+
 /* Revive a compiled immediate struct - propogate new 'Current'
  * values.  Often this is redundant because the current values were
- * known and fixed up at compile time.
+ * known and fixed up at compile time (or in the first execution of
+ * the cassette).
  */
 void _tnl_fixup_compiled_cassette( GLcontext *ctx, struct immediate *IM )
 {
    TNLcontext *tnl = TNL_CONTEXT(ctx);
    GLuint fixup;
-   GLuint count = IM->Count;
    GLuint start = IM->Start;
 
-   if (count == start)
-      return;
+/*     fprintf(stderr, "%s\n", __FUNCTION__); */
 
+   IM->Evaluated = 0;
    IM->CopyOrFlag = IM->OrFlag;          
    IM->CopyAndFlag = IM->AndFlag; 
    IM->CopyTexSize = IM->TexSize | tnl->ExecCopyTexSize;
@@ -507,12 +557,23 @@ void _tnl_fixup_compiled_cassette( GLcontext *ctx, struct immediate *IM )
     * display list.  Need to translate them away:
     */
    if (IM->CopyOrFlag & VERT_ELT) {
+      GLuint copy = tnl->pipeline.inputs & ~ctx->Array._Enabled;
+      GLuint i;
+
       ASSERT(IM->CopyStart < IM->Start);
+
       _tnl_translate_array_elts( ctx, IM, IM->CopyStart, IM->Start );
+
+      for (i = IM->CopyStart ; i < IM->Start ; i++)
+        copy_from_current( ctx, IM, i, copy ); 
+
+      _tnl_copy_to_current( ctx, IM, ctx->Array._Enabled, IM->Start );
    }
 
    fixup = tnl->pipeline.inputs & ~IM->Flag[start] & VERT_FIXUP;
 
+/*     _tnl_print_vert_flags("fixup compiled", fixup); */
+
    if (fixup) {
       if (fixup & VERT_TEX_ANY) {
         GLuint i;
@@ -531,10 +592,13 @@ void _tnl_fixup_compiled_cassette( GLcontext *ctx, struct immediate *IM )
         fixup_first_1ui(IM->Index, IM->Flag, VERT_INDEX, start,
                         ctx->Current.Index );
 
-      if (fixup & VERT_RGBA)
+      if (fixup & VERT_RGBA) {
         if (IM->CopyOrFlag & VERT_RGBA)
            fixup_first_4f(IM->Color, IM->Flag, VERT_RGBA, start,
                           ctx->Current.Color );
+        else
+           fixup &= ~VERT_RGBA;
+      }
 
       if (fixup & VERT_SPEC_RGB)
         fixup_first_4f(IM->SecondaryColor, IM->Flag, VERT_SPEC_RGB, start,
@@ -548,7 +612,10 @@ void _tnl_fixup_compiled_cassette( GLcontext *ctx, struct immediate *IM )
         fixup_first_3f(IM->Normal, IM->Flag, VERT_NORM, start,
                        ctx->Current.Normal );
       }
+
+      IM->CopyOrFlag |= fixup;
    }
+   
 
    /* Materials:
     */
@@ -568,96 +635,6 @@ void _tnl_fixup_compiled_cassette( GLcontext *ctx, struct immediate *IM )
 
       } while (vulnerable);
    }
-
-   /* Can potentially overwrite primitive details - need to save the
-    * first slot:
-    */
-   tnl->DlistPrimitive = IM->Primitive[IM->Start];
-   tnl->DlistPrimitiveLength = IM->PrimitiveLength[IM->Start];
-   tnl->DlistLastPrimitive = IM->LastPrimitive;
-
-   /* The first primitive may be different from what was recorded in
-    * the immediate struct.  Consider an immediate that starts with a
-    * glBegin, compiled in a display list, which is called from within
-    * an existing Begin/End object.
-    */
-   if (ctx->Driver.CurrentExecPrimitive == GL_POLYGON+1) {
-      GLuint i;
-
-      if (IM->BeginState & VERT_ERROR_1)
-        _mesa_error( ctx, GL_INVALID_OPERATION, "glBegin/glEnd");
-
-      for (i = IM->Start ; i <= IM->Count ; i += IM->PrimitiveLength[i])
-        if (IM->Flag[i] & (VERT_BEGIN|VERT_END_VB))
-           break;
-
-      /* Would like to just ignore vertices upto this point.  Can't
-       * set copystart because it might skip materials?
-       */
-      ASSERT(IM->Start == IM->CopyStart);
-      if (i > IM->CopyStart) {
-        IM->Primitive[IM->CopyStart] = GL_POLYGON+1;
-        IM->PrimitiveLength[IM->CopyStart] = i - IM->CopyStart;
-        if (IM->Flag[i] & VERT_END_VB) {
-           IM->Primitive[IM->CopyStart] |= PRIM_LAST;
-           IM->LastPrimitive = IM->CopyStart;
-        }
-      }
-   } else {
-      GLuint i;
-
-      if (IM->BeginState & VERT_ERROR_0)
-        _mesa_error( ctx, GL_INVALID_OPERATION, "glBegin/glEnd");
-
-      if (IM->CopyStart == IM->Start &&
-         IM->Flag[IM->Start] & (VERT_END|VERT_END_VB))
-      {
-      }
-      else
-      {
-        IM->Primitive[IM->CopyStart] = ctx->Driver.CurrentExecPrimitive;
-        if (tnl->ExecParity)
-           IM->Primitive[IM->CopyStart] |= PRIM_PARITY;
-
-         /* one of these should be true, else we'll be in an infinite loop */
-         assert(IM->PrimitiveLength[IM->Start] > 0 ||
-                IM->Flag[IM->Start] & (VERT_END|VERT_END_VB));
-        for (i = IM->Start ; i <= IM->Count ; i += IM->PrimitiveLength[i])
-           if (IM->Flag[i] & (VERT_END|VERT_END_VB)) {
-              IM->PrimitiveLength[IM->CopyStart] = i - IM->CopyStart;
-              if (IM->Flag[i] & VERT_END_VB) {
-                 IM->Primitive[IM->CopyStart] |= PRIM_LAST;
-                 IM->LastPrimitive = IM->CopyStart;
-              }
-              if (IM->Flag[i] & VERT_END) {
-                 IM->Primitive[IM->CopyStart] |= PRIM_END;
-              }
-              break;
-           }
-      }
-   }
-
-   if (IM->Primitive[IM->LastPrimitive] & PRIM_END)
-      ctx->Driver.CurrentExecPrimitive = GL_POLYGON+1;
-   else
-      ctx->Driver.CurrentExecPrimitive =
-        IM->Primitive[IM->LastPrimitive] & PRIM_MODE_MASK;
-
-/*     fprintf(stderr, "setting cep %x in %s\n",  */
-/*        ctx->Driver.CurrentExecPrimitive, __FUNCTION__); */
-/*     fprintf(stderr, "%s lastprim %d: %x\n", __FUNCTION__,  */
-/*        IM->LastPrimitive, IM->Primitive[IM->LastPrimitive]); */
-}
-
-
-/* Undo any changes potentially made to the immediate in the range
- * IM->Start..IM->Count above.
- */
-void _tnl_restore_compiled_cassette( GLcontext *ctx, struct immediate *IM )
-{
-   TNLcontext *tnl = TNL_CONTEXT(ctx);
-   IM->Primitive[IM->Start] = tnl->DlistPrimitive;
-   IM->PrimitiveLength[IM->Start] = tnl->DlistPrimitiveLength;
 }
 
 
@@ -758,7 +735,12 @@ _tnl_get_exec_copy_verts( GLcontext *ctx, struct immediate *IM )
       tnl->ExecCopySource = IM;
       tnl->ExecCopyCount = 0;
       tnl->ExecCopyTexSize = IM->CopyTexSize;
-      tnl->ExecParity = IM->PrimitiveLength[IM->LastPrimitive] & 1;
+
+      if (IM->LastPrimitive != IM->CopyStart)
+        tnl->ExecParity = 0;
+        
+      tnl->ExecParity ^= IM->PrimitiveLength[IM->LastPrimitive] & 1;
+
 
       if (pincr != 1 && (IM->Count - last - pintro))
         ovf = (IM->Count - last - pintro) % pincr;
@@ -784,7 +766,10 @@ _tnl_get_purged_copy_verts( GLcontext *ctx, struct immediate *IM )
       GLuint ovf = 0, i;
 
       tnl->ExecCopyCount = 0;
-      tnl->ExecParity = IM->PrimitiveLength[last] & 1;
+      if (IM->LastPrimitive != IM->CopyStart)
+        tnl->ExecParity = 0;
+        
+      tnl->ExecParity ^= IM->PrimitiveLength[IM->LastPrimitive] & 1;
 
       if (pincr != 1 && (IM->Count - last - pintro))
         ovf = (IM->Count - last - pintro) % pincr;
@@ -803,8 +788,8 @@ void _tnl_upgrade_current_data( GLcontext *ctx,
                                GLuint flags )
 {
    TNLcontext *tnl = TNL_CONTEXT(ctx);
-   struct immediate *IM = TNL_CURRENT_IM(ctx); /* hmmm */
    struct vertex_buffer *VB = &tnl->vb;
+   struct immediate *IM = (struct immediate *)VB->import_source;
 
    ASSERT(IM);
 
@@ -819,6 +804,11 @@ void _tnl_upgrade_current_data( GLcontext *ctx,
       tmp->Flags = 0;
 
       COPY_4FV( IM->Color[start], ctx->Current.Color);   
+
+      /*
+      ASSERT(IM->Flag[IM->LastData+1] & VERT_END_VB);
+      */
+
       fixup_first_4f( IM->Color, IM->Flag, VERT_END_VB, start, 
                      IM->Color[start] );