vbo: introduce vbo_get_minmax_indices function
authorYuanhan Liu <yuanhan.liu@linux.intel.com>
Sat, 31 Dec 2011 06:22:46 +0000 (14:22 +0800)
committerYuanhan Liu <yuanhan.liu@linux.intel.com>
Thu, 12 Jan 2012 02:47:41 +0000 (10:47 +0800)
Introduce vbo_get_minmax_indices() function to handle the min/max index
computation for nr_prims(>= 1). The old code just compute the first
prim's min/max index; this would results an error rendering if user
called functions like glMultiDrawElements(). This patch servers as
fixing this issue.

As when nr_prims = 1, we can pass 1 to paramter nr_prims, thus I made
vbo_get_minmax_index() static.

v2: per Roland's suggestion, put the indices address compuation into
    vbo_get_minmax_index() instead.

    Also do comination if possible to reduce map/unmap count

v3: per Brian's suggestion, use a pointer for start_prim to avoid
    structure copy per loop.

Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
Reviewed-by: Roland Scheidegger <sroland@vmware.com>
Reviewed-by: Brian Paul <brianp@vmware.com>
src/mesa/drivers/dri/i965/brw_draw.c
src/mesa/drivers/dri/nouveau/nouveau_vbo_t.c
src/mesa/main/api_validate.c
src/mesa/state_tracker/st_draw.c
src/mesa/state_tracker/st_draw_feedback.c
src/mesa/tnl/t_draw.c
src/mesa/vbo/vbo.h
src/mesa/vbo/vbo_exec_array.c

index 621195d02292e0bc2d0c43bf9360ea4965bd072f..f50fffd7ce4a8b010fe899d5c124c292a3c3f6a6 100644 (file)
@@ -586,7 +586,7 @@ void brw_draw_prims( struct gl_context *ctx,
 
    if (!vbo_all_varyings_in_vbos(arrays)) {
       if (!index_bounds_valid)
-        vbo_get_minmax_index(ctx, prim, ib, &min_index, &max_index);
+        vbo_get_minmax_indices(ctx, prim, ib, &min_index, &max_index, nr_prims);
 
       /* Decide if we want to rebase.  If so we end up recursing once
        * only into this function.
index de04d1897c1ca8f8ae16f5cfaf463bac9f0b15a1..59f1542e29379755ad6afe1ef1097f694fb0e063 100644 (file)
@@ -437,7 +437,8 @@ TAG(vbo_render_prims)(struct gl_context *ctx,
        struct nouveau_render_state *render = to_render_state(ctx);
 
        if (!index_bounds_valid)
-               vbo_get_minmax_index(ctx, prims, ib, &min_index, &max_index);
+               vbo_get_minmax_indices(ctx, prims, ib, &min_index, &max_index,
+                                      nr_prims);
 
        vbo_choose_render_mode(ctx, arrays);
        vbo_choose_attrs(ctx, arrays);
index 945f12752d37b5944366995914e4d0b4ec0a442e..b6871d0dbd1492a24a90cc2113def38a4a9c8d61 100644 (file)
@@ -184,7 +184,7 @@ check_index_bounds(struct gl_context *ctx, GLsizei count, GLenum type,
    ib.ptr = indices;
    ib.obj = ctx->Array.ArrayObj->ElementArrayBufferObj;
 
-   vbo_get_minmax_index(ctx, &prim, &ib, &min, &max);
+   vbo_get_minmax_indices(ctx, &prim, &ib, &min, &max, 1);
 
    if ((int)(min + basevertex) < 0 ||
        max + basevertex > ctx->Array.ArrayObj->_MaxElement) {
index 6d6fc858de4633dd81f017cf801a131f7f879313..c0554cfc70a5b664cfc931651d0bdb99416c1129 100644 (file)
@@ -990,7 +990,8 @@ st_draw_vbo(struct gl_context *ctx,
       /* Gallium probably doesn't want this in some cases. */
       if (!index_bounds_valid)
          if (!all_varyings_in_vbos(arrays))
-            vbo_get_minmax_index(ctx, prims, ib, &min_index, &max_index);
+            vbo_get_minmax_indices(ctx, prims, ib, &min_index, &max_index,
+                                   nr_prims);
 
       for (i = 0; i < nr_prims; i++) {
          num_instances = MAX2(num_instances, prims[i].num_instances);
index fbf0349b41bde69538613041df15f866656000d9..a559b733ac207d96ddde9923c14f5c8b1ffe5d6c 100644 (file)
@@ -119,7 +119,7 @@ st_feedback_draw_vbo(struct gl_context *ctx,
    st_validate_state(st);
 
    if (!index_bounds_valid)
-      vbo_get_minmax_index(ctx, prims, ib, &min_index, &max_index);
+      vbo_get_minmax_indices(ctx, prims, ib, &min_index, &max_index, nr_prims);
 
    /* must get these after state validation! */
    vp = st->vp;
index f949c34d3353cb9e81581c86de6321f203d92b39..17042cf8f375a526f026d9e78b525c53881b2a1d 100644 (file)
@@ -418,7 +418,7 @@ void _tnl_vbo_draw_prims(struct gl_context *ctx,
                         struct gl_transform_feedback_object *tfb_vertcount)
 {
    if (!index_bounds_valid)
-      vbo_get_minmax_index(ctx, prim, ib, &min_index, &max_index);
+      vbo_get_minmax_indices(ctx, prim, ib, &min_index, &max_index, nr_prims);
 
    _tnl_draw_prims(ctx, arrays, prim, nr_prims, ib, min_index, max_index);
 }
index ed8fc1722aea5f72fca989dca888cffba044b8c3..bf925ab16f3991b51697391c29b08796982b1da5 100644 (file)
@@ -127,9 +127,9 @@ int
 vbo_sizeof_ib_type(GLenum type);
 
 void
-vbo_get_minmax_index(struct gl_context *ctx, const struct _mesa_prim *prim,
-                    const struct _mesa_index_buffer *ib,
-                    GLuint *min_index, GLuint *max_index);
+vbo_get_minmax_indices(struct gl_context *ctx, const struct _mesa_prim *prim,
+                       const struct _mesa_index_buffer *ib,
+                       GLuint *min_index, GLuint *max_index, GLuint nr_prims);
 
 void vbo_use_buffer_objects(struct gl_context *ctx);
 
index fec49d35e386167a0b1679456dccf3eb19e8d0b6..263e429ace2643b818d4facd556e88cf252adf4e 100644 (file)
@@ -99,24 +99,23 @@ vbo_sizeof_ib_type(GLenum type)
  * If primitive restart is enabled, we need to ignore restart
  * indexes when computing min/max.
  */
-void
+static void
 vbo_get_minmax_index(struct gl_context *ctx,
                     const struct _mesa_prim *prim,
                     const struct _mesa_index_buffer *ib,
-                    GLuint *min_index, GLuint *max_index)
+                    GLuint *min_index, GLuint *max_index,
+                    const GLuint count)
 {
    const GLboolean restart = ctx->Array.PrimitiveRestart;
    const GLuint restartIndex = ctx->Array.RestartIndex;
-   const GLuint count = prim->count;
    const void *indices;
    GLuint i;
 
+   indices = (void *)ib->ptr + prim->start * vbo_sizeof_ib_type(ib->type);
    if (_mesa_is_bufferobj(ib->obj)) {
-      indices = ctx->Driver.MapBufferRange(ctx, (GLsizeiptr) ib->ptr,
-                                           count * vbo_sizeof_ib_type(ib->type),
-                                          GL_MAP_READ_BIT, ib->obj);
-   } else {
-      indices = ib->ptr;
+      GLsizeiptr size = MIN2(count * vbo_sizeof_ib_type(ib->type), ib->obj->Size);
+      indices = ctx->Driver.MapBufferRange(ctx, (GLsizeiptr) indices, size,
+                                           GL_MAP_READ_BIT, ib->obj);
    }
 
    switch (ib->type) {
@@ -196,6 +195,41 @@ vbo_get_minmax_index(struct gl_context *ctx,
    }
 }
 
+/**
+ * Compute min and max elements for nr_prims
+ */
+void
+vbo_get_minmax_indices(struct gl_context *ctx,
+                       const struct _mesa_prim *prims,
+                       const struct _mesa_index_buffer *ib,
+                       GLuint *min_index,
+                       GLuint *max_index,
+                       GLuint nr_prims)
+{
+   GLuint tmp_min, tmp_max;
+   GLuint i;
+   GLuint count;
+
+   *min_index = ~0;
+   *max_index = 0;
+
+   for (i = 0; i < nr_prims; i++) {
+      const struct _mesa_prim *start_prim;
+
+      start_prim = &prims[i];
+      count = start_prim->count;
+      /* Do combination if possible to reduce map/unmap count */
+      while ((i + 1 < nr_prims) &&
+             (prims[i].start + prims[i].count == prims[i+1].start)) {
+         count += prims[i+1].count;
+         i++;
+      }
+      vbo_get_minmax_index(ctx, start_prim, ib, &tmp_min, &tmp_max, count);
+      *min_index = MIN2(*min_index, tmp_min);
+      *max_index = MAX2(*max_index, tmp_max);
+   }
+}
+
 
 /**
  * Check that element 'j' of the array has reasonable data.