|
|
@ -35,15 +35,29 @@ class GLFunction(object): |
|
|
|
self.ret_type = ret_type |
|
|
|
self.ret_type = ret_type |
|
|
|
self.providers = [] |
|
|
|
self.providers = [] |
|
|
|
self.args = [] |
|
|
|
self.args = [] |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# This is the string of C code for passing through the |
|
|
|
|
|
|
|
# arguments to the function. |
|
|
|
self.args_list = '' |
|
|
|
self.args_list = '' |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# This is the string of C code for declaring the arguments |
|
|
|
|
|
|
|
# list. |
|
|
|
self.args_decl = 'void' |
|
|
|
self.args_decl = 'void' |
|
|
|
|
|
|
|
|
|
|
|
# For an alias group, alias_func is the function they are all |
|
|
|
# If present, this is the string name of the function that |
|
|
|
# marked as the alias of. |
|
|
|
# this is an alias of. This initially comes from the |
|
|
|
|
|
|
|
# registry, and may get updated if it turns out our alias is |
|
|
|
|
|
|
|
# itself an alias (for example glFramebufferTextureEXT -> |
|
|
|
|
|
|
|
# glFramebufferTextureARB -> glFramebufferTexture) |
|
|
|
|
|
|
|
self.alias_name = None |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# After alias resolution, this is the function that this is an |
|
|
|
|
|
|
|
# alias of. |
|
|
|
self.alias_func = None |
|
|
|
self.alias_func = None |
|
|
|
# For an alias group, the shared alias_func has this list of |
|
|
|
|
|
|
|
# functions (of different names) that are marked as aliases of |
|
|
|
# For the root of an alias tree, this lists the functions that |
|
|
|
# it, so that it can write a resolver for all of them. |
|
|
|
# are marked as aliases of it, so that it can write a resolver |
|
|
|
|
|
|
|
# for all of them. |
|
|
|
self.alias_exts = [] |
|
|
|
self.alias_exts = [] |
|
|
|
|
|
|
|
|
|
|
|
def add_arg(self, type, name): |
|
|
|
def add_arg(self, type, name): |
|
|
@ -138,8 +152,11 @@ class Generator(object): |
|
|
|
|
|
|
|
|
|
|
|
alias = command.find('alias') |
|
|
|
alias = command.find('alias') |
|
|
|
if alias is not None: |
|
|
|
if alias is not None: |
|
|
|
alias_func = self.functions[alias.get('name')] |
|
|
|
# XXX print('{0} -> {1}'.format(func.name, alias.get('name'))) |
|
|
|
alias_func.add_alias(func) |
|
|
|
# Note that some alias references appear before the |
|
|
|
|
|
|
|
# target command is defined (glAttachObjectARB() -> |
|
|
|
|
|
|
|
# glAttachShader(), for example). |
|
|
|
|
|
|
|
func.alias_name = alias.get('name') |
|
|
|
|
|
|
|
|
|
|
|
self.functions[name] = func |
|
|
|
self.functions[name] = func |
|
|
|
|
|
|
|
|
|
|
@ -154,6 +171,17 @@ class Generator(object): |
|
|
|
for name in weird_functions: |
|
|
|
for name in weird_functions: |
|
|
|
del self.functions[name] |
|
|
|
del self.functions[name] |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def resolve_aliases(self): |
|
|
|
|
|
|
|
for func in self.functions.values(): |
|
|
|
|
|
|
|
# Find the root of the alias tree, and add ourselves to it. |
|
|
|
|
|
|
|
if func.alias_name: |
|
|
|
|
|
|
|
alias_func = func |
|
|
|
|
|
|
|
while alias_func.alias_name: |
|
|
|
|
|
|
|
alias_func = self.functions[alias_func.alias_name] |
|
|
|
|
|
|
|
func.alias_name = alias_func.name |
|
|
|
|
|
|
|
func.alias_func = alias_func |
|
|
|
|
|
|
|
alias_func.alias_exts.append(func) |
|
|
|
|
|
|
|
|
|
|
|
def process_require_statements(self, feature, condition, loader, human_name): |
|
|
|
def process_require_statements(self, feature, condition, loader, human_name): |
|
|
|
for command in feature.findall('require/command'): |
|
|
|
for command in feature.findall('require/command'): |
|
|
|
name = command.get('name') |
|
|
|
name = command.get('name') |
|
|
@ -373,20 +401,20 @@ class Generator(object): |
|
|
|
self.outln('') |
|
|
|
self.outln('') |
|
|
|
|
|
|
|
|
|
|
|
def write_dispatch_table_stub(self, func): |
|
|
|
def write_dispatch_table_stub(self, func): |
|
|
|
dispatch_table_entry = 'dispatch_table->p{0}'.format(func.name) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Use the same resolver for all the aliases of a particular |
|
|
|
# Use the same resolver for all the aliases of a particular |
|
|
|
# function. |
|
|
|
# function. |
|
|
|
alias_func = func |
|
|
|
alias_name = func.name |
|
|
|
if func.alias_func: |
|
|
|
if func.alias_name: |
|
|
|
alias_func = func |
|
|
|
alias_name = func.alias_name |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
dispatch_table_entry = 'dispatch_table->p{0}'.format(alias_name) |
|
|
|
|
|
|
|
|
|
|
|
self.outln('PUBLIC {0}'.format(func.ret_type)) |
|
|
|
self.outln('PUBLIC {0}'.format(func.ret_type)) |
|
|
|
self.outln('epoxy_{0}({1})'.format(func.name, func.args_decl)) |
|
|
|
self.outln('epoxy_{0}({1})'.format(func.name, func.args_decl)) |
|
|
|
self.outln('{') |
|
|
|
self.outln('{') |
|
|
|
self.outln(' if (!{0})'.format(dispatch_table_entry)) |
|
|
|
self.outln(' if (!{0})'.format(dispatch_table_entry)) |
|
|
|
self.outln(' {0} = epoxy_{1}_resolver();'.format(dispatch_table_entry, |
|
|
|
self.outln(' {0} = epoxy_{1}_resolver();'.format(dispatch_table_entry, |
|
|
|
alias_func.name)) |
|
|
|
alias_name)) |
|
|
|
self.outln('') |
|
|
|
self.outln('') |
|
|
|
if func.ret_type == 'void': |
|
|
|
if func.ret_type == 'void': |
|
|
|
self.outln(' {0}({1});'.format(dispatch_table_entry, func.args_list)) |
|
|
|
self.outln(' {0}({1});'.format(dispatch_table_entry, func.args_list)) |
|
|
@ -415,6 +443,8 @@ class Generator(object): |
|
|
|
|
|
|
|
|
|
|
|
self.outln('struct dispatch_table {') |
|
|
|
self.outln('struct dispatch_table {') |
|
|
|
for func in self.functions.values(): |
|
|
|
for func in self.functions.values(): |
|
|
|
|
|
|
|
# Aliases don't get their own slot, since they use a shared resolver. |
|
|
|
|
|
|
|
if not func.alias_name: |
|
|
|
self.outln(' {0} p{1};'.format(func.ptr_type, func.name)) |
|
|
|
self.outln(' {0} p{1};'.format(func.ptr_type, func.name)) |
|
|
|
self.outln('};') |
|
|
|
self.outln('};') |
|
|
|
self.outln('') |
|
|
|
self.outln('') |
|
|
@ -428,6 +458,7 @@ class Generator(object): |
|
|
|
if not func.alias_func: |
|
|
|
if not func.alias_func: |
|
|
|
self.write_function_ptr_resolver(func) |
|
|
|
self.write_function_ptr_resolver(func) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for func in self.functions.values(): |
|
|
|
self.write_dispatch_table_stub(func) |
|
|
|
self.write_dispatch_table_stub(func) |
|
|
|
|
|
|
|
|
|
|
|
argparser = argparse.ArgumentParser(description='Generate GL dispatch wrappers.') |
|
|
|
argparser = argparse.ArgumentParser(description='Generate GL dispatch wrappers.') |
|
|
@ -443,13 +474,14 @@ for file in args.files: |
|
|
|
generator = Generator() |
|
|
|
generator = Generator() |
|
|
|
generator.parse(file) |
|
|
|
generator.parse(file) |
|
|
|
generator.drop_weird_glx_functions() |
|
|
|
generator.drop_weird_glx_functions() |
|
|
|
|
|
|
|
generator.resolve_aliases() |
|
|
|
generator.fixup_bootstrap_function('glGetString') |
|
|
|
generator.fixup_bootstrap_function('glGetString') |
|
|
|
generator.fixup_bootstrap_function('glGetIntegerv') |
|
|
|
generator.fixup_bootstrap_function('glGetIntegerv') |
|
|
|
|
|
|
|
|
|
|
|
# While this is technically exposed as a GLX extension, it's |
|
|
|
# While this is technically exposed as a GLX extension, it's |
|
|
|
# required to be present as a public symbol by the Linux OpenGL |
|
|
|
# required to be present as a public symbol by the Linux OpenGL |
|
|
|
# ABI. |
|
|
|
# ABI. |
|
|
|
generator.fixup_bootstrap_function('glXGetProcAddressARB') |
|
|
|
generator.fixup_bootstrap_function('glXGetProcAddress') |
|
|
|
|
|
|
|
|
|
|
|
generator.write_header(incdir + name + '_generated.h') |
|
|
|
generator.write_header(incdir + name + '_generated.h') |
|
|
|
generator.write_proto_define_header(incdir + name + '_generated_vtable_defines.h', '') |
|
|
|
generator.write_proto_define_header(incdir + name + '_generated_vtable_defines.h', '') |
|
|
|