/* Called only when buffers are wrapped as the result of filling the * vertex_store struct. */ static void _save_wrap_filled_vertex( GLcontext *ctx ) { struct vbo_save_context *save = &vbo_context(ctx)->save; GLfloat *data = save->copied.buffer; GLuint i; /* Emit a glEnd to close off the last vertex list. */ _save_wrap_buffers( ctx ); /* Copy stored stored vertices to start of new list. */ assert(save->max_vert - save->vert_count > save->copied.nr); for (i = 0 ; i < save->copied.nr ; i++) { _mesa_memcpy( save->vbptr, data, save->vertex_size * sizeof(GLfloat)); data += save->vertex_size; save->vbptr += save->vertex_size; save->vert_count++; } }
/* Called only when buffers are wrapped as the result of filling the * vertex_store struct. */ static void _save_wrap_filled_vertex( GLcontext *ctx ) { TNLcontext *tnl = TNL_CONTEXT(ctx); GLfloat *data = tnl->save.copied.buffer; GLuint i; /* Emit a glEnd to close off the last vertex list. */ _save_wrap_buffers( ctx ); /* Copy stored stored vertices to start of new list. */ assert(tnl->save.counter > tnl->save.copied.nr); for (i = 0 ; i < tnl->save.copied.nr ; i++) { _mesa_memcpy( tnl->save.vbptr, data, tnl->save.vertex_size * sizeof(GLfloat)); data += tnl->save.vertex_size; tnl->save.vbptr += tnl->save.vertex_size; tnl->save.counter--; } }
/* Flush existing data, set new attrib size, replay copied vertices. */ static void _save_upgrade_vertex( GLcontext *ctx, GLuint attr, GLuint newsz ) { struct vbo_save_context *save = &vbo_context(ctx)->save; GLuint oldsz; GLuint i; GLfloat *tmp; /* Store the current run of vertices, and emit a GL_END. Emit a * BEGIN in the new buffer. */ if (save->vert_count) _save_wrap_buffers( ctx ); else assert( save->copied.nr == 0 ); /* Do a COPY_TO_CURRENT to ensure back-copying works for the case * when the attribute already exists in the vertex and is having * its size increased. */ _save_copy_to_current( ctx ); /* Fix up sizes: */ oldsz = save->attrsz[attr]; save->attrsz[attr] = newsz; save->vertex_size += newsz - oldsz; save->max_vert = ((VBO_SAVE_BUFFER_SIZE - save->vertex_store->used) / save->vertex_size); save->vert_count = 0; /* Recalculate all the attrptr[] values: */ for (i = 0, tmp = save->vertex ; i < VBO_ATTRIB_MAX ; i++) { if (save->attrsz[i]) { save->attrptr[i] = tmp; tmp += save->attrsz[i]; } else save->attrptr[i] = NULL; /* will not be dereferenced. */ } /* Copy from current to repopulate the vertex with correct values. */ _save_copy_from_current( ctx ); /* Replay stored vertices to translate them to new format here. * * If there are copied vertices and the new (upgraded) attribute * has not been defined before, this list is somewhat degenerate, * and will need fixup at runtime. */ if (save->copied.nr) { GLfloat *data = save->copied.buffer; GLfloat *dest = save->buffer; GLuint j; /* Need to note this and fix up at runtime (or loopback): */ if (attr != VBO_ATTRIB_POS && save->currentsz[attr][0] == 0) { assert(oldsz == 0); save->dangling_attr_ref = GL_TRUE; } for (i = 0 ; i < save->copied.nr ; i++) { for (j = 0 ; j < VBO_ATTRIB_MAX ; j++) { if (save->attrsz[j]) { if (j == attr) { if (oldsz) { COPY_CLEAN_4V( dest, oldsz, data ); data += oldsz; dest += newsz; } else { COPY_SZ_4V( dest, newsz, save->current[attr] ); dest += newsz; } } else { GLint sz = save->attrsz[j]; COPY_SZ_4V( dest, sz, data ); data += sz; dest += sz; } } } } save->vbptr = dest; save->vert_count += save->copied.nr; } }
/* Flush existing data, set new attrib size, replay copied vertices. */ static void _save_upgrade_vertex( GLcontext *ctx, GLuint attr, GLuint newsz ) { TNLcontext *tnl = TNL_CONTEXT(ctx); GLuint oldsz; GLuint i; GLfloat *tmp; /* Store the current run of vertices, and emit a GL_END. Emit a * BEGIN in the new buffer. */ if (tnl->save.initial_counter != tnl->save.counter) _save_wrap_buffers( ctx ); else assert( tnl->save.copied.nr == 0 ); /* Do a COPY_TO_CURRENT to ensure back-copying works for the case * when the attribute already exists in the vertex and is having * its size increased. */ _save_copy_to_current( ctx ); /* Fix up sizes: */ oldsz = tnl->save.attrsz[attr]; tnl->save.attrsz[attr] = newsz; tnl->save.vertex_size += newsz - oldsz; tnl->save.counter = ((SAVE_BUFFER_SIZE - tnl->save.vertex_store->used) / tnl->save.vertex_size); if (tnl->save.counter > ctx->Const.MaxArrayLockSize ) tnl->save.counter = ctx->Const.MaxArrayLockSize; tnl->save.initial_counter = tnl->save.counter; /* Recalculate all the attrptr[] values: */ for (i = 0, tmp = tnl->save.vertex ; i < _TNL_ATTRIB_MAX ; i++) { if (tnl->save.attrsz[i]) { tnl->save.attrptr[i] = tmp; tmp += tnl->save.attrsz[i]; } else tnl->save.attrptr[i] = 0; /* will not be dereferenced. */ } /* Copy from current to repopulate the vertex with correct values. */ _save_copy_from_current( ctx ); /* Replay stored vertices to translate them to new format here. * * If there are copied vertices and the new (upgraded) attribute * has not been defined before, this list is somewhat degenerate, * and will need fixup at runtime. */ if (tnl->save.copied.nr) { GLfloat *data = tnl->save.copied.buffer; GLfloat *dest = tnl->save.buffer; GLuint j; /* Need to note this and fix up at runtime (or loopback): */ if (tnl->save.currentsz[attr][0] == 0) { assert(oldsz == 0); tnl->save.dangling_attr_ref = GL_TRUE; _mesa_debug(0, "_save_upgrade_vertex: dangling reference attr %d\n", attr); #if 0 /* The current strategy is to punt these degenerate cases * through _tnl_loopback_vertex_list(), a lower-performance * option. To minimize the impact of this, artificially * reduce the size of this vertex_list. */ if (t->save.counter > 10) { t->save.initial_counter = 10; t->save.counter = 10; } #endif } for (i = 0 ; i < tnl->save.copied.nr ; i++) { for (j = 0 ; j < _TNL_ATTRIB_MAX ; j++) { if (tnl->save.attrsz[j]) { if (j == attr) { if (oldsz) { ASSIGN_4V( dest, 0, 0, 0, 1 ); COPY_SZ_4V( dest, oldsz, data ); data += oldsz; dest += newsz; } else { COPY_SZ_4V( dest, newsz, tnl->save.current[attr] ); dest += newsz; } } else { GLint sz = tnl->save.attrsz[j]; COPY_SZ_4V( dest, sz, data ); data += sz; dest += sz; } } } } tnl->save.vbptr = dest; tnl->save.counter -= tnl->save.copied.nr; } }