101e04c3fSmrg
201e04c3fSmrg/*
301e04c3fSmrg * Mesa 3-D graphics library
401e04c3fSmrg *
501e04c3fSmrg * Copyright (C) 1999-2006  Brian Paul   All Rights Reserved.
601e04c3fSmrg *
701e04c3fSmrg * Permission is hereby granted, free of charge, to any person obtaining a
801e04c3fSmrg * copy of this software and associated documentation files (the "Software"),
901e04c3fSmrg * to deal in the Software without restriction, including without limitation
1001e04c3fSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
1101e04c3fSmrg * and/or sell copies of the Software, and to permit persons to whom the
1201e04c3fSmrg * Software is furnished to do so, subject to the following conditions:
1301e04c3fSmrg *
1401e04c3fSmrg * The above copyright notice and this permission notice shall be included
1501e04c3fSmrg * in all copies or substantial portions of the Software.
1601e04c3fSmrg *
1701e04c3fSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
1801e04c3fSmrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1901e04c3fSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
2001e04c3fSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
2101e04c3fSmrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
2201e04c3fSmrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
2301e04c3fSmrg * OTHER DEALINGS IN THE SOFTWARE.
2401e04c3fSmrg *
2501e04c3fSmrg * Authors:
2601e04c3fSmrg *    Keith Whitwell <keithw@vmware.com>
2701e04c3fSmrg */
2801e04c3fSmrg
2901e04c3fSmrg/* Deal with hardware and/or swtnl maximums:
3001e04c3fSmrg * - maximum number of vertices in buffer
3101e04c3fSmrg * - maximum number of elements (maybe zero)
3201e04c3fSmrg *
3301e04c3fSmrg * The maximums may vary with opengl state (eg if a larger hardware
3401e04c3fSmrg * vertex is required in this state, the maximum number of vertices
3501e04c3fSmrg * may be smaller than in another state).
3601e04c3fSmrg *
3701e04c3fSmrg * We want buffer splitting to be a convenience function for the code
3801e04c3fSmrg * actually drawing the primitives rather than a system-wide maximum,
3901e04c3fSmrg * otherwise it is hard to avoid pessimism.
4001e04c3fSmrg *
4101e04c3fSmrg * For instance, if a driver has no hardware limits on vertex buffer
4201e04c3fSmrg * dimensions, it would not ordinarily want to split vbos.  But if
4301e04c3fSmrg * there is an unexpected fallback, eg memory manager fails to upload
4401e04c3fSmrg * textures, it will want to pass the drawing commands onto swtnl,
4501e04c3fSmrg * which does have limitations.  A convenience function allows swtnl
4601e04c3fSmrg * to split the drawing and vbos internally without imposing its
4701e04c3fSmrg * limitations on drivers which want to use it as a fallback path.
4801e04c3fSmrg */
4901e04c3fSmrg
5001e04c3fSmrg#include "main/glheader.h"
5101e04c3fSmrg#include "main/mtypes.h"
5201e04c3fSmrg#include "vbo/vbo.h"
5301e04c3fSmrg
5401e04c3fSmrg#include "t_split.h"
5501e04c3fSmrg
5601e04c3fSmrg
5701e04c3fSmrg/* True if a primitive can be split without copying of vertices, false
5801e04c3fSmrg * otherwise.
5901e04c3fSmrg */
6001e04c3fSmrgGLboolean
6101e04c3fSmrg_tnl_split_prim_inplace(GLenum mode, GLuint *first, GLuint *incr)
6201e04c3fSmrg{
6301e04c3fSmrg   switch (mode) {
6401e04c3fSmrg   case GL_POINTS:
6501e04c3fSmrg      *first = 1;
6601e04c3fSmrg      *incr = 1;
6701e04c3fSmrg      return GL_TRUE;
6801e04c3fSmrg   case GL_LINES:
6901e04c3fSmrg      *first = 2;
7001e04c3fSmrg      *incr = 2;
7101e04c3fSmrg      return GL_TRUE;
7201e04c3fSmrg   case GL_LINE_STRIP:
7301e04c3fSmrg      *first = 2;
7401e04c3fSmrg      *incr = 1;
7501e04c3fSmrg      return GL_TRUE;
7601e04c3fSmrg   case GL_TRIANGLES:
7701e04c3fSmrg      *first = 3;
7801e04c3fSmrg      *incr = 3;
7901e04c3fSmrg      return GL_TRUE;
8001e04c3fSmrg   case GL_TRIANGLE_STRIP:
8101e04c3fSmrg      *first = 3;
8201e04c3fSmrg      *incr = 1;
8301e04c3fSmrg      return GL_TRUE;
8401e04c3fSmrg   case GL_QUADS:
8501e04c3fSmrg      *first = 4;
8601e04c3fSmrg      *incr = 4;
8701e04c3fSmrg      return GL_TRUE;
8801e04c3fSmrg   case GL_QUAD_STRIP:
8901e04c3fSmrg      *first = 4;
9001e04c3fSmrg      *incr = 2;
9101e04c3fSmrg      return GL_TRUE;
9201e04c3fSmrg   default:
9301e04c3fSmrg      *first = 0;
9401e04c3fSmrg      *incr = 1;		/* so that count % incr works */
9501e04c3fSmrg      return GL_FALSE;
9601e04c3fSmrg   }
9701e04c3fSmrg}
9801e04c3fSmrg
9901e04c3fSmrg
10001e04c3fSmrg
10101e04c3fSmrgvoid
10201e04c3fSmrg_tnl_split_prims(struct gl_context *ctx,
10301e04c3fSmrg                 const struct tnl_vertex_array arrays[],
10401e04c3fSmrg                 const struct _mesa_prim *prim,
10501e04c3fSmrg                 GLuint nr_prims,
10601e04c3fSmrg                 const struct _mesa_index_buffer *ib,
10701e04c3fSmrg                 GLuint min_index,
10801e04c3fSmrg                 GLuint max_index,
1097ec681f3Smrg                 GLuint num_instances,
1107ec681f3Smrg                 GLuint base_instance,
11101e04c3fSmrg                 tnl_draw_func draw,
11201e04c3fSmrg                 const struct split_limits *limits)
11301e04c3fSmrg{
11401e04c3fSmrg   if (ib) {
11501e04c3fSmrg      if (limits->max_indices == 0) {
11601e04c3fSmrg         /* Could traverse the indices, re-emitting vertices in turn.
11701e04c3fSmrg          * But it's hard to see why this case would be needed - for
11801e04c3fSmrg          * software tnl, it is better to convert to non-indexed
11901e04c3fSmrg          * rendering after transformation is complete.  Are there any devices
12001e04c3fSmrg          * with hardware tnl that cannot do indexed rendering?
12101e04c3fSmrg          *
12201e04c3fSmrg          * For now, this path is disabled.
12301e04c3fSmrg          */
12401e04c3fSmrg         assert(0);
12501e04c3fSmrg      }
12601e04c3fSmrg      else if (max_index - min_index >= limits->max_verts) {
12701e04c3fSmrg         /* The vertex buffers are too large for hardware (or the
12801e04c3fSmrg          * swtnl module).  Traverse the indices, re-emitting vertices
12901e04c3fSmrg          * in turn.  Use a vertex cache to preserve some of the
13001e04c3fSmrg          * sharing from the original index list.
13101e04c3fSmrg          */
13201e04c3fSmrg         _tnl_split_copy(ctx, arrays, prim, nr_prims, ib, draw, limits);
13301e04c3fSmrg      }
13401e04c3fSmrg      else if (ib->count > limits->max_indices) {
13501e04c3fSmrg         /* The index buffer is too large for hardware.  Try to split
13601e04c3fSmrg          * on whole-primitive boundaries, otherwise try to split the
13701e04c3fSmrg          * individual primitives.
13801e04c3fSmrg          */
13901e04c3fSmrg         _tnl_split_inplace(ctx, arrays, prim, nr_prims, ib,
1407ec681f3Smrg                            num_instances, base_instance, draw, limits);
14101e04c3fSmrg      }
14201e04c3fSmrg      else {
14301e04c3fSmrg         /* Why were we called? */
14401e04c3fSmrg         assert(0);
14501e04c3fSmrg      }
14601e04c3fSmrg   }
14701e04c3fSmrg   else {
14801e04c3fSmrg      if (max_index - min_index >= limits->max_verts) {
14901e04c3fSmrg         /* The vertex buffer is too large for hardware (or the swtnl
15001e04c3fSmrg          * module).  Try to split on whole-primitive boundaries,
15101e04c3fSmrg          * otherwise try to split the individual primitives.
15201e04c3fSmrg          */
15301e04c3fSmrg         _tnl_split_inplace(ctx, arrays, prim, nr_prims, ib,
1547ec681f3Smrg                            num_instances, base_instance, draw, limits);
15501e04c3fSmrg      }
15601e04c3fSmrg      else {
15701e04c3fSmrg         /* Why were we called? */
15801e04c3fSmrg         assert(0);
15901e04c3fSmrg      }
16001e04c3fSmrg   }
16101e04c3fSmrg}
16201e04c3fSmrg
163