xref: /aosp_15_r20/external/mesa3d/src/gallium/drivers/llvmpipe/lp_setup_vbuf.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
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