Determine ahead of time whether a display list will include vertices
authorKeith Whitwell <keith@tungstengraphics.com>
Sat, 22 Jan 2005 14:38:00 +0000 (14:38 +0000)
committerKeith Whitwell <keith@tungstengraphics.com>
Sat, 22 Jan 2005 14:38:00 +0000 (14:38 +0000)
which have to be processed in the 'loopback' path.  If so, send
all vertices that way as the transition from playback->loopback has
several problems.

src/mesa/main/dd.h
src/mesa/main/dlist.c
src/mesa/main/mtypes.h
src/mesa/tnl/t_context.h
src/mesa/tnl/t_save_api.c
src/mesa/tnl/t_save_api.h
src/mesa/tnl/t_save_playback.c

index f7f7eacf060c516ab183082109986fa041fc20ac..def550109cb3bd9f862f865d6badabf31daaf6e0 100644 (file)
@@ -34,6 +34,7 @@
 /* THIS FILE ONLY INCLUDED BY mtypes.h !!!!! */
 
 struct gl_pixelstore_attrib;
+struct mesa_display_list;
 
 /**
  * Device driver function table.
@@ -886,12 +887,12 @@ struct dd_function_table {
    void (*EndList)( GLcontext *ctx );
 
    /**
-    * Called by glCallList(s), but not recursively.
+    * Called by glCallList(s).
     *
     * Notify the T&L component before and after calling a display list.
-    * Called by glCallList(s), but not recursively.
     */
-   void (*BeginCallList)( GLcontext *ctx, GLuint list );
+   void (*BeginCallList)( GLcontext *ctx, 
+                         struct mesa_display_list *dlist );
    /**
     * Called by glEndCallList().
     *
index beacf5b1f9956390fc3d5d57fc11f44eae6d2465..f95e8db98cb6491b995a5f71ad8cf8f1dcdc9f39 100644 (file)
@@ -412,11 +412,13 @@ void mesa_print_display_list( GLuint list );
  * Make an empty display list.  This is used by glGenLists() to
  * reserver display list IDs.
  */
-static Node *make_empty_list( void )
+static struct mesa_display_list *make_list( GLuint list, GLuint count )
 {
-   Node *n = (Node *) MALLOC( sizeof(Node) );
-   n[0].opcode = OPCODE_END_OF_LIST;
-   return n;
+   struct mesa_display_list *dlist = CALLOC_STRUCT( mesa_display_list );
+   dlist->id = list;
+   dlist->node = (Node *) MALLOC( sizeof(Node) * count );
+   dlist->node[0].opcode = OPCODE_END_OF_LIST;
+   return dlist;
 }
 
 
@@ -427,14 +429,18 @@ static Node *make_empty_list( void )
  */
 void _mesa_destroy_list( GLcontext *ctx, GLuint list )
 {
+   struct mesa_display_list *dlist;
    Node *n, *block;
    GLboolean done;
 
    if (list==0)
       return;
 
-   block = (Node *) _mesa_HashLookup(ctx->Shared->DisplayList, list);
-   n = block;
+   dlist = (struct mesa_display_list *) _mesa_HashLookup(ctx->Shared->DisplayList, list);
+   if (!dlist)
+      return;
+   
+   n = block = dlist->node;
 
    done = block ? GL_FALSE : GL_TRUE;
    while (!done) {
@@ -572,6 +578,7 @@ void _mesa_destroy_list( GLcontext *ctx, GLuint list )
       }
    }
 
+   FREE( dlist );
    _mesa_HashRemove(ctx->Shared->DisplayList, list);
 }
 
@@ -5637,18 +5644,29 @@ islist(GLcontext *ctx, GLuint list)
 static void GLAPIENTRY
 execute_list( GLcontext *ctx, GLuint list )
 {
+   struct mesa_display_list *dlist;
    Node *n;
    GLboolean done;
 
    if (list == 0 || !islist(ctx,list))
       return;
 
-   if (ctx->Driver.BeginCallList)
-      ctx->Driver.BeginCallList( ctx, list );
+   if (ctx->ListState.CallDepth == MAX_LIST_NESTING) {
+      /* raise an error? */
+      return;
+   }
 
-   ctx->ListState.CallDepth++;
 
-   n = (Node *) _mesa_HashLookup(ctx->Shared->DisplayList, list);
+   dlist = (struct mesa_display_list *) _mesa_HashLookup(ctx->Shared->DisplayList, list);
+   if (!dlist)
+      return;
+
+   ctx->ListState.CallStack[ctx->ListState.CallDepth++] = dlist;
+
+   if (ctx->Driver.BeginCallList)
+      ctx->Driver.BeginCallList( ctx, dlist );
+
+   n = dlist->node;
 
    done = GL_FALSE;
    while (!done) {
@@ -6501,10 +6519,11 @@ execute_list( GLcontext *ctx, GLuint list )
         }
       }
    }
-   ctx->ListState.CallDepth--;
 
    if (ctx->Driver.EndCallList)
       ctx->Driver.EndCallList( ctx );
+
+   ctx->ListState.CallStack[ctx->ListState.CallDepth--] = NULL;
 }
 
 
@@ -6583,7 +6602,7 @@ _mesa_GenLists(GLsizei range )
       /* reserve the list IDs by with empty/dummy lists */
       GLint i;
       for (i=0; i<range; i++) {
-         _mesa_HashInsert(ctx->Shared->DisplayList, base+i, make_empty_list());
+         _mesa_HashInsert(ctx->Shared->DisplayList, base+i, make_list(base+i, 1));
       }
    }
 
@@ -6631,7 +6650,8 @@ _mesa_NewList( GLuint list, GLenum mode )
 
    /* Allocate new display list */
    ctx->ListState.CurrentListNum = list;
-   ctx->ListState.CurrentBlock = (Node *) CALLOC( sizeof(Node) * BLOCK_SIZE );
+   ctx->ListState.CurrentList = make_list( list, BLOCK_SIZE );
+   ctx->ListState.CurrentBlock = ctx->ListState.CurrentList->node;
    ctx->ListState.CurrentListPtr = ctx->ListState.CurrentBlock;
    ctx->ListState.CurrentPos = 0;
 
@@ -6679,19 +6699,20 @@ _mesa_EndList( void )
    /* Destroy old list, if any */
    _mesa_destroy_list(ctx, ctx->ListState.CurrentListNum);
    /* Install the list */
-   _mesa_HashInsert(ctx->Shared->DisplayList, ctx->ListState.CurrentListNum, ctx->ListState.CurrentListPtr);
+   _mesa_HashInsert(ctx->Shared->DisplayList, ctx->ListState.CurrentListNum, ctx->ListState.CurrentList);
 
 
    if (MESA_VERBOSE & VERBOSE_DISPLAY_LIST)
       mesa_print_display_list(ctx->ListState.CurrentListNum);
 
+   ctx->Driver.EndList( ctx );
+
+   ctx->ListState.CurrentList = NULL;
    ctx->ListState.CurrentListNum = 0;
    ctx->ListState.CurrentListPtr = NULL;
    ctx->ExecuteFlag = GL_TRUE;
    ctx->CompileFlag = GL_FALSE;
 
-   ctx->Driver.EndList( ctx );
-
    ctx->CurrentDispatch = ctx->Exec;
    _glapi_set_dispatch( ctx->CurrentDispatch );
 }
@@ -8032,6 +8053,7 @@ static const char *enum_string( GLenum k )
  */
 static void GLAPIENTRY print_list( GLcontext *ctx, GLuint list )
 {
+   struct mesa_display_list *dlist;
    Node *n;
    GLboolean done;
 
@@ -8040,8 +8062,12 @@ static void GLAPIENTRY print_list( GLcontext *ctx, GLuint list )
       return;
    }
 
-   n = (Node *) _mesa_HashLookup(ctx->Shared->DisplayList, list);
+   dlist = (struct mesa_display_list *) _mesa_HashLookup(ctx->Shared->DisplayList, list);
+   if (!dlist)
+      return;
 
+   n = dlist->node;
+   
    _mesa_printf("START-LIST %u, address %p\n", list, (void*)n );
 
    done = n ? GL_FALSE : GL_TRUE;
index ed6e6b02b36e3f1e2d305a44ff90a8629c1ccc95..dc3dcbba1a2bf2d0792980394bfa10c530f37413 100644 (file)
@@ -2428,17 +2428,38 @@ struct gl_tnl_module
    /*@}*/
 };
 
+/* Strictly this is a tnl/ private concept, but it doesn't seem
+ * worthwhile adding a tnl private structure just to hold this one bit
+ * of information:
+ */
+#define MESA_DLIST_DANGLING_REFS     0x1 
+
+/* Provide a location where information about a display list can be
+ * collected.  Could be extended with driverPrivate structures,
+ * etc. in the future.
+ */
+struct mesa_display_list
+{
+   Node *node;
+   GLuint id;
+   GLuint flags;
+};
+
 
 /**
  * State used during display list compilation and execution.
  */
 struct mesa_list_state
 {
+   struct mesa_display_list *CallStack[MAX_LIST_NESTING];
    GLuint CallDepth;           /**< Current recursion calling depth */
+
+   struct mesa_display_list *CurrentList;
    Node *CurrentListPtr;       /**< Head of list being compiled */
    GLuint CurrentListNum;      /**< Number of the list being compiled */
    Node *CurrentBlock;         /**< Pointer to current block of nodes */
    GLuint CurrentPos;          /**< Index into current block of nodes */
+
    GLvertexformat ListVtxfmt;
 
    GLubyte ActiveAttribSize[VERT_ATTRIB_MAX];
index 2d99c8576f0eef98cf4bc56cc95bf53f57e89391..56fc2013dc366f5d5e5eb4b95e89c6c2c27954c8 100644 (file)
@@ -364,6 +364,7 @@ struct tnl_save {
    GLfloat *buffer;
    GLuint count;
    GLuint wrap_count;
+   GLuint replay_flags;
 
    struct tnl_prim *prim;
    GLuint prim_count, prim_max;
index 81b68f77beaef57d08983e8ebd9de1857e9b41cd..6e737f400f45a0d151b1e80592cf75ee3de67f17 100644 (file)
@@ -248,7 +248,6 @@ static void _save_compile_vertex_list( GLcontext *ctx )
    node->prim_count = tnl->save.prim_count;
    node->vertex_store = tnl->save.vertex_store;
    node->prim_store = tnl->save.prim_store;
-   node->dangling_attr_ref = tnl->save.dangling_attr_ref;
    node->normal_lengths = 0;
 
    node->vertex_store->refcount++;
@@ -257,13 +256,17 @@ static void _save_compile_vertex_list( GLcontext *ctx )
    assert(node->attrsz[_TNL_ATTRIB_POS] != 0 ||
          node->count == 0);
 
+   if (tnl->save.dangling_attr_ref)
+      ctx->ListState.CurrentList->flags |= MESA_DLIST_DANGLING_REFS;
+
    /* Maybe calculate normal lengths:
     */
    if (tnl->CalcDListNormalLengths && 
        node->attrsz[_TNL_ATTRIB_NORMAL] == 3 &&
-       !node->dangling_attr_ref)
+       !(ctx->ListState.CurrentList->flags & MESA_DLIST_DANGLING_REFS))
       build_normal_lengths( node );
 
+
    tnl->save.vertex_store->used += tnl->save.vertex_size * node->count;
    tnl->save.prim_store->used += node->prim_count;
 
@@ -1189,8 +1192,6 @@ static void GLAPIENTRY _save_Indexfv( const GLfloat *f )
 do {                                                                   \
    TNLcontext *tnl = TNL_CONTEXT(ctx);                                 \
                                                                        \
-   /*fprintf(stderr, "fallback %s inside begin/end\n", __FUNCTION__);*/        \
-                                                                       \
    if (tnl->save.initial_counter != tnl->save.counter ||               \
        tnl->save.prim_count)                                           \
       _save_compile_vertex_list( ctx );                                        \
@@ -1577,14 +1578,19 @@ void _tnl_EndList( GLcontext *ctx )
    assert(TNL_CONTEXT(ctx)->save.vertex_size == 0);
 }
  
-void _tnl_BeginCallList( GLcontext *ctx, GLuint list )
+void _tnl_BeginCallList( GLcontext *ctx, struct mesa_display_list *dlist )
 {
-   (void) ctx; (void) list;
+   TNLcontext *tnl = TNL_CONTEXT(ctx);
+   tnl->save.replay_flags |= dlist->flags;
+   tnl->save.replay_flags |= tnl->LoopbackDListCassettes;
 }
 
 void _tnl_EndCallList( GLcontext *ctx )
 {
-   (void) ctx;
+   TNLcontext *tnl = TNL_CONTEXT(ctx);
+   
+   if (ctx->ListState.CallDepth == 1)
+      tnl->save.replay_flags = 0;
 }
 
 
index eec2d685b00c70036eaf636f056440b9b5230600..8ffb7f573310ee55d16eea3d1f3a4acd5b9068e2 100644 (file)
@@ -43,7 +43,7 @@ extern void _tnl_EndList( GLcontext *ctx );
 extern void _tnl_NewList( GLcontext *ctx, GLuint list, GLenum mode );
 
 extern void _tnl_EndCallList( GLcontext *ctx );
-extern void _tnl_BeginCallList( GLcontext *ctx, GLuint list );
+extern void _tnl_BeginCallList( GLcontext *ctx, struct mesa_display_list *list );
 
 extern void _tnl_SaveFlushVertices( GLcontext *ctx );
 
index 26c77bd7d8e8311a6d1746eeec8fcfbea6f5594c..d5fcbe6c02a732d3822ad58defdfdca9e153cbf9 100644 (file)
@@ -178,7 +178,7 @@ void _tnl_playback_vertex_list( GLcontext *ctx, void *data )
    if (node->prim_count > 0 && node->count > 0) {
 
       if (ctx->Driver.CurrentExecPrimitive != PRIM_OUTSIDE_BEGIN_END &&
-              (node->prim[0].mode & PRIM_BEGIN)) {
+         (node->prim[0].mode & PRIM_BEGIN)) {
 
         /* Degenerate case: list is called inside begin/end pair and
          * includes operations such as glBegin or glDrawArrays.
@@ -187,10 +187,9 @@ void _tnl_playback_vertex_list( GLcontext *ctx, void *data )
         _tnl_loopback_vertex_list( ctx, node );
         return;
       }
-      else if (tnl->LoopbackDListCassettes ||
-              node->dangling_attr_ref) {
-        /* Degenerate case: list references current data and would
-         * require fixup.  Take the easier option & loop it back.
+      else if (tnl->save.replay_flags) {
+        /* Various degnerate cases: translate into immediate mode
+         * calls rather than trying to execute in place.
          */
         _tnl_loopback_vertex_list( ctx, node );
         return;