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
);
63 return setup
->vertex_info
;
68 lp_setup_allocate_vertices(struct vbuf_render
*vbr
,
69 ushort vertex_size
, ushort nr_vertices
)
71 struct lp_setup_context
*setup
= lp_setup_context(vbr
);
72 unsigned size
= vertex_size
* nr_vertices
;
74 if (setup
->vertex_buffer_size
< size
) {
75 align_free(setup
->vertex_buffer
);
76 setup
->vertex_buffer
= align_malloc(size
, 16);
77 setup
->vertex_buffer_size
= size
;
80 setup
->vertex_size
= vertex_size
;
81 setup
->nr_vertices
= nr_vertices
;
83 return setup
->vertex_buffer
!= NULL
;
87 lp_setup_release_vertices(struct vbuf_render
*vbr
)
89 /* keep the old allocation for next time */
93 lp_setup_map_vertices(struct vbuf_render
*vbr
)
95 struct lp_setup_context
*setup
= lp_setup_context(vbr
);
96 return setup
->vertex_buffer
;
100 lp_setup_unmap_vertices(struct vbuf_render
*vbr
,
104 struct lp_setup_context
*setup
= lp_setup_context(vbr
);
105 assert( setup
->vertex_buffer_size
>= (max_index
+1) * setup
->vertex_size
);
111 lp_setup_set_primitive(struct vbuf_render
*vbr
, unsigned prim
)
113 lp_setup_context(vbr
)->prim
= prim
;
117 typedef const float (*const_float4_ptr
)[4];
119 static INLINE const_float4_ptr
get_vert( const void *vertex_buffer
,
123 return (const_float4_ptr
)((char *)vertex_buffer
+ index
* stride
);
127 * draw elements / indexed primitives
130 lp_setup_draw_elements(struct vbuf_render
*vbr
, const ushort
*indices
, uint nr
)
132 struct lp_setup_context
*setup
= lp_setup_context(vbr
);
133 const unsigned stride
= setup
->vertex_info
->size
* sizeof(float);
134 const void *vertex_buffer
= setup
->vertex_buffer
;
135 const boolean flatshade_first
= setup
->flatshade_first
;
138 lp_setup_update_state(setup
);
140 switch (setup
->prim
) {
141 case PIPE_PRIM_POINTS
:
142 for (i
= 0; i
< nr
; i
++) {
144 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
148 case PIPE_PRIM_LINES
:
149 for (i
= 1; i
< nr
; i
+= 2) {
151 get_vert(vertex_buffer
, indices
[i
-1], stride
),
152 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
156 case PIPE_PRIM_LINE_STRIP
:
157 for (i
= 1; i
< nr
; i
++) {
159 get_vert(vertex_buffer
, indices
[i
-1], stride
),
160 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
164 case PIPE_PRIM_LINE_LOOP
:
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 get_vert(vertex_buffer
, indices
[nr
-1], stride
),
173 get_vert(vertex_buffer
, indices
[0], stride
) );
177 case PIPE_PRIM_TRIANGLES
:
178 for (i
= 2; i
< nr
; i
+= 3) {
179 setup
->triangle( setup
,
180 get_vert(vertex_buffer
, indices
[i
-2], stride
),
181 get_vert(vertex_buffer
, indices
[i
-1], stride
),
182 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
186 case PIPE_PRIM_TRIANGLE_STRIP
:
187 if (flatshade_first
) {
188 for (i
= 2; i
< nr
; i
+= 1) {
189 /* emit first triangle vertex as first triangle vertex */
190 setup
->triangle( setup
,
191 get_vert(vertex_buffer
, indices
[i
-2], stride
),
192 get_vert(vertex_buffer
, indices
[i
+(i
&1)-1], stride
),
193 get_vert(vertex_buffer
, indices
[i
-(i
&1)], stride
) );
198 for (i
= 2; i
< nr
; i
+= 1) {
199 /* emit last triangle vertex as last triangle vertex */
200 setup
->triangle( setup
,
201 get_vert(vertex_buffer
, indices
[i
+(i
&1)-2], stride
),
202 get_vert(vertex_buffer
, indices
[i
-(i
&1)-1], stride
),
203 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
208 case PIPE_PRIM_TRIANGLE_FAN
:
209 if (flatshade_first
) {
210 for (i
= 2; i
< nr
; i
+= 1) {
211 /* emit first non-spoke vertex as first vertex */
212 setup
->triangle( setup
,
213 get_vert(vertex_buffer
, indices
[i
-1], stride
),
214 get_vert(vertex_buffer
, indices
[i
-0], stride
),
215 get_vert(vertex_buffer
, indices
[0], stride
) );
219 for (i
= 2; i
< nr
; i
+= 1) {
220 /* emit last non-spoke vertex as last vertex */
221 setup
->triangle( setup
,
222 get_vert(vertex_buffer
, indices
[0], stride
),
223 get_vert(vertex_buffer
, indices
[i
-1], stride
),
224 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
229 case PIPE_PRIM_QUADS
:
230 /* GL quads don't follow provoking vertex convention */
231 if (flatshade_first
) {
232 /* emit last quad vertex as first triangle vertex */
233 for (i
= 3; i
< nr
; i
+= 4) {
234 setup
->triangle( setup
,
235 get_vert(vertex_buffer
, indices
[i
-0], stride
),
236 get_vert(vertex_buffer
, indices
[i
-3], stride
),
237 get_vert(vertex_buffer
, indices
[i
-2], stride
) );
239 setup
->triangle( setup
,
240 get_vert(vertex_buffer
, indices
[i
-0], stride
),
241 get_vert(vertex_buffer
, indices
[i
-2], stride
),
242 get_vert(vertex_buffer
, indices
[i
-1], stride
) );
246 /* emit last quad vertex as last triangle vertex */
247 for (i
= 3; i
< nr
; i
+= 4) {
248 setup
->triangle( setup
,
249 get_vert(vertex_buffer
, indices
[i
-3], stride
),
250 get_vert(vertex_buffer
, indices
[i
-2], stride
),
251 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
253 setup
->triangle( setup
,
254 get_vert(vertex_buffer
, indices
[i
-2], stride
),
255 get_vert(vertex_buffer
, indices
[i
-1], stride
),
256 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
261 case PIPE_PRIM_QUAD_STRIP
:
262 /* GL quad strips don't follow provoking vertex convention */
263 if (flatshade_first
) {
264 /* emit last quad vertex as first triangle vertex */
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
-3], stride
),
269 get_vert(vertex_buffer
, indices
[i
-2], stride
) );
270 setup
->triangle( setup
,
271 get_vert(vertex_buffer
, indices
[i
-0], stride
),
272 get_vert(vertex_buffer
, indices
[i
-1], stride
),
273 get_vert(vertex_buffer
, indices
[i
-3], stride
) );
277 /* emit last quad vertex as last triangle vertex */
278 for (i
= 3; i
< nr
; i
+= 2) {
279 setup
->triangle( setup
,
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
) );
283 setup
->triangle( setup
,
284 get_vert(vertex_buffer
, indices
[i
-1], stride
),
285 get_vert(vertex_buffer
, indices
[i
-3], stride
),
286 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
291 case PIPE_PRIM_POLYGON
:
292 /* Almost same as tri fan but the _first_ vertex specifies the flat
295 if (flatshade_first
) {
296 /* emit first polygon vertex as first triangle vertex */
297 for (i
= 2; i
< nr
; i
+= 1) {
298 setup
->triangle( setup
,
299 get_vert(vertex_buffer
, indices
[0], stride
),
300 get_vert(vertex_buffer
, indices
[i
-1], stride
),
301 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
305 /* emit first polygon vertex as last triangle vertex */
306 for (i
= 2; i
< nr
; i
+= 1) {
307 setup
->triangle( setup
,
308 get_vert(vertex_buffer
, indices
[i
-1], stride
),
309 get_vert(vertex_buffer
, indices
[i
-0], stride
),
310 get_vert(vertex_buffer
, indices
[0], stride
) );
322 * This function is hit when the draw module is working in pass-through mode.
323 * It's up to us to convert the vertex array into point/line/tri prims.
326 lp_setup_draw_arrays(struct vbuf_render
*vbr
, uint start
, uint nr
)
328 struct lp_setup_context
*setup
= lp_setup_context(vbr
);
329 const unsigned stride
= setup
->vertex_info
->size
* sizeof(float);
330 const void *vertex_buffer
=
331 (void *) get_vert(setup
->vertex_buffer
, start
, stride
);
332 const boolean flatshade_first
= setup
->flatshade_first
;
335 lp_setup_update_state(setup
);
337 switch (setup
->prim
) {
338 case PIPE_PRIM_POINTS
:
339 for (i
= 0; i
< nr
; i
++) {
341 get_vert(vertex_buffer
, i
-0, stride
) );
345 case PIPE_PRIM_LINES
:
346 for (i
= 1; i
< nr
; i
+= 2) {
348 get_vert(vertex_buffer
, i
-1, stride
),
349 get_vert(vertex_buffer
, i
-0, stride
) );
353 case PIPE_PRIM_LINE_STRIP
:
354 for (i
= 1; i
< nr
; i
++) {
356 get_vert(vertex_buffer
, i
-1, stride
),
357 get_vert(vertex_buffer
, i
-0, stride
) );
361 case PIPE_PRIM_LINE_LOOP
:
362 for (i
= 1; i
< nr
; i
++) {
364 get_vert(vertex_buffer
, i
-1, stride
),
365 get_vert(vertex_buffer
, i
-0, stride
) );
369 get_vert(vertex_buffer
, nr
-1, stride
),
370 get_vert(vertex_buffer
, 0, stride
) );
374 case PIPE_PRIM_TRIANGLES
:
375 for (i
= 2; i
< nr
; i
+= 3) {
376 setup
->triangle( setup
,
377 get_vert(vertex_buffer
, i
-2, stride
),
378 get_vert(vertex_buffer
, i
-1, stride
),
379 get_vert(vertex_buffer
, i
-0, stride
) );
383 case PIPE_PRIM_TRIANGLE_STRIP
:
384 if (flatshade_first
) {
385 for (i
= 2; i
< nr
; i
++) {
386 /* emit first triangle vertex as first triangle vertex */
387 setup
->triangle( setup
,
388 get_vert(vertex_buffer
, i
-2, stride
),
389 get_vert(vertex_buffer
, i
+(i
&1)-1, stride
),
390 get_vert(vertex_buffer
, i
-(i
&1), stride
) );
394 for (i
= 2; i
< nr
; i
++) {
395 /* emit last triangle vertex as last triangle vertex */
396 setup
->triangle( setup
,
397 get_vert(vertex_buffer
, i
+(i
&1)-2, stride
),
398 get_vert(vertex_buffer
, i
-(i
&1)-1, stride
),
399 get_vert(vertex_buffer
, i
-0, stride
) );
404 case PIPE_PRIM_TRIANGLE_FAN
:
405 if (flatshade_first
) {
406 for (i
= 2; i
< nr
; i
+= 1) {
407 /* emit first non-spoke vertex as first vertex */
408 setup
->triangle( setup
,
409 get_vert(vertex_buffer
, i
-1, stride
),
410 get_vert(vertex_buffer
, i
-0, stride
),
411 get_vert(vertex_buffer
, 0, stride
) );
415 for (i
= 2; i
< nr
; i
+= 1) {
416 /* emit last non-spoke vertex as last vertex */
417 setup
->triangle( setup
,
418 get_vert(vertex_buffer
, 0, stride
),
419 get_vert(vertex_buffer
, i
-1, stride
),
420 get_vert(vertex_buffer
, i
-0, stride
) );
425 case PIPE_PRIM_QUADS
:
426 /* GL quads don't follow provoking vertex convention */
427 if (flatshade_first
) {
428 /* emit last quad vertex as first triangle vertex */
429 for (i
= 3; i
< nr
; i
+= 4) {
430 setup
->triangle( setup
,
431 get_vert(vertex_buffer
, i
-0, stride
),
432 get_vert(vertex_buffer
, i
-3, stride
),
433 get_vert(vertex_buffer
, i
-2, stride
) );
434 setup
->triangle( setup
,
435 get_vert(vertex_buffer
, i
-0, stride
),
436 get_vert(vertex_buffer
, i
-2, stride
),
437 get_vert(vertex_buffer
, i
-1, stride
) );
441 /* emit last quad vertex as last triangle vertex */
442 for (i
= 3; i
< nr
; i
+= 4) {
443 setup
->triangle( setup
,
444 get_vert(vertex_buffer
, i
-3, stride
),
445 get_vert(vertex_buffer
, i
-2, stride
),
446 get_vert(vertex_buffer
, i
-0, stride
) );
447 setup
->triangle( setup
,
448 get_vert(vertex_buffer
, i
-2, stride
),
449 get_vert(vertex_buffer
, i
-1, stride
),
450 get_vert(vertex_buffer
, i
-0, stride
) );
455 case PIPE_PRIM_QUAD_STRIP
:
456 /* GL quad strips don't follow provoking vertex convention */
457 if (flatshade_first
) {
458 /* emit last quad vertex as first triangle vertex */
459 for (i
= 3; i
< nr
; i
+= 2) {
460 setup
->triangle( setup
,
461 get_vert(vertex_buffer
, i
-0, stride
),
462 get_vert(vertex_buffer
, i
-3, stride
),
463 get_vert(vertex_buffer
, i
-2, stride
) );
464 setup
->triangle( setup
,
465 get_vert(vertex_buffer
, i
-0, stride
),
466 get_vert(vertex_buffer
, i
-1, stride
),
467 get_vert(vertex_buffer
, i
-3, stride
) );
471 /* emit last quad vertex as last triangle vertex */
472 for (i
= 3; i
< nr
; i
+= 2) {
473 setup
->triangle( setup
,
474 get_vert(vertex_buffer
, i
-3, stride
),
475 get_vert(vertex_buffer
, i
-2, stride
),
476 get_vert(vertex_buffer
, i
-0, stride
) );
477 setup
->triangle( setup
,
478 get_vert(vertex_buffer
, i
-1, stride
),
479 get_vert(vertex_buffer
, i
-3, stride
),
480 get_vert(vertex_buffer
, i
-0, stride
) );
485 case PIPE_PRIM_POLYGON
:
486 /* Almost same as tri fan but the _first_ vertex specifies the flat
489 if (flatshade_first
) {
490 /* emit first polygon vertex as first triangle vertex */
491 for (i
= 2; i
< nr
; i
+= 1) {
492 setup
->triangle( setup
,
493 get_vert(vertex_buffer
, 0, stride
),
494 get_vert(vertex_buffer
, i
-1, stride
),
495 get_vert(vertex_buffer
, i
-0, stride
) );
499 /* emit first polygon vertex as last triangle vertex */
500 for (i
= 2; i
< nr
; i
+= 1) {
501 setup
->triangle( setup
,
502 get_vert(vertex_buffer
, i
-1, stride
),
503 get_vert(vertex_buffer
, i
-0, stride
),
504 get_vert(vertex_buffer
, 0, stride
) );
517 lp_setup_vbuf_destroy(struct vbuf_render
*vbr
)
519 struct lp_setup_context
*setup
= lp_setup_context(vbr
);
520 if (setup
->vertex_buffer
) {
521 align_free(setup
->vertex_buffer
);
522 setup
->vertex_buffer
= NULL
;
524 lp_setup_destroy(setup
);
529 * Create the post-transform vertex handler for the given context.
532 lp_setup_init_vbuf(struct lp_setup_context
*setup
)
534 setup
->base
.max_indices
= LP_MAX_VBUF_INDEXES
;
535 setup
->base
.max_vertex_buffer_bytes
= LP_MAX_VBUF_SIZE
;
537 setup
->base
.get_vertex_info
= lp_setup_get_vertex_info
;
538 setup
->base
.allocate_vertices
= lp_setup_allocate_vertices
;
539 setup
->base
.map_vertices
= lp_setup_map_vertices
;
540 setup
->base
.unmap_vertices
= lp_setup_unmap_vertices
;
541 setup
->base
.set_primitive
= lp_setup_set_primitive
;
542 setup
->base
.draw_elements
= lp_setup_draw_elements
;
543 setup
->base
.draw_arrays
= lp_setup_draw_arrays
;
544 setup
->base
.release_vertices
= lp_setup_release_vertices
;
545 setup
->base
.destroy
= lp_setup_vbuf_destroy
;