• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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