1 /**************************************************************************
3 * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
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:
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
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.
26 **************************************************************************/
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.
39 #include "lp_context.h"
41 #include "lp_prim_vbuf.h"
42 #include "lp_prim_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"
50 #define LP_MAX_VBUF_INDEXES 1024
51 #define LP_MAX_VBUF_SIZE 4096
53 typedef const float (*cptrf4
)[4];
56 * Subclass of vbuf_render.
58 struct llvmpipe_vbuf_render
60 struct vbuf_render base
;
61 struct llvmpipe_context
*llvmpipe
;
65 uint vertex_buffer_size
;
71 static struct llvmpipe_vbuf_render
*
72 llvmpipe_vbuf_render(struct vbuf_render
*vbr
)
74 return (struct llvmpipe_vbuf_render
*) vbr
;
78 static const struct vertex_info
*
79 lp_vbuf_get_vertex_info(struct vbuf_render
*vbr
)
81 struct llvmpipe_vbuf_render
*cvbr
= llvmpipe_vbuf_render(vbr
);
82 return llvmpipe_get_vbuf_vertex_info(cvbr
->llvmpipe
);
87 lp_vbuf_allocate_vertices(struct vbuf_render
*vbr
,
88 ushort vertex_size
, ushort nr_vertices
)
90 struct llvmpipe_vbuf_render
*cvbr
= llvmpipe_vbuf_render(vbr
);
91 unsigned size
= vertex_size
* nr_vertices
;
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
;
99 cvbr
->vertex_size
= vertex_size
;
100 cvbr
->nr_vertices
= nr_vertices
;
102 return cvbr
->vertex_buffer
!= NULL
;
106 lp_vbuf_release_vertices(struct vbuf_render
*vbr
)
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
;
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
++) {
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;
127 debug_printf("Vert %u attr %u: ", i
, j
);
129 debug_printf("%g ", vtx
[0]);
138 /* keep the old allocation for next time */
142 lp_vbuf_map_vertices(struct vbuf_render
*vbr
)
144 struct llvmpipe_vbuf_render
*cvbr
= llvmpipe_vbuf_render(vbr
);
145 return cvbr
->vertex_buffer
;
149 lp_vbuf_unmap_vertices(struct vbuf_render
*vbr
,
153 struct llvmpipe_vbuf_render
*cvbr
= llvmpipe_vbuf_render(vbr
);
154 assert( cvbr
->vertex_buffer_size
>= (max_index
+1) * cvbr
->vertex_size
);
160 lp_vbuf_set_primitive(struct vbuf_render
*vbr
, unsigned prim
)
162 struct llvmpipe_vbuf_render
*cvbr
= llvmpipe_vbuf_render(vbr
);
164 /* XXX: break this dependency - make setup_context live under
165 * llvmpipe, rename the old "setup" draw stage to something else.
167 struct setup_context
*setup_ctx
= lp_draw_setup_context(cvbr
->llvmpipe
->setup
);
169 setup_prepare( setup_ctx
);
171 cvbr
->llvmpipe
->reduced_prim
= u_reduced_prim(prim
);
178 static INLINE cptrf4
get_vert( const void *vertex_buffer
,
182 return (cptrf4
)((char *)vertex_buffer
+ index
* stride
);
187 * draw elements / indexed primitives
190 lp_vbuf_draw(struct vbuf_render
*vbr
, const ushort
*indices
, uint nr
)
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
;
198 /* XXX: break this dependency - make setup_context live under
199 * llvmpipe, rename the old "setup" draw stage to something else.
201 struct draw_stage
*setup
= llvmpipe
->setup
;
202 struct setup_context
*setup_ctx
= lp_draw_setup_context(setup
);
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
) );
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
) );
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
) );
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
) );
235 setup_line( setup_ctx
,
236 get_vert(vertex_buffer
, indices
[nr
-1], stride
),
237 get_vert(vertex_buffer
, indices
[0], stride
) );
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
) );
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
) );
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
) );
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
) );
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
) );
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
) );
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
) );
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
) );
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
) );
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
) );
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
) );
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.
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
) );
361 /* XXX: why are we calling this??? If we had to call something, it
362 * would be a function in lp_setup.c:
364 lp_draw_flush( setup
);
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.
373 lp_vbuf_draw_arrays(struct vbuf_render
*vbr
, uint start
, uint nr
)
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
);
382 /* XXX: break this dependency - make setup_context live under
383 * llvmpipe, rename the old "setup" draw stage to something else.
385 struct draw_stage
*setup
= llvmpipe
->setup
;
386 struct setup_context
*setup_ctx
= lp_draw_setup_context(setup
);
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
) );
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
) );
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
) );
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
) );
419 setup_line( setup_ctx
,
420 get_vert(vertex_buffer
, nr
-1, stride
),
421 get_vert(vertex_buffer
, 0, stride
) );
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
) );
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
) );
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
) );
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
) );
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
) );
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
) );
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
) );
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
) );
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
) );
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
) );
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.
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
) );
548 lp_vbuf_destroy(struct vbuf_render
*vbr
)
550 struct llvmpipe_vbuf_render
*cvbr
= llvmpipe_vbuf_render(vbr
);
551 cvbr
->llvmpipe
->vbuf_render
= NULL
;
557 * Initialize the post-transform vertex buffer information for the given
561 lp_init_vbuf(struct llvmpipe_context
*lp
)
565 lp
->vbuf_render
= CALLOC_STRUCT(llvmpipe_vbuf_render
);
567 lp
->vbuf_render
->base
.max_indices
= LP_MAX_VBUF_INDEXES
;
568 lp
->vbuf_render
->base
.max_vertex_buffer_bytes
= LP_MAX_VBUF_SIZE
;
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
;
580 lp
->vbuf_render
->llvmpipe
= lp
;
582 lp
->vbuf
= draw_vbuf_stage(lp
->draw
, &lp
->vbuf_render
->base
);
584 draw_set_rasterize_stage(lp
->draw
, lp
->vbuf
);
586 draw_set_render(lp
->draw
, &lp
->vbuf_render
->base
);