xref: /aosp_15_r20/external/mesa3d/src/gallium/auxiliary/indices/u_indices_gen.py (revision 6104692788411f58d303aa86923a9ff6ecaded22)
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