vbo: Move vbo_split into the tnl module.
authorMathias Fröhlich <mathias.froehlich@web.de>
Sun, 25 Mar 2018 17:16:54 +0000 (19:16 +0200)
committerMathias Fröhlich <Mathias.Froehlich@gmx.net>
Sat, 31 Mar 2018 04:32:14 +0000 (06:32 +0200)
Move the files, adapt to the naming scheme in tnl, update callers
and build system.

Reviewed-by: Brian Paul <brianp@vmware.com>
Signed-off-by: Mathias Fröhlich <Mathias.Froehlich@web.de>
16 files changed:
src/mesa/Makefile.sources
src/mesa/drivers/dri/nouveau/nouveau_vbo_t.c
src/mesa/meson.build
src/mesa/tnl/t_draw.c
src/mesa/tnl/t_rebase.c
src/mesa/tnl/t_rebase.h
src/mesa/tnl/t_split.c [new file with mode: 0644]
src/mesa/tnl/t_split.h [new file with mode: 0644]
src/mesa/tnl/t_split_copy.c [new file with mode: 0644]
src/mesa/tnl/t_split_inplace.c [new file with mode: 0644]
src/mesa/tnl/tnl.h
src/mesa/vbo/vbo.h
src/mesa/vbo/vbo_split.c [deleted file]
src/mesa/vbo/vbo_split.h [deleted file]
src/mesa/vbo/vbo_split_copy.c [deleted file]
src/mesa/vbo/vbo_split_inplace.c [deleted file]

index 0446078136d90944db4e80b40003ad7e550b8b3a..92565ef8f5e7e8de3356c2479e5361a5b5582f66 100644 (file)
@@ -372,6 +372,10 @@ TNL_FILES = \
        tnl/t_pipeline.h \
        tnl/t_rebase.c \
        tnl/t_rebase.h \
+       tnl/t_split.c \
+       tnl/t_split_copy.c \
+       tnl/t_split.h \
+       tnl/t_split_inplace.c \
        tnl/t_vb_cliptmp.h \
        tnl/t_vb_fog.c \
        tnl/t_vb_light.c \
@@ -411,11 +415,7 @@ VBO_FILES = \
        vbo/vbo_save.c \
        vbo/vbo_save_draw.c \
        vbo/vbo_save.h \
-       vbo/vbo_save_loopback.c \
-       vbo/vbo_split.c \
-       vbo/vbo_split_copy.c \
-       vbo/vbo_split.h \
-       vbo/vbo_split_inplace.c
+       vbo/vbo_save_loopback.c
 
 STATETRACKER_FILES = \
        state_tracker/st_atifs_to_tgsi.c \
index 4533069692c1235a2a10a49523776fed7a808720..79b444cf55f0335928550c94c55419e7e0e08141 100644 (file)
@@ -277,8 +277,8 @@ vbo_maybe_split(struct gl_context *ctx, const struct gl_vertex_array *arrays,
                        .max_vb_size = ~0,
                };
 
-               vbo_split_prims(ctx, arrays, prims, nr_prims, ib, min_index,
-                               max_index, TAG(vbo_render_prims), &limits);
+               _tnl_split_prims(ctx, arrays, prims, nr_prims, ib, min_index,
+                                max_index, TAG(vbo_render_prims), &limits);
                return GL_TRUE;
        }
 
index b74d1693771bc9eab2bbb70fe4e4252cbbed11b9..d2d058bfa3c7a5824c2f5e9572737ef9a97650e4 100644 (file)
@@ -343,10 +343,6 @@ files_libmesa_common = files(
   'vbo/vbo_save_draw.c',
   'vbo/vbo_save.h',
   'vbo/vbo_save_loopback.c',
-  'vbo/vbo_split.c',
-  'vbo/vbo_split_copy.c',
-  'vbo/vbo_split.h',
-  'vbo/vbo_split_inplace.c',
   'x86/common_x86.c',
 )
 
@@ -366,6 +362,10 @@ files_libmesa_classic = files(
   'tnl/t_pipeline.c',
   'tnl/t_pipeline.h',
   'tnl/t_rebase.c',
+  'tnl/t_split.c',
+  'tnl/t_split_copy.c',
+  'tnl/t_split.h',
+  'tnl/t_split_inplace.c',
   'tnl/t_vb_cliptmp.h',
   'tnl/t_vb_fog.c',
   'tnl/t_vb_light.c',
index a0fd58432a1db46f14019ddc0ec9fe4443f10d59..a83b98eede14d24e6648741a30658bb17cad708a 100644 (file)
@@ -486,10 +486,10 @@ void _tnl_draw_prims(struct gl_context *ctx,
       /* This will split the buffers one way or another and
        * recursively call back into this function.
        */
-      vbo_split_prims( ctx, arrays, prim, nr_prims, ib, 
-                      0, max_index + prim->basevertex,
-                      _tnl_draw_prims,
-                      &limits );
+      _tnl_split_prims( ctx, arrays, prim, nr_prims, ib,
+                        0, max_index + prim->basevertex,
+                        _tnl_draw_prims,
+                        &limits );
    }
    else {
       /* May need to map a vertex buffer object for every attribute plus
index 19e759f44be9c946fb78ff19efd78ab3e8295897..d28512423c3f5e4d5f304e4623fbcacbef4ad7b2 100644 (file)
@@ -51,6 +51,7 @@
 #include "main/glheader.h"
 #include "main/imports.h"
 #include "main/mtypes.h"
+#include "vbo/vbo.h"
 
 #include "t_rebase.h"
 
@@ -108,7 +109,7 @@ void t_rebase_prims( struct gl_context *ctx,
                      const struct _mesa_index_buffer *ib,
                      GLuint min_index,
                      GLuint max_index,
-                     vbo_draw_func draw )
+                     tnl_draw_func draw )
 {
    struct gl_array_attributes tmp_attribs[VERT_ATTRIB_MAX];
    struct gl_vertex_array tmp_arrays[VERT_ATTRIB_MAX];
index 16a3a2b5a335bcab86dd369e68bb440c957145c3..ce2e8b0590e2ceb8882df00ed895f2eb81f6c920 100644 (file)
@@ -25,7 +25,7 @@
 #ifndef _T_REBASE_H_
 #define _T_REBASE_H_
 
-#include "vbo/vbo.h"
+#include "tnl.h"
 
 void t_rebase_prims( struct gl_context *ctx,
                      const struct gl_vertex_array *arrays,
@@ -34,6 +34,6 @@ void t_rebase_prims( struct gl_context *ctx,
                      const struct _mesa_index_buffer *ib,
                      GLuint min_index,
                      GLuint max_index,
-                     vbo_draw_func draw );
+                     tnl_draw_func draw );
 
 #endif
diff --git a/src/mesa/tnl/t_split.c b/src/mesa/tnl/t_split.c
new file mode 100644 (file)
index 0000000..b98bd40
--- /dev/null
@@ -0,0 +1,160 @@
+
+/*
+ * Mesa 3-D graphics library
+ *
+ * Copyright (C) 1999-2006  Brian Paul   All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * 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
+ * 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 <keithw@vmware.com>
+ */
+
+/* Deal with hardware and/or swtnl maximums:
+ * - maximum number of vertices in buffer
+ * - maximum number of elements (maybe zero)
+ *
+ * The maximums may vary with opengl state (eg if a larger hardware
+ * vertex is required in this state, the maximum number of vertices
+ * may be smaller than in another state).
+ *
+ * We want buffer splitting to be a convenience function for the code
+ * actually drawing the primitives rather than a system-wide maximum,
+ * otherwise it is hard to avoid pessimism.
+ *
+ * For instance, if a driver has no hardware limits on vertex buffer
+ * dimensions, it would not ordinarily want to split vbos.  But if
+ * there is an unexpected fallback, eg memory manager fails to upload
+ * textures, it will want to pass the drawing commands onto swtnl,
+ * which does have limitations.  A convenience function allows swtnl
+ * to split the drawing and vbos internally without imposing its
+ * limitations on drivers which want to use it as a fallback path.
+ */
+
+#include "main/glheader.h"
+#include "main/mtypes.h"
+#include "vbo/vbo.h"
+
+#include "t_split.h"
+
+
+/* True if a primitive can be split without copying of vertices, false
+ * otherwise.
+ */
+GLboolean
+_tnl_split_prim_inplace(GLenum mode, GLuint *first, GLuint *incr)
+{
+   switch (mode) {
+   case GL_POINTS:
+      *first = 1;
+      *incr = 1;
+      return GL_TRUE;
+   case GL_LINES:
+      *first = 2;
+      *incr = 2;
+      return GL_TRUE;
+   case GL_LINE_STRIP:
+      *first = 2;
+      *incr = 1;
+      return GL_TRUE;
+   case GL_TRIANGLES:
+      *first = 3;
+      *incr = 3;
+      return GL_TRUE;
+   case GL_TRIANGLE_STRIP:
+      *first = 3;
+      *incr = 1;
+      return GL_TRUE;
+   case GL_QUADS:
+      *first = 4;
+      *incr = 4;
+      return GL_TRUE;
+   case GL_QUAD_STRIP:
+      *first = 4;
+      *incr = 2;
+      return GL_TRUE;
+   default:
+      *first = 0;
+      *incr = 1;               /* so that count % incr works */
+      return GL_FALSE;
+   }
+}
+
+
+
+void
+_tnl_split_prims(struct gl_context *ctx,
+                 const struct gl_vertex_array arrays[],
+                 const struct _mesa_prim *prim,
+                 GLuint nr_prims,
+                 const struct _mesa_index_buffer *ib,
+                 GLuint min_index,
+                 GLuint max_index,
+                 tnl_draw_func draw,
+                 const struct split_limits *limits)
+{
+   if (ib) {
+      if (limits->max_indices == 0) {
+         /* Could traverse the indices, re-emitting vertices in turn.
+          * But it's hard to see why this case would be needed - for
+          * software tnl, it is better to convert to non-indexed
+          * rendering after transformation is complete.  Are there any devices
+          * with hardware tnl that cannot do indexed rendering?
+          *
+          * For now, this path is disabled.
+          */
+         assert(0);
+      }
+      else if (max_index - min_index >= limits->max_verts) {
+         /* The vertex buffers are too large for hardware (or the
+          * swtnl module).  Traverse the indices, re-emitting vertices
+          * in turn.  Use a vertex cache to preserve some of the
+          * sharing from the original index list.
+          */
+         _tnl_split_copy(ctx, arrays, prim, nr_prims, ib, draw, limits);
+      }
+      else if (ib->count > limits->max_indices) {
+         /* The index buffer is too large for hardware.  Try to split
+          * on whole-primitive boundaries, otherwise try to split the
+          * individual primitives.
+          */
+         _tnl_split_inplace(ctx, arrays, prim, nr_prims, ib,
+                            min_index, max_index, draw, limits);
+      }
+      else {
+         /* Why were we called? */
+         assert(0);
+      }
+   }
+   else {
+      if (max_index - min_index >= limits->max_verts) {
+         /* The vertex buffer is too large for hardware (or the swtnl
+          * module).  Try to split on whole-primitive boundaries,
+          * otherwise try to split the individual primitives.
+          */
+         _tnl_split_inplace(ctx, arrays, prim, nr_prims, ib,
+                            min_index, max_index, draw, limits);
+      }
+      else {
+         /* Why were we called? */
+         assert(0);
+      }
+   }
+}
+
diff --git a/src/mesa/tnl/t_split.h b/src/mesa/tnl/t_split.h
new file mode 100644 (file)
index 0000000..ced7d30
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * mesa 3-D graphics library
+ *
+ * Copyright (C) 1999-2006  Brian Paul   All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * 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
+ * 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.
+ */
+
+/**
+ * \brief VBO builder module datatypes and definitions.
+ * \author Keith Whitwell
+ */
+
+
+/**
+ * \mainpage The TNL splitter
+ *
+ * This is the private data used internally to the _tnl_split_prims()
+ * helper function.  Nobody outside the _tnl_split* files needs to
+ * include or know about this structure.
+ */
+
+
+#ifndef _TNL_SPLIT_H
+#define _TNL_SPLIT_H
+
+#include "tnl.h"
+
+
+/* True if a primitive can be split without copying of vertices, false
+ * otherwise.
+ */
+GLboolean
+_tnl_split_prim_inplace(GLenum mode, GLuint *first, GLuint *incr);
+
+void
+_tnl_split_inplace(struct gl_context *ctx,
+                   const struct gl_vertex_array arrays[],
+                   const struct _mesa_prim *prim,
+                   GLuint nr_prims,
+                   const struct _mesa_index_buffer *ib,
+                   GLuint min_index,
+                   GLuint max_index,
+                   tnl_draw_func draw,
+                   const struct split_limits *limits);
+
+/* Requires ib != NULL:
+ */
+void
+_tnl_split_copy(struct gl_context *ctx,
+                const struct gl_vertex_array arrays[],
+                const struct _mesa_prim *prim,
+                GLuint nr_prims,
+                const struct _mesa_index_buffer *ib,
+                tnl_draw_func draw,
+                const struct split_limits *limits);
+
+#endif
diff --git a/src/mesa/tnl/t_split_copy.c b/src/mesa/tnl/t_split_copy.c
new file mode 100644 (file)
index 0000000..f76a470
--- /dev/null
@@ -0,0 +1,638 @@
+
+/*
+ * Mesa 3-D graphics library
+ *
+ * Copyright (C) 1999-2006  Brian Paul   All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * 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
+ * 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 <keithw@vmware.com>
+ */
+
+/* Split indexed primitives with per-vertex copying.
+ */
+
+#include <stdio.h>
+
+#include "main/glheader.h"
+#include "main/bufferobj.h"
+#include "main/imports.h"
+#include "main/glformats.h"
+#include "main/macros.h"
+#include "main/mtypes.h"
+#include "main/varray.h"
+#include "vbo/vbo.h"
+
+#include "t_split.h"
+#include "tnl.h"
+
+
+#define ELT_TABLE_SIZE 16
+
+/**
+ * Used for vertex-level splitting of indexed buffers.  Note that
+ * non-indexed primitives may be converted to indexed in some cases
+ * (eg loops, fans) in order to use this splitting path.
+ */
+struct copy_context {
+   struct gl_context *ctx;
+   const struct gl_vertex_array *array;
+   const struct _mesa_prim *prim;
+   GLuint nr_prims;
+   const struct _mesa_index_buffer *ib;
+   tnl_draw_func draw;
+
+   const struct split_limits *limits;
+
+   struct {
+      GLuint attr;
+      GLuint size;
+      const struct gl_vertex_array *array;
+      const GLubyte *src_ptr;
+
+      struct gl_vertex_buffer_binding dstbinding;
+      struct gl_array_attributes dstattribs;
+
+   } varying[VERT_ATTRIB_MAX];
+   GLuint nr_varying;
+
+   struct gl_vertex_array dstarray[VERT_ATTRIB_MAX];
+   struct _mesa_index_buffer dstib;
+
+   GLuint *translated_elt_buf;
+   const GLuint *srcelt;
+
+   /** A baby hash table to avoid re-emitting (some) duplicate
+    * vertices when splitting indexed primitives.
+    */
+   struct {
+      GLuint in;
+      GLuint out;
+   } vert_cache[ELT_TABLE_SIZE];
+
+   GLuint vertex_size;
+   GLubyte *dstbuf;
+   GLubyte *dstptr;     /**< dstptr == dstbuf + dstelt_max * vertsize */
+   GLuint dstbuf_size;  /**< in vertices */
+   GLuint dstbuf_nr;    /**< count of emitted vertices, also the largest value
+                         * in dstelt.  Our MaxIndex.
+                         */
+
+   GLuint *dstelt;
+   GLuint dstelt_nr;
+   GLuint dstelt_size;
+
+#define MAX_PRIM 32
+   struct _mesa_prim dstprim[MAX_PRIM];
+   GLuint dstprim_nr;
+};
+
+
+static GLuint
+attr_size(const struct gl_array_attributes *attrib)
+{
+   return attrib->Size * _mesa_sizeof_type(attrib->Type);
+}
+
+
+/**
+ * Starts returning true slightly before the buffer fills, to ensure
+ * that there is sufficient room for any remaining vertices to finish
+ * off the prim:
+ */
+static GLboolean
+check_flush(struct copy_context *copy)
+{
+   GLenum mode = copy->dstprim[copy->dstprim_nr].mode;
+
+   if (GL_TRIANGLE_STRIP == mode &&
+       copy->dstelt_nr & 1) { /* see bug9962 */
+       return GL_FALSE;
+   }
+
+   if (copy->dstbuf_nr + 4 > copy->dstbuf_size)
+      return GL_TRUE;
+
+   if (copy->dstelt_nr + 4 > copy->dstelt_size)
+      return GL_TRUE;
+
+   return GL_FALSE;
+}
+
+
+/**
+ * Dump the parameters/info for a vbo->draw() call.
+ */
+static void
+dump_draw_info(struct gl_context *ctx,
+               const struct gl_vertex_array *arrays,
+               const struct _mesa_prim *prims,
+               GLuint nr_prims,
+               const struct _mesa_index_buffer *ib,
+               GLuint min_index,
+               GLuint max_index)
+{
+   GLuint i, j;
+
+   printf("VBO Draw:\n");
+   for (i = 0; i < nr_prims; i++) {
+      printf("Prim %u of %u\n", i, nr_prims);
+      printf("  Prim mode 0x%x\n", prims[i].mode);
+      printf("  IB: %p\n", (void*) ib);
+      for (j = 0; j < VERT_ATTRIB_MAX; j++) {
+         const struct gl_vertex_array *array = &arrays[j];
+         const struct gl_vertex_buffer_binding *binding
+            = array->BufferBinding;
+         const struct gl_array_attributes *attrib = array->VertexAttrib;
+         const GLubyte *ptr = _mesa_vertex_attrib_address(attrib, binding);
+         printf("    array %d at %p:\n", j, (void*) &arrays[j]);
+         printf("      ptr %p, size %d, type 0x%x, stride %d\n",
+                ptr, attrib->Size, attrib->Type, binding->Stride);
+         if (0) {
+            GLint k = prims[i].start + prims[i].count - 1;
+            GLfloat *last = (GLfloat *) (ptr + binding->Stride * k);
+            printf("        last: %f %f %f\n",
+                   last[0], last[1], last[2]);
+         }
+      }
+   }
+}
+
+
+static void
+flush(struct copy_context *copy)
+{
+   struct gl_context *ctx = copy->ctx;
+   GLuint i;
+
+   /* Set some counters:
+    */
+   copy->dstib.count = copy->dstelt_nr;
+
+#if 0
+   dump_draw_info(copy->ctx,
+                  copy->dstarray,
+                  copy->dstprim,
+                  copy->dstprim_nr,
+                  &copy->dstib,
+                  0,
+                  copy->dstbuf_nr);
+#else
+   (void) dump_draw_info;
+#endif
+
+   copy->draw(ctx,
+              copy->dstarray,
+              copy->dstprim,
+              copy->dstprim_nr,
+              &copy->dstib,
+              GL_TRUE,
+              0,
+              copy->dstbuf_nr - 1,
+              NULL, 0, NULL);
+
+   /* Reset all pointers:
+    */
+   copy->dstprim_nr = 0;
+   copy->dstelt_nr = 0;
+   copy->dstbuf_nr = 0;
+   copy->dstptr = copy->dstbuf;
+
+   /* Clear the vertex cache:
+    */
+   for (i = 0; i < ELT_TABLE_SIZE; i++)
+      copy->vert_cache[i].in = ~0;
+}
+
+
+/**
+ * Called at begin of each primitive during replay.
+ */
+static void
+begin(struct copy_context *copy, GLenum mode, GLboolean begin_flag)
+{
+   struct _mesa_prim *prim = &copy->dstprim[copy->dstprim_nr];
+
+   prim->mode = mode;
+   prim->begin = begin_flag;
+   prim->num_instances = 1;
+}
+
+
+/**
+ * Use a hashtable to attempt to identify recently-emitted vertices
+ * and avoid re-emitting them.
+ */
+static GLuint
+elt(struct copy_context *copy, GLuint elt_idx)
+{
+   GLuint elt = copy->srcelt[elt_idx] + copy->prim->basevertex;
+   GLuint slot = elt & (ELT_TABLE_SIZE-1);
+
+   /* Look up the incoming element in the vertex cache.  Re-emit if
+    * necessary.
+    */
+   if (copy->vert_cache[slot].in != elt) {
+      GLubyte *csr = copy->dstptr;
+      GLuint i;
+
+      for (i = 0; i < copy->nr_varying; i++) {
+         const struct gl_vertex_array *srcarray = copy->varying[i].array;
+         const struct gl_vertex_buffer_binding* srcbinding
+            = srcarray->BufferBinding;
+         const GLubyte *srcptr
+            = copy->varying[i].src_ptr + elt * srcbinding->Stride;
+
+         memcpy(csr, srcptr, copy->varying[i].size);
+         csr += copy->varying[i].size;
+
+#ifdef NAN_CHECK
+         if (srcarray->Type == GL_FLOAT) {
+            GLuint k;
+            GLfloat *f = (GLfloat *) srcptr;
+            for (k = 0; k < srcarray->Size; k++) {
+               assert(!IS_INF_OR_NAN(f[k]));
+               assert(f[k] <= 1.0e20 && f[k] >= -1.0e20);
+            }
+         }
+#endif
+
+         if (0) {
+            const GLuint *f = (const GLuint *)srcptr;
+            GLuint j;
+            printf("  varying %d: ", i);
+            for (j = 0; j < copy->varying[i].size / 4; j++)
+               printf("%x ", f[j]);
+            printf("\n");
+         }
+      }
+
+      copy->vert_cache[slot].in = elt;
+      copy->vert_cache[slot].out = copy->dstbuf_nr++;
+      copy->dstptr += copy->vertex_size;
+
+      assert(csr == copy->dstptr);
+      assert(copy->dstptr == (copy->dstbuf +
+                              copy->dstbuf_nr * copy->vertex_size));
+   }
+
+   copy->dstelt[copy->dstelt_nr++] = copy->vert_cache[slot].out;
+   return check_flush(copy);
+}
+
+
+/**
+ * Called at end of each primitive during replay.
+ */
+static void
+end(struct copy_context *copy, GLboolean end_flag)
+{
+   struct _mesa_prim *prim = &copy->dstprim[copy->dstprim_nr];
+
+   prim->end = end_flag;
+   prim->count = copy->dstelt_nr - prim->start;
+
+   if (++copy->dstprim_nr == MAX_PRIM || check_flush(copy)) {
+      flush(copy);
+   }
+}
+
+
+static void
+replay_elts(struct copy_context *copy)
+{
+   GLuint i, j, k;
+   GLboolean split;
+
+   for (i = 0; i < copy->nr_prims; i++) {
+      const struct _mesa_prim *prim = &copy->prim[i];
+      const GLuint start = prim->start;
+      GLuint first, incr;
+
+      switch (prim->mode) {
+      case GL_LINE_LOOP:
+         /* Convert to linestrip and emit the final vertex explicitly,
+          * but only in the resultant strip that requires it.
+          */
+         j = 0;
+         while (j != prim->count) {
+            begin(copy, GL_LINE_STRIP, prim->begin && j == 0);
+
+            for (split = GL_FALSE; j != prim->count && !split; j++)
+               split = elt(copy, start + j);
+
+            if (j == prim->count) {
+               /* Done, emit final line.  Split doesn't matter as
+                * it is always raised a bit early so we can emit
+                * the last verts if necessary!
+                */
+               if (prim->end)
+                  (void)elt(copy, start + 0);
+
+               end(copy, prim->end);
+            }
+            else {
+               /* Wrap
+                */
+               assert(split);
+               end(copy, 0);
+               j--;
+            }
+         }
+         break;
+
+      case GL_TRIANGLE_FAN:
+      case GL_POLYGON:
+         j = 2;
+         while (j != prim->count) {
+            begin(copy, prim->mode, prim->begin && j == 0);
+
+            split = elt(copy, start+0);
+            assert(!split);
+
+            split = elt(copy, start+j-1);
+            assert(!split);
+
+            for (; j != prim->count && !split; j++)
+               split = elt(copy, start+j);
+
+            end(copy, prim->end && j == prim->count);
+
+            if (j != prim->count) {
+               /* Wrapped the primitive, need to repeat some vertices:
+                */
+               j -= 1;
+            }
+         }
+         break;
+
+      default:
+         (void)_tnl_split_prim_inplace(prim->mode, &first, &incr);
+
+         j = 0;
+         while (j != prim->count) {
+
+            begin(copy, prim->mode, prim->begin && j == 0);
+
+            split = 0;
+            for (k = 0; k < first; k++, j++)
+               split |= elt(copy, start+j);
+
+            assert(!split);
+
+            for (; j != prim->count && !split;)
+               for (k = 0; k < incr; k++, j++)
+                  split |= elt(copy, start+j);
+
+            end(copy, prim->end && j == prim->count);
+
+            if (j != prim->count) {
+               /* Wrapped the primitive, need to repeat some vertices:
+                */
+               assert(j > first - incr);
+               j -= (first - incr);
+            }
+         }
+         break;
+      }
+   }
+
+   if (copy->dstprim_nr)
+      flush(copy);
+}
+
+
+static void
+replay_init(struct copy_context *copy)
+{
+   struct gl_context *ctx = copy->ctx;
+   GLuint i;
+   GLuint offset;
+   const GLvoid *srcptr;
+
+   /* Make a list of varying attributes and their vbo's.  Also
+    * calculate vertex size.
+    */
+   copy->vertex_size = 0;
+   for (i = 0; i < VERT_ATTRIB_MAX; i++) {
+      const struct gl_vertex_array *array = &copy->array[i];
+      const struct gl_vertex_buffer_binding *binding = array->BufferBinding;
+
+      if (binding->Stride == 0) {
+         _mesa_copy_vertex_array(&copy->dstarray[i], array);
+      }
+      else {
+         const struct gl_array_attributes *attrib = array->VertexAttrib;
+         struct gl_buffer_object *vbo = binding->BufferObj;
+         const GLubyte *ptr = _mesa_vertex_attrib_address(attrib, binding);
+         GLuint j = copy->nr_varying++;
+
+         copy->varying[j].attr = i;
+         copy->varying[j].array = &copy->array[i];
+         copy->varying[j].size = attr_size(attrib);
+         copy->vertex_size += attr_size(attrib);
+
+         if (_mesa_is_bufferobj(vbo) &&
+             !_mesa_bufferobj_mapped(vbo, MAP_INTERNAL))
+            ctx->Driver.MapBufferRange(ctx, 0, vbo->Size, GL_MAP_READ_BIT, vbo,
+                                       MAP_INTERNAL);
+
+         copy->varying[j].src_ptr =
+               ADD_POINTERS(vbo->Mappings[MAP_INTERNAL].Pointer, ptr);
+
+         copy->dstarray[i].VertexAttrib = &copy->varying[j].dstattribs;
+         copy->dstarray[i].BufferBinding = &copy->varying[j].dstbinding;
+      }
+   }
+
+   /* There must always be an index buffer.  Currently require the
+    * caller convert non-indexed prims to indexed.  Could alternately
+    * do it internally.
+    */
+   if (_mesa_is_bufferobj(copy->ib->obj) &&
+       !_mesa_bufferobj_mapped(copy->ib->obj, MAP_INTERNAL))
+      ctx->Driver.MapBufferRange(ctx, 0, copy->ib->obj->Size, GL_MAP_READ_BIT,
+                                 copy->ib->obj, MAP_INTERNAL);
+
+   srcptr = (const GLubyte *)
+            ADD_POINTERS(copy->ib->obj->Mappings[MAP_INTERNAL].Pointer,
+                         copy->ib->ptr);
+
+   switch (copy->ib->index_size) {
+   case 1:
+      copy->translated_elt_buf = malloc(sizeof(GLuint) * copy->ib->count);
+      copy->srcelt = copy->translated_elt_buf;
+
+      for (i = 0; i < copy->ib->count; i++)
+         copy->translated_elt_buf[i] = ((const GLubyte *)srcptr)[i];
+      break;
+
+   case 2:
+      copy->translated_elt_buf = malloc(sizeof(GLuint) * copy->ib->count);
+      copy->srcelt = copy->translated_elt_buf;
+
+      for (i = 0; i < copy->ib->count; i++)
+         copy->translated_elt_buf[i] = ((const GLushort *)srcptr)[i];
+      break;
+
+   case 4:
+      copy->translated_elt_buf = NULL;
+      copy->srcelt = (const GLuint *)srcptr;
+      break;
+   }
+
+   /* Figure out the maximum allowed vertex buffer size:
+    */
+   if (copy->vertex_size * copy->limits->max_verts <= copy->limits->max_vb_size) {
+      copy->dstbuf_size = copy->limits->max_verts;
+   }
+   else {
+      copy->dstbuf_size = copy->limits->max_vb_size / copy->vertex_size;
+   }
+
+   /* Allocate an output vertex buffer:
+    *
+    * XXX:  This should be a VBO!
+    */
+   copy->dstbuf = malloc(copy->dstbuf_size * copy->vertex_size);
+   copy->dstptr = copy->dstbuf;
+
+   /* Setup new vertex arrays to point into the output buffer:
+    */
+   for (offset = 0, i = 0; i < copy->nr_varying; i++) {
+      const struct gl_vertex_array *src = copy->varying[i].array;
+      const struct gl_array_attributes *srcattr = src->VertexAttrib;
+      struct gl_vertex_array *dst = &copy->dstarray[i];
+      struct gl_vertex_buffer_binding *dstbind = &copy->varying[i].dstbinding;
+      struct gl_array_attributes *dstattr = &copy->varying[i].dstattribs;
+
+      dstattr->Size = srcattr->Size;
+      dstattr->Type = srcattr->Type;
+      dstattr->Format = GL_RGBA;
+      dstbind->Stride = copy->vertex_size;
+      dstattr->Ptr = copy->dstbuf + offset;
+      dstattr->Normalized = srcattr->Normalized;
+      dstattr->Integer = srcattr->Integer;
+      dstattr->Doubles = srcattr->Doubles;
+      dstbind->BufferObj = ctx->Shared->NullBufferObj;
+      dstattr->_ElementSize = srcattr->_ElementSize;
+      dst->BufferBinding = dstbind;
+      dst->VertexAttrib = dstattr;
+
+      offset += copy->varying[i].size;
+   }
+
+   /* Allocate an output element list:
+    */
+   copy->dstelt_size = MIN2(65536, copy->ib->count * 2 + 3);
+   copy->dstelt_size = MIN2(copy->dstelt_size, copy->limits->max_indices);
+   copy->dstelt = malloc(sizeof(GLuint) * copy->dstelt_size);
+   copy->dstelt_nr = 0;
+
+   /* Setup the new index buffer to point to the allocated element
+    * list:
+    */
+   copy->dstib.count = 0;        /* duplicates dstelt_nr */
+   copy->dstib.index_size = 4;
+   copy->dstib.obj = ctx->Shared->NullBufferObj;
+   copy->dstib.ptr = copy->dstelt;
+}
+
+
+/**
+ * Free up everything allocated during split/replay.
+ */
+static void
+replay_finish(struct copy_context *copy)
+{
+   struct gl_context *ctx = copy->ctx;
+   GLuint i;
+
+   /* Free our vertex and index buffers */
+   free(copy->translated_elt_buf);
+   free(copy->dstbuf);
+   free(copy->dstelt);
+
+   /* Unmap VBO's */
+   for (i = 0; i < copy->nr_varying; i++) {
+      struct gl_buffer_object *vbo =
+         copy->varying[i].array->BufferBinding->BufferObj;
+      if (_mesa_is_bufferobj(vbo) && _mesa_bufferobj_mapped(vbo, MAP_INTERNAL))
+         ctx->Driver.UnmapBuffer(ctx, vbo, MAP_INTERNAL);
+   }
+
+   /* Unmap index buffer */
+   if (_mesa_is_bufferobj(copy->ib->obj) &&
+       _mesa_bufferobj_mapped(copy->ib->obj, MAP_INTERNAL)) {
+      ctx->Driver.UnmapBuffer(ctx, copy->ib->obj, MAP_INTERNAL);
+   }
+}
+
+
+/**
+ * Split VBO into smaller pieces, draw the pieces.
+ */
+void
+_tnl_split_copy(struct gl_context *ctx,
+                const struct gl_vertex_array *arrays,
+                const struct _mesa_prim *prim,
+                GLuint nr_prims,
+                const struct _mesa_index_buffer *ib,
+                tnl_draw_func draw,
+                const struct split_limits *limits)
+{
+   struct copy_context copy;
+   GLuint i, this_nr_prims;
+
+   for (i = 0; i < nr_prims;) {
+      /* Our SW TNL pipeline doesn't handle basevertex yet, so bind_indices
+       * will rebase the elements to the basevertex, and we'll only
+       * emit strings of prims with the same basevertex in one draw call.
+       */
+      for (this_nr_prims = 1; i + this_nr_prims < nr_prims;
+           this_nr_prims++) {
+         if (prim[i].basevertex != prim[i + this_nr_prims].basevertex)
+            break;
+      }
+
+      memset(&copy, 0, sizeof(copy));
+
+      /* Require indexed primitives:
+       */
+      assert(ib);
+
+      copy.ctx = ctx;
+      copy.array = arrays;
+      copy.prim = &prim[i];
+      copy.nr_prims = this_nr_prims;
+      copy.ib = ib;
+      copy.draw = draw;
+      copy.limits = limits;
+
+      /* Clear the vertex cache:
+       */
+      for (i = 0; i < ELT_TABLE_SIZE; i++)
+         copy.vert_cache[i].in = ~0;
+
+      replay_init(&copy);
+      replay_elts(&copy);
+      replay_finish(&copy);
+   }
+}
diff --git a/src/mesa/tnl/t_split_inplace.c b/src/mesa/tnl/t_split_inplace.c
new file mode 100644 (file)
index 0000000..15a0986
--- /dev/null
@@ -0,0 +1,298 @@
+
+/*
+ * Mesa 3-D graphics library
+ *
+ * Copyright (C) 1999-2006  Brian Paul   All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * 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
+ * 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 <keithw@vmware.com>
+ */
+
+
+#include "main/mtypes.h"
+#include "main/macros.h"
+#include "main/enums.h"
+#include "vbo/vbo.h"
+
+#include "t_split.h"
+
+
+#define MAX_PRIM 32
+
+/* 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 {
+   struct gl_context *ctx;
+   const struct gl_vertex_array *array;
+   const struct _mesa_prim *prim;
+   GLuint nr_prims;
+   const struct _mesa_index_buffer *ib;
+   GLuint min_index;
+   GLuint max_index;
+   tnl_draw_func draw;
+
+   const struct split_limits *limits;
+   GLuint limit;
+
+   struct _mesa_prim dstprim[MAX_PRIM];
+   GLuint dstprim_nr;
+};
+
+
+
+
+static void
+flush_vertex( struct split_context *split)
+{
+   struct gl_context *ctx = split->ctx;
+   struct _mesa_index_buffer ib;
+   GLuint i;
+
+   if (!split->dstprim_nr)
+      return;
+
+   if (split->ib) {
+      ib = *split->ib;
+
+      ib.count = split->max_index - split->min_index + 1;
+      ib.ptr = (const void *)((const char *)ib.ptr +
+                              split->min_index * ib.index_size);
+
+      /* Rebase the primitives to save index buffer entries. */
+      for (i = 0; i < split->dstprim_nr; i++)
+         split->dstprim[i].start -= split->min_index;
+   }
+
+   assert(split->max_index >= split->min_index);
+
+   split->draw(ctx,
+               split->array,
+               split->dstprim,
+               split->dstprim_nr,
+               split->ib ? &ib : NULL,
+               !split->ib,
+               split->min_index,
+               split->max_index,
+               NULL, 0, NULL);
+
+   split->dstprim_nr = 0;
+   split->min_index = ~0;
+   split->max_index = 0;
+}
+
+
+static struct _mesa_prim *
+next_outprim(struct split_context *split)
+{
+   if (split->dstprim_nr == MAX_PRIM-1) {
+      flush_vertex(split);
+   }
+
+   {
+      struct _mesa_prim *prim = &split->dstprim[split->dstprim_nr++];
+      memset(prim, 0, sizeof(*prim));
+      return prim;
+   }
+}
+
+
+static void
+update_index_bounds(struct split_context *split,
+                    const struct _mesa_prim *prim)
+{
+   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 i;
+
+   for (i = 0; i < split->nr_prims; i++) {
+      const struct _mesa_prim *prim = &split->prim[i];
+      GLuint first, incr;
+      GLboolean split_inplace =
+         _tnl_split_prim_inplace(prim->mode, &first, &incr);
+      GLuint available = get_max_vertices(split, prim);
+      GLuint count = prim->count - (prim->count - first) % incr;
+
+      if (prim->count < first)
+         continue;
+
+      if ((available < count && !split_inplace) ||
+          (available < first && split_inplace)) {
+         flush_vertex(split);
+         available = get_max_vertices(split, prim);
+      }
+
+      if (available >= count) {
+         struct _mesa_prim *outprim = next_outprim(split);
+
+         *outprim = *prim;
+         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;
+            }
+            else {
+               /* Wrapped the primitive */
+               j += nr - (first - incr);
+               flush_vertex(split);
+               available = get_max_vertices(split, prim);
+            }
+         }
+      }
+      else if (split->ib == NULL) {
+         /* XXX: could at least send the first max_verts off from the
+          * inplace buffers.
+          */
+
+         /* else convert to indexed primitive and pass to split_elts,
+          * which will do the necessary copying and turn it back into a
+          * vertex primitive for rendering...
+          */
+         struct _mesa_index_buffer ib;
+         struct _mesa_prim tmpprim;
+         GLuint *elts = malloc(count * sizeof(GLuint));
+         GLuint j;
+
+         for (j = 0; j < count; j++)
+            elts[j] = prim->start + j;
+
+         ib.count = count;
+         ib.index_size = 4;
+         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);
+
+         _tnl_split_copy(split->ctx,
+                         split->array,
+                         &tmpprim, 1,
+                         &ib,
+                         split->draw,
+                         split->limits);
+
+         free(elts);
+      }
+      else {
+         flush_vertex(split);
+
+         _tnl_split_copy(split->ctx,
+                         split->array,
+                         prim, 1,
+                         split->ib,
+                         split->draw,
+                         split->limits);
+      }
+   }
+
+   flush_vertex(split);
+}
+
+
+void
+_tnl_split_inplace(struct gl_context *ctx,
+                   const struct gl_vertex_array *arrays,
+                   const struct _mesa_prim *prim,
+                   GLuint nr_prims,
+                   const struct _mesa_index_buffer *ib,
+                   GLuint min_index,
+                   GLuint max_index,
+                   tnl_draw_func draw,
+                   const struct split_limits *limits)
+{
+   struct split_context split;
+
+   memset(&split, 0, sizeof(split));
+
+   split.ctx = ctx;
+   split.array = arrays;
+   split.prim = prim;
+   split.nr_prims = nr_prims;
+   split.ib = ib;
+
+   /* 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);
+}
+
+
index e79c4f620484eb68021aab5ef2eef4008103237e..45052a3a89c7f0a95cc9eba589954843f970b0d9 100644 (file)
@@ -108,4 +108,84 @@ _tnl_RasterPos(struct gl_context *ctx, const GLfloat vObj[4]);
 extern void
 _tnl_validate_shine_tables( struct gl_context *ctx );
 
+
+
+/**
+ * For indirect array drawing:
+ *
+ *    typedef struct {
+ *       GLuint count;
+ *       GLuint primCount;
+ *       GLuint first;
+ *       GLuint baseInstance; // in GL 4.2 and later, must be zero otherwise
+ *    } DrawArraysIndirectCommand;
+ *
+ * For indirect indexed drawing:
+ *
+ *    typedef struct {
+ *       GLuint count;
+ *       GLuint primCount;
+ *       GLuint firstIndex;
+ *       GLint  baseVertex;
+ *       GLuint baseInstance; // in GL 4.2 and later, must be zero otherwise
+ *    } DrawElementsIndirectCommand;
+ */
+
+
+/**
+ * Draw a number of primitives.
+ * \param prims  array [nr_prims] describing what to draw (prim type,
+ *               vertex count, first index, instance count, etc).
+ * \param arrays array of vertex arrays for draw
+ * \param ib  index buffer for indexed drawing, NULL for array drawing
+ * \param index_bounds_valid  are min_index and max_index valid?
+ * \param min_index  lowest vertex index used
+ * \param max_index  highest vertex index used
+ * \param tfb_vertcount  if non-null, indicates which transform feedback
+ *                       object has the vertex count.
+ * \param tfb_stream  If called via DrawTransformFeedbackStream, specifies the
+ *                    vertex stream buffer from which to get the vertex count.
+ * \param indirect  If any prims are indirect, this specifies the buffer
+ *                  to find the "DrawArrays/ElementsIndirectCommand" data.
+ *                  This may be deprecated in the future
+ */
+typedef void (*tnl_draw_func)(struct gl_context *ctx,
+                              const struct gl_vertex_array* arrays,
+                              const struct _mesa_prim *prims,
+                              GLuint nr_prims,
+                              const struct _mesa_index_buffer *ib,
+                              GLboolean index_bounds_valid,
+                              GLuint min_index,
+                              GLuint max_index,
+                              struct gl_transform_feedback_object *tfb_vertcount,
+                              unsigned tfb_stream,
+                              struct gl_buffer_object *indirect);
+
+
+/* Utility function to cope with various constraints on tnl modules or
+ * hardware.  This can be used to split an incoming set of arrays and
+ * primitives against the following constraints:
+ *    - Maximum number of indices in index buffer.
+ *    - Maximum number of vertices referenced by index buffer.
+ *    - Maximum hardware vertex buffer size.
+ */
+struct split_limits
+{
+   GLuint max_verts;
+   GLuint max_indices;
+   GLuint max_vb_size;         /* bytes */
+};
+
+void
+_tnl_split_prims(struct gl_context *ctx,
+                 const struct gl_vertex_array *arrays,
+                 const struct _mesa_prim *prim,
+                 GLuint nr_prims,
+                 const struct _mesa_index_buffer *ib,
+                 GLuint min_index,
+                 GLuint max_index,
+                 tnl_draw_func draw,
+                 const struct split_limits *limits);
+
+
 #endif
index 37aa59d306192827aead4ffdb6c0fb6da8bcd5f7..9b15066291504cbe90d89384ab800cec8bd51121 100644 (file)
@@ -119,75 +119,6 @@ void
 vbo_save_EndCallList(struct gl_context *ctx);
 
 
-/**
- * For indirect array drawing:
- *
- *    typedef struct {
- *       GLuint count;
- *       GLuint primCount;
- *       GLuint first;
- *       GLuint baseInstance; // in GL 4.2 and later, must be zero otherwise
- *    } DrawArraysIndirectCommand;
- *
- * For indirect indexed drawing:
- *
- *    typedef struct {
- *       GLuint count;
- *       GLuint primCount;
- *       GLuint firstIndex;
- *       GLint  baseVertex;
- *       GLuint baseInstance; // in GL 4.2 and later, must be zero otherwise
- *    } DrawElementsIndirectCommand;
- */
-
-
-/**
- * Draw a number of primitives.
- * \param prims  array [nr_prims] describing what to draw (prim type,
- *               vertex count, first index, instance count, etc).
- * \param arrays array of vertex arrays for draw
- * \param ib  index buffer for indexed drawing, NULL for array drawing
- * \param index_bounds_valid  are min_index and max_index valid?
- * \param min_index  lowest vertex index used
- * \param max_index  highest vertex index used
- * \param tfb_vertcount  if non-null, indicates which transform feedback
- *                       object has the vertex count.
- * \param tfb_stream  If called via DrawTransformFeedbackStream, specifies the
- *                    vertex stream buffer from which to get the vertex count.
- * \param indirect  If any prims are indirect, this specifies the buffer
- *                  to find the "DrawArrays/ElementsIndirectCommand" data.
- *                  This may be deprecated in the future
- */
-typedef void (*vbo_draw_func)(struct gl_context *ctx,
-                              const struct gl_vertex_array* arrays,
-                              const struct _mesa_prim *prims,
-                              GLuint nr_prims,
-                              const struct _mesa_index_buffer *ib,
-                              GLboolean index_bounds_valid,
-                              GLuint min_index,
-                              GLuint max_index,
-                              struct gl_transform_feedback_object *tfb_vertcount,
-                              unsigned tfb_stream,
-                              struct gl_buffer_object *indirect);
-
-
-
-
-/* Utility function to cope with various constraints on tnl modules or
- * hardware.  This can be used to split an incoming set of arrays and
- * primitives against the following constraints:
- *    - Maximum number of indices in index buffer.
- *    - Maximum number of vertices referenced by index buffer.
- *    - Maximum hardware vertex buffer size.
- */
-struct split_limits
-{
-   GLuint max_verts;
-   GLuint max_indices;
-   GLuint max_vb_size;         /* bytes */
-};
-
-
 void
 _vbo_draw_indirect(struct gl_context *ctx, GLuint mode,
                         struct gl_buffer_object *indirect_data,
@@ -198,18 +129,6 @@ _vbo_draw_indirect(struct gl_context *ctx, GLuint mode,
                         const struct _mesa_index_buffer *ib);
 
 
-void
-vbo_split_prims(struct gl_context *ctx,
-                const struct gl_vertex_array *arrays,
-                const struct _mesa_prim *prim,
-                GLuint nr_prims,
-                const struct _mesa_index_buffer *ib,
-                GLuint min_index,
-                GLuint max_index,
-                vbo_draw_func draw,
-                const struct split_limits *limits);
-
-
 void
 vbo_delete_minmax_cache(struct gl_buffer_object *bufferObj);
 
diff --git a/src/mesa/vbo/vbo_split.c b/src/mesa/vbo/vbo_split.c
deleted file mode 100644 (file)
index ffe1d67..0000000
+++ /dev/null
@@ -1,160 +0,0 @@
-
-/*
- * Mesa 3-D graphics library
- *
- * Copyright (C) 1999-2006  Brian Paul   All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * 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
- * 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 <keithw@vmware.com>
- */
-
-/* Deal with hardware and/or swtnl maximums:
- * - maximum number of vertices in buffer
- * - maximum number of elements (maybe zero)
- *
- * The maximums may vary with opengl state (eg if a larger hardware
- * vertex is required in this state, the maximum number of vertices
- * may be smaller than in another state).
- *
- * We want buffer splitting to be a convenience function for the code
- * actually drawing the primitives rather than a system-wide maximum,
- * otherwise it is hard to avoid pessimism.
- *
- * For instance, if a driver has no hardware limits on vertex buffer
- * dimensions, it would not ordinarily want to split vbos.  But if
- * there is an unexpected fallback, eg memory manager fails to upload
- * textures, it will want to pass the drawing commands onto swtnl,
- * which does have limitations.  A convenience function allows swtnl
- * to split the drawing and vbos internally without imposing its
- * limitations on drivers which want to use it as a fallback path.
- */
-
-#include "main/glheader.h"
-#include "main/mtypes.h"
-
-#include "vbo_split.h"
-#include "vbo.h"
-
-
-/* True if a primitive can be split without copying of vertices, false
- * otherwise.
- */
-GLboolean
-split_prim_inplace(GLenum mode, GLuint *first, GLuint *incr)
-{
-   switch (mode) {
-   case GL_POINTS:
-      *first = 1;
-      *incr = 1;
-      return GL_TRUE;
-   case GL_LINES:
-      *first = 2;
-      *incr = 2;
-      return GL_TRUE;
-   case GL_LINE_STRIP:
-      *first = 2;
-      *incr = 1;
-      return GL_TRUE;
-   case GL_TRIANGLES:
-      *first = 3;
-      *incr = 3;
-      return GL_TRUE;
-   case GL_TRIANGLE_STRIP:
-      *first = 3;
-      *incr = 1;
-      return GL_TRUE;
-   case GL_QUADS:
-      *first = 4;
-      *incr = 4;
-      return GL_TRUE;
-   case GL_QUAD_STRIP:
-      *first = 4;
-      *incr = 2;
-      return GL_TRUE;
-   default:
-      *first = 0;
-      *incr = 1;               /* so that count % incr works */
-      return GL_FALSE;
-   }
-}
-
-
-
-void
-vbo_split_prims(struct gl_context *ctx,
-                const struct gl_vertex_array arrays[],
-                const struct _mesa_prim *prim,
-                GLuint nr_prims,
-                const struct _mesa_index_buffer *ib,
-                GLuint min_index,
-                GLuint max_index,
-                vbo_draw_func draw,
-                const struct split_limits *limits)
-{
-   if (ib) {
-      if (limits->max_indices == 0) {
-         /* Could traverse the indices, re-emitting vertices in turn.
-          * But it's hard to see why this case would be needed - for
-          * software tnl, it is better to convert to non-indexed
-          * rendering after transformation is complete.  Are there any devices
-          * with hardware tnl that cannot do indexed rendering?
-          *
-          * For now, this path is disabled.
-          */
-         assert(0);
-      }
-      else if (max_index - min_index >= limits->max_verts) {
-         /* The vertex buffers are too large for hardware (or the
-          * swtnl module).  Traverse the indices, re-emitting vertices
-          * in turn.  Use a vertex cache to preserve some of the
-          * sharing from the original index list.
-          */
-         vbo_split_copy(ctx, arrays, prim, nr_prims, ib, draw, limits);
-      }
-      else if (ib->count > limits->max_indices) {
-         /* The index buffer is too large for hardware.  Try to split
-          * on whole-primitive boundaries, otherwise try to split the
-          * individual primitives.
-          */
-         vbo_split_inplace(ctx, arrays, prim, nr_prims, ib,
-                           min_index, max_index, draw, limits);
-      }
-      else {
-         /* Why were we called? */
-         assert(0);
-      }
-   }
-   else {
-      if (max_index - min_index >= limits->max_verts) {
-         /* The vertex buffer is too large for hardware (or the swtnl
-          * module).  Try to split on whole-primitive boundaries,
-          * otherwise try to split the individual primitives.
-          */
-         vbo_split_inplace(ctx, arrays, prim, nr_prims, ib,
-                           min_index, max_index, draw, limits);
-      }
-      else {
-         /* Why were we called? */
-         assert(0);
-      }
-   }
-}
-
diff --git a/src/mesa/vbo/vbo_split.h b/src/mesa/vbo/vbo_split.h
deleted file mode 100644 (file)
index fea2b48..0000000
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * mesa 3-D graphics library
- *
- * Copyright (C) 1999-2006  Brian Paul   All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * 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
- * 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.
- */
-
-/**
- * \brief VBO builder module datatypes and definitions.
- * \author Keith Whitwell
- */
-
-
-/**
- * \mainpage The VBO splitter
- *
- * This is the private data used internally to the vbo_split_prims()
- * helper function.  Nobody outside the vbo_split* files needs to
- * include or know about this structure.
- */
-
-
-#ifndef _VBO_SPLIT_H
-#define _VBO_SPLIT_H
-
-#include "vbo.h"
-
-
-/* True if a primitive can be split without copying of vertices, false
- * otherwise.
- */
-GLboolean
-split_prim_inplace(GLenum mode, GLuint *first, GLuint *incr);
-
-void
-vbo_split_inplace(struct gl_context *ctx,
-                  const struct gl_vertex_array arrays[],
-                  const struct _mesa_prim *prim,
-                  GLuint nr_prims,
-                  const struct _mesa_index_buffer *ib,
-                  GLuint min_index,
-                  GLuint max_index,
-                  vbo_draw_func draw,
-                  const struct split_limits *limits);
-
-/* Requires ib != NULL:
- */
-void
-vbo_split_copy(struct gl_context *ctx,
-               const struct gl_vertex_array arrays[],
-               const struct _mesa_prim *prim,
-               GLuint nr_prims,
-               const struct _mesa_index_buffer *ib,
-               vbo_draw_func draw,
-               const struct split_limits *limits);
-
-#endif
diff --git a/src/mesa/vbo/vbo_split_copy.c b/src/mesa/vbo/vbo_split_copy.c
deleted file mode 100644 (file)
index 2aab670..0000000
+++ /dev/null
@@ -1,637 +0,0 @@
-
-/*
- * Mesa 3-D graphics library
- *
- * Copyright (C) 1999-2006  Brian Paul   All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * 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
- * 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 <keithw@vmware.com>
- */
-
-/* Split indexed primitives with per-vertex copying.
- */
-
-#include <stdio.h>
-
-#include "main/glheader.h"
-#include "main/bufferobj.h"
-#include "main/imports.h"
-#include "main/glformats.h"
-#include "main/macros.h"
-#include "main/mtypes.h"
-#include "main/varray.h"
-
-#include "vbo_split.h"
-#include "vbo.h"
-
-
-#define ELT_TABLE_SIZE 16
-
-/**
- * Used for vertex-level splitting of indexed buffers.  Note that
- * non-indexed primitives may be converted to indexed in some cases
- * (eg loops, fans) in order to use this splitting path.
- */
-struct copy_context {
-   struct gl_context *ctx;
-   const struct gl_vertex_array *array;
-   const struct _mesa_prim *prim;
-   GLuint nr_prims;
-   const struct _mesa_index_buffer *ib;
-   vbo_draw_func draw;
-
-   const struct split_limits *limits;
-
-   struct {
-      GLuint attr;
-      GLuint size;
-      const struct gl_vertex_array *array;
-      const GLubyte *src_ptr;
-
-      struct gl_vertex_buffer_binding dstbinding;
-      struct gl_array_attributes dstattribs;
-
-   } varying[VERT_ATTRIB_MAX];
-   GLuint nr_varying;
-
-   struct gl_vertex_array dstarray[VERT_ATTRIB_MAX];
-   struct _mesa_index_buffer dstib;
-
-   GLuint *translated_elt_buf;
-   const GLuint *srcelt;
-
-   /** A baby hash table to avoid re-emitting (some) duplicate
-    * vertices when splitting indexed primitives.
-    */
-   struct {
-      GLuint in;
-      GLuint out;
-   } vert_cache[ELT_TABLE_SIZE];
-
-   GLuint vertex_size;
-   GLubyte *dstbuf;
-   GLubyte *dstptr;     /**< dstptr == dstbuf + dstelt_max * vertsize */
-   GLuint dstbuf_size;  /**< in vertices */
-   GLuint dstbuf_nr;    /**< count of emitted vertices, also the largest value
-                         * in dstelt.  Our MaxIndex.
-                         */
-
-   GLuint *dstelt;
-   GLuint dstelt_nr;
-   GLuint dstelt_size;
-
-#define MAX_PRIM 32
-   struct _mesa_prim dstprim[MAX_PRIM];
-   GLuint dstprim_nr;
-};
-
-
-static GLuint
-attr_size(const struct gl_array_attributes *attrib)
-{
-   return attrib->Size * _mesa_sizeof_type(attrib->Type);
-}
-
-
-/**
- * Starts returning true slightly before the buffer fills, to ensure
- * that there is sufficient room for any remaining vertices to finish
- * off the prim:
- */
-static GLboolean
-check_flush(struct copy_context *copy)
-{
-   GLenum mode = copy->dstprim[copy->dstprim_nr].mode;
-
-   if (GL_TRIANGLE_STRIP == mode &&
-       copy->dstelt_nr & 1) { /* see bug9962 */
-       return GL_FALSE;
-   }
-
-   if (copy->dstbuf_nr + 4 > copy->dstbuf_size)
-      return GL_TRUE;
-
-   if (copy->dstelt_nr + 4 > copy->dstelt_size)
-      return GL_TRUE;
-
-   return GL_FALSE;
-}
-
-
-/**
- * Dump the parameters/info for a vbo->draw() call.
- */
-static void
-dump_draw_info(struct gl_context *ctx,
-               const struct gl_vertex_array *arrays,
-               const struct _mesa_prim *prims,
-               GLuint nr_prims,
-               const struct _mesa_index_buffer *ib,
-               GLuint min_index,
-               GLuint max_index)
-{
-   GLuint i, j;
-
-   printf("VBO Draw:\n");
-   for (i = 0; i < nr_prims; i++) {
-      printf("Prim %u of %u\n", i, nr_prims);
-      printf("  Prim mode 0x%x\n", prims[i].mode);
-      printf("  IB: %p\n", (void*) ib);
-      for (j = 0; j < VERT_ATTRIB_MAX; j++) {
-         const struct gl_vertex_array *array = &arrays[j];
-         const struct gl_vertex_buffer_binding *binding
-            = array->BufferBinding;
-         const struct gl_array_attributes *attrib = array->VertexAttrib;
-         const GLubyte *ptr = _mesa_vertex_attrib_address(attrib, binding);
-         printf("    array %d at %p:\n", j, (void*) &arrays[j]);
-         printf("      ptr %p, size %d, type 0x%x, stride %d\n",
-                ptr, attrib->Size, attrib->Type, binding->Stride);
-         if (0) {
-            GLint k = prims[i].start + prims[i].count - 1;
-            GLfloat *last = (GLfloat *) (ptr + binding->Stride * k);
-            printf("        last: %f %f %f\n",
-                   last[0], last[1], last[2]);
-         }
-      }
-   }
-}
-
-
-static void
-flush(struct copy_context *copy)
-{
-   struct gl_context *ctx = copy->ctx;
-   GLuint i;
-
-   /* Set some counters:
-    */
-   copy->dstib.count = copy->dstelt_nr;
-
-#if 0
-   dump_draw_info(copy->ctx,
-                  copy->dstarray,
-                  copy->dstprim,
-                  copy->dstprim_nr,
-                  &copy->dstib,
-                  0,
-                  copy->dstbuf_nr);
-#else
-   (void) dump_draw_info;
-#endif
-
-   copy->draw(ctx,
-              copy->dstarray,
-              copy->dstprim,
-              copy->dstprim_nr,
-              &copy->dstib,
-              GL_TRUE,
-              0,
-              copy->dstbuf_nr - 1,
-              NULL, 0, NULL);
-
-   /* Reset all pointers:
-    */
-   copy->dstprim_nr = 0;
-   copy->dstelt_nr = 0;
-   copy->dstbuf_nr = 0;
-   copy->dstptr = copy->dstbuf;
-
-   /* Clear the vertex cache:
-    */
-   for (i = 0; i < ELT_TABLE_SIZE; i++)
-      copy->vert_cache[i].in = ~0;
-}
-
-
-/**
- * Called at begin of each primitive during replay.
- */
-static void
-begin(struct copy_context *copy, GLenum mode, GLboolean begin_flag)
-{
-   struct _mesa_prim *prim = &copy->dstprim[copy->dstprim_nr];
-
-   prim->mode = mode;
-   prim->begin = begin_flag;
-   prim->num_instances = 1;
-}
-
-
-/**
- * Use a hashtable to attempt to identify recently-emitted vertices
- * and avoid re-emitting them.
- */
-static GLuint
-elt(struct copy_context *copy, GLuint elt_idx)
-{
-   GLuint elt = copy->srcelt[elt_idx] + copy->prim->basevertex;
-   GLuint slot = elt & (ELT_TABLE_SIZE-1);
-
-   /* Look up the incoming element in the vertex cache.  Re-emit if
-    * necessary.
-    */
-   if (copy->vert_cache[slot].in != elt) {
-      GLubyte *csr = copy->dstptr;
-      GLuint i;
-
-      for (i = 0; i < copy->nr_varying; i++) {
-         const struct gl_vertex_array *srcarray = copy->varying[i].array;
-         const struct gl_vertex_buffer_binding* srcbinding
-            = srcarray->BufferBinding;
-         const GLubyte *srcptr
-            = copy->varying[i].src_ptr + elt * srcbinding->Stride;
-
-         memcpy(csr, srcptr, copy->varying[i].size);
-         csr += copy->varying[i].size;
-
-#ifdef NAN_CHECK
-         if (srcarray->Type == GL_FLOAT) {
-            GLuint k;
-            GLfloat *f = (GLfloat *) srcptr;
-            for (k = 0; k < srcarray->Size; k++) {
-               assert(!IS_INF_OR_NAN(f[k]));
-               assert(f[k] <= 1.0e20 && f[k] >= -1.0e20);
-            }
-         }
-#endif
-
-         if (0) {
-            const GLuint *f = (const GLuint *)srcptr;
-            GLuint j;
-            printf("  varying %d: ", i);
-            for (j = 0; j < copy->varying[i].size / 4; j++)
-               printf("%x ", f[j]);
-            printf("\n");
-         }
-      }
-
-      copy->vert_cache[slot].in = elt;
-      copy->vert_cache[slot].out = copy->dstbuf_nr++;
-      copy->dstptr += copy->vertex_size;
-
-      assert(csr == copy->dstptr);
-      assert(copy->dstptr == (copy->dstbuf +
-                              copy->dstbuf_nr * copy->vertex_size));
-   }
-
-   copy->dstelt[copy->dstelt_nr++] = copy->vert_cache[slot].out;
-   return check_flush(copy);
-}
-
-
-/**
- * Called at end of each primitive during replay.
- */
-static void
-end(struct copy_context *copy, GLboolean end_flag)
-{
-   struct _mesa_prim *prim = &copy->dstprim[copy->dstprim_nr];
-
-   prim->end = end_flag;
-   prim->count = copy->dstelt_nr - prim->start;
-
-   if (++copy->dstprim_nr == MAX_PRIM || check_flush(copy)) {
-      flush(copy);
-   }
-}
-
-
-static void
-replay_elts(struct copy_context *copy)
-{
-   GLuint i, j, k;
-   GLboolean split;
-
-   for (i = 0; i < copy->nr_prims; i++) {
-      const struct _mesa_prim *prim = &copy->prim[i];
-      const GLuint start = prim->start;
-      GLuint first, incr;
-
-      switch (prim->mode) {
-      case GL_LINE_LOOP:
-         /* Convert to linestrip and emit the final vertex explicitly,
-          * but only in the resultant strip that requires it.
-          */
-         j = 0;
-         while (j != prim->count) {
-            begin(copy, GL_LINE_STRIP, prim->begin && j == 0);
-
-            for (split = GL_FALSE; j != prim->count && !split; j++)
-               split = elt(copy, start + j);
-
-            if (j == prim->count) {
-               /* Done, emit final line.  Split doesn't matter as
-                * it is always raised a bit early so we can emit
-                * the last verts if necessary!
-                */
-               if (prim->end)
-                  (void)elt(copy, start + 0);
-
-               end(copy, prim->end);
-            }
-            else {
-               /* Wrap
-                */
-               assert(split);
-               end(copy, 0);
-               j--;
-            }
-         }
-         break;
-
-      case GL_TRIANGLE_FAN:
-      case GL_POLYGON:
-         j = 2;
-         while (j != prim->count) {
-            begin(copy, prim->mode, prim->begin && j == 0);
-
-            split = elt(copy, start+0);
-            assert(!split);
-
-            split = elt(copy, start+j-1);
-            assert(!split);
-
-            for (; j != prim->count && !split; j++)
-               split = elt(copy, start+j);
-
-            end(copy, prim->end && j == prim->count);
-
-            if (j != prim->count) {
-               /* Wrapped the primitive, need to repeat some vertices:
-                */
-               j -= 1;
-            }
-         }
-         break;
-
-      default:
-         (void)split_prim_inplace(prim->mode, &first, &incr);
-
-         j = 0;
-         while (j != prim->count) {
-
-            begin(copy, prim->mode, prim->begin && j == 0);
-
-            split = 0;
-            for (k = 0; k < first; k++, j++)
-               split |= elt(copy, start+j);
-
-            assert(!split);
-
-            for (; j != prim->count && !split;)
-               for (k = 0; k < incr; k++, j++)
-                  split |= elt(copy, start+j);
-
-            end(copy, prim->end && j == prim->count);
-
-            if (j != prim->count) {
-               /* Wrapped the primitive, need to repeat some vertices:
-                */
-               assert(j > first - incr);
-               j -= (first - incr);
-            }
-         }
-         break;
-      }
-   }
-
-   if (copy->dstprim_nr)
-      flush(copy);
-}
-
-
-static void
-replay_init(struct copy_context *copy)
-{
-   struct gl_context *ctx = copy->ctx;
-   GLuint i;
-   GLuint offset;
-   const GLvoid *srcptr;
-
-   /* Make a list of varying attributes and their vbo's.  Also
-    * calculate vertex size.
-    */
-   copy->vertex_size = 0;
-   for (i = 0; i < VERT_ATTRIB_MAX; i++) {
-      const struct gl_vertex_array *array = &copy->array[i];
-      const struct gl_vertex_buffer_binding *binding = array->BufferBinding;
-
-      if (binding->Stride == 0) {
-         _mesa_copy_vertex_array(&copy->dstarray[i], array);
-      }
-      else {
-         const struct gl_array_attributes *attrib = array->VertexAttrib;
-         struct gl_buffer_object *vbo = binding->BufferObj;
-         const GLubyte *ptr = _mesa_vertex_attrib_address(attrib, binding);
-         GLuint j = copy->nr_varying++;
-
-         copy->varying[j].attr = i;
-         copy->varying[j].array = &copy->array[i];
-         copy->varying[j].size = attr_size(attrib);
-         copy->vertex_size += attr_size(attrib);
-
-         if (_mesa_is_bufferobj(vbo) &&
-             !_mesa_bufferobj_mapped(vbo, MAP_INTERNAL))
-            ctx->Driver.MapBufferRange(ctx, 0, vbo->Size, GL_MAP_READ_BIT, vbo,
-                                       MAP_INTERNAL);
-
-         copy->varying[j].src_ptr =
-               ADD_POINTERS(vbo->Mappings[MAP_INTERNAL].Pointer, ptr);
-
-         copy->dstarray[i].VertexAttrib = &copy->varying[j].dstattribs;
-         copy->dstarray[i].BufferBinding = &copy->varying[j].dstbinding;
-      }
-   }
-
-   /* There must always be an index buffer.  Currently require the
-    * caller convert non-indexed prims to indexed.  Could alternately
-    * do it internally.
-    */
-   if (_mesa_is_bufferobj(copy->ib->obj) &&
-       !_mesa_bufferobj_mapped(copy->ib->obj, MAP_INTERNAL))
-      ctx->Driver.MapBufferRange(ctx, 0, copy->ib->obj->Size, GL_MAP_READ_BIT,
-                                 copy->ib->obj, MAP_INTERNAL);
-
-   srcptr = (const GLubyte *)
-            ADD_POINTERS(copy->ib->obj->Mappings[MAP_INTERNAL].Pointer,
-                         copy->ib->ptr);
-
-   switch (copy->ib->index_size) {
-   case 1:
-      copy->translated_elt_buf = malloc(sizeof(GLuint) * copy->ib->count);
-      copy->srcelt = copy->translated_elt_buf;
-
-      for (i = 0; i < copy->ib->count; i++)
-         copy->translated_elt_buf[i] = ((const GLubyte *)srcptr)[i];
-      break;
-
-   case 2:
-      copy->translated_elt_buf = malloc(sizeof(GLuint) * copy->ib->count);
-      copy->srcelt = copy->translated_elt_buf;
-
-      for (i = 0; i < copy->ib->count; i++)
-         copy->translated_elt_buf[i] = ((const GLushort *)srcptr)[i];
-      break;
-
-   case 4:
-      copy->translated_elt_buf = NULL;
-      copy->srcelt = (const GLuint *)srcptr;
-      break;
-   }
-
-   /* Figure out the maximum allowed vertex buffer size:
-    */
-   if (copy->vertex_size * copy->limits->max_verts <= copy->limits->max_vb_size) {
-      copy->dstbuf_size = copy->limits->max_verts;
-   }
-   else {
-      copy->dstbuf_size = copy->limits->max_vb_size / copy->vertex_size;
-   }
-
-   /* Allocate an output vertex buffer:
-    *
-    * XXX:  This should be a VBO!
-    */
-   copy->dstbuf = malloc(copy->dstbuf_size * copy->vertex_size);
-   copy->dstptr = copy->dstbuf;
-
-   /* Setup new vertex arrays to point into the output buffer:
-    */
-   for (offset = 0, i = 0; i < copy->nr_varying; i++) {
-      const struct gl_vertex_array *src = copy->varying[i].array;
-      const struct gl_array_attributes *srcattr = src->VertexAttrib;
-      struct gl_vertex_array *dst = &copy->dstarray[i];
-      struct gl_vertex_buffer_binding *dstbind = &copy->varying[i].dstbinding;
-      struct gl_array_attributes *dstattr = &copy->varying[i].dstattribs;
-
-      dstattr->Size = srcattr->Size;
-      dstattr->Type = srcattr->Type;
-      dstattr->Format = GL_RGBA;
-      dstbind->Stride = copy->vertex_size;
-      dstattr->Ptr = copy->dstbuf + offset;
-      dstattr->Normalized = srcattr->Normalized;
-      dstattr->Integer = srcattr->Integer;
-      dstattr->Doubles = srcattr->Doubles;
-      dstbind->BufferObj = ctx->Shared->NullBufferObj;
-      dstattr->_ElementSize = srcattr->_ElementSize;
-      dst->BufferBinding = dstbind;
-      dst->VertexAttrib = dstattr;
-
-      offset += copy->varying[i].size;
-   }
-
-   /* Allocate an output element list:
-    */
-   copy->dstelt_size = MIN2(65536, copy->ib->count * 2 + 3);
-   copy->dstelt_size = MIN2(copy->dstelt_size, copy->limits->max_indices);
-   copy->dstelt = malloc(sizeof(GLuint) * copy->dstelt_size);
-   copy->dstelt_nr = 0;
-
-   /* Setup the new index buffer to point to the allocated element
-    * list:
-    */
-   copy->dstib.count = 0;        /* duplicates dstelt_nr */
-   copy->dstib.index_size = 4;
-   copy->dstib.obj = ctx->Shared->NullBufferObj;
-   copy->dstib.ptr = copy->dstelt;
-}
-
-
-/**
- * Free up everything allocated during split/replay.
- */
-static void
-replay_finish(struct copy_context *copy)
-{
-   struct gl_context *ctx = copy->ctx;
-   GLuint i;
-
-   /* Free our vertex and index buffers */
-   free(copy->translated_elt_buf);
-   free(copy->dstbuf);
-   free(copy->dstelt);
-
-   /* Unmap VBO's */
-   for (i = 0; i < copy->nr_varying; i++) {
-      struct gl_buffer_object *vbo =
-         copy->varying[i].array->BufferBinding->BufferObj;
-      if (_mesa_is_bufferobj(vbo) && _mesa_bufferobj_mapped(vbo, MAP_INTERNAL))
-         ctx->Driver.UnmapBuffer(ctx, vbo, MAP_INTERNAL);
-   }
-
-   /* Unmap index buffer */
-   if (_mesa_is_bufferobj(copy->ib->obj) &&
-       _mesa_bufferobj_mapped(copy->ib->obj, MAP_INTERNAL)) {
-      ctx->Driver.UnmapBuffer(ctx, copy->ib->obj, MAP_INTERNAL);
-   }
-}
-
-
-/**
- * Split VBO into smaller pieces, draw the pieces.
- */
-void
-vbo_split_copy(struct gl_context *ctx,
-               const struct gl_vertex_array *arrays,
-               const struct _mesa_prim *prim,
-               GLuint nr_prims,
-               const struct _mesa_index_buffer *ib,
-               vbo_draw_func draw,
-               const struct split_limits *limits)
-{
-   struct copy_context copy;
-   GLuint i, this_nr_prims;
-
-   for (i = 0; i < nr_prims;) {
-      /* Our SW TNL pipeline doesn't handle basevertex yet, so bind_indices
-       * will rebase the elements to the basevertex, and we'll only
-       * emit strings of prims with the same basevertex in one draw call.
-       */
-      for (this_nr_prims = 1; i + this_nr_prims < nr_prims;
-           this_nr_prims++) {
-         if (prim[i].basevertex != prim[i + this_nr_prims].basevertex)
-            break;
-      }
-
-      memset(&copy, 0, sizeof(copy));
-
-      /* Require indexed primitives:
-       */
-      assert(ib);
-
-      copy.ctx = ctx;
-      copy.array = arrays;
-      copy.prim = &prim[i];
-      copy.nr_prims = this_nr_prims;
-      copy.ib = ib;
-      copy.draw = draw;
-      copy.limits = limits;
-
-      /* Clear the vertex cache:
-       */
-      for (i = 0; i < ELT_TABLE_SIZE; i++)
-         copy.vert_cache[i].in = ~0;
-
-      replay_init(&copy);
-      replay_elts(&copy);
-      replay_finish(&copy);
-   }
-}
diff --git a/src/mesa/vbo/vbo_split_inplace.c b/src/mesa/vbo/vbo_split_inplace.c
deleted file mode 100644 (file)
index b63c05c..0000000
+++ /dev/null
@@ -1,295 +0,0 @@
-
-/*
- * Mesa 3-D graphics library
- *
- * Copyright (C) 1999-2006  Brian Paul   All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * 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
- * 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 <keithw@vmware.com>
- */
-
-
-#include "main/mtypes.h"
-#include "main/macros.h"
-#include "main/enums.h"
-#include "vbo_split.h"
-
-
-#define MAX_PRIM 32
-
-/* 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 {
-   struct gl_context *ctx;
-   const struct gl_vertex_array *array;
-   const struct _mesa_prim *prim;
-   GLuint nr_prims;
-   const struct _mesa_index_buffer *ib;
-   GLuint min_index;
-   GLuint max_index;
-   vbo_draw_func draw;
-
-   const struct split_limits *limits;
-   GLuint limit;
-
-   struct _mesa_prim dstprim[MAX_PRIM];
-   GLuint dstprim_nr;
-};
-
-
-
-
-static void
-flush_vertex( struct split_context *split)
-{
-   struct gl_context *ctx = split->ctx;
-   struct _mesa_index_buffer ib;
-   GLuint i;
-
-   if (!split->dstprim_nr)
-      return;
-
-   if (split->ib) {
-      ib = *split->ib;
-
-      ib.count = split->max_index - split->min_index + 1;
-      ib.ptr = (const void *)((const char *)ib.ptr +
-                              split->min_index * ib.index_size);
-
-      /* Rebase the primitives to save index buffer entries. */
-      for (i = 0; i < split->dstprim_nr; i++)
-         split->dstprim[i].start -= split->min_index;
-   }
-
-   assert(split->max_index >= split->min_index);
-
-   split->draw(ctx,
-               split->array,
-               split->dstprim,
-               split->dstprim_nr,
-               split->ib ? &ib : NULL,
-               !split->ib,
-               split->min_index,
-               split->max_index,
-               NULL, 0, NULL);
-
-   split->dstprim_nr = 0;
-   split->min_index = ~0;
-   split->max_index = 0;
-}
-
-
-static struct _mesa_prim *
-next_outprim(struct split_context *split)
-{
-   if (split->dstprim_nr == MAX_PRIM-1) {
-      flush_vertex(split);
-   }
-
-   {
-      struct _mesa_prim *prim = &split->dstprim[split->dstprim_nr++];
-      memset(prim, 0, sizeof(*prim));
-      return prim;
-   }
-}
-
-
-static void
-update_index_bounds(struct split_context *split,
-                    const struct _mesa_prim *prim)
-{
-   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 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 available = get_max_vertices(split, prim);
-      GLuint count = prim->count - (prim->count - first) % incr;
-
-      if (prim->count < first)
-         continue;
-
-      if ((available < count && !split_inplace) ||
-          (available < first && split_inplace)) {
-         flush_vertex(split);
-         available = get_max_vertices(split, prim);
-      }
-
-      if (available >= count) {
-         struct _mesa_prim *outprim = next_outprim(split);
-
-         *outprim = *prim;
-         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;
-            }
-            else {
-               /* Wrapped the primitive */
-               j += nr - (first - incr);
-               flush_vertex(split);
-               available = get_max_vertices(split, prim);
-            }
-         }
-      }
-      else if (split->ib == NULL) {
-         /* XXX: could at least send the first max_verts off from the
-          * inplace buffers.
-          */
-
-         /* else convert to indexed primitive and pass to split_elts,
-          * which will do the necessary copying and turn it back into a
-          * vertex primitive for rendering...
-          */
-         struct _mesa_index_buffer ib;
-         struct _mesa_prim tmpprim;
-         GLuint *elts = malloc(count * sizeof(GLuint));
-         GLuint j;
-
-         for (j = 0; j < count; j++)
-            elts[j] = prim->start + j;
-
-         ib.count = count;
-         ib.index_size = 4;
-         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);
-
-         vbo_split_copy(split->ctx,
-                        split->array,
-                        &tmpprim, 1,
-                        &ib,
-                        split->draw,
-                        split->limits);
-
-         free(elts);
-      }
-      else {
-         flush_vertex(split);
-
-         vbo_split_copy(split->ctx,
-                        split->array,
-                        prim, 1,
-                        split->ib,
-                        split->draw,
-                        split->limits);
-      }
-   }
-
-   flush_vertex(split);
-}
-
-
-void
-vbo_split_inplace(struct gl_context *ctx,
-                  const struct gl_vertex_array *arrays,
-                  const struct _mesa_prim *prim,
-                  GLuint nr_prims,
-                  const struct _mesa_index_buffer *ib,
-                  GLuint min_index,
-                  GLuint max_index,
-                  vbo_draw_func draw,
-                  const struct split_limits *limits)
-{
-   struct split_context split;
-
-   memset(&split, 0, sizeof(split));
-
-   split.ctx = ctx;
-   split.array = arrays;
-   split.prim = prim;
-   split.nr_prims = nr_prims;
-   split.ib = ib;
-
-   /* 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);
-}
-
-