/* 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 ); } }
/* 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(struct gl_context *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_dlist_alloc(ctx, save->opcode_vertex_list, sizeof(*node)); if (!node) return; /* Duplicate our template, increment refcounts to the storage structs: */ 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++; if (node->prim[0].no_current_update) { node->current_size = 0; node->current_data = NULL; } else { node->current_size = node->vertex_size - node->attrsz[0]; node->current_data = NULL; if (node->current_size) { /* If the malloc fails, we just pull the data out of the VBO * later instead. */ node->current_data = MALLOC(node->current_size * sizeof(GLfloat)); if (node->current_data) { const char *buffer = (const char *) save->vertex_store->buffer; unsigned attr_offset = node->attrsz[0] * sizeof(GLfloat); unsigned vertex_offset = 0; if (node->count) vertex_offset = (node->count - 1) * node->vertex_size * sizeof(GLfloat); memcpy(node->current_data, buffer + node->buffer_offset + vertex_offset + attr_offset, node->current_size * sizeof(GLfloat)); } } } assert(node->attrsz[VBO_ATTRIB_POS] != 0 || node->count == 0); if (save->dangling_attr_ref) ctx->ListState.CurrentList->Flags |= 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: */ vbo_save_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->buffer_ptr = vbo_save_map_vertex_store(ctx, save->vertex_store); save->out_of_memory = save->buffer_ptr == NULL; } 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); }