/** * Execute the buffer and save copied verts. * \param keep_unmapped if true, leave the VBO unmapped when we're done. */ void vbo_exec_vtx_flush(struct vbo_exec_context *exec, GLboolean keepUnmapped) { if (0) vbo_exec_debug_verts(exec); if (exec->vtx.prim_count && exec->vtx.vert_count) { exec->vtx.copied.nr = vbo_copy_vertices(exec); if (exec->vtx.copied.nr != exec->vtx.vert_count) { struct gl_context *ctx = exec->ctx; /* Prepare and set the exec draws internal VAO for drawing. */ vbo_exec_bind_arrays(ctx); if (ctx->NewState) _mesa_update_state(ctx); vbo_exec_vtx_unmap(exec); assert(ctx->NewState == 0); if (0) printf("%s %d %d\n", __func__, exec->vtx.prim_count, exec->vtx.vert_count); ctx->Driver.Draw(ctx, exec->vtx.prim, exec->vtx.prim_count, NULL, GL_TRUE, 0, exec->vtx.vert_count - 1, NULL, 0, NULL); /* Get new storage -- unless asked not to. */ if (!keepUnmapped) vbo_exec_vtx_map(exec); } } /* May have to unmap explicitly if we didn't draw: */ if (keepUnmapped && exec->vtx.buffer_map) { vbo_exec_vtx_unmap(exec); } if (keepUnmapped || exec->vtx.vertex_size == 0) exec->vtx.max_vert = 0; else exec->vtx.max_vert = vbo_compute_max_verts(exec); exec->vtx.buffer_ptr = exec->vtx.buffer_map; exec->vtx.prim_count = 0; exec->vtx.vert_count = 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; } }
/** * Execute the buffer and save copied verts. * \param keep_unmapped if true, leave the VBO unmapped when we're done. */ void vbo_exec_vtx_flush(struct vbo_exec_context *exec, GLboolean keepUnmapped) { if (0) vbo_exec_debug_verts( exec ); if (exec->vtx.prim_count && exec->vtx.vert_count) { exec->vtx.copied.nr = vbo_copy_vertices( exec ); if (exec->vtx.copied.nr != exec->vtx.vert_count) { struct gl_context *ctx = exec->ctx; /* Before the update_state() as this may raise _NEW_VARYING_VP_INPUTS * from _mesa_set_varying_vp_inputs(). */ vbo_exec_bind_arrays( ctx ); if (ctx->NewState) _mesa_update_state( ctx ); if (_mesa_is_bufferobj(exec->vtx.bufferobj)) { vbo_exec_vtx_unmap( exec ); } if (0) printf("%s %d %d\n", __func__, exec->vtx.prim_count, exec->vtx.vert_count); vbo_context(ctx)->draw_prims( ctx, exec->vtx.prim, exec->vtx.prim_count, NULL, GL_TRUE, 0, exec->vtx.vert_count - 1, NULL, 0, NULL); /* If using a real VBO, get new storage -- unless asked not to. */ if (_mesa_is_bufferobj(exec->vtx.bufferobj) && !keepUnmapped) { vbo_exec_vtx_map( exec ); } } } /* May have to unmap explicitly if we didn't draw: */ if (keepUnmapped && _mesa_is_bufferobj(exec->vtx.bufferobj) && exec->vtx.buffer_map) { vbo_exec_vtx_unmap( exec ); } if (keepUnmapped || exec->vtx.vertex_size == 0) exec->vtx.max_vert = 0; else exec->vtx.max_vert = vbo_compute_max_verts(exec); exec->vtx.buffer_ptr = exec->vtx.buffer_map; exec->vtx.prim_count = 0; exec->vtx.vert_count = 0; }