softpipe: do something sensible on an error path, squash warning
[mesa.git] / src / gallium / drivers / softpipe / sp_prim_vbuf.c
1 /**************************************************************************
2 *
3 * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * 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
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 **************************************************************************/
27
28 /**
29 * Post-transform vertex buffering. This is an optional part of the
30 * softpipe rendering pipeline.
31 * Probably not desired in general, but useful for testing/debuggin.
32 * Enabled/Disabled with SP_VBUF env var.
33 *
34 * Authors
35 * Brian Paul
36 */
37
38
39 #include "sp_context.h"
40 #include "sp_state.h"
41 #include "sp_prim_vbuf.h"
42 #include "sp_prim_setup.h"
43 #include "sp_setup.h"
44 #include "draw/draw_context.h"
45 #include "draw/draw_vbuf.h"
46
47
48 #define SP_MAX_VBUF_INDEXES 1024
49 #define SP_MAX_VBUF_SIZE 4096
50
51 typedef const float (*cptrf4)[4];
52
53 /**
54 * Subclass of vbuf_render.
55 */
56 struct softpipe_vbuf_render
57 {
58 struct vbuf_render base;
59 struct softpipe_context *softpipe;
60 uint prim;
61 uint vertex_size;
62 void *vertex_buffer;
63 };
64
65
66 /** cast wrapper */
67 static struct softpipe_vbuf_render *
68 softpipe_vbuf_render(struct vbuf_render *vbr)
69 {
70 return (struct softpipe_vbuf_render *) vbr;
71 }
72
73
74 static const struct vertex_info *
75 sp_vbuf_get_vertex_info(struct vbuf_render *vbr)
76 {
77 struct softpipe_vbuf_render *cvbr = softpipe_vbuf_render(vbr);
78 return softpipe_get_vbuf_vertex_info(cvbr->softpipe);
79 }
80
81
82 static void *
83 sp_vbuf_allocate_vertices(struct vbuf_render *vbr,
84 ushort vertex_size, ushort nr_vertices)
85 {
86 struct softpipe_vbuf_render *cvbr = softpipe_vbuf_render(vbr);
87 assert(!cvbr->vertex_buffer);
88 cvbr->vertex_buffer = align_malloc(vertex_size * nr_vertices, 16);
89 cvbr->vertex_size = vertex_size;
90 return cvbr->vertex_buffer;
91 }
92
93
94 static void
95 sp_vbuf_release_vertices(struct vbuf_render *vbr, void *vertices,
96 unsigned vertex_size, unsigned vertices_used)
97 {
98 struct softpipe_vbuf_render *cvbr = softpipe_vbuf_render(vbr);
99 align_free(vertices);
100 assert(vertices == cvbr->vertex_buffer);
101 cvbr->vertex_buffer = NULL;
102 }
103
104
105 static boolean
106 sp_vbuf_set_primitive(struct vbuf_render *vbr, unsigned prim)
107 {
108 struct softpipe_vbuf_render *cvbr = softpipe_vbuf_render(vbr);
109
110 /* XXX: break this dependency - make setup_context live under
111 * softpipe, rename the old "setup" draw stage to something else.
112 */
113 struct setup_context *setup_ctx = sp_draw_setup_context(cvbr->softpipe->setup);
114
115 setup_prepare( setup_ctx );
116
117
118
119 if (prim == PIPE_PRIM_TRIANGLES ||
120 prim == PIPE_PRIM_LINES ||
121 prim == PIPE_PRIM_POINTS) {
122 cvbr->prim = prim;
123 return TRUE;
124 }
125 else {
126 return FALSE;
127 }
128
129 }
130
131
132
133
134 static void
135 sp_vbuf_draw(struct vbuf_render *vbr, const ushort *indices, uint nr_indices)
136 {
137 struct softpipe_vbuf_render *cvbr = softpipe_vbuf_render(vbr);
138 struct softpipe_context *softpipe = cvbr->softpipe;
139 unsigned vertex_size = softpipe->vertex_info_vbuf.size * sizeof(float);
140 unsigned i, j;
141 void *vertex_buffer = cvbr->vertex_buffer;
142 cptrf4 v[3];
143
144 /* XXX: break this dependency - make setup_context live under
145 * softpipe, rename the old "setup" draw stage to something else.
146 */
147 struct draw_stage *setup = softpipe->setup;
148 struct setup_context *setup_ctx = sp_draw_setup_context(softpipe->setup);
149
150
151 switch (cvbr->prim) {
152 case PIPE_PRIM_TRIANGLES:
153 for (i = 0; i < nr_indices; i += 3) {
154 for (j = 0; j < 3; j++)
155 v[j] = (cptrf4)((char *)vertex_buffer +
156 indices[i+j] * vertex_size);
157
158 setup_tri( setup_ctx,
159 v[0],
160 v[1],
161 v[2]);
162 }
163 break;
164
165 case PIPE_PRIM_LINES:
166 for (i = 0; i < nr_indices; i += 2) {
167 for (j = 0; j < 2; j++)
168 v[j] = (cptrf4)((char *)vertex_buffer +
169 indices[i+j] * vertex_size);
170
171 setup_line( setup_ctx,
172 v[0],
173 v[1] );
174 }
175 break;
176
177 case PIPE_PRIM_POINTS:
178 for (i = 0; i < nr_indices; i++) {
179 v[0] = (cptrf4)((char *)vertex_buffer +
180 indices[i] * vertex_size);
181
182 setup_point( setup_ctx,
183 v[0] );
184 }
185 break;
186 }
187
188 /* XXX: why are we calling this??? If we had to call something, it
189 * would be a function in sp_setup.c:
190 */
191 sp_draw_flush( setup );
192 }
193
194
195 /**
196 * This function is hit when the draw module is working in pass-through mode.
197 * It's up to us to convert the vertex array into point/line/tri prims.
198 */
199 static void
200 sp_vbuf_draw_arrays(struct vbuf_render *vbr, uint start, uint nr)
201 {
202 struct softpipe_vbuf_render *cvbr = softpipe_vbuf_render(vbr);
203 struct softpipe_context *softpipe = cvbr->softpipe;
204 struct draw_stage *setup = softpipe->setup;
205 const void *vertex_buffer = cvbr->vertex_buffer;
206 const unsigned vertex_size = softpipe->vertex_info_vbuf.size * sizeof(float);
207 unsigned i;
208 struct setup_context *setup_ctx = sp_draw_setup_context(setup);
209 cptrf4 v[3];
210
211 #define VERTEX(I) \
212 (cptrf4) ((char *) vertex_buffer + (I) * vertex_size)
213
214 switch (cvbr->prim) {
215 case PIPE_PRIM_POINTS:
216 for (i = 0; i < nr; i++) {
217 v[0] = VERTEX(i);
218 setup_point( setup_ctx, v[0] );
219 }
220 break;
221 case PIPE_PRIM_LINES:
222 assert(nr % 2 == 0);
223 for (i = 0; i < nr; i += 2) {
224 v[0] = VERTEX(i);
225 v[1] = VERTEX(i + 1);
226 setup_line( setup_ctx, v[0], v[1] );
227 }
228 break;
229 case PIPE_PRIM_LINE_STRIP:
230 for (i = 1; i < nr; i++) {
231 v[0] = VERTEX(i - 1);
232 v[1] = VERTEX(i);
233 setup_line( setup_ctx, v[0], v[1] );
234 }
235 break;
236 case PIPE_PRIM_TRIANGLES:
237 assert(nr % 3 == 0);
238 for (i = 0; i < nr; i += 3) {
239 v[0] = VERTEX(i + 0);
240 v[1] = VERTEX(i + 1);
241 v[2] = VERTEX(i + 2);
242 setup_tri( setup_ctx,
243 v[0],
244 v[1],
245 v[2] );
246 }
247 break;
248 case PIPE_PRIM_TRIANGLE_STRIP:
249 assert(nr >= 3);
250 for (i = 2; i < nr; i++) {
251 v[0] = VERTEX(i - 2);
252 v[1] = VERTEX(i - 1);
253 v[2] = VERTEX(i);
254 setup_tri( setup_ctx,
255 v[0],
256 v[1],
257 v[2] );
258 }
259 break;
260 case PIPE_PRIM_TRIANGLE_FAN:
261 assert(nr >= 3);
262 for (i = 2; i < nr; i++) {
263 v[0] = VERTEX(0);
264 v[1] = VERTEX(i - 1);
265 v[2] = VERTEX(i);
266 setup_tri( setup_ctx,
267 v[0],
268 v[1],
269 v[2] );
270 }
271 break;
272 case PIPE_PRIM_QUADS:
273 assert(nr % 4 == 0);
274 for (i = 0; i < nr; i += 4) {
275 v[0] = VERTEX(i + 0);
276 v[1] = VERTEX(i + 1);
277 v[2] = VERTEX(i + 2);
278 setup_tri( setup_ctx,
279 v[0],
280 v[1],
281 v[2] );
282
283 v[0] = VERTEX(i + 0);
284 v[1] = VERTEX(i + 2);
285 v[2] = VERTEX(i + 3);
286 setup_tri( setup_ctx,
287 v[0],
288 v[1],
289 v[2] );
290 }
291 break;
292 case PIPE_PRIM_QUAD_STRIP:
293 assert(nr >= 4);
294 for (i = 2; i < nr; i += 2) {
295 v[0] = VERTEX(i - 2);
296 v[1] = VERTEX(i);
297 v[2] = VERTEX(i + 1);
298 setup_tri( setup_ctx,
299 v[0],
300 v[1],
301 v[2] );
302
303 v[0] = VERTEX(i - 2);
304 v[1] = VERTEX(i + 1);
305 v[2] = VERTEX(i - 1);
306 setup_tri( setup_ctx,
307 v[0],
308 v[1],
309 v[2] );
310 }
311 break;
312 case PIPE_PRIM_POLYGON:
313 /* draw as tri fan */
314 for (i = 2; i < nr; i++) {
315 v[0] = VERTEX(0);
316 v[1] = VERTEX(i - 1);
317 v[2] = VERTEX(i);
318 setup_tri( setup_ctx,
319 v[0],
320 v[1],
321 v[2] );
322 }
323 break;
324 default:
325 /* XXX finish remaining prim types */
326 assert(0);
327 }
328
329 #undef VERTEX
330 }
331
332
333
334 static void
335 sp_vbuf_destroy(struct vbuf_render *vbr)
336 {
337 struct softpipe_vbuf_render *cvbr = softpipe_vbuf_render(vbr);
338 cvbr->softpipe->vbuf_render = NULL;
339 FREE(cvbr);
340 }
341
342
343 /**
344 * Initialize the post-transform vertex buffer information for the given
345 * context.
346 */
347 void
348 sp_init_vbuf(struct softpipe_context *sp)
349 {
350 assert(sp->draw);
351
352 sp->vbuf_render = CALLOC_STRUCT(softpipe_vbuf_render);
353
354 sp->vbuf_render->base.max_indices = SP_MAX_VBUF_INDEXES;
355 sp->vbuf_render->base.max_vertex_buffer_bytes = SP_MAX_VBUF_SIZE;
356
357 sp->vbuf_render->base.get_vertex_info = sp_vbuf_get_vertex_info;
358 sp->vbuf_render->base.allocate_vertices = sp_vbuf_allocate_vertices;
359 sp->vbuf_render->base.set_primitive = sp_vbuf_set_primitive;
360 sp->vbuf_render->base.draw = sp_vbuf_draw;
361 sp->vbuf_render->base.draw_arrays = sp_vbuf_draw_arrays;
362 sp->vbuf_render->base.release_vertices = sp_vbuf_release_vertices;
363 sp->vbuf_render->base.destroy = sp_vbuf_destroy;
364
365 sp->vbuf_render->softpipe = sp;
366
367 sp->vbuf = draw_vbuf_stage(sp->draw, &sp->vbuf_render->base);
368
369 draw_set_rasterize_stage(sp->draw, sp->vbuf);
370
371 draw_set_render(sp->draw, &sp->vbuf_render->base);
372 }