Merge remote branch 'upstream/gallium-0.1' into nouveau-gallium-0.1
[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 if (prim == PIPE_PRIM_TRIANGLES ||
110 prim == PIPE_PRIM_LINES ||
111 prim == PIPE_PRIM_POINTS) {
112 cvbr->prim = prim;
113 return TRUE;
114 }
115 else {
116 return FALSE;
117 }
118
119 }
120
121
122
123
124 static void
125 sp_vbuf_draw(struct vbuf_render *vbr, const ushort *indices, uint nr_indices)
126 {
127 struct softpipe_vbuf_render *cvbr = softpipe_vbuf_render(vbr);
128 struct softpipe_context *softpipe = cvbr->softpipe;
129 unsigned vertex_size = softpipe->vertex_info_vbuf.size * sizeof(float);
130 unsigned i, j;
131 void *vertex_buffer = cvbr->vertex_buffer;
132 cptrf4 v[3];
133
134 /* XXX: break this dependency - make setup_context live under
135 * softpipe, rename the old "setup" draw stage to something else.
136 */
137 struct draw_stage *setup = softpipe->setup;
138 struct setup_context *setup_ctx = sp_draw_setup_context(softpipe->setup);
139
140 /* XXX: call this from allocate_vertices:
141 */
142 setup_prepare( setup_ctx );
143
144
145 switch (cvbr->prim) {
146 case PIPE_PRIM_TRIANGLES:
147 for (i = 0; i < nr_indices; i += 3) {
148 for (j = 0; j < 3; j++)
149 v[j] = (cptrf4)((char *)vertex_buffer +
150 indices[i+j] * vertex_size);
151
152 setup_tri( setup_ctx,
153 v[0],
154 v[1],
155 v[2]);
156 }
157 break;
158
159 case PIPE_PRIM_LINES:
160 for (i = 0; i < nr_indices; i += 2) {
161 for (j = 0; j < 2; j++)
162 v[j] = (cptrf4)((char *)vertex_buffer +
163 indices[i+j] * vertex_size);
164
165 setup_line( setup_ctx,
166 v[0],
167 v[1] );
168 }
169 break;
170
171 case PIPE_PRIM_POINTS:
172 for (i = 0; i < nr_indices; i++) {
173 v[0] = (cptrf4)((char *)vertex_buffer +
174 indices[i] * vertex_size);
175
176 setup_point( setup_ctx,
177 v[0] );
178 }
179 break;
180 }
181
182 /* XXX: why are we calling this??? If we had to call something, it
183 * would be a function in sp_setup.c:
184 */
185 sp_draw_flush( setup );
186 }
187
188
189 /**
190 * This function is hit when the draw module is working in pass-through mode.
191 * It's up to us to convert the vertex array into point/line/tri prims.
192 */
193 static void
194 sp_vbuf_draw_arrays(struct vbuf_render *vbr, uint start, uint nr)
195 {
196 struct softpipe_vbuf_render *cvbr = softpipe_vbuf_render(vbr);
197 struct softpipe_context *softpipe = cvbr->softpipe;
198 struct draw_stage *setup = softpipe->setup;
199 const void *vertex_buffer = cvbr->vertex_buffer;
200 const unsigned vertex_size = softpipe->vertex_info_vbuf.size * sizeof(float);
201 unsigned i;
202 struct setup_context *setup_ctx = sp_draw_setup_context(setup);
203 cptrf4 v[3];
204
205 #define VERTEX(I) \
206 (cptrf4) ((char *) vertex_buffer + (I) * vertex_size)
207
208 switch (cvbr->prim) {
209 case PIPE_PRIM_POINTS:
210 for (i = 0; i < nr; i++) {
211 v[0] = VERTEX(i);
212 setup_point( setup_ctx, v[0] );
213 }
214 break;
215 case PIPE_PRIM_LINES:
216 assert(nr % 2 == 0);
217 for (i = 0; i < nr; i += 2) {
218 v[0] = VERTEX(i);
219 v[1] = VERTEX(i + 1);
220 setup_line( setup_ctx, v[0], v[1] );
221 }
222 break;
223 case PIPE_PRIM_LINE_STRIP:
224 for (i = 1; i < nr; i++) {
225 v[0] = VERTEX(i - 1);
226 v[1] = VERTEX(i);
227 setup_line( setup_ctx, v[0], v[1] );
228 }
229 break;
230 case PIPE_PRIM_TRIANGLES:
231 assert(nr % 3 == 0);
232 for (i = 0; i < nr; i += 3) {
233 v[0] = VERTEX(i + 0);
234 v[1] = VERTEX(i + 1);
235 v[2] = VERTEX(i + 2);
236 setup_tri( setup_ctx,
237 v[0],
238 v[1],
239 v[2] );
240 }
241 break;
242 case PIPE_PRIM_TRIANGLE_STRIP:
243 assert(nr >= 3);
244 for (i = 2; i < nr; i++) {
245 v[0] = VERTEX(i - 2);
246 v[1] = VERTEX(i - 1);
247 v[2] = VERTEX(i);
248 setup_tri( setup_ctx,
249 v[0],
250 v[1],
251 v[2] );
252 }
253 break;
254 case PIPE_PRIM_TRIANGLE_FAN:
255 assert(nr >= 3);
256 for (i = 2; i < nr; i++) {
257 v[0] = VERTEX(0);
258 v[1] = VERTEX(i - 1);
259 v[2] = VERTEX(i);
260 setup_tri( setup_ctx,
261 v[0],
262 v[1],
263 v[2] );
264 }
265 break;
266 case PIPE_PRIM_QUADS:
267 assert(nr % 4 == 0);
268 for (i = 0; i < nr; i += 4) {
269 v[0] = VERTEX(i + 0);
270 v[1] = VERTEX(i + 1);
271 v[2] = VERTEX(i + 2);
272 setup_tri( setup_ctx,
273 v[0],
274 v[1],
275 v[2] );
276
277 v[0] = VERTEX(i + 0);
278 v[1] = VERTEX(i + 2);
279 v[2] = VERTEX(i + 3);
280 setup_tri( setup_ctx,
281 v[0],
282 v[1],
283 v[2] );
284 }
285 break;
286 case PIPE_PRIM_QUAD_STRIP:
287 assert(nr >= 4);
288 for (i = 2; i < nr; i += 2) {
289 v[0] = VERTEX(i - 2);
290 v[1] = VERTEX(i);
291 v[2] = VERTEX(i + 1);
292 setup_tri( setup_ctx,
293 v[0],
294 v[1],
295 v[2] );
296
297 v[0] = VERTEX(i - 2);
298 v[1] = VERTEX(i + 1);
299 v[2] = VERTEX(i - 1);
300 setup_tri( setup_ctx,
301 v[0],
302 v[1],
303 v[2] );
304 }
305 break;
306 case PIPE_PRIM_POLYGON:
307 /* draw as tri fan */
308 for (i = 2; i < nr; i++) {
309 v[0] = VERTEX(0);
310 v[1] = VERTEX(i - 1);
311 v[2] = VERTEX(i);
312 setup_tri( setup_ctx,
313 v[0],
314 v[1],
315 v[2] );
316 }
317 break;
318 default:
319 /* XXX finish remaining prim types */
320 assert(0);
321 }
322
323 #undef VERTEX
324 }
325
326
327
328 static void
329 sp_vbuf_destroy(struct vbuf_render *vbr)
330 {
331 struct softpipe_vbuf_render *cvbr = softpipe_vbuf_render(vbr);
332 cvbr->softpipe->vbuf_render = NULL;
333 FREE(cvbr);
334 }
335
336
337 /**
338 * Initialize the post-transform vertex buffer information for the given
339 * context.
340 */
341 void
342 sp_init_vbuf(struct softpipe_context *sp)
343 {
344 assert(sp->draw);
345
346 sp->vbuf_render = CALLOC_STRUCT(softpipe_vbuf_render);
347
348 sp->vbuf_render->base.max_indices = SP_MAX_VBUF_INDEXES;
349 sp->vbuf_render->base.max_vertex_buffer_bytes = SP_MAX_VBUF_SIZE;
350
351 sp->vbuf_render->base.get_vertex_info = sp_vbuf_get_vertex_info;
352 sp->vbuf_render->base.allocate_vertices = sp_vbuf_allocate_vertices;
353 sp->vbuf_render->base.set_primitive = sp_vbuf_set_primitive;
354 sp->vbuf_render->base.draw = sp_vbuf_draw;
355 sp->vbuf_render->base.draw_arrays = sp_vbuf_draw_arrays;
356 sp->vbuf_render->base.release_vertices = sp_vbuf_release_vertices;
357 sp->vbuf_render->base.destroy = sp_vbuf_destroy;
358
359 sp->vbuf_render->softpipe = sp;
360
361 sp->vbuf = draw_vbuf_stage(sp->draw, &sp->vbuf_render->base);
362
363 draw_set_rasterize_stage(sp->draw, sp->vbuf);
364
365 draw_set_render(sp->draw, &sp->vbuf_render->base);
366 }