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(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
;
141 lp_setup_update_state(setup
);
143 switch (setup
->prim
) {
144 case PIPE_PRIM_POINTS
:
145 for (i
= 0; i
< nr
; i
++) {
147 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
151 case PIPE_PRIM_LINES
:
152 for (i
= 1; i
< nr
; i
+= 2) {
154 get_vert(vertex_buffer
, indices
[i
-1], stride
),
155 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
159 case PIPE_PRIM_LINE_STRIP
:
160 for (i
= 1; i
< nr
; i
++) {
162 get_vert(vertex_buffer
, indices
[i
-1], stride
),
163 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
167 case PIPE_PRIM_LINE_LOOP
:
168 for (i
= 1; i
< nr
; i
++) {
170 get_vert(vertex_buffer
, indices
[i
-1], stride
),
171 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
175 get_vert(vertex_buffer
, indices
[nr
-1], stride
),
176 get_vert(vertex_buffer
, indices
[0], stride
) );
180 case PIPE_PRIM_TRIANGLES
:
181 if (setup
->flatshade_first
) {
182 for (i
= 2; i
< nr
; i
+= 3) {
183 setup
->triangle( setup
,
184 get_vert(vertex_buffer
, indices
[i
-1], stride
),
185 get_vert(vertex_buffer
, indices
[i
-0], stride
),
186 get_vert(vertex_buffer
, indices
[i
-2], stride
) );
190 for (i
= 2; i
< nr
; i
+= 3) {
191 setup
->triangle( setup
,
192 get_vert(vertex_buffer
, indices
[i
-2], stride
),
193 get_vert(vertex_buffer
, indices
[i
-1], stride
),
194 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
199 case PIPE_PRIM_TRIANGLE_STRIP
:
200 if (setup
->flatshade_first
) {
201 for (i
= 2; i
< nr
; i
+= 1) {
202 setup
->triangle( setup
,
203 get_vert(vertex_buffer
, indices
[i
+(i
&1)-1], stride
),
204 get_vert(vertex_buffer
, indices
[i
-(i
&1)], stride
),
205 get_vert(vertex_buffer
, indices
[i
-2], stride
) );
209 for (i
= 2; i
< nr
; i
+= 1) {
210 setup
->triangle( setup
,
211 get_vert(vertex_buffer
, indices
[i
+(i
&1)-2], stride
),
212 get_vert(vertex_buffer
, indices
[i
-(i
&1)-1], stride
),
213 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
218 case PIPE_PRIM_TRIANGLE_FAN
:
219 if (setup
->flatshade_first
) {
220 for (i
= 2; i
< nr
; i
+= 1) {
221 setup
->triangle( setup
,
222 get_vert(vertex_buffer
, indices
[i
-0], stride
),
223 get_vert(vertex_buffer
, indices
[0], stride
),
224 get_vert(vertex_buffer
, indices
[i
-1], stride
) );
228 for (i
= 2; i
< nr
; i
+= 1) {
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 for (i
= 3; i
< nr
; i
+= 4) {
239 setup
->triangle( setup
,
240 get_vert(vertex_buffer
, indices
[i
-3], stride
),
241 get_vert(vertex_buffer
, indices
[i
-2], stride
),
242 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
244 setup
->triangle( setup
,
245 get_vert(vertex_buffer
, indices
[i
-2], stride
),
246 get_vert(vertex_buffer
, indices
[i
-1], stride
),
247 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
251 case PIPE_PRIM_QUAD_STRIP
:
252 for (i
= 3; i
< nr
; i
+= 2) {
253 setup
->triangle( setup
,
254 get_vert(vertex_buffer
, indices
[i
-3], stride
),
255 get_vert(vertex_buffer
, indices
[i
-2], stride
),
256 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
257 setup
->triangle( setup
,
258 get_vert(vertex_buffer
, indices
[i
-1], stride
),
259 get_vert(vertex_buffer
, indices
[i
-3], stride
),
260 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
264 case PIPE_PRIM_POLYGON
:
265 /* Almost same as tri fan but the _first_ vertex specifies the flat
266 * shading color. Note that the first polygon vertex is passed as
267 * the last triangle vertex here.
268 * flatshade_first state makes no difference.
270 for (i
= 2; i
< nr
; i
+= 1) {
271 setup
->triangle( setup
,
272 get_vert(vertex_buffer
, indices
[i
-0], stride
),
273 get_vert(vertex_buffer
, indices
[i
-1], stride
),
274 get_vert(vertex_buffer
, indices
[0], stride
) );
285 * This function is hit when the draw module is working in pass-through mode.
286 * It's up to us to convert the vertex array into point/line/tri prims.
289 lp_setup_draw_arrays(struct vbuf_render
*vbr
, uint start
, uint nr
)
291 struct lp_setup_context
*setup
= lp_setup_context(vbr
);
292 const unsigned stride
= setup
->vertex_info
->size
* sizeof(float);
293 const void *vertex_buffer
=
294 (void *) get_vert(setup
->vertex_buffer
, start
, stride
);
297 lp_setup_update_state(setup
);
299 switch (setup
->prim
) {
300 case PIPE_PRIM_POINTS
:
301 for (i
= 0; i
< nr
; i
++) {
303 get_vert(vertex_buffer
, i
-0, stride
) );
307 case PIPE_PRIM_LINES
:
308 for (i
= 1; i
< nr
; i
+= 2) {
310 get_vert(vertex_buffer
, i
-1, stride
),
311 get_vert(vertex_buffer
, i
-0, stride
) );
315 case PIPE_PRIM_LINE_STRIP
:
316 for (i
= 1; i
< nr
; i
++) {
318 get_vert(vertex_buffer
, i
-1, stride
),
319 get_vert(vertex_buffer
, i
-0, stride
) );
323 case PIPE_PRIM_LINE_LOOP
:
324 for (i
= 1; i
< nr
; i
++) {
326 get_vert(vertex_buffer
, i
-1, stride
),
327 get_vert(vertex_buffer
, i
-0, stride
) );
331 get_vert(vertex_buffer
, nr
-1, stride
),
332 get_vert(vertex_buffer
, 0, stride
) );
336 case PIPE_PRIM_TRIANGLES
:
337 if (setup
->flatshade_first
) {
338 for (i
= 2; i
< nr
; i
+= 3) {
339 setup
->triangle( setup
,
340 get_vert(vertex_buffer
, i
-1, stride
),
341 get_vert(vertex_buffer
, i
-0, stride
),
342 get_vert(vertex_buffer
, i
-2, stride
) );
346 for (i
= 2; i
< nr
; i
+= 3) {
347 setup
->triangle( setup
,
348 get_vert(vertex_buffer
, i
-2, stride
),
349 get_vert(vertex_buffer
, i
-1, stride
),
350 get_vert(vertex_buffer
, i
-0, stride
) );
355 case PIPE_PRIM_TRIANGLE_STRIP
:
356 if (setup
->flatshade_first
) {
357 for (i
= 2; i
< nr
; i
++) {
358 setup
->triangle( setup
,
359 get_vert(vertex_buffer
, i
+(i
&1)-1, stride
),
360 get_vert(vertex_buffer
, i
-(i
&1), stride
),
361 get_vert(vertex_buffer
, i
-2, stride
) );
365 for (i
= 2; i
< nr
; i
++) {
366 setup
->triangle( setup
,
367 get_vert(vertex_buffer
, i
+(i
&1)-2, stride
),
368 get_vert(vertex_buffer
, i
-(i
&1)-1, stride
),
369 get_vert(vertex_buffer
, i
-0, stride
) );
374 case PIPE_PRIM_TRIANGLE_FAN
:
375 if (setup
->flatshade_first
) {
376 for (i
= 2; i
< nr
; i
+= 1) {
377 setup
->triangle( setup
,
378 get_vert(vertex_buffer
, i
-0, stride
),
379 get_vert(vertex_buffer
, 0, stride
),
380 get_vert(vertex_buffer
, i
-1, stride
) );
384 for (i
= 2; i
< nr
; i
+= 1) {
385 setup
->triangle( setup
,
386 get_vert(vertex_buffer
, 0, stride
),
387 get_vert(vertex_buffer
, i
-1, stride
),
388 get_vert(vertex_buffer
, i
-0, stride
) );
393 case PIPE_PRIM_QUADS
:
394 for (i
= 3; i
< nr
; i
+= 4) {
395 setup
->triangle( setup
,
396 get_vert(vertex_buffer
, i
-3, stride
),
397 get_vert(vertex_buffer
, i
-2, stride
),
398 get_vert(vertex_buffer
, i
-0, stride
) );
399 setup
->triangle( setup
,
400 get_vert(vertex_buffer
, i
-2, stride
),
401 get_vert(vertex_buffer
, i
-1, stride
),
402 get_vert(vertex_buffer
, i
-0, stride
) );
406 case PIPE_PRIM_QUAD_STRIP
:
407 for (i
= 3; i
< nr
; i
+= 2) {
408 setup
->triangle( setup
,
409 get_vert(vertex_buffer
, i
-3, stride
),
410 get_vert(vertex_buffer
, i
-2, stride
),
411 get_vert(vertex_buffer
, i
-0, stride
) );
412 setup
->triangle( setup
,
413 get_vert(vertex_buffer
, i
-1, stride
),
414 get_vert(vertex_buffer
, i
-3, stride
),
415 get_vert(vertex_buffer
, i
-0, stride
) );
419 case PIPE_PRIM_POLYGON
:
420 /* Almost same as tri fan but the _first_ vertex specifies the flat
421 * shading color. Note that the first polygon vertex is passed as
422 * the last triangle vertex here.
423 * flatshade_first state makes no difference.
425 for (i
= 2; i
< nr
; i
+= 1) {
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
, 0, stride
) );
441 lp_setup_vbuf_destroy(struct vbuf_render
*vbr
)
443 lp_setup_destroy(lp_setup_context(vbr
));
448 * Create the post-transform vertex handler for the given context.
451 lp_setup_init_vbuf(struct lp_setup_context
*setup
)
453 setup
->base
.max_indices
= LP_MAX_VBUF_INDEXES
;
454 setup
->base
.max_vertex_buffer_bytes
= LP_MAX_VBUF_SIZE
;
456 setup
->base
.get_vertex_info
= lp_setup_get_vertex_info
;
457 setup
->base
.allocate_vertices
= lp_setup_allocate_vertices
;
458 setup
->base
.map_vertices
= lp_setup_map_vertices
;
459 setup
->base
.unmap_vertices
= lp_setup_unmap_vertices
;
460 setup
->base
.set_primitive
= lp_setup_set_primitive
;
461 setup
->base
.draw
= lp_setup_draw
;
462 setup
->base
.draw_arrays
= lp_setup_draw_arrays
;
463 setup
->base
.release_vertices
= lp_setup_release_vertices
;
464 setup
->base
.destroy
= lp_setup_vbuf_destroy
;