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