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 */
59static struct lp_setup_context *
60lp_setup_context(struct vbuf_render *vbr)
61{
62   return (struct lp_setup_context *) vbr;
63}
64
65
66
67static const struct vertex_info *
68lp_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
81static boolean
82lp_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
100static void
101lp_setup_release_vertices(struct vbuf_render *vbr)
102{
103   /* keep the old allocation for next time */
104}
105
106static void *
107lp_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
113static void
114lp_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
124static void
125lp_setup_set_primitive(struct vbuf_render *vbr, enum pipe_prim_type prim)
126{
127   lp_setup_context(vbr)->prim = prim;
128}
129
130static void
131lp_setup_set_view_index(struct vbuf_render *vbr, unsigned view_index)
132{
133   lp_setup_context(vbr)->view_index = view_index;
134}
135
136typedef const float (*const_float4_ptr)[4];
137
138static 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
145static inline void
146rect(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 */
164static void
165lp_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 */
379static void
380lp_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
648static void
649lp_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 */
668static void
669lp_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
678static void
679lp_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 */
711void
712lp_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