Merge branch 'mesa_7_5_branch' into mesa_7_6_branch
[mesa.git] / src / gallium / drivers / llvmpipe / lp_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 * Interface between 'draw' module's output and the llvmpipe rasterizer/setup
30 * code. When the 'draw' module has finished filling a vertex buffer, the
31 * draw_arrays() functions below will be called. Loop over the vertices and
32 * call the point/line/tri setup functions.
33 *
34 * Authors
35 * Brian Paul
36 */
37
38
39 #include "lp_context.h"
40 #include "lp_state.h"
41 #include "lp_prim_vbuf.h"
42 #include "lp_prim_setup.h"
43 #include "lp_setup.h"
44 #include "draw/draw_context.h"
45 #include "draw/draw_vbuf.h"
46 #include "util/u_memory.h"
47 #include "util/u_prim.h"
48
49
50 #define LP_MAX_VBUF_INDEXES 1024
51 #define LP_MAX_VBUF_SIZE 4096
52
53 typedef const float (*cptrf4)[4];
54
55 /**
56 * Subclass of vbuf_render.
57 */
58 struct llvmpipe_vbuf_render
59 {
60 struct vbuf_render base;
61 struct llvmpipe_context *llvmpipe;
62 uint prim;
63 uint vertex_size;
64 uint nr_vertices;
65 uint vertex_buffer_size;
66 void *vertex_buffer;
67 };
68
69
70 /** cast wrapper */
71 static struct llvmpipe_vbuf_render *
72 llvmpipe_vbuf_render(struct vbuf_render *vbr)
73 {
74 return (struct llvmpipe_vbuf_render *) vbr;
75 }
76
77
78 static const struct vertex_info *
79 lp_vbuf_get_vertex_info(struct vbuf_render *vbr)
80 {
81 struct llvmpipe_vbuf_render *cvbr = llvmpipe_vbuf_render(vbr);
82 return llvmpipe_get_vbuf_vertex_info(cvbr->llvmpipe);
83 }
84
85
86 static boolean
87 lp_vbuf_allocate_vertices(struct vbuf_render *vbr,
88 ushort vertex_size, ushort nr_vertices)
89 {
90 struct llvmpipe_vbuf_render *cvbr = llvmpipe_vbuf_render(vbr);
91 unsigned size = vertex_size * nr_vertices;
92
93 if (cvbr->vertex_buffer_size < size) {
94 align_free(cvbr->vertex_buffer);
95 cvbr->vertex_buffer = align_malloc(size, 16);
96 cvbr->vertex_buffer_size = size;
97 }
98
99 cvbr->vertex_size = vertex_size;
100 cvbr->nr_vertices = nr_vertices;
101
102 return cvbr->vertex_buffer != NULL;
103 }
104
105 static void
106 lp_vbuf_release_vertices(struct vbuf_render *vbr)
107 {
108 #if 0
109 {
110 struct llvmpipe_vbuf_render *cvbr = llvmpipe_vbuf_render(vbr);
111 const struct vertex_info *info =
112 llvmpipe_get_vbuf_vertex_info(cvbr->llvmpipe);
113 const float *vtx = (const float *) cvbr->vertex_buffer;
114 uint i, j;
115 debug_printf("%s (vtx_size = %u, vtx_used = %u)\n",
116 __FUNCTION__, cvbr->vertex_size, cvbr->nr_vertices);
117 for (i = 0; i < cvbr->nr_vertices; i++) {
118 for (j = 0; j < info->num_attribs; j++) {
119 uint k;
120 switch (info->attrib[j].emit) {
121 case EMIT_4F: k = 4; break;
122 case EMIT_3F: k = 3; break;
123 case EMIT_2F: k = 2; break;
124 case EMIT_1F: k = 1; break;
125 default: assert(0);
126 }
127 debug_printf("Vert %u attr %u: ", i, j);
128 while (k-- > 0) {
129 debug_printf("%g ", vtx[0]);
130 vtx++;
131 }
132 debug_printf("\n");
133 }
134 }
135 }
136 #endif
137
138 /* keep the old allocation for next time */
139 }
140
141 static void *
142 lp_vbuf_map_vertices(struct vbuf_render *vbr)
143 {
144 struct llvmpipe_vbuf_render *cvbr = llvmpipe_vbuf_render(vbr);
145 return cvbr->vertex_buffer;
146 }
147
148 static void
149 lp_vbuf_unmap_vertices(struct vbuf_render *vbr,
150 ushort min_index,
151 ushort max_index )
152 {
153 struct llvmpipe_vbuf_render *cvbr = llvmpipe_vbuf_render(vbr);
154 assert( cvbr->vertex_buffer_size >= (max_index+1) * cvbr->vertex_size );
155 /* do nothing */
156 }
157
158
159 static boolean
160 lp_vbuf_set_primitive(struct vbuf_render *vbr, unsigned prim)
161 {
162 struct llvmpipe_vbuf_render *cvbr = llvmpipe_vbuf_render(vbr);
163
164 /* XXX: break this dependency - make setup_context live under
165 * llvmpipe, rename the old "setup" draw stage to something else.
166 */
167 struct setup_context *setup_ctx = lp_draw_setup_context(cvbr->llvmpipe->setup);
168
169 llvmpipe_setup_prepare( setup_ctx );
170
171 cvbr->llvmpipe->reduced_prim = u_reduced_prim(prim);
172 cvbr->prim = prim;
173 return TRUE;
174
175 }
176
177
178 static INLINE cptrf4 get_vert( const void *vertex_buffer,
179 int index,
180 int stride )
181 {
182 return (cptrf4)((char *)vertex_buffer + index * stride);
183 }
184
185
186 /**
187 * draw elements / indexed primitives
188 */
189 static void
190 lp_vbuf_draw(struct vbuf_render *vbr, const ushort *indices, uint nr)
191 {
192 struct llvmpipe_vbuf_render *cvbr = llvmpipe_vbuf_render(vbr);
193 struct llvmpipe_context *llvmpipe = cvbr->llvmpipe;
194 const unsigned stride = llvmpipe->vertex_info_vbuf.size * sizeof(float);
195 const void *vertex_buffer = cvbr->vertex_buffer;
196 unsigned i;
197
198 /* XXX: break this dependency - make setup_context live under
199 * llvmpipe, rename the old "setup" draw stage to something else.
200 */
201 struct draw_stage *setup = llvmpipe->setup;
202 struct setup_context *setup_ctx = lp_draw_setup_context(setup);
203
204 switch (cvbr->prim) {
205 case PIPE_PRIM_POINTS:
206 for (i = 0; i < nr; i++) {
207 llvmpipe_setup_point( setup_ctx,
208 get_vert(vertex_buffer, indices[i-0], stride) );
209 }
210 break;
211
212 case PIPE_PRIM_LINES:
213 for (i = 1; i < nr; i += 2) {
214 llvmpipe_setup_line( setup_ctx,
215 get_vert(vertex_buffer, indices[i-1], stride),
216 get_vert(vertex_buffer, indices[i-0], stride) );
217 }
218 break;
219
220 case PIPE_PRIM_LINE_STRIP:
221 for (i = 1; i < nr; i ++) {
222 llvmpipe_setup_line( setup_ctx,
223 get_vert(vertex_buffer, indices[i-1], stride),
224 get_vert(vertex_buffer, indices[i-0], stride) );
225 }
226 break;
227
228 case PIPE_PRIM_LINE_LOOP:
229 for (i = 1; i < nr; i ++) {
230 llvmpipe_setup_line( setup_ctx,
231 get_vert(vertex_buffer, indices[i-1], stride),
232 get_vert(vertex_buffer, indices[i-0], stride) );
233 }
234 if (nr) {
235 llvmpipe_setup_line( setup_ctx,
236 get_vert(vertex_buffer, indices[nr-1], stride),
237 get_vert(vertex_buffer, indices[0], stride) );
238 }
239 break;
240
241 case PIPE_PRIM_TRIANGLES:
242 if (llvmpipe->rasterizer->flatshade_first) {
243 for (i = 2; i < nr; i += 3) {
244 llvmpipe_setup_tri( setup_ctx,
245 get_vert(vertex_buffer, indices[i-1], stride),
246 get_vert(vertex_buffer, indices[i-0], stride),
247 get_vert(vertex_buffer, indices[i-2], stride) );
248 }
249 }
250 else {
251 for (i = 2; i < nr; i += 3) {
252 llvmpipe_setup_tri( setup_ctx,
253 get_vert(vertex_buffer, indices[i-2], stride),
254 get_vert(vertex_buffer, indices[i-1], stride),
255 get_vert(vertex_buffer, indices[i-0], stride) );
256 }
257 }
258 break;
259
260 case PIPE_PRIM_TRIANGLE_STRIP:
261 if (llvmpipe->rasterizer->flatshade_first) {
262 for (i = 2; i < nr; i += 1) {
263 llvmpipe_setup_tri( setup_ctx,
264 get_vert(vertex_buffer, indices[i+(i&1)-1], stride),
265 get_vert(vertex_buffer, indices[i-(i&1)], stride),
266 get_vert(vertex_buffer, indices[i-2], stride) );
267 }
268 }
269 else {
270 for (i = 2; i < nr; i += 1) {
271 llvmpipe_setup_tri( setup_ctx,
272 get_vert(vertex_buffer, indices[i+(i&1)-2], stride),
273 get_vert(vertex_buffer, indices[i-(i&1)-1], stride),
274 get_vert(vertex_buffer, indices[i-0], stride) );
275 }
276 }
277 break;
278
279 case PIPE_PRIM_TRIANGLE_FAN:
280 if (llvmpipe->rasterizer->flatshade_first) {
281 for (i = 2; i < nr; i += 1) {
282 llvmpipe_setup_tri( setup_ctx,
283 get_vert(vertex_buffer, indices[i-0], stride),
284 get_vert(vertex_buffer, indices[0], stride),
285 get_vert(vertex_buffer, indices[i-1], stride) );
286 }
287 }
288 else {
289 for (i = 2; i < nr; i += 1) {
290 llvmpipe_setup_tri( setup_ctx,
291 get_vert(vertex_buffer, indices[0], stride),
292 get_vert(vertex_buffer, indices[i-1], stride),
293 get_vert(vertex_buffer, indices[i-0], stride) );
294 }
295 }
296 break;
297
298 case PIPE_PRIM_QUADS:
299 if (llvmpipe->rasterizer->flatshade_first) {
300 for (i = 3; i < nr; i += 4) {
301 llvmpipe_setup_tri( setup_ctx,
302 get_vert(vertex_buffer, indices[i-2], stride),
303 get_vert(vertex_buffer, indices[i-1], stride),
304 get_vert(vertex_buffer, indices[i-3], stride) );
305 llvmpipe_setup_tri( setup_ctx,
306 get_vert(vertex_buffer, indices[i-1], stride),
307 get_vert(vertex_buffer, indices[i-0], stride),
308 get_vert(vertex_buffer, indices[i-3], stride) );
309 }
310 }
311 else {
312 for (i = 3; i < nr; i += 4) {
313 llvmpipe_setup_tri( setup_ctx,
314 get_vert(vertex_buffer, indices[i-3], stride),
315 get_vert(vertex_buffer, indices[i-2], stride),
316 get_vert(vertex_buffer, indices[i-0], stride) );
317
318 llvmpipe_setup_tri( setup_ctx,
319 get_vert(vertex_buffer, indices[i-2], stride),
320 get_vert(vertex_buffer, indices[i-1], stride),
321 get_vert(vertex_buffer, indices[i-0], stride) );
322 }
323 }
324 break;
325
326 case PIPE_PRIM_QUAD_STRIP:
327 if (llvmpipe->rasterizer->flatshade_first) {
328 for (i = 3; i < nr; i += 2) {
329 llvmpipe_setup_tri( setup_ctx,
330 get_vert(vertex_buffer, indices[i-0], stride),
331 get_vert(vertex_buffer, indices[i-1], stride),
332 get_vert(vertex_buffer, indices[i-3], stride));
333 llvmpipe_setup_tri( setup_ctx,
334 get_vert(vertex_buffer, indices[i-2], stride),
335 get_vert(vertex_buffer, indices[i-0], stride),
336 get_vert(vertex_buffer, indices[i-3], stride) );
337 }
338 }
339 else {
340 for (i = 3; i < nr; i += 2) {
341 llvmpipe_setup_tri( setup_ctx,
342 get_vert(vertex_buffer, indices[i-3], stride),
343 get_vert(vertex_buffer, indices[i-2], stride),
344 get_vert(vertex_buffer, indices[i-0], stride) );
345 llvmpipe_setup_tri( setup_ctx,
346 get_vert(vertex_buffer, indices[i-1], stride),
347 get_vert(vertex_buffer, indices[i-3], stride),
348 get_vert(vertex_buffer, indices[i-0], stride) );
349 }
350 }
351 break;
352
353 case PIPE_PRIM_POLYGON:
354 /* Almost same as tri fan but the _first_ vertex specifies the flat
355 * shading color. Note that the first polygon vertex is passed as
356 * the last triangle vertex here.
357 * flatshade_first state makes no difference.
358 */
359 for (i = 2; i < nr; i += 1) {
360 llvmpipe_setup_tri( setup_ctx,
361 get_vert(vertex_buffer, indices[i-0], stride),
362 get_vert(vertex_buffer, indices[i-1], stride),
363 get_vert(vertex_buffer, indices[0], stride) );
364 }
365 break;
366
367 default:
368 assert(0);
369 }
370
371 /* XXX: why are we calling this??? If we had to call something, it
372 * would be a function in lp_setup.c:
373 */
374 lp_draw_flush( setup );
375 }
376
377
378 /**
379 * This function is hit when the draw module is working in pass-through mode.
380 * It's up to us to convert the vertex array into point/line/tri prims.
381 */
382 static void
383 lp_vbuf_draw_arrays(struct vbuf_render *vbr, uint start, uint nr)
384 {
385 struct llvmpipe_vbuf_render *cvbr = llvmpipe_vbuf_render(vbr);
386 struct llvmpipe_context *llvmpipe = cvbr->llvmpipe;
387 const unsigned stride = llvmpipe->vertex_info_vbuf.size * sizeof(float);
388 const void *vertex_buffer =
389 (void *) get_vert(cvbr->vertex_buffer, start, stride);
390 unsigned i;
391
392 /* XXX: break this dependency - make setup_context live under
393 * llvmpipe, rename the old "setup" draw stage to something else.
394 */
395 struct draw_stage *setup = llvmpipe->setup;
396 struct setup_context *setup_ctx = lp_draw_setup_context(setup);
397
398 switch (cvbr->prim) {
399 case PIPE_PRIM_POINTS:
400 for (i = 0; i < nr; i++) {
401 llvmpipe_setup_point( setup_ctx,
402 get_vert(vertex_buffer, i-0, stride) );
403 }
404 break;
405
406 case PIPE_PRIM_LINES:
407 for (i = 1; i < nr; i += 2) {
408 llvmpipe_setup_line( setup_ctx,
409 get_vert(vertex_buffer, i-1, stride),
410 get_vert(vertex_buffer, i-0, stride) );
411 }
412 break;
413
414 case PIPE_PRIM_LINE_STRIP:
415 for (i = 1; i < nr; i ++) {
416 llvmpipe_setup_line( setup_ctx,
417 get_vert(vertex_buffer, i-1, stride),
418 get_vert(vertex_buffer, i-0, stride) );
419 }
420 break;
421
422 case PIPE_PRIM_LINE_LOOP:
423 for (i = 1; i < nr; i ++) {
424 llvmpipe_setup_line( setup_ctx,
425 get_vert(vertex_buffer, i-1, stride),
426 get_vert(vertex_buffer, i-0, stride) );
427 }
428 if (nr) {
429 llvmpipe_setup_line( setup_ctx,
430 get_vert(vertex_buffer, nr-1, stride),
431 get_vert(vertex_buffer, 0, stride) );
432 }
433 break;
434
435 case PIPE_PRIM_TRIANGLES:
436 if (llvmpipe->rasterizer->flatshade_first) {
437 for (i = 2; i < nr; i += 3) {
438 llvmpipe_setup_tri( setup_ctx,
439 get_vert(vertex_buffer, i-1, stride),
440 get_vert(vertex_buffer, i-0, stride),
441 get_vert(vertex_buffer, i-2, stride) );
442 }
443 }
444 else {
445 for (i = 2; i < nr; i += 3) {
446 llvmpipe_setup_tri( setup_ctx,
447 get_vert(vertex_buffer, i-2, stride),
448 get_vert(vertex_buffer, i-1, stride),
449 get_vert(vertex_buffer, i-0, stride) );
450 }
451 }
452 break;
453
454 case PIPE_PRIM_TRIANGLE_STRIP:
455 if (llvmpipe->rasterizer->flatshade_first) {
456 for (i = 2; i < nr; i++) {
457 llvmpipe_setup_tri( setup_ctx,
458 get_vert(vertex_buffer, i+(i&1)-1, stride),
459 get_vert(vertex_buffer, i-(i&1), stride),
460 get_vert(vertex_buffer, i-2, stride) );
461 }
462 }
463 else {
464 for (i = 2; i < nr; i++) {
465 llvmpipe_setup_tri( setup_ctx,
466 get_vert(vertex_buffer, i+(i&1)-2, stride),
467 get_vert(vertex_buffer, i-(i&1)-1, stride),
468 get_vert(vertex_buffer, i-0, stride) );
469 }
470 }
471 break;
472
473 case PIPE_PRIM_TRIANGLE_FAN:
474 if (llvmpipe->rasterizer->flatshade_first) {
475 for (i = 2; i < nr; i += 1) {
476 llvmpipe_setup_tri( setup_ctx,
477 get_vert(vertex_buffer, i-0, stride),
478 get_vert(vertex_buffer, 0, stride),
479 get_vert(vertex_buffer, i-1, stride) );
480 }
481 }
482 else {
483 for (i = 2; i < nr; i += 1) {
484 llvmpipe_setup_tri( setup_ctx,
485 get_vert(vertex_buffer, 0, stride),
486 get_vert(vertex_buffer, i-1, stride),
487 get_vert(vertex_buffer, i-0, stride) );
488 }
489 }
490 break;
491
492 case PIPE_PRIM_QUADS:
493 if (llvmpipe->rasterizer->flatshade_first) {
494 for (i = 3; i < nr; i += 4) {
495 llvmpipe_setup_tri( setup_ctx,
496 get_vert(vertex_buffer, i-2, stride),
497 get_vert(vertex_buffer, i-1, stride),
498 get_vert(vertex_buffer, i-3, stride) );
499 llvmpipe_setup_tri( setup_ctx,
500 get_vert(vertex_buffer, i-1, stride),
501 get_vert(vertex_buffer, i-0, stride),
502 get_vert(vertex_buffer, i-3, stride) );
503 }
504 }
505 else {
506 for (i = 3; i < nr; i += 4) {
507 llvmpipe_setup_tri( setup_ctx,
508 get_vert(vertex_buffer, i-3, stride),
509 get_vert(vertex_buffer, i-2, stride),
510 get_vert(vertex_buffer, i-0, stride) );
511 llvmpipe_setup_tri( setup_ctx,
512 get_vert(vertex_buffer, i-2, stride),
513 get_vert(vertex_buffer, i-1, stride),
514 get_vert(vertex_buffer, i-0, stride) );
515 }
516 }
517 break;
518
519 case PIPE_PRIM_QUAD_STRIP:
520 if (llvmpipe->rasterizer->flatshade_first) {
521 for (i = 3; i < nr; i += 2) {
522 llvmpipe_setup_tri( setup_ctx,
523 get_vert(vertex_buffer, i-0, stride),
524 get_vert(vertex_buffer, i-1, stride),
525 get_vert(vertex_buffer, i-3, stride) );
526 llvmpipe_setup_tri( setup_ctx,
527 get_vert(vertex_buffer, i-2, stride),
528 get_vert(vertex_buffer, i-0, stride),
529 get_vert(vertex_buffer, i-3, stride) );
530 }
531 }
532 else {
533 for (i = 3; i < nr; i += 2) {
534 llvmpipe_setup_tri( setup_ctx,
535 get_vert(vertex_buffer, i-3, stride),
536 get_vert(vertex_buffer, i-2, stride),
537 get_vert(vertex_buffer, i-0, stride) );
538 llvmpipe_setup_tri( setup_ctx,
539 get_vert(vertex_buffer, i-1, stride),
540 get_vert(vertex_buffer, i-3, stride),
541 get_vert(vertex_buffer, i-0, stride) );
542 }
543 }
544 break;
545
546 case PIPE_PRIM_POLYGON:
547 /* Almost same as tri fan but the _first_ vertex specifies the flat
548 * shading color. Note that the first polygon vertex is passed as
549 * the last triangle vertex here.
550 * flatshade_first state makes no difference.
551 */
552 for (i = 2; i < nr; i += 1) {
553 llvmpipe_setup_tri( setup_ctx,
554 get_vert(vertex_buffer, i-1, stride),
555 get_vert(vertex_buffer, i-0, stride),
556 get_vert(vertex_buffer, 0, stride) );
557 }
558 break;
559
560 default:
561 assert(0);
562 }
563 }
564
565
566
567 static void
568 lp_vbuf_destroy(struct vbuf_render *vbr)
569 {
570 struct llvmpipe_vbuf_render *cvbr = llvmpipe_vbuf_render(vbr);
571 cvbr->llvmpipe->vbuf_render = NULL;
572 FREE(cvbr);
573 }
574
575
576 /**
577 * Initialize the post-transform vertex buffer information for the given
578 * context.
579 */
580 void
581 lp_init_vbuf(struct llvmpipe_context *lp)
582 {
583 assert(lp->draw);
584
585 lp->vbuf_render = CALLOC_STRUCT(llvmpipe_vbuf_render);
586
587 lp->vbuf_render->base.max_indices = LP_MAX_VBUF_INDEXES;
588 lp->vbuf_render->base.max_vertex_buffer_bytes = LP_MAX_VBUF_SIZE;
589
590 lp->vbuf_render->base.get_vertex_info = lp_vbuf_get_vertex_info;
591 lp->vbuf_render->base.allocate_vertices = lp_vbuf_allocate_vertices;
592 lp->vbuf_render->base.map_vertices = lp_vbuf_map_vertices;
593 lp->vbuf_render->base.unmap_vertices = lp_vbuf_unmap_vertices;
594 lp->vbuf_render->base.set_primitive = lp_vbuf_set_primitive;
595 lp->vbuf_render->base.draw = lp_vbuf_draw;
596 lp->vbuf_render->base.draw_arrays = lp_vbuf_draw_arrays;
597 lp->vbuf_render->base.release_vertices = lp_vbuf_release_vertices;
598 lp->vbuf_render->base.destroy = lp_vbuf_destroy;
599
600 lp->vbuf_render->llvmpipe = lp;
601
602 lp->vbuf = draw_vbuf_stage(lp->draw, &lp->vbuf_render->base);
603
604 draw_set_rasterize_stage(lp->draw, lp->vbuf);
605
606 draw_set_render(lp->draw, &lp->vbuf_render->base);
607 }