1bf215546Sopenharmony_ci/*
2bf215546Sopenharmony_ci * Copyright 2009 VMware, Inc.
3bf215546Sopenharmony_ci * All Rights Reserved.
4bf215546Sopenharmony_ci *
5bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
6bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"),
7bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation
8bf215546Sopenharmony_ci * on the rights to use, copy, modify, merge, publish, distribute, sub
9bf215546Sopenharmony_ci * license, and/or sell copies of the Software, and to permit persons to whom
10bf215546Sopenharmony_ci * the Software is furnished to do so, subject to the following conditions:
11bf215546Sopenharmony_ci *
12bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next
13bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the
14bf215546Sopenharmony_ci * Software.
15bf215546Sopenharmony_ci *
16bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.  IN NO EVENT SHALL
19bf215546Sopenharmony_ci * VMWARE AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
20bf215546Sopenharmony_ci * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
21bf215546Sopenharmony_ci * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
22bf215546Sopenharmony_ci * USE OR OTHER DEALINGS IN THE SOFTWARE.
23bf215546Sopenharmony_ci */
24bf215546Sopenharmony_ci
25bf215546Sopenharmony_ci#include "u_indices.h"
26bf215546Sopenharmony_ci#include "u_indices_priv.h"
27bf215546Sopenharmony_ci
28bf215546Sopenharmony_cistatic void translate_memcpy_ushort( const void *in,
29bf215546Sopenharmony_ci                                     unsigned start,
30bf215546Sopenharmony_ci                                     unsigned in_nr,
31bf215546Sopenharmony_ci                                     unsigned out_nr,
32bf215546Sopenharmony_ci                                     unsigned restart_index,
33bf215546Sopenharmony_ci                                     void *out )
34bf215546Sopenharmony_ci{
35bf215546Sopenharmony_ci   memcpy(out, &((short *)in)[start], out_nr*sizeof(short));
36bf215546Sopenharmony_ci}
37bf215546Sopenharmony_ci
38bf215546Sopenharmony_cistatic void translate_memcpy_uint( const void *in,
39bf215546Sopenharmony_ci                                   unsigned start,
40bf215546Sopenharmony_ci                                   unsigned in_nr,
41bf215546Sopenharmony_ci                                   unsigned out_nr,
42bf215546Sopenharmony_ci                                   unsigned restart_index,
43bf215546Sopenharmony_ci                                   void *out )
44bf215546Sopenharmony_ci{
45bf215546Sopenharmony_ci   memcpy(out, &((int *)in)[start], out_nr*sizeof(int));
46bf215546Sopenharmony_ci}
47bf215546Sopenharmony_ci
48bf215546Sopenharmony_cistatic void translate_byte_to_ushort( const void *in,
49bf215546Sopenharmony_ci                                      unsigned start,
50bf215546Sopenharmony_ci                                      UNUSED unsigned in_nr,
51bf215546Sopenharmony_ci                                      unsigned out_nr,
52bf215546Sopenharmony_ci                                      UNUSED unsigned restart_index,
53bf215546Sopenharmony_ci                                      void *out )
54bf215546Sopenharmony_ci{
55bf215546Sopenharmony_ci   uint8_t *src = (uint8_t *)in + start;
56bf215546Sopenharmony_ci   uint16_t *dst = out;
57bf215546Sopenharmony_ci   while (out_nr--) {
58bf215546Sopenharmony_ci      *dst++ = *src++;
59bf215546Sopenharmony_ci   }
60bf215546Sopenharmony_ci}
61bf215546Sopenharmony_ci
62bf215546Sopenharmony_cienum pipe_prim_type
63bf215546Sopenharmony_ciu_index_prim_type_convert(unsigned hw_mask, enum pipe_prim_type prim, bool pv_matches)
64bf215546Sopenharmony_ci{
65bf215546Sopenharmony_ci   if ((hw_mask & (1<<prim)) && pv_matches)
66bf215546Sopenharmony_ci      return prim;
67bf215546Sopenharmony_ci
68bf215546Sopenharmony_ci   switch (prim) {
69bf215546Sopenharmony_ci   case PIPE_PRIM_POINTS:
70bf215546Sopenharmony_ci      return PIPE_PRIM_POINTS;
71bf215546Sopenharmony_ci   case PIPE_PRIM_LINES:
72bf215546Sopenharmony_ci   case PIPE_PRIM_LINE_STRIP:
73bf215546Sopenharmony_ci   case PIPE_PRIM_LINE_LOOP:
74bf215546Sopenharmony_ci      return PIPE_PRIM_LINES;
75bf215546Sopenharmony_ci   case PIPE_PRIM_TRIANGLES:
76bf215546Sopenharmony_ci   case PIPE_PRIM_TRIANGLE_STRIP:
77bf215546Sopenharmony_ci   case PIPE_PRIM_TRIANGLE_FAN:
78bf215546Sopenharmony_ci   case PIPE_PRIM_QUADS:
79bf215546Sopenharmony_ci   case PIPE_PRIM_QUAD_STRIP:
80bf215546Sopenharmony_ci   case PIPE_PRIM_POLYGON:
81bf215546Sopenharmony_ci      return PIPE_PRIM_TRIANGLES;
82bf215546Sopenharmony_ci   case PIPE_PRIM_LINES_ADJACENCY:
83bf215546Sopenharmony_ci   case PIPE_PRIM_LINE_STRIP_ADJACENCY:
84bf215546Sopenharmony_ci      return PIPE_PRIM_LINES_ADJACENCY;
85bf215546Sopenharmony_ci   case PIPE_PRIM_TRIANGLES_ADJACENCY:
86bf215546Sopenharmony_ci   case PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY:
87bf215546Sopenharmony_ci      return PIPE_PRIM_TRIANGLES_ADJACENCY;
88bf215546Sopenharmony_ci   case PIPE_PRIM_PATCHES:
89bf215546Sopenharmony_ci      return PIPE_PRIM_PATCHES;
90bf215546Sopenharmony_ci   default:
91bf215546Sopenharmony_ci      assert(0);
92bf215546Sopenharmony_ci      break;
93bf215546Sopenharmony_ci   }
94bf215546Sopenharmony_ci   return PIPE_PRIM_POINTS;
95bf215546Sopenharmony_ci}
96bf215546Sopenharmony_ci
97bf215546Sopenharmony_ci/**
98bf215546Sopenharmony_ci * Translate indexes when a driver can't support certain types
99bf215546Sopenharmony_ci * of drawing.  Example include:
100bf215546Sopenharmony_ci * - Translate 1-byte indexes into 2-byte indexes
101bf215546Sopenharmony_ci * - Translate PIPE_PRIM_QUADS into PIPE_PRIM_TRIANGLES when the hardware
102bf215546Sopenharmony_ci *   doesn't support the former.
103bf215546Sopenharmony_ci * - Translate from first provoking vertex to last provoking vertex and
104bf215546Sopenharmony_ci *   vice versa.
105bf215546Sopenharmony_ci *
106bf215546Sopenharmony_ci * Note that this function is used for indexed primitives.
107bf215546Sopenharmony_ci *
108bf215546Sopenharmony_ci * \param hw_mask  mask of (1 << PIPE_PRIM_x) flags indicating which types
109bf215546Sopenharmony_ci *                 of primitives are supported by the hardware.
110bf215546Sopenharmony_ci * \param prim  incoming PIPE_PRIM_x
111bf215546Sopenharmony_ci * \param in_index_size  bytes per index value (1, 2 or 4)
112bf215546Sopenharmony_ci * \param nr  number of incoming vertices
113bf215546Sopenharmony_ci * \param in_pv  incoming provoking vertex convention (PV_FIRST or PV_LAST)
114bf215546Sopenharmony_ci * \param out_pv  desired provoking vertex convention (PV_FIRST or PV_LAST)
115bf215546Sopenharmony_ci * \param prim_restart  whether primitive restart is disable or enabled
116bf215546Sopenharmony_ci * \param out_prim  returns new PIPE_PRIM_x we'll translate to
117bf215546Sopenharmony_ci * \param out_index_size  returns bytes per new index value (2 or 4)
118bf215546Sopenharmony_ci * \param out_nr  returns number of new vertices
119bf215546Sopenharmony_ci * \param out_translate  returns the translation function to use by the caller
120bf215546Sopenharmony_ci */
121bf215546Sopenharmony_cienum indices_mode
122bf215546Sopenharmony_ciu_index_translator(unsigned hw_mask,
123bf215546Sopenharmony_ci                   enum pipe_prim_type prim,
124bf215546Sopenharmony_ci                   unsigned in_index_size,
125bf215546Sopenharmony_ci                   unsigned nr,
126bf215546Sopenharmony_ci                   unsigned in_pv,
127bf215546Sopenharmony_ci                   unsigned out_pv,
128bf215546Sopenharmony_ci                   unsigned prim_restart,
129bf215546Sopenharmony_ci                   enum pipe_prim_type *out_prim,
130bf215546Sopenharmony_ci                   unsigned *out_index_size,
131bf215546Sopenharmony_ci                   unsigned *out_nr,
132bf215546Sopenharmony_ci                   u_translate_func *out_translate)
133bf215546Sopenharmony_ci{
134bf215546Sopenharmony_ci   unsigned in_idx;
135bf215546Sopenharmony_ci   unsigned out_idx;
136bf215546Sopenharmony_ci   enum indices_mode ret = U_TRANSLATE_NORMAL;
137bf215546Sopenharmony_ci
138bf215546Sopenharmony_ci   assert(in_index_size == 1 ||
139bf215546Sopenharmony_ci          in_index_size == 2 ||
140bf215546Sopenharmony_ci          in_index_size == 4);
141bf215546Sopenharmony_ci
142bf215546Sopenharmony_ci   u_index_init();
143bf215546Sopenharmony_ci
144bf215546Sopenharmony_ci   in_idx = in_size_idx(in_index_size);
145bf215546Sopenharmony_ci   *out_index_size = u_index_size_convert(in_index_size);
146bf215546Sopenharmony_ci   out_idx = out_size_idx(*out_index_size);
147bf215546Sopenharmony_ci
148bf215546Sopenharmony_ci   if ((hw_mask & (1<<prim)) &&
149bf215546Sopenharmony_ci       in_pv == out_pv)
150bf215546Sopenharmony_ci   {
151bf215546Sopenharmony_ci      if (in_index_size == 4)
152bf215546Sopenharmony_ci         *out_translate = translate_memcpy_uint;
153bf215546Sopenharmony_ci      else if (in_index_size == 2)
154bf215546Sopenharmony_ci         *out_translate = translate_memcpy_ushort;
155bf215546Sopenharmony_ci      else
156bf215546Sopenharmony_ci         *out_translate = translate_byte_to_ushort;
157bf215546Sopenharmony_ci
158bf215546Sopenharmony_ci      *out_prim = prim;
159bf215546Sopenharmony_ci      *out_nr = nr;
160bf215546Sopenharmony_ci
161bf215546Sopenharmony_ci      return U_TRANSLATE_MEMCPY;
162bf215546Sopenharmony_ci   }
163bf215546Sopenharmony_ci   *out_translate = translate[in_idx][out_idx][in_pv][out_pv][prim_restart][prim];
164bf215546Sopenharmony_ci   *out_prim = u_index_prim_type_convert(hw_mask, prim, in_pv == out_pv);
165bf215546Sopenharmony_ci   *out_nr = u_index_count_converted_indices(hw_mask, in_pv == out_pv, prim, nr);
166bf215546Sopenharmony_ci
167bf215546Sopenharmony_ci   return ret;
168bf215546Sopenharmony_ci}
169bf215546Sopenharmony_ci
170bf215546Sopenharmony_ciunsigned
171bf215546Sopenharmony_ciu_index_count_converted_indices(unsigned hw_mask, bool pv_matches, enum pipe_prim_type prim, unsigned nr)
172bf215546Sopenharmony_ci{
173bf215546Sopenharmony_ci   if ((hw_mask & (1<<prim)) && pv_matches)
174bf215546Sopenharmony_ci      return nr;
175bf215546Sopenharmony_ci
176bf215546Sopenharmony_ci   switch (prim) {
177bf215546Sopenharmony_ci   case PIPE_PRIM_POINTS:
178bf215546Sopenharmony_ci   case PIPE_PRIM_PATCHES:
179bf215546Sopenharmony_ci      return nr;
180bf215546Sopenharmony_ci   case PIPE_PRIM_LINES:
181bf215546Sopenharmony_ci      return nr;
182bf215546Sopenharmony_ci   case PIPE_PRIM_LINE_STRIP:
183bf215546Sopenharmony_ci      return (nr - 1) * 2;
184bf215546Sopenharmony_ci   case PIPE_PRIM_LINE_LOOP:
185bf215546Sopenharmony_ci      return nr * 2;
186bf215546Sopenharmony_ci   case PIPE_PRIM_TRIANGLES:
187bf215546Sopenharmony_ci      return nr;
188bf215546Sopenharmony_ci   case PIPE_PRIM_TRIANGLE_STRIP:
189bf215546Sopenharmony_ci      return (nr - 2) * 3;
190bf215546Sopenharmony_ci   case PIPE_PRIM_TRIANGLE_FAN:
191bf215546Sopenharmony_ci      return (nr - 2) * 3;
192bf215546Sopenharmony_ci   case PIPE_PRIM_QUADS:
193bf215546Sopenharmony_ci      return (nr / 4) * 6;
194bf215546Sopenharmony_ci   case PIPE_PRIM_QUAD_STRIP:
195bf215546Sopenharmony_ci      return (nr - 2) * 3;
196bf215546Sopenharmony_ci   case PIPE_PRIM_POLYGON:
197bf215546Sopenharmony_ci      return (nr - 2) * 3;
198bf215546Sopenharmony_ci   case PIPE_PRIM_LINES_ADJACENCY:
199bf215546Sopenharmony_ci      return nr;
200bf215546Sopenharmony_ci   case PIPE_PRIM_LINE_STRIP_ADJACENCY:
201bf215546Sopenharmony_ci      return (nr - 3) * 4;
202bf215546Sopenharmony_ci   case PIPE_PRIM_TRIANGLES_ADJACENCY:
203bf215546Sopenharmony_ci      return nr;
204bf215546Sopenharmony_ci   case PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY:
205bf215546Sopenharmony_ci      return ((nr - 4) / 2) * 6;
206bf215546Sopenharmony_ci   default:
207bf215546Sopenharmony_ci      assert(0);
208bf215546Sopenharmony_ci      break;
209bf215546Sopenharmony_ci   }
210bf215546Sopenharmony_ci   return nr;
211bf215546Sopenharmony_ci}
212bf215546Sopenharmony_ci
213bf215546Sopenharmony_ci
214bf215546Sopenharmony_ci/**
215bf215546Sopenharmony_ci * If a driver does not support a particular gallium primitive type
216bf215546Sopenharmony_ci * (such as PIPE_PRIM_QUAD_STRIP) this function can be used to help
217bf215546Sopenharmony_ci * convert the primitive into a simpler type (like PIPE_PRIM_TRIANGLES).
218bf215546Sopenharmony_ci *
219bf215546Sopenharmony_ci * The generator functions generates a number of ushort or uint indexes
220bf215546Sopenharmony_ci * for drawing the new type of primitive.
221bf215546Sopenharmony_ci *
222bf215546Sopenharmony_ci * Note that this function is used for non-indexed primitives.
223bf215546Sopenharmony_ci *
224bf215546Sopenharmony_ci * \param hw_mask  a bitmask of (1 << PIPE_PRIM_x) values that indicates
225bf215546Sopenharmony_ci *                 kind of primitives are supported by the driver.
226bf215546Sopenharmony_ci * \param prim  the PIPE_PRIM_x that the user wants to draw
227bf215546Sopenharmony_ci * \param start  index of first vertex to draw
228bf215546Sopenharmony_ci * \param nr  number of vertices to draw
229bf215546Sopenharmony_ci * \param in_pv  user's provoking vertex (PV_FIRST/LAST)
230bf215546Sopenharmony_ci * \param out_pv  desired proking vertex for the hardware (PV_FIRST/LAST)
231bf215546Sopenharmony_ci * \param out_prim  returns the new primitive type for the driver
232bf215546Sopenharmony_ci * \param out_index_size  returns OUT_USHORT or OUT_UINT
233bf215546Sopenharmony_ci * \param out_nr  returns new number of vertices to draw
234bf215546Sopenharmony_ci * \param out_generate  returns pointer to the generator function
235bf215546Sopenharmony_ci */
236bf215546Sopenharmony_cienum indices_mode
237bf215546Sopenharmony_ciu_index_generator(unsigned hw_mask,
238bf215546Sopenharmony_ci                  enum pipe_prim_type prim,
239bf215546Sopenharmony_ci                  unsigned start,
240bf215546Sopenharmony_ci                  unsigned nr,
241bf215546Sopenharmony_ci                  unsigned in_pv,
242bf215546Sopenharmony_ci                  unsigned out_pv,
243bf215546Sopenharmony_ci                  enum pipe_prim_type *out_prim,
244bf215546Sopenharmony_ci                  unsigned *out_index_size,
245bf215546Sopenharmony_ci                  unsigned *out_nr,
246bf215546Sopenharmony_ci                  u_generate_func *out_generate)
247bf215546Sopenharmony_ci{
248bf215546Sopenharmony_ci   unsigned out_idx;
249bf215546Sopenharmony_ci
250bf215546Sopenharmony_ci   u_index_init();
251bf215546Sopenharmony_ci
252bf215546Sopenharmony_ci   *out_index_size = ((start + nr) > 0xfffe) ? 4 : 2;
253bf215546Sopenharmony_ci   out_idx = out_size_idx(*out_index_size);
254bf215546Sopenharmony_ci   *out_prim = u_index_prim_type_convert(hw_mask, prim, in_pv == out_pv);
255bf215546Sopenharmony_ci   *out_nr = u_index_count_converted_indices(hw_mask, in_pv == out_pv, prim, nr);
256bf215546Sopenharmony_ci
257bf215546Sopenharmony_ci   if ((hw_mask & (1<<prim)) &&
258bf215546Sopenharmony_ci       (in_pv == out_pv)) {
259bf215546Sopenharmony_ci
260bf215546Sopenharmony_ci      *out_generate = generate[out_idx][in_pv][out_pv][PIPE_PRIM_POINTS];
261bf215546Sopenharmony_ci      return U_GENERATE_LINEAR;
262bf215546Sopenharmony_ci   }
263bf215546Sopenharmony_ci   *out_generate = generate[out_idx][in_pv][out_pv][prim];
264bf215546Sopenharmony_ci   return prim == PIPE_PRIM_LINE_LOOP ? U_GENERATE_ONE_OFF : U_GENERATE_REUSABLE;
265bf215546Sopenharmony_ci}
266