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