llvmpipe: actually pass >1 quad from triangle routine
[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 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 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 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 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 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 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 for (i = 2; i < nr; i += 3) {
243 if (llvmpipe->rasterizer->flatshade_first) {
244 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 else {
250 setup_tri( setup_ctx,
251 get_vert(vertex_buffer, indices[i-2], stride),
252 get_vert(vertex_buffer, indices[i-1], stride),
253 get_vert(vertex_buffer, indices[i-0], stride) );
254 }
255 }
256 break;
257
258 case PIPE_PRIM_TRIANGLE_STRIP:
259 for (i = 2; i < nr; i += 1) {
260 if (llvmpipe->rasterizer->flatshade_first) {
261 setup_tri( setup_ctx,
262 get_vert(vertex_buffer, indices[i+(i&1)-1], stride),
263 get_vert(vertex_buffer, indices[i-(i&1)], stride),
264 get_vert(vertex_buffer, indices[i-2], stride) );
265 }
266 else {
267 setup_tri( setup_ctx,
268 get_vert(vertex_buffer, indices[i+(i&1)-2], stride),
269 get_vert(vertex_buffer, indices[i-(i&1)-1], stride),
270 get_vert(vertex_buffer, indices[i-0], stride) );
271 }
272 }
273 break;
274
275 case PIPE_PRIM_TRIANGLE_FAN:
276 for (i = 2; i < nr; i += 1) {
277 if (llvmpipe->rasterizer->flatshade_first) {
278 setup_tri( setup_ctx,
279 get_vert(vertex_buffer, indices[i-0], stride),
280 get_vert(vertex_buffer, indices[0], stride),
281 get_vert(vertex_buffer, indices[i-1], stride) );
282 }
283 else {
284 setup_tri( setup_ctx,
285 get_vert(vertex_buffer, indices[0], stride),
286 get_vert(vertex_buffer, indices[i-1], stride),
287 get_vert(vertex_buffer, indices[i-0], stride) );
288 }
289 }
290 break;
291
292 case PIPE_PRIM_QUADS:
293 for (i = 3; i < nr; i += 4) {
294 if (llvmpipe->rasterizer->flatshade_first) {
295 setup_tri( setup_ctx,
296 get_vert(vertex_buffer, indices[i-2], stride),
297 get_vert(vertex_buffer, indices[i-1], stride),
298 get_vert(vertex_buffer, indices[i-3], stride) );
299 setup_tri( setup_ctx,
300 get_vert(vertex_buffer, indices[i-1], stride),
301 get_vert(vertex_buffer, indices[i-0], stride),
302 get_vert(vertex_buffer, indices[i-3], stride) );
303 }
304 else {
305 setup_tri( setup_ctx,
306 get_vert(vertex_buffer, indices[i-3], stride),
307 get_vert(vertex_buffer, indices[i-2], stride),
308 get_vert(vertex_buffer, indices[i-0], stride) );
309
310 setup_tri( setup_ctx,
311 get_vert(vertex_buffer, indices[i-2], stride),
312 get_vert(vertex_buffer, indices[i-1], stride),
313 get_vert(vertex_buffer, indices[i-0], stride) );
314 }
315 }
316 break;
317
318 case PIPE_PRIM_QUAD_STRIP:
319 for (i = 3; i < nr; i += 2) {
320 if (llvmpipe->rasterizer->flatshade_first) {
321 setup_tri( setup_ctx,
322 get_vert(vertex_buffer, indices[i-0], stride),
323 get_vert(vertex_buffer, indices[i-1], stride),
324 get_vert(vertex_buffer, indices[i-3], stride));
325 setup_tri( setup_ctx,
326 get_vert(vertex_buffer, indices[i-2], stride),
327 get_vert(vertex_buffer, indices[i-0], stride),
328 get_vert(vertex_buffer, indices[i-3], stride) );
329 }
330 else {
331 setup_tri( setup_ctx,
332 get_vert(vertex_buffer, indices[i-3], stride),
333 get_vert(vertex_buffer, indices[i-2], stride),
334 get_vert(vertex_buffer, indices[i-0], stride) );
335 setup_tri( setup_ctx,
336 get_vert(vertex_buffer, indices[i-1], stride),
337 get_vert(vertex_buffer, indices[i-3], stride),
338 get_vert(vertex_buffer, indices[i-0], stride) );
339 }
340 }
341 break;
342
343 case PIPE_PRIM_POLYGON:
344 /* Almost same as tri fan but the _first_ vertex specifies the flat
345 * shading color. Note that the first polygon vertex is passed as
346 * the last triangle vertex here.
347 * flatshade_first state makes no difference.
348 */
349 for (i = 2; i < nr; i += 1) {
350 setup_tri( setup_ctx,
351 get_vert(vertex_buffer, indices[i-0], stride),
352 get_vert(vertex_buffer, indices[i-1], stride),
353 get_vert(vertex_buffer, indices[0], stride) );
354 }
355 break;
356
357 default:
358 assert(0);
359 }
360
361 /* XXX: why are we calling this??? If we had to call something, it
362 * would be a function in lp_setup.c:
363 */
364 lp_draw_flush( setup );
365 }
366
367
368 /**
369 * This function is hit when the draw module is working in pass-through mode.
370 * It's up to us to convert the vertex array into point/line/tri prims.
371 */
372 static void
373 lp_vbuf_draw_arrays(struct vbuf_render *vbr, uint start, uint nr)
374 {
375 struct llvmpipe_vbuf_render *cvbr = llvmpipe_vbuf_render(vbr);
376 struct llvmpipe_context *llvmpipe = cvbr->llvmpipe;
377 const unsigned stride = llvmpipe->vertex_info_vbuf.size * sizeof(float);
378 const void *vertex_buffer =
379 (void *) get_vert(cvbr->vertex_buffer, start, stride);
380 unsigned i;
381
382 /* XXX: break this dependency - make setup_context live under
383 * llvmpipe, rename the old "setup" draw stage to something else.
384 */
385 struct draw_stage *setup = llvmpipe->setup;
386 struct setup_context *setup_ctx = lp_draw_setup_context(setup);
387
388 switch (cvbr->prim) {
389 case PIPE_PRIM_POINTS:
390 for (i = 0; i < nr; i++) {
391 setup_point( setup_ctx,
392 get_vert(vertex_buffer, i-0, stride) );
393 }
394 break;
395
396 case PIPE_PRIM_LINES:
397 for (i = 1; i < nr; i += 2) {
398 setup_line( setup_ctx,
399 get_vert(vertex_buffer, i-1, stride),
400 get_vert(vertex_buffer, i-0, stride) );
401 }
402 break;
403
404 case PIPE_PRIM_LINE_STRIP:
405 for (i = 1; i < nr; i ++) {
406 setup_line( setup_ctx,
407 get_vert(vertex_buffer, i-1, stride),
408 get_vert(vertex_buffer, i-0, stride) );
409 }
410 break;
411
412 case PIPE_PRIM_LINE_LOOP:
413 for (i = 1; i < nr; i ++) {
414 setup_line( setup_ctx,
415 get_vert(vertex_buffer, i-1, stride),
416 get_vert(vertex_buffer, i-0, stride) );
417 }
418 if (nr) {
419 setup_line( setup_ctx,
420 get_vert(vertex_buffer, nr-1, stride),
421 get_vert(vertex_buffer, 0, stride) );
422 }
423 break;
424
425 case PIPE_PRIM_TRIANGLES:
426 for (i = 2; i < nr; i += 3) {
427 if (llvmpipe->rasterizer->flatshade_first) {
428 setup_tri( setup_ctx,
429 get_vert(vertex_buffer, i-1, stride),
430 get_vert(vertex_buffer, i-0, stride),
431 get_vert(vertex_buffer, i-2, stride) );
432 }
433 else {
434 setup_tri( setup_ctx,
435 get_vert(vertex_buffer, i-2, stride),
436 get_vert(vertex_buffer, i-1, stride),
437 get_vert(vertex_buffer, i-0, stride) );
438 }
439 }
440 break;
441
442 case PIPE_PRIM_TRIANGLE_STRIP:
443 for (i = 2; i < nr; i++) {
444 if (llvmpipe->rasterizer->flatshade_first) {
445 setup_tri( setup_ctx,
446 get_vert(vertex_buffer, i+(i&1)-1, stride),
447 get_vert(vertex_buffer, i-(i&1), stride),
448 get_vert(vertex_buffer, i-2, stride) );
449 }
450 else {
451 setup_tri( setup_ctx,
452 get_vert(vertex_buffer, i+(i&1)-2, stride),
453 get_vert(vertex_buffer, i-(i&1)-1, stride),
454 get_vert(vertex_buffer, i-0, stride) );
455 }
456 }
457 break;
458
459 case PIPE_PRIM_TRIANGLE_FAN:
460 for (i = 2; i < nr; i += 1) {
461 if (llvmpipe->rasterizer->flatshade_first) {
462 setup_tri( setup_ctx,
463 get_vert(vertex_buffer, i-0, stride),
464 get_vert(vertex_buffer, 0, stride),
465 get_vert(vertex_buffer, i-1, stride) );
466 }
467 else {
468 setup_tri( setup_ctx,
469 get_vert(vertex_buffer, 0, stride),
470 get_vert(vertex_buffer, i-1, stride),
471 get_vert(vertex_buffer, i-0, stride) );
472 }
473 }
474 break;
475
476 case PIPE_PRIM_QUADS:
477 for (i = 3; i < nr; i += 4) {
478 if (llvmpipe->rasterizer->flatshade_first) {
479 setup_tri( setup_ctx,
480 get_vert(vertex_buffer, i-2, stride),
481 get_vert(vertex_buffer, i-1, stride),
482 get_vert(vertex_buffer, i-3, stride) );
483 setup_tri( setup_ctx,
484 get_vert(vertex_buffer, i-1, stride),
485 get_vert(vertex_buffer, i-0, stride),
486 get_vert(vertex_buffer, i-3, stride) );
487 }
488 else {
489 setup_tri( setup_ctx,
490 get_vert(vertex_buffer, i-3, stride),
491 get_vert(vertex_buffer, i-2, stride),
492 get_vert(vertex_buffer, i-0, stride) );
493 setup_tri( setup_ctx,
494 get_vert(vertex_buffer, i-2, stride),
495 get_vert(vertex_buffer, i-1, stride),
496 get_vert(vertex_buffer, i-0, stride) );
497 }
498 }
499 break;
500
501 case PIPE_PRIM_QUAD_STRIP:
502 for (i = 3; i < nr; i += 2) {
503 if (llvmpipe->rasterizer->flatshade_first) {
504 setup_tri( setup_ctx,
505 get_vert(vertex_buffer, i-0, stride),
506 get_vert(vertex_buffer, i-1, stride),
507 get_vert(vertex_buffer, i-3, stride) );
508 setup_tri( setup_ctx,
509 get_vert(vertex_buffer, i-2, stride),
510 get_vert(vertex_buffer, i-0, stride),
511 get_vert(vertex_buffer, i-3, stride) );
512 }
513 else {
514 setup_tri( setup_ctx,
515 get_vert(vertex_buffer, i-3, stride),
516 get_vert(vertex_buffer, i-2, stride),
517 get_vert(vertex_buffer, i-0, stride) );
518 setup_tri( setup_ctx,
519 get_vert(vertex_buffer, i-1, stride),
520 get_vert(vertex_buffer, i-3, stride),
521 get_vert(vertex_buffer, i-0, stride) );
522 }
523 }
524 break;
525
526 case PIPE_PRIM_POLYGON:
527 /* Almost same as tri fan but the _first_ vertex specifies the flat
528 * shading color. Note that the first polygon vertex is passed as
529 * the last triangle vertex here.
530 * flatshade_first state makes no difference.
531 */
532 for (i = 2; i < nr; i += 1) {
533 setup_tri( setup_ctx,
534 get_vert(vertex_buffer, i-1, stride),
535 get_vert(vertex_buffer, i-0, stride),
536 get_vert(vertex_buffer, 0, stride) );
537 }
538 break;
539
540 default:
541 assert(0);
542 }
543 }
544
545
546
547 static void
548 lp_vbuf_destroy(struct vbuf_render *vbr)
549 {
550 struct llvmpipe_vbuf_render *cvbr = llvmpipe_vbuf_render(vbr);
551 cvbr->llvmpipe->vbuf_render = NULL;
552 FREE(cvbr);
553 }
554
555
556 /**
557 * Initialize the post-transform vertex buffer information for the given
558 * context.
559 */
560 void
561 lp_init_vbuf(struct llvmpipe_context *lp)
562 {
563 assert(lp->draw);
564
565 lp->vbuf_render = CALLOC_STRUCT(llvmpipe_vbuf_render);
566
567 lp->vbuf_render->base.max_indices = LP_MAX_VBUF_INDEXES;
568 lp->vbuf_render->base.max_vertex_buffer_bytes = LP_MAX_VBUF_SIZE;
569
570 lp->vbuf_render->base.get_vertex_info = lp_vbuf_get_vertex_info;
571 lp->vbuf_render->base.allocate_vertices = lp_vbuf_allocate_vertices;
572 lp->vbuf_render->base.map_vertices = lp_vbuf_map_vertices;
573 lp->vbuf_render->base.unmap_vertices = lp_vbuf_unmap_vertices;
574 lp->vbuf_render->base.set_primitive = lp_vbuf_set_primitive;
575 lp->vbuf_render->base.draw = lp_vbuf_draw;
576 lp->vbuf_render->base.draw_arrays = lp_vbuf_draw_arrays;
577 lp->vbuf_render->base.release_vertices = lp_vbuf_release_vertices;
578 lp->vbuf_render->base.destroy = lp_vbuf_destroy;
579
580 lp->vbuf_render->llvmpipe = lp;
581
582 lp->vbuf = draw_vbuf_stage(lp->draw, &lp->vbuf_render->base);
583
584 draw_set_rasterize_stage(lp->draw, lp->vbuf);
585
586 draw_set_render(lp->draw, &lp->vbuf_render->base);
587 }