python: Fix rich comparisons
[mesa.git] / src / mapi / mapi_abi.py
1
2 # Mesa 3-D graphics library
3 #
4 # Copyright (C) 2010 LunarG Inc.
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 # the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 # and/or sell copies of the Software, and to permit persons to whom the
11 # Software is furnished to do so, subject to the following conditions:
12 #
13 # The above copyright notice and this permission notice shall be included
14 # in all copies or substantial portions of the 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 NONINFRINGEMENT. IN NO EVENT SHALL
19 # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 # DEALINGS IN THE SOFTWARE.
23 #
24 # Authors:
25 # Chia-I Wu <olv@lunarg.com>
26
27 from __future__ import print_function
28
29 import sys
30 # make it possible to import glapi
31 import os
32 GLAPI = os.path.join(".", os.path.dirname(sys.argv[0]), "glapi/gen")
33 sys.path.append(GLAPI)
34
35 import re
36 from optparse import OptionParser
37 import gl_XML
38 import glX_XML
39
40
41 # number of dynamic entries
42 ABI_NUM_DYNAMIC_ENTRIES = 256
43
44 class ABIEntry(object):
45 """Represent an ABI entry."""
46
47 _match_c_param = re.compile(
48 '^(?P<type>[\w\s*]+?)(?P<name>\w+)(\[(?P<array>\d+)\])?$')
49
50 def __init__(self, cols, attrs, xml_data = None):
51 self._parse(cols)
52
53 self.slot = attrs['slot']
54 self.hidden = attrs['hidden']
55 self.alias = attrs['alias']
56 self.handcode = attrs['handcode']
57 self.xml_data = xml_data
58
59 def c_prototype(self):
60 return '%s %s(%s)' % (self.c_return(), self.name, self.c_params())
61
62 def c_return(self):
63 ret = self.ret
64 if not ret:
65 ret = 'void'
66
67 return ret
68
69 def c_params(self):
70 """Return the parameter list used in the entry prototype."""
71 c_params = []
72 for t, n, a in self.params:
73 sep = '' if t.endswith('*') else ' '
74 arr = '[%d]' % a if a else ''
75 c_params.append(t + sep + n + arr)
76 if not c_params:
77 c_params.append('void')
78
79 return ", ".join(c_params)
80
81 def c_args(self):
82 """Return the argument list used in the entry invocation."""
83 c_args = []
84 for t, n, a in self.params:
85 c_args.append(n)
86
87 return ", ".join(c_args)
88
89 def _parse(self, cols):
90 ret = cols.pop(0)
91 if ret == 'void':
92 ret = None
93
94 name = cols.pop(0)
95
96 params = []
97 if not cols:
98 raise Exception(cols)
99 elif len(cols) == 1 and cols[0] == 'void':
100 pass
101 else:
102 for val in cols:
103 params.append(self._parse_param(val))
104
105 self.ret = ret
106 self.name = name
107 self.params = params
108
109 def _parse_param(self, c_param):
110 m = self._match_c_param.match(c_param)
111 if not m:
112 raise Exception('unrecognized param ' + c_param)
113
114 c_type = m.group('type').strip()
115 c_name = m.group('name')
116 c_array = m.group('array')
117 c_array = int(c_array) if c_array else 0
118
119 return (c_type, c_name, c_array)
120
121 def __str__(self):
122 return self.c_prototype()
123
124 def __lt__(self, other):
125 # compare slot, alias, and then name
126 if self.slot == other.slot:
127 if not self.alias:
128 return True
129 elif not other.alias:
130 return False
131
132 return self.name < other.name
133
134 return self.slot < other.slot
135
136
137 def abi_parse_xml(xml):
138 """Parse a GLAPI XML file for ABI entries."""
139 api = gl_XML.parse_GL_API(xml, glX_XML.glx_item_factory())
140
141 entry_dict = {}
142 for func in api.functionIterateByOffset():
143 # make sure func.name appear first
144 entry_points = func.entry_points[:]
145 entry_points.remove(func.name)
146 entry_points.insert(0, func.name)
147
148 for name in entry_points:
149 attrs = {
150 'slot': func.offset,
151 'hidden': not func.is_static_entry_point(name),
152 'alias': None if name == func.name else func.name,
153 'handcode': bool(func.has_different_protocol(name)),
154 }
155
156 # post-process attrs
157 if attrs['alias']:
158 try:
159 alias = entry_dict[attrs['alias']]
160 except KeyError:
161 raise Exception('failed to alias %s' % attrs['alias'])
162 if alias.alias:
163 raise Exception('recursive alias %s' % ent.name)
164 attrs['alias'] = alias
165 if attrs['handcode']:
166 attrs['handcode'] = func.static_glx_name(name)
167 else:
168 attrs['handcode'] = None
169
170 if name in entry_dict:
171 raise Exception('%s is duplicated' % (name))
172
173 cols = []
174 cols.append(func.return_type)
175 cols.append(name)
176 params = func.get_parameter_string(name)
177 cols.extend([p.strip() for p in params.split(',')])
178
179 ent = ABIEntry(cols, attrs, func)
180 entry_dict[ent.name] = ent
181
182 entries = sorted(entry_dict.values())
183
184 return entries
185
186 def abi_parse_line(line):
187 cols = [col.strip() for col in line.split(',')]
188
189 attrs = {
190 'slot': -1,
191 'hidden': False,
192 'alias': None,
193 'handcode': None,
194 }
195
196 # extract attributes from the first column
197 vals = cols[0].split(':')
198 while len(vals) > 1:
199 val = vals.pop(0)
200 if val.startswith('slot='):
201 attrs['slot'] = int(val[5:])
202 elif val == 'hidden':
203 attrs['hidden'] = True
204 elif val.startswith('alias='):
205 attrs['alias'] = val[6:]
206 elif val.startswith('handcode='):
207 attrs['handcode'] = val[9:]
208 elif not val:
209 pass
210 else:
211 raise Exception('unknown attribute %s' % val)
212 cols[0] = vals[0]
213
214 return (attrs, cols)
215
216 def abi_parse(filename):
217 """Parse a CSV file for ABI entries."""
218 fp = open(filename) if filename != '-' else sys.stdin
219 lines = [line.strip() for line in fp.readlines()
220 if not line.startswith('#') and line.strip()]
221
222 entry_dict = {}
223 next_slot = 0
224 for line in lines:
225 attrs, cols = abi_parse_line(line)
226
227 # post-process attributes
228 if attrs['alias']:
229 try:
230 alias = entry_dict[attrs['alias']]
231 except KeyError:
232 raise Exception('failed to alias %s' % attrs['alias'])
233 if alias.alias:
234 raise Exception('recursive alias %s' % ent.name)
235 slot = alias.slot
236 attrs['alias'] = alias
237 else:
238 slot = next_slot
239 next_slot += 1
240
241 if attrs['slot'] < 0:
242 attrs['slot'] = slot
243 elif attrs['slot'] != slot:
244 raise Exception('invalid slot in %s' % (line))
245
246 ent = ABIEntry(cols, attrs)
247 if ent.name in entry_dict:
248 raise Exception('%s is duplicated' % (ent.name))
249 entry_dict[ent.name] = ent
250
251 entries = sorted(entry_dict.values())
252
253 return entries
254
255 def abi_sanity_check(entries):
256 if not entries:
257 return
258
259 all_names = []
260 last_slot = entries[-1].slot
261 i = 0
262 for slot in range(last_slot + 1):
263 if entries[i].slot != slot:
264 raise Exception('entries are not ordered by slots')
265 if entries[i].alias:
266 raise Exception('first entry of slot %d aliases %s'
267 % (slot, entries[i].alias.name))
268 handcode = None
269 while i < len(entries) and entries[i].slot == slot:
270 ent = entries[i]
271 if not handcode and ent.handcode:
272 handcode = ent.handcode
273 elif ent.handcode != handcode:
274 raise Exception('two aliases with handcode %s != %s',
275 ent.handcode, handcode)
276
277 if ent.name in all_names:
278 raise Exception('%s is duplicated' % (ent.name))
279 if ent.alias and ent.alias.name not in all_names:
280 raise Exception('failed to alias %s' % (ent.alias.name))
281 all_names.append(ent.name)
282 i += 1
283 if i < len(entries):
284 raise Exception('there are %d invalid entries' % (len(entries) - 1))
285
286 class ABIPrinter(object):
287 """MAPI Printer"""
288
289 def __init__(self, entries):
290 self.entries = entries
291
292 # sort entries by their names
293 self.entries_sorted_by_names = self.entries[:]
294 self.entries_sorted_by_names.sort(lambda x, y: cmp(x.name, y.name))
295
296 self.indent = ' ' * 3
297 self.noop_warn = 'noop_warn'
298 self.noop_generic = 'noop_generic'
299 self.current_get = 'entry_current_get'
300
301 self.api_defines = []
302 self.api_headers = ['"KHR/khrplatform.h"']
303 self.api_call = 'KHRONOS_APICALL'
304 self.api_entry = 'KHRONOS_APIENTRY'
305 self.api_attrs = 'KHRONOS_APIATTRIBUTES'
306
307 self.c_header = ''
308
309 self.lib_need_table_size = True
310 self.lib_need_noop_array = True
311 self.lib_need_stubs = True
312 self.lib_need_all_entries = True
313 self.lib_need_non_hidden_entries = False
314
315 def c_notice(self):
316 return '/* This file is automatically generated by mapi_abi.py. Do not modify. */'
317
318 def c_public_includes(self):
319 """Return includes of the client API headers."""
320 defines = ['#define ' + d for d in self.api_defines]
321 includes = ['#include ' + h for h in self.api_headers]
322 return "\n".join(defines + includes)
323
324 def need_entry_point(self, ent):
325 """Return True if an entry point is needed for the entry."""
326 # non-handcode hidden aliases may share the entry they alias
327 use_alias = (ent.hidden and ent.alias and not ent.handcode)
328 return not use_alias
329
330 def c_public_declarations(self, prefix):
331 """Return the declarations of public entry points."""
332 decls = []
333 for ent in self.entries:
334 if not self.need_entry_point(ent):
335 continue
336 export = self.api_call if not ent.hidden else ''
337 decls.append(self._c_decl(ent, prefix, True, export) + ';')
338
339 return "\n".join(decls)
340
341 def c_mapi_table(self):
342 """Return defines of the dispatch table size."""
343 num_static_entries = self.entries[-1].slot + 1
344 return ('#define MAPI_TABLE_NUM_STATIC %d\n' + \
345 '#define MAPI_TABLE_NUM_DYNAMIC %d') % (
346 num_static_entries, ABI_NUM_DYNAMIC_ENTRIES)
347
348 def _c_function(self, ent, prefix, mangle=False, stringify=False):
349 """Return the function name of an entry."""
350 formats = {
351 True: { True: '%s_STR(%s)', False: '%s(%s)' },
352 False: { True: '"%s%s"', False: '%s%s' },
353 }
354 fmt = formats[prefix.isupper()][stringify]
355 name = ent.name
356 if mangle and ent.hidden:
357 name = '_dispatch_stub_' + str(ent.slot)
358 return fmt % (prefix, name)
359
360 def _c_function_call(self, ent, prefix):
361 """Return the function name used for calling."""
362 if ent.handcode:
363 # _c_function does not handle this case
364 formats = { True: '%s(%s)', False: '%s%s' }
365 fmt = formats[prefix.isupper()]
366 name = fmt % (prefix, ent.handcode)
367 elif self.need_entry_point(ent):
368 name = self._c_function(ent, prefix, True)
369 else:
370 name = self._c_function(ent.alias, prefix, True)
371 return name
372
373 def _c_decl(self, ent, prefix, mangle=False, export=''):
374 """Return the C declaration for the entry."""
375 decl = '%s %s %s(%s)' % (ent.c_return(), self.api_entry,
376 self._c_function(ent, prefix, mangle), ent.c_params())
377 if export:
378 decl = export + ' ' + decl
379 if self.api_attrs:
380 decl += ' ' + self.api_attrs
381
382 return decl
383
384 def _c_cast(self, ent):
385 """Return the C cast for the entry."""
386 cast = '%s (%s *)(%s)' % (
387 ent.c_return(), self.api_entry, ent.c_params())
388
389 return cast
390
391 def c_public_dispatches(self, prefix, no_hidden):
392 """Return the public dispatch functions."""
393 dispatches = []
394 for ent in self.entries:
395 if ent.hidden and no_hidden:
396 continue
397
398 if not self.need_entry_point(ent):
399 continue
400
401 export = self.api_call if not ent.hidden else ''
402
403 proto = self._c_decl(ent, prefix, True, export)
404 cast = self._c_cast(ent)
405
406 ret = ''
407 if ent.ret:
408 ret = 'return '
409 stmt1 = self.indent
410 stmt1 += 'const struct _glapi_table *_tbl = %s();' % (
411 self.current_get)
412 stmt2 = self.indent
413 stmt2 += 'mapi_func _func = ((const mapi_func *) _tbl)[%d];' % (
414 ent.slot)
415 stmt3 = self.indent
416 stmt3 += '%s((%s) _func)(%s);' % (ret, cast, ent.c_args())
417
418 disp = '%s\n{\n%s\n%s\n%s\n}' % (proto, stmt1, stmt2, stmt3)
419
420 if ent.handcode:
421 disp = '#if 0\n' + disp + '\n#endif'
422
423 dispatches.append(disp)
424
425 return '\n\n'.join(dispatches)
426
427 def c_public_initializer(self, prefix):
428 """Return the initializer for public dispatch functions."""
429 names = []
430 for ent in self.entries:
431 if ent.alias:
432 continue
433
434 name = '%s(mapi_func) %s' % (self.indent,
435 self._c_function_call(ent, prefix))
436 names.append(name)
437
438 return ',\n'.join(names)
439
440 def c_stub_string_pool(self):
441 """Return the string pool for use by stubs."""
442 # sort entries by their names
443 sorted_entries = self.entries[:]
444 sorted_entries.sort(lambda x, y: cmp(x.name, y.name))
445
446 pool = []
447 offsets = {}
448 count = 0
449 for ent in sorted_entries:
450 offsets[ent] = count
451 pool.append('%s' % (ent.name))
452 count += len(ent.name) + 1
453
454 pool_str = self.indent + '"' + \
455 ('\\0"\n' + self.indent + '"').join(pool) + '";'
456 return (pool_str, offsets)
457
458 def c_stub_initializer(self, prefix, pool_offsets):
459 """Return the initializer for struct mapi_stub array."""
460 stubs = []
461 for ent in self.entries_sorted_by_names:
462 stubs.append('%s{ (void *) %d, %d, NULL }' % (
463 self.indent, pool_offsets[ent], ent.slot))
464
465 return ',\n'.join(stubs)
466
467 def c_noop_functions(self, prefix, warn_prefix):
468 """Return the noop functions."""
469 noops = []
470 for ent in self.entries:
471 if ent.alias:
472 continue
473
474 proto = self._c_decl(ent, prefix, False, 'static')
475
476 stmt1 = self.indent;
477 space = ''
478 for t, n, a in ent.params:
479 stmt1 += "%s(void) %s;" % (space, n)
480 space = ' '
481
482 if ent.params:
483 stmt1 += '\n';
484
485 stmt1 += self.indent + '%s(%s);' % (self.noop_warn,
486 self._c_function(ent, warn_prefix, False, True))
487
488 if ent.ret:
489 stmt2 = self.indent + 'return (%s) 0;' % (ent.ret)
490 noop = '%s\n{\n%s\n%s\n}' % (proto, stmt1, stmt2)
491 else:
492 noop = '%s\n{\n%s\n}' % (proto, stmt1)
493
494 noops.append(noop)
495
496 return '\n\n'.join(noops)
497
498 def c_noop_initializer(self, prefix, use_generic):
499 """Return an initializer for the noop dispatch table."""
500 entries = [self._c_function(ent, prefix)
501 for ent in self.entries if not ent.alias]
502 if use_generic:
503 entries = [self.noop_generic] * len(entries)
504
505 entries.extend([self.noop_generic] * ABI_NUM_DYNAMIC_ENTRIES)
506
507 pre = self.indent + '(mapi_func) '
508 return pre + (',\n' + pre).join(entries)
509
510 def c_asm_gcc(self, prefix, no_hidden):
511 asm = []
512
513 for ent in self.entries:
514 if ent.hidden and no_hidden:
515 continue
516
517 if not self.need_entry_point(ent):
518 continue
519
520 name = self._c_function(ent, prefix, True, True)
521
522 if ent.handcode:
523 asm.append('#if 0')
524
525 if ent.hidden:
526 asm.append('".hidden "%s"\\n"' % (name))
527
528 if ent.alias and not (ent.alias.hidden and no_hidden):
529 asm.append('".globl "%s"\\n"' % (name))
530 asm.append('".set "%s", "%s"\\n"' % (name,
531 self._c_function(ent.alias, prefix, True, True)))
532 else:
533 asm.append('STUB_ASM_ENTRY(%s)"\\n"' % (name))
534 asm.append('"\\t"STUB_ASM_CODE("%d")"\\n"' % (ent.slot))
535
536 if ent.handcode:
537 asm.append('#endif')
538 asm.append('')
539
540 return "\n".join(asm)
541
542 def output_for_lib(self):
543 print(self.c_notice())
544
545 if self.c_header:
546 print()
547 print(self.c_header)
548
549 print()
550 print('#ifdef MAPI_TMP_DEFINES')
551 print(self.c_public_includes())
552 print()
553 print(self.c_public_declarations(self.prefix_lib))
554 print('#undef MAPI_TMP_DEFINES')
555 print('#endif /* MAPI_TMP_DEFINES */')
556
557 if self.lib_need_table_size:
558 print()
559 print('#ifdef MAPI_TMP_TABLE')
560 print(self.c_mapi_table())
561 print('#undef MAPI_TMP_TABLE')
562 print('#endif /* MAPI_TMP_TABLE */')
563
564 if self.lib_need_noop_array:
565 print()
566 print('#ifdef MAPI_TMP_NOOP_ARRAY')
567 print('#ifdef DEBUG')
568 print()
569 print(self.c_noop_functions(self.prefix_noop, self.prefix_warn))
570 print()
571 print('const mapi_func table_%s_array[] = {' % (self.prefix_noop))
572 print(self.c_noop_initializer(self.prefix_noop, False))
573 print('};')
574 print()
575 print('#else /* DEBUG */')
576 print()
577 print('const mapi_func table_%s_array[] = {' % (self.prefix_noop))
578 print(self.c_noop_initializer(self.prefix_noop, True))
579 print('};')
580 print()
581 print('#endif /* DEBUG */')
582 print('#undef MAPI_TMP_NOOP_ARRAY')
583 print('#endif /* MAPI_TMP_NOOP_ARRAY */')
584
585 if self.lib_need_stubs:
586 pool, pool_offsets = self.c_stub_string_pool()
587 print()
588 print('#ifdef MAPI_TMP_PUBLIC_STUBS')
589 print('static const char public_string_pool[] =')
590 print(pool)
591 print()
592 print('static const struct mapi_stub public_stubs[] = {')
593 print(self.c_stub_initializer(self.prefix_lib, pool_offsets))
594 print('};')
595 print('#undef MAPI_TMP_PUBLIC_STUBS')
596 print('#endif /* MAPI_TMP_PUBLIC_STUBS */')
597
598 if self.lib_need_all_entries:
599 print()
600 print('#ifdef MAPI_TMP_PUBLIC_ENTRIES')
601 print(self.c_public_dispatches(self.prefix_lib, False))
602 print()
603 print('static const mapi_func public_entries[] = {')
604 print(self.c_public_initializer(self.prefix_lib))
605 print('};')
606 print('#undef MAPI_TMP_PUBLIC_ENTRIES')
607 print('#endif /* MAPI_TMP_PUBLIC_ENTRIES */')
608
609 print()
610 print('#ifdef MAPI_TMP_STUB_ASM_GCC')
611 print('__asm__(')
612 print(self.c_asm_gcc(self.prefix_lib, False))
613 print(');')
614 print('#undef MAPI_TMP_STUB_ASM_GCC')
615 print('#endif /* MAPI_TMP_STUB_ASM_GCC */')
616
617 if self.lib_need_non_hidden_entries:
618 all_hidden = True
619 for ent in self.entries:
620 if not ent.hidden:
621 all_hidden = False
622 break
623 if not all_hidden:
624 print()
625 print('#ifdef MAPI_TMP_PUBLIC_ENTRIES_NO_HIDDEN')
626 print(self.c_public_dispatches(self.prefix_lib, True))
627 print()
628 print('/* does not need public_entries */')
629 print('#undef MAPI_TMP_PUBLIC_ENTRIES_NO_HIDDEN')
630 print('#endif /* MAPI_TMP_PUBLIC_ENTRIES_NO_HIDDEN */')
631
632 print()
633 print('#ifdef MAPI_TMP_STUB_ASM_GCC_NO_HIDDEN')
634 print('__asm__(')
635 print(self.c_asm_gcc(self.prefix_lib, True))
636 print(');')
637 print('#undef MAPI_TMP_STUB_ASM_GCC_NO_HIDDEN')
638 print('#endif /* MAPI_TMP_STUB_ASM_GCC_NO_HIDDEN */')
639
640 class GLAPIPrinter(ABIPrinter):
641 """OpenGL API Printer"""
642
643 def __init__(self, entries):
644 for ent in entries:
645 self._override_for_api(ent)
646 super(GLAPIPrinter, self).__init__(entries)
647
648 self.api_defines = ['GL_GLEXT_PROTOTYPES']
649 self.api_headers = ['"GL/gl.h"', '"GL/glext.h"']
650 self.api_call = 'GLAPI'
651 self.api_entry = 'APIENTRY'
652 self.api_attrs = ''
653
654 self.lib_need_table_size = False
655 self.lib_need_noop_array = False
656 self.lib_need_stubs = False
657 self.lib_need_all_entries = False
658 self.lib_need_non_hidden_entries = True
659
660 self.prefix_lib = 'GLAPI_PREFIX'
661 self.prefix_noop = 'noop'
662 self.prefix_warn = self.prefix_lib
663
664 self.c_header = self._get_c_header()
665
666 def _override_for_api(self, ent):
667 """Override attributes of an entry if necessary for this
668 printer."""
669 # By default, no override is necessary.
670 pass
671
672 def _get_c_header(self):
673 header = """#ifndef _GLAPI_TMP_H_
674 #define _GLAPI_TMP_H_
675 #ifdef USE_MGL_NAMESPACE
676 #define GLAPI_PREFIX(func) mgl##func
677 #define GLAPI_PREFIX_STR(func) "mgl"#func
678 #else
679 #define GLAPI_PREFIX(func) gl##func
680 #define GLAPI_PREFIX_STR(func) "gl"#func
681 #endif /* USE_MGL_NAMESPACE */
682
683 typedef int GLclampx;
684 #endif /* _GLAPI_TMP_H_ */"""
685
686 return header
687
688 class ES1APIPrinter(GLAPIPrinter):
689 """OpenGL ES 1.x API Printer"""
690
691 def __init__(self, entries):
692 super(ES1APIPrinter, self).__init__(entries)
693 self.prefix_lib = 'gl'
694 self.prefix_warn = 'gl'
695
696 def _override_for_api(self, ent):
697 if ent.xml_data is None:
698 raise Exception('ES2 API printer requires XML input')
699 ent.hidden = (ent.name not in \
700 ent.xml_data.entry_points_for_api_version('es1')) \
701 or ent.hidden
702 ent.handcode = False
703
704 def _get_c_header(self):
705 header = """#ifndef _GLAPI_TMP_H_
706 #define _GLAPI_TMP_H_
707 typedef int GLclampx;
708 #endif /* _GLAPI_TMP_H_ */"""
709
710 return header
711
712 class ES2APIPrinter(GLAPIPrinter):
713 """OpenGL ES 2.x API Printer"""
714
715 def __init__(self, entries):
716 super(ES2APIPrinter, self).__init__(entries)
717 self.prefix_lib = 'gl'
718 self.prefix_warn = 'gl'
719
720 def _override_for_api(self, ent):
721 if ent.xml_data is None:
722 raise Exception('ES2 API printer requires XML input')
723 ent.hidden = (ent.name not in \
724 ent.xml_data.entry_points_for_api_version('es2')) \
725 or ent.hidden
726
727 # This is hella ugly. The same-named function in desktop OpenGL is
728 # hidden, but it needs to be exposed by libGLESv2 for OpenGL ES 3.0.
729 # There's no way to express in the XML that a function should be be
730 # hidden in one API but exposed in another.
731 if ent.name == 'GetInternalformativ':
732 ent.hidden = False
733
734 ent.handcode = False
735
736 def _get_c_header(self):
737 header = """#ifndef _GLAPI_TMP_H_
738 #define _GLAPI_TMP_H_
739 typedef int GLclampx;
740 #endif /* _GLAPI_TMP_H_ */"""
741
742 return header
743
744 class SharedGLAPIPrinter(GLAPIPrinter):
745 """Shared GLAPI API Printer"""
746
747 def __init__(self, entries):
748 super(SharedGLAPIPrinter, self).__init__(entries)
749
750 self.lib_need_table_size = True
751 self.lib_need_noop_array = True
752 self.lib_need_stubs = True
753 self.lib_need_all_entries = True
754 self.lib_need_non_hidden_entries = False
755
756 self.prefix_lib = 'shared'
757 self.prefix_warn = 'gl'
758
759 def _override_for_api(self, ent):
760 ent.hidden = True
761 ent.handcode = False
762
763 def _get_c_header(self):
764 header = """#ifndef _GLAPI_TMP_H_
765 #define _GLAPI_TMP_H_
766 typedef int GLclampx;
767 #endif /* _GLAPI_TMP_H_ */"""
768
769 return header
770
771 def parse_args():
772 printers = ['glapi', 'es1api', 'es2api', 'shared-glapi']
773
774 parser = OptionParser(usage='usage: %prog [options] <filename>')
775 parser.add_option('-p', '--printer', dest='printer',
776 help='printer to use: %s' % (", ".join(printers)))
777
778 options, args = parser.parse_args()
779 if not args or options.printer not in printers:
780 parser.print_help()
781 sys.exit(1)
782
783 return (args[0], options)
784
785 def main():
786 printers = {
787 'glapi': GLAPIPrinter,
788 'es1api': ES1APIPrinter,
789 'es2api': ES2APIPrinter,
790 'shared-glapi': SharedGLAPIPrinter,
791 }
792
793 filename, options = parse_args()
794
795 if filename.endswith('.xml'):
796 entries = abi_parse_xml(filename)
797 else:
798 entries = abi_parse(filename)
799 abi_sanity_check(entries)
800
801 printer = printers[options.printer](entries)
802 printer.output_for_lib()
803
804 if __name__ == '__main__':
805 main()