1 /**************************************************************************
2 *
3 * Copyright 2007 VMware, Inc.
4 * All Rights Reserved.
5 *
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:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
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.
25 *
26 **************************************************************************/
27
28 /**
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.
33 *
34 * Authors
35 * Brian Paul
36 */
37
38
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"
44 #include "util/u_math.h"
45 #include "lp_state_fs.h"
46 #include "lp_perf.h"
47
48
49 /* It should be a multiple of both 6 and 4 (in other words, a multiple of 12)
50 * to ensure draw splits between a whole number of rectangles.
51 */
52 #define LP_MAX_VBUF_INDEXES 1020
53
54 #define LP_MAX_VBUF_SIZE 4096
55
56
57
58 /** cast wrapper */
59 static struct lp_setup_context *
lp_setup_context(struct vbuf_render * vbr)60 lp_setup_context(struct vbuf_render *vbr)
61 {
62 return (struct lp_setup_context *) vbr;
63 }
64
65
66
67 static const struct vertex_info *
lp_setup_get_vertex_info(struct vbuf_render * vbr)68 lp_setup_get_vertex_info(struct vbuf_render *vbr)
69 {
70 struct lp_setup_context *setup = lp_setup_context(vbr);
71
72 /* Vertex size/info depends on the latest state.
73 * The draw module may have issued additional state-change commands.
74 */
75 lp_setup_update_state(setup, false);
76
77 return setup->vertex_info;
78 }
79
80
81 static bool
lp_setup_allocate_vertices(struct vbuf_render * vbr,uint16_t vertex_size,uint16_t nr_vertices)82 lp_setup_allocate_vertices(struct vbuf_render *vbr,
83 uint16_t vertex_size, uint16_t nr_vertices)
84 {
85 struct lp_setup_context *setup = lp_setup_context(vbr);
86 unsigned size = vertex_size * nr_vertices;
87
88 if (setup->vertex_buffer_size < size) {
89 align_free(setup->vertex_buffer);
90 setup->vertex_buffer = align_malloc(size, 16);
91 setup->vertex_buffer_size = size;
92 }
93
94 setup->vertex_size = vertex_size;
95 setup->nr_vertices = nr_vertices;
96
97 return setup->vertex_buffer != NULL;
98 }
99
100
101 static void
lp_setup_release_vertices(struct vbuf_render * vbr)102 lp_setup_release_vertices(struct vbuf_render *vbr)
103 {
104 /* keep the old allocation for next time */
105 }
106
107
108 static void *
lp_setup_map_vertices(struct vbuf_render * vbr)109 lp_setup_map_vertices(struct vbuf_render *vbr)
110 {
111 struct lp_setup_context *setup = lp_setup_context(vbr);
112 return setup->vertex_buffer;
113 }
114
115
116 static void
lp_setup_unmap_vertices(struct vbuf_render * vbr,uint16_t min_index,uint16_t max_index)117 lp_setup_unmap_vertices(struct vbuf_render *vbr,
118 uint16_t min_index,
119 uint16_t max_index)
120 {
121 ASSERTED struct lp_setup_context *setup = lp_setup_context(vbr);
122 assert(setup->vertex_buffer_size >= (max_index+1) * setup->vertex_size);
123 /* do nothing */
124 }
125
126
127 static void
lp_setup_set_primitive(struct vbuf_render * vbr,enum mesa_prim prim)128 lp_setup_set_primitive(struct vbuf_render *vbr, enum mesa_prim prim)
129 {
130 lp_setup_context(vbr)->prim = prim;
131 }
132
133
134 static void
lp_setup_set_view_index(struct vbuf_render * vbr,unsigned view_index)135 lp_setup_set_view_index(struct vbuf_render *vbr, unsigned view_index)
136 {
137 lp_setup_context(vbr)->view_index = view_index;
138 }
139
140
141 typedef const float (*const_float4_ptr)[4];
142
143
144 static inline const_float4_ptr
get_vert(const void * vertex_buffer,int index,int stride)145 get_vert(const void *vertex_buffer, int index, int stride)
146 {
147 return (const_float4_ptr)((char *)vertex_buffer + index * stride);
148 }
149
150
151 static inline void
rect(struct lp_setup_context * setup,const float (* v0)[4],const float (* v1)[4],const float (* v2)[4],const float (* v3)[4],const float (* v4)[4],const float (* v5)[4])152 rect(struct lp_setup_context *setup,
153 const float (*v0)[4],
154 const float (*v1)[4],
155 const float (*v2)[4],
156 const float (*v3)[4],
157 const float (*v4)[4],
158 const float (*v5)[4])
159 {
160 if (!setup->permit_linear_rasterizer ||
161 !setup->rect(setup, v0, v1, v2, v3, v4, v5)) {
162 setup->triangle(setup, v0, v1, v2);
163 setup->triangle(setup, v3, v4, v5);
164 }
165 }
166
167
168 /**
169 * draw elements / indexed primitives
170 */
171 static void
lp_setup_draw_elements(struct vbuf_render * vbr,const uint16_t * indices,uint nr)172 lp_setup_draw_elements(struct vbuf_render *vbr, const uint16_t *indices, uint nr)
173 {
174 struct lp_setup_context *setup = lp_setup_context(vbr);
175 const unsigned stride = setup->vertex_info->size * sizeof(float);
176 const void *vertex_buffer = setup->vertex_buffer;
177 const bool flatshade_first = setup->flatshade_first;
178 unsigned i;
179
180 assert(setup->setup.variant);
181
182 if (!lp_setup_update_state(setup, true))
183 return;
184
185 const bool uses_constant_interp =
186 setup->setup.variant->key.uses_constant_interp;
187
188 switch (setup->prim) {
189 case MESA_PRIM_POINTS:
190 for (i = 0; i < nr; i++) {
191 setup->point(setup,
192 get_vert(vertex_buffer, indices[i-0], stride));
193 }
194 break;
195
196 case MESA_PRIM_LINES:
197 for (i = 1; i < nr; i += 2) {
198 setup->line(setup,
199 get_vert(vertex_buffer, indices[i-1], stride),
200 get_vert(vertex_buffer, indices[i-0], stride));
201 }
202 break;
203
204 case MESA_PRIM_LINE_STRIP:
205 for (i = 1; i < nr; i ++) {
206 setup->line(setup,
207 get_vert(vertex_buffer, indices[i-1], stride),
208 get_vert(vertex_buffer, indices[i-0], stride));
209 }
210 break;
211
212 case MESA_PRIM_LINE_LOOP:
213 for (i = 1; i < nr; i ++) {
214 setup->line(setup,
215 get_vert(vertex_buffer, indices[i-1], stride),
216 get_vert(vertex_buffer, indices[i-0], stride));
217 }
218 if (nr) {
219 setup->line(setup,
220 get_vert(vertex_buffer, indices[nr-1], stride),
221 get_vert(vertex_buffer, indices[0], stride));
222 }
223 break;
224
225 case MESA_PRIM_TRIANGLES:
226 if (nr % 6 == 0 && !uses_constant_interp) {
227 for (i = 5; i < nr; i += 6) {
228 rect(setup,
229 get_vert(vertex_buffer, indices[i-5], stride),
230 get_vert(vertex_buffer, indices[i-4], stride),
231 get_vert(vertex_buffer, indices[i-3], stride),
232 get_vert(vertex_buffer, indices[i-2], stride),
233 get_vert(vertex_buffer, indices[i-1], stride),
234 get_vert(vertex_buffer, indices[i-0], stride));
235 }
236 } else {
237 for (i = 2; i < nr; i += 3) {
238 setup->triangle(setup,
239 get_vert(vertex_buffer, indices[i-2], stride),
240 get_vert(vertex_buffer, indices[i-1], stride),
241 get_vert(vertex_buffer, indices[i-0], stride));
242 }
243 }
244 break;
245
246 case MESA_PRIM_TRIANGLE_STRIP:
247 if (flatshade_first) {
248 for (i = 2; i < nr; i += 1) {
249 /* emit first triangle vertex as first triangle vertex */
250 setup->triangle(setup,
251 get_vert(vertex_buffer, indices[i-2], stride),
252 get_vert(vertex_buffer, indices[i+(i&1)-1], stride),
253 get_vert(vertex_buffer, indices[i-(i&1)], stride));
254
255 }
256 } else {
257 for (i = 2; i < nr; i += 1) {
258 /* emit last triangle vertex as last triangle vertex */
259 setup->triangle(setup,
260 get_vert(vertex_buffer, indices[i+(i&1)-2], stride),
261 get_vert(vertex_buffer, indices[i-(i&1)-1], stride),
262 get_vert(vertex_buffer, indices[i-0], stride));
263 }
264 }
265 break;
266
267 case MESA_PRIM_TRIANGLE_FAN:
268 if (flatshade_first) {
269 for (i = 2; i < nr; i += 1) {
270 /* emit first non-spoke vertex as first vertex */
271 setup->triangle(setup,
272 get_vert(vertex_buffer, indices[i-1], stride),
273 get_vert(vertex_buffer, indices[i-0], stride),
274 get_vert(vertex_buffer, indices[0], stride));
275 }
276 } else {
277 for (i = 2; i < nr; i += 1) {
278 /* emit last non-spoke vertex as last vertex */
279 setup->triangle(setup,
280 get_vert(vertex_buffer, indices[0], stride),
281 get_vert(vertex_buffer, indices[i-1], stride),
282 get_vert(vertex_buffer, indices[i-0], stride));
283 }
284 }
285 break;
286
287 case MESA_PRIM_QUADS:
288 /* GL quads don't follow provoking vertex convention */
289 if (flatshade_first) {
290 /* emit last quad vertex as first triangle vertex */
291 for (i = 3; i < nr; i += 4) {
292 setup->triangle(setup,
293 get_vert(vertex_buffer, indices[i-0], stride),
294 get_vert(vertex_buffer, indices[i-3], stride),
295 get_vert(vertex_buffer, indices[i-2], stride));
296
297 setup->triangle(setup,
298 get_vert(vertex_buffer, indices[i-0], stride),
299 get_vert(vertex_buffer, indices[i-2], stride),
300 get_vert(vertex_buffer, indices[i-1], stride));
301 }
302 } else {
303 /* emit last quad vertex as last triangle vertex */
304 for (i = 3; i < nr; i += 4) {
305 setup->triangle(setup,
306 get_vert(vertex_buffer, indices[i-3], stride),
307 get_vert(vertex_buffer, indices[i-2], stride),
308 get_vert(vertex_buffer, indices[i-0], stride));
309
310 setup->triangle(setup,
311 get_vert(vertex_buffer, indices[i-2], stride),
312 get_vert(vertex_buffer, indices[i-1], stride),
313 get_vert(vertex_buffer, indices[i-0], stride));
314 }
315 }
316 break;
317
318 case MESA_PRIM_QUAD_STRIP:
319 /* GL quad strips don't follow provoking vertex convention */
320 if (flatshade_first) {
321 /* emit last quad vertex as first triangle vertex */
322 for (i = 3; i < nr; i += 2) {
323 setup->triangle(setup,
324 get_vert(vertex_buffer, indices[i-0], stride),
325 get_vert(vertex_buffer, indices[i-3], stride),
326 get_vert(vertex_buffer, indices[i-2], stride));
327 setup->triangle(setup,
328 get_vert(vertex_buffer, indices[i-0], stride),
329 get_vert(vertex_buffer, indices[i-1], stride),
330 get_vert(vertex_buffer, indices[i-3], stride));
331 }
332 } else {
333 /* emit last quad vertex as last triangle vertex */
334 for (i = 3; i < nr; i += 2) {
335 setup->triangle(setup,
336 get_vert(vertex_buffer, indices[i-3], stride),
337 get_vert(vertex_buffer, indices[i-2], stride),
338 get_vert(vertex_buffer, indices[i-0], stride));
339 setup->triangle(setup,
340 get_vert(vertex_buffer, indices[i-1], stride),
341 get_vert(vertex_buffer, indices[i-3], stride),
342 get_vert(vertex_buffer, indices[i-0], stride));
343 }
344 }
345 break;
346
347 case MESA_PRIM_POLYGON:
348 /* Almost same as tri fan but the _first_ vertex specifies the flat
349 * shading color.
350 */
351 if (flatshade_first) {
352 /* emit first polygon vertex as first triangle vertex */
353 for (i = 2; i < nr; i += 1) {
354 setup->triangle(setup,
355 get_vert(vertex_buffer, indices[0], stride),
356 get_vert(vertex_buffer, indices[i-1], stride),
357 get_vert(vertex_buffer, indices[i-0], stride));
358 }
359 } else {
360 /* emit first polygon vertex as last triangle vertex */
361 for (i = 2; i < nr; i += 1) {
362 setup->triangle(setup,
363 get_vert(vertex_buffer, indices[i-1], stride),
364 get_vert(vertex_buffer, indices[i-0], stride),
365 get_vert(vertex_buffer, indices[0], stride));
366 }
367 }
368 break;
369
370 default:
371 assert(0);
372 }
373 }
374
375
376 /**
377 * This function is hit when the draw module is working in pass-through mode.
378 * It's up to us to convert the vertex array into point/line/tri prims.
379 */
380 static void
lp_setup_draw_arrays(struct vbuf_render * vbr,uint start,uint nr)381 lp_setup_draw_arrays(struct vbuf_render *vbr, uint start, uint nr)
382 {
383 struct lp_setup_context *setup = lp_setup_context(vbr);
384 const unsigned stride = setup->vertex_info->size * sizeof(float);
385 const void *vertex_buffer =
386 (void *) get_vert(setup->vertex_buffer, start, stride);
387 const bool flatshade_first = setup->flatshade_first;
388 unsigned i;
389
390 if (!lp_setup_update_state(setup, true))
391 return;
392
393 const bool uses_constant_interp =
394 setup->setup.variant->key.uses_constant_interp;
395
396 switch (setup->prim) {
397 case MESA_PRIM_POINTS:
398 for (i = 0; i < nr; i++) {
399 setup->point(setup,
400 get_vert(vertex_buffer, i-0, stride));
401 }
402 break;
403
404 case MESA_PRIM_LINES:
405 for (i = 1; i < nr; i += 2) {
406 setup->line(setup,
407 get_vert(vertex_buffer, i-1, stride),
408 get_vert(vertex_buffer, i-0, stride));
409 }
410 break;
411
412 case MESA_PRIM_LINE_STRIP:
413 for (i = 1; i < nr; i ++) {
414 setup->line(setup,
415 get_vert(vertex_buffer, i-1, stride),
416 get_vert(vertex_buffer, i-0, stride));
417 }
418 break;
419
420 case MESA_PRIM_LINE_LOOP:
421 for (i = 1; i < nr; i ++) {
422 setup->line(setup,
423 get_vert(vertex_buffer, i-1, stride),
424 get_vert(vertex_buffer, i-0, stride));
425 }
426 if (nr) {
427 setup->line(setup,
428 get_vert(vertex_buffer, nr-1, stride),
429 get_vert(vertex_buffer, 0, stride));
430 }
431 break;
432
433 case MESA_PRIM_TRIANGLES:
434 if (nr % 6 == 0 && !uses_constant_interp) {
435 for (i = 5; i < nr; i += 6) {
436 rect(setup,
437 get_vert(vertex_buffer, i-5, stride),
438 get_vert(vertex_buffer, i-4, stride),
439 get_vert(vertex_buffer, i-3, stride),
440 get_vert(vertex_buffer, i-2, stride),
441 get_vert(vertex_buffer, i-1, stride),
442 get_vert(vertex_buffer, i-0, stride));
443 }
444 } else if (!uses_constant_interp &&
445 lp_setup_analyse_triangles(setup, vertex_buffer, stride, nr)) {
446 /* If lp_setup_analyse_triangles() returned true, it also
447 * emitted (setup) the rect or triangles.
448 */
449 } else {
450 for (i = 2; i < nr; i += 3) {
451 setup->triangle(setup,
452 get_vert(vertex_buffer, i-2, stride),
453 get_vert(vertex_buffer, i-1, stride),
454 get_vert(vertex_buffer, i-0, stride));
455 }
456 }
457 break;
458
459 case MESA_PRIM_TRIANGLE_STRIP:
460 if (flatshade_first) {
461 if (!uses_constant_interp) {
462 int j;
463 i = 2;
464 j = 3;
465 while (j < nr) {
466 /* emit first triangle vertex as first triangle vertex */
467 const float (*v0)[4] = get_vert(vertex_buffer, i-2, stride);
468 const float (*v1)[4] = get_vert(vertex_buffer, i+(i&1)-1, stride);
469 const float (*v2)[4] = get_vert(vertex_buffer, i-(i&1), stride);
470 const float (*v3)[4] = get_vert(vertex_buffer, j-2, stride);
471 const float (*v4)[4] = get_vert(vertex_buffer, j+(j&1)-1, stride);
472 const float (*v5)[4] = get_vert(vertex_buffer, j-(j&1), stride);
473 if (setup->permit_linear_rasterizer &&
474 setup->rect(setup, v0, v1, v2, v3, v4, v5)) {
475 i += 2;
476 j += 2;
477 } else {
478 /* emit one triangle, and retry rectangle in the next one */
479 setup->triangle(setup, v0, v1, v2);
480 i += 1;
481 j += 1;
482 }
483 }
484 if (i < nr) {
485 /* emit last triangle */
486 setup->triangle(setup,
487 get_vert(vertex_buffer, i-2, stride),
488 get_vert(vertex_buffer, i+(i&1)-1, stride),
489 get_vert(vertex_buffer, i-(i&1), stride));
490 }
491 } else {
492 for (i = 2; i < nr; i++) {
493 /* emit first triangle vertex as first triangle vertex */
494 setup->triangle(setup,
495 get_vert(vertex_buffer, i-2, stride),
496 get_vert(vertex_buffer, i+(i&1)-1, stride),
497 get_vert(vertex_buffer, i-(i&1), stride));
498 }
499 }
500 } else {
501 for (i = 2; i < nr; i++) {
502 /* emit last triangle vertex as last triangle vertex */
503 setup->triangle(setup,
504 get_vert(vertex_buffer, i+(i&1)-2, stride),
505 get_vert(vertex_buffer, i-(i&1)-1, stride),
506 get_vert(vertex_buffer, i-0, stride));
507 }
508 }
509 break;
510
511 case MESA_PRIM_TRIANGLE_FAN:
512 if (nr == 4 && !uses_constant_interp) {
513 rect(setup,
514 get_vert(vertex_buffer, 0, stride),
515 get_vert(vertex_buffer, 1, stride),
516 get_vert(vertex_buffer, 2, stride),
517 get_vert(vertex_buffer, 0, stride),
518 get_vert(vertex_buffer, 2, stride),
519 get_vert(vertex_buffer, 3, stride));
520 } else if (flatshade_first) {
521 for (i = 2; i < nr; i += 1) {
522 /* emit first non-spoke vertex as first vertex */
523 setup->triangle(setup,
524 get_vert(vertex_buffer, i-1, stride),
525 get_vert(vertex_buffer, i-0, stride),
526 get_vert(vertex_buffer, 0, stride));
527 }
528 } else {
529 for (i = 2; i < nr; i += 1) {
530 /* emit last non-spoke vertex as last vertex */
531 setup->triangle(setup,
532 get_vert(vertex_buffer, 0, stride),
533 get_vert(vertex_buffer, i-1, stride),
534 get_vert(vertex_buffer, i-0, stride));
535 }
536 }
537 break;
538
539 case MESA_PRIM_QUADS:
540 /* GL quads don't follow provoking vertex convention */
541 if (flatshade_first) {
542 /* emit last quad vertex as first triangle vertex */
543 for (i = 3; i < nr; i += 4) {
544 setup->triangle(setup,
545 get_vert(vertex_buffer, i-0, stride),
546 get_vert(vertex_buffer, i-3, stride),
547 get_vert(vertex_buffer, i-2, stride));
548 setup->triangle(setup,
549 get_vert(vertex_buffer, i-0, stride),
550 get_vert(vertex_buffer, i-2, stride),
551 get_vert(vertex_buffer, i-1, stride));
552 }
553 } else {
554 /* emit last quad vertex as last triangle vertex */
555 if (!uses_constant_interp) {
556 for (i = 3; i < nr; i += 4) {
557 rect(setup,
558 get_vert(vertex_buffer, i-3, stride),
559 get_vert(vertex_buffer, i-2, stride),
560 get_vert(vertex_buffer, i-1, stride),
561 get_vert(vertex_buffer, i-3, stride),
562 get_vert(vertex_buffer, i-1, stride),
563 get_vert(vertex_buffer, i-0, stride));
564 }
565 } else {
566 for (i = 3; i < nr; i += 4) {
567 setup->triangle(setup,
568 get_vert(vertex_buffer, i-3, stride),
569 get_vert(vertex_buffer, i-2, stride),
570 get_vert(vertex_buffer, i-0, stride));
571 setup->triangle(setup,
572 get_vert(vertex_buffer, i-2, stride),
573 get_vert(vertex_buffer, i-1, stride),
574 get_vert(vertex_buffer, i-0, stride));
575 }
576 }
577 }
578 break;
579
580 case MESA_PRIM_QUAD_STRIP:
581 /* GL quad strips don't follow provoking vertex convention */
582 if (flatshade_first) {
583 /* emit last quad vertex as first triangle vertex */
584 for (i = 3; i < nr; i += 2) {
585 setup->triangle(setup,
586 get_vert(vertex_buffer, i-0, stride),
587 get_vert(vertex_buffer, i-3, stride),
588 get_vert(vertex_buffer, i-2, stride));
589 setup->triangle(setup,
590 get_vert(vertex_buffer, i-0, stride),
591 get_vert(vertex_buffer, i-1, stride),
592 get_vert(vertex_buffer, i-3, stride));
593 }
594 } else {
595 /* emit last quad vertex as last triangle vertex */
596 for (i = 3; i < nr; i += 2) {
597 setup->triangle(setup,
598 get_vert(vertex_buffer, i-3, stride),
599 get_vert(vertex_buffer, i-2, stride),
600 get_vert(vertex_buffer, i-0, stride));
601 setup->triangle(setup,
602 get_vert(vertex_buffer, i-1, stride),
603 get_vert(vertex_buffer, i-3, stride),
604 get_vert(vertex_buffer, i-0, stride));
605 }
606 }
607 break;
608
609 case MESA_PRIM_POLYGON:
610 /* Almost same as tri fan but the _first_ vertex specifies the flat
611 * shading color.
612 */
613 if (flatshade_first) {
614 /* emit first polygon vertex as first triangle vertex */
615 for (i = 2; i < nr; i += 1) {
616 setup->triangle(setup,
617 get_vert(vertex_buffer, 0, stride),
618 get_vert(vertex_buffer, i-1, stride),
619 get_vert(vertex_buffer, i-0, stride));
620 }
621 } else {
622 /* emit first polygon vertex as last triangle vertex */
623 for (i = 2; i < nr; i += 1) {
624 setup->triangle(setup,
625 get_vert(vertex_buffer, i-1, stride),
626 get_vert(vertex_buffer, i-0, stride),
627 get_vert(vertex_buffer, 0, stride));
628 }
629 }
630 break;
631
632 default:
633 assert(0);
634 }
635 }
636
637
638 static void
lp_setup_vbuf_destroy(struct vbuf_render * vbr)639 lp_setup_vbuf_destroy(struct vbuf_render *vbr)
640 {
641 struct lp_setup_context *setup = lp_setup_context(vbr);
642 if (setup->vertex_buffer) {
643 align_free(setup->vertex_buffer);
644 setup->vertex_buffer = NULL;
645 }
646 lp_setup_destroy(setup);
647 }
648
649
650 /*
651 * FIXME: it is unclear if primitives_storage_needed (which is generally
652 * the same as pipe query num_primitives_generated) should increase
653 * if SO is disabled for d3d10, but for GL we definitely need to
654 * increase num_primitives_generated and this is only called for active
655 * SO. If it must not increase for d3d10 need to disambiguate the counters
656 * in the driver and do some work for getting correct values, if it should
657 * increase too should call this from outside streamout code.
658 */
659 static void
lp_setup_so_info(struct vbuf_render * vbr,uint stream,uint primitives,uint prim_generated)660 lp_setup_so_info(struct vbuf_render *vbr, uint stream,
661 uint primitives, uint prim_generated)
662 {
663 struct lp_setup_context *setup = lp_setup_context(vbr);
664 struct llvmpipe_context *lp = llvmpipe_context(setup->pipe);
665
666 lp->so_stats[stream].num_primitives_written += primitives;
667 lp->so_stats[stream].primitives_storage_needed += prim_generated;
668 }
669
670
671 static void
lp_setup_pipeline_statistics(struct vbuf_render * vbr,const struct pipe_query_data_pipeline_statistics * stats)672 lp_setup_pipeline_statistics(
673 struct vbuf_render *vbr,
674 const struct pipe_query_data_pipeline_statistics *stats)
675 {
676 struct lp_setup_context *setup = lp_setup_context(vbr);
677 struct llvmpipe_context *llvmpipe = llvmpipe_context(setup->pipe);
678
679 llvmpipe->pipeline_statistics.ia_vertices +=
680 stats->ia_vertices;
681 llvmpipe->pipeline_statistics.ia_primitives +=
682 stats->ia_primitives;
683 llvmpipe->pipeline_statistics.vs_invocations +=
684 stats->vs_invocations;
685 llvmpipe->pipeline_statistics.gs_invocations +=
686 stats->gs_invocations;
687 llvmpipe->pipeline_statistics.gs_primitives +=
688 stats->gs_primitives;
689 llvmpipe->pipeline_statistics.hs_invocations +=
690 stats->hs_invocations;
691 llvmpipe->pipeline_statistics.ds_invocations +=
692 stats->ds_invocations;
693 if (!setup->rasterizer_discard) {
694 llvmpipe->pipeline_statistics.c_invocations +=
695 stats->c_invocations;
696 } else {
697 llvmpipe->pipeline_statistics.c_invocations = 0;
698 }
699 }
700
701
702 /**
703 * Create the post-transform vertex handler for the given context.
704 */
705 void
lp_setup_init_vbuf(struct lp_setup_context * setup)706 lp_setup_init_vbuf(struct lp_setup_context *setup)
707 {
708 setup->base.max_indices = LP_MAX_VBUF_INDEXES;
709 setup->base.max_vertex_buffer_bytes = LP_MAX_VBUF_SIZE;
710
711 setup->base.get_vertex_info = lp_setup_get_vertex_info;
712 setup->base.allocate_vertices = lp_setup_allocate_vertices;
713 setup->base.map_vertices = lp_setup_map_vertices;
714 setup->base.unmap_vertices = lp_setup_unmap_vertices;
715 setup->base.set_primitive = lp_setup_set_primitive;
716 setup->base.set_view_index = lp_setup_set_view_index;
717 setup->base.draw_elements = lp_setup_draw_elements;
718 setup->base.draw_arrays = lp_setup_draw_arrays;
719 setup->base.release_vertices = lp_setup_release_vertices;
720 setup->base.destroy = lp_setup_vbuf_destroy;
721 setup->base.set_stream_output_info = lp_setup_so_info;
722 setup->base.pipeline_statistics = lp_setup_pipeline_statistics;
723 }
724