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 lp_setup_update_state(setup
);
67 return setup
->vertex_info
;
72 lp_setup_allocate_vertices(struct vbuf_render
*vbr
,
73 ushort vertex_size
, ushort nr_vertices
)
75 struct lp_setup_context
*setup
= lp_setup_context(vbr
);
76 unsigned size
= vertex_size
* nr_vertices
;
78 if (setup
->vertex_buffer_size
< size
) {
79 align_free(setup
->vertex_buffer
);
80 setup
->vertex_buffer
= align_malloc(size
, 16);
81 setup
->vertex_buffer_size
= size
;
84 setup
->vertex_size
= vertex_size
;
85 setup
->nr_vertices
= nr_vertices
;
87 return setup
->vertex_buffer
!= NULL
;
91 lp_setup_release_vertices(struct vbuf_render
*vbr
)
93 /* keep the old allocation for next time */
97 lp_setup_map_vertices(struct vbuf_render
*vbr
)
99 struct lp_setup_context
*setup
= lp_setup_context(vbr
);
100 return setup
->vertex_buffer
;
104 lp_setup_unmap_vertices(struct vbuf_render
*vbr
,
108 struct lp_setup_context
*setup
= lp_setup_context(vbr
);
109 assert( setup
->vertex_buffer_size
>= (max_index
+1) * setup
->vertex_size
);
115 lp_setup_set_primitive(struct vbuf_render
*vbr
, unsigned prim
)
117 lp_setup_context(vbr
)->prim
= prim
;
121 typedef const float (*const_float4_ptr
)[4];
123 static INLINE const_float4_ptr
get_vert( const void *vertex_buffer
,
127 return (const_float4_ptr
)((char *)vertex_buffer
+ index
* stride
);
131 * draw elements / indexed primitives
134 lp_setup_draw_elements(struct vbuf_render
*vbr
, const ushort
*indices
, uint nr
)
136 struct lp_setup_context
*setup
= lp_setup_context(vbr
);
137 const unsigned stride
= setup
->vertex_info
->size
* sizeof(float);
138 const void *vertex_buffer
= setup
->vertex_buffer
;
139 const boolean flatshade_first
= setup
->flatshade_first
;
142 lp_setup_update_state(setup
);
144 switch (setup
->prim
) {
145 case PIPE_PRIM_POINTS
:
146 for (i
= 0; i
< nr
; i
++) {
148 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
152 case PIPE_PRIM_LINES
:
153 for (i
= 1; i
< nr
; i
+= 2) {
155 get_vert(vertex_buffer
, indices
[i
-1], stride
),
156 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
160 case PIPE_PRIM_LINE_STRIP
:
161 for (i
= 1; i
< nr
; i
++) {
163 get_vert(vertex_buffer
, indices
[i
-1], stride
),
164 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
168 case PIPE_PRIM_LINE_LOOP
:
169 for (i
= 1; i
< nr
; i
++) {
171 get_vert(vertex_buffer
, indices
[i
-1], stride
),
172 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
176 get_vert(vertex_buffer
, indices
[nr
-1], stride
),
177 get_vert(vertex_buffer
, indices
[0], stride
) );
181 case PIPE_PRIM_TRIANGLES
:
182 for (i
= 2; i
< nr
; i
+= 3) {
183 setup
->triangle( setup
,
184 get_vert(vertex_buffer
, indices
[i
-2], stride
),
185 get_vert(vertex_buffer
, indices
[i
-1], stride
),
186 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
190 case PIPE_PRIM_TRIANGLE_STRIP
:
191 if (flatshade_first
) {
192 for (i
= 2; i
< nr
; i
+= 1) {
193 /* emit first triangle vertex as first triangle vertex */
194 setup
->triangle( setup
,
195 get_vert(vertex_buffer
, indices
[i
-2], stride
),
196 get_vert(vertex_buffer
, indices
[i
+(i
&1)-1], stride
),
197 get_vert(vertex_buffer
, indices
[i
-(i
&1)], stride
) );
202 for (i
= 2; i
< nr
; i
+= 1) {
203 /* emit last triangle vertex as last triangle vertex */
204 setup
->triangle( setup
,
205 get_vert(vertex_buffer
, indices
[i
+(i
&1)-2], stride
),
206 get_vert(vertex_buffer
, indices
[i
-(i
&1)-1], stride
),
207 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
212 case PIPE_PRIM_TRIANGLE_FAN
:
213 if (flatshade_first
) {
214 for (i
= 2; i
< nr
; i
+= 1) {
215 /* emit first non-spoke vertex as first vertex */
216 setup
->triangle( setup
,
217 get_vert(vertex_buffer
, indices
[i
-1], stride
),
218 get_vert(vertex_buffer
, indices
[i
-0], stride
),
219 get_vert(vertex_buffer
, indices
[0], stride
) );
223 for (i
= 2; i
< nr
; i
+= 1) {
224 /* emit last non-spoke vertex as last vertex */
225 setup
->triangle( setup
,
226 get_vert(vertex_buffer
, indices
[0], stride
),
227 get_vert(vertex_buffer
, indices
[i
-1], stride
),
228 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
233 case PIPE_PRIM_QUADS
:
234 /* GL quads don't follow provoking vertex convention */
235 if (flatshade_first
) {
236 /* emit last quad vertex as first triangle vertex */
237 for (i
= 3; i
< nr
; i
+= 4) {
238 setup
->triangle( setup
,
239 get_vert(vertex_buffer
, indices
[i
-0], stride
),
240 get_vert(vertex_buffer
, indices
[i
-3], stride
),
241 get_vert(vertex_buffer
, indices
[i
-2], stride
) );
243 setup
->triangle( setup
,
244 get_vert(vertex_buffer
, indices
[i
-0], stride
),
245 get_vert(vertex_buffer
, indices
[i
-2], stride
),
246 get_vert(vertex_buffer
, indices
[i
-1], stride
) );
250 /* emit last quad vertex as last triangle vertex */
251 for (i
= 3; i
< nr
; i
+= 4) {
252 setup
->triangle( setup
,
253 get_vert(vertex_buffer
, indices
[i
-3], stride
),
254 get_vert(vertex_buffer
, indices
[i
-2], stride
),
255 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
257 setup
->triangle( setup
,
258 get_vert(vertex_buffer
, indices
[i
-2], stride
),
259 get_vert(vertex_buffer
, indices
[i
-1], stride
),
260 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
265 case PIPE_PRIM_QUAD_STRIP
:
266 /* GL quad strips don't follow provoking vertex convention */
267 if (flatshade_first
) {
268 /* emit last quad vertex as first triangle vertex */
269 for (i
= 3; i
< nr
; i
+= 2) {
270 setup
->triangle( setup
,
271 get_vert(vertex_buffer
, indices
[i
-0], stride
),
272 get_vert(vertex_buffer
, indices
[i
-3], stride
),
273 get_vert(vertex_buffer
, indices
[i
-2], stride
) );
274 setup
->triangle( setup
,
275 get_vert(vertex_buffer
, indices
[i
-0], stride
),
276 get_vert(vertex_buffer
, indices
[i
-1], stride
),
277 get_vert(vertex_buffer
, indices
[i
-3], stride
) );
281 /* emit last quad vertex as last triangle vertex */
282 for (i
= 3; i
< nr
; i
+= 2) {
283 setup
->triangle( setup
,
284 get_vert(vertex_buffer
, indices
[i
-3], stride
),
285 get_vert(vertex_buffer
, indices
[i
-2], stride
),
286 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
287 setup
->triangle( setup
,
288 get_vert(vertex_buffer
, indices
[i
-1], stride
),
289 get_vert(vertex_buffer
, indices
[i
-3], stride
),
290 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
295 case PIPE_PRIM_POLYGON
:
296 /* Almost same as tri fan but the _first_ vertex specifies the flat
299 if (flatshade_first
) {
300 /* emit first polygon vertex as first triangle vertex */
301 for (i
= 2; i
< nr
; i
+= 1) {
302 setup
->triangle( setup
,
303 get_vert(vertex_buffer
, indices
[0], stride
),
304 get_vert(vertex_buffer
, indices
[i
-1], stride
),
305 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
309 /* emit first polygon vertex as last triangle vertex */
310 for (i
= 2; i
< nr
; i
+= 1) {
311 setup
->triangle( setup
,
312 get_vert(vertex_buffer
, indices
[i
-1], stride
),
313 get_vert(vertex_buffer
, indices
[i
-0], stride
),
314 get_vert(vertex_buffer
, indices
[0], stride
) );
326 * This function is hit when the draw module is working in pass-through mode.
327 * It's up to us to convert the vertex array into point/line/tri prims.
330 lp_setup_draw_arrays(struct vbuf_render
*vbr
, uint start
, uint nr
)
332 struct lp_setup_context
*setup
= lp_setup_context(vbr
);
333 const unsigned stride
= setup
->vertex_info
->size
* sizeof(float);
334 const void *vertex_buffer
=
335 (void *) get_vert(setup
->vertex_buffer
, start
, stride
);
336 const boolean flatshade_first
= setup
->flatshade_first
;
339 lp_setup_update_state(setup
);
341 switch (setup
->prim
) {
342 case PIPE_PRIM_POINTS
:
343 for (i
= 0; i
< nr
; i
++) {
345 get_vert(vertex_buffer
, i
-0, stride
) );
349 case PIPE_PRIM_LINES
:
350 for (i
= 1; i
< nr
; i
+= 2) {
352 get_vert(vertex_buffer
, i
-1, stride
),
353 get_vert(vertex_buffer
, i
-0, stride
) );
357 case PIPE_PRIM_LINE_STRIP
:
358 for (i
= 1; i
< nr
; i
++) {
360 get_vert(vertex_buffer
, i
-1, stride
),
361 get_vert(vertex_buffer
, i
-0, stride
) );
365 case PIPE_PRIM_LINE_LOOP
:
366 for (i
= 1; i
< nr
; i
++) {
368 get_vert(vertex_buffer
, i
-1, stride
),
369 get_vert(vertex_buffer
, i
-0, stride
) );
373 get_vert(vertex_buffer
, nr
-1, stride
),
374 get_vert(vertex_buffer
, 0, stride
) );
378 case PIPE_PRIM_TRIANGLES
:
379 for (i
= 2; i
< nr
; i
+= 3) {
380 setup
->triangle( setup
,
381 get_vert(vertex_buffer
, i
-2, stride
),
382 get_vert(vertex_buffer
, i
-1, stride
),
383 get_vert(vertex_buffer
, i
-0, stride
) );
387 case PIPE_PRIM_TRIANGLE_STRIP
:
388 if (flatshade_first
) {
389 for (i
= 2; i
< nr
; i
++) {
390 /* emit first triangle vertex as first triangle vertex */
391 setup
->triangle( setup
,
392 get_vert(vertex_buffer
, i
-2, stride
),
393 get_vert(vertex_buffer
, i
+(i
&1)-1, stride
),
394 get_vert(vertex_buffer
, i
-(i
&1), stride
) );
398 for (i
= 2; i
< nr
; i
++) {
399 /* emit last triangle vertex as last triangle vertex */
400 setup
->triangle( setup
,
401 get_vert(vertex_buffer
, i
+(i
&1)-2, stride
),
402 get_vert(vertex_buffer
, i
-(i
&1)-1, stride
),
403 get_vert(vertex_buffer
, i
-0, stride
) );
408 case PIPE_PRIM_TRIANGLE_FAN
:
409 if (flatshade_first
) {
410 for (i
= 2; i
< nr
; i
+= 1) {
411 /* emit first non-spoke vertex as first vertex */
412 setup
->triangle( setup
,
413 get_vert(vertex_buffer
, i
-1, stride
),
414 get_vert(vertex_buffer
, i
-0, stride
),
415 get_vert(vertex_buffer
, 0, stride
) );
419 for (i
= 2; i
< nr
; i
+= 1) {
420 /* emit last non-spoke vertex as last vertex */
421 setup
->triangle( setup
,
422 get_vert(vertex_buffer
, 0, stride
),
423 get_vert(vertex_buffer
, i
-1, stride
),
424 get_vert(vertex_buffer
, i
-0, stride
) );
429 case PIPE_PRIM_QUADS
:
430 /* GL quads don't follow provoking vertex convention */
431 if (flatshade_first
) {
432 /* emit last quad vertex as first triangle vertex */
433 for (i
= 3; i
< nr
; i
+= 4) {
434 setup
->triangle( setup
,
435 get_vert(vertex_buffer
, i
-0, stride
),
436 get_vert(vertex_buffer
, i
-3, stride
),
437 get_vert(vertex_buffer
, i
-2, stride
) );
438 setup
->triangle( setup
,
439 get_vert(vertex_buffer
, i
-0, stride
),
440 get_vert(vertex_buffer
, i
-2, stride
),
441 get_vert(vertex_buffer
, i
-1, stride
) );
445 /* emit last quad vertex as last triangle vertex */
446 for (i
= 3; i
< nr
; i
+= 4) {
447 setup
->triangle( setup
,
448 get_vert(vertex_buffer
, i
-3, stride
),
449 get_vert(vertex_buffer
, i
-2, stride
),
450 get_vert(vertex_buffer
, i
-0, stride
) );
451 setup
->triangle( setup
,
452 get_vert(vertex_buffer
, i
-2, stride
),
453 get_vert(vertex_buffer
, i
-1, stride
),
454 get_vert(vertex_buffer
, i
-0, stride
) );
459 case PIPE_PRIM_QUAD_STRIP
:
460 /* GL quad strips don't follow provoking vertex convention */
461 if (flatshade_first
) {
462 /* emit last quad vertex as first triangle vertex */
463 for (i
= 3; i
< nr
; i
+= 2) {
464 setup
->triangle( setup
,
465 get_vert(vertex_buffer
, i
-0, stride
),
466 get_vert(vertex_buffer
, i
-3, stride
),
467 get_vert(vertex_buffer
, i
-2, stride
) );
468 setup
->triangle( setup
,
469 get_vert(vertex_buffer
, i
-0, stride
),
470 get_vert(vertex_buffer
, i
-1, stride
),
471 get_vert(vertex_buffer
, i
-3, stride
) );
475 /* emit last quad vertex as last triangle vertex */
476 for (i
= 3; i
< nr
; i
+= 2) {
477 setup
->triangle( setup
,
478 get_vert(vertex_buffer
, i
-3, stride
),
479 get_vert(vertex_buffer
, i
-2, stride
),
480 get_vert(vertex_buffer
, i
-0, stride
) );
481 setup
->triangle( setup
,
482 get_vert(vertex_buffer
, i
-1, stride
),
483 get_vert(vertex_buffer
, i
-3, stride
),
484 get_vert(vertex_buffer
, i
-0, stride
) );
489 case PIPE_PRIM_POLYGON
:
490 /* Almost same as tri fan but the _first_ vertex specifies the flat
493 if (flatshade_first
) {
494 /* emit first polygon vertex as first triangle vertex */
495 for (i
= 2; i
< nr
; i
+= 1) {
496 setup
->triangle( setup
,
497 get_vert(vertex_buffer
, 0, stride
),
498 get_vert(vertex_buffer
, i
-1, stride
),
499 get_vert(vertex_buffer
, i
-0, stride
) );
503 /* emit first polygon vertex as last triangle vertex */
504 for (i
= 2; i
< nr
; i
+= 1) {
505 setup
->triangle( setup
,
506 get_vert(vertex_buffer
, i
-1, stride
),
507 get_vert(vertex_buffer
, i
-0, stride
),
508 get_vert(vertex_buffer
, 0, stride
) );
521 lp_setup_vbuf_destroy(struct vbuf_render
*vbr
)
523 struct lp_setup_context
*setup
= lp_setup_context(vbr
);
524 if (setup
->vertex_buffer
) {
525 align_free(setup
->vertex_buffer
);
526 setup
->vertex_buffer
= NULL
;
528 lp_setup_destroy(setup
);
533 * Create the post-transform vertex handler for the given context.
536 lp_setup_init_vbuf(struct lp_setup_context
*setup
)
538 setup
->base
.max_indices
= LP_MAX_VBUF_INDEXES
;
539 setup
->base
.max_vertex_buffer_bytes
= LP_MAX_VBUF_SIZE
;
541 setup
->base
.get_vertex_info
= lp_setup_get_vertex_info
;
542 setup
->base
.allocate_vertices
= lp_setup_allocate_vertices
;
543 setup
->base
.map_vertices
= lp_setup_map_vertices
;
544 setup
->base
.unmap_vertices
= lp_setup_unmap_vertices
;
545 setup
->base
.set_primitive
= lp_setup_set_primitive
;
546 setup
->base
.draw_elements
= lp_setup_draw_elements
;
547 setup
->base
.draw_arrays
= lp_setup_draw_arrays
;
548 setup
->base
.release_vertices
= lp_setup_release_vertices
;
549 setup
->base
.destroy
= lp_setup_vbuf_destroy
;