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