1b8e80941Smrg
2b8e80941Smrg/*
3b8e80941Smrg * Mesa 3-D graphics library
4b8e80941Smrg *
5b8e80941Smrg * Copyright (C) 1999-2006  Brian Paul   All Rights Reserved.
6b8e80941Smrg *
7b8e80941Smrg * Permission is hereby granted, free of charge, to any person obtaining a
8b8e80941Smrg * copy of this software and associated documentation files (the "Software"),
9b8e80941Smrg * to deal in the Software without restriction, including without limitation
10b8e80941Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11b8e80941Smrg * and/or sell copies of the Software, and to permit persons to whom the
12b8e80941Smrg * Software is furnished to do so, subject to the following conditions:
13b8e80941Smrg *
14b8e80941Smrg * The above copyright notice and this permission notice shall be included
15b8e80941Smrg * in all copies or substantial portions of the Software.
16b8e80941Smrg *
17b8e80941Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18b8e80941Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19b8e80941Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20b8e80941Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
21b8e80941Smrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
22b8e80941Smrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23b8e80941Smrg * OTHER DEALINGS IN THE SOFTWARE.
24b8e80941Smrg *
25b8e80941Smrg * Authors:
26b8e80941Smrg *    Keith Whitwell <keithw@vmware.com>
27b8e80941Smrg */
28b8e80941Smrg
29b8e80941Smrg/* Deal with hardware and/or swtnl maximums:
30b8e80941Smrg * - maximum number of vertices in buffer
31b8e80941Smrg * - maximum number of elements (maybe zero)
32b8e80941Smrg *
33b8e80941Smrg * The maximums may vary with opengl state (eg if a larger hardware
34b8e80941Smrg * vertex is required in this state, the maximum number of vertices
35b8e80941Smrg * may be smaller than in another state).
36b8e80941Smrg *
37b8e80941Smrg * We want buffer splitting to be a convenience function for the code
38b8e80941Smrg * actually drawing the primitives rather than a system-wide maximum,
39b8e80941Smrg * otherwise it is hard to avoid pessimism.
40b8e80941Smrg *
41b8e80941Smrg * For instance, if a driver has no hardware limits on vertex buffer
42b8e80941Smrg * dimensions, it would not ordinarily want to split vbos.  But if
43b8e80941Smrg * there is an unexpected fallback, eg memory manager fails to upload
44b8e80941Smrg * textures, it will want to pass the drawing commands onto swtnl,
45b8e80941Smrg * which does have limitations.  A convenience function allows swtnl
46b8e80941Smrg * to split the drawing and vbos internally without imposing its
47b8e80941Smrg * limitations on drivers which want to use it as a fallback path.
48b8e80941Smrg */
49b8e80941Smrg
50b8e80941Smrg#include "main/glheader.h"
51b8e80941Smrg#include "main/mtypes.h"
52b8e80941Smrg#include "vbo/vbo.h"
53b8e80941Smrg
54b8e80941Smrg#include "t_split.h"
55b8e80941Smrg
56b8e80941Smrg
57b8e80941Smrg/* True if a primitive can be split without copying of vertices, false
58b8e80941Smrg * otherwise.
59b8e80941Smrg */
60b8e80941SmrgGLboolean
61b8e80941Smrg_tnl_split_prim_inplace(GLenum mode, GLuint *first, GLuint *incr)
62b8e80941Smrg{
63b8e80941Smrg   switch (mode) {
64b8e80941Smrg   case GL_POINTS:
65b8e80941Smrg      *first = 1;
66b8e80941Smrg      *incr = 1;
67b8e80941Smrg      return GL_TRUE;
68b8e80941Smrg   case GL_LINES:
69b8e80941Smrg      *first = 2;
70b8e80941Smrg      *incr = 2;
71b8e80941Smrg      return GL_TRUE;
72b8e80941Smrg   case GL_LINE_STRIP:
73b8e80941Smrg      *first = 2;
74b8e80941Smrg      *incr = 1;
75b8e80941Smrg      return GL_TRUE;
76b8e80941Smrg   case GL_TRIANGLES:
77b8e80941Smrg      *first = 3;
78b8e80941Smrg      *incr = 3;
79b8e80941Smrg      return GL_TRUE;
80b8e80941Smrg   case GL_TRIANGLE_STRIP:
81b8e80941Smrg      *first = 3;
82b8e80941Smrg      *incr = 1;
83b8e80941Smrg      return GL_TRUE;
84b8e80941Smrg   case GL_QUADS:
85b8e80941Smrg      *first = 4;
86b8e80941Smrg      *incr = 4;
87b8e80941Smrg      return GL_TRUE;
88b8e80941Smrg   case GL_QUAD_STRIP:
89b8e80941Smrg      *first = 4;
90b8e80941Smrg      *incr = 2;
91b8e80941Smrg      return GL_TRUE;
92b8e80941Smrg   default:
93b8e80941Smrg      *first = 0;
94b8e80941Smrg      *incr = 1;		/* so that count % incr works */
95b8e80941Smrg      return GL_FALSE;
96b8e80941Smrg   }
97b8e80941Smrg}
98b8e80941Smrg
99b8e80941Smrg
100b8e80941Smrg
101b8e80941Smrgvoid
102b8e80941Smrg_tnl_split_prims(struct gl_context *ctx,
103b8e80941Smrg                 const struct tnl_vertex_array arrays[],
104b8e80941Smrg                 const struct _mesa_prim *prim,
105b8e80941Smrg                 GLuint nr_prims,
106b8e80941Smrg                 const struct _mesa_index_buffer *ib,
107b8e80941Smrg                 GLuint min_index,
108b8e80941Smrg                 GLuint max_index,
109b8e80941Smrg                 tnl_draw_func draw,
110b8e80941Smrg                 const struct split_limits *limits)
111b8e80941Smrg{
112b8e80941Smrg   if (ib) {
113b8e80941Smrg      if (limits->max_indices == 0) {
114b8e80941Smrg         /* Could traverse the indices, re-emitting vertices in turn.
115b8e80941Smrg          * But it's hard to see why this case would be needed - for
116b8e80941Smrg          * software tnl, it is better to convert to non-indexed
117b8e80941Smrg          * rendering after transformation is complete.  Are there any devices
118b8e80941Smrg          * with hardware tnl that cannot do indexed rendering?
119b8e80941Smrg          *
120b8e80941Smrg          * For now, this path is disabled.
121b8e80941Smrg          */
122b8e80941Smrg         assert(0);
123b8e80941Smrg      }
124b8e80941Smrg      else if (max_index - min_index >= limits->max_verts) {
125b8e80941Smrg         /* The vertex buffers are too large for hardware (or the
126b8e80941Smrg          * swtnl module).  Traverse the indices, re-emitting vertices
127b8e80941Smrg          * in turn.  Use a vertex cache to preserve some of the
128b8e80941Smrg          * sharing from the original index list.
129b8e80941Smrg          */
130b8e80941Smrg         _tnl_split_copy(ctx, arrays, prim, nr_prims, ib, draw, limits);
131b8e80941Smrg      }
132b8e80941Smrg      else if (ib->count > limits->max_indices) {
133b8e80941Smrg         /* The index buffer is too large for hardware.  Try to split
134b8e80941Smrg          * on whole-primitive boundaries, otherwise try to split the
135b8e80941Smrg          * individual primitives.
136b8e80941Smrg          */
137b8e80941Smrg         _tnl_split_inplace(ctx, arrays, prim, nr_prims, ib,
138b8e80941Smrg                            min_index, max_index, draw, limits);
139b8e80941Smrg      }
140b8e80941Smrg      else {
141b8e80941Smrg         /* Why were we called? */
142b8e80941Smrg         assert(0);
143b8e80941Smrg      }
144b8e80941Smrg   }
145b8e80941Smrg   else {
146b8e80941Smrg      if (max_index - min_index >= limits->max_verts) {
147b8e80941Smrg         /* The vertex buffer is too large for hardware (or the swtnl
148b8e80941Smrg          * module).  Try to split on whole-primitive boundaries,
149b8e80941Smrg          * otherwise try to split the individual primitives.
150b8e80941Smrg          */
151b8e80941Smrg         _tnl_split_inplace(ctx, arrays, prim, nr_prims, ib,
152b8e80941Smrg                            min_index, max_index, draw, limits);
153b8e80941Smrg      }
154b8e80941Smrg      else {
155b8e80941Smrg         /* Why were we called? */
156b8e80941Smrg         assert(0);
157b8e80941Smrg      }
158b8e80941Smrg   }
159b8e80941Smrg}
160b8e80941Smrg
161