gallium,util: Pull u_indices and u_primconvert back into gallium
[platform/upstream/mesa.git] / src / mesa / vbo / vbo_save_api.c
index e3e7b0d..a41d518 100644 (file)
@@ -110,21 +110,20 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "main/macros.h"
 #include "main/draw_validate.h"
 #include "main/api_arrayelt.h"
-#include "main/vtxfmt.h"
 #include "main/dispatch.h"
 #include "main/state.h"
 #include "main/varray.h"
 #include "util/bitscan.h"
 #include "util/u_memory.h"
 #include "util/hash_table.h"
-#include "util/indices/u_indices.h"
+#include "gallium/auxiliary/indices/u_indices.h"
+#include "util/u_prim.h"
 
 #include "gallium/include/pipe/p_state.h"
 
-#include "vbo_noop.h"
 #include "vbo_private.h"
-
-#include "state_tracker/st_cb_bufferobjects.h"
+#include "api_exec_decl.h"
+#include "api_save.h"
 
 #ifdef ERROR
 #undef ERROR
@@ -142,14 +141,6 @@ _save_EvalCoord1f(GLfloat u);
 static void GLAPIENTRY
 _save_EvalCoord2f(GLfloat u, GLfloat v);
 
-static void
-handle_out_of_memory(struct gl_context *ctx)
-{
-   struct vbo_save_context *save = &vbo_context(ctx)->save;
-   _mesa_noop_vtxfmt_init(ctx, &save->vtxfmt);
-   save->out_of_memory = true;
-}
-
 /*
  * NOTE: Old 'parity' issue is gone, but copying can still be
  * wrong-footed on replay.
@@ -426,9 +417,8 @@ grow_vertex_storage(struct gl_context *ctx, int vertex_count)
       save->vertex_store->buffer_in_ram = realloc(save->vertex_store->buffer_in_ram,
                                                   save->vertex_store->buffer_in_ram_size);
       if (save->vertex_store->buffer_in_ram == NULL)
-         handle_out_of_memory(ctx);
+         save->out_of_memory = true;
    }
-
 }
 
 struct vertex_key {
@@ -568,7 +558,7 @@ compile_vertex_list(struct gl_context *ctx)
                    current_size * sizeof(GLfloat));
          } else {
             _mesa_error(ctx, GL_OUT_OF_MEMORY, "Current value allocation");
-            handle_out_of_memory(ctx);
+            save->out_of_memory = true;
          }
       }
    }
@@ -610,10 +600,8 @@ compile_vertex_list(struct gl_context *ctx)
    /* converting primitive types may result in many more indices */
    bool all_prims_supported = (ctx->Const.DriverSupportedPrimMask & BITFIELD_MASK(PIPE_PRIM_MAX)) == BITFIELD_MASK(PIPE_PRIM_MAX);
    int max_index_count = total_vert_count * (all_prims_supported ? 2 : 3);
-
-   int size = max_index_count * sizeof(uint32_t);
-   uint32_t* indices = (uint32_t*) malloc(size);
-   void *tmp_indices = all_prims_supported ? NULL : malloc(size);
+   uint32_t* indices = (uint32_t*) malloc(max_index_count * sizeof(uint32_t));
+   void *tmp_indices = all_prims_supported ? NULL : malloc(max_index_count * sizeof(uint32_t));
    struct _mesa_prim *merged_prims = NULL;
 
    int idx = 0;
@@ -643,6 +631,13 @@ compile_vertex_list(struct gl_context *ctx)
          continue;
       }
 
+      /* Increase indices storage if the original estimation was too small. */
+      if (idx + 3 * vertex_count > max_index_count) {
+         max_index_count = max_index_count + 3 * vertex_count;
+         indices = (uint32_t*) realloc(indices, max_index_count * sizeof(uint32_t));
+         tmp_indices = all_prims_supported ? NULL : realloc(tmp_indices, max_index_count * sizeof(uint32_t));
+      }
+
       /* Line strips may get converted to lines */
       if (mode == GL_LINE_STRIP)
          mode = GL_LINES;
@@ -656,12 +651,11 @@ compile_vertex_list(struct gl_context *ctx)
                            PV_LAST, PV_LAST,
                            &pmode, &index_size, &new_count,
                            &trans_func);
-         if (new_count > 0) {
+         if (new_count > 0)
             trans_func(original_prims[i].start, new_count, tmp_indices);
-            vertex_count = new_count;
-            mode = (GLubyte)pmode;
-            converted_prim = true;
-         }
+         vertex_count = new_count;
+         mode = (GLubyte)pmode;
+         converted_prim = true;
       }
 
       /* If 2 consecutive prims use the same mode => merge them. */
@@ -731,6 +725,18 @@ compile_vertex_list(struct gl_context *ctx)
                                         temp_vertices_buffer, &max_index);
          }
       }
+
+      /* Duplicate the last vertex for incomplete primitives */
+      if (vertex_count > 0) {
+         unsigned min_vert = u_prim_vertex_count(mode)->min;
+         for (unsigned j = vertex_count; j < min_vert; j++) {
+            indices[idx++] = add_vertex(save, vertex_to_index,
+                                       converted_prim ? CAST_INDEX(tmp_indices, index_size, vertex_count - 1) :
+                                                         original_prims[i].start + vertex_count - 1,
+                                       temp_vertices_buffer, &max_index);
+         }
+      }
+
 #undef CAST_INDEX
       if (merge_prims) {
          /* Update vertex count. */
@@ -745,9 +751,10 @@ compile_vertex_list(struct gl_context *ctx)
          merged_prims[last_valid_prim].count = idx - start;
       }
       merged_prims[last_valid_prim].mode = mode;
-   }
 
-   assert(idx > 0 && idx <= max_index_count);
+      /* converted prims will filter incomplete primitives and may have no indices */
+      assert((idx > 0 || converted_prim) && idx <= max_index_count);
+   }
 
    unsigned merged_prim_count = last_valid_prim + 1;
    node->cold->ib.ptr = NULL;
@@ -777,18 +784,18 @@ compile_vertex_list(struct gl_context *ctx)
    if (total_bytes_needed > available_bytes) {
       if (save->current_bo)
          _mesa_reference_buffer_object(ctx, &save->current_bo, NULL);
-      save->current_bo = st_bufferobj_alloc(ctx, VBO_BUF_ID + 1);
-      bool success = st_bufferobj_data(ctx,
-                                       GL_ELEMENT_ARRAY_BUFFER_ARB,
-                                       MAX2(total_bytes_needed, VBO_SAVE_BUFFER_SIZE),
-                                       NULL,
-                                       GL_STATIC_DRAW_ARB, GL_MAP_WRITE_BIT |
-                                       MESA_GALLIUM_VERTEX_STATE_STORAGE,
-                                       save->current_bo);
+      save->current_bo = _mesa_bufferobj_alloc(ctx, VBO_BUF_ID + 1);
+      bool success = _mesa_bufferobj_data(ctx,
+                                          GL_ELEMENT_ARRAY_BUFFER_ARB,
+                                          MAX2(total_bytes_needed, VBO_SAVE_BUFFER_SIZE),
+                                          NULL,
+                                          GL_STATIC_DRAW_ARB, GL_MAP_WRITE_BIT |
+                                          MESA_GALLIUM_VERTEX_STATE_STORAGE,
+                                          save->current_bo);
       if (!success) {
          _mesa_reference_buffer_object(ctx, &save->current_bo, NULL);
          _mesa_error(ctx, GL_OUT_OF_MEMORY, "IB allocation");
-         handle_out_of_memory(ctx);
+         save->out_of_memory = true;
       } else {
          save->current_bo_bytes_used = 0;
          available_bytes = save->current_bo->Size;
@@ -833,33 +840,36 @@ compile_vertex_list(struct gl_context *ctx)
    _mesa_reference_buffer_object(ctx, &node->cold->ib.obj, save->current_bo);
 
    /* Upload the vertices first (see buffer_offset) */
-   st_bufferobj_subdata(ctx,
-                        save->current_bo_bytes_used,
-                        total_vert_count * save->vertex_size * sizeof(fi_type),
-                        vertex_to_index ? temp_vertices_buffer : save->vertex_store->buffer_in_ram,
-                        node->cold->ib.obj);
+   _mesa_bufferobj_subdata(ctx,
+                           save->current_bo_bytes_used,
+                           total_vert_count * save->vertex_size * sizeof(fi_type),
+                           vertex_to_index ? temp_vertices_buffer : save->vertex_store->buffer_in_ram,
+                           node->cold->ib.obj);
    save->current_bo_bytes_used += total_vert_count * save->vertex_size * sizeof(fi_type);
+   node->cold->bo_bytes_used = save->current_bo_bytes_used;
 
   if (vertex_to_index) {
       _mesa_hash_table_destroy(vertex_to_index, _free_entry);
       free(temp_vertices_buffer);
    }
 
-   /* Since we're append the indices to an existing buffer, we need to adjust the start value of each
+   /* Since we append the indices to an existing buffer, we need to adjust the start value of each
     * primitive (not the indices themselves). */
-   save->current_bo_bytes_used += align(save->current_bo_bytes_used, 4) - save->current_bo_bytes_used;
-   int indices_offset = save->current_bo_bytes_used / 4;
-   for (int i = 0; i < merged_prim_count; i++) {
-      merged_prims[i].start += indices_offset;
+   if (!ctx->ListState.Current.UseLoopback) {
+      save->current_bo_bytes_used += align(save->current_bo_bytes_used, 4) - save->current_bo_bytes_used;
+      int indices_offset = save->current_bo_bytes_used / 4;
+      for (int i = 0; i < merged_prim_count; i++) {
+         merged_prims[i].start += indices_offset;
+      }
    }
 
    /* Then upload the indices. */
    if (node->cold->ib.obj) {
-      st_bufferobj_subdata(ctx,
-                           save->current_bo_bytes_used,
-                           idx * sizeof(uint32_t),
-                           indices,
-                           node->cold->ib.obj);
+      _mesa_bufferobj_subdata(ctx,
+                              save->current_bo_bytes_used,
+                              idx * sizeof(uint32_t),
+                              indices,
+                              node->cold->ib.obj);
       save->current_bo_bytes_used += idx * sizeof(uint32_t);
    } else {
       node->cold->vertex_count = 0;
@@ -910,16 +920,16 @@ end:
    node->draw_begins = node->cold->prims[0].begin;
 
    if (!save->current_bo) {
-      save->current_bo = st_bufferobj_alloc(ctx, VBO_BUF_ID + 1);
-      bool success = st_bufferobj_data(ctx,
-                                       GL_ELEMENT_ARRAY_BUFFER_ARB,
-                                       VBO_SAVE_BUFFER_SIZE,
-                                       NULL,
-                                       GL_STATIC_DRAW_ARB, GL_MAP_WRITE_BIT |
-                                       MESA_GALLIUM_VERTEX_STATE_STORAGE,
-                                       save->current_bo);
+      save->current_bo = _mesa_bufferobj_alloc(ctx, VBO_BUF_ID + 1);
+      bool success = _mesa_bufferobj_data(ctx,
+                                          GL_ELEMENT_ARRAY_BUFFER_ARB,
+                                          VBO_SAVE_BUFFER_SIZE,
+                                          NULL,
+                                          GL_STATIC_DRAW_ARB, GL_MAP_WRITE_BIT |
+                                          MESA_GALLIUM_VERTEX_STATE_STORAGE,
+                                          save->current_bo);
       if (!success)
-         handle_out_of_memory(ctx);
+         save->out_of_memory = true;
    }
 
    GLuint offsets[VBO_ATTRIB_MAX];
@@ -962,29 +972,19 @@ end:
    /* Deal with GL_COMPILE_AND_EXECUTE:
     */
    if (ctx->ExecuteFlag) {
-      struct _glapi_table *dispatch = GET_DISPATCH();
-
-      _glapi_set_dispatch(ctx->Exec);
-
       /* _vbo_loopback_vertex_list doesn't use the index buffer, so we have to
-       * use buffer_in_ram instead of current_bo which contains all vertices instead
-       * of the deduplicated vertices only in the !UseLoopback case.
+       * use buffer_in_ram (which contains all vertices) instead of current_bo
+       * (which contains deduplicated vertices *when* UseLoopback is false).
        *
        * The problem is that the VAO offset is based on current_bo's layout,
        * so we have to use a temp value.
        */
       struct gl_vertex_array_object *vao = node->cold->VAO[VP_MODE_SHADER];
       GLintptr original = vao->BufferBinding[0].Offset;
-      if (!ctx->ListState.Current.UseLoopback) {
-         GLintptr new_offset = 0;
-         /* 'start_offset' has been added to all primitives 'start', so undo it here. */
-         new_offset -= start_offset * stride;
-         vao->BufferBinding[0].Offset = new_offset;
-      }
+      /* 'start_offset' has been added to all primitives 'start', so undo it here. */
+      vao->BufferBinding[0].Offset = -(GLintptr)(start_offset * stride);
       _vbo_loopback_vertex_list(ctx, node, save->vertex_store->buffer_in_ram);
       vao->BufferBinding[0].Offset = original;
-
-      _glapi_set_dispatch(dispatch);
    }
 
    /* Reset our structures for the next run of vertices:
@@ -1407,6 +1407,10 @@ _save_Materialfv(GLenum face, GLenum pname, const GLfloat *params)
 }
 
 
+static void
+vbo_init_dispatch_save_begin_end(struct gl_context *ctx);
+
+
 /* Cope with EvalCoord/CallList called within a begin/end object:
  *     -- Flush current buffer
  *     -- Fallback to opcodes for the rest of the begin/end object.
@@ -1438,10 +1442,10 @@ dlist_fallback(struct gl_context *ctx)
    copy_to_current(ctx);
    reset_vertex(ctx);
    if (save->out_of_memory) {
-      _mesa_install_save_vtxfmt(ctx, &save->vtxfmt);
+      vbo_install_save_vtxfmt_noop(ctx);
    }
    else {
-      _mesa_install_save_vtxfmt(ctx, &ctx->ListState.ListVtxfmt);
+      _mesa_init_dispatch_save_begin_end(ctx);
    }
    ctx->Driver.SaveNeedFlush = GL_FALSE;
 }
@@ -1537,7 +1541,7 @@ vbo_save_NotifyBegin(struct gl_context *ctx, GLenum mode,
 
    save->no_current_update = no_current_update;
 
-   _mesa_install_save_vtxfmt(ctx, &save->vtxfmt);
+   vbo_init_dispatch_save_begin_end(ctx);
 
    /* We need to call vbo_save_SaveFlushVertices() if there's state change */
    ctx->Driver.SaveNeedFlush = GL_TRUE;
@@ -1560,10 +1564,10 @@ _save_End(void)
     * as opcodes.
     */
    if (save->out_of_memory) {
-      _mesa_install_save_vtxfmt(ctx, &save->vtxfmt);
+      vbo_install_save_vtxfmt_noop(ctx);
    }
    else {
-      _mesa_install_save_vtxfmt(ctx, &ctx->ListState.ListVtxfmt);
+      _mesa_init_dispatch_save_begin_end(ctx);
    }
 }
 
@@ -1601,11 +1605,6 @@ _save_PrimitiveRestartNV(void)
 }
 
 
-/* Unlike the functions above, these are to be hooked into the vtxfmt
- * maintained in ctx->ListState, active when the list is known or
- * suspected to be outside any begin/end primitive.
- * Note: OBE = Outside Begin/End
- */
 void GLAPIENTRY
 save_Rectf(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2)
 {
@@ -1622,12 +1621,6 @@ save_Rectf(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2)
 
 
 void GLAPIENTRY
-save_Rectd(GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2)
-{
-   save_Rectf((GLfloat) x1, (GLfloat) y1, (GLfloat) x2, (GLfloat) y2);
-}
-
-void GLAPIENTRY
 save_Rectdv(const GLdouble *v1, const GLdouble *v2)
 {
    save_Rectf((GLfloat) v1[0], (GLfloat) v1[1], (GLfloat) v2[0], (GLfloat) v2[1]);
@@ -1871,10 +1864,25 @@ save_DrawRangeElements(GLenum mode, GLuint start, GLuint end,
    save_DrawElements(mode, count, type, indices);
 }
 
+void GLAPIENTRY
+save_DrawRangeElementsBaseVertex(GLenum mode, GLuint start, GLuint end,
+                                 GLsizei count, GLenum type,
+                                 const GLvoid *indices, GLint basevertex)
+{
+   GET_CURRENT_CONTEXT(ctx);
+
+   if (end < start) {
+      _mesa_compile_error(ctx, GL_INVALID_VALUE,
+                          "glDrawRangeElementsBaseVertex(end < start)");
+      return;
+   }
+
+   save_DrawElementsBaseVertex(mode, count, type, indices, basevertex);
+}
 
 void GLAPIENTRY
-save_MultiDrawElementsEXT(GLenum mode, const GLsizei *count, GLenum type,
-                           const GLvoid * const *indices, GLsizei primcount)
+save_MultiDrawElements(GLenum mode, const GLsizei *count, GLenum type,
+                       const GLvoid * const *indices, GLsizei primcount)
 {
    GET_CURRENT_CONTEXT(ctx);
    struct _glapi_table *dispatch = ctx->CurrentServerDispatch;
@@ -1922,17 +1930,15 @@ save_MultiDrawElementsBaseVertex(GLenum mode, const GLsizei *count,
 
 
 static void
-vtxfmt_init(struct gl_context *ctx)
+vbo_init_dispatch_save_begin_end(struct gl_context *ctx)
 {
-   struct vbo_save_context *save = &vbo_context(ctx)->save;
-   GLvertexformat *vfmt = &save->vtxfmt;
-
-#define NAME_AE(x) _ae_##x
+#define NAME_AE(x) _mesa_##x
 #define NAME_CALLLIST(x) _save_##x
 #define NAME(x) _save_##x
-#define NAME_ES(x) _save_##x##ARB
+#define NAME_ES(x) _save_##x
 
-#include "vbo_init_tmp.h"
+   struct _glapi_table *tab = ctx->Save;
+   #include "api_beginend_init.h"
 }
 
 
@@ -2005,7 +2011,7 @@ vbo_save_EndList(struct gl_context *ctx)
        * etc. received between here and the next begin will be compiled
        * as opcodes.
        */
-      _mesa_install_save_vtxfmt(ctx, &ctx->ListState.ListVtxfmt);
+      _mesa_init_dispatch_save_begin_end(ctx);
    }
 
    assert(save->vertex_size == 0);
@@ -2044,6 +2050,5 @@ vbo_save_api_init(struct vbo_save_context *save)
 {
    struct gl_context *ctx = gl_context_from_vbo_save(save);
 
-   vtxfmt_init(ctx);
    current_init(ctx);
 }