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"
43 #include "draw/draw_context.h"
44 #include "draw/draw_vbuf.h"
45 #include "util/u_memory.h"
46 #include "util/u_prim.h"
49 #define LP_MAX_VBUF_INDEXES 1024
50 #define LP_MAX_VBUF_SIZE 4096
52 typedef const float (*cptrf4
)[4];
55 * Subclass of vbuf_render.
57 struct llvmpipe_vbuf_render
59 struct vbuf_render base
;
60 struct llvmpipe_context
*llvmpipe
;
61 struct setup_context
*setup
;
66 uint vertex_buffer_size
;
72 static struct llvmpipe_vbuf_render
*
73 llvmpipe_vbuf_render(struct vbuf_render
*vbr
)
75 return (struct llvmpipe_vbuf_render
*) vbr
;
84 static const struct vertex_info
*
85 lp_vbuf_get_vertex_info(struct vbuf_render
*vbr
)
87 struct llvmpipe_vbuf_render
*cvbr
= llvmpipe_vbuf_render(vbr
);
88 return llvmpipe_get_vbuf_vertex_info(cvbr
->llvmpipe
);
93 lp_vbuf_allocate_vertices(struct vbuf_render
*vbr
,
94 ushort vertex_size
, ushort nr_vertices
)
96 struct llvmpipe_vbuf_render
*cvbr
= llvmpipe_vbuf_render(vbr
);
97 unsigned size
= vertex_size
* nr_vertices
;
99 if (cvbr
->vertex_buffer_size
< size
) {
100 align_free(cvbr
->vertex_buffer
);
101 cvbr
->vertex_buffer
= align_malloc(size
, 16);
102 cvbr
->vertex_buffer_size
= size
;
105 cvbr
->vertex_size
= vertex_size
;
106 cvbr
->nr_vertices
= nr_vertices
;
108 return cvbr
->vertex_buffer
!= NULL
;
112 lp_vbuf_release_vertices(struct vbuf_render
*vbr
)
114 /* keep the old allocation for next time */
118 lp_vbuf_map_vertices(struct vbuf_render
*vbr
)
120 struct llvmpipe_vbuf_render
*cvbr
= llvmpipe_vbuf_render(vbr
);
121 return cvbr
->vertex_buffer
;
125 lp_vbuf_unmap_vertices(struct vbuf_render
*vbr
,
129 struct llvmpipe_vbuf_render
*cvbr
= llvmpipe_vbuf_render(vbr
);
130 assert( cvbr
->vertex_buffer_size
>= (max_index
+1) * cvbr
->vertex_size
);
136 lp_vbuf_set_primitive(struct vbuf_render
*vbr
, unsigned prim
)
138 struct llvmpipe_vbuf_render
*cvbr
= llvmpipe_vbuf_render(vbr
);
140 llvmpipe_update_derived( cvbr
->llvmpipe
);
142 cvbr
->llvmpipe
->reduced_prim
= u_reduced_prim(prim
);
149 static INLINE cptrf4
get_vert( const void *vertex_buffer
,
153 return (cptrf4
)((char *)vertex_buffer
+ index
* stride
);
158 * draw elements / indexed primitives
161 lp_vbuf_draw(struct vbuf_render
*vbr
, const ushort
*indices
, uint nr
)
163 struct llvmpipe_vbuf_render
*cvbr
= llvmpipe_vbuf_render(vbr
);
164 struct llvmpipe_context
*llvmpipe
= cvbr
->llvmpipe
;
165 const unsigned stride
= llvmpipe
->vertex_info_vbuf
.size
* sizeof(float);
166 const void *vertex_buffer
= cvbr
->vertex_buffer
;
167 struct setup_context
*setup_ctx
= cvbr
->setup
;
170 switch (cvbr
->prim
) {
171 case PIPE_PRIM_POINTS
:
172 for (i
= 0; i
< nr
; i
++) {
173 lp_setup_point( setup_ctx
,
174 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
178 case PIPE_PRIM_LINES
:
179 for (i
= 1; i
< nr
; i
+= 2) {
180 lp_setup_line( setup_ctx
,
181 get_vert(vertex_buffer
, indices
[i
-1], stride
),
182 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
186 case PIPE_PRIM_LINE_STRIP
:
187 for (i
= 1; i
< nr
; i
++) {
188 lp_setup_line( setup_ctx
,
189 get_vert(vertex_buffer
, indices
[i
-1], stride
),
190 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
194 case PIPE_PRIM_LINE_LOOP
:
195 for (i
= 1; i
< nr
; i
++) {
196 lp_setup_line( setup_ctx
,
197 get_vert(vertex_buffer
, indices
[i
-1], stride
),
198 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
201 lp_setup_line( setup_ctx
,
202 get_vert(vertex_buffer
, indices
[nr
-1], stride
),
203 get_vert(vertex_buffer
, indices
[0], stride
) );
207 case PIPE_PRIM_TRIANGLES
:
208 if (llvmpipe
->rasterizer
->flatshade_first
) {
209 for (i
= 2; i
< nr
; i
+= 3) {
210 lp_setup_tri( setup_ctx
,
211 get_vert(vertex_buffer
, indices
[i
-1], stride
),
212 get_vert(vertex_buffer
, indices
[i
-0], stride
),
213 get_vert(vertex_buffer
, indices
[i
-2], stride
) );
217 for (i
= 2; i
< nr
; i
+= 3) {
218 lp_setup_tri( setup_ctx
,
219 get_vert(vertex_buffer
, indices
[i
-2], stride
),
220 get_vert(vertex_buffer
, indices
[i
-1], stride
),
221 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
226 case PIPE_PRIM_TRIANGLE_STRIP
:
227 if (llvmpipe
->rasterizer
->flatshade_first
) {
228 for (i
= 2; i
< nr
; i
+= 1) {
229 lp_setup_tri( setup_ctx
,
230 get_vert(vertex_buffer
, indices
[i
+(i
&1)-1], stride
),
231 get_vert(vertex_buffer
, indices
[i
-(i
&1)], stride
),
232 get_vert(vertex_buffer
, indices
[i
-2], stride
) );
236 for (i
= 2; i
< nr
; i
+= 1) {
237 lp_setup_tri( setup_ctx
,
238 get_vert(vertex_buffer
, indices
[i
+(i
&1)-2], stride
),
239 get_vert(vertex_buffer
, indices
[i
-(i
&1)-1], stride
),
240 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
245 case PIPE_PRIM_TRIANGLE_FAN
:
246 if (llvmpipe
->rasterizer
->flatshade_first
) {
247 for (i
= 2; i
< nr
; i
+= 1) {
248 lp_setup_tri( setup_ctx
,
249 get_vert(vertex_buffer
, indices
[i
-0], stride
),
250 get_vert(vertex_buffer
, indices
[0], stride
),
251 get_vert(vertex_buffer
, indices
[i
-1], stride
) );
255 for (i
= 2; i
< nr
; i
+= 1) {
256 lp_setup_tri( setup_ctx
,
257 get_vert(vertex_buffer
, indices
[0], stride
),
258 get_vert(vertex_buffer
, indices
[i
-1], stride
),
259 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
264 case PIPE_PRIM_QUADS
:
265 if (llvmpipe
->rasterizer
->flatshade_first
) {
266 for (i
= 3; i
< nr
; i
+= 4) {
267 lp_setup_tri( setup_ctx
,
268 get_vert(vertex_buffer
, indices
[i
-2], stride
),
269 get_vert(vertex_buffer
, indices
[i
-1], stride
),
270 get_vert(vertex_buffer
, indices
[i
-3], stride
) );
271 lp_setup_tri( setup_ctx
,
272 get_vert(vertex_buffer
, indices
[i
-1], stride
),
273 get_vert(vertex_buffer
, indices
[i
-0], stride
),
274 get_vert(vertex_buffer
, indices
[i
-3], stride
) );
278 for (i
= 3; i
< nr
; i
+= 4) {
279 lp_setup_tri( setup_ctx
,
280 get_vert(vertex_buffer
, indices
[i
-3], stride
),
281 get_vert(vertex_buffer
, indices
[i
-2], stride
),
282 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
284 lp_setup_tri( setup_ctx
,
285 get_vert(vertex_buffer
, indices
[i
-2], stride
),
286 get_vert(vertex_buffer
, indices
[i
-1], stride
),
287 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
292 case PIPE_PRIM_QUAD_STRIP
:
293 if (llvmpipe
->rasterizer
->flatshade_first
) {
294 for (i
= 3; i
< nr
; i
+= 2) {
295 lp_setup_tri( setup_ctx
,
296 get_vert(vertex_buffer
, indices
[i
-0], stride
),
297 get_vert(vertex_buffer
, indices
[i
-1], stride
),
298 get_vert(vertex_buffer
, indices
[i
-3], stride
));
299 lp_setup_tri( setup_ctx
,
300 get_vert(vertex_buffer
, indices
[i
-2], stride
),
301 get_vert(vertex_buffer
, indices
[i
-0], stride
),
302 get_vert(vertex_buffer
, indices
[i
-3], stride
) );
306 for (i
= 3; i
< nr
; i
+= 2) {
307 lp_setup_tri( setup_ctx
,
308 get_vert(vertex_buffer
, indices
[i
-3], stride
),
309 get_vert(vertex_buffer
, indices
[i
-2], stride
),
310 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
311 lp_setup_tri( setup_ctx
,
312 get_vert(vertex_buffer
, indices
[i
-1], stride
),
313 get_vert(vertex_buffer
, indices
[i
-3], stride
),
314 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
319 case PIPE_PRIM_POLYGON
:
320 /* Almost same as tri fan but the _first_ vertex specifies the flat
321 * shading color. Note that the first polygon vertex is passed as
322 * the last triangle vertex here.
323 * flatshade_first state makes no difference.
325 for (i
= 2; i
< nr
; i
+= 1) {
326 lp_setup_tri( setup_ctx
,
327 get_vert(vertex_buffer
, indices
[i
-0], stride
),
328 get_vert(vertex_buffer
, indices
[i
-1], stride
),
329 get_vert(vertex_buffer
, indices
[0], stride
) );
340 * This function is hit when the draw module is working in pass-through mode.
341 * It's up to us to convert the vertex array into point/line/tri prims.
344 lp_vbuf_draw_arrays(struct vbuf_render
*vbr
, uint start
, uint nr
)
346 struct llvmpipe_vbuf_render
*cvbr
= llvmpipe_vbuf_render(vbr
);
347 struct llvmpipe_context
*llvmpipe
= cvbr
->llvmpipe
;
348 struct setup_context
*setup_ctx
= cvbr
->setup
;
349 const unsigned stride
= llvmpipe
->vertex_info_vbuf
.size
* sizeof(float);
350 const void *vertex_buffer
=
351 (void *) get_vert(cvbr
->vertex_buffer
, start
, stride
);
354 switch (cvbr
->prim
) {
355 case PIPE_PRIM_POINTS
:
356 for (i
= 0; i
< nr
; i
++) {
357 lp_setup_point( setup_ctx
,
358 get_vert(vertex_buffer
, i
-0, stride
) );
362 case PIPE_PRIM_LINES
:
363 for (i
= 1; i
< nr
; i
+= 2) {
364 lp_setup_line( setup_ctx
,
365 get_vert(vertex_buffer
, i
-1, stride
),
366 get_vert(vertex_buffer
, i
-0, stride
) );
370 case PIPE_PRIM_LINE_STRIP
:
371 for (i
= 1; i
< nr
; i
++) {
372 lp_setup_line( setup_ctx
,
373 get_vert(vertex_buffer
, i
-1, stride
),
374 get_vert(vertex_buffer
, i
-0, stride
) );
378 case PIPE_PRIM_LINE_LOOP
:
379 for (i
= 1; i
< nr
; i
++) {
380 lp_setup_line( setup_ctx
,
381 get_vert(vertex_buffer
, i
-1, stride
),
382 get_vert(vertex_buffer
, i
-0, stride
) );
385 lp_setup_line( setup_ctx
,
386 get_vert(vertex_buffer
, nr
-1, stride
),
387 get_vert(vertex_buffer
, 0, stride
) );
391 case PIPE_PRIM_TRIANGLES
:
392 if (llvmpipe
->rasterizer
->flatshade_first
) {
393 for (i
= 2; i
< nr
; i
+= 3) {
394 lp_setup_tri( setup_ctx
,
395 get_vert(vertex_buffer
, i
-1, stride
),
396 get_vert(vertex_buffer
, i
-0, stride
),
397 get_vert(vertex_buffer
, i
-2, stride
) );
401 for (i
= 2; i
< nr
; i
+= 3) {
402 lp_setup_tri( setup_ctx
,
403 get_vert(vertex_buffer
, i
-2, stride
),
404 get_vert(vertex_buffer
, i
-1, stride
),
405 get_vert(vertex_buffer
, i
-0, stride
) );
410 case PIPE_PRIM_TRIANGLE_STRIP
:
411 if (llvmpipe
->rasterizer
->flatshade_first
) {
412 for (i
= 2; i
< nr
; i
++) {
413 lp_setup_tri( setup_ctx
,
414 get_vert(vertex_buffer
, i
+(i
&1)-1, stride
),
415 get_vert(vertex_buffer
, i
-(i
&1), stride
),
416 get_vert(vertex_buffer
, i
-2, stride
) );
420 for (i
= 2; i
< nr
; i
++) {
421 lp_setup_tri( setup_ctx
,
422 get_vert(vertex_buffer
, i
+(i
&1)-2, stride
),
423 get_vert(vertex_buffer
, i
-(i
&1)-1, stride
),
424 get_vert(vertex_buffer
, i
-0, stride
) );
429 case PIPE_PRIM_TRIANGLE_FAN
:
430 if (llvmpipe
->rasterizer
->flatshade_first
) {
431 for (i
= 2; i
< nr
; i
+= 1) {
432 lp_setup_tri( setup_ctx
,
433 get_vert(vertex_buffer
, i
-0, stride
),
434 get_vert(vertex_buffer
, 0, stride
),
435 get_vert(vertex_buffer
, i
-1, stride
) );
439 for (i
= 2; i
< nr
; i
+= 1) {
440 lp_setup_tri( setup_ctx
,
441 get_vert(vertex_buffer
, 0, stride
),
442 get_vert(vertex_buffer
, i
-1, stride
),
443 get_vert(vertex_buffer
, i
-0, stride
) );
448 case PIPE_PRIM_QUADS
:
449 if (llvmpipe
->rasterizer
->flatshade_first
) {
450 for (i
= 3; i
< nr
; i
+= 4) {
451 lp_setup_tri( setup_ctx
,
452 get_vert(vertex_buffer
, i
-2, stride
),
453 get_vert(vertex_buffer
, i
-1, stride
),
454 get_vert(vertex_buffer
, i
-3, stride
) );
455 lp_setup_tri( setup_ctx
,
456 get_vert(vertex_buffer
, i
-1, stride
),
457 get_vert(vertex_buffer
, i
-0, stride
),
458 get_vert(vertex_buffer
, i
-3, stride
) );
462 for (i
= 3; i
< nr
; i
+= 4) {
463 lp_setup_tri( setup_ctx
,
464 get_vert(vertex_buffer
, i
-3, stride
),
465 get_vert(vertex_buffer
, i
-2, stride
),
466 get_vert(vertex_buffer
, i
-0, stride
) );
467 lp_setup_tri( setup_ctx
,
468 get_vert(vertex_buffer
, i
-2, stride
),
469 get_vert(vertex_buffer
, i
-1, stride
),
470 get_vert(vertex_buffer
, i
-0, stride
) );
475 case PIPE_PRIM_QUAD_STRIP
:
476 if (llvmpipe
->rasterizer
->flatshade_first
) {
477 for (i
= 3; i
< nr
; i
+= 2) {
478 lp_setup_tri( setup_ctx
,
479 get_vert(vertex_buffer
, i
-0, stride
),
480 get_vert(vertex_buffer
, i
-1, stride
),
481 get_vert(vertex_buffer
, i
-3, stride
) );
482 lp_setup_tri( setup_ctx
,
483 get_vert(vertex_buffer
, i
-2, stride
),
484 get_vert(vertex_buffer
, i
-0, stride
),
485 get_vert(vertex_buffer
, i
-3, stride
) );
489 for (i
= 3; i
< nr
; i
+= 2) {
490 lp_setup_tri( setup_ctx
,
491 get_vert(vertex_buffer
, i
-3, stride
),
492 get_vert(vertex_buffer
, i
-2, stride
),
493 get_vert(vertex_buffer
, i
-0, stride
) );
494 lp_setup_tri( setup_ctx
,
495 get_vert(vertex_buffer
, i
-1, stride
),
496 get_vert(vertex_buffer
, i
-3, stride
),
497 get_vert(vertex_buffer
, i
-0, stride
) );
502 case PIPE_PRIM_POLYGON
:
503 /* Almost same as tri fan but the _first_ vertex specifies the flat
504 * shading color. Note that the first polygon vertex is passed as
505 * the last triangle vertex here.
506 * flatshade_first state makes no difference.
508 for (i
= 2; i
< nr
; i
+= 1) {
509 lp_setup_tri( setup_ctx
,
510 get_vert(vertex_buffer
, i
-1, stride
),
511 get_vert(vertex_buffer
, i
-0, stride
),
512 get_vert(vertex_buffer
, 0, stride
) );
524 lp_vbuf_destroy(struct vbuf_render
*vbr
)
531 * Create the post-transform vertex handler for the given context.
534 lp_create_vbuf_backend(struct llvmpipe_context
*lp
)
536 struct llvmpipe_vbuf_render
*cvbr
= CALLOC_STRUCT(llvmpipe_vbuf_render
);
542 cvbr
->base
.max_indices
= LP_MAX_VBUF_INDEXES
;
543 cvbr
->base
.max_vertex_buffer_bytes
= LP_MAX_VBUF_SIZE
;
545 cvbr
->base
.get_vertex_info
= lp_vbuf_get_vertex_info
;
546 cvbr
->base
.allocate_vertices
= lp_vbuf_allocate_vertices
;
547 cvbr
->base
.map_vertices
= lp_vbuf_map_vertices
;
548 cvbr
->base
.unmap_vertices
= lp_vbuf_unmap_vertices
;
549 cvbr
->base
.set_primitive
= lp_vbuf_set_primitive
;
550 cvbr
->base
.draw
= lp_vbuf_draw
;
551 cvbr
->base
.draw_arrays
= lp_vbuf_draw_arrays
;
552 cvbr
->base
.release_vertices
= lp_vbuf_release_vertices
;
553 cvbr
->base
.destroy
= lp_vbuf_destroy
;
556 cvbr
->setup
= lp
->setup
;