radeon/r600: Fix remaining warnings when building 64 bit binary.
[mesa.git] / src / mesa / vbo / vbo_split_inplace.c
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
30 #include "main/mtypes.h"
31 #include "main/macros.h"
32 #include "main/enums.h"
33 #include "vbo_split.h"
34
35
36 #define MAX_PRIM 32
37
38 /* Used for splitting without copying.
39 */
40 struct split_context {
41 GLcontext *ctx;
42 const struct gl_client_array **array;
43 const struct _mesa_prim *prim;
44 GLuint nr_prims;
45 const struct _mesa_index_buffer *ib;
46 GLuint min_index;
47 GLuint max_index;
48 vbo_draw_func draw;
49
50 const struct split_limits *limits;
51
52 struct _mesa_prim dstprim[MAX_PRIM];
53 GLuint dstprim_nr;
54 };
55
56
57
58
59 static void flush_vertex( struct split_context *split )
60 {
61 GLuint min_index, max_index;
62 GLuint i;
63
64 if (!split->dstprim_nr)
65 return;
66
67 min_index = split->dstprim[0].start;
68 max_index = min_index + split->dstprim[0].count - 1;
69
70 for (i = 1; i < split->dstprim_nr; i++) {
71 GLuint tmp_min = split->dstprim[i].start;
72 GLuint tmp_max = tmp_min + split->dstprim[i].count - 1;
73
74 if (tmp_min < min_index)
75 min_index = tmp_min;
76
77 if (tmp_max > max_index)
78 max_index = tmp_max;
79 }
80
81 assert(max_index >= min_index);
82
83 split->draw( split->ctx,
84 split->array,
85 split->dstprim,
86 split->dstprim_nr,
87 NULL,
88 GL_TRUE,
89 min_index,
90 max_index);
91
92 split->dstprim_nr = 0;
93 }
94
95
96 static struct _mesa_prim *next_outprim( struct split_context *split )
97 {
98 if (split->dstprim_nr == MAX_PRIM-1) {
99 flush_vertex(split);
100 }
101
102 {
103 struct _mesa_prim *prim = &split->dstprim[split->dstprim_nr++];
104 memset(prim, 0, sizeof(*prim));
105 return prim;
106 }
107 }
108
109 static int align(int value, int alignment)
110 {
111 return (value + alignment - 1) & ~(alignment - 1);
112 }
113
114
115
116 /* Break large primitives into smaller ones. If not possible, convert
117 * the primitive to indexed and pass to split_elts().
118 */
119 static void split_prims( struct split_context *split)
120 {
121 GLuint csr = 0;
122 GLuint i;
123
124 for (i = 0; i < split->nr_prims; i++) {
125 const struct _mesa_prim *prim = &split->prim[i];
126 GLuint first, incr;
127 GLboolean split_inplace = split_prim_inplace(prim->mode, &first, &incr);
128 GLuint count;
129
130 /* Always wrap on an even numbered vertex to avoid problems with
131 * triangle strips.
132 */
133 GLuint available = align(split->limits->max_verts - csr - 1, 2);
134 assert(split->limits->max_verts >= csr);
135
136 if (prim->count < first)
137 continue;
138
139 count = prim->count - (prim->count - first) % incr;
140
141
142 if ((available < count && !split_inplace) ||
143 (available < first && split_inplace)) {
144 flush_vertex(split);
145 csr = 0;
146 available = align(split->limits->max_verts - csr - 1, 2);
147 }
148
149 if (available >= count) {
150 struct _mesa_prim *outprim = next_outprim(split);
151 *outprim = *prim;
152 csr += prim->count;
153 available = align(split->limits->max_verts - csr - 1, 2);
154 }
155 else if (split_inplace) {
156 GLuint j, nr;
157
158
159 for (j = 0 ; j < count ; ) {
160 GLuint remaining = count - j;
161 struct _mesa_prim *outprim = next_outprim(split);
162
163 nr = MIN2( available, remaining );
164
165 nr -= (nr - first) % incr;
166
167 outprim->mode = prim->mode;
168 outprim->begin = (j == 0 && prim->begin);
169 outprim->end = (nr == remaining && prim->end);
170 outprim->start = prim->start + j;
171 outprim->count = nr;
172
173 if (nr == remaining) {
174 /* Finished.
175 */
176 j += nr;
177 csr += nr;
178 available = align(split->limits->max_verts - csr - 1, 2);
179 }
180 else {
181 /* Wrapped the primitive:
182 */
183 j += nr - (first - incr);
184 flush_vertex(split);
185 csr = 0;
186 available = align(split->limits->max_verts - csr - 1, 2);
187 }
188 }
189 }
190 else if (split->ib == NULL) {
191 /* XXX: could at least send the first max_verts off from the
192 * inplace buffers.
193 */
194
195 /* else convert to indexed primitive and pass to split_elts,
196 * which will do the necessary copying and turn it back into a
197 * vertex primitive for rendering...
198 */
199 struct _mesa_index_buffer ib;
200 struct _mesa_prim tmpprim;
201 GLuint *elts = malloc(count * sizeof(GLuint));
202 GLuint j;
203
204 for (j = 0; j < count; j++)
205 elts[j] = prim->start + j;
206
207 ib.count = count;
208 ib.type = GL_UNSIGNED_INT;
209 ib.obj = split->ctx->Shared->NullBufferObj;
210 ib.ptr = elts;
211
212 tmpprim = *prim;
213 tmpprim.indexed = 1;
214 tmpprim.start = 0;
215 tmpprim.count = count;
216
217 flush_vertex(split);
218
219 vbo_split_copy(split->ctx,
220 split->array,
221 &tmpprim, 1,
222 &ib,
223 split->draw,
224 split->limits);
225
226 free(elts);
227 }
228 else {
229 flush_vertex(split);
230
231 vbo_split_copy(split->ctx,
232 split->array,
233 prim, 1,
234 split->ib,
235 split->draw,
236 split->limits);
237 }
238 }
239
240 flush_vertex(split);
241 }
242
243
244 void vbo_split_inplace( GLcontext *ctx,
245 const struct gl_client_array *arrays[],
246 const struct _mesa_prim *prim,
247 GLuint nr_prims,
248 const struct _mesa_index_buffer *ib,
249 GLuint min_index,
250 GLuint max_index,
251 vbo_draw_func draw,
252 const struct split_limits *limits )
253 {
254 struct split_context split;
255
256 memset(&split, 0, sizeof(split));
257
258 split.ctx = ctx;
259 split.array = arrays;
260 split.prim = prim;
261 split.nr_prims = nr_prims;
262 split.ib = ib;
263 split.min_index = min_index;
264 split.max_index = max_index;
265 split.draw = draw;
266 split.limits = limits;
267
268 split_prims( &split );
269 }
270
271