1 /**************************************************************************
3 * Copyright 2007 VMware, Inc.
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 VMWARE 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
);
148 static INLINE cptrf4
get_vert( const void *vertex_buffer
,
152 return (cptrf4
)((char *)vertex_buffer
+ index
* stride
);
157 * draw elements / indexed primitives
160 sp_vbuf_draw_elements(struct vbuf_render
*vbr
, const ushort
*indices
, uint nr
)
162 struct softpipe_vbuf_render
*cvbr
= softpipe_vbuf_render(vbr
);
163 struct softpipe_context
*softpipe
= cvbr
->softpipe
;
164 const unsigned stride
= softpipe
->vertex_info_vbuf
.size
* sizeof(float);
165 const void *vertex_buffer
= cvbr
->vertex_buffer
;
166 struct setup_context
*setup
= cvbr
->setup
;
167 const boolean flatshade_first
= softpipe
->rasterizer
->flatshade_first
;
170 switch (cvbr
->prim
) {
171 case PIPE_PRIM_POINTS
:
172 for (i
= 0; i
< nr
; i
++) {
173 sp_setup_point( setup
,
174 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
178 case PIPE_PRIM_LINES
:
179 for (i
= 1; i
< nr
; i
+= 2) {
180 sp_setup_line( setup
,
181 get_vert(vertex_buffer
, indices
[i
-1], stride
),
182 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
186 case PIPE_PRIM_LINE_STRIP
:
187 for (i
= 1; i
< nr
; i
++) {
188 sp_setup_line( setup
,
189 get_vert(vertex_buffer
, indices
[i
-1], stride
),
190 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
194 case PIPE_PRIM_LINE_LOOP
:
195 for (i
= 1; i
< nr
; i
++) {
196 sp_setup_line( setup
,
197 get_vert(vertex_buffer
, indices
[i
-1], stride
),
198 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
201 sp_setup_line( setup
,
202 get_vert(vertex_buffer
, indices
[nr
-1], stride
),
203 get_vert(vertex_buffer
, indices
[0], stride
) );
207 case PIPE_PRIM_TRIANGLES
:
208 for (i
= 2; i
< nr
; i
+= 3) {
210 get_vert(vertex_buffer
, indices
[i
-2], stride
),
211 get_vert(vertex_buffer
, indices
[i
-1], stride
),
212 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
216 case PIPE_PRIM_TRIANGLE_STRIP
:
217 if (flatshade_first
) {
218 for (i
= 2; i
< nr
; i
+= 1) {
219 /* emit first triangle vertex as first triangle vertex */
221 get_vert(vertex_buffer
, indices
[i
-2], stride
),
222 get_vert(vertex_buffer
, indices
[i
+(i
&1)-1], stride
),
223 get_vert(vertex_buffer
, indices
[i
-(i
&1)], stride
) );
228 for (i
= 2; i
< nr
; i
+= 1) {
229 /* emit last triangle vertex as last triangle vertex */
231 get_vert(vertex_buffer
, indices
[i
+(i
&1)-2], stride
),
232 get_vert(vertex_buffer
, indices
[i
-(i
&1)-1], stride
),
233 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
238 case PIPE_PRIM_TRIANGLE_FAN
:
239 if (flatshade_first
) {
240 for (i
= 2; i
< nr
; i
+= 1) {
241 /* emit first non-spoke vertex as first vertex */
243 get_vert(vertex_buffer
, indices
[i
-1], stride
),
244 get_vert(vertex_buffer
, indices
[i
-0], stride
),
245 get_vert(vertex_buffer
, indices
[0], stride
) );
249 for (i
= 2; i
< nr
; i
+= 1) {
250 /* emit last non-spoke vertex as last vertex */
252 get_vert(vertex_buffer
, indices
[0], stride
),
253 get_vert(vertex_buffer
, indices
[i
-1], stride
),
254 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
259 case PIPE_PRIM_QUADS
:
260 /* GL quads don't follow provoking vertex convention */
261 if (flatshade_first
) {
262 /* emit last quad vertex as first triangle vertex */
263 for (i
= 3; i
< nr
; i
+= 4) {
265 get_vert(vertex_buffer
, indices
[i
-0], stride
),
266 get_vert(vertex_buffer
, indices
[i
-3], stride
),
267 get_vert(vertex_buffer
, indices
[i
-2], stride
) );
270 get_vert(vertex_buffer
, indices
[i
-0], stride
),
271 get_vert(vertex_buffer
, indices
[i
-2], stride
),
272 get_vert(vertex_buffer
, indices
[i
-1], stride
) );
276 /* emit last quad vertex as last triangle vertex */
277 for (i
= 3; i
< nr
; i
+= 4) {
279 get_vert(vertex_buffer
, indices
[i
-3], stride
),
280 get_vert(vertex_buffer
, indices
[i
-2], stride
),
281 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
284 get_vert(vertex_buffer
, indices
[i
-2], stride
),
285 get_vert(vertex_buffer
, indices
[i
-1], stride
),
286 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
291 case PIPE_PRIM_QUAD_STRIP
:
292 /* GL quad strips don't follow provoking vertex convention */
293 if (flatshade_first
) {
294 /* emit last quad vertex as first triangle vertex */
295 for (i
= 3; i
< nr
; i
+= 2) {
297 get_vert(vertex_buffer
, indices
[i
-0], stride
),
298 get_vert(vertex_buffer
, indices
[i
-3], stride
),
299 get_vert(vertex_buffer
, indices
[i
-2], stride
) );
301 get_vert(vertex_buffer
, indices
[i
-0], stride
),
302 get_vert(vertex_buffer
, indices
[i
-1], stride
),
303 get_vert(vertex_buffer
, indices
[i
-3], stride
) );
307 /* emit last quad vertex as last triangle vertex */
308 for (i
= 3; i
< nr
; i
+= 2) {
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
) );
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
325 if (flatshade_first
) {
326 /* emit first polygon vertex as first triangle vertex */
327 for (i
= 2; i
< nr
; i
+= 1) {
329 get_vert(vertex_buffer
, indices
[0], stride
),
330 get_vert(vertex_buffer
, indices
[i
-1], stride
),
331 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
335 /* emit first polygon vertex as last triangle vertex */
336 for (i
= 2; i
< nr
; i
+= 1) {
338 get_vert(vertex_buffer
, indices
[i
-1], stride
),
339 get_vert(vertex_buffer
, indices
[i
-0], stride
),
340 get_vert(vertex_buffer
, indices
[0], stride
) );
352 * This function is hit when the draw module is working in pass-through mode.
353 * It's up to us to convert the vertex array into point/line/tri prims.
356 sp_vbuf_draw_arrays(struct vbuf_render
*vbr
, uint start
, uint nr
)
358 struct softpipe_vbuf_render
*cvbr
= softpipe_vbuf_render(vbr
);
359 struct softpipe_context
*softpipe
= cvbr
->softpipe
;
360 struct setup_context
*setup
= cvbr
->setup
;
361 const unsigned stride
= softpipe
->vertex_info_vbuf
.size
* sizeof(float);
362 const void *vertex_buffer
=
363 (void *) get_vert(cvbr
->vertex_buffer
, start
, stride
);
364 const boolean flatshade_first
= softpipe
->rasterizer
->flatshade_first
;
367 switch (cvbr
->prim
) {
368 case PIPE_PRIM_POINTS
:
369 for (i
= 0; i
< nr
; i
++) {
370 sp_setup_point( setup
,
371 get_vert(vertex_buffer
, i
-0, stride
) );
375 case PIPE_PRIM_LINES
:
376 for (i
= 1; i
< nr
; i
+= 2) {
377 sp_setup_line( setup
,
378 get_vert(vertex_buffer
, i
-1, stride
),
379 get_vert(vertex_buffer
, i
-0, stride
) );
383 case PIPE_PRIM_LINES_ADJACENCY
:
384 for (i
= 3; i
< nr
; i
+= 4) {
385 sp_setup_line( setup
,
386 get_vert(vertex_buffer
, i
-2, stride
),
387 get_vert(vertex_buffer
, i
-1, stride
) );
391 case PIPE_PRIM_LINE_STRIP
:
392 for (i
= 1; i
< nr
; i
++) {
393 sp_setup_line( setup
,
394 get_vert(vertex_buffer
, i
-1, stride
),
395 get_vert(vertex_buffer
, i
-0, stride
) );
399 case PIPE_PRIM_LINE_STRIP_ADJACENCY
:
400 for (i
= 3; i
< nr
; i
++) {
401 sp_setup_line( setup
,
402 get_vert(vertex_buffer
, i
-2, stride
),
403 get_vert(vertex_buffer
, i
-1, stride
) );
407 case PIPE_PRIM_LINE_LOOP
:
408 for (i
= 1; i
< nr
; i
++) {
409 sp_setup_line( setup
,
410 get_vert(vertex_buffer
, i
-1, stride
),
411 get_vert(vertex_buffer
, i
-0, stride
) );
414 sp_setup_line( setup
,
415 get_vert(vertex_buffer
, nr
-1, stride
),
416 get_vert(vertex_buffer
, 0, stride
) );
420 case PIPE_PRIM_TRIANGLES
:
421 for (i
= 2; i
< nr
; i
+= 3) {
423 get_vert(vertex_buffer
, i
-2, stride
),
424 get_vert(vertex_buffer
, i
-1, stride
),
425 get_vert(vertex_buffer
, i
-0, stride
) );
429 case PIPE_PRIM_TRIANGLES_ADJACENCY
:
430 for (i
= 5; i
< nr
; i
+= 6) {
432 get_vert(vertex_buffer
, i
-5, stride
),
433 get_vert(vertex_buffer
, i
-3, stride
),
434 get_vert(vertex_buffer
, i
-1, stride
) );
438 case PIPE_PRIM_TRIANGLE_STRIP
:
439 if (flatshade_first
) {
440 for (i
= 2; i
< nr
; i
++) {
441 /* emit first triangle vertex as first triangle vertex */
443 get_vert(vertex_buffer
, i
-2, stride
),
444 get_vert(vertex_buffer
, i
+(i
&1)-1, stride
),
445 get_vert(vertex_buffer
, i
-(i
&1), stride
) );
449 for (i
= 2; i
< nr
; i
++) {
450 /* emit last triangle vertex as last triangle vertex */
452 get_vert(vertex_buffer
, i
+(i
&1)-2, stride
),
453 get_vert(vertex_buffer
, i
-(i
&1)-1, stride
),
454 get_vert(vertex_buffer
, i
-0, stride
) );
459 case PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY
:
460 if (flatshade_first
) {
461 for (i
= 5; i
< nr
; i
+= 2) {
462 /* emit first triangle vertex as first triangle vertex */
464 get_vert(vertex_buffer
, i
-5, stride
),
465 get_vert(vertex_buffer
, i
+(i
&1)*2-3, stride
),
466 get_vert(vertex_buffer
, i
-(i
&1)*2-1, stride
) );
470 for (i
= 5; i
< nr
; i
+= 2) {
471 /* emit last triangle vertex as last triangle vertex */
473 get_vert(vertex_buffer
, i
+(i
&1)*2-5, stride
),
474 get_vert(vertex_buffer
, i
-(i
&1)*2-3, stride
),
475 get_vert(vertex_buffer
, i
-1, stride
) );
480 case PIPE_PRIM_TRIANGLE_FAN
:
481 if (flatshade_first
) {
482 for (i
= 2; i
< nr
; i
+= 1) {
483 /* emit first non-spoke vertex as first vertex */
485 get_vert(vertex_buffer
, i
-1, stride
),
486 get_vert(vertex_buffer
, i
-0, stride
),
487 get_vert(vertex_buffer
, 0, stride
) );
491 for (i
= 2; i
< nr
; i
+= 1) {
492 /* emit last non-spoke vertex as last vertex */
494 get_vert(vertex_buffer
, 0, stride
),
495 get_vert(vertex_buffer
, i
-1, stride
),
496 get_vert(vertex_buffer
, i
-0, stride
) );
501 case PIPE_PRIM_QUADS
:
502 /* GL quads don't follow provoking vertex convention */
503 if (flatshade_first
) {
504 /* emit last quad vertex as first triangle vertex */
505 for (i
= 3; i
< nr
; i
+= 4) {
507 get_vert(vertex_buffer
, i
-0, stride
),
508 get_vert(vertex_buffer
, i
-3, stride
),
509 get_vert(vertex_buffer
, i
-2, stride
) );
511 get_vert(vertex_buffer
, i
-0, stride
),
512 get_vert(vertex_buffer
, i
-2, stride
),
513 get_vert(vertex_buffer
, i
-1, stride
) );
517 /* emit last quad vertex as last triangle vertex */
518 for (i
= 3; i
< nr
; i
+= 4) {
520 get_vert(vertex_buffer
, i
-3, stride
),
521 get_vert(vertex_buffer
, i
-2, stride
),
522 get_vert(vertex_buffer
, i
-0, stride
) );
524 get_vert(vertex_buffer
, i
-2, stride
),
525 get_vert(vertex_buffer
, i
-1, stride
),
526 get_vert(vertex_buffer
, i
-0, stride
) );
531 case PIPE_PRIM_QUAD_STRIP
:
532 /* GL quad strips don't follow provoking vertex convention */
533 if (flatshade_first
) {
534 /* emit last quad vertex as first triangle vertex */
535 for (i
= 3; i
< nr
; i
+= 2) {
537 get_vert(vertex_buffer
, i
-0, stride
),
538 get_vert(vertex_buffer
, i
-3, stride
),
539 get_vert(vertex_buffer
, i
-2, stride
) );
541 get_vert(vertex_buffer
, i
-0, stride
),
542 get_vert(vertex_buffer
, i
-1, stride
),
543 get_vert(vertex_buffer
, i
-3, stride
) );
547 /* emit last quad vertex as last triangle vertex */
548 for (i
= 3; i
< nr
; i
+= 2) {
550 get_vert(vertex_buffer
, i
-3, stride
),
551 get_vert(vertex_buffer
, i
-2, stride
),
552 get_vert(vertex_buffer
, i
-0, stride
) );
554 get_vert(vertex_buffer
, i
-1, stride
),
555 get_vert(vertex_buffer
, i
-3, stride
),
556 get_vert(vertex_buffer
, i
-0, stride
) );
561 case PIPE_PRIM_POLYGON
:
562 /* Almost same as tri fan but the _first_ vertex specifies the flat
565 if (flatshade_first
) {
566 /* emit first polygon vertex as first triangle vertex */
567 for (i
= 2; i
< nr
; i
+= 1) {
569 get_vert(vertex_buffer
, 0, stride
),
570 get_vert(vertex_buffer
, i
-1, stride
),
571 get_vert(vertex_buffer
, i
-0, stride
) );
575 /* emit first polygon vertex as last triangle vertex */
576 for (i
= 2; i
< nr
; i
+= 1) {
578 get_vert(vertex_buffer
, i
-1, stride
),
579 get_vert(vertex_buffer
, i
-0, stride
),
580 get_vert(vertex_buffer
, 0, stride
) );
591 * FIXME: it is unclear if primitives_storage_needed (which is generally
592 * the same as pipe query num_primitives_generated) should increase
593 * if SO is disabled for d3d10, but for GL we definitely need to
594 * increase num_primitives_generated and this is only called for active
595 * SO. If it must not increase for d3d10 need to disambiguate the counters
596 * in the driver and do some work for getting correct values, if it should
597 * increase too should call this from outside streamout code.
600 sp_vbuf_so_info(struct vbuf_render
*vbr
, uint primitives
, uint prim_generated
)
602 struct softpipe_vbuf_render
*cvbr
= softpipe_vbuf_render(vbr
);
603 struct softpipe_context
*softpipe
= cvbr
->softpipe
;
605 softpipe
->so_stats
.num_primitives_written
+= primitives
;
606 softpipe
->so_stats
.primitives_storage_needed
+= prim_generated
;
610 sp_vbuf_pipeline_statistics(
611 struct vbuf_render
*vbr
,
612 const struct pipe_query_data_pipeline_statistics
*stats
)
614 struct softpipe_vbuf_render
*cvbr
= softpipe_vbuf_render(vbr
);
615 struct softpipe_context
*softpipe
= cvbr
->softpipe
;
617 softpipe
->pipeline_statistics
.ia_vertices
+=
619 softpipe
->pipeline_statistics
.ia_primitives
+=
620 stats
->ia_primitives
;
621 softpipe
->pipeline_statistics
.vs_invocations
+=
622 stats
->vs_invocations
;
623 softpipe
->pipeline_statistics
.gs_invocations
+=
624 stats
->gs_invocations
;
625 softpipe
->pipeline_statistics
.gs_primitives
+=
626 stats
->gs_primitives
;
627 softpipe
->pipeline_statistics
.c_invocations
+=
628 stats
->c_invocations
;
633 sp_vbuf_destroy(struct vbuf_render
*vbr
)
635 struct softpipe_vbuf_render
*cvbr
= softpipe_vbuf_render(vbr
);
636 if (cvbr
->vertex_buffer
)
637 align_free(cvbr
->vertex_buffer
);
638 sp_setup_destroy_context(cvbr
->setup
);
644 * Create the post-transform vertex handler for the given context.
647 sp_create_vbuf_backend(struct softpipe_context
*sp
)
649 struct softpipe_vbuf_render
*cvbr
= CALLOC_STRUCT(softpipe_vbuf_render
);
653 cvbr
->base
.max_indices
= SP_MAX_VBUF_INDEXES
;
654 cvbr
->base
.max_vertex_buffer_bytes
= SP_MAX_VBUF_SIZE
;
656 cvbr
->base
.get_vertex_info
= sp_vbuf_get_vertex_info
;
657 cvbr
->base
.allocate_vertices
= sp_vbuf_allocate_vertices
;
658 cvbr
->base
.map_vertices
= sp_vbuf_map_vertices
;
659 cvbr
->base
.unmap_vertices
= sp_vbuf_unmap_vertices
;
660 cvbr
->base
.set_primitive
= sp_vbuf_set_primitive
;
661 cvbr
->base
.draw_elements
= sp_vbuf_draw_elements
;
662 cvbr
->base
.draw_arrays
= sp_vbuf_draw_arrays
;
663 cvbr
->base
.release_vertices
= sp_vbuf_release_vertices
;
664 cvbr
->base
.set_stream_output_info
= sp_vbuf_so_info
;
665 cvbr
->base
.pipeline_statistics
= sp_vbuf_pipeline_statistics
;
666 cvbr
->base
.destroy
= sp_vbuf_destroy
;
670 cvbr
->setup
= sp_setup_create_context(cvbr
->softpipe
);