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