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