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 softpipe 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 "sp_context.h"
42 #include "sp_prim_vbuf.h"
43 #include "draw/draw_context.h"
44 #include "draw/draw_vbuf.h"
45 #include "util/u_memory.h"
46 #include "util/u_prim.h"
49 #define SP_MAX_VBUF_INDEXES 1024
50 #define SP_MAX_VBUF_SIZE 4096
52 typedef const float (*cptrf4
)[4];
55 * Subclass of vbuf_render.
57 struct softpipe_vbuf_render
59 struct vbuf_render base
;
60 struct softpipe_context
*softpipe
;
61 struct setup_context
*setup
;
66 uint vertex_buffer_size
;
72 static struct softpipe_vbuf_render
*
73 softpipe_vbuf_render(struct vbuf_render
*vbr
)
75 return (struct softpipe_vbuf_render
*) vbr
;
84 static const struct vertex_info
*
85 sp_vbuf_get_vertex_info(struct vbuf_render
*vbr
)
87 struct softpipe_vbuf_render
*cvbr
= softpipe_vbuf_render(vbr
);
88 return softpipe_get_vbuf_vertex_info(cvbr
->softpipe
);
93 sp_vbuf_allocate_vertices(struct vbuf_render
*vbr
,
94 ushort vertex_size
, ushort nr_vertices
)
96 struct softpipe_vbuf_render
*cvbr
= softpipe_vbuf_render(vbr
);
97 unsigned size
= vertex_size
* nr_vertices
;
99 if (cvbr
->vertex_buffer_size
< size
) {
100 align_free(cvbr
->vertex_buffer
);
101 cvbr
->vertex_buffer
= align_malloc(size
, 16);
102 cvbr
->vertex_buffer_size
= size
;
105 cvbr
->vertex_size
= vertex_size
;
106 cvbr
->nr_vertices
= nr_vertices
;
108 return cvbr
->vertex_buffer
!= NULL
;
112 sp_vbuf_release_vertices(struct vbuf_render
*vbr
)
114 /* keep the old allocation for next time */
118 sp_vbuf_map_vertices(struct vbuf_render
*vbr
)
120 struct softpipe_vbuf_render
*cvbr
= softpipe_vbuf_render(vbr
);
121 return cvbr
->vertex_buffer
;
125 sp_vbuf_unmap_vertices(struct vbuf_render
*vbr
,
129 struct softpipe_vbuf_render
*cvbr
= softpipe_vbuf_render(vbr
);
130 assert( cvbr
->vertex_buffer_size
>= (max_index
+1) * cvbr
->vertex_size
);
137 sp_vbuf_set_primitive(struct vbuf_render
*vbr
, unsigned prim
)
139 struct softpipe_vbuf_render
*cvbr
= softpipe_vbuf_render(vbr
);
140 struct setup_context
*setup_ctx
= cvbr
->setup
;
142 sp_setup_prepare( setup_ctx
);
144 cvbr
->softpipe
->reduced_prim
= u_reduced_prim(prim
);
151 static INLINE cptrf4
get_vert( const void *vertex_buffer
,
155 return (cptrf4
)((char *)vertex_buffer
+ index
* stride
);
160 * draw elements / indexed primitives
163 sp_vbuf_draw(struct vbuf_render
*vbr
, const ushort
*indices
, uint nr
)
165 struct softpipe_vbuf_render
*cvbr
= softpipe_vbuf_render(vbr
);
166 struct softpipe_context
*softpipe
= cvbr
->softpipe
;
167 const unsigned stride
= softpipe
->vertex_info_vbuf
.size
* sizeof(float);
168 const void *vertex_buffer
= cvbr
->vertex_buffer
;
169 struct setup_context
*setup_ctx
= cvbr
->setup
;
172 switch (cvbr
->prim
) {
173 case PIPE_PRIM_POINTS
:
174 for (i
= 0; i
< nr
; i
++) {
175 sp_setup_point( setup_ctx
,
176 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
180 case PIPE_PRIM_LINES
:
181 for (i
= 1; i
< nr
; i
+= 2) {
182 sp_setup_line( setup_ctx
,
183 get_vert(vertex_buffer
, indices
[i
-1], stride
),
184 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
188 case PIPE_PRIM_LINE_STRIP
:
189 for (i
= 1; i
< nr
; i
++) {
190 sp_setup_line( setup_ctx
,
191 get_vert(vertex_buffer
, indices
[i
-1], stride
),
192 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
196 case PIPE_PRIM_LINE_LOOP
:
197 for (i
= 1; i
< nr
; i
++) {
198 sp_setup_line( setup_ctx
,
199 get_vert(vertex_buffer
, indices
[i
-1], stride
),
200 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
203 sp_setup_line( setup_ctx
,
204 get_vert(vertex_buffer
, indices
[nr
-1], stride
),
205 get_vert(vertex_buffer
, indices
[0], stride
) );
209 case PIPE_PRIM_TRIANGLES
:
210 if (softpipe
->rasterizer
->flatshade_first
) {
211 for (i
= 2; i
< nr
; i
+= 3) {
212 sp_setup_tri( setup_ctx
,
213 get_vert(vertex_buffer
, indices
[i
-1], stride
),
214 get_vert(vertex_buffer
, indices
[i
-0], stride
),
215 get_vert(vertex_buffer
, indices
[i
-2], stride
) );
219 for (i
= 2; i
< nr
; i
+= 3) {
220 sp_setup_tri( setup_ctx
,
221 get_vert(vertex_buffer
, indices
[i
-2], stride
),
222 get_vert(vertex_buffer
, indices
[i
-1], stride
),
223 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
228 case PIPE_PRIM_TRIANGLE_STRIP
:
229 if (softpipe
->rasterizer
->flatshade_first
) {
230 for (i
= 2; i
< nr
; i
+= 1) {
231 sp_setup_tri( setup_ctx
,
232 get_vert(vertex_buffer
, indices
[i
+(i
&1)-1], stride
),
233 get_vert(vertex_buffer
, indices
[i
-(i
&1)], stride
),
234 get_vert(vertex_buffer
, indices
[i
-2], stride
) );
238 for (i
= 2; i
< nr
; i
+= 1) {
239 sp_setup_tri( setup_ctx
,
240 get_vert(vertex_buffer
, indices
[i
+(i
&1)-2], stride
),
241 get_vert(vertex_buffer
, indices
[i
-(i
&1)-1], stride
),
242 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
247 case PIPE_PRIM_TRIANGLE_FAN
:
248 if (softpipe
->rasterizer
->flatshade_first
) {
249 for (i
= 2; i
< nr
; i
+= 1) {
250 sp_setup_tri( setup_ctx
,
251 get_vert(vertex_buffer
, indices
[i
-0], stride
),
252 get_vert(vertex_buffer
, indices
[0], stride
),
253 get_vert(vertex_buffer
, indices
[i
-1], stride
) );
257 for (i
= 2; i
< nr
; i
+= 1) {
258 sp_setup_tri( setup_ctx
,
259 get_vert(vertex_buffer
, indices
[0], stride
),
260 get_vert(vertex_buffer
, indices
[i
-1], stride
),
261 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
266 case PIPE_PRIM_QUADS
:
267 if (softpipe
->rasterizer
->flatshade_first
) {
268 for (i
= 3; i
< nr
; i
+= 4) {
269 sp_setup_tri( setup_ctx
,
270 get_vert(vertex_buffer
, indices
[i
-2], stride
),
271 get_vert(vertex_buffer
, indices
[i
-1], stride
),
272 get_vert(vertex_buffer
, indices
[i
-3], stride
) );
273 sp_setup_tri( setup_ctx
,
274 get_vert(vertex_buffer
, indices
[i
-1], stride
),
275 get_vert(vertex_buffer
, indices
[i
-0], stride
),
276 get_vert(vertex_buffer
, indices
[i
-3], stride
) );
280 for (i
= 3; i
< nr
; i
+= 4) {
281 sp_setup_tri( setup_ctx
,
282 get_vert(vertex_buffer
, indices
[i
-3], stride
),
283 get_vert(vertex_buffer
, indices
[i
-2], stride
),
284 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
286 sp_setup_tri( setup_ctx
,
287 get_vert(vertex_buffer
, indices
[i
-2], stride
),
288 get_vert(vertex_buffer
, indices
[i
-1], stride
),
289 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
294 case PIPE_PRIM_QUAD_STRIP
:
295 if (softpipe
->rasterizer
->flatshade_first
) {
296 for (i
= 3; i
< nr
; i
+= 2) {
297 sp_setup_tri( setup_ctx
,
298 get_vert(vertex_buffer
, indices
[i
-0], stride
),
299 get_vert(vertex_buffer
, indices
[i
-1], stride
),
300 get_vert(vertex_buffer
, indices
[i
-3], stride
));
301 sp_setup_tri( setup_ctx
,
302 get_vert(vertex_buffer
, indices
[i
-2], stride
),
303 get_vert(vertex_buffer
, indices
[i
-0], stride
),
304 get_vert(vertex_buffer
, indices
[i
-3], stride
) );
308 for (i
= 3; i
< nr
; i
+= 2) {
309 sp_setup_tri( setup_ctx
,
310 get_vert(vertex_buffer
, indices
[i
-3], stride
),
311 get_vert(vertex_buffer
, indices
[i
-2], stride
),
312 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
313 sp_setup_tri( setup_ctx
,
314 get_vert(vertex_buffer
, indices
[i
-1], stride
),
315 get_vert(vertex_buffer
, indices
[i
-3], stride
),
316 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
321 case PIPE_PRIM_POLYGON
:
322 /* Almost same as tri fan but the _first_ vertex specifies the flat
323 * shading color. Note that the first polygon vertex is passed as
324 * the last triangle vertex here.
325 * flatshade_first state makes no difference.
327 for (i
= 2; i
< nr
; i
+= 1) {
328 sp_setup_tri( setup_ctx
,
329 get_vert(vertex_buffer
, indices
[i
-0], stride
),
330 get_vert(vertex_buffer
, indices
[i
-1], stride
),
331 get_vert(vertex_buffer
, indices
[0], stride
) );
342 * This function is hit when the draw module is working in pass-through mode.
343 * It's up to us to convert the vertex array into point/line/tri prims.
346 sp_vbuf_draw_arrays(struct vbuf_render
*vbr
, uint start
, uint nr
)
348 struct softpipe_vbuf_render
*cvbr
= softpipe_vbuf_render(vbr
);
349 struct softpipe_context
*softpipe
= cvbr
->softpipe
;
350 struct setup_context
*setup_ctx
= cvbr
->setup
;
351 const unsigned stride
= softpipe
->vertex_info_vbuf
.size
* sizeof(float);
352 const void *vertex_buffer
=
353 (void *) get_vert(cvbr
->vertex_buffer
, start
, stride
);
356 switch (cvbr
->prim
) {
357 case PIPE_PRIM_POINTS
:
358 for (i
= 0; i
< nr
; i
++) {
359 sp_setup_point( setup_ctx
,
360 get_vert(vertex_buffer
, i
-0, stride
) );
364 case PIPE_PRIM_LINES
:
365 for (i
= 1; i
< nr
; i
+= 2) {
366 sp_setup_line( setup_ctx
,
367 get_vert(vertex_buffer
, i
-1, stride
),
368 get_vert(vertex_buffer
, i
-0, stride
) );
372 case PIPE_PRIM_LINE_STRIP
:
373 for (i
= 1; i
< nr
; i
++) {
374 sp_setup_line( setup_ctx
,
375 get_vert(vertex_buffer
, i
-1, stride
),
376 get_vert(vertex_buffer
, i
-0, stride
) );
380 case PIPE_PRIM_LINE_LOOP
:
381 for (i
= 1; i
< nr
; i
++) {
382 sp_setup_line( setup_ctx
,
383 get_vert(vertex_buffer
, i
-1, stride
),
384 get_vert(vertex_buffer
, i
-0, stride
) );
387 sp_setup_line( setup_ctx
,
388 get_vert(vertex_buffer
, nr
-1, stride
),
389 get_vert(vertex_buffer
, 0, stride
) );
393 case PIPE_PRIM_TRIANGLES
:
394 if (softpipe
->rasterizer
->flatshade_first
) {
395 for (i
= 2; i
< nr
; i
+= 3) {
396 sp_setup_tri( setup_ctx
,
397 get_vert(vertex_buffer
, i
-1, stride
),
398 get_vert(vertex_buffer
, i
-0, stride
),
399 get_vert(vertex_buffer
, i
-2, stride
) );
403 for (i
= 2; i
< nr
; i
+= 3) {
404 sp_setup_tri( setup_ctx
,
405 get_vert(vertex_buffer
, i
-2, stride
),
406 get_vert(vertex_buffer
, i
-1, stride
),
407 get_vert(vertex_buffer
, i
-0, stride
) );
412 case PIPE_PRIM_TRIANGLE_STRIP
:
413 if (softpipe
->rasterizer
->flatshade_first
) {
414 for (i
= 2; i
< nr
; i
++) {
415 sp_setup_tri( setup_ctx
,
416 get_vert(vertex_buffer
, i
+(i
&1)-1, stride
),
417 get_vert(vertex_buffer
, i
-(i
&1), stride
),
418 get_vert(vertex_buffer
, i
-2, stride
) );
422 for (i
= 2; i
< nr
; i
++) {
423 sp_setup_tri( setup_ctx
,
424 get_vert(vertex_buffer
, i
+(i
&1)-2, stride
),
425 get_vert(vertex_buffer
, i
-(i
&1)-1, stride
),
426 get_vert(vertex_buffer
, i
-0, stride
) );
431 case PIPE_PRIM_TRIANGLE_FAN
:
432 if (softpipe
->rasterizer
->flatshade_first
) {
433 for (i
= 2; i
< nr
; i
+= 1) {
434 sp_setup_tri( setup_ctx
,
435 get_vert(vertex_buffer
, i
-0, stride
),
436 get_vert(vertex_buffer
, 0, stride
),
437 get_vert(vertex_buffer
, i
-1, stride
) );
441 for (i
= 2; i
< nr
; i
+= 1) {
442 sp_setup_tri( setup_ctx
,
443 get_vert(vertex_buffer
, 0, stride
),
444 get_vert(vertex_buffer
, i
-1, stride
),
445 get_vert(vertex_buffer
, i
-0, stride
) );
450 case PIPE_PRIM_QUADS
:
451 if (softpipe
->rasterizer
->flatshade_first
) {
452 for (i
= 3; i
< nr
; i
+= 4) {
453 sp_setup_tri( setup_ctx
,
454 get_vert(vertex_buffer
, i
-2, stride
),
455 get_vert(vertex_buffer
, i
-1, stride
),
456 get_vert(vertex_buffer
, i
-3, stride
) );
457 sp_setup_tri( setup_ctx
,
458 get_vert(vertex_buffer
, i
-1, stride
),
459 get_vert(vertex_buffer
, i
-0, stride
),
460 get_vert(vertex_buffer
, i
-3, stride
) );
464 for (i
= 3; i
< nr
; i
+= 4) {
465 sp_setup_tri( setup_ctx
,
466 get_vert(vertex_buffer
, i
-3, stride
),
467 get_vert(vertex_buffer
, i
-2, stride
),
468 get_vert(vertex_buffer
, i
-0, stride
) );
469 sp_setup_tri( setup_ctx
,
470 get_vert(vertex_buffer
, i
-2, stride
),
471 get_vert(vertex_buffer
, i
-1, stride
),
472 get_vert(vertex_buffer
, i
-0, stride
) );
477 case PIPE_PRIM_QUAD_STRIP
:
478 if (softpipe
->rasterizer
->flatshade_first
) {
479 for (i
= 3; i
< nr
; i
+= 2) {
480 sp_setup_tri( setup_ctx
,
481 get_vert(vertex_buffer
, i
-0, stride
),
482 get_vert(vertex_buffer
, i
-1, stride
),
483 get_vert(vertex_buffer
, i
-3, stride
) );
484 sp_setup_tri( setup_ctx
,
485 get_vert(vertex_buffer
, i
-2, stride
),
486 get_vert(vertex_buffer
, i
-0, stride
),
487 get_vert(vertex_buffer
, i
-3, stride
) );
491 for (i
= 3; i
< nr
; i
+= 2) {
492 sp_setup_tri( setup_ctx
,
493 get_vert(vertex_buffer
, i
-3, stride
),
494 get_vert(vertex_buffer
, i
-2, stride
),
495 get_vert(vertex_buffer
, i
-0, stride
) );
496 sp_setup_tri( setup_ctx
,
497 get_vert(vertex_buffer
, i
-1, stride
),
498 get_vert(vertex_buffer
, i
-3, stride
),
499 get_vert(vertex_buffer
, i
-0, stride
) );
504 case PIPE_PRIM_POLYGON
:
505 /* Almost same as tri fan but the _first_ vertex specifies the flat
506 * shading color. Note that the first polygon vertex is passed as
507 * the last triangle vertex here.
508 * flatshade_first state makes no difference.
510 for (i
= 2; i
< nr
; i
+= 1) {
511 sp_setup_tri( setup_ctx
,
512 get_vert(vertex_buffer
, i
-1, stride
),
513 get_vert(vertex_buffer
, i
-0, stride
),
514 get_vert(vertex_buffer
, 0, stride
) );
526 sp_vbuf_destroy(struct vbuf_render
*vbr
)
528 struct softpipe_vbuf_render
*cvbr
= softpipe_vbuf_render(vbr
);
529 sp_setup_destroy_context(cvbr
->setup
);
535 * Create the post-transform vertex handler for the given context.
538 sp_create_vbuf_backend(struct softpipe_context
*sp
)
540 struct softpipe_vbuf_render
*cvbr
= CALLOC_STRUCT(softpipe_vbuf_render
);
545 cvbr
->base
.max_indices
= SP_MAX_VBUF_INDEXES
;
546 cvbr
->base
.max_vertex_buffer_bytes
= SP_MAX_VBUF_SIZE
;
548 cvbr
->base
.get_vertex_info
= sp_vbuf_get_vertex_info
;
549 cvbr
->base
.allocate_vertices
= sp_vbuf_allocate_vertices
;
550 cvbr
->base
.map_vertices
= sp_vbuf_map_vertices
;
551 cvbr
->base
.unmap_vertices
= sp_vbuf_unmap_vertices
;
552 cvbr
->base
.set_primitive
= sp_vbuf_set_primitive
;
553 cvbr
->base
.draw
= sp_vbuf_draw
;
554 cvbr
->base
.draw_arrays
= sp_vbuf_draw_arrays
;
555 cvbr
->base
.release_vertices
= sp_vbuf_release_vertices
;
556 cvbr
->base
.destroy
= sp_vbuf_destroy
;
560 cvbr
->setup
= sp_setup_create_context(cvbr
->softpipe
);