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 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 "lp_context.h"
41 #include "draw/draw_vbuf.h"
42 #include "draw/draw_vertex.h"
43 #include "util/u_memory.h"
46 #define LP_MAX_VBUF_INDEXES 1024
47 #define LP_MAX_VBUF_SIZE 4096
52 static struct lp_setup_context
*
53 lp_setup_context(struct vbuf_render
*vbr
)
55 return (struct lp_setup_context
*) vbr
;
60 static const struct vertex_info
*
61 lp_setup_get_vertex_info(struct vbuf_render
*vbr
)
63 struct lp_setup_context
*setup
= lp_setup_context(vbr
);
65 /* Vertex size/info depends on the latest state.
66 * The draw module may have issued additional state-change commands.
68 lp_setup_update_state(setup
, FALSE
);
70 return setup
->vertex_info
;
75 lp_setup_allocate_vertices(struct vbuf_render
*vbr
,
76 ushort vertex_size
, ushort nr_vertices
)
78 struct lp_setup_context
*setup
= lp_setup_context(vbr
);
79 unsigned size
= vertex_size
* nr_vertices
;
81 if (setup
->vertex_buffer_size
< size
) {
82 align_free(setup
->vertex_buffer
);
83 setup
->vertex_buffer
= align_malloc(size
, 16);
84 setup
->vertex_buffer_size
= size
;
87 setup
->vertex_size
= vertex_size
;
88 setup
->nr_vertices
= nr_vertices
;
90 return setup
->vertex_buffer
!= NULL
;
94 lp_setup_release_vertices(struct vbuf_render
*vbr
)
96 /* keep the old allocation for next time */
100 lp_setup_map_vertices(struct vbuf_render
*vbr
)
102 struct lp_setup_context
*setup
= lp_setup_context(vbr
);
103 return setup
->vertex_buffer
;
107 lp_setup_unmap_vertices(struct vbuf_render
*vbr
,
111 struct lp_setup_context
*setup
= lp_setup_context(vbr
);
112 assert( setup
->vertex_buffer_size
>= (max_index
+1) * setup
->vertex_size
);
118 lp_setup_set_primitive(struct vbuf_render
*vbr
, unsigned prim
)
120 lp_setup_context(vbr
)->prim
= prim
;
123 typedef const float (*const_float4_ptr
)[4];
125 static inline const_float4_ptr
get_vert( const void *vertex_buffer
,
129 return (const_float4_ptr
)((char *)vertex_buffer
+ index
* stride
);
133 * draw elements / indexed primitives
136 lp_setup_draw_elements(struct vbuf_render
*vbr
, const ushort
*indices
, uint nr
)
138 struct lp_setup_context
*setup
= lp_setup_context(vbr
);
139 const unsigned stride
= setup
->vertex_info
->size
* sizeof(float);
140 const void *vertex_buffer
= setup
->vertex_buffer
;
141 const boolean flatshade_first
= setup
->flatshade_first
;
144 assert(setup
->setup
.variant
);
146 if (!lp_setup_update_state(setup
, TRUE
))
149 switch (setup
->prim
) {
150 case PIPE_PRIM_POINTS
:
151 for (i
= 0; i
< nr
; i
++) {
153 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
157 case PIPE_PRIM_LINES
:
158 for (i
= 1; i
< nr
; i
+= 2) {
160 get_vert(vertex_buffer
, indices
[i
-1], stride
),
161 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
165 case PIPE_PRIM_LINE_STRIP
:
166 for (i
= 1; i
< nr
; i
++) {
168 get_vert(vertex_buffer
, indices
[i
-1], stride
),
169 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
173 case PIPE_PRIM_LINE_LOOP
:
174 for (i
= 1; i
< nr
; i
++) {
176 get_vert(vertex_buffer
, indices
[i
-1], stride
),
177 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
181 get_vert(vertex_buffer
, indices
[nr
-1], stride
),
182 get_vert(vertex_buffer
, indices
[0], stride
) );
186 case PIPE_PRIM_TRIANGLES
:
187 for (i
= 2; i
< nr
; i
+= 3) {
188 setup
->triangle( setup
,
189 get_vert(vertex_buffer
, indices
[i
-2], stride
),
190 get_vert(vertex_buffer
, indices
[i
-1], stride
),
191 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
195 case PIPE_PRIM_TRIANGLE_STRIP
:
196 if (flatshade_first
) {
197 for (i
= 2; i
< nr
; i
+= 1) {
198 /* emit first triangle vertex as first triangle vertex */
199 setup
->triangle( setup
,
200 get_vert(vertex_buffer
, indices
[i
-2], stride
),
201 get_vert(vertex_buffer
, indices
[i
+(i
&1)-1], stride
),
202 get_vert(vertex_buffer
, indices
[i
-(i
&1)], stride
) );
207 for (i
= 2; i
< nr
; i
+= 1) {
208 /* emit last triangle vertex as last triangle vertex */
209 setup
->triangle( setup
,
210 get_vert(vertex_buffer
, indices
[i
+(i
&1)-2], stride
),
211 get_vert(vertex_buffer
, indices
[i
-(i
&1)-1], stride
),
212 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
217 case PIPE_PRIM_TRIANGLE_FAN
:
218 if (flatshade_first
) {
219 for (i
= 2; i
< nr
; i
+= 1) {
220 /* emit first non-spoke vertex as first vertex */
221 setup
->triangle( setup
,
222 get_vert(vertex_buffer
, indices
[i
-1], stride
),
223 get_vert(vertex_buffer
, indices
[i
-0], stride
),
224 get_vert(vertex_buffer
, indices
[0], stride
) );
228 for (i
= 2; i
< nr
; i
+= 1) {
229 /* emit last non-spoke vertex as last vertex */
230 setup
->triangle( setup
,
231 get_vert(vertex_buffer
, indices
[0], stride
),
232 get_vert(vertex_buffer
, indices
[i
-1], stride
),
233 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
238 case PIPE_PRIM_QUADS
:
239 /* GL quads don't follow provoking vertex convention */
240 if (flatshade_first
) {
241 /* emit last quad vertex as first triangle vertex */
242 for (i
= 3; i
< nr
; i
+= 4) {
243 setup
->triangle( setup
,
244 get_vert(vertex_buffer
, indices
[i
-0], stride
),
245 get_vert(vertex_buffer
, indices
[i
-3], stride
),
246 get_vert(vertex_buffer
, indices
[i
-2], stride
) );
248 setup
->triangle( setup
,
249 get_vert(vertex_buffer
, indices
[i
-0], stride
),
250 get_vert(vertex_buffer
, indices
[i
-2], stride
),
251 get_vert(vertex_buffer
, indices
[i
-1], stride
) );
255 /* emit last quad vertex as last triangle vertex */
256 for (i
= 3; i
< nr
; i
+= 4) {
257 setup
->triangle( setup
,
258 get_vert(vertex_buffer
, indices
[i
-3], stride
),
259 get_vert(vertex_buffer
, indices
[i
-2], stride
),
260 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
262 setup
->triangle( setup
,
263 get_vert(vertex_buffer
, indices
[i
-2], stride
),
264 get_vert(vertex_buffer
, indices
[i
-1], stride
),
265 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
270 case PIPE_PRIM_QUAD_STRIP
:
271 /* GL quad strips don't follow provoking vertex convention */
272 if (flatshade_first
) {
273 /* emit last quad vertex as first triangle vertex */
274 for (i
= 3; i
< nr
; i
+= 2) {
275 setup
->triangle( setup
,
276 get_vert(vertex_buffer
, indices
[i
-0], stride
),
277 get_vert(vertex_buffer
, indices
[i
-3], stride
),
278 get_vert(vertex_buffer
, indices
[i
-2], stride
) );
279 setup
->triangle( setup
,
280 get_vert(vertex_buffer
, indices
[i
-0], stride
),
281 get_vert(vertex_buffer
, indices
[i
-1], stride
),
282 get_vert(vertex_buffer
, indices
[i
-3], stride
) );
286 /* emit last quad vertex as last triangle vertex */
287 for (i
= 3; i
< nr
; i
+= 2) {
288 setup
->triangle( setup
,
289 get_vert(vertex_buffer
, indices
[i
-3], stride
),
290 get_vert(vertex_buffer
, indices
[i
-2], stride
),
291 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
292 setup
->triangle( setup
,
293 get_vert(vertex_buffer
, indices
[i
-1], stride
),
294 get_vert(vertex_buffer
, indices
[i
-3], stride
),
295 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
300 case PIPE_PRIM_POLYGON
:
301 /* Almost same as tri fan but the _first_ vertex specifies the flat
304 if (flatshade_first
) {
305 /* emit first polygon vertex as first triangle vertex */
306 for (i
= 2; i
< nr
; i
+= 1) {
307 setup
->triangle( setup
,
308 get_vert(vertex_buffer
, indices
[0], stride
),
309 get_vert(vertex_buffer
, indices
[i
-1], stride
),
310 get_vert(vertex_buffer
, indices
[i
-0], stride
) );
314 /* emit first polygon vertex as last triangle vertex */
315 for (i
= 2; i
< nr
; i
+= 1) {
316 setup
->triangle( setup
,
317 get_vert(vertex_buffer
, indices
[i
-1], stride
),
318 get_vert(vertex_buffer
, indices
[i
-0], stride
),
319 get_vert(vertex_buffer
, indices
[0], stride
) );
331 * This function is hit when the draw module is working in pass-through mode.
332 * It's up to us to convert the vertex array into point/line/tri prims.
335 lp_setup_draw_arrays(struct vbuf_render
*vbr
, uint start
, uint nr
)
337 struct lp_setup_context
*setup
= lp_setup_context(vbr
);
338 const unsigned stride
= setup
->vertex_info
->size
* sizeof(float);
339 const void *vertex_buffer
=
340 (void *) get_vert(setup
->vertex_buffer
, start
, stride
);
341 const boolean flatshade_first
= setup
->flatshade_first
;
344 if (!lp_setup_update_state(setup
, TRUE
))
347 switch (setup
->prim
) {
348 case PIPE_PRIM_POINTS
:
349 for (i
= 0; i
< nr
; i
++) {
351 get_vert(vertex_buffer
, i
-0, stride
) );
355 case PIPE_PRIM_LINES
:
356 for (i
= 1; i
< nr
; i
+= 2) {
358 get_vert(vertex_buffer
, i
-1, stride
),
359 get_vert(vertex_buffer
, i
-0, stride
) );
363 case PIPE_PRIM_LINE_STRIP
:
364 for (i
= 1; i
< nr
; i
++) {
366 get_vert(vertex_buffer
, i
-1, stride
),
367 get_vert(vertex_buffer
, i
-0, stride
) );
371 case PIPE_PRIM_LINE_LOOP
:
372 for (i
= 1; i
< nr
; i
++) {
374 get_vert(vertex_buffer
, i
-1, stride
),
375 get_vert(vertex_buffer
, i
-0, stride
) );
379 get_vert(vertex_buffer
, nr
-1, stride
),
380 get_vert(vertex_buffer
, 0, stride
) );
384 case PIPE_PRIM_TRIANGLES
:
385 for (i
= 2; i
< nr
; i
+= 3) {
386 setup
->triangle( setup
,
387 get_vert(vertex_buffer
, i
-2, stride
),
388 get_vert(vertex_buffer
, i
-1, stride
),
389 get_vert(vertex_buffer
, i
-0, stride
) );
393 case PIPE_PRIM_TRIANGLE_STRIP
:
394 if (flatshade_first
) {
395 for (i
= 2; i
< nr
; i
++) {
396 /* emit first triangle vertex as first triangle vertex */
397 setup
->triangle( setup
,
398 get_vert(vertex_buffer
, i
-2, stride
),
399 get_vert(vertex_buffer
, i
+(i
&1)-1, stride
),
400 get_vert(vertex_buffer
, i
-(i
&1), stride
) );
404 for (i
= 2; i
< nr
; i
++) {
405 /* emit last triangle vertex as last triangle vertex */
406 setup
->triangle( setup
,
407 get_vert(vertex_buffer
, i
+(i
&1)-2, stride
),
408 get_vert(vertex_buffer
, i
-(i
&1)-1, stride
),
409 get_vert(vertex_buffer
, i
-0, stride
) );
414 case PIPE_PRIM_TRIANGLE_FAN
:
415 if (flatshade_first
) {
416 for (i
= 2; i
< nr
; i
+= 1) {
417 /* emit first non-spoke vertex as first vertex */
418 setup
->triangle( setup
,
419 get_vert(vertex_buffer
, i
-1, stride
),
420 get_vert(vertex_buffer
, i
-0, stride
),
421 get_vert(vertex_buffer
, 0, stride
) );
425 for (i
= 2; i
< nr
; i
+= 1) {
426 /* emit last non-spoke vertex as last vertex */
427 setup
->triangle( setup
,
428 get_vert(vertex_buffer
, 0, stride
),
429 get_vert(vertex_buffer
, i
-1, stride
),
430 get_vert(vertex_buffer
, i
-0, stride
) );
435 case PIPE_PRIM_QUADS
:
436 /* GL quads don't follow provoking vertex convention */
437 if (flatshade_first
) {
438 /* emit last quad vertex as first triangle vertex */
439 for (i
= 3; i
< nr
; i
+= 4) {
440 setup
->triangle( setup
,
441 get_vert(vertex_buffer
, i
-0, stride
),
442 get_vert(vertex_buffer
, i
-3, stride
),
443 get_vert(vertex_buffer
, i
-2, stride
) );
444 setup
->triangle( setup
,
445 get_vert(vertex_buffer
, i
-0, stride
),
446 get_vert(vertex_buffer
, i
-2, stride
),
447 get_vert(vertex_buffer
, i
-1, stride
) );
451 /* emit last quad vertex as last triangle vertex */
452 for (i
= 3; i
< nr
; i
+= 4) {
453 setup
->triangle( setup
,
454 get_vert(vertex_buffer
, i
-3, stride
),
455 get_vert(vertex_buffer
, i
-2, stride
),
456 get_vert(vertex_buffer
, i
-0, stride
) );
457 setup
->triangle( setup
,
458 get_vert(vertex_buffer
, i
-2, stride
),
459 get_vert(vertex_buffer
, i
-1, stride
),
460 get_vert(vertex_buffer
, i
-0, stride
) );
465 case PIPE_PRIM_QUAD_STRIP
:
466 /* GL quad strips don't follow provoking vertex convention */
467 if (flatshade_first
) {
468 /* emit last quad vertex as first triangle vertex */
469 for (i
= 3; i
< nr
; i
+= 2) {
470 setup
->triangle( setup
,
471 get_vert(vertex_buffer
, i
-0, stride
),
472 get_vert(vertex_buffer
, i
-3, stride
),
473 get_vert(vertex_buffer
, i
-2, stride
) );
474 setup
->triangle( setup
,
475 get_vert(vertex_buffer
, i
-0, stride
),
476 get_vert(vertex_buffer
, i
-1, stride
),
477 get_vert(vertex_buffer
, i
-3, stride
) );
481 /* emit last quad vertex as last triangle vertex */
482 for (i
= 3; i
< nr
; i
+= 2) {
483 setup
->triangle( setup
,
484 get_vert(vertex_buffer
, i
-3, stride
),
485 get_vert(vertex_buffer
, i
-2, stride
),
486 get_vert(vertex_buffer
, i
-0, stride
) );
487 setup
->triangle( setup
,
488 get_vert(vertex_buffer
, i
-1, stride
),
489 get_vert(vertex_buffer
, i
-3, stride
),
490 get_vert(vertex_buffer
, i
-0, stride
) );
495 case PIPE_PRIM_POLYGON
:
496 /* Almost same as tri fan but the _first_ vertex specifies the flat
499 if (flatshade_first
) {
500 /* emit first polygon vertex as first triangle vertex */
501 for (i
= 2; i
< nr
; i
+= 1) {
502 setup
->triangle( setup
,
503 get_vert(vertex_buffer
, 0, stride
),
504 get_vert(vertex_buffer
, i
-1, stride
),
505 get_vert(vertex_buffer
, i
-0, stride
) );
509 /* emit first polygon vertex as last triangle vertex */
510 for (i
= 2; i
< nr
; i
+= 1) {
511 setup
->triangle( setup
,
512 get_vert(vertex_buffer
, i
-1, stride
),
513 get_vert(vertex_buffer
, i
-0, stride
),
514 get_vert(vertex_buffer
, 0, stride
) );
527 lp_setup_vbuf_destroy(struct vbuf_render
*vbr
)
529 struct lp_setup_context
*setup
= lp_setup_context(vbr
);
530 if (setup
->vertex_buffer
) {
531 align_free(setup
->vertex_buffer
);
532 setup
->vertex_buffer
= NULL
;
534 lp_setup_destroy(setup
);
538 * FIXME: it is unclear if primitives_storage_needed (which is generally
539 * the same as pipe query num_primitives_generated) should increase
540 * if SO is disabled for d3d10, but for GL we definitely need to
541 * increase num_primitives_generated and this is only called for active
542 * SO. If it must not increase for d3d10 need to disambiguate the counters
543 * in the driver and do some work for getting correct values, if it should
544 * increase too should call this from outside streamout code.
547 lp_setup_so_info(struct vbuf_render
*vbr
, uint primitives
, uint prim_generated
)
549 struct lp_setup_context
*setup
= lp_setup_context(vbr
);
550 struct llvmpipe_context
*lp
= llvmpipe_context(setup
->pipe
);
552 lp
->so_stats
.num_primitives_written
+= primitives
;
553 lp
->so_stats
.primitives_storage_needed
+= prim_generated
;
557 lp_setup_pipeline_statistics(
558 struct vbuf_render
*vbr
,
559 const struct pipe_query_data_pipeline_statistics
*stats
)
561 struct lp_setup_context
*setup
= lp_setup_context(vbr
);
562 struct llvmpipe_context
*llvmpipe
= llvmpipe_context(setup
->pipe
);
564 llvmpipe
->pipeline_statistics
.ia_vertices
+=
566 llvmpipe
->pipeline_statistics
.ia_primitives
+=
567 stats
->ia_primitives
;
568 llvmpipe
->pipeline_statistics
.vs_invocations
+=
569 stats
->vs_invocations
;
570 llvmpipe
->pipeline_statistics
.gs_invocations
+=
571 stats
->gs_invocations
;
572 llvmpipe
->pipeline_statistics
.gs_primitives
+=
573 stats
->gs_primitives
;
574 if (!llvmpipe_rasterization_disabled(llvmpipe
)) {
575 llvmpipe
->pipeline_statistics
.c_invocations
+=
576 stats
->c_invocations
;
578 llvmpipe
->pipeline_statistics
.c_invocations
= 0;
583 * Create the post-transform vertex handler for the given context.
586 lp_setup_init_vbuf(struct lp_setup_context
*setup
)
588 setup
->base
.max_indices
= LP_MAX_VBUF_INDEXES
;
589 setup
->base
.max_vertex_buffer_bytes
= LP_MAX_VBUF_SIZE
;
591 setup
->base
.get_vertex_info
= lp_setup_get_vertex_info
;
592 setup
->base
.allocate_vertices
= lp_setup_allocate_vertices
;
593 setup
->base
.map_vertices
= lp_setup_map_vertices
;
594 setup
->base
.unmap_vertices
= lp_setup_unmap_vertices
;
595 setup
->base
.set_primitive
= lp_setup_set_primitive
;
596 setup
->base
.draw_elements
= lp_setup_draw_elements
;
597 setup
->base
.draw_arrays
= lp_setup_draw_arrays
;
598 setup
->base
.release_vertices
= lp_setup_release_vertices
;
599 setup
->base
.destroy
= lp_setup_vbuf_destroy
;
600 setup
->base
.set_stream_output_info
= lp_setup_so_info
;
601 setup
->base
.pipeline_statistics
= lp_setup_pipeline_statistics
;