1bf215546Sopenharmony_ci/**************************************************************************
2bf215546Sopenharmony_ci *
3bf215546Sopenharmony_ci * Copyright 2007 VMware, Inc.
4bf215546Sopenharmony_ci * All Rights Reserved.
5bf215546Sopenharmony_ci *
6bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
7bf215546Sopenharmony_ci * copy of this software and associated documentation files (the
8bf215546Sopenharmony_ci * "Software"), to deal in the Software without restriction, including
9bf215546Sopenharmony_ci * without limitation the rights to use, copy, modify, merge, publish,
10bf215546Sopenharmony_ci * distribute, sub license, and/or sell copies of the Software, and to
11bf215546Sopenharmony_ci * permit persons to whom the Software is furnished to do so, subject to
12bf215546Sopenharmony_ci * the following conditions:
13bf215546Sopenharmony_ci *
14bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the
15bf215546Sopenharmony_ci * next paragraph) shall be included in all copies or substantial portions
16bf215546Sopenharmony_ci * of the Software.
17bf215546Sopenharmony_ci *
18bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19bf215546Sopenharmony_ci * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20bf215546Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21bf215546Sopenharmony_ci * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
22bf215546Sopenharmony_ci * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23bf215546Sopenharmony_ci * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24bf215546Sopenharmony_ci * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25bf215546Sopenharmony_ci *
26bf215546Sopenharmony_ci **************************************************************************/
27bf215546Sopenharmony_ci
28bf215546Sopenharmony_ci/**
29bf215546Sopenharmony_ci * Interface between 'draw' module's output and the softpipe rasterizer/setup
30bf215546Sopenharmony_ci * code.  When the 'draw' module has finished filling a vertex buffer, the
31bf215546Sopenharmony_ci * draw_arrays() functions below will be called.  Loop over the vertices and
32bf215546Sopenharmony_ci * call the point/line/tri setup functions.
33bf215546Sopenharmony_ci *
34bf215546Sopenharmony_ci * Authors
35bf215546Sopenharmony_ci *  Brian Paul
36bf215546Sopenharmony_ci */
37bf215546Sopenharmony_ci
38bf215546Sopenharmony_ci
39bf215546Sopenharmony_ci#include "sp_context.h"
40bf215546Sopenharmony_ci#include "sp_setup.h"
41bf215546Sopenharmony_ci#include "sp_state.h"
42bf215546Sopenharmony_ci#include "sp_prim_vbuf.h"
43bf215546Sopenharmony_ci#include "draw/draw_context.h"
44bf215546Sopenharmony_ci#include "draw/draw_vbuf.h"
45bf215546Sopenharmony_ci#include "util/u_memory.h"
46bf215546Sopenharmony_ci#include "util/u_prim.h"
47bf215546Sopenharmony_ci
48bf215546Sopenharmony_ci
49bf215546Sopenharmony_ci#define SP_MAX_VBUF_INDEXES 1024
50bf215546Sopenharmony_ci#define SP_MAX_VBUF_SIZE    4096
51bf215546Sopenharmony_ci
52bf215546Sopenharmony_citypedef const float (*cptrf4)[4];
53bf215546Sopenharmony_ci
54bf215546Sopenharmony_ci/**
55bf215546Sopenharmony_ci * Subclass of vbuf_render.
56bf215546Sopenharmony_ci */
57bf215546Sopenharmony_cistruct softpipe_vbuf_render
58bf215546Sopenharmony_ci{
59bf215546Sopenharmony_ci   struct vbuf_render base;
60bf215546Sopenharmony_ci   struct softpipe_context *softpipe;
61bf215546Sopenharmony_ci   struct setup_context *setup;
62bf215546Sopenharmony_ci
63bf215546Sopenharmony_ci   enum pipe_prim_type prim;
64bf215546Sopenharmony_ci   uint vertex_size;
65bf215546Sopenharmony_ci   uint nr_vertices;
66bf215546Sopenharmony_ci   uint vertex_buffer_size;
67bf215546Sopenharmony_ci   void *vertex_buffer;
68bf215546Sopenharmony_ci};
69bf215546Sopenharmony_ci
70bf215546Sopenharmony_ci
71bf215546Sopenharmony_ci/** cast wrapper */
72bf215546Sopenharmony_cistatic struct softpipe_vbuf_render *
73bf215546Sopenharmony_cisoftpipe_vbuf_render(struct vbuf_render *vbr)
74bf215546Sopenharmony_ci{
75bf215546Sopenharmony_ci   return (struct softpipe_vbuf_render *) vbr;
76bf215546Sopenharmony_ci}
77bf215546Sopenharmony_ci
78bf215546Sopenharmony_ci
79bf215546Sopenharmony_ci/** This tells the draw module about our desired vertex layout */
80bf215546Sopenharmony_cistatic const struct vertex_info *
81bf215546Sopenharmony_cisp_vbuf_get_vertex_info(struct vbuf_render *vbr)
82bf215546Sopenharmony_ci{
83bf215546Sopenharmony_ci   struct softpipe_vbuf_render *cvbr = softpipe_vbuf_render(vbr);
84bf215546Sopenharmony_ci   return softpipe_get_vbuf_vertex_info(cvbr->softpipe);
85bf215546Sopenharmony_ci}
86bf215546Sopenharmony_ci
87bf215546Sopenharmony_ci
88bf215546Sopenharmony_cistatic boolean
89bf215546Sopenharmony_cisp_vbuf_allocate_vertices(struct vbuf_render *vbr,
90bf215546Sopenharmony_ci                          ushort vertex_size, ushort nr_vertices)
91bf215546Sopenharmony_ci{
92bf215546Sopenharmony_ci   struct softpipe_vbuf_render *cvbr = softpipe_vbuf_render(vbr);
93bf215546Sopenharmony_ci   unsigned size = vertex_size * nr_vertices;
94bf215546Sopenharmony_ci
95bf215546Sopenharmony_ci   if (cvbr->vertex_buffer_size < size) {
96bf215546Sopenharmony_ci      align_free(cvbr->vertex_buffer);
97bf215546Sopenharmony_ci      cvbr->vertex_buffer = align_malloc(size, 16);
98bf215546Sopenharmony_ci      cvbr->vertex_buffer_size = size;
99bf215546Sopenharmony_ci   }
100bf215546Sopenharmony_ci
101bf215546Sopenharmony_ci   cvbr->vertex_size = vertex_size;
102bf215546Sopenharmony_ci   cvbr->nr_vertices = nr_vertices;
103bf215546Sopenharmony_ci
104bf215546Sopenharmony_ci   return cvbr->vertex_buffer != NULL;
105bf215546Sopenharmony_ci}
106bf215546Sopenharmony_ci
107bf215546Sopenharmony_ci
108bf215546Sopenharmony_cistatic void
109bf215546Sopenharmony_cisp_vbuf_release_vertices(struct vbuf_render *vbr)
110bf215546Sopenharmony_ci{
111bf215546Sopenharmony_ci   /* keep the old allocation for next time */
112bf215546Sopenharmony_ci}
113bf215546Sopenharmony_ci
114bf215546Sopenharmony_ci
115bf215546Sopenharmony_cistatic void *
116bf215546Sopenharmony_cisp_vbuf_map_vertices(struct vbuf_render *vbr)
117bf215546Sopenharmony_ci{
118bf215546Sopenharmony_ci   struct softpipe_vbuf_render *cvbr = softpipe_vbuf_render(vbr);
119bf215546Sopenharmony_ci   return cvbr->vertex_buffer;
120bf215546Sopenharmony_ci}
121bf215546Sopenharmony_ci
122bf215546Sopenharmony_ci
123bf215546Sopenharmony_cistatic void
124bf215546Sopenharmony_cisp_vbuf_unmap_vertices(struct vbuf_render *vbr,
125bf215546Sopenharmony_ci                       ushort min_index,
126bf215546Sopenharmony_ci                       ushort max_index )
127bf215546Sopenharmony_ci{
128bf215546Sopenharmony_ci   struct softpipe_vbuf_render *cvbr = softpipe_vbuf_render(vbr);
129bf215546Sopenharmony_ci   assert( cvbr->vertex_buffer_size >= (max_index+1) * cvbr->vertex_size );
130bf215546Sopenharmony_ci   (void) cvbr;
131bf215546Sopenharmony_ci   /* do nothing */
132bf215546Sopenharmony_ci}
133bf215546Sopenharmony_ci
134bf215546Sopenharmony_ci
135bf215546Sopenharmony_cistatic void
136bf215546Sopenharmony_cisp_vbuf_set_primitive(struct vbuf_render *vbr, enum pipe_prim_type prim)
137bf215546Sopenharmony_ci{
138bf215546Sopenharmony_ci   struct softpipe_vbuf_render *cvbr = softpipe_vbuf_render(vbr);
139bf215546Sopenharmony_ci   struct setup_context *setup_ctx = cvbr->setup;
140bf215546Sopenharmony_ci
141bf215546Sopenharmony_ci   sp_setup_prepare( setup_ctx );
142bf215546Sopenharmony_ci
143bf215546Sopenharmony_ci   cvbr->softpipe->reduced_prim = u_reduced_prim(prim);
144bf215546Sopenharmony_ci   cvbr->prim = prim;
145bf215546Sopenharmony_ci}
146bf215546Sopenharmony_ci
147bf215546Sopenharmony_ci
148bf215546Sopenharmony_cistatic inline cptrf4 get_vert( const void *vertex_buffer,
149bf215546Sopenharmony_ci                               int index,
150bf215546Sopenharmony_ci                               int stride )
151bf215546Sopenharmony_ci{
152bf215546Sopenharmony_ci   return (cptrf4)((char *)vertex_buffer + index * stride);
153bf215546Sopenharmony_ci}
154bf215546Sopenharmony_ci
155bf215546Sopenharmony_ci
156bf215546Sopenharmony_ci/**
157bf215546Sopenharmony_ci * draw elements / indexed primitives
158bf215546Sopenharmony_ci */
159bf215546Sopenharmony_cistatic void
160bf215546Sopenharmony_cisp_vbuf_draw_elements(struct vbuf_render *vbr, const ushort *indices, uint nr)
161bf215546Sopenharmony_ci{
162bf215546Sopenharmony_ci   struct softpipe_vbuf_render *cvbr = softpipe_vbuf_render(vbr);
163bf215546Sopenharmony_ci   struct softpipe_context *softpipe = cvbr->softpipe;
164bf215546Sopenharmony_ci   const unsigned stride = softpipe->vertex_info.size * sizeof(float);
165bf215546Sopenharmony_ci   const void *vertex_buffer = cvbr->vertex_buffer;
166bf215546Sopenharmony_ci   struct setup_context *setup = cvbr->setup;
167bf215546Sopenharmony_ci   const boolean flatshade_first = softpipe->rasterizer->flatshade_first;
168bf215546Sopenharmony_ci   unsigned i;
169bf215546Sopenharmony_ci
170bf215546Sopenharmony_ci   switch (cvbr->prim) {
171bf215546Sopenharmony_ci   case PIPE_PRIM_POINTS:
172bf215546Sopenharmony_ci      for (i = 0; i < nr; i++) {
173bf215546Sopenharmony_ci         sp_setup_point( setup,
174bf215546Sopenharmony_ci                         get_vert(vertex_buffer, indices[i-0], stride) );
175bf215546Sopenharmony_ci      }
176bf215546Sopenharmony_ci      break;
177bf215546Sopenharmony_ci
178bf215546Sopenharmony_ci   case PIPE_PRIM_LINES:
179bf215546Sopenharmony_ci      for (i = 1; i < nr; i += 2) {
180bf215546Sopenharmony_ci         sp_setup_line( setup,
181bf215546Sopenharmony_ci                        get_vert(vertex_buffer, indices[i-1], stride),
182bf215546Sopenharmony_ci                        get_vert(vertex_buffer, indices[i-0], stride) );
183bf215546Sopenharmony_ci      }
184bf215546Sopenharmony_ci      break;
185bf215546Sopenharmony_ci
186bf215546Sopenharmony_ci   case PIPE_PRIM_LINE_STRIP:
187bf215546Sopenharmony_ci      for (i = 1; i < nr; i ++) {
188bf215546Sopenharmony_ci         sp_setup_line( setup,
189bf215546Sopenharmony_ci                        get_vert(vertex_buffer, indices[i-1], stride),
190bf215546Sopenharmony_ci                        get_vert(vertex_buffer, indices[i-0], stride) );
191bf215546Sopenharmony_ci      }
192bf215546Sopenharmony_ci      break;
193bf215546Sopenharmony_ci
194bf215546Sopenharmony_ci   case PIPE_PRIM_LINE_LOOP:
195bf215546Sopenharmony_ci      for (i = 1; i < nr; i ++) {
196bf215546Sopenharmony_ci         sp_setup_line( setup,
197bf215546Sopenharmony_ci                        get_vert(vertex_buffer, indices[i-1], stride),
198bf215546Sopenharmony_ci                        get_vert(vertex_buffer, indices[i-0], stride) );
199bf215546Sopenharmony_ci      }
200bf215546Sopenharmony_ci      if (nr) {
201bf215546Sopenharmony_ci         sp_setup_line( setup,
202bf215546Sopenharmony_ci                        get_vert(vertex_buffer, indices[nr-1], stride),
203bf215546Sopenharmony_ci                        get_vert(vertex_buffer, indices[0], stride) );
204bf215546Sopenharmony_ci      }
205bf215546Sopenharmony_ci      break;
206bf215546Sopenharmony_ci
207bf215546Sopenharmony_ci   case PIPE_PRIM_TRIANGLES:
208bf215546Sopenharmony_ci      for (i = 2; i < nr; i += 3) {
209bf215546Sopenharmony_ci         sp_setup_tri( setup,
210bf215546Sopenharmony_ci                       get_vert(vertex_buffer, indices[i-2], stride),
211bf215546Sopenharmony_ci                       get_vert(vertex_buffer, indices[i-1], stride),
212bf215546Sopenharmony_ci                       get_vert(vertex_buffer, indices[i-0], stride) );
213bf215546Sopenharmony_ci      }
214bf215546Sopenharmony_ci      break;
215bf215546Sopenharmony_ci
216bf215546Sopenharmony_ci   case PIPE_PRIM_TRIANGLE_STRIP:
217bf215546Sopenharmony_ci      if (flatshade_first) {
218bf215546Sopenharmony_ci         for (i = 2; i < nr; i += 1) {
219bf215546Sopenharmony_ci            /* emit first triangle vertex as first triangle vertex */
220bf215546Sopenharmony_ci            sp_setup_tri( setup,
221bf215546Sopenharmony_ci                          get_vert(vertex_buffer, indices[i-2], stride),
222bf215546Sopenharmony_ci                          get_vert(vertex_buffer, indices[i+(i&1)-1], stride),
223bf215546Sopenharmony_ci                          get_vert(vertex_buffer, indices[i-(i&1)], stride) );
224bf215546Sopenharmony_ci
225bf215546Sopenharmony_ci         }
226bf215546Sopenharmony_ci      }
227bf215546Sopenharmony_ci      else {
228bf215546Sopenharmony_ci         for (i = 2; i < nr; i += 1) {
229bf215546Sopenharmony_ci            /* emit last triangle vertex as last triangle vertex */
230bf215546Sopenharmony_ci            sp_setup_tri( setup,
231bf215546Sopenharmony_ci                          get_vert(vertex_buffer, indices[i+(i&1)-2], stride),
232bf215546Sopenharmony_ci                          get_vert(vertex_buffer, indices[i-(i&1)-1], stride),
233bf215546Sopenharmony_ci                          get_vert(vertex_buffer, indices[i-0], stride) );
234bf215546Sopenharmony_ci         }
235bf215546Sopenharmony_ci      }
236bf215546Sopenharmony_ci      break;
237bf215546Sopenharmony_ci
238bf215546Sopenharmony_ci   case PIPE_PRIM_TRIANGLE_FAN:
239bf215546Sopenharmony_ci      if (flatshade_first) {
240bf215546Sopenharmony_ci         for (i = 2; i < nr; i += 1) {
241bf215546Sopenharmony_ci            /* emit first non-spoke vertex as first vertex */
242bf215546Sopenharmony_ci            sp_setup_tri( setup,
243bf215546Sopenharmony_ci                          get_vert(vertex_buffer, indices[i-1], stride),
244bf215546Sopenharmony_ci                          get_vert(vertex_buffer, indices[i-0], stride),
245bf215546Sopenharmony_ci                          get_vert(vertex_buffer, indices[0], stride) );
246bf215546Sopenharmony_ci         }
247bf215546Sopenharmony_ci      }
248bf215546Sopenharmony_ci      else {
249bf215546Sopenharmony_ci         for (i = 2; i < nr; i += 1) {
250bf215546Sopenharmony_ci            /* emit last non-spoke vertex as last vertex */
251bf215546Sopenharmony_ci            sp_setup_tri( setup,
252bf215546Sopenharmony_ci                          get_vert(vertex_buffer, indices[0], stride),
253bf215546Sopenharmony_ci                          get_vert(vertex_buffer, indices[i-1], stride),
254bf215546Sopenharmony_ci                          get_vert(vertex_buffer, indices[i-0], stride) );
255bf215546Sopenharmony_ci         }
256bf215546Sopenharmony_ci      }
257bf215546Sopenharmony_ci      break;
258bf215546Sopenharmony_ci
259bf215546Sopenharmony_ci   case PIPE_PRIM_QUADS:
260bf215546Sopenharmony_ci      /* GL quads don't follow provoking vertex convention */
261bf215546Sopenharmony_ci      if (flatshade_first) {
262bf215546Sopenharmony_ci         /* emit last quad vertex as first triangle vertex */
263bf215546Sopenharmony_ci         for (i = 3; i < nr; i += 4) {
264bf215546Sopenharmony_ci            sp_setup_tri( setup,
265bf215546Sopenharmony_ci                          get_vert(vertex_buffer, indices[i-0], stride),
266bf215546Sopenharmony_ci                          get_vert(vertex_buffer, indices[i-3], stride),
267bf215546Sopenharmony_ci                          get_vert(vertex_buffer, indices[i-2], stride) );
268bf215546Sopenharmony_ci
269bf215546Sopenharmony_ci            sp_setup_tri( setup,
270bf215546Sopenharmony_ci                          get_vert(vertex_buffer, indices[i-0], stride),
271bf215546Sopenharmony_ci                          get_vert(vertex_buffer, indices[i-2], stride),
272bf215546Sopenharmony_ci                          get_vert(vertex_buffer, indices[i-1], stride) );
273bf215546Sopenharmony_ci         }
274bf215546Sopenharmony_ci      }
275bf215546Sopenharmony_ci      else {
276bf215546Sopenharmony_ci         /* emit last quad vertex as last triangle vertex */
277bf215546Sopenharmony_ci         for (i = 3; i < nr; i += 4) {
278bf215546Sopenharmony_ci            sp_setup_tri( setup,
279bf215546Sopenharmony_ci                          get_vert(vertex_buffer, indices[i-3], stride),
280bf215546Sopenharmony_ci                          get_vert(vertex_buffer, indices[i-2], stride),
281bf215546Sopenharmony_ci                          get_vert(vertex_buffer, indices[i-0], stride) );
282bf215546Sopenharmony_ci
283bf215546Sopenharmony_ci            sp_setup_tri( setup,
284bf215546Sopenharmony_ci                          get_vert(vertex_buffer, indices[i-2], stride),
285bf215546Sopenharmony_ci                          get_vert(vertex_buffer, indices[i-1], stride),
286bf215546Sopenharmony_ci                          get_vert(vertex_buffer, indices[i-0], stride) );
287bf215546Sopenharmony_ci         }
288bf215546Sopenharmony_ci      }
289bf215546Sopenharmony_ci      break;
290bf215546Sopenharmony_ci
291bf215546Sopenharmony_ci   case PIPE_PRIM_QUAD_STRIP:
292bf215546Sopenharmony_ci      /* GL quad strips don't follow provoking vertex convention */
293bf215546Sopenharmony_ci      if (flatshade_first) {
294bf215546Sopenharmony_ci         /* emit last quad vertex as first triangle vertex */
295bf215546Sopenharmony_ci         for (i = 3; i < nr; i += 2) {
296bf215546Sopenharmony_ci            sp_setup_tri( setup,
297bf215546Sopenharmony_ci                          get_vert(vertex_buffer, indices[i-0], stride),
298bf215546Sopenharmony_ci                          get_vert(vertex_buffer, indices[i-3], stride),
299bf215546Sopenharmony_ci                          get_vert(vertex_buffer, indices[i-2], stride) );
300bf215546Sopenharmony_ci            sp_setup_tri( setup,
301bf215546Sopenharmony_ci                          get_vert(vertex_buffer, indices[i-0], stride),
302bf215546Sopenharmony_ci                          get_vert(vertex_buffer, indices[i-1], stride),
303bf215546Sopenharmony_ci                          get_vert(vertex_buffer, indices[i-3], stride) );
304bf215546Sopenharmony_ci         }
305bf215546Sopenharmony_ci      }
306bf215546Sopenharmony_ci      else {
307bf215546Sopenharmony_ci         /* emit last quad vertex as last triangle vertex */
308bf215546Sopenharmony_ci         for (i = 3; i < nr; i += 2) {
309bf215546Sopenharmony_ci            sp_setup_tri( setup,
310bf215546Sopenharmony_ci                          get_vert(vertex_buffer, indices[i-3], stride),
311bf215546Sopenharmony_ci                          get_vert(vertex_buffer, indices[i-2], stride),
312bf215546Sopenharmony_ci                          get_vert(vertex_buffer, indices[i-0], stride) );
313bf215546Sopenharmony_ci            sp_setup_tri( setup,
314bf215546Sopenharmony_ci                          get_vert(vertex_buffer, indices[i-1], stride),
315bf215546Sopenharmony_ci                          get_vert(vertex_buffer, indices[i-3], stride),
316bf215546Sopenharmony_ci                          get_vert(vertex_buffer, indices[i-0], stride) );
317bf215546Sopenharmony_ci         }
318bf215546Sopenharmony_ci      }
319bf215546Sopenharmony_ci      break;
320bf215546Sopenharmony_ci
321bf215546Sopenharmony_ci   case PIPE_PRIM_POLYGON:
322bf215546Sopenharmony_ci      /* Almost same as tri fan but the _first_ vertex specifies the flat
323bf215546Sopenharmony_ci       * shading color.
324bf215546Sopenharmony_ci       */
325bf215546Sopenharmony_ci      if (flatshade_first) {
326bf215546Sopenharmony_ci         /* emit first polygon  vertex as first triangle vertex */
327bf215546Sopenharmony_ci         for (i = 2; i < nr; i += 1) {
328bf215546Sopenharmony_ci            sp_setup_tri( setup,
329bf215546Sopenharmony_ci                          get_vert(vertex_buffer, indices[0], stride),
330bf215546Sopenharmony_ci                          get_vert(vertex_buffer, indices[i-1], stride),
331bf215546Sopenharmony_ci                          get_vert(vertex_buffer, indices[i-0], stride) );
332bf215546Sopenharmony_ci         }
333bf215546Sopenharmony_ci      }
334bf215546Sopenharmony_ci      else {
335bf215546Sopenharmony_ci         /* emit first polygon  vertex as last triangle vertex */
336bf215546Sopenharmony_ci         for (i = 2; i < nr; i += 1) {
337bf215546Sopenharmony_ci            sp_setup_tri( setup,
338bf215546Sopenharmony_ci                          get_vert(vertex_buffer, indices[i-1], stride),
339bf215546Sopenharmony_ci                          get_vert(vertex_buffer, indices[i-0], stride),
340bf215546Sopenharmony_ci                          get_vert(vertex_buffer, indices[0], stride) );
341bf215546Sopenharmony_ci         }
342bf215546Sopenharmony_ci      }
343bf215546Sopenharmony_ci      break;
344bf215546Sopenharmony_ci
345bf215546Sopenharmony_ci   default:
346bf215546Sopenharmony_ci      assert(0);
347bf215546Sopenharmony_ci   }
348bf215546Sopenharmony_ci}
349bf215546Sopenharmony_ci
350bf215546Sopenharmony_ci
351bf215546Sopenharmony_ci/**
352bf215546Sopenharmony_ci * This function is hit when the draw module is working in pass-through mode.
353bf215546Sopenharmony_ci * It's up to us to convert the vertex array into point/line/tri prims.
354bf215546Sopenharmony_ci */
355bf215546Sopenharmony_cistatic void
356bf215546Sopenharmony_cisp_vbuf_draw_arrays(struct vbuf_render *vbr, uint start, uint nr)
357bf215546Sopenharmony_ci{
358bf215546Sopenharmony_ci   struct softpipe_vbuf_render *cvbr = softpipe_vbuf_render(vbr);
359bf215546Sopenharmony_ci   struct softpipe_context *softpipe = cvbr->softpipe;
360bf215546Sopenharmony_ci   struct setup_context *setup = cvbr->setup;
361bf215546Sopenharmony_ci   const unsigned stride = softpipe->vertex_info.size * sizeof(float);
362bf215546Sopenharmony_ci   const void *vertex_buffer =
363bf215546Sopenharmony_ci      (void *) get_vert(cvbr->vertex_buffer, start, stride);
364bf215546Sopenharmony_ci   const boolean flatshade_first = softpipe->rasterizer->flatshade_first;
365bf215546Sopenharmony_ci   unsigned i;
366bf215546Sopenharmony_ci
367bf215546Sopenharmony_ci   switch (cvbr->prim) {
368bf215546Sopenharmony_ci   case PIPE_PRIM_POINTS:
369bf215546Sopenharmony_ci      for (i = 0; i < nr; i++) {
370bf215546Sopenharmony_ci         sp_setup_point( setup,
371bf215546Sopenharmony_ci                         get_vert(vertex_buffer, i-0, stride) );
372bf215546Sopenharmony_ci      }
373bf215546Sopenharmony_ci      break;
374bf215546Sopenharmony_ci
375bf215546Sopenharmony_ci   case PIPE_PRIM_LINES:
376bf215546Sopenharmony_ci      for (i = 1; i < nr; i += 2) {
377bf215546Sopenharmony_ci         sp_setup_line( setup,
378bf215546Sopenharmony_ci                        get_vert(vertex_buffer, i-1, stride),
379bf215546Sopenharmony_ci                        get_vert(vertex_buffer, i-0, stride) );
380bf215546Sopenharmony_ci      }
381bf215546Sopenharmony_ci      break;
382bf215546Sopenharmony_ci
383bf215546Sopenharmony_ci   case PIPE_PRIM_LINES_ADJACENCY:
384bf215546Sopenharmony_ci      for (i = 3; i < nr; i += 4) {
385bf215546Sopenharmony_ci         sp_setup_line( setup,
386bf215546Sopenharmony_ci                        get_vert(vertex_buffer, i-2, stride),
387bf215546Sopenharmony_ci                        get_vert(vertex_buffer, i-1, stride) );
388bf215546Sopenharmony_ci      }
389bf215546Sopenharmony_ci      break;
390bf215546Sopenharmony_ci
391bf215546Sopenharmony_ci   case PIPE_PRIM_LINE_STRIP:
392bf215546Sopenharmony_ci      for (i = 1; i < nr; i ++) {
393bf215546Sopenharmony_ci         sp_setup_line( setup,
394bf215546Sopenharmony_ci                     get_vert(vertex_buffer, i-1, stride),
395bf215546Sopenharmony_ci                     get_vert(vertex_buffer, i-0, stride) );
396bf215546Sopenharmony_ci      }
397bf215546Sopenharmony_ci      break;
398bf215546Sopenharmony_ci
399bf215546Sopenharmony_ci   case PIPE_PRIM_LINE_STRIP_ADJACENCY:
400bf215546Sopenharmony_ci      for (i = 3; i < nr; i++) {
401bf215546Sopenharmony_ci         sp_setup_line( setup,
402bf215546Sopenharmony_ci                     get_vert(vertex_buffer, i-2, stride),
403bf215546Sopenharmony_ci                     get_vert(vertex_buffer, i-1, stride) );
404bf215546Sopenharmony_ci      }
405bf215546Sopenharmony_ci      break;
406bf215546Sopenharmony_ci
407bf215546Sopenharmony_ci   case PIPE_PRIM_LINE_LOOP:
408bf215546Sopenharmony_ci      for (i = 1; i < nr; i ++) {
409bf215546Sopenharmony_ci         sp_setup_line( setup,
410bf215546Sopenharmony_ci                        get_vert(vertex_buffer, i-1, stride),
411bf215546Sopenharmony_ci                        get_vert(vertex_buffer, i-0, stride) );
412bf215546Sopenharmony_ci      }
413bf215546Sopenharmony_ci      if (nr) {
414bf215546Sopenharmony_ci         sp_setup_line( setup,
415bf215546Sopenharmony_ci                        get_vert(vertex_buffer, nr-1, stride),
416bf215546Sopenharmony_ci                        get_vert(vertex_buffer, 0, stride) );
417bf215546Sopenharmony_ci      }
418bf215546Sopenharmony_ci      break;
419bf215546Sopenharmony_ci
420bf215546Sopenharmony_ci   case PIPE_PRIM_TRIANGLES:
421bf215546Sopenharmony_ci      for (i = 2; i < nr; i += 3) {
422bf215546Sopenharmony_ci         sp_setup_tri( setup,
423bf215546Sopenharmony_ci                       get_vert(vertex_buffer, i-2, stride),
424bf215546Sopenharmony_ci                       get_vert(vertex_buffer, i-1, stride),
425bf215546Sopenharmony_ci                       get_vert(vertex_buffer, i-0, stride) );
426bf215546Sopenharmony_ci      }
427bf215546Sopenharmony_ci      break;
428bf215546Sopenharmony_ci
429bf215546Sopenharmony_ci   case PIPE_PRIM_TRIANGLES_ADJACENCY:
430bf215546Sopenharmony_ci      for (i = 5; i < nr; i += 6) {
431bf215546Sopenharmony_ci         sp_setup_tri( setup,
432bf215546Sopenharmony_ci                       get_vert(vertex_buffer, i-5, stride),
433bf215546Sopenharmony_ci                       get_vert(vertex_buffer, i-3, stride),
434bf215546Sopenharmony_ci                       get_vert(vertex_buffer, i-1, stride) );
435bf215546Sopenharmony_ci      }
436bf215546Sopenharmony_ci      break;
437bf215546Sopenharmony_ci
438bf215546Sopenharmony_ci   case PIPE_PRIM_TRIANGLE_STRIP:
439bf215546Sopenharmony_ci      if (flatshade_first) {
440bf215546Sopenharmony_ci         for (i = 2; i < nr; i++) {
441bf215546Sopenharmony_ci            /* emit first triangle vertex as first triangle vertex */
442bf215546Sopenharmony_ci            sp_setup_tri( setup,
443bf215546Sopenharmony_ci                          get_vert(vertex_buffer, i-2, stride),
444bf215546Sopenharmony_ci                          get_vert(vertex_buffer, i+(i&1)-1, stride),
445bf215546Sopenharmony_ci                          get_vert(vertex_buffer, i-(i&1), stride) );
446bf215546Sopenharmony_ci         }
447bf215546Sopenharmony_ci      }
448bf215546Sopenharmony_ci      else {
449bf215546Sopenharmony_ci         for (i = 2; i < nr; i++) {
450bf215546Sopenharmony_ci            /* emit last triangle vertex as last triangle vertex */
451bf215546Sopenharmony_ci            sp_setup_tri( setup,
452bf215546Sopenharmony_ci                          get_vert(vertex_buffer, i+(i&1)-2, stride),
453bf215546Sopenharmony_ci                          get_vert(vertex_buffer, i-(i&1)-1, stride),
454bf215546Sopenharmony_ci                          get_vert(vertex_buffer, i-0, stride) );
455bf215546Sopenharmony_ci         }
456bf215546Sopenharmony_ci      }
457bf215546Sopenharmony_ci      break;
458bf215546Sopenharmony_ci
459bf215546Sopenharmony_ci   case PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY:
460bf215546Sopenharmony_ci      if (flatshade_first) {
461bf215546Sopenharmony_ci         for (i = 5; i < nr; i += 2) {
462bf215546Sopenharmony_ci            /* emit first triangle vertex as first triangle vertex */
463bf215546Sopenharmony_ci            sp_setup_tri( setup,
464bf215546Sopenharmony_ci                          get_vert(vertex_buffer, i-5, stride),
465bf215546Sopenharmony_ci                          get_vert(vertex_buffer, i+(i&1)*2-3, stride),
466bf215546Sopenharmony_ci                          get_vert(vertex_buffer, i-(i&1)*2-1, stride) );
467bf215546Sopenharmony_ci         }
468bf215546Sopenharmony_ci      }
469bf215546Sopenharmony_ci      else {
470bf215546Sopenharmony_ci         for (i = 5; i < nr; i += 2) {
471bf215546Sopenharmony_ci            /* emit last triangle vertex as last triangle vertex */
472bf215546Sopenharmony_ci            sp_setup_tri( setup,
473bf215546Sopenharmony_ci                          get_vert(vertex_buffer, i+(i&1)*2-5, stride),
474bf215546Sopenharmony_ci                          get_vert(vertex_buffer, i-(i&1)*2-3, stride),
475bf215546Sopenharmony_ci                          get_vert(vertex_buffer, i-1, stride) );
476bf215546Sopenharmony_ci         }
477bf215546Sopenharmony_ci      }
478bf215546Sopenharmony_ci      break;
479bf215546Sopenharmony_ci
480bf215546Sopenharmony_ci   case PIPE_PRIM_TRIANGLE_FAN:
481bf215546Sopenharmony_ci      if (flatshade_first) {
482bf215546Sopenharmony_ci         for (i = 2; i < nr; i += 1) {
483bf215546Sopenharmony_ci            /* emit first non-spoke vertex as first vertex */
484bf215546Sopenharmony_ci            sp_setup_tri( setup,
485bf215546Sopenharmony_ci                          get_vert(vertex_buffer, i-1, stride),
486bf215546Sopenharmony_ci                          get_vert(vertex_buffer, i-0, stride),
487bf215546Sopenharmony_ci                          get_vert(vertex_buffer, 0, stride)  );
488bf215546Sopenharmony_ci         }
489bf215546Sopenharmony_ci      }
490bf215546Sopenharmony_ci      else {
491bf215546Sopenharmony_ci         for (i = 2; i < nr; i += 1) {
492bf215546Sopenharmony_ci            /* emit last non-spoke vertex as last vertex */
493bf215546Sopenharmony_ci            sp_setup_tri( setup,
494bf215546Sopenharmony_ci                          get_vert(vertex_buffer, 0, stride),
495bf215546Sopenharmony_ci                          get_vert(vertex_buffer, i-1, stride),
496bf215546Sopenharmony_ci                          get_vert(vertex_buffer, i-0, stride) );
497bf215546Sopenharmony_ci         }
498bf215546Sopenharmony_ci      }
499bf215546Sopenharmony_ci      break;
500bf215546Sopenharmony_ci
501bf215546Sopenharmony_ci   case PIPE_PRIM_QUADS:
502bf215546Sopenharmony_ci      /* GL quads don't follow provoking vertex convention */
503bf215546Sopenharmony_ci      if (flatshade_first) {
504bf215546Sopenharmony_ci         /* emit last quad vertex as first triangle vertex */
505bf215546Sopenharmony_ci         for (i = 3; i < nr; i += 4) {
506bf215546Sopenharmony_ci            sp_setup_tri( setup,
507bf215546Sopenharmony_ci                          get_vert(vertex_buffer, i-0, stride),
508bf215546Sopenharmony_ci                          get_vert(vertex_buffer, i-3, stride),
509bf215546Sopenharmony_ci                          get_vert(vertex_buffer, i-2, stride) );
510bf215546Sopenharmony_ci            sp_setup_tri( setup,
511bf215546Sopenharmony_ci                          get_vert(vertex_buffer, i-0, stride),
512bf215546Sopenharmony_ci                          get_vert(vertex_buffer, i-2, stride),
513bf215546Sopenharmony_ci                          get_vert(vertex_buffer, i-1, stride) );
514bf215546Sopenharmony_ci         }
515bf215546Sopenharmony_ci      }
516bf215546Sopenharmony_ci      else {
517bf215546Sopenharmony_ci         /* emit last quad vertex as last triangle vertex */
518bf215546Sopenharmony_ci         for (i = 3; i < nr; i += 4) {
519bf215546Sopenharmony_ci            sp_setup_tri( setup,
520bf215546Sopenharmony_ci                          get_vert(vertex_buffer, i-3, stride),
521bf215546Sopenharmony_ci                          get_vert(vertex_buffer, i-2, stride),
522bf215546Sopenharmony_ci                          get_vert(vertex_buffer, i-0, stride) );
523bf215546Sopenharmony_ci            sp_setup_tri( setup,
524bf215546Sopenharmony_ci                          get_vert(vertex_buffer, i-2, stride),
525bf215546Sopenharmony_ci                          get_vert(vertex_buffer, i-1, stride),
526bf215546Sopenharmony_ci                          get_vert(vertex_buffer, i-0, stride) );
527bf215546Sopenharmony_ci         }
528bf215546Sopenharmony_ci      }
529bf215546Sopenharmony_ci      break;
530bf215546Sopenharmony_ci
531bf215546Sopenharmony_ci   case PIPE_PRIM_QUAD_STRIP:
532bf215546Sopenharmony_ci      /* GL quad strips don't follow provoking vertex convention */
533bf215546Sopenharmony_ci      if (flatshade_first) {
534bf215546Sopenharmony_ci         /* emit last quad vertex as first triangle vertex */
535bf215546Sopenharmony_ci         for (i = 3; i < nr; i += 2) {
536bf215546Sopenharmony_ci            sp_setup_tri( setup,
537bf215546Sopenharmony_ci                          get_vert(vertex_buffer, i-0, stride),
538bf215546Sopenharmony_ci                          get_vert(vertex_buffer, i-3, stride),
539bf215546Sopenharmony_ci                          get_vert(vertex_buffer, i-2, stride) );
540bf215546Sopenharmony_ci            sp_setup_tri( setup,
541bf215546Sopenharmony_ci                          get_vert(vertex_buffer, i-0, stride),
542bf215546Sopenharmony_ci                          get_vert(vertex_buffer, i-1, stride),
543bf215546Sopenharmony_ci                          get_vert(vertex_buffer, i-3, stride) );
544bf215546Sopenharmony_ci         }
545bf215546Sopenharmony_ci      }
546bf215546Sopenharmony_ci      else {
547bf215546Sopenharmony_ci         /* emit last quad vertex as last triangle vertex */
548bf215546Sopenharmony_ci         for (i = 3; i < nr; i += 2) {
549bf215546Sopenharmony_ci            sp_setup_tri( setup,
550bf215546Sopenharmony_ci                          get_vert(vertex_buffer, i-3, stride),
551bf215546Sopenharmony_ci                          get_vert(vertex_buffer, i-2, stride),
552bf215546Sopenharmony_ci                          get_vert(vertex_buffer, i-0, stride) );
553bf215546Sopenharmony_ci            sp_setup_tri( setup,
554bf215546Sopenharmony_ci                          get_vert(vertex_buffer, i-1, stride),
555bf215546Sopenharmony_ci                          get_vert(vertex_buffer, i-3, stride),
556bf215546Sopenharmony_ci                          get_vert(vertex_buffer, i-0, stride) );
557bf215546Sopenharmony_ci         }
558bf215546Sopenharmony_ci      }
559bf215546Sopenharmony_ci      break;
560bf215546Sopenharmony_ci
561bf215546Sopenharmony_ci   case PIPE_PRIM_POLYGON:
562bf215546Sopenharmony_ci      /* Almost same as tri fan but the _first_ vertex specifies the flat
563bf215546Sopenharmony_ci       * shading color.
564bf215546Sopenharmony_ci       */
565bf215546Sopenharmony_ci      if (flatshade_first) {
566bf215546Sopenharmony_ci         /* emit first polygon  vertex as first triangle vertex */
567bf215546Sopenharmony_ci         for (i = 2; i < nr; i += 1) {
568bf215546Sopenharmony_ci            sp_setup_tri( setup,
569bf215546Sopenharmony_ci                          get_vert(vertex_buffer, 0, stride),
570bf215546Sopenharmony_ci                          get_vert(vertex_buffer, i-1, stride),
571bf215546Sopenharmony_ci                          get_vert(vertex_buffer, i-0, stride) );
572bf215546Sopenharmony_ci         }
573bf215546Sopenharmony_ci      }
574bf215546Sopenharmony_ci      else {
575bf215546Sopenharmony_ci         /* emit first polygon  vertex as last triangle vertex */
576bf215546Sopenharmony_ci         for (i = 2; i < nr; i += 1) {
577bf215546Sopenharmony_ci            sp_setup_tri( setup,
578bf215546Sopenharmony_ci                          get_vert(vertex_buffer, i-1, stride),
579bf215546Sopenharmony_ci                          get_vert(vertex_buffer, i-0, stride),
580bf215546Sopenharmony_ci                          get_vert(vertex_buffer, 0, stride) );
581bf215546Sopenharmony_ci         }
582bf215546Sopenharmony_ci      }
583bf215546Sopenharmony_ci      break;
584bf215546Sopenharmony_ci
585bf215546Sopenharmony_ci   default:
586bf215546Sopenharmony_ci      assert(0);
587bf215546Sopenharmony_ci   }
588bf215546Sopenharmony_ci}
589bf215546Sopenharmony_ci
590bf215546Sopenharmony_ci/*
591bf215546Sopenharmony_ci * FIXME: it is unclear if primitives_storage_needed (which is generally
592bf215546Sopenharmony_ci * the same as pipe query num_primitives_generated) should increase
593bf215546Sopenharmony_ci * if SO is disabled for d3d10, but for GL we definitely need to
594bf215546Sopenharmony_ci * increase num_primitives_generated and this is only called for active
595bf215546Sopenharmony_ci * SO. If it must not increase for d3d10 need to disambiguate the counters
596bf215546Sopenharmony_ci * in the driver and do some work for getting correct values, if it should
597bf215546Sopenharmony_ci * increase too should call this from outside streamout code.
598bf215546Sopenharmony_ci */
599bf215546Sopenharmony_cistatic void
600bf215546Sopenharmony_cisp_vbuf_so_info(struct vbuf_render *vbr, uint stream, uint primitives, uint prim_generated)
601bf215546Sopenharmony_ci{
602bf215546Sopenharmony_ci   struct softpipe_vbuf_render *cvbr = softpipe_vbuf_render(vbr);
603bf215546Sopenharmony_ci   struct softpipe_context *softpipe = cvbr->softpipe;
604bf215546Sopenharmony_ci
605bf215546Sopenharmony_ci   softpipe->so_stats[stream].num_primitives_written += primitives;
606bf215546Sopenharmony_ci   softpipe->so_stats[stream].primitives_storage_needed += prim_generated;
607bf215546Sopenharmony_ci}
608bf215546Sopenharmony_ci
609bf215546Sopenharmony_cistatic void
610bf215546Sopenharmony_cisp_vbuf_pipeline_statistics(
611bf215546Sopenharmony_ci   struct vbuf_render *vbr,
612bf215546Sopenharmony_ci   const struct pipe_query_data_pipeline_statistics *stats)
613bf215546Sopenharmony_ci{
614bf215546Sopenharmony_ci   struct softpipe_vbuf_render *cvbr = softpipe_vbuf_render(vbr);
615bf215546Sopenharmony_ci   struct softpipe_context *softpipe = cvbr->softpipe;
616bf215546Sopenharmony_ci
617bf215546Sopenharmony_ci   softpipe->pipeline_statistics.ia_vertices +=
618bf215546Sopenharmony_ci      stats->ia_vertices;
619bf215546Sopenharmony_ci   softpipe->pipeline_statistics.ia_primitives +=
620bf215546Sopenharmony_ci      stats->ia_primitives;
621bf215546Sopenharmony_ci   softpipe->pipeline_statistics.vs_invocations +=
622bf215546Sopenharmony_ci      stats->vs_invocations;
623bf215546Sopenharmony_ci   softpipe->pipeline_statistics.gs_invocations +=
624bf215546Sopenharmony_ci      stats->gs_invocations;
625bf215546Sopenharmony_ci   softpipe->pipeline_statistics.gs_primitives +=
626bf215546Sopenharmony_ci      stats->gs_primitives;
627bf215546Sopenharmony_ci   softpipe->pipeline_statistics.c_invocations +=
628bf215546Sopenharmony_ci      stats->c_invocations;
629bf215546Sopenharmony_ci}
630bf215546Sopenharmony_ci
631bf215546Sopenharmony_ci
632bf215546Sopenharmony_cistatic void
633bf215546Sopenharmony_cisp_vbuf_destroy(struct vbuf_render *vbr)
634bf215546Sopenharmony_ci{
635bf215546Sopenharmony_ci   struct softpipe_vbuf_render *cvbr = softpipe_vbuf_render(vbr);
636bf215546Sopenharmony_ci   if (cvbr->vertex_buffer)
637bf215546Sopenharmony_ci      align_free(cvbr->vertex_buffer);
638bf215546Sopenharmony_ci   sp_setup_destroy_context(cvbr->setup);
639bf215546Sopenharmony_ci   FREE(cvbr);
640bf215546Sopenharmony_ci}
641bf215546Sopenharmony_ci
642bf215546Sopenharmony_ci
643bf215546Sopenharmony_ci/**
644bf215546Sopenharmony_ci * Create the post-transform vertex handler for the given context.
645bf215546Sopenharmony_ci */
646bf215546Sopenharmony_cistruct vbuf_render *
647bf215546Sopenharmony_cisp_create_vbuf_backend(struct softpipe_context *sp)
648bf215546Sopenharmony_ci{
649bf215546Sopenharmony_ci   struct softpipe_vbuf_render *cvbr = CALLOC_STRUCT(softpipe_vbuf_render);
650bf215546Sopenharmony_ci
651bf215546Sopenharmony_ci   assert(sp->draw);
652bf215546Sopenharmony_ci
653bf215546Sopenharmony_ci   cvbr->base.max_indices = SP_MAX_VBUF_INDEXES;
654bf215546Sopenharmony_ci   cvbr->base.max_vertex_buffer_bytes = SP_MAX_VBUF_SIZE;
655bf215546Sopenharmony_ci
656bf215546Sopenharmony_ci   cvbr->base.get_vertex_info = sp_vbuf_get_vertex_info;
657bf215546Sopenharmony_ci   cvbr->base.allocate_vertices = sp_vbuf_allocate_vertices;
658bf215546Sopenharmony_ci   cvbr->base.map_vertices = sp_vbuf_map_vertices;
659bf215546Sopenharmony_ci   cvbr->base.unmap_vertices = sp_vbuf_unmap_vertices;
660bf215546Sopenharmony_ci   cvbr->base.set_primitive = sp_vbuf_set_primitive;
661bf215546Sopenharmony_ci   cvbr->base.draw_elements = sp_vbuf_draw_elements;
662bf215546Sopenharmony_ci   cvbr->base.draw_arrays = sp_vbuf_draw_arrays;
663bf215546Sopenharmony_ci   cvbr->base.release_vertices = sp_vbuf_release_vertices;
664bf215546Sopenharmony_ci   cvbr->base.set_stream_output_info = sp_vbuf_so_info;
665bf215546Sopenharmony_ci   cvbr->base.pipeline_statistics = sp_vbuf_pipeline_statistics;
666bf215546Sopenharmony_ci   cvbr->base.destroy = sp_vbuf_destroy;
667bf215546Sopenharmony_ci
668bf215546Sopenharmony_ci   cvbr->softpipe = sp;
669bf215546Sopenharmony_ci
670bf215546Sopenharmony_ci   cvbr->setup = sp_setup_create_context(cvbr->softpipe);
671bf215546Sopenharmony_ci
672bf215546Sopenharmony_ci   return &cvbr->base;
673bf215546Sopenharmony_ci}
674