Clean up _tnl_Begin/begin/hard_begin.
authorKeith Whitwell <keith@tungstengraphics.com>
Fri, 11 May 2001 15:53:06 +0000 (15:53 +0000)
committerKeith Whitwell <keith@tungstengraphics.com>
Fri, 11 May 2001 15:53:06 +0000 (15:53 +0000)
Fix some problems with draw_arrays, draw_elements.

src/mesa/tnl/t_array_api.c
src/mesa/tnl/t_array_import.c
src/mesa/tnl/t_imm_api.c
src/mesa/tnl/t_imm_dlist.c
src/mesa/tnl/t_imm_fixup.c
src/mesa/tnl/t_vb_render.c

index 0e482de..257febe 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: t_array_api.c,v 1.14 2001/05/11 08:11:31 keithw Exp $ */
+/* $Id: t_array_api.c,v 1.15 2001/05/11 15:53:06 keithw Exp $ */
 
 /*
  * Mesa 3-D graphics library
@@ -48,6 +48,8 @@
 static void fallback_drawarrays( GLcontext *ctx, GLenum mode, GLint start,
                                 GLsizei count )
 {
+/*     fprintf(stderr, "%s\n", __FUNCTION__); */
+
    /* Need to produce immediate structs, either for compiling or
     * because the array range is too large to process in a single
     * VB.  In GL_EXECUTE mode, this introduces two redundant
@@ -56,20 +58,18 @@ static void fallback_drawarrays( GLcontext *ctx, GLenum mode, GLint start,
     */
 #if 1
    if (_tnl_hard_begin( ctx, mode )) {
-      GLint j;
-      for (j = 0 ; j < count ; ) {
+      GLint i;
+      for (i = 0 ; i < count ; ) {
         struct immediate *IM = TNL_CURRENT_IM(ctx);
-        GLuint nr = MIN2( IMM_MAXDATA - IM->Start, (GLuint) (count - j) );
-        GLuint sf = IM->Flag[IM->Start];
-
-        _tnl_fill_immediate_drawarrays( ctx, IM, j, j+nr );
+        GLuint start = IM->Start;
+        GLuint nr = MIN2( IMM_MAXDATA - start, (GLuint) (count - i) );
 
-        if (j == 0) IM->Flag[IM->Start] |= sf;
+        _tnl_fill_immediate_drawarrays( ctx, IM, i, i+nr );
 
-        IM->Count = IM->Start + nr;
-        j += nr;
+        IM->Count = start + nr;
+        i += nr;
 
-        if (j == count)
+        if (i == count)
            _tnl_end( ctx );
 
         _tnl_flush_immediate( IM );
@@ -93,30 +93,31 @@ static void fallback_drawarrays( GLcontext *ctx, GLenum mode, GLint start,
 static void fallback_drawelements( GLcontext *ctx, GLenum mode, GLsizei count,
                                   const GLuint *indices)
 {
+/*     fprintf(stderr, "%s\n", __FUNCTION__); */
+
 #if 1
    /* Optimized code that fakes the effect of calling
     * _tnl_array_element for each index in the list.
     */
    if (_tnl_hard_begin( ctx, mode )) {
       GLint i, j;
-      for (j = 0 ; j < count ; ) {
+      for (i = 0 ; i < count ; ) {
         struct immediate *IM = TNL_CURRENT_IM(ctx);
         GLuint start = IM->Start;
-        GLint nr = MIN2( (GLint) (IMM_MAXDATA - start), count - j ) + start;
+        GLint end = MIN2( IMM_MAXDATA, (count - i) + start);
         GLuint sf = IM->Flag[start];
         IM->FlushElt = IM->ArrayEltFlush;
 
-        for (i = start ; i < nr ; i++) {
-           IM->Elt[i] = (GLuint) *indices++;
-           IM->Flag[i] = VERT_ELT;
+        for (j = start ; j < end ; j++) {
+           IM->Elt[j] = (GLuint) *indices++;
+           IM->Flag[j] = VERT_ELT;
         }
 
-        if (j == 0) IM->Flag[start] |= sf;
+        IM->Flag[start] |= (sf & IM->ArrayEltFlags);
+        IM->Count = end;
+        i += end - start;
 
-        IM->Count = nr;
-        j += nr - start;
-
-        if (j == count)
+        if (i == count)
            _tnl_end( ctx );
 
         _tnl_flush_immediate( IM );
@@ -171,6 +172,8 @@ _tnl_DrawArrays(GLenum mode, GLint start, GLsizei count)
    TNLcontext *tnl = TNL_CONTEXT(ctx);
    struct vertex_buffer *VB = &tnl->vb;
 
+/*     fprintf(stderr, "%s\n", __FUNCTION__); */
+   
    /* Check arguments, etc.
     */
    if (!_mesa_validate_DrawArrays( ctx, mode, start, count ))
@@ -277,11 +280,14 @@ _tnl_DrawArrays(GLenum mode, GLint start, GLsizei count)
 
 /*        fprintf(stderr, "start %d count %d min %d modulo %d skip %d\n", */
 /*           start, count, minimum, modulo, skip); */
+
       
+      bufsz -= bufsz % modulo;
+      bufsz -= minimum;
+
       for (j = start + minimum ; j < count ; j += nr + skip ) {
 
         nr = MIN2( bufsz, count - j );
-        nr -= nr % modulo;
 
 /*      fprintf(stderr, "%d..%d\n", j - minimum, j+nr); */
 
@@ -307,6 +313,8 @@ _tnl_DrawRangeElements(GLenum mode,
    TNLcontext *tnl = TNL_CONTEXT(ctx);
    GLuint *ui_indices;
 
+/*     fprintf(stderr, "%s\n", __FUNCTION__); */
+
    /* Check arguments, etc.
     */
    if (!_mesa_validate_DrawRangeElements( ctx, mode, start, end, count,
@@ -367,6 +375,8 @@ _tnl_DrawElements(GLenum mode, GLsizei count, GLenum type,
    TNLcontext *tnl = TNL_CONTEXT(ctx);
    GLuint *ui_indices;
 
+/*     fprintf(stderr, "%s\n", __FUNCTION__); */
+
    /* Check arguments, etc.
     */
    if (!_mesa_validate_DrawElements( ctx, mode, count, type, indices ))
index 5194758..77fa8a4 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: t_array_import.c,v 1.15 2001/05/11 08:11:31 keithw Exp $ */
+/* $Id: t_array_import.c,v 1.16 2001/05/11 15:53:06 keithw Exp $ */
 
 /*
  * Mesa 3-D graphics library
@@ -492,6 +492,7 @@ void _tnl_fill_immediate_drawarrays( GLcontext *ctx, struct immediate *IM,
    }
 
    IM->Count = IM->Start + n;
+   IM->Flag[IM->Start] &= IM->ArrayEltFlags;
    IM->Flag[IM->Start] |= required;
    for (i = IM->Start+1 ; i < IM->Count ; i++)
       IM->Flag[i] = required;
index 143cee2..2a55e0e 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: t_imm_api.c,v 1.13 2001/05/11 08:11:31 keithw Exp $ */
+/* $Id: t_imm_api.c,v 1.14 2001/05/11 15:53:06 keithw Exp $ */
 
 /*
  * Mesa 3-D graphics library
@@ -78,6 +78,11 @@ void _tnl_flush_vertices( GLcontext *ctx, GLuint flags )
 }
 
 
+
+
+/* Note the ctx argument.  This function called only by _tnl_Begin,
+ * _tnl_save_Begin and _tnl_hard_begin() in this file.  
+ */
 static void
 _tnl_begin( GLcontext *ctx, GLenum p )
 {
@@ -136,6 +141,25 @@ _tnl_begin( GLcontext *ctx, GLenum p )
 }
 
 
+void
+_tnl_save_Begin( GLenum mode )
+{
+   GET_CURRENT_CONTEXT(ctx);
+
+   if (mode > GL_POLYGON) {
+      _mesa_compile_error( ctx, GL_INVALID_ENUM, "glBegin" );
+      return;
+   }
+
+   _tnl_begin( ctx, mode );
+
+   /* Update save_primitive now.
+    */
+   if (ctx->Driver.CurrentSavePrimitive == PRIM_UNKNOWN)
+      ctx->Driver.CurrentSavePrimitive = PRIM_INSIDE_UNKNOWN_PRIM;
+   else if (ctx->Driver.CurrentSavePrimitive == PRIM_OUTSIDE_BEGIN_END)
+      ctx->Driver.CurrentSavePrimitive = mode;
+}
 
 static void
 _tnl_Begin( GLenum mode )
@@ -149,136 +173,101 @@ _tnl_Begin( GLenum mode )
 
    _tnl_begin(ctx, mode);
 
-   /* If compiling update SavePrimitive now.
-    *
-    * In compile_and_exec mode, exec_primitive will be updated when
-    * the cassette is finished.
-    *
-    * If not compiling, update exec_primitive now.
+   /* Update exec_primitive now.
     */
-   if (ctx->CompileFlag) {
-      if (ctx->Driver.CurrentSavePrimitive == PRIM_UNKNOWN)
-        ctx->Driver.CurrentSavePrimitive = PRIM_INSIDE_UNKNOWN_PRIM;
-      else if (ctx->Driver.CurrentSavePrimitive == PRIM_OUTSIDE_BEGIN_END)
-        ctx->Driver.CurrentSavePrimitive = mode;
-      }
-   else if (ctx->Driver.CurrentExecPrimitive == PRIM_OUTSIDE_BEGIN_END) {
-/*        fprintf(stderr, "setting cep %x in %s\n", mode, __FUNCTION__); */
+   ASSERT (!ctx->CompileFlag);
+   if (ctx->Driver.CurrentExecPrimitive == PRIM_OUTSIDE_BEGIN_END) {
       ctx->Driver.CurrentExecPrimitive = mode;
    }
 }
 
 
+/* Function which allows operations like 'glRectf' to decompose to a
+ * begin/end object and vertices without worrying about what happens
+ * with display lists.
+ */
 GLboolean
 _tnl_hard_begin( GLcontext *ctx, GLenum p )
 {
-   struct immediate *IM = TNL_CURRENT_IM(ctx);
-   GLuint count, last;
-
-   if (ctx->NewState)
-      _mesa_update_state(ctx);
-
-   /* If not compiling, treat as a normal begin().
-    */
    if (!ctx->CompileFlag) {
-      _tnl_begin( ctx, p );
-
-      /* Set this for the duration:
+      /* If not compiling, treat as a normal begin().
        */
+      _tnl_begin( ctx, p );
+      ASSERT(ctx->Driver.CurrentExecPrimitive == PRIM_OUTSIDE_BEGIN_END);
       ctx->Driver.CurrentExecPrimitive = p;
-/*        fprintf(stderr, "setting cep %x in %s\n",  */
-/*           ctx->Driver.CurrentExecPrimitive, __FUNCTION__); */
       return GL_TRUE;
    }
-
-   if (IM->Count > IMM_MAXDATA-8) {
-      _tnl_flush_immediate( IM );
-      IM = TNL_CURRENT_IM(ctx);
-   }
-
-   switch (IM->BeginState & (VERT_BEGIN_0|VERT_BEGIN_1)) {
-   case VERT_BEGIN_0|VERT_BEGIN_1:
-      /* This is an immediate known to be inside a begin/end object.
-       */
-      IM->BeginState |= (VERT_ERROR_1|VERT_ERROR_0);
-      return GL_FALSE;
-
-   case VERT_BEGIN_0:
-   case VERT_BEGIN_1:
-      /* This is a display-list immediate in an unknown begin/end
-       * state.  Assert it is empty and conviert it to a 'hard' one.
-       */
-      ASSERT (IM->SavedBeginState == 0);
-
-      /* Push current beginstate, to be restored later.  Don't worry
-       * about raising errors.
+   else {
+      /* Otherwise, need to do special processing to preserve the
+       * condition that these vertices will only be replayed outside
+       * future begin/end objects.
        */
-      IM->SavedBeginState = IM->BeginState;
+      struct immediate *IM = TNL_CURRENT_IM(ctx);
 
-      /* FALLTHROUGH */
-   case 0:
-      /* Unless we have fallen through, this is an immediate known to
-       * be outside begin/end objects.
-       */
-
-      IM->BeginState |= VERT_BEGIN_0|VERT_BEGIN_1;
-
-
-      count = IM->Count;
-      last = IM->LastPrimitive;
-
-      IM->Flag[count] |= VERT_BEGIN;
-      IM->Primitive[count] = p | PRIM_BEGIN;
-      IM->PrimitiveLength[last] = count - last;
-      IM->LastPrimitive = count;
+      if (ctx->NewState)
+        _mesa_update_state(ctx);
 
-      ASSERT (IM->FlushElt != FLUSH_ELT_EAGER);
+      if (IM->Count > IMM_MAXDATA-8) {
+        _tnl_flush_immediate( IM );
+        IM = TNL_CURRENT_IM(ctx);
+      }
 
-      /* This is necessary as this immediate will not be flushed in
-       * _tnl_end() -- we leave it active, hoping to pick up more
-       * vertices before the next state change.
+      /* A lot depends on the degree to which the display list has
+       * constrained the possible begin/end states at this point:
        */
-      ctx->Driver.NeedFlush |= FLUSH_STORED_VERTICES;
-
-      return GL_TRUE;
-
-   default:
-      ASSERT (0);
-      return GL_TRUE;
+      switch (IM->BeginState & (VERT_BEGIN_0|VERT_BEGIN_1)) {
+      case VERT_BEGIN_0|VERT_BEGIN_1:
+        /* This is an immediate known to be inside a begin/end object.
+         */
+        ASSERT(ctx->Driver.CurrentSavePrimitive <= GL_POLYGON);
+        IM->BeginState |= (VERT_ERROR_1|VERT_ERROR_0);
+        return GL_FALSE;
+
+      case VERT_BEGIN_0:
+      case VERT_BEGIN_1:
+        /* This is a display-list immediate in an unknown begin/end
+         * state.  Assert it is empty and convert it to a 'hard' one.
+         */
+        ASSERT(IM->SavedBeginState == 0);
+        ASSERT(ctx->Driver.CurrentSavePrimitive == PRIM_UNKNOWN);
+
+        /* Push current beginstate, to be restored later.  Don't worry
+         * about raising errors.
+         */
+        IM->SavedBeginState = IM->BeginState;
+
+        /* FALLTHROUGH */
+
+      case 0:
+        /* Unless we have fallen through, this is an immediate known to
+         * be outside begin/end objects.
+         */
+        ASSERT(ctx->Driver.CurrentSavePrimitive == PRIM_UNKNOWN ||
+               ctx->Driver.CurrentSavePrimitive == PRIM_OUTSIDE_BEGIN_END);
+        ASSERT (IM->FlushElt != FLUSH_ELT_EAGER);
+
+        IM->BeginState |= VERT_BEGIN_0|VERT_BEGIN_1;
+        IM->Flag[IM->Count] |= VERT_BEGIN;
+        IM->Primitive[IM->Count] = p | PRIM_BEGIN;
+        IM->PrimitiveLength[IM->LastPrimitive] = IM->Count - IM->LastPrimitive;
+        IM->LastPrimitive = IM->Count;
+
+        /* This is necessary as this immediate will not be flushed in
+         * _tnl_end() -- we leave it active, hoping to pick up more
+         * vertices before the next state change.
+         */
+        ctx->Driver.NeedFlush |= FLUSH_STORED_VERTICES;
+        return GL_TRUE;
+
+      default:
+        ASSERT (0);
+        return GL_TRUE;
+      }
    }
 }
 
 
 
-/* Need to do this to get the correct begin/end error behaviour from
- * functions like ColorPointerEXT which are still active in
- * SAVE_AND_EXEC modes.
- */
-void
-_tnl_save_Begin( GLenum mode )
-{
-   GET_CURRENT_CONTEXT(ctx);
-
-   if (mode > GL_POLYGON) {
-      _mesa_compile_error( ctx, GL_INVALID_ENUM, "glBegin" );
-      return;
-   }
-
-   if (ctx->ExecuteFlag) {
-      /* Preserve vtxfmt invarient:
-       */
-      if (ctx->NewState)
-        _mesa_update_state( ctx );
-
-      /* Slot in geomexec: No need to call setdispatch as we know
-       * CurrentDispatch is Save.
-       */
-      ASSERT(ctx->CurrentDispatch == ctx->Save);
-   }
-
-   _tnl_begin( ctx, mode );
-}
-
 
 
 
@@ -317,8 +306,6 @@ _tnl_end( GLcontext *ctx )
 
    if (!ctx->CompileFlag) {
       ctx->Driver.CurrentExecPrimitive = PRIM_OUTSIDE_BEGIN_END;
-/*        fprintf(stderr, "setting cep %x in %s\n",  */
-/*           ctx->Driver.CurrentExecPrimitive, __FUNCTION__); */
    }
 
    /* You can set this flag to get the old 'flush_vb on glEnd()'
@@ -1113,8 +1100,8 @@ _tnl_vertex2f( GLcontext *ctx, GLfloat x, GLfloat y )
 
 /* Execute a glRectf() function.  _tnl_hard_begin() ensures the check
  * on outside_begin_end is executed even in compiled lists.  These
- * vertices can now participate in the same VB as regular ones, even
- * in most display lists.
+ * vertices can now participate in the same immediate as regular ones,
+ * even in most display lists.  
  */
 static void
 _tnl_Rectf( GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2 )
index cb7493c..7cb947a 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: t_imm_dlist.c,v 1.17 2001/05/11 08:11:31 keithw Exp $ */
+/* $Id: t_imm_dlist.c,v 1.18 2001/05/11 15:53:06 keithw Exp $ */
 
 /*
  * Mesa 3-D graphics library
@@ -82,6 +82,13 @@ _tnl_compile_cassette( GLcontext *ctx, struct immediate *IM )
    }
 
    _tnl_compute_orflag( IM, IM->Start );
+
+   /* Need to clear this flag, or fixup gets confused.  (The elements
+    * have been translated away by now.)  
+    */
+   IM->OrFlag &= ~VERT_ELT;    
+   IM->AndFlag &= ~VERT_ELT;   
+
    _tnl_fixup_input( ctx, IM );
 /*     _tnl_print_cassette( IM ); */
 
index 979fc0c..5300585 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: t_imm_fixup.c,v 1.15 2001/05/11 08:11:31 keithw Exp $ */
+/* $Id: t_imm_fixup.c,v 1.16 2001/05/11 15:53:06 keithw Exp $ */
 
 /*
  * Mesa 3-D graphics library
@@ -290,9 +290,9 @@ void _tnl_fixup_input( GLcontext *ctx, struct immediate *IM )
       if (fixup & VERT_RGBA) {
         if (orflag & VERT_RGBA)
            _tnl_fixup_4f( IM->Color, IM->Flag, start, VERT_RGBA );
-/*      else */
-/*         fixup_first_4f( IM->Color, IM->Flag, VERT_END_VB, start,  */
-/*                         IM->Color[start] ); */
+        /* No need for else case as the drivers understand stride
+         * zero here.  (TODO - propogate this)
+         */
       }
       
       if (fixup & VERT_SPEC_RGB) {
index fc4fb95..414c6bd 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: t_vb_render.c,v 1.19 2001/04/28 08:39:18 keithw Exp $ */
+/* $Id: t_vb_render.c,v 1.20 2001/05/11 15:53:06 keithw Exp $ */
 
 /*
  * Mesa 3-D graphics library
@@ -318,7 +318,8 @@ static GLboolean run_render( GLcontext *ctx,
 
 
    tnl->Driver.RenderFinish( ctx );
-/*     usleep(100000); */
+/*     _swrast_flush(ctx); */
+/*     usleep(1000000); */
    return GL_FALSE;            /* finished the pipe */
 }