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
, FALSE
);
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
;
122 typedef const float (*const_float4_ptr
)[4];
124 static INLINE const_float4_ptr
get_vert( const void *vertex_buffer
,
128 return (const_float4_ptr
)((char *)vertex_buffer
+ index
* stride
);
132 * draw elements / indexed primitives
135 lp_setup_draw_elements(struct vbuf_render
*vbr
, const ushort
*indices
, uint nr
)
137 struct lp_setup_context
*setup
= lp_setup_context(vbr
);
138 const unsigned stride
= setup
->vertex_info
->size
* sizeof(float);
139 const void *vertex_buffer
= setup
->vertex_buffer
;
140 const boolean flatshade_first
= setup
->flatshade_first
;
143 assert(setup
->setup
.variant
);
145 if (!lp_setup_update_state(setup
, TRUE
))
148 switch (setup
->prim
) {
149 case PIPE_PRIM_POINTS
:
150 for (i
= 0; i
< nr
; i
++) {
152 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
156 case PIPE_PRIM_LINES
:
157 for (i
= 1; i
< nr
; i
+= 2) {
159 get_vert(vertex_buffer
, indices
[i
-1], stride
),
160 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
164 case PIPE_PRIM_LINE_STRIP
:
165 for (i
= 1; i
< nr
; i
++) {
167 get_vert(vertex_buffer
, indices
[i
-1], stride
),
168 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
172 case PIPE_PRIM_LINE_LOOP
:
173 for (i
= 1; i
< nr
; i
++) {
175 get_vert(vertex_buffer
, indices
[i
-1], stride
),
176 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
180 get_vert(vertex_buffer
, indices
[nr
-1], stride
),
181 get_vert(vertex_buffer
, indices
[0], stride
) );
185 case PIPE_PRIM_TRIANGLES
:
186 for (i
= 2; i
< nr
; i
+= 3) {
187 setup
->triangle( setup
,
188 get_vert(vertex_buffer
, indices
[i
-2], stride
),
189 get_vert(vertex_buffer
, indices
[i
-1], stride
),
190 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
194 case PIPE_PRIM_TRIANGLE_STRIP
:
195 if (flatshade_first
) {
196 for (i
= 2; i
< nr
; i
+= 1) {
197 /* emit first triangle vertex as first triangle vertex */
198 setup
->triangle( setup
,
199 get_vert(vertex_buffer
, indices
[i
-2], stride
),
200 get_vert(vertex_buffer
, indices
[i
+(i
&1)-1], stride
),
201 get_vert(vertex_buffer
, indices
[i
-(i
&1)], stride
) );
206 for (i
= 2; i
< nr
; i
+= 1) {
207 /* emit last triangle vertex as last triangle vertex */
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 (flatshade_first
) {
218 for (i
= 2; i
< nr
; i
+= 1) {
219 /* emit first non-spoke vertex as first vertex */
220 setup
->triangle( setup
,
221 get_vert(vertex_buffer
, indices
[i
-1], stride
),
222 get_vert(vertex_buffer
, indices
[i
-0], stride
),
223 get_vert(vertex_buffer
, indices
[0], stride
) );
227 for (i
= 2; i
< nr
; i
+= 1) {
228 /* emit last non-spoke vertex as last vertex */
229 setup
->triangle( setup
,
230 get_vert(vertex_buffer
, indices
[0], stride
),
231 get_vert(vertex_buffer
, indices
[i
-1], stride
),
232 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
237 case PIPE_PRIM_QUADS
:
238 /* GL quads don't follow provoking vertex convention */
239 if (flatshade_first
) {
240 /* emit last quad vertex as first triangle vertex */
241 for (i
= 3; i
< nr
; i
+= 4) {
242 setup
->triangle( setup
,
243 get_vert(vertex_buffer
, indices
[i
-0], stride
),
244 get_vert(vertex_buffer
, indices
[i
-3], stride
),
245 get_vert(vertex_buffer
, indices
[i
-2], stride
) );
247 setup
->triangle( setup
,
248 get_vert(vertex_buffer
, indices
[i
-0], stride
),
249 get_vert(vertex_buffer
, indices
[i
-2], stride
),
250 get_vert(vertex_buffer
, indices
[i
-1], stride
) );
254 /* emit last quad vertex as last triangle vertex */
255 for (i
= 3; i
< nr
; i
+= 4) {
256 setup
->triangle( setup
,
257 get_vert(vertex_buffer
, indices
[i
-3], stride
),
258 get_vert(vertex_buffer
, indices
[i
-2], stride
),
259 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
261 setup
->triangle( setup
,
262 get_vert(vertex_buffer
, indices
[i
-2], stride
),
263 get_vert(vertex_buffer
, indices
[i
-1], stride
),
264 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
269 case PIPE_PRIM_QUAD_STRIP
:
270 /* GL quad strips don't follow provoking vertex convention */
271 if (flatshade_first
) {
272 /* emit last quad vertex as first triangle vertex */
273 for (i
= 3; i
< nr
; i
+= 2) {
274 setup
->triangle( setup
,
275 get_vert(vertex_buffer
, indices
[i
-0], stride
),
276 get_vert(vertex_buffer
, indices
[i
-3], stride
),
277 get_vert(vertex_buffer
, indices
[i
-2], stride
) );
278 setup
->triangle( setup
,
279 get_vert(vertex_buffer
, indices
[i
-0], stride
),
280 get_vert(vertex_buffer
, indices
[i
-1], stride
),
281 get_vert(vertex_buffer
, indices
[i
-3], stride
) );
285 /* emit last quad vertex as last triangle vertex */
286 for (i
= 3; i
< nr
; i
+= 2) {
287 setup
->triangle( setup
,
288 get_vert(vertex_buffer
, indices
[i
-3], stride
),
289 get_vert(vertex_buffer
, indices
[i
-2], stride
),
290 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
291 setup
->triangle( setup
,
292 get_vert(vertex_buffer
, indices
[i
-1], stride
),
293 get_vert(vertex_buffer
, indices
[i
-3], stride
),
294 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
299 case PIPE_PRIM_POLYGON
:
300 /* Almost same as tri fan but the _first_ vertex specifies the flat
303 if (flatshade_first
) {
304 /* emit first polygon vertex as first triangle vertex */
305 for (i
= 2; i
< nr
; i
+= 1) {
306 setup
->triangle( setup
,
307 get_vert(vertex_buffer
, indices
[0], stride
),
308 get_vert(vertex_buffer
, indices
[i
-1], stride
),
309 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
313 /* emit first polygon vertex as last triangle vertex */
314 for (i
= 2; i
< nr
; i
+= 1) {
315 setup
->triangle( setup
,
316 get_vert(vertex_buffer
, indices
[i
-1], stride
),
317 get_vert(vertex_buffer
, indices
[i
-0], stride
),
318 get_vert(vertex_buffer
, indices
[0], stride
) );
330 * This function is hit when the draw module is working in pass-through mode.
331 * It's up to us to convert the vertex array into point/line/tri prims.
334 lp_setup_draw_arrays(struct vbuf_render
*vbr
, uint start
, uint nr
)
336 struct lp_setup_context
*setup
= lp_setup_context(vbr
);
337 const unsigned stride
= setup
->vertex_info
->size
* sizeof(float);
338 const void *vertex_buffer
=
339 (void *) get_vert(setup
->vertex_buffer
, start
, stride
);
340 const boolean flatshade_first
= setup
->flatshade_first
;
343 if (!lp_setup_update_state(setup
, TRUE
))
346 switch (setup
->prim
) {
347 case PIPE_PRIM_POINTS
:
348 for (i
= 0; i
< nr
; i
++) {
350 get_vert(vertex_buffer
, i
-0, stride
) );
354 case PIPE_PRIM_LINES
:
355 for (i
= 1; i
< nr
; i
+= 2) {
357 get_vert(vertex_buffer
, i
-1, stride
),
358 get_vert(vertex_buffer
, i
-0, stride
) );
362 case PIPE_PRIM_LINE_STRIP
:
363 for (i
= 1; i
< nr
; i
++) {
365 get_vert(vertex_buffer
, i
-1, stride
),
366 get_vert(vertex_buffer
, i
-0, stride
) );
370 case PIPE_PRIM_LINE_LOOP
:
371 for (i
= 1; i
< nr
; i
++) {
373 get_vert(vertex_buffer
, i
-1, stride
),
374 get_vert(vertex_buffer
, i
-0, stride
) );
378 get_vert(vertex_buffer
, nr
-1, stride
),
379 get_vert(vertex_buffer
, 0, stride
) );
383 case PIPE_PRIM_TRIANGLES
:
384 for (i
= 2; i
< nr
; i
+= 3) {
385 setup
->triangle( setup
,
386 get_vert(vertex_buffer
, i
-2, stride
),
387 get_vert(vertex_buffer
, i
-1, stride
),
388 get_vert(vertex_buffer
, i
-0, stride
) );
392 case PIPE_PRIM_TRIANGLE_STRIP
:
393 if (flatshade_first
) {
394 for (i
= 2; i
< nr
; i
++) {
395 /* emit first triangle vertex as first triangle vertex */
396 setup
->triangle( setup
,
397 get_vert(vertex_buffer
, i
-2, stride
),
398 get_vert(vertex_buffer
, i
+(i
&1)-1, stride
),
399 get_vert(vertex_buffer
, i
-(i
&1), stride
) );
403 for (i
= 2; i
< nr
; i
++) {
404 /* emit last triangle vertex as last triangle vertex */
405 setup
->triangle( setup
,
406 get_vert(vertex_buffer
, i
+(i
&1)-2, stride
),
407 get_vert(vertex_buffer
, i
-(i
&1)-1, stride
),
408 get_vert(vertex_buffer
, i
-0, stride
) );
413 case PIPE_PRIM_TRIANGLE_FAN
:
414 if (flatshade_first
) {
415 for (i
= 2; i
< nr
; i
+= 1) {
416 /* emit first non-spoke vertex as first vertex */
417 setup
->triangle( setup
,
418 get_vert(vertex_buffer
, i
-1, stride
),
419 get_vert(vertex_buffer
, i
-0, stride
),
420 get_vert(vertex_buffer
, 0, stride
) );
424 for (i
= 2; i
< nr
; i
+= 1) {
425 /* emit last non-spoke vertex as last vertex */
426 setup
->triangle( setup
,
427 get_vert(vertex_buffer
, 0, stride
),
428 get_vert(vertex_buffer
, i
-1, stride
),
429 get_vert(vertex_buffer
, i
-0, stride
) );
434 case PIPE_PRIM_QUADS
:
435 /* GL quads don't follow provoking vertex convention */
436 if (flatshade_first
) {
437 /* emit last quad vertex as first triangle vertex */
438 for (i
= 3; i
< nr
; i
+= 4) {
439 setup
->triangle( setup
,
440 get_vert(vertex_buffer
, i
-0, stride
),
441 get_vert(vertex_buffer
, i
-3, stride
),
442 get_vert(vertex_buffer
, i
-2, stride
) );
443 setup
->triangle( setup
,
444 get_vert(vertex_buffer
, i
-0, stride
),
445 get_vert(vertex_buffer
, i
-2, stride
),
446 get_vert(vertex_buffer
, i
-1, stride
) );
450 /* emit last quad vertex as last triangle vertex */
451 for (i
= 3; i
< nr
; i
+= 4) {
452 setup
->triangle( setup
,
453 get_vert(vertex_buffer
, i
-3, stride
),
454 get_vert(vertex_buffer
, i
-2, stride
),
455 get_vert(vertex_buffer
, i
-0, stride
) );
456 setup
->triangle( setup
,
457 get_vert(vertex_buffer
, i
-2, stride
),
458 get_vert(vertex_buffer
, i
-1, stride
),
459 get_vert(vertex_buffer
, i
-0, stride
) );
464 case PIPE_PRIM_QUAD_STRIP
:
465 /* GL quad strips don't follow provoking vertex convention */
466 if (flatshade_first
) {
467 /* emit last quad vertex as first triangle vertex */
468 for (i
= 3; i
< nr
; i
+= 2) {
469 setup
->triangle( setup
,
470 get_vert(vertex_buffer
, i
-0, stride
),
471 get_vert(vertex_buffer
, i
-3, stride
),
472 get_vert(vertex_buffer
, i
-2, stride
) );
473 setup
->triangle( setup
,
474 get_vert(vertex_buffer
, i
-0, stride
),
475 get_vert(vertex_buffer
, i
-1, stride
),
476 get_vert(vertex_buffer
, i
-3, stride
) );
480 /* emit last quad vertex as last triangle vertex */
481 for (i
= 3; i
< nr
; i
+= 2) {
482 setup
->triangle( setup
,
483 get_vert(vertex_buffer
, i
-3, stride
),
484 get_vert(vertex_buffer
, i
-2, stride
),
485 get_vert(vertex_buffer
, i
-0, stride
) );
486 setup
->triangle( setup
,
487 get_vert(vertex_buffer
, i
-1, stride
),
488 get_vert(vertex_buffer
, i
-3, stride
),
489 get_vert(vertex_buffer
, i
-0, stride
) );
494 case PIPE_PRIM_POLYGON
:
495 /* Almost same as tri fan but the _first_ vertex specifies the flat
498 if (flatshade_first
) {
499 /* emit first polygon vertex as first triangle vertex */
500 for (i
= 2; i
< nr
; i
+= 1) {
501 setup
->triangle( setup
,
502 get_vert(vertex_buffer
, 0, stride
),
503 get_vert(vertex_buffer
, i
-1, stride
),
504 get_vert(vertex_buffer
, i
-0, stride
) );
508 /* emit first polygon vertex as last triangle vertex */
509 for (i
= 2; i
< nr
; i
+= 1) {
510 setup
->triangle( setup
,
511 get_vert(vertex_buffer
, i
-1, stride
),
512 get_vert(vertex_buffer
, i
-0, stride
),
513 get_vert(vertex_buffer
, 0, stride
) );
526 lp_setup_vbuf_destroy(struct vbuf_render
*vbr
)
528 struct lp_setup_context
*setup
= lp_setup_context(vbr
);
529 if (setup
->vertex_buffer
) {
530 align_free(setup
->vertex_buffer
);
531 setup
->vertex_buffer
= NULL
;
533 lp_setup_destroy(setup
);
538 * Create the post-transform vertex handler for the given context.
541 lp_setup_init_vbuf(struct lp_setup_context
*setup
)
543 setup
->base
.max_indices
= LP_MAX_VBUF_INDEXES
;
544 setup
->base
.max_vertex_buffer_bytes
= LP_MAX_VBUF_SIZE
;
546 setup
->base
.get_vertex_info
= lp_setup_get_vertex_info
;
547 setup
->base
.allocate_vertices
= lp_setup_allocate_vertices
;
548 setup
->base
.map_vertices
= lp_setup_map_vertices
;
549 setup
->base
.unmap_vertices
= lp_setup_unmap_vertices
;
550 setup
->base
.set_primitive
= lp_setup_set_primitive
;
551 setup
->base
.draw_elements
= lp_setup_draw_elements
;
552 setup
->base
.draw_arrays
= lp_setup_draw_arrays
;
553 setup
->base
.release_vertices
= lp_setup_release_vertices
;
554 setup
->base
.destroy
= lp_setup_vbuf_destroy
;