u_indices.c revision af69d88d
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 28static void translate_memcpy_ushort( const void *in, 29 unsigned start, 30 unsigned nr, 31 void *out ) 32{ 33 memcpy(out, &((short *)in)[start], nr*sizeof(short)); 34} 35 36static void translate_memcpy_uint( const void *in, 37 unsigned start, 38 unsigned nr, 39 void *out ) 40{ 41 memcpy(out, &((int *)in)[start], nr*sizeof(int)); 42} 43 44 45/** 46 * Translate indexes when a driver can't support certain types 47 * of drawing. Example include: 48 * - Translate 1-byte indexes into 2-byte indexes 49 * - Translate PIPE_PRIM_QUADS into PIPE_PRIM_TRIANGLES when the hardware 50 * doesn't support the former. 51 * - Translate from first provoking vertex to last provoking vertex and 52 * vice versa. 53 * 54 * \param hw_mask mask of (1 << PIPE_PRIM_x) flags indicating which types 55 * of primitives are supported by the hardware. 56 * \param prim incoming PIPE_PRIM_x 57 * \param in_index_size bytes per index value (1, 2 or 4) 58 * \param nr number of incoming vertices 59 * \param in_pv incoming provoking vertex convention (PV_FIRST or PV_LAST) 60 * \param out_pv desired provoking vertex convention (PV_FIRST or PV_LAST) 61 * \param out_prim returns new PIPE_PRIM_x we'll translate to 62 * \param out_index_size returns bytes per new index value (2 or 4) 63 * \param out_nr returns number of new vertices 64 * \param out_translate returns the translation function to use by the caller 65 */ 66int u_index_translator( unsigned hw_mask, 67 unsigned prim, 68 unsigned in_index_size, 69 unsigned nr, 70 unsigned in_pv, 71 unsigned out_pv, 72 unsigned *out_prim, 73 unsigned *out_index_size, 74 unsigned *out_nr, 75 u_translate_func *out_translate ) 76{ 77 unsigned in_idx; 78 unsigned out_idx; 79 int ret = U_TRANSLATE_NORMAL; 80 81 assert(in_index_size == 1 || 82 in_index_size == 2 || 83 in_index_size == 4); 84 85 u_index_init(); 86 87 in_idx = in_size_idx(in_index_size); 88 *out_index_size = (in_index_size == 4) ? 4 : 2; 89 out_idx = out_size_idx(*out_index_size); 90 91 if ((hw_mask & (1<<prim)) && 92 in_index_size == *out_index_size && 93 in_pv == out_pv) 94 { 95 /* Index translation not really needed */ 96 if (in_index_size == 4) 97 *out_translate = translate_memcpy_uint; 98 else 99 *out_translate = translate_memcpy_ushort; 100 101 *out_prim = prim; 102 *out_nr = nr; 103 104 return U_TRANSLATE_MEMCPY; 105 } 106 else { 107 switch (prim) { 108 case PIPE_PRIM_POINTS: 109 *out_translate = translate[in_idx][out_idx][in_pv][out_pv][prim]; 110 *out_prim = PIPE_PRIM_POINTS; 111 *out_nr = nr; 112 break; 113 114 case PIPE_PRIM_LINES: 115 *out_translate = translate[in_idx][out_idx][in_pv][out_pv][prim]; 116 *out_prim = PIPE_PRIM_LINES; 117 *out_nr = nr; 118 break; 119 120 case PIPE_PRIM_LINE_STRIP: 121 *out_translate = translate[in_idx][out_idx][in_pv][out_pv][prim]; 122 *out_prim = PIPE_PRIM_LINES; 123 *out_nr = (nr - 1) * 2; 124 break; 125 126 case PIPE_PRIM_LINE_LOOP: 127 *out_translate = translate[in_idx][out_idx][in_pv][out_pv][prim]; 128 *out_prim = PIPE_PRIM_LINES; 129 *out_nr = nr * 2; 130 break; 131 132 case PIPE_PRIM_TRIANGLES: 133 *out_translate = translate[in_idx][out_idx][in_pv][out_pv][prim]; 134 *out_prim = PIPE_PRIM_TRIANGLES; 135 *out_nr = nr; 136 break; 137 138 case PIPE_PRIM_TRIANGLE_STRIP: 139 *out_translate = translate[in_idx][out_idx][in_pv][out_pv][prim]; 140 *out_prim = PIPE_PRIM_TRIANGLES; 141 *out_nr = (nr - 2) * 3; 142 break; 143 144 case PIPE_PRIM_TRIANGLE_FAN: 145 *out_translate = translate[in_idx][out_idx][in_pv][out_pv][prim]; 146 *out_prim = PIPE_PRIM_TRIANGLES; 147 *out_nr = (nr - 2) * 3; 148 break; 149 150 case PIPE_PRIM_QUADS: 151 *out_translate = translate[in_idx][out_idx][in_pv][out_pv][prim]; 152 *out_prim = PIPE_PRIM_TRIANGLES; 153 *out_nr = (nr / 4) * 6; 154 break; 155 156 case PIPE_PRIM_QUAD_STRIP: 157 *out_translate = translate[in_idx][out_idx][in_pv][out_pv][prim]; 158 *out_prim = PIPE_PRIM_TRIANGLES; 159 *out_nr = (nr - 2) * 3; 160 break; 161 162 case PIPE_PRIM_POLYGON: 163 *out_translate = translate[in_idx][out_idx][in_pv][out_pv][prim]; 164 *out_prim = PIPE_PRIM_TRIANGLES; 165 *out_nr = (nr - 2) * 3; 166 break; 167 168 default: 169 assert(0); 170 *out_translate = translate[in_idx][out_idx][in_pv][out_pv][prim]; 171 *out_prim = PIPE_PRIM_POINTS; 172 *out_nr = nr; 173 return U_TRANSLATE_ERROR; 174 } 175 } 176 177 return ret; 178} 179 180 181/** 182 * If a driver does not support a particular gallium primitive type 183 * (such as PIPE_PRIM_QUAD_STRIP) this function can be used to help 184 * convert the primitive into a simpler type (like PIPE_PRIM_TRIANGLES). 185 * 186 * The generator functions generates a number of ushort or uint indexes 187 * for drawing the new type of primitive. 188 * 189 * \param hw_mask a bitmask of (1 << PIPE_PRIM_x) values that indicates 190 * kind of primitives are supported by the driver. 191 * \param prim the PIPE_PRIM_x that the user wants to draw 192 * \param start index of first vertex to draw 193 * \param nr number of vertices to draw 194 * \param in_pv user's provoking vertex (PV_FIRST/LAST) 195 * \param out_pv desired proking vertex for the hardware (PV_FIRST/LAST) 196 * \param out_prim returns the new primitive type for the driver 197 * \param out_index_size returns OUT_USHORT or OUT_UINT 198 * \param out_nr returns new number of vertices to draw 199 * \param out_generate returns pointer to the generator function 200 */ 201int u_index_generator( unsigned hw_mask, 202 unsigned prim, 203 unsigned start, 204 unsigned nr, 205 unsigned in_pv, 206 unsigned out_pv, 207 unsigned *out_prim, 208 unsigned *out_index_size, 209 unsigned *out_nr, 210 u_generate_func *out_generate ) 211 212{ 213 unsigned out_idx; 214 215 u_index_init(); 216 217 *out_index_size = ((start + nr) > 0xfffe) ? 4 : 2; 218 out_idx = out_size_idx(*out_index_size); 219 220 if ((hw_mask & (1<<prim)) && 221 (in_pv == out_pv)) { 222 223 *out_generate = generate[out_idx][in_pv][out_pv][PIPE_PRIM_POINTS]; 224 *out_prim = prim; 225 *out_nr = nr; 226 return U_GENERATE_LINEAR; 227 } 228 else { 229 switch (prim) { 230 case PIPE_PRIM_POINTS: 231 *out_generate = generate[out_idx][in_pv][out_pv][prim]; 232 *out_prim = PIPE_PRIM_POINTS; 233 *out_nr = nr; 234 return U_GENERATE_REUSABLE; 235 236 case PIPE_PRIM_LINES: 237 *out_generate = generate[out_idx][in_pv][out_pv][prim]; 238 *out_prim = PIPE_PRIM_LINES; 239 *out_nr = nr; 240 return U_GENERATE_REUSABLE; 241 242 case PIPE_PRIM_LINE_STRIP: 243 *out_generate = generate[out_idx][in_pv][out_pv][prim]; 244 *out_prim = PIPE_PRIM_LINES; 245 *out_nr = (nr - 1) * 2; 246 return U_GENERATE_REUSABLE; 247 248 case PIPE_PRIM_LINE_LOOP: 249 *out_generate = generate[out_idx][in_pv][out_pv][prim]; 250 *out_prim = PIPE_PRIM_LINES; 251 *out_nr = nr * 2; 252 return U_GENERATE_ONE_OFF; 253 254 case PIPE_PRIM_TRIANGLES: 255 *out_generate = generate[out_idx][in_pv][out_pv][prim]; 256 *out_prim = PIPE_PRIM_TRIANGLES; 257 *out_nr = nr; 258 return U_GENERATE_REUSABLE; 259 260 case PIPE_PRIM_TRIANGLE_STRIP: 261 *out_generate = generate[out_idx][in_pv][out_pv][prim]; 262 *out_prim = PIPE_PRIM_TRIANGLES; 263 *out_nr = (nr - 2) * 3; 264 return U_GENERATE_REUSABLE; 265 266 case PIPE_PRIM_TRIANGLE_FAN: 267 *out_generate = generate[out_idx][in_pv][out_pv][prim]; 268 *out_prim = PIPE_PRIM_TRIANGLES; 269 *out_nr = (nr - 2) * 3; 270 return U_GENERATE_REUSABLE; 271 272 case PIPE_PRIM_QUADS: 273 *out_generate = generate[out_idx][in_pv][out_pv][prim]; 274 *out_prim = PIPE_PRIM_TRIANGLES; 275 *out_nr = (nr / 4) * 6; 276 return U_GENERATE_REUSABLE; 277 278 case PIPE_PRIM_QUAD_STRIP: 279 *out_generate = generate[out_idx][in_pv][out_pv][prim]; 280 *out_prim = PIPE_PRIM_TRIANGLES; 281 *out_nr = (nr - 2) * 3; 282 return U_GENERATE_REUSABLE; 283 284 case PIPE_PRIM_POLYGON: 285 *out_generate = generate[out_idx][in_pv][out_pv][prim]; 286 *out_prim = PIPE_PRIM_TRIANGLES; 287 *out_nr = (nr - 2) * 3; 288 return U_GENERATE_REUSABLE; 289 290 default: 291 assert(0); 292 *out_generate = generate[out_idx][in_pv][out_pv][PIPE_PRIM_POINTS]; 293 *out_prim = PIPE_PRIM_POINTS; 294 *out_nr = nr; 295 return U_TRANSLATE_ERROR; 296 } 297 } 298} 299