/** * Deal with buffer wrapping where provoked by the vertex buffer * filling up, as opposed to upgrade_vertex(). */ static void vbo_exec_vtx_wrap(struct vbo_exec_context *exec) { unsigned numComponents; /* Run pipeline on current vertices, copy wrapped vertices * to exec->vtx.copied. */ vbo_exec_wrap_buffers( exec ); if (!exec->vtx.buffer_ptr) { /* probably ran out of memory earlier when allocating the VBO */ return; } /* Copy stored stored vertices to start of new list. */ assert(exec->vtx.max_vert - exec->vtx.vert_count > exec->vtx.copied.nr); numComponents = exec->vtx.copied.nr * exec->vtx.vertex_size; memcpy(exec->vtx.buffer_ptr, exec->vtx.copied.buffer, numComponents * sizeof(fi_type)); exec->vtx.buffer_ptr += numComponents; exec->vtx.vert_count += exec->vtx.copied.nr; exec->vtx.copied.nr = 0; }
/** * Deal with buffer wrapping where provoked by the vertex buffer * filling up, as opposed to upgrade_vertex(). */ void vbo_exec_vtx_wrap( struct vbo_exec_context *exec ) { GLfloat *data = exec->vtx.copied.buffer; GLuint i; /* Run pipeline on current vertices, copy wrapped vertices * to exec->vtx.copied. */ vbo_exec_wrap_buffers( exec ); if (!exec->vtx.buffer_ptr) { /* probably ran out of memory earlier when allocating the VBO */ return; } /* Copy stored stored vertices to start of new list. */ assert(exec->vtx.max_vert - exec->vtx.vert_count > exec->vtx.copied.nr); for (i = 0 ; i < exec->vtx.copied.nr ; i++) { memcpy( exec->vtx.buffer_ptr, data, exec->vtx.vertex_size * sizeof(GLfloat)); exec->vtx.buffer_ptr += exec->vtx.vertex_size; data += exec->vtx.vertex_size; exec->vtx.vert_count++; } exec->vtx.copied.nr = 0; }
/** * Deal with buffer wrapping where provoked by the vertex buffer * filling up, as opposed to upgrade_vertex(). */ void vbo_exec_vtx_wrap( struct vbo_exec_context *exec ) { GLfloat *data = exec->vtx.copied.buffer; GLuint i; /* Run pipeline on current vertices, copy wrapped vertices * to exec->vtx.copied. */ vbo_exec_wrap_buffers( exec ); /* Copy stored stored vertices to start of new list. */ assert(exec->vtx.max_vert - exec->vtx.vert_count > exec->vtx.copied.nr); for (i = 0 ; i < exec->vtx.copied.nr ; i++) { memcpy( exec->vtx.buffer_ptr, data, exec->vtx.vertex_size * sizeof(GLfloat)); exec->vtx.buffer_ptr += exec->vtx.vertex_size; data += exec->vtx.vertex_size; exec->vtx.vert_count++; } exec->vtx.copied.nr = 0; }
/** * Flush existing data, set new attrib size, replay copied vertices. * This is called when we transition from a small vertex attribute size * to a larger one. Ex: glTexCoord2f -> glTexCoord4f. * We need to go back over the previous 2-component texcoords and insert * zero and one values. */ static void vbo_exec_wrap_upgrade_vertex(struct vbo_exec_context *exec, GLuint attr, GLuint newSize ) { struct gl_context *ctx = exec->ctx; struct vbo_context *vbo = vbo_context(ctx); const GLint lastcount = exec->vtx.vert_count; fi_type *old_attrptr[VBO_ATTRIB_MAX]; const GLuint old_vtx_size = exec->vtx.vertex_size; /* floats per vertex */ const GLuint oldSize = exec->vtx.attrsz[attr]; GLuint i; /* Run pipeline on current vertices, copy wrapped vertices * to exec->vtx.copied. */ vbo_exec_wrap_buffers( exec ); if (unlikely(exec->vtx.copied.nr)) { /* We're in the middle of a primitive, keep the old vertex * format around to be able to translate the copied vertices to * the new format. */ memcpy(old_attrptr, exec->vtx.attrptr, sizeof(old_attrptr)); } if (unlikely(oldSize)) { /* 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. */ vbo_exec_copy_to_current( exec ); } /* Heuristic: Attempt to isolate attributes received outside * begin/end so that they don't bloat the vertices. */ if (!_mesa_inside_begin_end(ctx) && !oldSize && lastcount > 8 && exec->vtx.vertex_size) { vbo_exec_copy_to_current( exec ); reset_attrfv( exec ); } /* Fix up sizes: */ exec->vtx.attrsz[attr] = newSize; exec->vtx.vertex_size += newSize - oldSize; exec->vtx.max_vert = vbo_compute_max_verts(exec); exec->vtx.vert_count = 0; exec->vtx.buffer_ptr = exec->vtx.buffer_map; exec->vtx.enabled |= BITFIELD64_BIT(attr); if (unlikely(oldSize)) { /* Size changed, recalculate all the attrptr[] values */ fi_type *tmp = exec->vtx.vertex; for (i = 0 ; i < VBO_ATTRIB_MAX ; i++) { if (exec->vtx.attrsz[i]) { exec->vtx.attrptr[i] = tmp; tmp += exec->vtx.attrsz[i]; } else exec->vtx.attrptr[i] = NULL; /* will not be dereferenced */ } /* Copy from current to repopulate the vertex with correct * values. */ vbo_exec_copy_from_current( exec ); } else { /* Just have to append the new attribute at the end */ exec->vtx.attrptr[attr] = exec->vtx.vertex + exec->vtx.vertex_size - newSize; } /* Replay stored vertices to translate them * to new format here. * * -- No need to replay - just copy piecewise */ if (unlikely(exec->vtx.copied.nr)) { fi_type *data = exec->vtx.copied.buffer; fi_type *dest = exec->vtx.buffer_ptr; assert(exec->vtx.buffer_ptr == exec->vtx.buffer_map); for (i = 0 ; i < exec->vtx.copied.nr ; i++) { GLbitfield64 enabled = exec->vtx.enabled; while (enabled) { const int j = u_bit_scan64(&enabled); GLuint sz = exec->vtx.attrsz[j]; GLint old_offset = old_attrptr[j] - exec->vtx.vertex; GLint new_offset = exec->vtx.attrptr[j] - exec->vtx.vertex; assert(sz); if (j == attr) { if (oldSize) { fi_type tmp[4]; COPY_CLEAN_4V_TYPE_AS_UNION(tmp, oldSize, data + old_offset, exec->vtx.attrtype[j]); COPY_SZ_4V(dest + new_offset, newSize, tmp); } else { fi_type *current = (fi_type *)vbo->currval[j].Ptr; COPY_SZ_4V(dest + new_offset, sz, current); } } else { COPY_SZ_4V(dest + new_offset, sz, data + old_offset); } } data += old_vtx_size; dest += exec->vtx.vertex_size; } exec->vtx.buffer_ptr = dest; exec->vtx.vert_count += exec->vtx.copied.nr; exec->vtx.copied.nr = 0; } }
/** * Flush existing data, set new attrib size, replay copied vertices. * This is called when we transition from a small vertex attribute size * to a larger one. Ex: glTexCoord2f -> glTexCoord4f. * We need to go back over the previous 2-component texcoords and insert * zero and one values. */ static void vbo_exec_wrap_upgrade_vertex(struct vbo_exec_context *exec, GLuint attr, GLuint newSize ) { struct gl_context *ctx = exec->ctx; struct vbo_context *vbo = vbo_context(ctx); const GLint lastcount = exec->vtx.vert_count; GLfloat *old_attrptr[VBO_ATTRIB_MAX]; const GLuint old_vtx_size = exec->vtx.vertex_size; /* floats per vertex */ const GLuint oldSize = exec->vtx.attrsz[attr]; GLuint i; /* Run pipeline on current vertices, copy wrapped vertices * to exec->vtx.copied. */ vbo_exec_wrap_buffers( exec ); if (unlikely(exec->vtx.copied.nr)) { /* We're in the middle of a primitive, keep the old vertex * format around to be able to translate the copied vertices to * the new format. */ memcpy(old_attrptr, exec->vtx.attrptr, sizeof(old_attrptr)); } if (unlikely(oldSize)) { /* 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. */ vbo_exec_copy_to_current( exec ); } /* Heuristic: Attempt to isolate attributes received outside * begin/end so that they don't bloat the vertices. */ if (ctx->Driver.CurrentExecPrimitive == PRIM_OUTSIDE_BEGIN_END && !oldSize && lastcount > 8 && exec->vtx.vertex_size) { vbo_exec_copy_to_current( exec ); reset_attrfv( exec ); } /* Fix up sizes: */ exec->vtx.attrsz[attr] = newSize; exec->vtx.vertex_size += newSize - oldSize; exec->vtx.max_vert = ((VBO_VERT_BUFFER_SIZE - exec->vtx.buffer_used) / (exec->vtx.vertex_size * sizeof(GLfloat))); exec->vtx.vert_count = 0; exec->vtx.buffer_ptr = exec->vtx.buffer_map; if (unlikely(oldSize)) { /* Size changed, recalculate all the attrptr[] values */ GLfloat *tmp = exec->vtx.vertex; for (i = 0 ; i < VBO_ATTRIB_MAX ; i++) { if (exec->vtx.attrsz[i]) { exec->vtx.attrptr[i] = tmp; tmp += exec->vtx.attrsz[i]; } else exec->vtx.attrptr[i] = NULL; /* will not be dereferenced */ } /* Copy from current to repopulate the vertex with correct * values. */ vbo_exec_copy_from_current( exec ); } else { /* Just have to append the new attribute at the end */ exec->vtx.attrptr[attr] = exec->vtx.vertex + exec->vtx.vertex_size - newSize; } /* Replay stored vertices to translate them * to new format here. * * -- No need to replay - just copy piecewise */ if (unlikely(exec->vtx.copied.nr)) { GLfloat *data = exec->vtx.copied.buffer; GLfloat *dest = exec->vtx.buffer_ptr; GLuint j; assert(exec->vtx.buffer_ptr == exec->vtx.buffer_map); for (i = 0 ; i < exec->vtx.copied.nr ; i++) { for (j = 0 ; j < VBO_ATTRIB_MAX ; j++) { GLuint sz = exec->vtx.attrsz[j]; if (sz) { GLint old_offset = old_attrptr[j] - exec->vtx.vertex; GLint new_offset = exec->vtx.attrptr[j] - exec->vtx.vertex; if (j == attr) { if (oldSize) { GLfloat tmp[4]; COPY_CLEAN_4V(tmp, oldSize, data + old_offset); COPY_SZ_4V(dest + new_offset, newSize, tmp); } else { GLfloat *current = (GLfloat *)vbo->currval[j].Ptr; COPY_SZ_4V(dest + new_offset, sz, current); } } else { COPY_SZ_4V(dest + new_offset, sz, data + old_offset); } } } data += old_vtx_size; dest += exec->vtx.vertex_size; } exec->vtx.buffer_ptr = dest; exec->vtx.vert_count += exec->vtx.copied.nr; exec->vtx.copied.nr = 0; } }
/** * Flush existing data, set new attrib size, replay copied vertices. */ static void vbo_exec_wrap_upgrade_vertex( struct vbo_exec_context *exec, GLuint attr, GLuint newsz ) { GLcontext *ctx = exec->ctx; struct vbo_context *vbo = vbo_context(ctx); GLint lastcount = exec->vtx.vert_count; GLfloat *tmp; GLuint oldsz; GLuint i; /* Run pipeline on current vertices, copy wrapped vertices * to exec->vtx.copied. */ vbo_exec_wrap_buffers( exec ); /* 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. */ vbo_exec_copy_to_current( exec ); /* Heuristic: Attempt to isolate attributes received outside * begin/end so that they don't bloat the vertices. */ if (ctx->Driver.CurrentExecPrimitive == PRIM_OUTSIDE_BEGIN_END && exec->vtx.attrsz[attr] == 0 && lastcount > 8 && exec->vtx.vertex_size) { reset_attrfv( exec ); } /* Fix up sizes: */ oldsz = exec->vtx.attrsz[attr]; exec->vtx.attrsz[attr] = newsz; exec->vtx.vertex_size += newsz - oldsz; exec->vtx.max_vert = ((VBO_VERT_BUFFER_SIZE - exec->vtx.buffer_used) / (exec->vtx.vertex_size * sizeof(GLfloat))); exec->vtx.vert_count = 0; exec->vtx.buffer_ptr = exec->vtx.buffer_map; /* Recalculate all the attrptr[] values */ for (i = 0, tmp = exec->vtx.vertex ; i < VBO_ATTRIB_MAX ; i++) { if (exec->vtx.attrsz[i]) { exec->vtx.attrptr[i] = tmp; tmp += exec->vtx.attrsz[i]; } else exec->vtx.attrptr[i] = NULL; /* will not be dereferenced */ } /* Copy from current to repopulate the vertex with correct values. */ vbo_exec_copy_from_current( exec ); /* Replay stored vertices to translate them * to new format here. * * -- No need to replay - just copy piecewise */ if (exec->vtx.copied.nr) { GLfloat *data = exec->vtx.copied.buffer; GLfloat *dest = exec->vtx.buffer_ptr; GLuint j; assert(exec->vtx.buffer_ptr == exec->vtx.buffer_map); for (i = 0 ; i < exec->vtx.copied.nr ; i++) { for (j = 0 ; j < VBO_ATTRIB_MAX ; j++) { if (exec->vtx.attrsz[j]) { if (j == attr) { if (oldsz) { COPY_CLEAN_4V( dest, oldsz, data ); data += oldsz; dest += newsz; } else { const GLfloat *current = (const GLfloat *)vbo->currval[j].Ptr; COPY_SZ_4V( dest, newsz, current ); dest += newsz; } } else { GLuint sz = exec->vtx.attrsz[j]; COPY_SZ_4V( dest, sz, data ); dest += sz; data += sz; } } } } exec->vtx.buffer_ptr = dest; exec->vtx.vert_count += exec->vtx.copied.nr; exec->vtx.copied.nr = 0; } }