/* Insert the active immediate struct onto the display list currently
 * being built.
 */
static void _save_compile_vertex_list( GLcontext *ctx )
{
   struct vbo_save_context *save = &vbo_context(ctx)->save;
   struct vbo_save_vertex_list *node;

   /* Allocate space for this structure in the display list currently
    * being compiled.
    */
   node = (struct vbo_save_vertex_list *)
      _mesa_alloc_instruction(ctx, save->opcode_vertex_list, sizeof(*node));

   if (!node)
      return;

   /* Duplicate our template, increment refcounts to the storage structs:
    */
   _mesa_memcpy(node->attrsz, save->attrsz, sizeof(node->attrsz)); 
   node->vertex_size = save->vertex_size;
   node->buffer_offset = (save->buffer - save->vertex_store->buffer) * sizeof(GLfloat); 
   node->count = save->vert_count;
   node->wrap_count = save->copied.nr;
   node->dangling_attr_ref = save->dangling_attr_ref;
   node->prim = save->prim;
   node->prim_count = save->prim_count;
   node->vertex_store = save->vertex_store;
   node->prim_store = save->prim_store;

   node->vertex_store->refcount++;
   node->prim_store->refcount++;

   assert(node->attrsz[VBO_ATTRIB_POS] != 0 ||
	  node->count == 0);

   if (save->dangling_attr_ref)
      ctx->ListState.CurrentList->flags |= MESA_DLIST_DANGLING_REFS;

   save->vertex_store->used += save->vertex_size * node->count;
   save->prim_store->used += node->prim_count;


   /* Copy duplicated vertices 
    */
   save->copied.nr = _save_copy_vertices( ctx, node, save->buffer );


   /* Deal with GL_COMPILE_AND_EXECUTE:
    */
   if (ctx->ExecuteFlag) {
      struct _glapi_table *dispatch = GET_DISPATCH();

      _glapi_set_dispatch(ctx->Exec);

      vbo_loopback_vertex_list( ctx,
				(const GLfloat *)((const char *)save->vertex_store->buffer + 
						  node->buffer_offset),
				node->attrsz,
				node->prim,
				node->prim_count,
				node->wrap_count,
				node->vertex_size);

      _glapi_set_dispatch(dispatch);
   }


   /* Decide whether the storage structs are full, or can be used for
    * the next vertex lists as well.
    */
   if (save->vertex_store->used > 
       VBO_SAVE_BUFFER_SIZE - 16 * (save->vertex_size + 4)) {

      /* Unmap old store:
       */
      unmap_vertex_store( ctx, save->vertex_store );

      /* Release old reference:
       */
      save->vertex_store->refcount--; 
      assert(save->vertex_store->refcount != 0);
      save->vertex_store = NULL;

      /* Allocate and map new store:
       */
      save->vertex_store = alloc_vertex_store( ctx );
      save->vbptr = map_vertex_store( ctx, save->vertex_store );
   } 

   if (save->prim_store->used > VBO_SAVE_PRIM_SIZE - 6) {
      save->prim_store->refcount--; 
      assert(save->prim_store->refcount != 0);
      save->prim_store = alloc_prim_store( ctx );
   } 

   /* Reset our structures for the next run of vertices:
    */
   _save_reset_counters( ctx );
}
/* Insert the active immediate struct onto the display list currently
 * being built.
 */
static void _save_compile_vertex_list( GLcontext *ctx )
{
   TNLcontext *tnl = TNL_CONTEXT(ctx);
   struct tnl_vertex_list *node;

   /* Allocate space for this structure in the display list currently
    * being compiled.
    */
   node = (struct tnl_vertex_list *)
      _mesa_alloc_instruction(ctx, tnl->save.opcode_vertex_list, sizeof(*node));

   if (!node)
      return;

   /* Duplicate our template, increment refcounts to the storage structs:
    */
   _mesa_memcpy(node->attrsz, tnl->save.attrsz, sizeof(node->attrsz));
   node->vertex_size = tnl->save.vertex_size;
   node->buffer = tnl->save.buffer;
   node->wrap_count = tnl->save.copied.nr;
   node->count = tnl->save.initial_counter - tnl->save.counter;
   node->prim = tnl->save.prim;
   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++;
   node->prim_store->refcount++;

   assert(node->attrsz[_TNL_ATTRIB_POS] != 0 ||
	  node->count == 0);

   /* Maybe calculate normal lengths:
    */
   if (tnl->CalcDListNormalLengths && 
       node->attrsz[_TNL_ATTRIB_NORMAL] == 3 &&
       !node->dangling_attr_ref)
      build_normal_lengths( node );

   tnl->save.vertex_store->used += tnl->save.vertex_size * node->count;
   tnl->save.prim_store->used += node->prim_count;

   /* Decide whether the storage structs are full, or can be used for
    * the next vertex lists as well.
    */
   if (tnl->save.vertex_store->used > 
       SAVE_BUFFER_SIZE - 16 * (tnl->save.vertex_size + 4)) {

      tnl->save.vertex_store->refcount--; 
      assert(tnl->save.vertex_store->refcount != 0);
      tnl->save.vertex_store = alloc_vertex_store( ctx );
      tnl->save.vbptr = tnl->save.vertex_store->buffer;
   } 

   if (tnl->save.prim_store->used > SAVE_PRIM_SIZE - 6) {
      tnl->save.prim_store->refcount--; 
      assert(tnl->save.prim_store->refcount != 0);
      tnl->save.prim_store = alloc_prim_store( ctx );
   } 

   /* Reset our structures for the next run of vertices:
    */
   _save_reset_counters( ctx );

   /* Copy duplicated vertices 
    */
   tnl->save.copied.nr = _save_copy_vertices( ctx, node );


   /* Deal with GL_COMPILE_AND_EXECUTE:
    */
   if (ctx->ExecuteFlag) {
      _tnl_playback_vertex_list( ctx, (void *) node );
   }
}