mesa: Rename "arrayObj" local variables to "vao".
[mesa.git] / src / mesa / vbo / vbo_split_inplace.c
index 266bc56c8269b3770ddd3c4ccc2c62e0cea14722..5887b74d8298cb832fa38cd9a6a12cfefe47cb97 100644 (file)
@@ -1,7 +1,6 @@
 
 /*
  * Mesa 3-D graphics library
- * Version:  6.5
  *
  * Copyright (C) 1999-2006  Brian Paul   All Rights Reserved.
  *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
  *
  * Authors:
- *    Keith Whitwell <keith@tungstengraphics.com>
+ *    Keith Whitwell <keithw@vmware.com>
  */
 
 
 #include "main/mtypes.h"
 #include "main/macros.h"
 #include "main/enums.h"
+#include "main/glformats.h"
 #include "vbo_split.h"
 
 
 #define MAX_PRIM 32
 
-/* Used for splitting without copying.
+/* Used for splitting without copying. No attempt is made to handle
+ * too large indexed vertex buffers: In general you need to copy to do
+ * that.
  */
 struct split_context {
-   GLcontext *ctx;
+   struct gl_context *ctx;
    const struct gl_client_array **array;
    const struct _mesa_prim *prim;
    GLuint nr_prims;
@@ -48,6 +51,7 @@ struct split_context {
    vbo_draw_func draw;
 
    const struct split_limits *limits;
+   GLuint limit;
 
    struct _mesa_prim dstprim[MAX_PRIM];
    GLuint dstprim_nr;
@@ -58,37 +62,46 @@ struct split_context {
 
 static void flush_vertex( struct split_context *split )
 {
-   GLuint min_index, max_index;
+   struct gl_context *ctx = split->ctx;
+   const struct gl_client_array **saved_arrays = ctx->Array._DrawArrays;
+   struct _mesa_index_buffer ib;
+   GLuint i;
 
    if (!split->dstprim_nr) 
       return;
 
-   GLuint i;
-   min_index = split->dstprim[0].start;
-   max_index = min_index + split->dstprim[0].count - 1;
-
-   for (i = 1; i < split->dstprim_nr; i++) {
-      GLuint tmp_min = split->dstprim[i].start;
-      GLuint tmp_max = tmp_min + split->dstprim[i].count - 1;
+   if (split->ib) {
+      ib = *split->ib;
 
-      if (tmp_min < min_index)
-        min_index = tmp_min;
+      ib.count = split->max_index - split->min_index + 1;
+      ib.ptr = (const void *)((const char *)ib.ptr + 
+                              split->min_index * _mesa_sizeof_type(ib.type));
 
-      if (tmp_max > max_index)
-        max_index = tmp_max;
+      /* Rebase the primitives to save index buffer entries. */
+      for (i = 0; i < split->dstprim_nr; i++)
+        split->dstprim[i].start -= split->min_index;
    }
 
-   assert(max_index >= min_index);
+   assert(split->max_index >= split->min_index);
+
+   ctx->Array._DrawArrays = split->array;
+   ctx->NewDriverState |= ctx->DriverFlags.NewArray;
 
-   split->draw( split->ctx, 
-               split->array, 
-               split->dstprim,
-               split->dstprim_nr,
-               NULL,
-               min_index,
-               max_index);
+   split->draw(ctx,
+              split->dstprim,
+              split->dstprim_nr,
+              split->ib ? &ib : NULL,
+              !split->ib,
+              split->min_index,
+              split->max_index,
+              NULL, NULL);
+
+   ctx->Array._DrawArrays = saved_arrays;
+   ctx->NewDriverState |= ctx->DriverFlags.NewArray;
 
    split->dstprim_nr = 0;
+   split->min_index = ~0;
+   split->max_index = 0;
 }
 
 
@@ -105,84 +118,90 @@ static struct _mesa_prim *next_outprim( struct split_context *split )
    }
 }
 
-static int align(int value, int alignment)
+static void update_index_bounds(struct split_context *split,
+                               const struct _mesa_prim *prim)
 {
-   return (value + alignment - 1) & ~(alignment - 1);
+   split->min_index = MIN2(split->min_index, prim->start);
+   split->max_index = MAX2(split->max_index, prim->start + prim->count - 1);
 }
 
-
+/* Return the maximum amount of vertices that can be emitted for a
+ * primitive starting at 'prim->start', depending on the previous
+ * index bounds.
+ */
+static GLuint get_max_vertices(struct split_context *split,
+                              const struct _mesa_prim *prim)
+{
+   if ((prim->start > split->min_index &&
+       prim->start - split->min_index >= split->limit) ||
+       (prim->start < split->max_index &&
+        split->max_index - prim->start >= split->limit))
+      /* "prim" starts too far away from the old range. */
+      return 0;
+
+   return MIN2(split->min_index, prim->start) + split->limit - prim->start;
+}
 
 /* Break large primitives into smaller ones.  If not possible, convert
  * the primitive to indexed and pass to split_elts().
  */
 static void split_prims( struct split_context *split) 
 {
-   GLuint csr = 0;
    GLuint i;
 
    for (i = 0; i < split->nr_prims; i++) {
       const struct _mesa_prim *prim = &split->prim[i];
       GLuint first, incr;
       GLboolean split_inplace = split_prim_inplace(prim->mode, &first, &incr);
-      GLuint count;
-
-      /* Always wrap on an even numbered vertex to avoid problems with
-       * triangle strips.  
-       */
-      GLuint available = align(split->limits->max_verts - csr - 1, 2); 
-      assert(split->limits->max_verts >= csr);
+      GLuint available = get_max_vertices(split, prim);
+      GLuint count = prim->count - (prim->count - first) % incr;
 
       if (prim->count < first)
         continue;
-      
-      count = prim->count - (prim->count - first) % incr; 
-
 
-      if ((available < count && !split_inplace) || 
+      if ((available < count && !split_inplace) ||
          (available < first && split_inplace)) {
         flush_vertex(split);
-        csr = 0;
-        available = align(split->limits->max_verts - csr - 1, 2);
+        available = get_max_vertices(split, prim);
       }
       
       if (available >= count) {
         struct _mesa_prim *outprim = next_outprim(split);
+
         *outprim = *prim;
-        csr += prim->count;
-        available = align(split->limits->max_verts - csr - 1, 2); 
-      } 
+        update_index_bounds(split, outprim);
+      }
       else if (split_inplace) {
         GLuint j, nr;
 
-
         for (j = 0 ; j < count ; ) {
            GLuint remaining = count - j;
            struct _mesa_prim *outprim = next_outprim(split);
 
            nr = MIN2( available, remaining );
-           
            nr -= (nr - first) % incr;
-           
+
            outprim->mode = prim->mode;
            outprim->begin = (j == 0 && prim->begin);
            outprim->end = (nr == remaining && prim->end);
            outprim->start = prim->start + j;
            outprim->count = nr;
-           
+            outprim->num_instances = prim->num_instances;
+            outprim->base_instance = prim->base_instance;
+
+           update_index_bounds(split, outprim);
+
            if (nr == remaining) {
               /* Finished. 
                */
-              j += nr;         
-              csr += nr;
-              available = align(split->limits->max_verts - csr - 1, 2); 
+              j += nr;
            }
            else {
               /* Wrapped the primitive: 
                */
               j += nr - (first - incr);
               flush_vertex(split);
-              csr = 0;
-              available = align(split->limits->max_verts - csr - 1, 2); 
+              available = get_max_vertices(split, prim);
            }
         }
       }
@@ -207,11 +226,13 @@ static void split_prims( struct split_context *split)
         ib.type = GL_UNSIGNED_INT;
         ib.obj = split->ctx->Shared->NullBufferObj;
         ib.ptr = elts;
-           
+
         tmpprim = *prim;
         tmpprim.indexed = 1;
         tmpprim.start = 0;
         tmpprim.count = count;
+         tmpprim.num_instances = 1;
+         tmpprim.base_instance = 0;
 
         flush_vertex(split);
 
@@ -240,7 +261,7 @@ static void split_prims( struct split_context *split)
 }
 
 
-void vbo_split_inplace( GLcontext *ctx,
+void vbo_split_inplace( struct gl_context *ctx,
                        const struct gl_client_array *arrays[],
                        const struct _mesa_prim *prim,
                        GLuint nr_prims,
@@ -259,10 +280,14 @@ void vbo_split_inplace( GLcontext *ctx,
    split.prim = prim;
    split.nr_prims = nr_prims;
    split.ib = ib;
-   split.min_index = min_index;
-   split.max_index = max_index;
+
+   /* Empty interval, makes calculations simpler. */
+   split.min_index = ~0;
+   split.max_index = 0;
+
    split.draw = draw;
    split.limits = limits;
+   split.limit = ib ? limits->max_indices : limits->max_verts;
 
    split_prims( &split );
 }