mesa/src/mapi/mapi_abi.py

812 lines
26 KiB
Python
Raw Normal View History

# Mesa 3-D graphics library
#
# 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 <olv@lunarg.com>
import sys
# make it possible to import glapi
import os
GLAPI = os.path.join(".", os.path.dirname(sys.argv[0]), "glapi/gen")
sys.path.append(GLAPI)
import re
from optparse import OptionParser
import gl_XML
import glX_XML
# number of dynamic entries
ABI_NUM_DYNAMIC_ENTRIES = 256
class ABIEntry(object):
"""Represent an ABI entry."""
_match_c_param = re.compile(
'^(?P<type>[\w\s*]+?)(?P<name>\w+)(\[(?P<array>\d+)\])?$')
def __init__(self, cols, attrs, xml_data = None):
self._parse(cols)
self.slot = attrs['slot']
self.hidden = attrs['hidden']
self.alias = attrs['alias']
self.handcode = attrs['handcode']
self.xml_data = xml_data
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."""
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, func)
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_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_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 _glapi_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;
space = ''
for t, n, a in ent.params:
stmt1 += "%s(void) %s;" % (space, n)
space = ' '
if ent.params:
stmt1 += '\n';
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 */'
class GLAPIPrinter(ABIPrinter):
"""OpenGL API Printer"""
def __init__(self, entries):
for ent in entries:
self._override_for_api(ent)
super(GLAPIPrinter, self).__init__(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_noop = 'noop'
self.prefix_warn = self.prefix_lib
self.c_header = self._get_c_header()
def _override_for_api(self, ent):
"""Override attributes of an entry if necessary for this
printer."""
# By default, no override is necessary.
pass
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 GLclampx;
#endif /* _GLAPI_TMP_H_ */"""
return header
class ES1APIPrinter(GLAPIPrinter):
"""OpenGL ES 1.x API Printer"""
def __init__(self, entries):
super(ES1APIPrinter, self).__init__(entries)
self.prefix_lib = 'gl'
self.prefix_warn = 'gl'
def _override_for_api(self, ent):
if ent.xml_data is None:
raise Exception('ES2 API printer requires XML input')
mapi_abi: Make ES1 and ES2 static_dispatch=false functions hidden This has been a long standing issue with the ES libraries. Functions marked in the XML with 'static_dispatch=false' were still incorrectly exported. ABI-check is supposed to detect this case, but we have to paper over failures every time a new extension is added. This change will cause a big pile of functions to disappear from libGLESv2 and libGLESv1_CM. libGLESv2 loses (20 functions): glBindVertexArrayOES glCompressedTexImage3DOES glCompressedTexSubImage3DOES glCopyTexSubImage3DOES glDeleteVertexArraysOES glDiscardFramebufferEXT glDrawBuffersNV glFlushMappedBufferRangeEXT glFramebufferTexture3DOES glGenVertexArraysOES glGetBufferPointervOES glGetProgramBinaryOES glIsVertexArrayOES glMapBufferOES glMapBufferRangeEXT glProgramBinaryOES glReadBufferNV glTexImage3DOES glTexSubImage3DOES glUnmapBufferOES libGLESv1_CM loses (88 functions): glAlphaFuncxOES glBindFramebufferOES glBindRenderbufferOES glBlendEquationOES glBlendEquationSeparateOES glBlendFuncSeparateOES glCheckFramebufferStatusOES glClearColorxOES glClearDepthfOES glClearDepthxOES glClipPlanefOES glClipPlanexOES glColor4xOES glDeleteFramebuffersOES glDeleteRenderbuffersOES glDepthRangefOES glDepthRangexOES glDiscardFramebufferEXT glDrawTexfOES glDrawTexfvOES glDrawTexiOES glDrawTexivOES glDrawTexsOES glDrawTexsvOES glDrawTexxOES glDrawTexxvOES glFlushMappedBufferRangeEXT glFogxOES glFogxvOES glFramebufferRenderbufferOES glFramebufferTexture2DOES glFrustumfOES glFrustumxOES glGenerateMipmapOES glGenFramebuffersOES glGenRenderbuffersOES glGetBufferPointervOES glGetClipPlanefOES glGetClipPlanexOES glGetFixedvOES glGetFramebufferAttachmentParameterivOES glGetLightxvOES glGetMaterialxvOES glGetRenderbufferParameterivOES glGetTexEnvxvOES glGetTexGenfvOES glGetTexGenivOES glGetTexGenxvOES glGetTexParameterxvOES glIsFramebufferOES glIsRenderbufferOES glLightModelxOES glLightModelxvOES glLightxOES glLightxvOES glLineWidthxOES glLoadMatrixxOES glMapBufferOES glMapBufferRangeEXT glMaterialxOES glMaterialxvOES glMultiTexCoord4xOES glMultMatrixxOES glNormal3xOES glOrthofOES glOrthoxOES glPointParameterxOES glPointParameterxvOES glPointSizePointerOES glPointSizexOES glPolygonOffsetxOES glQueryMatrixxOES glRenderbufferStorageOES glRotatexOES glSampleCoveragexOES glScalexOES glTexEnvxOES glTexEnvxvOES glTexGenfOES glTexGenfvOES glTexGeniOES glTexGenivOES glTexGenxOES glTexGenxvOES glTexParameterxOES glTexParameterxvOES glTranslatexOES glUnmapBufferOES Signed-off-by: Ian Romanick <ian.d.romanick@intel.com> Reviewed-by: Matt Turner <mattst88@gmail.com> Reviewed-by: Chad Versace <chad.versace@linux.intel.com> Reviewed-by: Chia-I Wu <olv@lunarg.com> Cc: Paul Berry <stereotype441@gmail.com>
2014-03-26 19:57:47 +00:00
ent.hidden = (ent.name not in \
ent.xml_data.entry_points_for_api_version('es1')) \
or ent.hidden
ent.handcode = False
def _get_c_header(self):
header = """#ifndef _GLAPI_TMP_H_
#define _GLAPI_TMP_H_
typedef int GLclampx;
#endif /* _GLAPI_TMP_H_ */"""
return header
class ES2APIPrinter(GLAPIPrinter):
"""OpenGL ES 2.x API Printer"""
def __init__(self, entries):
super(ES2APIPrinter, self).__init__(entries)
self.prefix_lib = 'gl'
self.prefix_warn = 'gl'
def _override_for_api(self, ent):
if ent.xml_data is None:
raise Exception('ES2 API printer requires XML input')
mapi_abi: Make ES1 and ES2 static_dispatch=false functions hidden This has been a long standing issue with the ES libraries. Functions marked in the XML with 'static_dispatch=false' were still incorrectly exported. ABI-check is supposed to detect this case, but we have to paper over failures every time a new extension is added. This change will cause a big pile of functions to disappear from libGLESv2 and libGLESv1_CM. libGLESv2 loses (20 functions): glBindVertexArrayOES glCompressedTexImage3DOES glCompressedTexSubImage3DOES glCopyTexSubImage3DOES glDeleteVertexArraysOES glDiscardFramebufferEXT glDrawBuffersNV glFlushMappedBufferRangeEXT glFramebufferTexture3DOES glGenVertexArraysOES glGetBufferPointervOES glGetProgramBinaryOES glIsVertexArrayOES glMapBufferOES glMapBufferRangeEXT glProgramBinaryOES glReadBufferNV glTexImage3DOES glTexSubImage3DOES glUnmapBufferOES libGLESv1_CM loses (88 functions): glAlphaFuncxOES glBindFramebufferOES glBindRenderbufferOES glBlendEquationOES glBlendEquationSeparateOES glBlendFuncSeparateOES glCheckFramebufferStatusOES glClearColorxOES glClearDepthfOES glClearDepthxOES glClipPlanefOES glClipPlanexOES glColor4xOES glDeleteFramebuffersOES glDeleteRenderbuffersOES glDepthRangefOES glDepthRangexOES glDiscardFramebufferEXT glDrawTexfOES glDrawTexfvOES glDrawTexiOES glDrawTexivOES glDrawTexsOES glDrawTexsvOES glDrawTexxOES glDrawTexxvOES glFlushMappedBufferRangeEXT glFogxOES glFogxvOES glFramebufferRenderbufferOES glFramebufferTexture2DOES glFrustumfOES glFrustumxOES glGenerateMipmapOES glGenFramebuffersOES glGenRenderbuffersOES glGetBufferPointervOES glGetClipPlanefOES glGetClipPlanexOES glGetFixedvOES glGetFramebufferAttachmentParameterivOES glGetLightxvOES glGetMaterialxvOES glGetRenderbufferParameterivOES glGetTexEnvxvOES glGetTexGenfvOES glGetTexGenivOES glGetTexGenxvOES glGetTexParameterxvOES glIsFramebufferOES glIsRenderbufferOES glLightModelxOES glLightModelxvOES glLightxOES glLightxvOES glLineWidthxOES glLoadMatrixxOES glMapBufferOES glMapBufferRangeEXT glMaterialxOES glMaterialxvOES glMultiTexCoord4xOES glMultMatrixxOES glNormal3xOES glOrthofOES glOrthoxOES glPointParameterxOES glPointParameterxvOES glPointSizePointerOES glPointSizexOES glPolygonOffsetxOES glQueryMatrixxOES glRenderbufferStorageOES glRotatexOES glSampleCoveragexOES glScalexOES glTexEnvxOES glTexEnvxvOES glTexGenfOES glTexGenfvOES glTexGeniOES glTexGenivOES glTexGenxOES glTexGenxvOES glTexParameterxOES glTexParameterxvOES glTranslatexOES glUnmapBufferOES Signed-off-by: Ian Romanick <ian.d.romanick@intel.com> Reviewed-by: Matt Turner <mattst88@gmail.com> Reviewed-by: Chad Versace <chad.versace@linux.intel.com> Reviewed-by: Chia-I Wu <olv@lunarg.com> Cc: Paul Berry <stereotype441@gmail.com>
2014-03-26 19:57:47 +00:00
ent.hidden = (ent.name not in \
ent.xml_data.entry_points_for_api_version('es2')) \
or ent.hidden
# This is hella ugly. The same-named function in desktop OpenGL is
# hidden, but it needs to be exposed by libGLESv2 for OpenGL ES 3.0.
# There's no way to express in the XML that a function should be be
# hidden in one API but exposed in another.
if ent.name == 'GetInternalformativ':
ent.hidden = False
ent.handcode = False
def _get_c_header(self):
header = """#ifndef _GLAPI_TMP_H_
#define _GLAPI_TMP_H_
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 _override_for_api(self, ent):
ent.hidden = True
ent.handcode = False
def _get_c_header(self):
header = """#ifndef _GLAPI_TMP_H_
#define _GLAPI_TMP_H_
typedef int GLclampx;
#endif /* _GLAPI_TMP_H_ */"""
return header
def parse_args():
printers = ['glapi', 'es1api', 'es2api', 'shared-glapi']
modes = ['lib', 'app']
parser = OptionParser(usage='usage: %prog [options] <filename>')
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 = {
'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()
if __name__ == '__main__':
main()