1 
2 /*
3  * Mesa 3-D graphics library
4  * Version:  6.5
5  *
6  * Copyright (C) 1999-2006  Brian Paul   All Rights Reserved.
7  *
8  * Permission is hereby granted, free of charge, to any person obtaining a
9  * copy of this software and associated documentation files (the "Software"),
10  * to deal in the Software without restriction, including without limitation
11  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12  * and/or sell copies of the Software, and to permit persons to whom the
13  * Software is furnished to do so, subject to the following conditions:
14  *
15  * The above copyright notice and this permission notice shall be included
16  * in all copies or substantial portions of the Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
21  * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
22  * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24  *
25  * Authors:
26  *    Keith Whitwell <keith@tungstengraphics.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/imports.h"
52 #include "main/mtypes.h"
53 #include "main/macros.h"
54 
55 #include "vbo_split.h"
56 #include "vbo.h"
57 
58 /* True if a primitive can be split without copying of vertices, false
59  * otherwise.
60  */
split_prim_inplace(GLenum mode,GLuint * first,GLuint * incr)61 GLboolean 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 
vbo_split_prims(struct gl_context * ctx,const struct gl_client_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)101 void vbo_split_prims( struct gl_context *ctx,
102 		      const struct gl_client_array *arrays[],
103 		      const struct _mesa_prim *prim,
104 		      GLuint nr_prims,
105 		      const struct _mesa_index_buffer *ib,
106 		      GLuint min_index,
107 		      GLuint max_index,
108 		      vbo_draw_func draw,
109 		      const struct split_limits *limits )
110 {
111    GLint max_basevertex = prim->basevertex;
112    GLuint i;
113 
114    for (i = 1; i < nr_prims; i++)
115       max_basevertex = MAX2(max_basevertex, prim[i].basevertex);
116 
117    /* XXX max_basevertex is computed but not used, why? */
118 
119    if (ib) {
120       if (limits->max_indices == 0) {
121 	 /* Could traverse the indices, re-emitting vertices in turn.
122 	  * But it's hard to see why this case would be needed - for
123 	  * software tnl, it is better to convert to non-indexed
124 	  * rendering after transformation is complete.  Are there any devices
125 	  * with hardware tnl that cannot do indexed rendering?
126 	  *
127 	  * For now, this path is disabled.
128 	  */
129 	 assert(0);
130       }
131       else if (max_index - min_index >= limits->max_verts) {
132 	 /* The vertex buffers are too large for hardware (or the
133 	  * swtnl module).  Traverse the indices, re-emitting vertices
134 	  * in turn.  Use a vertex cache to preserve some of the
135 	  * sharing from the original index list.
136 	  */
137 	 vbo_split_copy(ctx, arrays, prim, nr_prims, ib,
138 			draw, limits );
139       }
140       else if (ib->count > limits->max_indices) {
141 	 /* The index buffer is too large for hardware.  Try to split
142 	  * on whole-primitive boundaries, otherwise try to split the
143 	  * individual primitives.
144 	  */
145 	 vbo_split_inplace(ctx, arrays, prim, nr_prims, ib,
146 			   min_index, max_index, draw, limits );
147       }
148       else {
149 	 /* Why were we called? */
150 	 assert(0);
151       }
152    }
153    else {
154       if (max_index - min_index >= limits->max_verts) {
155 	 /* The vertex buffer is too large for hardware (or the swtnl
156 	  * module).  Try to split on whole-primitive boundaries,
157 	  * otherwise try to split the individual primitives.
158 	  */
159 	 vbo_split_inplace(ctx, arrays, prim, nr_prims, ib,
160 			   min_index, max_index, draw, limits );
161       }
162       else {
163 	 /* Why were we called? */
164 	 assert(0);
165       }
166    }
167 }
168 
169