vbo: remove dead code in vbo_can_merge_prims
[mesa.git] / src / mesa / vbo / vbo_exec_api.c
index 6c2d1d2d7dcbe82c1681ff73dd24a1a1037522c7..698663d48f5bd9c463abb64e2fc8ad7b286a5c42 100644 (file)
@@ -230,35 +230,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
@@ -275,6 +246,7 @@ vbo_exec_wrap_upgrade_vertex(struct vbo_exec_context *exec,
    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 +266,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.
     */
@@ -323,34 +285,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.
     *
@@ -490,8 +481,8 @@ 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)) {                         \
+   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);                         \
    }                                                                    \
                                                                         \
@@ -534,13 +525,10 @@ do {                                                                    \
       /* 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 */               \
@@ -657,17 +645,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 +806,22 @@ 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;
 
@@ -887,9 +895,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 +977,52 @@ 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);
 
-   vbo_exec_vtxfmt_init(exec);
-   _mesa_noop_vtxfmt_init(ctx, &exec->vtxfmt_noop);
+      /* Map the buffer. */
+      vbo_exec_vtx_map(exec);
+      assert(exec->vtx.buffer_ptr);
+   } else {
+      /* Use allocated memory for immediate mode. */
+      _mesa_reference_buffer_object(ctx,
+                                    &exec->vtx.bufferobj,
+                                    ctx->Shared->NullBufferObj);
 
-   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.buffer_map = _mesa_align_malloc(VBO_VERT_BUFFER_SIZE, 64);
+      exec->vtx.buffer_ptr = exec->vtx.buffer_map;
    }
 
-   exec->vtx.vertex_size = 0;
+   vbo_exec_vtxfmt_init(exec);
+   _mesa_noop_vtxfmt_init(ctx, &exec->vtxfmt_noop);
+
+   exec->vtx.enabled = u_bit_consecutive64(0, VBO_ATTRIB_MAX); /* reset all */
+   vbo_reset_all_attr(exec);
 }
 
 
@@ -1088,10 +1085,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 +1094,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)
 {