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_setup_context.h"
40 #include "draw/draw_context.h"
41 #include "draw/draw_vbuf.h"
42 #include "draw/draw_vertex.h"
43 #include "util/u_memory.h"
44 #include "util/u_prim.h"
47 #define LP_MAX_VBUF_INDEXES 1024
48 #define LP_MAX_VBUF_SIZE 4096
53 static struct setup_context
*
54 setup_context(struct vbuf_render
*vbr
)
56 return (struct setup_context
*) vbr
;
61 static const struct vertex_info
*
62 lp_setup_get_vertex_info(struct vbuf_render
*vbr
)
64 struct setup_context
*setup
= setup_context(vbr
);
65 return setup
->vertex_info
;
70 lp_setup_allocate_vertices(struct vbuf_render
*vbr
,
71 ushort vertex_size
, ushort nr_vertices
)
73 struct setup_context
*setup
= setup_context(vbr
);
74 unsigned size
= vertex_size
* nr_vertices
;
76 if (setup
->vertex_buffer_size
< size
) {
77 align_free(setup
->vertex_buffer
);
78 setup
->vertex_buffer
= align_malloc(size
, 16);
79 setup
->vertex_buffer_size
= size
;
82 setup
->vertex_size
= vertex_size
;
83 setup
->nr_vertices
= nr_vertices
;
85 return setup
->vertex_buffer
!= NULL
;
89 lp_setup_release_vertices(struct vbuf_render
*vbr
)
91 /* keep the old allocation for next time */
95 lp_setup_map_vertices(struct vbuf_render
*vbr
)
97 struct setup_context
*setup
= setup_context(vbr
);
98 return setup
->vertex_buffer
;
102 lp_setup_unmap_vertices(struct vbuf_render
*vbr
,
106 struct setup_context
*setup
= setup_context(vbr
);
107 assert( setup
->vertex_buffer_size
>= (max_index
+1) * setup
->vertex_size
);
113 lp_setup_set_primitive(struct vbuf_render
*vbr
, unsigned prim
)
115 setup_context(vbr
)->prim
= prim
;
119 typedef const float (*const_float4_ptr
)[4];
121 static INLINE const_float4_ptr
get_vert( const void *vertex_buffer
,
125 return (const_float4_ptr
)((char *)vertex_buffer
+ index
* stride
);
129 * draw elements / indexed primitives
132 lp_setup_draw(struct vbuf_render
*vbr
, const ushort
*indices
, uint nr
)
134 struct setup_context
*setup
= setup_context(vbr
);
135 const unsigned stride
= setup
->vertex_info
->size
* sizeof(float);
136 const void *vertex_buffer
= setup
->vertex_buffer
;
139 lp_setup_update_state(setup
);
141 switch (setup
->prim
) {
142 case PIPE_PRIM_POINTS
:
143 for (i
= 0; i
< nr
; i
++) {
145 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
149 case PIPE_PRIM_LINES
:
150 for (i
= 1; i
< nr
; i
+= 2) {
152 get_vert(vertex_buffer
, indices
[i
-1], stride
),
153 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
157 case PIPE_PRIM_LINE_STRIP
:
158 for (i
= 1; i
< nr
; i
++) {
160 get_vert(vertex_buffer
, indices
[i
-1], stride
),
161 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
165 case PIPE_PRIM_LINE_LOOP
:
166 for (i
= 1; i
< nr
; i
++) {
168 get_vert(vertex_buffer
, indices
[i
-1], stride
),
169 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
173 get_vert(vertex_buffer
, indices
[nr
-1], stride
),
174 get_vert(vertex_buffer
, indices
[0], stride
) );
178 case PIPE_PRIM_TRIANGLES
:
179 if (setup
->flatshade_first
) {
180 for (i
= 2; i
< nr
; i
+= 3) {
181 setup
->triangle( setup
,
182 get_vert(vertex_buffer
, indices
[i
-1], stride
),
183 get_vert(vertex_buffer
, indices
[i
-0], stride
),
184 get_vert(vertex_buffer
, indices
[i
-2], stride
) );
188 for (i
= 2; i
< nr
; i
+= 3) {
189 setup
->triangle( setup
,
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
) );
197 case PIPE_PRIM_TRIANGLE_STRIP
:
198 if (setup
->flatshade_first
) {
199 for (i
= 2; i
< nr
; i
+= 1) {
200 setup
->triangle( setup
,
201 get_vert(vertex_buffer
, indices
[i
+(i
&1)-1], stride
),
202 get_vert(vertex_buffer
, indices
[i
-(i
&1)], stride
),
203 get_vert(vertex_buffer
, indices
[i
-2], stride
) );
207 for (i
= 2; i
< nr
; i
+= 1) {
208 setup
->triangle( setup
,
209 get_vert(vertex_buffer
, indices
[i
+(i
&1)-2], stride
),
210 get_vert(vertex_buffer
, indices
[i
-(i
&1)-1], stride
),
211 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
216 case PIPE_PRIM_TRIANGLE_FAN
:
217 if (setup
->flatshade_first
) {
218 for (i
= 2; i
< nr
; i
+= 1) {
219 setup
->triangle( setup
,
220 get_vert(vertex_buffer
, indices
[i
-0], stride
),
221 get_vert(vertex_buffer
, indices
[0], stride
),
222 get_vert(vertex_buffer
, indices
[i
-1], stride
) );
226 for (i
= 2; i
< nr
; i
+= 1) {
227 setup
->triangle( setup
,
228 get_vert(vertex_buffer
, indices
[0], stride
),
229 get_vert(vertex_buffer
, indices
[i
-1], stride
),
230 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
235 case PIPE_PRIM_QUADS
:
236 if (setup
->flatshade_first
) {
237 for (i
= 3; i
< nr
; i
+= 4) {
238 setup
->triangle( setup
,
239 get_vert(vertex_buffer
, indices
[i
-2], stride
),
240 get_vert(vertex_buffer
, indices
[i
-1], stride
),
241 get_vert(vertex_buffer
, indices
[i
-3], stride
) );
242 setup
->triangle( setup
,
243 get_vert(vertex_buffer
, indices
[i
-1], stride
),
244 get_vert(vertex_buffer
, indices
[i
-0], stride
),
245 get_vert(vertex_buffer
, indices
[i
-3], stride
) );
249 for (i
= 3; i
< nr
; i
+= 4) {
250 setup
->triangle( setup
,
251 get_vert(vertex_buffer
, indices
[i
-3], stride
),
252 get_vert(vertex_buffer
, indices
[i
-2], stride
),
253 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
255 setup
->triangle( setup
,
256 get_vert(vertex_buffer
, indices
[i
-2], stride
),
257 get_vert(vertex_buffer
, indices
[i
-1], stride
),
258 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
263 case PIPE_PRIM_QUAD_STRIP
:
264 if (setup
->flatshade_first
) {
265 for (i
= 3; i
< nr
; i
+= 2) {
266 setup
->triangle( setup
,
267 get_vert(vertex_buffer
, indices
[i
-0], stride
),
268 get_vert(vertex_buffer
, indices
[i
-1], stride
),
269 get_vert(vertex_buffer
, indices
[i
-3], stride
));
270 setup
->triangle( setup
,
271 get_vert(vertex_buffer
, indices
[i
-2], stride
),
272 get_vert(vertex_buffer
, indices
[i
-0], stride
),
273 get_vert(vertex_buffer
, indices
[i
-3], stride
) );
277 for (i
= 3; i
< nr
; i
+= 2) {
278 setup
->triangle( setup
,
279 get_vert(vertex_buffer
, indices
[i
-3], stride
),
280 get_vert(vertex_buffer
, indices
[i
-2], stride
),
281 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
282 setup
->triangle( setup
,
283 get_vert(vertex_buffer
, indices
[i
-1], stride
),
284 get_vert(vertex_buffer
, indices
[i
-3], stride
),
285 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
290 case PIPE_PRIM_POLYGON
:
291 /* Almost same as tri fan but the _first_ vertex specifies the flat
292 * shading color. Note that the first polygon vertex is passed as
293 * the last triangle vertex here.
294 * flatshade_first state makes no difference.
296 for (i
= 2; i
< nr
; i
+= 1) {
297 setup
->triangle( setup
,
298 get_vert(vertex_buffer
, indices
[i
-0], stride
),
299 get_vert(vertex_buffer
, indices
[i
-1], stride
),
300 get_vert(vertex_buffer
, indices
[0], stride
) );
311 * This function is hit when the draw module is working in pass-through mode.
312 * It's up to us to convert the vertex array into point/line/tri prims.
315 lp_setup_draw_arrays(struct vbuf_render
*vbr
, uint start
, uint nr
)
317 struct setup_context
*setup
= setup_context(vbr
);
318 const unsigned stride
= setup
->vertex_info
->size
* sizeof(float);
319 const void *vertex_buffer
=
320 (void *) get_vert(setup
->vertex_buffer
, start
, stride
);
323 lp_setup_update_state(setup
);
325 switch (setup
->prim
) {
326 case PIPE_PRIM_POINTS
:
327 for (i
= 0; i
< nr
; i
++) {
329 get_vert(vertex_buffer
, i
-0, stride
) );
333 case PIPE_PRIM_LINES
:
334 for (i
= 1; i
< nr
; i
+= 2) {
336 get_vert(vertex_buffer
, i
-1, stride
),
337 get_vert(vertex_buffer
, i
-0, stride
) );
341 case PIPE_PRIM_LINE_STRIP
:
342 for (i
= 1; i
< nr
; i
++) {
344 get_vert(vertex_buffer
, i
-1, stride
),
345 get_vert(vertex_buffer
, i
-0, stride
) );
349 case PIPE_PRIM_LINE_LOOP
:
350 for (i
= 1; i
< nr
; i
++) {
352 get_vert(vertex_buffer
, i
-1, stride
),
353 get_vert(vertex_buffer
, i
-0, stride
) );
357 get_vert(vertex_buffer
, nr
-1, stride
),
358 get_vert(vertex_buffer
, 0, stride
) );
362 case PIPE_PRIM_TRIANGLES
:
363 if (setup
->flatshade_first
) {
364 for (i
= 2; i
< nr
; i
+= 3) {
365 setup
->triangle( setup
,
366 get_vert(vertex_buffer
, i
-1, stride
),
367 get_vert(vertex_buffer
, i
-0, stride
),
368 get_vert(vertex_buffer
, i
-2, stride
) );
372 for (i
= 2; i
< nr
; i
+= 3) {
373 setup
->triangle( setup
,
374 get_vert(vertex_buffer
, i
-2, stride
),
375 get_vert(vertex_buffer
, i
-1, stride
),
376 get_vert(vertex_buffer
, i
-0, stride
) );
381 case PIPE_PRIM_TRIANGLE_STRIP
:
382 if (setup
->flatshade_first
) {
383 for (i
= 2; i
< nr
; i
++) {
384 setup
->triangle( setup
,
385 get_vert(vertex_buffer
, i
+(i
&1)-1, stride
),
386 get_vert(vertex_buffer
, i
-(i
&1), stride
),
387 get_vert(vertex_buffer
, i
-2, stride
) );
391 for (i
= 2; i
< nr
; i
++) {
392 setup
->triangle( setup
,
393 get_vert(vertex_buffer
, i
+(i
&1)-2, stride
),
394 get_vert(vertex_buffer
, i
-(i
&1)-1, stride
),
395 get_vert(vertex_buffer
, i
-0, stride
) );
400 case PIPE_PRIM_TRIANGLE_FAN
:
401 if (setup
->flatshade_first
) {
402 for (i
= 2; i
< nr
; i
+= 1) {
403 setup
->triangle( setup
,
404 get_vert(vertex_buffer
, i
-0, stride
),
405 get_vert(vertex_buffer
, 0, stride
),
406 get_vert(vertex_buffer
, i
-1, stride
) );
410 for (i
= 2; i
< nr
; i
+= 1) {
411 setup
->triangle( setup
,
412 get_vert(vertex_buffer
, 0, stride
),
413 get_vert(vertex_buffer
, i
-1, stride
),
414 get_vert(vertex_buffer
, i
-0, stride
) );
419 case PIPE_PRIM_QUADS
:
420 if (setup
->flatshade_first
) {
421 for (i
= 3; i
< nr
; i
+= 4) {
422 setup
->triangle( setup
,
423 get_vert(vertex_buffer
, i
-2, stride
),
424 get_vert(vertex_buffer
, i
-1, stride
),
425 get_vert(vertex_buffer
, i
-3, stride
) );
426 setup
->triangle( setup
,
427 get_vert(vertex_buffer
, i
-1, stride
),
428 get_vert(vertex_buffer
, i
-0, stride
),
429 get_vert(vertex_buffer
, i
-3, stride
) );
433 for (i
= 3; i
< nr
; i
+= 4) {
434 setup
->triangle( setup
,
435 get_vert(vertex_buffer
, i
-3, stride
),
436 get_vert(vertex_buffer
, i
-2, stride
),
437 get_vert(vertex_buffer
, i
-0, stride
) );
438 setup
->triangle( setup
,
439 get_vert(vertex_buffer
, i
-2, stride
),
440 get_vert(vertex_buffer
, i
-1, stride
),
441 get_vert(vertex_buffer
, i
-0, stride
) );
446 case PIPE_PRIM_QUAD_STRIP
:
447 if (setup
->flatshade_first
) {
448 for (i
= 3; i
< nr
; i
+= 2) {
449 setup
->triangle( setup
,
450 get_vert(vertex_buffer
, i
-0, stride
),
451 get_vert(vertex_buffer
, i
-1, stride
),
452 get_vert(vertex_buffer
, i
-3, stride
) );
453 setup
->triangle( setup
,
455 get_vert(vertex_buffer
, i
-2, stride
),
456 get_vert(vertex_buffer
, i
-0, stride
),
457 get_vert(vertex_buffer
, i
-3, stride
) );
461 for (i
= 3; i
< nr
; i
+= 2) {
462 setup
->triangle( setup
,
463 get_vert(vertex_buffer
, i
-3, stride
),
464 get_vert(vertex_buffer
, i
-2, stride
),
465 get_vert(vertex_buffer
, i
-0, stride
) );
466 setup
->triangle( setup
,
467 get_vert(vertex_buffer
, i
-1, stride
),
468 get_vert(vertex_buffer
, i
-3, stride
),
469 get_vert(vertex_buffer
, i
-0, stride
) );
474 case PIPE_PRIM_POLYGON
:
475 /* Almost same as tri fan but the _first_ vertex specifies the flat
476 * shading color. Note that the first polygon vertex is passed as
477 * the last triangle vertex here.
478 * flatshade_first state makes no difference.
480 for (i
= 2; i
< nr
; i
+= 1) {
481 setup
->triangle( setup
,
482 get_vert(vertex_buffer
, i
-1, stride
),
483 get_vert(vertex_buffer
, i
-0, stride
),
484 get_vert(vertex_buffer
, 0, stride
) );
496 lp_setup_vbuf_destroy(struct vbuf_render
*vbr
)
498 lp_setup_destroy(setup_context(vbr
));
503 * Create the post-transform vertex handler for the given context.
506 lp_setup_init_vbuf(struct setup_context
*setup
)
508 setup
->base
.max_indices
= LP_MAX_VBUF_INDEXES
;
509 setup
->base
.max_vertex_buffer_bytes
= LP_MAX_VBUF_SIZE
;
511 setup
->base
.get_vertex_info
= lp_setup_get_vertex_info
;
512 setup
->base
.allocate_vertices
= lp_setup_allocate_vertices
;
513 setup
->base
.map_vertices
= lp_setup_map_vertices
;
514 setup
->base
.unmap_vertices
= lp_setup_unmap_vertices
;
515 setup
->base
.set_primitive
= lp_setup_set_primitive
;
516 setup
->base
.draw
= lp_setup_draw
;
517 setup
->base
.draw_arrays
= lp_setup_draw_arrays
;
518 setup
->base
.release_vertices
= lp_setup_release_vertices
;
519 setup
->base
.destroy
= lp_setup_vbuf_destroy
;