1copyright = ''' 2/* 3 * Copyright 2009 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 "Software"), 8 * to deal in the Software without restriction, including without limitation 9 * on the rights to use, copy, modify, merge, publish, distribute, sub 10 * license, and/or sell copies of the Software, and to permit persons to whom 11 * the Software is furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice (including the next 14 * paragraph) shall be included in all copies or substantial portions of the 15 * Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 20 * VMWARE AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, 21 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 22 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 23 * USE OR OTHER DEALINGS IN THE SOFTWARE. 24 */ 25''' 26 27import argparse 28import itertools 29import typing as T 30 31GENERATE, UINT8, UINT16, UINT32 = 'generate', 'uint8', 'uint16', 'uint32' 32FIRST, LAST = 'first', 'last' 33PRDISABLE, PRENABLE = 'prdisable', 'prenable' 34 35INTYPES = (GENERATE, UINT8, UINT16, UINT32) 36OUTTYPES = (UINT16, UINT32) 37PVS=(FIRST, LAST) 38PRS=(PRDISABLE, PRENABLE) 39PRIMS=('points', 40 'lines', 41 'linestrip', 42 'lineloop', 43 'tris', 44 'trifan', 45 'tristrip', 46 'quads', 47 'quadstrip', 48 'polygon', 49 'linesadj', 50 'linestripadj', 51 'trisadj', 52 'tristripadj') 53 54OUT_TRIS, OUT_QUADS = 'tris', 'quads' 55 56LONGPRIMS=('MESA_PRIM_POINTS', 57 'MESA_PRIM_LINES', 58 'MESA_PRIM_LINE_STRIP', 59 'MESA_PRIM_LINE_LOOP', 60 'MESA_PRIM_TRIANGLES', 61 'MESA_PRIM_TRIANGLE_FAN', 62 'MESA_PRIM_TRIANGLE_STRIP', 63 'MESA_PRIM_QUADS', 64 'MESA_PRIM_QUAD_STRIP', 65 'MESA_PRIM_POLYGON', 66 'MESA_PRIM_LINES_ADJACENCY', 67 'MESA_PRIM_LINE_STRIP_ADJACENCY', 68 'MESA_PRIM_TRIANGLES_ADJACENCY', 69 'MESA_PRIM_TRIANGLE_STRIP_ADJACENCY') 70 71longprim = dict(zip(PRIMS, LONGPRIMS)) 72intype_idx = dict(uint8='IN_UINT8', uint16='IN_UINT16', uint32='IN_UINT32') 73outtype_idx = dict(uint16='OUT_UINT16', uint32='OUT_UINT32') 74pv_idx = dict(first='PV_FIRST', last='PV_LAST') 75pr_idx = dict(prdisable='PR_DISABLE', prenable='PR_ENABLE') 76 77def prolog(f: 'T.TextIO') -> None: 78 f.write('/* File automatically generated by u_indices_gen.py */\n') 79 f.write(copyright) 80 f.write(r''' 81 82/** 83 * @file 84 * Functions to translate and generate index lists 85 */ 86 87#include "indices/u_indices_priv.h" 88#include "util/u_debug.h" 89#include "util/u_memory.h" 90 91#include "c99_compat.h" 92 93static u_translate_func translate[IN_COUNT][OUT_COUNT][PV_COUNT][PV_COUNT][PR_COUNT][PRIM_COUNT]; 94static u_generate_func generate[OUT_COUNT][PV_COUNT][PV_COUNT][PRIM_COUNT]; 95 96static u_translate_func translate_quads[IN_COUNT][OUT_COUNT][PV_COUNT][PV_COUNT][PR_COUNT][PRIM_COUNT]; 97static u_generate_func generate_quads[OUT_COUNT][PV_COUNT][PV_COUNT][PRIM_COUNT]; 98 99 100''') 101 102def vert( intype, outtype, v0 ): 103 if intype == GENERATE: 104 return '(' + outtype + '_t)(' + v0 + ')' 105 else: 106 return '(' + outtype + '_t)in[' + v0 + ']' 107 108def shape(f: 'T.TextIO', intype, outtype, ptr, *vertices): 109 for i, v in enumerate(vertices): 110 f.write(f' ({ptr})[{i}] = {vert(intype, outtype, v)};\n') 111 112def do_point(f: 'T.TextIO', intype, outtype, ptr, v0 ): 113 shape(f, intype, outtype, ptr, v0 ) 114 115def do_line(f: 'T.TextIO', intype, outtype, ptr, v0, v1, inpv, outpv ): 116 if inpv == outpv: 117 shape(f, intype, outtype, ptr, v0, v1 ) 118 else: 119 shape(f, intype, outtype, ptr, v1, v0 ) 120 121def do_tri(f: 'T.TextIO', intype, outtype, ptr, v0, v1, v2, inpv, outpv ): 122 if inpv == outpv: 123 shape(f, intype, outtype, ptr, v0, v1, v2 ) 124 elif inpv == FIRST: 125 shape(f, intype, outtype, ptr, v1, v2, v0 ) 126 else: 127 shape(f, intype, outtype, ptr, v2, v0, v1 ) 128 129def do_quad(f: 'T.TextIO', intype, outtype, ptr, v0, v1, v2, v3, inpv, outpv, out_prim ): 130 if out_prim == OUT_TRIS: 131 if inpv == LAST: 132 do_tri(f, intype, outtype, ptr+'+0', v0, v1, v3, inpv, outpv ); 133 do_tri(f, intype, outtype, ptr+'+3', v1, v2, v3, inpv, outpv ); 134 else: 135 do_tri(f, intype, outtype, ptr+'+0', v0, v1, v2, inpv, outpv ); 136 do_tri(f, intype, outtype, ptr+'+3', v0, v2, v3, inpv, outpv ); 137 else: 138 if inpv == outpv: 139 shape(f, intype, outtype, ptr, v0, v1, v2, v3) 140 elif inpv == FIRST: 141 shape(f, intype, outtype, ptr, v1, v2, v3, v0) 142 else: 143 shape(f, intype, outtype, ptr, v3, v0, v1, v2) 144 145def do_lineadj(f: 'T.TextIO', intype, outtype, ptr, v0, v1, v2, v3, inpv, outpv ): 146 if inpv == outpv: 147 shape(f, intype, outtype, ptr, v0, v1, v2, v3 ) 148 else: 149 shape(f, intype, outtype, ptr, v3, v2, v1, v0 ) 150 151def do_triadj(f: 'T.TextIO', intype, outtype, ptr, v0, v1, v2, v3, v4, v5, inpv, outpv ): 152 if inpv == outpv: 153 shape(f, intype, outtype, ptr, v0, v1, v2, v3, v4, v5 ) 154 else: 155 shape(f, intype, outtype, ptr, v4, v5, v0, v1, v2, v3 ) 156 157def name(intype, outtype, inpv, outpv, pr, prim, out_prim): 158 if intype == GENERATE: 159 return 'generate_' + prim + '_' + outtype + '_' + inpv + '2' + outpv + '_' + str(out_prim) 160 else: 161 return 'translate_' + prim + '_' + intype + '2' + outtype + '_' + inpv + '2' + outpv + '_' + pr + '_' + str(out_prim) 162 163def preamble(f: 'T.TextIO', intype, outtype, inpv, outpv, pr, prim, out_prim): 164 f.write('static void ' + name( intype, outtype, inpv, outpv, pr, prim, out_prim ) + '(\n') 165 if intype != GENERATE: 166 f.write(' const void * restrict _in,\n') 167 f.write(' unsigned start,\n') 168 if intype != GENERATE: 169 f.write(' unsigned in_nr,\n') 170 f.write(' unsigned out_nr,\n') 171 if intype != GENERATE: 172 f.write(' unsigned restart_index,\n') 173 f.write(' void * restrict _out )\n') 174 f.write('{\n') 175 if intype != GENERATE: 176 f.write(' const ' + intype + '_t* restrict in = (const ' + intype + '_t* restrict)_in;\n') 177 f.write(' ' + outtype + '_t * restrict out = (' + outtype + '_t* restrict)_out;\n') 178 f.write(' unsigned i, j;\n') 179 f.write(' (void)j;\n') 180 181def postamble(f: 'T.TextIO'): 182 f.write('}\n') 183 184def prim_restart(f: 'T.TextIO', in_verts, out_verts, out_prims, close_func = None): 185 f.write('restart:\n') 186 f.write(' if (i + ' + str(in_verts) + ' > in_nr) {\n') 187 for i, j in itertools.product(range(out_prims), range(out_verts)): 188 f.write(' (out+j+' + str(out_verts * i) + ')[' + str(j) + '] = restart_index;\n') 189 f.write(' continue;\n') 190 f.write(' }\n') 191 for i in range(in_verts): 192 f.write(' if (in[i + ' + str(i) + '] == restart_index) {\n') 193 f.write(' i += ' + str(i + 1) + ';\n') 194 195 if close_func is not None: 196 close_func(i) 197 198 f.write(' goto restart;\n') 199 f.write(' }\n') 200 201def points(f: 'T.TextIO', intype, outtype, inpv, outpv, pr): 202 preamble(f, intype, outtype, inpv, outpv, pr, out_prim=OUT_TRIS, prim='points') 203 f.write(' for (i = start, j = 0; j < out_nr; j++, i++) {\n') 204 do_point(f, intype, outtype, 'out+j', 'i' ); 205 f.write(' }\n') 206 postamble(f) 207 208def lines(f: 'T.TextIO', intype, outtype, inpv, outpv, pr): 209 preamble(f, intype, outtype, inpv, outpv, pr, out_prim=OUT_TRIS, prim='lines') 210 f.write(' for (i = start, j = 0; j < out_nr; j+=2, i+=2) {\n') 211 do_line(f, intype, outtype, 'out+j', 'i', 'i+1', inpv, outpv ); 212 f.write(' }\n') 213 postamble(f) 214 215def linestrip(f: 'T.TextIO', intype, outtype, inpv, outpv, pr): 216 preamble(f, intype, outtype, inpv, outpv, pr, out_prim=OUT_TRIS, prim='linestrip') 217 f.write(' for (i = start, j = 0; j < out_nr; j+=2, i++) {\n') 218 do_line(f, intype, outtype, 'out+j', 'i', 'i+1', inpv, outpv ); 219 f.write(' }\n') 220 postamble(f) 221 222def lineloop(f: 'T.TextIO', intype, outtype, inpv, outpv, pr): 223 preamble(f, intype, outtype, inpv, outpv, pr, out_prim=OUT_TRIS, prim='lineloop') 224 f.write(' unsigned end = start;\n') 225 f.write(' for (i = start, j = 0; j < out_nr - 2; j+=2, i++) {\n') 226 if pr == PRENABLE: 227 def close_func(index): 228 do_line(f, intype, outtype, 'out+j', 'end', 'start', inpv, outpv ) 229 f.write(' start = i;\n') 230 f.write(' end = start;\n') 231 f.write(' j += 2;\n') 232 233 prim_restart(f, 2, 2, 1, close_func) 234 235 do_line(f, intype, outtype, 'out+j', 'i', 'i+1', inpv, outpv ); 236 f.write(' end = i+1;\n') 237 f.write(' }\n') 238 do_line(f, intype, outtype, 'out+j', 'end', 'start', inpv, outpv ); 239 postamble(f) 240 241def tris(f: 'T.TextIO', intype, outtype, inpv, outpv, pr): 242 preamble(f, intype, outtype, inpv, outpv, pr, out_prim=OUT_TRIS, prim='tris') 243 f.write(' for (i = start, j = 0; j < out_nr; j+=3, i+=3) {\n') 244 do_tri(f, intype, outtype, 'out+j', 'i', 'i+1', 'i+2', inpv, outpv ); 245 f.write(' }\n') 246 postamble(f) 247 248 249def tristrip(f: 'T.TextIO', intype, outtype, inpv, outpv, pr): 250 preamble(f, intype, outtype, inpv, outpv, pr, out_prim=OUT_TRIS, prim='tristrip') 251 f.write(' for (i = start, j = 0; j < out_nr; j+=3, i++) {\n') 252 if inpv == FIRST: 253 do_tri(f, intype, outtype, 'out+j', 'i', 'i+1+(i&1)', 'i+2-(i&1)', inpv, outpv ); 254 else: 255 do_tri(f, intype, outtype, 'out+j', 'i+(i&1)', 'i+1-(i&1)', 'i+2', inpv, outpv ); 256 f.write(' }\n') 257 postamble(f) 258 259 260def trifan(f: 'T.TextIO', intype, outtype, inpv, outpv, pr): 261 preamble(f, intype, outtype, inpv, outpv, pr, out_prim=OUT_TRIS, prim='trifan') 262 f.write(' for (i = start, j = 0; j < out_nr; j+=3, i++) {\n') 263 264 if pr == PRENABLE: 265 def close_func(index): 266 f.write(' start = i;\n') 267 prim_restart(f, 3, 3, 1, close_func) 268 269 if inpv == FIRST: 270 do_tri(f, intype, outtype, 'out+j', 'i+1', 'i+2', 'start', inpv, outpv ); 271 else: 272 do_tri(f, intype, outtype, 'out+j', 'start', 'i+1', 'i+2', inpv, outpv ); 273 274 f.write(' }') 275 postamble(f) 276 277 278 279def polygon(f: 'T.TextIO', intype, outtype, inpv, outpv, pr): 280 preamble(f, intype, outtype, inpv, outpv, pr, out_prim=OUT_TRIS, prim='polygon') 281 f.write(' for (i = start, j = 0; j < out_nr; j+=3, i++) {\n') 282 if pr == PRENABLE: 283 def close_func(index): 284 f.write(' start = i;\n') 285 prim_restart(f, 3, 3, 1, close_func) 286 287 if inpv == FIRST: 288 do_tri(f, intype, outtype, 'out+j', 'start', 'i+1', 'i+2', inpv, outpv ); 289 else: 290 do_tri(f, intype, outtype, 'out+j', 'i+1', 'i+2', 'start', inpv, outpv ); 291 f.write(' }') 292 postamble(f) 293 294 295def quads(f: 'T.TextIO', intype, outtype, inpv, outpv, pr, out_prim): 296 preamble(f, intype, outtype, inpv, outpv, pr, out_prim=out_prim, prim='quads') 297 if out_prim == OUT_TRIS: 298 f.write(' for (i = start, j = 0; j < out_nr; j+=6, i+=4) {\n') 299 else: 300 f.write(' for (i = start, j = 0; j < out_nr; j+=4, i+=4) {\n') 301 if pr == PRENABLE and out_prim == OUT_TRIS: 302 prim_restart(f, 4, 3, 2) 303 elif pr == PRENABLE: 304 prim_restart(f, 4, 4, 1) 305 306 do_quad(f, intype, outtype, 'out+j', 'i+0', 'i+1', 'i+2', 'i+3', inpv, outpv, out_prim ); 307 f.write(' }\n') 308 postamble(f) 309 310 311def quadstrip(f: 'T.TextIO', intype, outtype, inpv, outpv, pr, out_prim): 312 preamble(f, intype, outtype, inpv, outpv, pr, out_prim=out_prim, prim='quadstrip') 313 if out_prim == OUT_TRIS: 314 f.write(' for (i = start, j = 0; j < out_nr; j+=6, i+=2) {\n') 315 else: 316 f.write(' for (i = start, j = 0; j < out_nr; j+=4, i+=2) {\n') 317 if pr == PRENABLE and out_prim == OUT_TRIS: 318 prim_restart(f, 4, 3, 2) 319 elif pr == PRENABLE: 320 prim_restart(f, 4, 4, 1) 321 322 if inpv == LAST: 323 do_quad(f, intype, outtype, 'out+j', 'i+2', 'i+0', 'i+1', 'i+3', inpv, outpv, out_prim ); 324 else: 325 do_quad(f, intype, outtype, 'out+j', 'i+0', 'i+1', 'i+3', 'i+2', inpv, outpv, out_prim ); 326 f.write(' }\n') 327 postamble(f) 328 329 330def linesadj(f: 'T.TextIO', intype, outtype, inpv, outpv, pr): 331 preamble(f, intype, outtype, inpv, outpv, pr, out_prim=OUT_TRIS, prim='linesadj') 332 f.write(' for (i = start, j = 0; j < out_nr; j+=4, i+=4) {\n') 333 do_lineadj(f, intype, outtype, 'out+j', 'i+0', 'i+1', 'i+2', 'i+3', inpv, outpv ) 334 f.write(' }\n') 335 postamble(f) 336 337 338def linestripadj(f: 'T.TextIO', intype, outtype, inpv, outpv, pr): 339 preamble(f, intype, outtype, inpv, outpv, pr, out_prim=OUT_TRIS, prim='linestripadj') 340 f.write(' for (i = start, j = 0; j < out_nr; j+=4, i++) {\n') 341 do_lineadj(f, intype, outtype, 'out+j', 'i+0', 'i+1', 'i+2', 'i+3', inpv, outpv ) 342 f.write(' }\n') 343 postamble(f) 344 345 346def trisadj(f: 'T.TextIO', intype, outtype, inpv, outpv, pr): 347 preamble(f, intype, outtype, inpv, outpv, pr, out_prim=OUT_TRIS, prim='trisadj') 348 f.write(' for (i = start, j = 0; j < out_nr; j+=6, i+=6) {\n') 349 do_triadj(f, intype, outtype, 'out+j', 'i+0', 'i+1', 'i+2', 'i+3', 350 'i+4', 'i+5', inpv, outpv ) 351 f.write(' }\n') 352 postamble(f) 353 354 355def tristripadj(f: 'T.TextIO', intype, outtype, inpv, outpv, pr): 356 preamble(f, intype, outtype, inpv, outpv, pr, out_prim=OUT_TRIS, prim='tristripadj') 357 f.write(' for (i = start, j = 0; j < out_nr; i+=2, j+=6) {\n') 358 f.write(' if (i % 4 == 0) {\n') 359 f.write(' /* even triangle */\n') 360 do_triadj(f, intype, outtype, 'out+j', 361 'i+0', 'i+1', 'i+2', 'i+3', 'i+4', 'i+5', inpv, outpv ) 362 f.write(' } else {\n') 363 f.write(' /* odd triangle */\n') 364 do_triadj(f, intype, outtype, 'out+j', 365 'i+2', 'i-2', 'i+0', 'i+3', 'i+4', 'i+6', inpv, outpv ) 366 f.write(' }\n') 367 f.write(' }\n') 368 postamble(f) 369 370 371def emit_funcs(f: 'T.TextIO') -> None: 372 for intype, outtype, inpv, outpv, pr in itertools.product( 373 INTYPES, OUTTYPES, [FIRST, LAST], [FIRST, LAST], [PRDISABLE, PRENABLE]): 374 if pr == PRENABLE and intype == GENERATE: 375 continue 376 points(f, intype, outtype, inpv, outpv, pr) 377 lines(f, intype, outtype, inpv, outpv, pr) 378 linestrip(f, intype, outtype, inpv, outpv, pr) 379 lineloop(f, intype, outtype, inpv, outpv, pr) 380 tris(f, intype, outtype, inpv, outpv, pr) 381 tristrip(f, intype, outtype, inpv, outpv, pr) 382 trifan(f, intype, outtype, inpv, outpv, pr) 383 quads(f, intype, outtype, inpv, outpv, pr, OUT_TRIS) 384 quadstrip(f, intype, outtype, inpv, outpv, pr, OUT_TRIS) 385 polygon(f, intype, outtype, inpv, outpv, pr) 386 linesadj(f, intype, outtype, inpv, outpv, pr) 387 linestripadj(f, intype, outtype, inpv, outpv, pr) 388 trisadj(f, intype, outtype, inpv, outpv, pr) 389 tristripadj(f, intype, outtype, inpv, outpv, pr) 390 391 for intype, outtype, inpv, outpv, pr in itertools.product( 392 INTYPES, OUTTYPES, [FIRST, LAST], [FIRST, LAST], [PRDISABLE, PRENABLE]): 393 if pr == PRENABLE and intype == GENERATE: 394 continue 395 quads(f, intype, outtype, inpv, outpv, pr, OUT_QUADS) 396 quadstrip(f, intype, outtype, inpv, outpv, pr, OUT_QUADS) 397 398def init(f: 'T.TextIO', intype, outtype, inpv, outpv, pr, prim, out_prim=OUT_TRIS): 399 generate_name = 'generate' 400 translate_name = 'translate' 401 if out_prim == OUT_QUADS: 402 generate_name = 'generate_quads' 403 translate_name = 'translate_quads' 404 405 if intype == GENERATE: 406 f.write(f'{generate_name}[' + 407 outtype_idx[outtype] + 408 '][' + pv_idx[inpv] + 409 '][' + pv_idx[outpv] + 410 '][' + longprim[prim] + 411 '] = ' + name( intype, outtype, inpv, outpv, pr, prim, out_prim ) + ';\n') 412 else: 413 f.write(f'{translate_name}[' + 414 intype_idx[intype] + 415 '][' + outtype_idx[outtype] + 416 '][' + pv_idx[inpv] + 417 '][' + pv_idx[outpv] + 418 '][' + pr_idx[pr] + 419 '][' + longprim[prim] + 420 '] = ' + name( intype, outtype, inpv, outpv, pr, prim, out_prim ) + ';\n') 421 422 423def emit_all_inits(f: 'T.TextIO'): 424 for intype, outtype, inpv, outpv, pr, prim in itertools.product( 425 INTYPES, OUTTYPES, PVS, PVS, PRS, PRIMS): 426 init(f,intype, outtype, inpv, outpv, pr, prim) 427 428 for intype, outtype, inpv, outpv, pr, prim in itertools.product( 429 INTYPES, OUTTYPES, PVS, PVS, PRS, ['quads', 'quadstrip']): 430 init(f,intype, outtype, inpv, outpv, pr, prim, OUT_QUADS) 431 432def emit_init(f: 'T.TextIO'): 433 f.write('void u_index_init( void )\n') 434 f.write('{\n') 435 f.write(' static int firsttime = 1;\n') 436 f.write(' if (!firsttime) return;\n') 437 f.write(' firsttime = 0;\n') 438 emit_all_inits(f) 439 f.write('}\n') 440 441 442 443 444def epilog(f: 'T.TextIO') -> None: 445 f.write('#include "indices/u_indices.c"\n') 446 447 448def main(): 449 parser = argparse.ArgumentParser() 450 parser.add_argument('output') 451 args = parser.parse_args() 452 453 with open(args.output, 'w') as f: 454 prolog(f) 455 emit_funcs(f) 456 emit_init(f) 457 epilog(f) 458 459 460if __name__ == '__main__': 461 main() 462