X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;ds=sidebyside;f=src%2Fmesa%2Fvbo%2Fvbo_exec_api.c;h=5e90f3671d7b572d31452e408eae4173474ae287;hb=88b935bb0c0c31523fa34cbec389b8200d91a8c9;hp=6c2d1d2d7dcbe82c1681ff73dd24a1a1037522c7;hpb=1f6e53e2437690de9a84e47f5587ff359b8484f2;p=mesa.git diff --git a/src/mesa/vbo/vbo_exec_api.c b/src/mesa/vbo/vbo_exec_api.c index 6c2d1d2d7dc..5e90f3671d7 100644 --- a/src/mesa/vbo/vbo_exec_api.c +++ b/src/mesa/vbo/vbo_exec_api.c @@ -43,6 +43,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #include "main/draw_validate.h" #include "main/dispatch.h" #include "util/bitscan.h" +#include "util/u_memory.h" #include "vbo_noop.h" #include "vbo_private.h" @@ -230,35 +231,6 @@ vbo_exec_copy_to_current(struct vbo_exec_context *exec) } -/** - * Copy current vertex attribute values into the current vertex. - */ -static void -vbo_exec_copy_from_current(struct vbo_exec_context *exec) -{ - struct gl_context *ctx = exec->ctx; - struct vbo_context *vbo = vbo_context(ctx); - GLint i; - - for (i = VBO_ATTRIB_POS + 1; i < VBO_ATTRIB_MAX; i++) { - if (exec->vtx.attr[i].type == GL_DOUBLE || - exec->vtx.attr[i].type == GL_UNSIGNED_INT64_ARB) { - memcpy(exec->vtx.attrptr[i], vbo->current[i].Ptr, - exec->vtx.attr[i].size * sizeof(GLfloat)); - } else { - const fi_type *current = (fi_type *) vbo->current[i].Ptr; - switch (exec->vtx.attr[i].size) { - case 4: exec->vtx.attrptr[i][3] = current[3]; - case 3: exec->vtx.attrptr[i][2] = current[2]; - case 2: exec->vtx.attrptr[i][1] = current[1]; - case 1: exec->vtx.attrptr[i][0] = current[0]; - break; - } - } - } -} - - /** * Flush existing data, set new attrib size, replay copied vertices. * This is called when we transition from a small vertex attribute size @@ -269,12 +241,13 @@ vbo_exec_copy_from_current(struct vbo_exec_context *exec) */ static void vbo_exec_wrap_upgrade_vertex(struct vbo_exec_context *exec, - GLuint attr, GLuint newSize) + GLuint attr, GLuint newSize, GLenum newType) { 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_no_pos = exec->vtx.vertex_size_no_pos; const GLuint old_vtx_size = exec->vtx.vertex_size; /* floats per vertex */ const GLuint oldSize = exec->vtx.attr[attr].size; GLuint i; @@ -294,16 +267,6 @@ vbo_exec_wrap_upgrade_vertex(struct vbo_exec_context *exec, memcpy(old_attrptr, exec->vtx.attrptr, sizeof(old_attrptr)); } - bool repopulate = unlikely(oldSize) || (attr != 0 && exec->vtx.attr[0].size); - - if (repopulate) { - /* 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. */ @@ -316,6 +279,8 @@ vbo_exec_wrap_upgrade_vertex(struct vbo_exec_context *exec, /* Fix up sizes: */ exec->vtx.attr[attr].size = newSize; + exec->vtx.attr[attr].active_size = newSize; + exec->vtx.attr[attr].type = newType; exec->vtx.vertex_size += newSize - oldSize; exec->vtx.vertex_size_no_pos = exec->vtx.vertex_size - exec->vtx.attr[0].size; exec->vtx.max_vert = vbo_compute_max_verts(exec); @@ -323,34 +288,63 @@ vbo_exec_wrap_upgrade_vertex(struct vbo_exec_context *exec, exec->vtx.buffer_ptr = exec->vtx.buffer_map; exec->vtx.enabled |= BITFIELD64_BIT(attr); - if (repopulate) { - /* Size changed, recalculate all the attrptr[] values - */ - fi_type *tmp = exec->vtx.vertex; + if (attr != 0) { + if (unlikely(oldSize)) { + unsigned offset = exec->vtx.attrptr[attr] - exec->vtx.vertex; + + /* If there are attribs after the resized attrib... */ + if (offset + oldSize < old_vtx_size_no_pos) { + int size_diff = newSize - oldSize; + fi_type *old_first = exec->vtx.attrptr[attr] + oldSize; + fi_type *new_first = exec->vtx.attrptr[attr] + newSize; + fi_type *old_last = exec->vtx.vertex + old_vtx_size_no_pos - 1; + fi_type *new_last = exec->vtx.vertex + exec->vtx.vertex_size_no_pos - 1; + + if (size_diff < 0) { + /* Decreasing the size: Copy from first to last to move + * elements to the left. + */ + fi_type *old_end = old_last + 1; + fi_type *old = old_first; + fi_type *new = new_first; + + do { + *new++ = *old++; + } while (old != old_end); + } else { + /* Increasing the size: Copy from last to first to move + * elements to the right. + */ + fi_type *old_end = old_first - 1; + fi_type *old = old_last; + fi_type *new = new_last; + + do { + *new-- = *old--; + } while (old != old_end); + } - /* Iterate backwards to make the position last, because glVertex - * expects that. - */ - for (int i = VBO_ATTRIB_MAX - 1; i >= 0; i--) { - if (exec->vtx.attr[i].size) { - exec->vtx.attrptr[i] = tmp; - tmp += exec->vtx.attr[i].size; + /* Update pointers to attribs, because we moved them. */ + GLbitfield64 enabled = exec->vtx.enabled & + ~BITFIELD64_BIT(VBO_ATTRIB_POS) & + ~BITFIELD64_BIT(attr); + while (enabled) { + unsigned i = u_bit_scan64(&enabled); + + if (exec->vtx.attrptr[i] > exec->vtx.attrptr[attr]) + exec->vtx.attrptr[i] += size_diff; + } } - else - exec->vtx.attrptr[i] = NULL; /* will not be dereferenced */ + } else { + /* Just have to append the new attribute at the end */ + exec->vtx.attrptr[attr] = exec->vtx.vertex + + exec->vtx.vertex_size_no_pos - newSize; } - - /* 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; } + /* The position is always last. */ + exec->vtx.attrptr[0] = exec->vtx.vertex + exec->vtx.vertex_size_no_pos; + /* Replay stored vertices to translate them * to new format here. * @@ -420,7 +414,7 @@ vbo_exec_fixup_vertex(struct gl_context *ctx, GLuint attr, /* New size is larger. Need to flush existing vertices and get * an enlarged vertex format. */ - vbo_exec_wrap_upgrade_vertex(exec, attr, newSize); + vbo_exec_wrap_upgrade_vertex(exec, attr, newSize, newType); } else if (newSize < exec->vtx.attr[attr].active_size) { GLuint i; @@ -432,17 +426,9 @@ vbo_exec_fixup_vertex(struct gl_context *ctx, GLuint attr, */ for (i = newSize; i <= exec->vtx.attr[attr].size; i++) exec->vtx.attrptr[attr][i-1] = id[i-1]; - } - exec->vtx.attr[attr].active_size = newSize; - exec->vtx.attr[attr].type = newType; - - /* Does setting NeedFlush belong here? Necessitates resetting - * vtxfmt on each flush (otherwise flags won't get reset - * afterwards). - */ - if (attr == 0) - ctx->Driver.NeedFlush |= FLUSH_STORED_VERTICES; + exec->vtx.attr[attr].active_size = newSize; + } } @@ -489,24 +475,33 @@ do { \ \ assert(sz == 1 || sz == 2); \ \ - /* check if attribute size or type is changing */ \ - if (unlikely(exec->vtx.attr[A].active_size != N * sz) || \ - unlikely(exec->vtx.attr[A].type != T)) { \ - vbo_exec_fixup_vertex(ctx, A, N * sz, T); \ - } \ - \ /* store a copy of the attribute in exec except for glVertex */ \ if ((A) != 0) { \ + /* Check if attribute size or type is changing. */ \ + if (unlikely(exec->vtx.attr[A].active_size != N * sz || \ + exec->vtx.attr[A].type != T)) { \ + vbo_exec_fixup_vertex(ctx, A, N * sz, T); \ + } \ + \ C *dest = (C *)exec->vtx.attrptr[A]; \ if (N>0) dest[0] = V0; \ if (N>1) dest[1] = V1; \ if (N>2) dest[2] = V2; \ if (N>3) dest[3] = V3; \ assert(exec->vtx.attr[A].type == T); \ - } \ \ - if ((A) == 0) { \ + /* we now have accumulated a per-vertex attribute */ \ + ctx->Driver.NeedFlush |= FLUSH_UPDATE_CURRENT; \ + } else { \ /* This is a glVertex call */ \ + int size = exec->vtx.attr[0].size; \ + \ + /* Check if attribute size or type is changing. */ \ + if (unlikely(size < N * sz || \ + exec->vtx.attr[0].type != T)) { \ + vbo_exec_wrap_upgrade_vertex(exec, 0, N * sz, T); \ + } \ + \ uint32_t *dst = (uint32_t *)exec->vtx.buffer_ptr; \ uint32_t *src = (uint32_t *)exec->vtx.vertex; \ unsigned vertex_size_no_pos = exec->vtx.vertex_size_no_pos; \ @@ -522,6 +517,12 @@ do { \ if (N > 1) *dst++ = V1; \ if (N > 2) *dst++ = V2; \ if (N > 3) *dst++ = V3; \ + \ + if (unlikely(N < size)) { \ + if (N < 2 && size >= 2) *dst++ = V1; \ + if (N < 3 && size >= 3) *dst++ = V2; \ + if (N < 4 && size >= 4) *dst++ = V3; \ + } \ } else { \ /* 64 bits: dst can be unaligned, so copy each 4-byte word */ \ /* separately */ \ @@ -529,22 +530,22 @@ do { \ if (N > 1) SET_64BIT(dst, V1); \ if (N > 2) SET_64BIT(dst, V2); \ if (N > 3) SET_64BIT(dst, V3); \ + \ + if (unlikely(N * 2 < size)) { \ + if (N < 2 && size >= 4) SET_64BIT(dst, V1); \ + if (N < 3 && size >= 6) SET_64BIT(dst, V2); \ + if (N < 4 && size >= 8) SET_64BIT(dst, V3); \ + } \ } \ \ /* dst now points at the beginning of the next vertex */ \ exec->vtx.buffer_ptr = (fi_type*)dst; \ \ - /* Set FLUSH_STORED_VERTICES to indicate that there's now */ \ - /* something to draw (not just updating a color or texcoord).*/ \ /* Don't set FLUSH_UPDATE_CURRENT because */ \ /* Current.Attrib[VBO_ATTRIB_POS] is never used. */ \ - ctx->Driver.NeedFlush |= FLUSH_STORED_VERTICES; \ \ - if (++exec->vtx.vert_count >= exec->vtx.max_vert) \ + if (unlikely(++exec->vtx.vert_count >= exec->vtx.max_vert)) \ vbo_exec_vtx_wrap(exec); \ - } else { \ - /* we now have accumulated per-vertex attributes */ \ - ctx->Driver.NeedFlush |= FLUSH_UPDATE_CURRENT; \ } \ } while (0) @@ -657,17 +658,36 @@ vbo_exec_Materialfv(GLenum face, GLenum pname, const GLfloat *params) /** * Flush (draw) vertices. + * + * \param flags bitmask of FLUSH_STORED_VERTICES, FLUSH_UPDATE_CURRENT */ static void -vbo_exec_FlushVertices_internal(struct vbo_exec_context *exec) +vbo_exec_FlushVertices_internal(struct vbo_exec_context *exec, unsigned flags) { - if (exec->vtx.vert_count) { - vbo_exec_vtx_flush(exec); - } + struct gl_context *ctx = exec->ctx; - if (exec->vtx.vertex_size) { + if (flags & FLUSH_STORED_VERTICES) { + if (exec->vtx.vert_count) { + vbo_exec_vtx_flush(exec); + } + + if (exec->vtx.vertex_size) { + vbo_exec_copy_to_current(exec); + vbo_reset_all_attr(exec); + } + + /* All done. */ + ctx->Driver.NeedFlush = 0; + } else { + assert(flags == FLUSH_UPDATE_CURRENT); + + /* Note that the vertex size is unchanged. + * (vbo_reset_all_attr isn't called) + */ vbo_exec_copy_to_current(exec); - vbo_reset_all_attr(exec); + + /* Only FLUSH_UPDATE_CURRENT is done. */ + ctx->Driver.NeedFlush = ~FLUSH_UPDATE_CURRENT; } } @@ -799,21 +819,19 @@ vbo_exec_Begin(GLenum mode) /* Heuristic: attempt to isolate attributes occurring outside * begin/end pairs. + * + * Use FLUSH_STORED_VERTICES, because it updates current attribs and + * sets vertex_size to 0. (FLUSH_UPDATE_CURRENT doesn't change vertex_size) */ if (exec->vtx.vertex_size && !exec->vtx.attr[VBO_ATTRIB_POS].size) - vbo_exec_FlushVertices_internal(exec); + vbo_exec_FlushVertices_internal(exec, FLUSH_STORED_VERTICES); i = exec->vtx.prim_count++; exec->vtx.prim[i].mode = mode; exec->vtx.prim[i].begin = 1; exec->vtx.prim[i].end = 0; - exec->vtx.prim[i].indexed = 0; - exec->vtx.prim[i].pad = 0; exec->vtx.prim[i].start = exec->vtx.vert_count; exec->vtx.prim[i].count = 0; - exec->vtx.prim[i].num_instances = 1; - exec->vtx.prim[i].base_instance = 0; - exec->vtx.prim[i].is_indirect = 0; ctx->Driver.CurrentExecPrimitive = mode; @@ -849,14 +867,8 @@ try_vbo_merge(struct vbo_exec_context *exec) struct _mesa_prim *prev = &exec->vtx.prim[exec->vtx.prim_count - 2]; assert(prev == cur - 1); - if (vbo_can_merge_prims(prev, cur)) { - assert(cur->begin); - assert(cur->end); - assert(prev->begin); - assert(prev->end); - vbo_merge_prims(prev, cur); + if (vbo_merge_draws(exec->ctx, false, prev, cur)) exec->vtx.prim_count--; /* drop the last primitive */ - } } } @@ -887,9 +899,13 @@ vbo_exec_End(void) if (exec->vtx.prim_count > 0) { /* close off current primitive */ struct _mesa_prim *last_prim = &exec->vtx.prim[exec->vtx.prim_count - 1]; + unsigned count = exec->vtx.vert_count - last_prim->start; last_prim->end = 1; - last_prim->count = exec->vtx.vert_count - last_prim->start; + last_prim->count = count; + + if (count) + ctx->Driver.NeedFlush |= FLUSH_STORED_VERTICES; /* Special handling for GL_LINE_LOOP */ if (last_prim->mode == GL_LINE_LOOP && last_prim->begin == 0) { @@ -965,67 +981,50 @@ vbo_exec_vtxfmt_init(struct vbo_exec_context *exec) } -/** - * Tell the VBO module to use a real OpenGL vertex buffer object to - * store accumulated immediate-mode vertex data. - * This replaces the malloced buffer which was created in - * vb_exec_vtx_init() below. - */ -void -vbo_use_buffer_objects(struct gl_context *ctx) +static void +vbo_reset_all_attr(struct vbo_exec_context *exec) { - struct vbo_exec_context *exec = &vbo_context(ctx)->exec; - /* Any buffer name but 0 can be used here since this bufferobj won't - * go into the bufferobj hashtable. - */ - GLuint bufName = IMM_BUFFER_NAME; - - /* Make sure this func is only used once */ - assert(exec->vtx.bufferobj == ctx->Shared->NullBufferObj); - - _mesa_align_free(exec->vtx.buffer_map); - exec->vtx.buffer_map = NULL; - exec->vtx.buffer_ptr = NULL; + while (exec->vtx.enabled) { + const int i = u_bit_scan64(&exec->vtx.enabled); - /* Allocate a real buffer object now */ - _mesa_reference_buffer_object(ctx, &exec->vtx.bufferobj, NULL); - exec->vtx.bufferobj = ctx->Driver.NewBufferObject(ctx, bufName); + /* Reset the vertex attribute by setting its size to zero. */ + exec->vtx.attr[i].size = 0; + exec->vtx.attr[i].type = GL_FLOAT; + exec->vtx.attr[i].active_size = 0; + exec->vtx.attrptr[i] = NULL; + } - /* Map the buffer. */ - vbo_exec_vtx_map(exec); - assert(exec->vtx.buffer_ptr); + exec->vtx.vertex_size = 0; } void -vbo_exec_vtx_init(struct vbo_exec_context *exec) +vbo_exec_vtx_init(struct vbo_exec_context *exec, bool use_buffer_objects) { struct gl_context *ctx = exec->ctx; - GLuint i; - /* Allocate a buffer object. Will just reuse this object - * continuously, unless vbo_use_buffer_objects() is called to enable - * use of real VBOs. - */ - _mesa_reference_buffer_object(ctx, - &exec->vtx.bufferobj, - ctx->Shared->NullBufferObj); + if (use_buffer_objects) { + /* Use buffer objects for immediate mode. */ + struct vbo_exec_context *exec = &vbo_context(ctx)->exec; - assert(!exec->vtx.buffer_map); - exec->vtx.buffer_map = _mesa_align_malloc(VBO_VERT_BUFFER_SIZE, 64); - exec->vtx.buffer_ptr = exec->vtx.buffer_map; + exec->vtx.bufferobj = ctx->Driver.NewBufferObject(ctx, IMM_BUFFER_NAME); + + /* Map the buffer. */ + vbo_exec_vtx_map(exec); + assert(exec->vtx.buffer_ptr); + } else { + /* Use allocated memory for immediate mode. */ + exec->vtx.bufferobj = NULL; + exec->vtx.buffer_map = + align_malloc(ctx->Const.glBeginEndBufferSize, 64); + exec->vtx.buffer_ptr = exec->vtx.buffer_map; + } vbo_exec_vtxfmt_init(exec); _mesa_noop_vtxfmt_init(ctx, &exec->vtxfmt_noop); - exec->vtx.enabled = 0; - for (i = 0 ; i < ARRAY_SIZE(exec->vtx.attr); i++) { - exec->vtx.attr[i].size = 0; - exec->vtx.attr[i].type = GL_FLOAT; - exec->vtx.attr[i].active_size = 0; - } - - exec->vtx.vertex_size = 0; + exec->vtx.enabled = u_bit_consecutive64(0, VBO_ATTRIB_MAX); /* reset all */ + vbo_reset_all_attr(exec); } @@ -1038,10 +1037,10 @@ vbo_exec_vtx_destroy(struct vbo_exec_context *exec) /* True VBOs should already be unmapped */ if (exec->vtx.buffer_map) { - assert(exec->vtx.bufferobj->Name == 0 || + assert(!exec->vtx.bufferobj || exec->vtx.bufferobj->Name == IMM_BUFFER_NAME); - if (exec->vtx.bufferobj->Name == 0) { - _mesa_align_free(exec->vtx.buffer_map); + if (!exec->vtx.bufferobj) { + align_free(exec->vtx.buffer_map); exec->vtx.buffer_map = NULL; exec->vtx.buffer_ptr = NULL; } @@ -1049,7 +1048,8 @@ vbo_exec_vtx_destroy(struct vbo_exec_context *exec) /* Free the vertex buffer. Unmap first if needed. */ - if (_mesa_bufferobj_mapped(exec->vtx.bufferobj, MAP_INTERNAL)) { + if (exec->vtx.bufferobj && + _mesa_bufferobj_mapped(exec->vtx.bufferobj, MAP_INTERNAL)) { ctx->Driver.UnmapBuffer(ctx, exec->vtx.bufferobj, MAP_INTERNAL); } _mesa_reference_buffer_object(ctx, &exec->vtx.bufferobj, NULL); @@ -1088,10 +1088,7 @@ vbo_exec_FlushVertices(struct gl_context *ctx, GLuint flags) } /* Flush (draw). */ - vbo_exec_FlushVertices_internal(exec); - - /* Clear the dirty flush flags, because the flush is finished. */ - ctx->Driver.NeedFlush &= ~(FLUSH_UPDATE_CURRENT | flags); + vbo_exec_FlushVertices_internal(exec, flags); #ifndef NDEBUG exec->flush_call_depth--; @@ -1100,30 +1097,6 @@ vbo_exec_FlushVertices(struct gl_context *ctx, GLuint flags) } -/** - * Reset the vertex attribute by setting its size to zero. - */ -static void -vbo_reset_attr(struct vbo_exec_context *exec, GLuint attr) -{ - exec->vtx.attr[attr].size = 0; - exec->vtx.attr[attr].type = GL_FLOAT; - exec->vtx.attr[attr].active_size = 0; -} - - -static void -vbo_reset_all_attr(struct vbo_exec_context *exec) -{ - while (exec->vtx.enabled) { - const int i = u_bit_scan64(&exec->vtx.enabled); - vbo_reset_attr(exec, i); - } - - exec->vtx.vertex_size = 0; -} - - void GLAPIENTRY _es_Color4f(GLfloat r, GLfloat g, GLfloat b, GLfloat a) {