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
;
79 /** This tells the draw module about our desired vertex layout */
80 static const struct vertex_info
*
81 sp_vbuf_get_vertex_info(struct vbuf_render
*vbr
)
83 struct softpipe_vbuf_render
*cvbr
= softpipe_vbuf_render(vbr
);
84 return softpipe_get_vbuf_vertex_info(cvbr
->softpipe
);
89 sp_vbuf_allocate_vertices(struct vbuf_render
*vbr
,
90 ushort vertex_size
, ushort nr_vertices
)
92 struct softpipe_vbuf_render
*cvbr
= softpipe_vbuf_render(vbr
);
93 unsigned size
= vertex_size
* nr_vertices
;
95 if (cvbr
->vertex_buffer_size
< size
) {
96 align_free(cvbr
->vertex_buffer
);
97 cvbr
->vertex_buffer
= align_malloc(size
, 16);
98 cvbr
->vertex_buffer_size
= size
;
101 cvbr
->vertex_size
= vertex_size
;
102 cvbr
->nr_vertices
= nr_vertices
;
104 return cvbr
->vertex_buffer
!= NULL
;
109 sp_vbuf_release_vertices(struct vbuf_render
*vbr
)
111 /* keep the old allocation for next time */
116 sp_vbuf_map_vertices(struct vbuf_render
*vbr
)
118 struct softpipe_vbuf_render
*cvbr
= softpipe_vbuf_render(vbr
);
119 return cvbr
->vertex_buffer
;
124 sp_vbuf_unmap_vertices(struct vbuf_render
*vbr
,
128 struct softpipe_vbuf_render
*cvbr
= softpipe_vbuf_render(vbr
);
129 assert( cvbr
->vertex_buffer_size
>= (max_index
+1) * cvbr
->vertex_size
);
136 sp_vbuf_set_primitive(struct vbuf_render
*vbr
, unsigned prim
)
138 struct softpipe_vbuf_render
*cvbr
= softpipe_vbuf_render(vbr
);
139 struct setup_context
*setup_ctx
= cvbr
->setup
;
141 sp_setup_prepare( setup_ctx
);
143 cvbr
->softpipe
->reduced_prim
= u_reduced_prim(prim
);
149 static INLINE cptrf4
get_vert( const void *vertex_buffer
,
153 return (cptrf4
)((char *)vertex_buffer
+ index
* stride
);
158 * draw elements / indexed primitives
161 sp_vbuf_draw_elements(struct vbuf_render
*vbr
, const ushort
*indices
, uint nr
)
163 struct softpipe_vbuf_render
*cvbr
= softpipe_vbuf_render(vbr
);
164 struct softpipe_context
*softpipe
= cvbr
->softpipe
;
165 const unsigned stride
= softpipe
->vertex_info_vbuf
.size
* sizeof(float);
166 const void *vertex_buffer
= cvbr
->vertex_buffer
;
167 struct setup_context
*setup
= cvbr
->setup
;
168 const boolean flatshade_first
= softpipe
->rasterizer
->flatshade_first
;
171 switch (cvbr
->prim
) {
172 case PIPE_PRIM_POINTS
:
173 for (i
= 0; i
< nr
; i
++) {
174 sp_setup_point( setup
,
175 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
179 case PIPE_PRIM_LINES
:
180 for (i
= 1; i
< nr
; i
+= 2) {
181 sp_setup_line( setup
,
182 get_vert(vertex_buffer
, indices
[i
-1], stride
),
183 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
187 case PIPE_PRIM_LINE_STRIP
:
188 for (i
= 1; i
< nr
; i
++) {
189 sp_setup_line( setup
,
190 get_vert(vertex_buffer
, indices
[i
-1], stride
),
191 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
195 case PIPE_PRIM_LINE_LOOP
:
196 for (i
= 1; i
< nr
; i
++) {
197 sp_setup_line( setup
,
198 get_vert(vertex_buffer
, indices
[i
-1], stride
),
199 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
202 sp_setup_line( setup
,
203 get_vert(vertex_buffer
, indices
[nr
-1], stride
),
204 get_vert(vertex_buffer
, indices
[0], stride
) );
208 case PIPE_PRIM_TRIANGLES
:
209 for (i
= 2; i
< nr
; i
+= 3) {
211 get_vert(vertex_buffer
, indices
[i
-2], stride
),
212 get_vert(vertex_buffer
, indices
[i
-1], stride
),
213 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
217 case PIPE_PRIM_TRIANGLE_STRIP
:
218 if (flatshade_first
) {
219 for (i
= 2; i
< nr
; i
+= 1) {
220 /* emit first triangle vertex as first triangle vertex */
222 get_vert(vertex_buffer
, indices
[i
-2], stride
),
223 get_vert(vertex_buffer
, indices
[i
+(i
&1)-1], stride
),
224 get_vert(vertex_buffer
, indices
[i
-(i
&1)], stride
) );
229 for (i
= 2; i
< nr
; i
+= 1) {
230 /* emit last triangle vertex as last triangle vertex */
232 get_vert(vertex_buffer
, indices
[i
+(i
&1)-2], stride
),
233 get_vert(vertex_buffer
, indices
[i
-(i
&1)-1], stride
),
234 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
239 case PIPE_PRIM_TRIANGLE_FAN
:
240 if (flatshade_first
) {
241 for (i
= 2; i
< nr
; i
+= 1) {
242 /* emit first non-spoke vertex as first vertex */
244 get_vert(vertex_buffer
, indices
[i
-1], stride
),
245 get_vert(vertex_buffer
, indices
[i
-0], stride
),
246 get_vert(vertex_buffer
, indices
[0], stride
) );
250 for (i
= 2; i
< nr
; i
+= 1) {
251 /* emit last non-spoke vertex as last vertex */
253 get_vert(vertex_buffer
, indices
[0], stride
),
254 get_vert(vertex_buffer
, indices
[i
-1], stride
),
255 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
260 case PIPE_PRIM_QUADS
:
261 /* GL quads don't follow provoking vertex convention */
262 if (flatshade_first
) {
263 /* emit last quad vertex as first triangle vertex */
264 for (i
= 3; i
< nr
; i
+= 4) {
266 get_vert(vertex_buffer
, indices
[i
-0], stride
),
267 get_vert(vertex_buffer
, indices
[i
-3], stride
),
268 get_vert(vertex_buffer
, indices
[i
-2], stride
) );
271 get_vert(vertex_buffer
, indices
[i
-0], stride
),
272 get_vert(vertex_buffer
, indices
[i
-2], stride
),
273 get_vert(vertex_buffer
, indices
[i
-1], stride
) );
277 /* emit last quad vertex as last triangle vertex */
278 for (i
= 3; i
< nr
; i
+= 4) {
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
) );
285 get_vert(vertex_buffer
, indices
[i
-2], stride
),
286 get_vert(vertex_buffer
, indices
[i
-1], stride
),
287 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
292 case PIPE_PRIM_QUAD_STRIP
:
293 /* GL quad strips don't follow provoking vertex convention */
294 if (flatshade_first
) {
295 /* emit last quad vertex as first triangle vertex */
296 for (i
= 3; i
< nr
; i
+= 2) {
298 get_vert(vertex_buffer
, indices
[i
-0], stride
),
299 get_vert(vertex_buffer
, indices
[i
-3], stride
),
300 get_vert(vertex_buffer
, indices
[i
-2], stride
) );
302 get_vert(vertex_buffer
, indices
[i
-0], stride
),
303 get_vert(vertex_buffer
, indices
[i
-1], stride
),
304 get_vert(vertex_buffer
, indices
[i
-3], stride
) );
308 /* emit last quad vertex as last triangle vertex */
309 for (i
= 3; i
< nr
; i
+= 2) {
311 get_vert(vertex_buffer
, indices
[i
-3], stride
),
312 get_vert(vertex_buffer
, indices
[i
-2], stride
),
313 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
315 get_vert(vertex_buffer
, indices
[i
-1], stride
),
316 get_vert(vertex_buffer
, indices
[i
-3], stride
),
317 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
322 case PIPE_PRIM_POLYGON
:
323 /* Almost same as tri fan but the _first_ vertex specifies the flat
326 if (flatshade_first
) {
327 /* emit first polygon vertex as first triangle vertex */
328 for (i
= 2; i
< nr
; i
+= 1) {
330 get_vert(vertex_buffer
, indices
[0], stride
),
331 get_vert(vertex_buffer
, indices
[i
-1], stride
),
332 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
336 /* emit first polygon vertex as last triangle vertex */
337 for (i
= 2; i
< nr
; i
+= 1) {
339 get_vert(vertex_buffer
, indices
[i
-1], stride
),
340 get_vert(vertex_buffer
, indices
[i
-0], stride
),
341 get_vert(vertex_buffer
, indices
[0], stride
) );
353 * This function is hit when the draw module is working in pass-through mode.
354 * It's up to us to convert the vertex array into point/line/tri prims.
357 sp_vbuf_draw_arrays(struct vbuf_render
*vbr
, uint start
, uint nr
)
359 struct softpipe_vbuf_render
*cvbr
= softpipe_vbuf_render(vbr
);
360 struct softpipe_context
*softpipe
= cvbr
->softpipe
;
361 struct setup_context
*setup
= cvbr
->setup
;
362 const unsigned stride
= softpipe
->vertex_info_vbuf
.size
* sizeof(float);
363 const void *vertex_buffer
=
364 (void *) get_vert(cvbr
->vertex_buffer
, start
, stride
);
365 const boolean flatshade_first
= softpipe
->rasterizer
->flatshade_first
;
368 switch (cvbr
->prim
) {
369 case PIPE_PRIM_POINTS
:
370 for (i
= 0; i
< nr
; i
++) {
371 sp_setup_point( setup
,
372 get_vert(vertex_buffer
, i
-0, stride
) );
376 case PIPE_PRIM_LINES
:
377 for (i
= 1; i
< nr
; i
+= 2) {
378 sp_setup_line( setup
,
379 get_vert(vertex_buffer
, i
-1, stride
),
380 get_vert(vertex_buffer
, i
-0, stride
) );
384 case PIPE_PRIM_LINE_STRIP
:
385 for (i
= 1; i
< nr
; i
++) {
386 sp_setup_line( setup
,
387 get_vert(vertex_buffer
, i
-1, stride
),
388 get_vert(vertex_buffer
, i
-0, stride
) );
392 case PIPE_PRIM_LINE_LOOP
:
393 for (i
= 1; i
< nr
; i
++) {
394 sp_setup_line( setup
,
395 get_vert(vertex_buffer
, i
-1, stride
),
396 get_vert(vertex_buffer
, i
-0, stride
) );
399 sp_setup_line( setup
,
400 get_vert(vertex_buffer
, nr
-1, stride
),
401 get_vert(vertex_buffer
, 0, stride
) );
405 case PIPE_PRIM_TRIANGLES
:
406 for (i
= 2; i
< nr
; i
+= 3) {
408 get_vert(vertex_buffer
, i
-2, stride
),
409 get_vert(vertex_buffer
, i
-1, stride
),
410 get_vert(vertex_buffer
, i
-0, stride
) );
414 case PIPE_PRIM_TRIANGLE_STRIP
:
415 if (flatshade_first
) {
416 for (i
= 2; i
< nr
; i
++) {
417 /* emit first triangle vertex as first triangle vertex */
419 get_vert(vertex_buffer
, i
-2, stride
),
420 get_vert(vertex_buffer
, i
+(i
&1)-1, stride
),
421 get_vert(vertex_buffer
, i
-(i
&1), stride
) );
425 for (i
= 2; i
< nr
; i
++) {
426 /* emit last triangle vertex as last triangle vertex */
428 get_vert(vertex_buffer
, i
+(i
&1)-2, stride
),
429 get_vert(vertex_buffer
, i
-(i
&1)-1, stride
),
430 get_vert(vertex_buffer
, i
-0, stride
) );
435 case PIPE_PRIM_TRIANGLE_FAN
:
436 if (flatshade_first
) {
437 for (i
= 2; i
< nr
; i
+= 1) {
438 /* emit first non-spoke vertex as first vertex */
440 get_vert(vertex_buffer
, i
-1, stride
),
441 get_vert(vertex_buffer
, i
-0, stride
),
442 get_vert(vertex_buffer
, 0, stride
) );
446 for (i
= 2; i
< nr
; i
+= 1) {
447 /* emit last non-spoke vertex as last vertex */
449 get_vert(vertex_buffer
, 0, stride
),
450 get_vert(vertex_buffer
, i
-1, stride
),
451 get_vert(vertex_buffer
, i
-0, stride
) );
456 case PIPE_PRIM_QUADS
:
457 /* GL quads don't follow provoking vertex convention */
458 if (flatshade_first
) {
459 /* emit last quad vertex as first triangle vertex */
460 for (i
= 3; i
< nr
; i
+= 4) {
462 get_vert(vertex_buffer
, i
-0, stride
),
463 get_vert(vertex_buffer
, i
-3, stride
),
464 get_vert(vertex_buffer
, i
-2, stride
) );
466 get_vert(vertex_buffer
, i
-0, stride
),
467 get_vert(vertex_buffer
, i
-2, stride
),
468 get_vert(vertex_buffer
, i
-1, stride
) );
472 /* emit last quad vertex as last triangle vertex */
473 for (i
= 3; i
< nr
; i
+= 4) {
475 get_vert(vertex_buffer
, i
-3, stride
),
476 get_vert(vertex_buffer
, i
-2, stride
),
477 get_vert(vertex_buffer
, i
-0, stride
) );
479 get_vert(vertex_buffer
, i
-2, stride
),
480 get_vert(vertex_buffer
, i
-1, stride
),
481 get_vert(vertex_buffer
, i
-0, stride
) );
486 case PIPE_PRIM_QUAD_STRIP
:
487 /* GL quad strips don't follow provoking vertex convention */
488 if (flatshade_first
) {
489 /* emit last quad vertex as first triangle vertex */
490 for (i
= 3; i
< nr
; i
+= 2) {
492 get_vert(vertex_buffer
, i
-0, stride
),
493 get_vert(vertex_buffer
, i
-3, stride
),
494 get_vert(vertex_buffer
, i
-2, stride
) );
496 get_vert(vertex_buffer
, i
-0, stride
),
497 get_vert(vertex_buffer
, i
-1, stride
),
498 get_vert(vertex_buffer
, i
-3, stride
) );
502 /* emit last quad vertex as last triangle vertex */
503 for (i
= 3; i
< nr
; i
+= 2) {
505 get_vert(vertex_buffer
, i
-3, stride
),
506 get_vert(vertex_buffer
, i
-2, stride
),
507 get_vert(vertex_buffer
, i
-0, stride
) );
509 get_vert(vertex_buffer
, i
-1, stride
),
510 get_vert(vertex_buffer
, i
-3, stride
),
511 get_vert(vertex_buffer
, i
-0, stride
) );
516 case PIPE_PRIM_POLYGON
:
517 /* Almost same as tri fan but the _first_ vertex specifies the flat
520 if (flatshade_first
) {
521 /* emit first polygon vertex as first triangle vertex */
522 for (i
= 2; i
< nr
; i
+= 1) {
524 get_vert(vertex_buffer
, 0, stride
),
525 get_vert(vertex_buffer
, i
-1, stride
),
526 get_vert(vertex_buffer
, i
-0, stride
) );
530 /* emit first polygon vertex as last triangle vertex */
531 for (i
= 2; i
< nr
; i
+= 1) {
533 get_vert(vertex_buffer
, i
-1, stride
),
534 get_vert(vertex_buffer
, i
-0, stride
),
535 get_vert(vertex_buffer
, 0, stride
) );
546 sp_vbuf_so_info(struct vbuf_render
*vbr
, uint primitives
, uint vertices
)
548 struct softpipe_vbuf_render
*cvbr
= softpipe_vbuf_render(vbr
);
549 struct softpipe_context
*softpipe
= cvbr
->softpipe
;
552 for (i
= 0; i
< softpipe
->so_target
.num_buffers
; ++i
) {
553 softpipe
->so_target
.so_count
[i
] += vertices
;
556 softpipe
->so_stats
.num_primitives_written
= primitives
;
557 softpipe
->so_stats
.primitives_storage_needed
=
558 vertices
* 4 /*sizeof(float|int32)*/ * 4 /*x,y,z,w*/;
563 sp_vbuf_destroy(struct vbuf_render
*vbr
)
565 struct softpipe_vbuf_render
*cvbr
= softpipe_vbuf_render(vbr
);
566 if (cvbr
->vertex_buffer
)
567 align_free(cvbr
->vertex_buffer
);
568 sp_setup_destroy_context(cvbr
->setup
);
574 * Create the post-transform vertex handler for the given context.
577 sp_create_vbuf_backend(struct softpipe_context
*sp
)
579 struct softpipe_vbuf_render
*cvbr
= CALLOC_STRUCT(softpipe_vbuf_render
);
583 cvbr
->base
.max_indices
= SP_MAX_VBUF_INDEXES
;
584 cvbr
->base
.max_vertex_buffer_bytes
= SP_MAX_VBUF_SIZE
;
586 cvbr
->base
.get_vertex_info
= sp_vbuf_get_vertex_info
;
587 cvbr
->base
.allocate_vertices
= sp_vbuf_allocate_vertices
;
588 cvbr
->base
.map_vertices
= sp_vbuf_map_vertices
;
589 cvbr
->base
.unmap_vertices
= sp_vbuf_unmap_vertices
;
590 cvbr
->base
.set_primitive
= sp_vbuf_set_primitive
;
591 cvbr
->base
.draw_elements
= sp_vbuf_draw_elements
;
592 cvbr
->base
.draw_arrays
= sp_vbuf_draw_arrays
;
593 cvbr
->base
.release_vertices
= sp_vbuf_release_vertices
;
594 cvbr
->base
.set_stream_output_info
= sp_vbuf_so_info
;
595 cvbr
->base
.destroy
= sp_vbuf_destroy
;
599 cvbr
->setup
= sp_setup_create_context(cvbr
->softpipe
);