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_vbuf.h"
41 #include "draw/draw_vertex.h"
42 #include "util/u_memory.h"
45 #define LP_MAX_VBUF_INDEXES 1024
46 #define LP_MAX_VBUF_SIZE 4096
51 static struct lp_setup_context
*
52 lp_setup_context(struct vbuf_render
*vbr
)
54 return (struct lp_setup_context
*) vbr
;
59 static const struct vertex_info
*
60 lp_setup_get_vertex_info(struct vbuf_render
*vbr
)
62 struct lp_setup_context
*setup
= lp_setup_context(vbr
);
64 /* Vertex size/info depends on the latest state.
65 * The draw module may have issued additional state-change commands.
67 lp_setup_update_state(setup
);
69 return setup
->vertex_info
;
74 lp_setup_allocate_vertices(struct vbuf_render
*vbr
,
75 ushort vertex_size
, ushort nr_vertices
)
77 struct lp_setup_context
*setup
= lp_setup_context(vbr
);
78 unsigned size
= vertex_size
* nr_vertices
;
80 if (setup
->vertex_buffer_size
< size
) {
81 align_free(setup
->vertex_buffer
);
82 setup
->vertex_buffer
= align_malloc(size
, 16);
83 setup
->vertex_buffer_size
= size
;
86 setup
->vertex_size
= vertex_size
;
87 setup
->nr_vertices
= nr_vertices
;
89 return setup
->vertex_buffer
!= NULL
;
93 lp_setup_release_vertices(struct vbuf_render
*vbr
)
95 /* keep the old allocation for next time */
99 lp_setup_map_vertices(struct vbuf_render
*vbr
)
101 struct lp_setup_context
*setup
= lp_setup_context(vbr
);
102 return setup
->vertex_buffer
;
106 lp_setup_unmap_vertices(struct vbuf_render
*vbr
,
110 struct lp_setup_context
*setup
= lp_setup_context(vbr
);
111 assert( setup
->vertex_buffer_size
>= (max_index
+1) * setup
->vertex_size
);
117 lp_setup_set_primitive(struct vbuf_render
*vbr
, unsigned prim
)
119 lp_setup_context(vbr
)->prim
= prim
;
123 typedef const float (*const_float4_ptr
)[4];
125 static INLINE const_float4_ptr
get_vert( const void *vertex_buffer
,
129 return (const_float4_ptr
)((char *)vertex_buffer
+ index
* stride
);
133 * draw elements / indexed primitives
136 lp_setup_draw_elements(struct vbuf_render
*vbr
, const ushort
*indices
, uint nr
)
138 struct lp_setup_context
*setup
= lp_setup_context(vbr
);
139 const unsigned stride
= setup
->vertex_info
->size
* sizeof(float);
140 const void *vertex_buffer
= setup
->vertex_buffer
;
141 const boolean flatshade_first
= setup
->flatshade_first
;
144 lp_setup_update_state(setup
);
146 switch (setup
->prim
) {
147 case PIPE_PRIM_POINTS
:
148 for (i
= 0; i
< nr
; i
++) {
150 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
154 case PIPE_PRIM_LINES
:
155 for (i
= 1; i
< nr
; i
+= 2) {
157 get_vert(vertex_buffer
, indices
[i
-1], stride
),
158 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
162 case PIPE_PRIM_LINE_STRIP
:
163 for (i
= 1; i
< nr
; i
++) {
165 get_vert(vertex_buffer
, indices
[i
-1], stride
),
166 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
170 case PIPE_PRIM_LINE_LOOP
:
171 for (i
= 1; i
< nr
; i
++) {
173 get_vert(vertex_buffer
, indices
[i
-1], stride
),
174 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
178 get_vert(vertex_buffer
, indices
[nr
-1], stride
),
179 get_vert(vertex_buffer
, indices
[0], stride
) );
183 case PIPE_PRIM_TRIANGLES
:
184 for (i
= 2; i
< nr
; i
+= 3) {
185 setup
->triangle( setup
,
186 get_vert(vertex_buffer
, indices
[i
-2], stride
),
187 get_vert(vertex_buffer
, indices
[i
-1], stride
),
188 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
192 case PIPE_PRIM_TRIANGLE_STRIP
:
193 if (flatshade_first
) {
194 for (i
= 2; i
< nr
; i
+= 1) {
195 /* emit first triangle vertex as first triangle vertex */
196 setup
->triangle( setup
,
197 get_vert(vertex_buffer
, indices
[i
-2], stride
),
198 get_vert(vertex_buffer
, indices
[i
+(i
&1)-1], stride
),
199 get_vert(vertex_buffer
, indices
[i
-(i
&1)], stride
) );
204 for (i
= 2; i
< nr
; i
+= 1) {
205 /* emit last triangle vertex as last triangle vertex */
206 setup
->triangle( setup
,
207 get_vert(vertex_buffer
, indices
[i
+(i
&1)-2], stride
),
208 get_vert(vertex_buffer
, indices
[i
-(i
&1)-1], stride
),
209 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
214 case PIPE_PRIM_TRIANGLE_FAN
:
215 if (flatshade_first
) {
216 for (i
= 2; i
< nr
; i
+= 1) {
217 /* emit first non-spoke vertex as first vertex */
218 setup
->triangle( setup
,
219 get_vert(vertex_buffer
, indices
[i
-1], stride
),
220 get_vert(vertex_buffer
, indices
[i
-0], stride
),
221 get_vert(vertex_buffer
, indices
[0], stride
) );
225 for (i
= 2; i
< nr
; i
+= 1) {
226 /* emit last non-spoke vertex as last vertex */
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 /* GL quads don't follow provoking vertex convention */
237 if (flatshade_first
) {
238 /* emit last quad vertex as first triangle vertex */
239 for (i
= 3; i
< nr
; i
+= 4) {
240 setup
->triangle( setup
,
241 get_vert(vertex_buffer
, indices
[i
-0], stride
),
242 get_vert(vertex_buffer
, indices
[i
-3], stride
),
243 get_vert(vertex_buffer
, indices
[i
-2], stride
) );
245 setup
->triangle( setup
,
246 get_vert(vertex_buffer
, indices
[i
-0], stride
),
247 get_vert(vertex_buffer
, indices
[i
-2], stride
),
248 get_vert(vertex_buffer
, indices
[i
-1], stride
) );
252 /* emit last quad vertex as last triangle vertex */
253 for (i
= 3; i
< nr
; i
+= 4) {
254 setup
->triangle( setup
,
255 get_vert(vertex_buffer
, indices
[i
-3], stride
),
256 get_vert(vertex_buffer
, indices
[i
-2], stride
),
257 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
259 setup
->triangle( setup
,
260 get_vert(vertex_buffer
, indices
[i
-2], stride
),
261 get_vert(vertex_buffer
, indices
[i
-1], stride
),
262 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
267 case PIPE_PRIM_QUAD_STRIP
:
268 /* GL quad strips don't follow provoking vertex convention */
269 if (flatshade_first
) {
270 /* emit last quad vertex as first triangle vertex */
271 for (i
= 3; i
< nr
; i
+= 2) {
272 setup
->triangle( setup
,
273 get_vert(vertex_buffer
, indices
[i
-0], stride
),
274 get_vert(vertex_buffer
, indices
[i
-3], stride
),
275 get_vert(vertex_buffer
, indices
[i
-2], stride
) );
276 setup
->triangle( setup
,
277 get_vert(vertex_buffer
, indices
[i
-0], stride
),
278 get_vert(vertex_buffer
, indices
[i
-1], stride
),
279 get_vert(vertex_buffer
, indices
[i
-3], stride
) );
283 /* emit last quad vertex as last triangle vertex */
284 for (i
= 3; i
< nr
; i
+= 2) {
285 setup
->triangle( setup
,
286 get_vert(vertex_buffer
, indices
[i
-3], stride
),
287 get_vert(vertex_buffer
, indices
[i
-2], stride
),
288 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
289 setup
->triangle( setup
,
290 get_vert(vertex_buffer
, indices
[i
-1], stride
),
291 get_vert(vertex_buffer
, indices
[i
-3], stride
),
292 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
297 case PIPE_PRIM_POLYGON
:
298 /* Almost same as tri fan but the _first_ vertex specifies the flat
301 if (flatshade_first
) {
302 /* emit first polygon vertex as first triangle vertex */
303 for (i
= 2; i
< nr
; i
+= 1) {
304 setup
->triangle( setup
,
305 get_vert(vertex_buffer
, indices
[0], stride
),
306 get_vert(vertex_buffer
, indices
[i
-1], stride
),
307 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
311 /* emit first polygon vertex as last triangle vertex */
312 for (i
= 2; i
< nr
; i
+= 1) {
313 setup
->triangle( setup
,
314 get_vert(vertex_buffer
, indices
[i
-1], stride
),
315 get_vert(vertex_buffer
, indices
[i
-0], stride
),
316 get_vert(vertex_buffer
, indices
[0], stride
) );
328 * This function is hit when the draw module is working in pass-through mode.
329 * It's up to us to convert the vertex array into point/line/tri prims.
332 lp_setup_draw_arrays(struct vbuf_render
*vbr
, uint start
, uint nr
)
334 struct lp_setup_context
*setup
= lp_setup_context(vbr
);
335 const unsigned stride
= setup
->vertex_info
->size
* sizeof(float);
336 const void *vertex_buffer
=
337 (void *) get_vert(setup
->vertex_buffer
, start
, stride
);
338 const boolean flatshade_first
= setup
->flatshade_first
;
341 lp_setup_update_state(setup
);
343 switch (setup
->prim
) {
344 case PIPE_PRIM_POINTS
:
345 for (i
= 0; i
< nr
; i
++) {
347 get_vert(vertex_buffer
, i
-0, stride
) );
351 case PIPE_PRIM_LINES
:
352 for (i
= 1; i
< nr
; i
+= 2) {
354 get_vert(vertex_buffer
, i
-1, stride
),
355 get_vert(vertex_buffer
, i
-0, stride
) );
359 case PIPE_PRIM_LINE_STRIP
:
360 for (i
= 1; i
< nr
; i
++) {
362 get_vert(vertex_buffer
, i
-1, stride
),
363 get_vert(vertex_buffer
, i
-0, stride
) );
367 case PIPE_PRIM_LINE_LOOP
:
368 for (i
= 1; i
< nr
; i
++) {
370 get_vert(vertex_buffer
, i
-1, stride
),
371 get_vert(vertex_buffer
, i
-0, stride
) );
375 get_vert(vertex_buffer
, nr
-1, stride
),
376 get_vert(vertex_buffer
, 0, stride
) );
380 case PIPE_PRIM_TRIANGLES
:
381 for (i
= 2; i
< nr
; i
+= 3) {
382 setup
->triangle( setup
,
383 get_vert(vertex_buffer
, i
-2, stride
),
384 get_vert(vertex_buffer
, i
-1, stride
),
385 get_vert(vertex_buffer
, i
-0, stride
) );
389 case PIPE_PRIM_TRIANGLE_STRIP
:
390 if (flatshade_first
) {
391 for (i
= 2; i
< nr
; i
++) {
392 /* emit first triangle vertex as first triangle vertex */
393 setup
->triangle( setup
,
394 get_vert(vertex_buffer
, i
-2, stride
),
395 get_vert(vertex_buffer
, i
+(i
&1)-1, stride
),
396 get_vert(vertex_buffer
, i
-(i
&1), stride
) );
400 for (i
= 2; i
< nr
; i
++) {
401 /* emit last triangle vertex as last triangle vertex */
402 setup
->triangle( setup
,
403 get_vert(vertex_buffer
, i
+(i
&1)-2, stride
),
404 get_vert(vertex_buffer
, i
-(i
&1)-1, stride
),
405 get_vert(vertex_buffer
, i
-0, stride
) );
410 case PIPE_PRIM_TRIANGLE_FAN
:
411 if (flatshade_first
) {
412 for (i
= 2; i
< nr
; i
+= 1) {
413 /* emit first non-spoke vertex as first vertex */
414 setup
->triangle( setup
,
415 get_vert(vertex_buffer
, i
-1, stride
),
416 get_vert(vertex_buffer
, i
-0, stride
),
417 get_vert(vertex_buffer
, 0, stride
) );
421 for (i
= 2; i
< nr
; i
+= 1) {
422 /* emit last non-spoke vertex as last vertex */
423 setup
->triangle( setup
,
424 get_vert(vertex_buffer
, 0, stride
),
425 get_vert(vertex_buffer
, i
-1, stride
),
426 get_vert(vertex_buffer
, i
-0, stride
) );
431 case PIPE_PRIM_QUADS
:
432 /* GL quads don't follow provoking vertex convention */
433 if (flatshade_first
) {
434 /* emit last quad vertex as first triangle vertex */
435 for (i
= 3; i
< nr
; i
+= 4) {
436 setup
->triangle( setup
,
437 get_vert(vertex_buffer
, i
-0, stride
),
438 get_vert(vertex_buffer
, i
-3, stride
),
439 get_vert(vertex_buffer
, i
-2, stride
) );
440 setup
->triangle( setup
,
441 get_vert(vertex_buffer
, i
-0, stride
),
442 get_vert(vertex_buffer
, i
-2, stride
),
443 get_vert(vertex_buffer
, i
-1, stride
) );
447 /* emit last quad vertex as last triangle vertex */
448 for (i
= 3; i
< nr
; i
+= 4) {
449 setup
->triangle( setup
,
450 get_vert(vertex_buffer
, i
-3, stride
),
451 get_vert(vertex_buffer
, i
-2, stride
),
452 get_vert(vertex_buffer
, i
-0, stride
) );
453 setup
->triangle( setup
,
454 get_vert(vertex_buffer
, i
-2, stride
),
455 get_vert(vertex_buffer
, i
-1, stride
),
456 get_vert(vertex_buffer
, i
-0, stride
) );
461 case PIPE_PRIM_QUAD_STRIP
:
462 /* GL quad strips don't follow provoking vertex convention */
463 if (flatshade_first
) {
464 /* emit last quad vertex as first triangle vertex */
465 for (i
= 3; i
< nr
; i
+= 2) {
466 setup
->triangle( setup
,
467 get_vert(vertex_buffer
, i
-0, stride
),
468 get_vert(vertex_buffer
, i
-3, stride
),
469 get_vert(vertex_buffer
, i
-2, stride
) );
470 setup
->triangle( setup
,
471 get_vert(vertex_buffer
, i
-0, stride
),
472 get_vert(vertex_buffer
, i
-1, stride
),
473 get_vert(vertex_buffer
, i
-3, stride
) );
477 /* emit last quad vertex as last triangle vertex */
478 for (i
= 3; i
< nr
; i
+= 2) {
479 setup
->triangle( setup
,
480 get_vert(vertex_buffer
, i
-3, stride
),
481 get_vert(vertex_buffer
, i
-2, stride
),
482 get_vert(vertex_buffer
, i
-0, stride
) );
483 setup
->triangle( setup
,
484 get_vert(vertex_buffer
, i
-1, stride
),
485 get_vert(vertex_buffer
, i
-3, stride
),
486 get_vert(vertex_buffer
, i
-0, stride
) );
491 case PIPE_PRIM_POLYGON
:
492 /* Almost same as tri fan but the _first_ vertex specifies the flat
495 if (flatshade_first
) {
496 /* emit first polygon vertex as first triangle vertex */
497 for (i
= 2; i
< nr
; i
+= 1) {
498 setup
->triangle( setup
,
499 get_vert(vertex_buffer
, 0, stride
),
500 get_vert(vertex_buffer
, i
-1, stride
),
501 get_vert(vertex_buffer
, i
-0, stride
) );
505 /* emit first polygon vertex as last triangle vertex */
506 for (i
= 2; i
< nr
; i
+= 1) {
507 setup
->triangle( setup
,
508 get_vert(vertex_buffer
, i
-1, stride
),
509 get_vert(vertex_buffer
, i
-0, stride
),
510 get_vert(vertex_buffer
, 0, stride
) );
523 lp_setup_vbuf_destroy(struct vbuf_render
*vbr
)
525 struct lp_setup_context
*setup
= lp_setup_context(vbr
);
526 if (setup
->vertex_buffer
) {
527 align_free(setup
->vertex_buffer
);
528 setup
->vertex_buffer
= NULL
;
530 lp_setup_destroy(setup
);
535 * Create the post-transform vertex handler for the given context.
538 lp_setup_init_vbuf(struct lp_setup_context
*setup
)
540 setup
->base
.max_indices
= LP_MAX_VBUF_INDEXES
;
541 setup
->base
.max_vertex_buffer_bytes
= LP_MAX_VBUF_SIZE
;
543 setup
->base
.get_vertex_info
= lp_setup_get_vertex_info
;
544 setup
->base
.allocate_vertices
= lp_setup_allocate_vertices
;
545 setup
->base
.map_vertices
= lp_setup_map_vertices
;
546 setup
->base
.unmap_vertices
= lp_setup_unmap_vertices
;
547 setup
->base
.set_primitive
= lp_setup_set_primitive
;
548 setup
->base
.draw_elements
= lp_setup_draw_elements
;
549 setup
->base
.draw_arrays
= lp_setup_draw_arrays
;
550 setup
->base
.release_vertices
= lp_setup_release_vertices
;
551 setup
->base
.destroy
= lp_setup_vbuf_destroy
;