#!/usr/bin/env python # Mesa 3-D graphics library # Version: 7.9 # # Copyright (C) 2010 LunarG Inc. # # Permission is hereby granted, free of charge, to any person obtaining a # copy of this software and associated documentation files (the "Software"), # to deal in the Software without restriction, including without limitation # the rights to use, copy, modify, merge, publish, distribute, sublicense, # and/or sell copies of the Software, and to permit persons to whom the # Software is furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included # in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER # DEALINGS IN THE SOFTWARE. # # Authors: # Chia-I Wu import sys import re from optparse import OptionParser # number of dynamic entries ABI_NUM_DYNAMIC_ENTRIES = 256 class ABIEntry(object): """Represent an ABI entry.""" _match_c_param = re.compile( '^(?P[\w\s*]+?)(?P\w+)(\[(?P\d+)\])?$') def __init__(self, cols, attrs): self._parse(cols) self.slot = attrs['slot'] self.hidden = attrs['hidden'] self.alias = attrs['alias'] self.handcode = attrs['handcode'] def c_prototype(self): return '%s %s(%s)' % (self.c_return(), self.name, self.c_params()) def c_return(self): ret = self.ret if not ret: ret = 'void' return ret def c_params(self): """Return the parameter list used in the entry prototype.""" c_params = [] for t, n, a in self.params: sep = '' if t.endswith('*') else ' ' arr = '[%d]' % a if a else '' c_params.append(t + sep + n + arr) if not c_params: c_params.append('void') return ", ".join(c_params) def c_args(self): """Return the argument list used in the entry invocation.""" c_args = [] for t, n, a in self.params: c_args.append(n) return ", ".join(c_args) def _parse(self, cols): ret = cols.pop(0) if ret == 'void': ret = None name = cols.pop(0) params = [] if not cols: raise Exception(cols) elif len(cols) == 1 and cols[0] == 'void': pass else: for val in cols: params.append(self._parse_param(val)) self.ret = ret self.name = name self.params = params def _parse_param(self, c_param): m = self._match_c_param.match(c_param) if not m: raise Exception('unrecognized param ' + c_param) c_type = m.group('type').strip() c_name = m.group('name') c_array = m.group('array') c_array = int(c_array) if c_array else 0 return (c_type, c_name, c_array) def __str__(self): return self.c_prototype() def __cmp__(self, other): # compare slot, alias, and then name res = cmp(self.slot, other.slot) if not res: if not self.alias: res = -1 elif not other.alias: res = 1 if not res: res = cmp(self.name, other.name) return res def abi_parse_xml(xml): """Parse a GLAPI XML file for ABI entries.""" import os GLAPI = "./%s/../glapi/gen" % (os.path.dirname(sys.argv[0])) sys.path.append(GLAPI) import gl_XML, glX_XML api = gl_XML.parse_GL_API(xml, glX_XML.glx_item_factory()) entry_dict = {} for func in api.functionIterateByOffset(): # make sure func.name appear first entry_points = func.entry_points[:] entry_points.remove(func.name) entry_points.insert(0, func.name) for name in entry_points: attrs = { 'slot': func.offset, 'hidden': not func.is_static_entry_point(name), 'alias': None if name == func.name else func.name, 'handcode': bool(func.has_different_protocol(name)), } # post-process attrs if attrs['alias']: try: alias = entry_dict[attrs['alias']] except KeyError: raise Exception('failed to alias %s' % attrs['alias']) if alias.alias: raise Exception('recursive alias %s' % ent.name) attrs['alias'] = alias if attrs['handcode']: attrs['handcode'] = func.static_glx_name(name) else: attrs['handcode'] = None if entry_dict.has_key(name): raise Exception('%s is duplicated' % (name)) cols = [] cols.append(func.return_type) cols.append(name) params = func.get_parameter_string(name) cols.extend([p.strip() for p in params.split(',')]) ent = ABIEntry(cols, attrs) entry_dict[ent.name] = ent entries = entry_dict.values() entries.sort() return entries def abi_parse_line(line): cols = [col.strip() for col in line.split(',')] attrs = { 'slot': -1, 'hidden': False, 'alias': None, 'handcode': None, } # extract attributes from the first column vals = cols[0].split(':') while len(vals) > 1: val = vals.pop(0) if val.startswith('slot='): attrs['slot'] = int(val[5:]) elif val == 'hidden': attrs['hidden'] = True elif val.startswith('alias='): attrs['alias'] = val[6:] elif val.startswith('handcode='): attrs['handcode'] = val[9:] elif not val: pass else: raise Exception('unknown attribute %s' % val) cols[0] = vals[0] return (attrs, cols) def abi_parse(filename): """Parse a CSV file for ABI entries.""" fp = open(filename) if filename != '-' else sys.stdin lines = [line.strip() for line in fp.readlines() if not line.startswith('#') and line.strip()] entry_dict = {} next_slot = 0 for line in lines: attrs, cols = abi_parse_line(line) # post-process attributes if attrs['alias']: try: alias = entry_dict[attrs['alias']] except KeyError: raise Exception('failed to alias %s' % attrs['alias']) if alias.alias: raise Exception('recursive alias %s' % ent.name) slot = alias.slot attrs['alias'] = alias else: slot = next_slot next_slot += 1 if attrs['slot'] < 0: attrs['slot'] = slot elif attrs['slot'] != slot: raise Exception('invalid slot in %s' % (line)) ent = ABIEntry(cols, attrs) if entry_dict.has_key(ent.name): raise Exception('%s is duplicated' % (ent.name)) entry_dict[ent.name] = ent entries = entry_dict.values() entries.sort() return entries def abi_sanity_check(entries): if not entries: return all_names = [] last_slot = entries[-1].slot i = 0 for slot in xrange(last_slot + 1): if entries[i].slot != slot: raise Exception('entries are not ordered by slots') if entries[i].alias: raise Exception('first entry of slot %d aliases %s' % (slot, entries[i].alias.name)) handcode = None while i < len(entries) and entries[i].slot == slot: ent = entries[i] if not handcode and ent.handcode: handcode = ent.handcode elif ent.handcode != handcode: raise Exception('two aliases with handcode %s != %s', ent.handcode, handcode) if ent.name in all_names: raise Exception('%s is duplicated' % (ent.name)) if ent.alias and ent.alias.name not in all_names: raise Exception('failed to alias %s' % (ent.alias.name)) all_names.append(ent.name) i += 1 if i < len(entries): raise Exception('there are %d invalid entries' % (len(entries) - 1)) class ABIPrinter(object): """MAPI Printer""" def __init__(self, entries): self.entries = entries # sort entries by their names self.entries_sorted_by_names = self.entries[:] self.entries_sorted_by_names.sort(lambda x, y: cmp(x.name, y.name)) self.indent = ' ' * 3 self.noop_warn = 'noop_warn' self.noop_generic = 'noop_generic' self.current_get = 'entry_current_get' self.api_defines = [] self.api_headers = ['"KHR/khrplatform.h"'] self.api_call = 'KHRONOS_APICALL' self.api_entry = 'KHRONOS_APIENTRY' self.api_attrs = 'KHRONOS_APIATTRIBUTES' self.c_header = '' self.lib_need_table_size = True self.lib_need_noop_array = True self.lib_need_stubs = True self.lib_need_all_entries = True self.lib_need_non_hidden_entries = False def c_notice(self): return '/* This file is automatically generated by mapi_abi.py. Do not modify. */' def c_public_includes(self): """Return includes of the client API headers.""" defines = ['#define ' + d for d in self.api_defines] includes = ['#include ' + h for h in self.api_headers] return "\n".join(defines + includes) def need_entry_point(self, ent): """Return True if an entry point is needed for the entry.""" # non-handcode hidden aliases may share the entry they alias use_alias = (ent.hidden and ent.alias and not ent.handcode) return not use_alias def c_public_declarations(self, prefix): """Return the declarations of public entry points.""" decls = [] for ent in self.entries: if not self.need_entry_point(ent): continue export = self.api_call if not ent.hidden else '' decls.append(self._c_decl(ent, prefix, True, export) + ';') return "\n".join(decls) def c_mapi_table(self): """Return defines of the dispatch table size.""" num_static_entries = self.entries[-1].slot + 1 return ('#define MAPI_TABLE_NUM_STATIC %d\n' + \ '#define MAPI_TABLE_NUM_DYNAMIC %d') % ( num_static_entries, ABI_NUM_DYNAMIC_ENTRIES) def c_mapi_table_initializer(self, prefix): """Return the array initializer for mapi_table_fill.""" entries = [self._c_function(ent, prefix) for ent in self.entries if not ent.alias] pre = self.indent + '(mapi_proc) ' return pre + (',\n' + pre).join(entries) def c_mapi_table_spec(self): """Return the spec for mapi_init.""" specv1 = [] line = '"1' for ent in self.entries: if not ent.alias: line += '\\0"\n' specv1.append(line) line = '"' line += '%s\\0' % ent.name line += '";' specv1.append(line) return self.indent + self.indent.join(specv1) def _c_function(self, ent, prefix, mangle=False, stringify=False): """Return the function name of an entry.""" formats = { True: { True: '%s_STR(%s)', False: '%s(%s)' }, False: { True: '"%s%s"', False: '%s%s' }, } fmt = formats[prefix.isupper()][stringify] name = ent.name if mangle and ent.hidden: name = '_dispatch_stub_' + str(ent.slot) return fmt % (prefix, name) def _c_function_call(self, ent, prefix): """Return the function name used for calling.""" if ent.handcode: # _c_function does not handle this case formats = { True: '%s(%s)', False: '%s%s' } fmt = formats[prefix.isupper()] name = fmt % (prefix, ent.handcode) elif self.need_entry_point(ent): name = self._c_function(ent, prefix, True) else: name = self._c_function(ent.alias, prefix, True) return name def _c_decl(self, ent, prefix, mangle=False, export=''): """Return the C declaration for the entry.""" decl = '%s %s %s(%s)' % (ent.c_return(), self.api_entry, self._c_function(ent, prefix, mangle), ent.c_params()) if export: decl = export + ' ' + decl if self.api_attrs: decl += ' ' + self.api_attrs return decl def _c_cast(self, ent): """Return the C cast for the entry.""" cast = '%s (%s *)(%s)' % ( ent.c_return(), self.api_entry, ent.c_params()) return cast def c_private_declarations(self, prefix): """Return the declarations of private functions.""" decls = [self._c_decl(ent, prefix) + ';' for ent in self.entries if not ent.alias] return "\n".join(decls) def c_public_dispatches(self, prefix, no_hidden): """Return the public dispatch functions.""" dispatches = [] for ent in self.entries: if ent.hidden and no_hidden: continue if not self.need_entry_point(ent): continue export = self.api_call if not ent.hidden else '' proto = self._c_decl(ent, prefix, True, export) cast = self._c_cast(ent) ret = '' if ent.ret: ret = 'return ' stmt1 = self.indent stmt1 += 'const struct mapi_table *_tbl = %s();' % ( self.current_get) stmt2 = self.indent stmt2 += 'mapi_func _func = ((const mapi_func *) _tbl)[%d];' % ( ent.slot) stmt3 = self.indent stmt3 += '%s((%s) _func)(%s);' % (ret, cast, ent.c_args()) disp = '%s\n{\n%s\n%s\n%s\n}' % (proto, stmt1, stmt2, stmt3) if ent.handcode: disp = '#if 0\n' + disp + '\n#endif' dispatches.append(disp) return '\n\n'.join(dispatches) def c_public_initializer(self, prefix): """Return the initializer for public dispatch functions.""" names = [] for ent in self.entries: if ent.alias: continue name = '%s(mapi_func) %s' % (self.indent, self._c_function_call(ent, prefix)) names.append(name) return ',\n'.join(names) def c_stub_string_pool(self): """Return the string pool for use by stubs.""" # sort entries by their names sorted_entries = self.entries[:] sorted_entries.sort(lambda x, y: cmp(x.name, y.name)) pool = [] offsets = {} count = 0 for ent in sorted_entries: offsets[ent] = count pool.append('%s' % (ent.name)) count += len(ent.name) + 1 pool_str = self.indent + '"' + \ ('\\0"\n' + self.indent + '"').join(pool) + '";' return (pool_str, offsets) def c_stub_initializer(self, prefix, pool_offsets): """Return the initializer for struct mapi_stub array.""" stubs = [] for ent in self.entries_sorted_by_names: stubs.append('%s{ (void *) %d, %d, NULL }' % ( self.indent, pool_offsets[ent], ent.slot)) return ',\n'.join(stubs) def c_noop_functions(self, prefix, warn_prefix): """Return the noop functions.""" noops = [] for ent in self.entries: if ent.alias: continue proto = self._c_decl(ent, prefix, False, 'static') stmt1 = self.indent + '%s(%s);' % (self.noop_warn, self._c_function(ent, warn_prefix, False, True)) if ent.ret: stmt2 = self.indent + 'return (%s) 0;' % (ent.ret) noop = '%s\n{\n%s\n%s\n}' % (proto, stmt1, stmt2) else: noop = '%s\n{\n%s\n}' % (proto, stmt1) noops.append(noop) return '\n\n'.join(noops) def c_noop_initializer(self, prefix, use_generic): """Return an initializer for the noop dispatch table.""" entries = [self._c_function(ent, prefix) for ent in self.entries if not ent.alias] if use_generic: entries = [self.noop_generic] * len(entries) entries.extend([self.noop_generic] * ABI_NUM_DYNAMIC_ENTRIES) pre = self.indent + '(mapi_func) ' return pre + (',\n' + pre).join(entries) def c_asm_gcc(self, prefix, no_hidden): asm = [] for ent in self.entries: if ent.hidden and no_hidden: continue if not self.need_entry_point(ent): continue name = self._c_function(ent, prefix, True, True) if ent.handcode: asm.append('#if 0') if ent.hidden: asm.append('".hidden "%s"\\n"' % (name)) if ent.alias and not (ent.alias.hidden and no_hidden): asm.append('".globl "%s"\\n"' % (name)) asm.append('".set "%s", "%s"\\n"' % (name, self._c_function(ent.alias, prefix, True, True))) else: asm.append('STUB_ASM_ENTRY(%s)"\\n"' % (name)) asm.append('"\\t"STUB_ASM_CODE("%d")"\\n"' % (ent.slot)) if ent.handcode: asm.append('#endif') asm.append('') return "\n".join(asm) def output_for_lib(self): print self.c_notice() if self.c_header: print print self.c_header print print '#ifdef MAPI_TMP_DEFINES' print self.c_public_includes() print print self.c_public_declarations(self.prefix_lib) print '#undef MAPI_TMP_DEFINES' print '#endif /* MAPI_TMP_DEFINES */' if self.lib_need_table_size: print print '#ifdef MAPI_TMP_TABLE' print self.c_mapi_table() print '#undef MAPI_TMP_TABLE' print '#endif /* MAPI_TMP_TABLE */' if self.lib_need_noop_array: print print '#ifdef MAPI_TMP_NOOP_ARRAY' print '#ifdef DEBUG' print print self.c_noop_functions(self.prefix_noop, self.prefix_warn) print print 'const mapi_func table_%s_array[] = {' % (self.prefix_noop) print self.c_noop_initializer(self.prefix_noop, False) print '};' print print '#else /* DEBUG */' print print 'const mapi_func table_%s_array[] = {' % (self.prefix_noop) print self.c_noop_initializer(self.prefix_noop, True) print '};' print print '#endif /* DEBUG */' print '#undef MAPI_TMP_NOOP_ARRAY' print '#endif /* MAPI_TMP_NOOP_ARRAY */' if self.lib_need_stubs: pool, pool_offsets = self.c_stub_string_pool() print print '#ifdef MAPI_TMP_PUBLIC_STUBS' print 'static const char public_string_pool[] =' print pool print print 'static const struct mapi_stub public_stubs[] = {' print self.c_stub_initializer(self.prefix_lib, pool_offsets) print '};' print '#undef MAPI_TMP_PUBLIC_STUBS' print '#endif /* MAPI_TMP_PUBLIC_STUBS */' if self.lib_need_all_entries: print print '#ifdef MAPI_TMP_PUBLIC_ENTRIES' print self.c_public_dispatches(self.prefix_lib, False) print print 'static const mapi_func public_entries[] = {' print self.c_public_initializer(self.prefix_lib) print '};' print '#undef MAPI_TMP_PUBLIC_ENTRIES' print '#endif /* MAPI_TMP_PUBLIC_ENTRIES */' print print '#ifdef MAPI_TMP_STUB_ASM_GCC' print '__asm__(' print self.c_asm_gcc(self.prefix_lib, False) print ');' print '#undef MAPI_TMP_STUB_ASM_GCC' print '#endif /* MAPI_TMP_STUB_ASM_GCC */' if self.lib_need_non_hidden_entries: all_hidden = True for ent in self.entries: if not ent.hidden: all_hidden = False break if not all_hidden: print print '#ifdef MAPI_TMP_PUBLIC_ENTRIES_NO_HIDDEN' print self.c_public_dispatches(self.prefix_lib, True) print print '/* does not need public_entries */' print '#undef MAPI_TMP_PUBLIC_ENTRIES_NO_HIDDEN' print '#endif /* MAPI_TMP_PUBLIC_ENTRIES_NO_HIDDEN */' print print '#ifdef MAPI_TMP_STUB_ASM_GCC_NO_HIDDEN' print '__asm__(' print self.c_asm_gcc(self.prefix_lib, True) print ');' print '#undef MAPI_TMP_STUB_ASM_GCC_NO_HIDDEN' print '#endif /* MAPI_TMP_STUB_ASM_GCC_NO_HIDDEN */' def output_for_app(self): print self.c_notice() print print self.c_private_declarations(self.prefix_app) print print '#ifdef API_TMP_DEFINE_SPEC' print print 'static const char %s_spec[] =' % (self.prefix_app) print self.c_mapi_table_spec() print print 'static const mapi_proc %s_procs[] = {' % (self.prefix_app) print self.c_mapi_table_initializer(self.prefix_app) print '};' print print '#endif /* API_TMP_DEFINE_SPEC */' class GLAPIPrinter(ABIPrinter): """OpenGL API Printer""" def __init__(self, entries, api=None): api_entries = self._get_api_entries(entries, api) super(GLAPIPrinter, self).__init__(api_entries) self.api_defines = ['GL_GLEXT_PROTOTYPES'] self.api_headers = ['"GL/gl.h"', '"GL/glext.h"'] self.api_call = 'GLAPI' self.api_entry = 'APIENTRY' self.api_attrs = '' self.lib_need_table_size = False self.lib_need_noop_array = False self.lib_need_stubs = False self.lib_need_all_entries = False self.lib_need_non_hidden_entries = True self.prefix_lib = 'GLAPI_PREFIX' self.prefix_app = '_mesa_' self.prefix_noop = 'noop' self.prefix_warn = self.prefix_lib self.c_header = self._get_c_header() def _get_api_entries(self, entries, api): """Override the entry attributes according to API.""" import copy # no override if api is None: return entries api_entries = {} for ent in entries: ent = copy.copy(ent) # override 'hidden' and 'handcode' ent.hidden = ent.name not in api ent.handcode = False if ent.alias: ent.alias = api_entries[ent.alias.name] api_entries[ent.name] = ent # sanity check missed = [name for name in api if name not in api_entries] if missed: raise Exception('%s is missing' % str(missed)) entries = api_entries.values() entries.sort() return entries def _get_c_header(self): header = """#ifndef _GLAPI_TMP_H_ #define _GLAPI_TMP_H_ #ifdef USE_MGL_NAMESPACE #define GLAPI_PREFIX(func) mgl##func #define GLAPI_PREFIX_STR(func) "mgl"#func #else #define GLAPI_PREFIX(func) gl##func #define GLAPI_PREFIX_STR(func) "gl"#func #endif /* USE_MGL_NAMESPACE */ typedef int GLfixed; typedef int GLclampx; #endif /* _GLAPI_TMP_H_ */""" return header class ES1APIPrinter(GLAPIPrinter): """OpenGL ES 1.x API Printer""" def __init__(self, entries): es1_api = [ # OpenGL ES 1.1 'ActiveTexture', 'AlphaFunc', 'AlphaFuncx', 'BindBuffer', 'BindTexture', 'BlendFunc', 'BufferData', 'BufferSubData', 'Clear', 'ClearColor', 'ClearColorx', 'ClearDepthf', 'ClearDepthx', 'ClearStencil', 'ClientActiveTexture', 'ClipPlanef', 'ClipPlanex', 'Color4f', 'Color4ub', 'Color4x', 'ColorMask', 'ColorPointer', 'CompressedTexImage2D', 'CompressedTexSubImage2D', 'CopyTexImage2D', 'CopyTexSubImage2D', 'CullFace', 'DeleteBuffers', 'DeleteTextures', 'DepthFunc', 'DepthMask', 'DepthRangef', 'DepthRangex', 'Disable', 'DisableClientState', 'DrawArrays', 'DrawElements', 'Enable', 'EnableClientState', 'Finish', 'Flush', 'Fogf', 'Fogfv', 'Fogx', 'Fogxv', 'FrontFace', 'Frustumf', 'Frustumx', 'GenBuffers', 'GenTextures', 'GetBooleanv', 'GetBufferParameteriv', 'GetClipPlanef', 'GetClipPlanex', 'GetError', 'GetFixedv', 'GetFloatv', 'GetIntegerv', 'GetLightfv', 'GetLightxv', 'GetMaterialfv', 'GetMaterialxv', 'GetPointerv', 'GetString', 'GetTexEnvfv', 'GetTexEnviv', 'GetTexEnvxv', 'GetTexParameterfv', 'GetTexParameteriv', 'GetTexParameterxv', 'Hint', 'IsBuffer', 'IsEnabled', 'IsTexture', 'Lightf', 'Lightfv', 'LightModelf', 'LightModelfv', 'LightModelx', 'LightModelxv', 'Lightx', 'Lightxv', 'LineWidth', 'LineWidthx', 'LoadIdentity', 'LoadMatrixf', 'LoadMatrixx', 'LogicOp', 'Materialf', 'Materialfv', 'Materialx', 'Materialxv', 'MatrixMode', 'MultiTexCoord4f', 'MultiTexCoord4x', 'MultMatrixf', 'MultMatrixx', 'Normal3f', 'Normal3x', 'NormalPointer', 'Orthof', 'Orthox', 'PixelStorei', 'PointParameterf', 'PointParameterfv', 'PointParameterx', 'PointParameterxv', 'PointSize', 'PointSizex', 'PolygonOffset', 'PolygonOffsetx', 'PopMatrix', 'PushMatrix', 'ReadPixels', 'Rotatef', 'Rotatex', 'SampleCoverage', 'SampleCoveragex', 'Scalef', 'Scalex', 'Scissor', 'ShadeModel', 'StencilFunc', 'StencilMask', 'StencilOp', 'TexCoordPointer', 'TexEnvf', 'TexEnvfv', 'TexEnvi', 'TexEnviv', 'TexEnvx', 'TexEnvxv', 'TexImage2D', 'TexParameterf', 'TexParameterfv', 'TexParameteri', 'TexParameteriv', 'TexParameterx', 'TexParameterxv', 'TexSubImage2D', 'Translatef', 'Translatex', 'VertexPointer', 'Viewport', # GL_OES_EGL_image 'EGLImageTargetTexture2DOES', 'EGLImageTargetRenderbufferStorageOES', # GL_OES_mapbuffer 'GetBufferPointervOES', 'MapBufferOES', 'UnmapBufferOES', # GL_EXT_multi_draw_arrays 'MultiDrawArraysEXT', 'MultiDrawElementsEXT', # GL_OES_blend_equation_separate 'BlendEquationSeparateOES', # GL_OES_blend_func_separate 'BlendFuncSeparateOES', # GL_OES_blend_subtract 'BlendEquationOES', # GL_OES_draw_texture 'DrawTexiOES', 'DrawTexivOES', 'DrawTexfOES', 'DrawTexfvOES', 'DrawTexsOES', 'DrawTexsvOES', 'DrawTexxOES', 'DrawTexxvOES', # GL_OES_fixed_point 'AlphaFuncxOES', 'ClearColorxOES', 'ClearDepthxOES', 'Color4xOES', 'DepthRangexOES', 'FogxOES', 'FogxvOES', 'FrustumxOES', 'LightModelxOES', 'LightModelxvOES', 'LightxOES', 'LightxvOES', 'LineWidthxOES', 'LoadMatrixxOES', 'MaterialxOES', 'MaterialxvOES', 'MultiTexCoord4xOES', 'MultMatrixxOES', 'Normal3xOES', 'OrthoxOES', 'PointSizexOES', 'PolygonOffsetxOES', 'RotatexOES', 'SampleCoveragexOES', 'ScalexOES', 'TexEnvxOES', 'TexEnvxvOES', 'TexParameterxOES', 'TranslatexOES', 'ClipPlanexOES', 'GetClipPlanexOES', 'GetFixedvOES', 'GetLightxvOES', 'GetMaterialxvOES', 'GetTexEnvxvOES', 'GetTexParameterxvOES', 'PointParameterxOES', 'PointParameterxvOES', 'TexParameterxvOES', # GL_OES_framebuffer_object 'BindFramebufferOES', 'BindRenderbufferOES', 'CheckFramebufferStatusOES', 'DeleteFramebuffersOES', 'DeleteRenderbuffersOES', 'FramebufferRenderbufferOES', 'FramebufferTexture2DOES', 'GenerateMipmapOES', 'GenFramebuffersOES', 'GenRenderbuffersOES', 'GetFramebufferAttachmentParameterivOES', 'GetRenderbufferParameterivOES', 'IsFramebufferOES', 'IsRenderbufferOES', 'RenderbufferStorageOES', # GL_OES_point_size_array 'PointSizePointerOES', # GL_OES_query_matrix 'QueryMatrixxOES', # GL_OES_single_precision 'ClearDepthfOES', 'DepthRangefOES', 'FrustumfOES', 'OrthofOES', 'ClipPlanefOES', 'GetClipPlanefOES', # GL_OES_texture_cube_map 'GetTexGenfvOES', 'GetTexGenivOES', 'GetTexGenxvOES', 'TexGenfOES', 'TexGenfvOES', 'TexGeniOES', 'TexGenivOES', 'TexGenxOES', 'TexGenxvOES', ] super(ES1APIPrinter, self).__init__(entries, es1_api) self.prefix_lib = 'gl' self.prefix_warn = 'gl' def _get_c_header(self): header = """#ifndef _GLAPI_TMP_H_ #define _GLAPI_TMP_H_ typedef int GLfixed; typedef int GLclampx; #endif /* _GLAPI_TMP_H_ */""" return header class ES2APIPrinter(GLAPIPrinter): """OpenGL ES 2.x API Printer""" def __init__(self, entries): es2_api = [ # OpenGL ES 2.0 "ActiveTexture", "AttachShader", "BindAttribLocation", "BindBuffer", "BindFramebuffer", "BindRenderbuffer", "BindTexture", "BlendColor", "BlendEquation", "BlendEquationSeparate", "BlendFunc", "BlendFuncSeparate", "BufferData", "BufferSubData", "CheckFramebufferStatus", "Clear", "ClearColor", "ClearDepthf", "ClearStencil", "ColorMask", "CompileShader", "CompressedTexImage2D", "CompressedTexSubImage2D", "CopyTexImage2D", "CopyTexSubImage2D", "CreateProgram", "CreateShader", "CullFace", "DeleteBuffers", "DeleteFramebuffers", "DeleteProgram", "DeleteRenderbuffers", "DeleteShader", "DeleteTextures", "DepthFunc", "DepthMask", "DepthRangef", "DetachShader", "Disable", "DisableVertexAttribArray", "DrawArrays", "DrawElements", "Enable", "EnableVertexAttribArray", "Finish", "Flush", "FramebufferRenderbuffer", "FramebufferTexture2D", "FrontFace", "GenBuffers", "GenerateMipmap", "GenFramebuffers", "GenRenderbuffers", "GenTextures", "GetActiveAttrib", "GetActiveUniform", "GetAttachedShaders", "GetAttribLocation", "GetBooleanv", "GetBufferParameteriv", "GetError", "GetFloatv", "GetFramebufferAttachmentParameteriv", "GetIntegerv", "GetProgramInfoLog", "GetProgramiv", "GetRenderbufferParameteriv", "GetShaderInfoLog", "GetShaderiv", "GetShaderPrecisionFormat", "GetShaderSource", "GetString", "GetTexParameterfv", "GetTexParameteriv", "GetUniformfv", "GetUniformiv", "GetUniformLocation", "GetVertexAttribfv", "GetVertexAttribiv", "GetVertexAttribPointerv", "Hint", "IsBuffer", "IsEnabled", "IsFramebuffer", "IsProgram", "IsRenderbuffer", "IsShader", "IsTexture", "LineWidth", "LinkProgram", "PixelStorei", "PolygonOffset", "ReadPixels", "ReleaseShaderCompiler", "RenderbufferStorage", "SampleCoverage", "Scissor", "ShaderBinary", "ShaderSource", "StencilFunc", "StencilFuncSeparate", "StencilMask", "StencilMaskSeparate", "StencilOp", "StencilOpSeparate", "TexImage2D", "TexParameterf", "TexParameterfv", "TexParameteri", "TexParameteriv", "TexSubImage2D", "Uniform1f", "Uniform1fv", "Uniform1i", "Uniform1iv", "Uniform2f", "Uniform2fv", "Uniform2i", "Uniform2iv", "Uniform3f", "Uniform3fv", "Uniform3i", "Uniform3iv", "Uniform4f", "Uniform4fv", "Uniform4i", "Uniform4iv", "UniformMatrix2fv", "UniformMatrix3fv", "UniformMatrix4fv", "UseProgram", "ValidateProgram", "VertexAttrib1f", "VertexAttrib1fv", "VertexAttrib2f", "VertexAttrib2fv", "VertexAttrib3f", "VertexAttrib3fv", "VertexAttrib4f", "VertexAttrib4fv", "VertexAttribPointer", "Viewport", # GL_OES_EGL_image 'EGLImageTargetTexture2DOES', 'EGLImageTargetRenderbufferStorageOES', # GL_OES_mapbuffer 'GetBufferPointervOES', 'MapBufferOES', 'UnmapBufferOES', # GL_EXT_multi_draw_arrays 'MultiDrawArraysEXT', 'MultiDrawElementsEXT', # GL_OES_texture_3D 'CompressedTexImage3DOES', 'CompressedTexSubImage3DOES', 'CopyTexSubImage3DOES', 'FramebufferTexture3DOES', 'TexImage3DOES', 'TexSubImage3DOES', # GL_OES_get_program_binary 'GetProgramBinaryOES', 'ProgramBinaryOES', ] super(ES2APIPrinter, self).__init__(entries, es2_api) self.prefix_lib = 'gl' self.prefix_warn = 'gl' def _get_c_header(self): header = """#ifndef _GLAPI_TMP_H_ #define _GLAPI_TMP_H_ typedef int GLfixed; typedef int GLclampx; #endif /* _GLAPI_TMP_H_ */""" return header class SharedGLAPIPrinter(GLAPIPrinter): """Shared GLAPI API Printer""" def __init__(self, entries): super(SharedGLAPIPrinter, self).__init__(entries, []) self.lib_need_table_size = True self.lib_need_noop_array = True self.lib_need_stubs = True self.lib_need_all_entries = True self.lib_need_non_hidden_entries = False self.prefix_lib = 'shared' self.prefix_warn = 'gl' def _get_c_header(self): header = """#ifndef _GLAPI_TMP_H_ #define _GLAPI_TMP_H_ typedef int GLfixed; typedef int GLclampx; #endif /* _GLAPI_TMP_H_ */""" return header class VGAPIPrinter(ABIPrinter): """OpenVG API Printer""" def __init__(self, entries): super(VGAPIPrinter, self).__init__(entries) self.api_defines = ['VG_VGEXT_PROTOTYPES'] self.api_headers = ['"VG/openvg.h"', '"VG/vgext.h"'] self.api_call = 'VG_API_CALL' self.api_entry = 'VG_API_ENTRY' self.api_attrs = 'VG_API_EXIT' self.prefix_lib = 'vg' self.prefix_app = 'vega' self.prefix_noop = 'noop' self.prefix_warn = 'vg' def parse_args(): printers = ['vgapi', 'glapi', 'es1api', 'es2api', 'shared-glapi'] modes = ['lib', 'app'] parser = OptionParser(usage='usage: %prog [options] ') parser.add_option('-p', '--printer', dest='printer', help='printer to use: %s' % (", ".join(printers))) parser.add_option('-m', '--mode', dest='mode', help='target user: %s' % (", ".join(modes))) options, args = parser.parse_args() if not args or options.printer not in printers or \ options.mode not in modes: parser.print_help() sys.exit(1) return (args[0], options) def main(): printers = { 'vgapi': VGAPIPrinter, 'glapi': GLAPIPrinter, 'es1api': ES1APIPrinter, 'es2api': ES2APIPrinter, 'shared-glapi': SharedGLAPIPrinter, } filename, options = parse_args() if filename.endswith('.xml'): entries = abi_parse_xml(filename) else: entries = abi_parse(filename) abi_sanity_check(entries) printer = printers[options.printer](entries) if options.mode == 'lib': printer.output_for_lib() else: printer.output_for_app() if __name__ == '__main__': main()