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