diff options
Diffstat (limited to 'src/mapi/mapi')
-rw-r--r-- | src/mapi/mapi/entry.c | 37 | ||||
-rw-r--r-- | src/mapi/mapi/entry.h | 9 | ||||
-rw-r--r-- | src/mapi/mapi/entry_x86-64_tls.h | 41 | ||||
-rw-r--r-- | src/mapi/mapi/entry_x86_tls.h | 36 | ||||
-rw-r--r-- | src/mapi/mapi/entry_x86_tsd.h | 24 | ||||
-rw-r--r-- | src/mapi/mapi/mapi.c | 7 | ||||
-rw-r--r-- | src/mapi/mapi/mapi_abi.py | 944 | ||||
-rw-r--r-- | src/mapi/mapi/mapi_glapi.c | 240 | ||||
-rw-r--r-- | src/mapi/mapi/mapi_tmp.h | 15 | ||||
-rw-r--r-- | src/mapi/mapi/sources.mak | 30 | ||||
-rw-r--r-- | src/mapi/mapi/stub.c | 43 | ||||
-rw-r--r-- | src/mapi/mapi/stub.h | 17 | ||||
-rw-r--r-- | src/mapi/mapi/table.c | 4 | ||||
-rw-r--r-- | src/mapi/mapi/table.h | 16 | ||||
-rw-r--r-- | src/mapi/mapi/u_current.c | 49 | ||||
-rw-r--r-- | src/mapi/mapi/u_current.h | 51 | ||||
-rw-r--r-- | src/mapi/mapi/u_thread.c | 11 | ||||
-rw-r--r-- | src/mapi/mapi/u_thread.h | 2 |
18 files changed, 1341 insertions, 235 deletions
diff --git a/src/mapi/mapi/entry.c b/src/mapi/mapi/entry.c index fdf2a89c52f..3d9168a7243 100644 --- a/src/mapi/mapi/entry.c +++ b/src/mapi/mapi/entry.c @@ -27,6 +27,18 @@ */ #include "entry.h" +#include "u_current.h" +#include "u_macros.h" + +/* define macros for use by assembly dispatchers */ +#define ENTRY_CURRENT_TABLE U_STRINGIFY(u_current_table) + +/* in bridge mode, mapi is a user of glapi */ +#ifdef MAPI_MODE_BRIDGE +#define ENTRY_CURRENT_TABLE_GET "_glapi_get_dispatch" +#else +#define ENTRY_CURRENT_TABLE_GET U_STRINGIFY(u_current_get_internal) +#endif #if defined(USE_X86_ASM) && defined(__GNUC__) # ifdef GLX_USE_TLS @@ -39,19 +51,38 @@ #else #include <stdlib.h> -#include "u_current.h" -#include "table.h" + +static INLINE const struct mapi_table * +entry_current_get(void) +{ +#ifdef MAPI_MODE_BRIDGE + return GET_DISPATCH(); +#else + return u_current_get(); +#endif +} /* C version of the public entries */ +#define MAPI_TMP_DEFINES +#define MAPI_TMP_PUBLIC_DECLARES #define MAPI_TMP_PUBLIC_ENTRIES #include "mapi_tmp.h" +#ifndef MAPI_MODE_BRIDGE + void entry_patch_public(void) { } mapi_func +entry_get_public(int slot) +{ + /* pubic_entries are defined by MAPI_TMP_PUBLIC_ENTRIES */ + return public_entries[slot]; +} + +mapi_func entry_generate(int slot) { return NULL; @@ -62,4 +93,6 @@ entry_patch(mapi_func entry, int slot) { } +#endif /* MAPI_MODE_BRIDGE */ + #endif /* asm */ diff --git a/src/mapi/mapi/entry.h b/src/mapi/mapi/entry.h index 48ed3f9ec4a..9df81000470 100644 --- a/src/mapi/mapi/entry.h +++ b/src/mapi/mapi/entry.h @@ -30,17 +30,16 @@ #define _ENTRY_H_ #include "u_compiler.h" -#include "stub.h" -/* declare public entries */ -#define MAPI_TMP_DEFINES -#define MAPI_TMP_PUBLIC_DECLARES -#include "mapi_tmp.h" +typedef void (*mapi_func)(void); void entry_patch_public(void); mapi_func +entry_get_public(int slot); + +mapi_func entry_generate(int slot); void diff --git a/src/mapi/mapi/entry_x86-64_tls.h b/src/mapi/mapi/entry_x86-64_tls.h index 2fbe73b5b32..d3b606c8ac5 100644 --- a/src/mapi/mapi/entry_x86-64_tls.h +++ b/src/mapi/mapi/entry_x86-64_tls.h @@ -26,15 +26,24 @@ * Chia-I Wu <olv@lunarg.com> */ -#include <string.h> -#include "u_execmem.h" #include "u_macros.h" -__asm__(".text"); +#ifdef __linux__ +__asm__(".section .note.ABI-tag, \"a\"\n\t" + ".p2align 2\n\t" + ".long 1f - 0f\n\t" /* name length */ + ".long 3f - 2f\n\t" /* data length */ + ".long 1\n\t" /* note length */ + "0: .asciz \"GNU\"\n\t" /* vendor name */ + "1: .p2align 2\n\t" + "2: .long 0\n\t" /* note data: the ABI tag */ + ".long 2,4,20\n\t" /* Minimum kernel version w/TLS */ + "3: .p2align 2\n\t"); /* pad out section */ +#endif /* __linux__ */ -__asm__("x86_64_current_tls:\n\t" - "movq u_current_table_tls@GOTTPOFF(%rip), %rax\n\t" - "ret"); +__asm__(".text\n" + ".balign 32\n" + "x86_64_entry_start:"); #define STUB_ASM_ENTRY(func) \ ".globl " func "\n" \ @@ -43,21 +52,37 @@ __asm__("x86_64_current_tls:\n\t" func ":" #define STUB_ASM_CODE(slot) \ - "movq u_current_table_tls@GOTTPOFF(%rip), %rax\n\t" \ + "movq " ENTRY_CURRENT_TABLE "@GOTTPOFF(%rip), %rax\n\t" \ "movq %fs:(%rax), %r11\n\t" \ "jmp *(8 * " slot ")(%r11)" #define MAPI_TMP_STUB_ASM_GCC #include "mapi_tmp.h" +#ifndef MAPI_MODE_BRIDGE + +__asm__("x86_64_current_tls:\n\t" + "movq " ENTRY_CURRENT_TABLE "@GOTTPOFF(%rip), %rax\n\t" + "ret"); + extern unsigned long x86_64_current_tls(); +#include <string.h> +#include "u_execmem.h" + void entry_patch_public(void) { } +mapi_func +entry_get_public(int slot) +{ + extern char x86_64_entry_start[]; + return (mapi_func) (x86_64_entry_start + slot * 32); +} + void entry_patch(mapi_func entry, int slot) { @@ -95,3 +120,5 @@ entry_generate(int slot) return entry; } + +#endif /* MAPI_MODE_BRIDGE */ diff --git a/src/mapi/mapi/entry_x86_tls.h b/src/mapi/mapi/entry_x86_tls.h index d4f7d98cf12..5169069a132 100644 --- a/src/mapi/mapi/entry_x86_tls.h +++ b/src/mapi/mapi/entry_x86_tls.h @@ -27,9 +27,21 @@ */ #include <string.h> -#include "u_execmem.h" #include "u_macros.h" +#ifdef __linux__ +__asm__(".section .note.ABI-tag, \"a\"\n\t" + ".p2align 2\n\t" + ".long 1f - 0f\n\t" /* name length */ + ".long 3f - 2f\n\t" /* data length */ + ".long 1\n\t" /* note length */ + "0: .asciz \"GNU\"\n\t" /* vendor name */ + "1: .p2align 2\n\t" + "2: .long 0\n\t" /* note data: the ABI tag */ + ".long 2,4,20\n\t" /* Minimum kernel version w/TLS */ + "3: .p2align 2\n\t"); /* pad out section */ +#endif /* __linux__ */ + __asm__(".text"); __asm__("x86_current_tls:\n\t" @@ -37,15 +49,16 @@ __asm__("x86_current_tls:\n\t" "1:\n\t" "popl %eax\n\t" "addl $_GLOBAL_OFFSET_TABLE_+[.-1b], %eax\n\t" - "movl u_current_table_tls@GOTNTPOFF(%eax), %eax\n\t" + "movl " ENTRY_CURRENT_TABLE "@GOTNTPOFF(%eax), %eax\n\t" "ret"); #ifndef GLX_X86_READONLY_TEXT -__asm__(".section wtext, \"awx\", @progbits\n" - ".balign 16\n" - "x86_entry_start:"); +__asm__(".section wtext, \"awx\", @progbits"); #endif /* GLX_X86_READONLY_TEXT */ +__asm__(".balign 16\n" + "x86_entry_start:"); + #define STUB_ASM_ENTRY(func) \ ".globl " func "\n" \ ".type " func ", @function\n" \ @@ -66,6 +79,10 @@ __asm__(".balign 16\n" __asm__(".text"); #endif /* GLX_X86_READONLY_TEXT */ +#ifndef MAPI_MODE_BRIDGE + +#include "u_execmem.h" + extern unsigned long x86_current_tls(); @@ -88,6 +105,13 @@ entry_patch_public(void) #endif } +mapi_func +entry_get_public(int slot) +{ + extern char x86_entry_start[]; + return (mapi_func) (x86_entry_start + slot * 16); +} + void entry_patch(mapi_func entry, int slot) { @@ -118,3 +142,5 @@ entry_generate(int slot) return entry; } + +#endif /* MAPI_MODE_BRIDGE */ diff --git a/src/mapi/mapi/entry_x86_tsd.h b/src/mapi/mapi/entry_x86_tsd.h index f37c7473a6f..1491478d470 100644 --- a/src/mapi/mapi/entry_x86_tsd.h +++ b/src/mapi/mapi/entry_x86_tsd.h @@ -26,13 +26,13 @@ * Chia-I Wu <olv@lunarg.com> */ -#include <string.h> -#include "u_execmem.h" #include "u_macros.h" #define X86_ENTRY_SIZE 32 -__asm__(".text"); +__asm__(".text\n" + ".balign 32\n" + "x86_entry_start:"); #define STUB_ASM_ENTRY(func) \ ".globl " func "\n" \ @@ -41,25 +41,37 @@ __asm__(".text"); func ":" #define STUB_ASM_CODE(slot) \ - "movl u_current_table, %eax\n\t" \ + "movl " ENTRY_CURRENT_TABLE ", %eax\n\t" \ "testl %eax, %eax\n\t" \ "je 1f\n\t" \ "jmp *(4 * " slot ")(%eax)\n" \ "1:\n\t" \ - "call u_current_get_internal\n\t"\ + "call " ENTRY_CURRENT_TABLE_GET "\n\t" \ "jmp *(4 * " slot ")(%eax)" #define MAPI_TMP_STUB_ASM_GCC #include "mapi_tmp.h" +#ifndef MAPI_MODE_BRIDGE + __asm__(".balign 32\n" "x86_entry_end:"); +#include <string.h> +#include "u_execmem.h" + void entry_patch_public(void) { } +mapi_func +entry_get_public(int slot) +{ + extern const char x86_entry_start[]; + return (mapi_func) (x86_entry_start + slot * X86_ENTRY_SIZE); +} + void entry_patch(mapi_func entry, int slot) { @@ -87,3 +99,5 @@ entry_generate(int slot) return entry; } + +#endif /* MAPI_MODE_BRIDGE */ diff --git a/src/mapi/mapi/mapi.c b/src/mapi/mapi/mapi.c index 5476d37fdc9..b471c40b144 100644 --- a/src/mapi/mapi/mapi.c +++ b/src/mapi/mapi/mapi.c @@ -132,7 +132,7 @@ mapi_get_proc_address(const char *name) if (!stub) stub = stub_find_dynamic(name, 0); - return (stub) ? (mapi_proc) stub->addr : NULL; + return (stub) ? (mapi_proc) stub_get_addr(stub) : NULL; } /** @@ -172,11 +172,12 @@ mapi_table_fill(struct mapi_table *tbl, const mapi_proc *procs) for (i = 0; i < mapi_num_stubs; i++) { const struct mapi_stub *stub = mapi_stub_map[i]; + int slot = stub_get_slot(stub); mapi_func func = (mapi_func) procs[i]; if (!func) - func = table_get_func(noop, stub); - table_set_func(tbl, stub, func); + func = table_get_func(noop, slot); + table_set_func(tbl, slot, func); } } diff --git a/src/mapi/mapi/mapi_abi.py b/src/mapi/mapi/mapi_abi.py index 3a872666f96..cb9fc0ef841 100644 --- a/src/mapi/mapi/mapi_abi.py +++ b/src/mapi/mapi/mapi_abi.py @@ -45,6 +45,7 @@ class ABIEntry(object): 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()) @@ -125,6 +126,61 @@ class ABIEntry(object): 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(',')] @@ -132,6 +188,7 @@ def abi_parse_line(line): 'slot': -1, 'hidden': False, 'alias': None, + 'handcode': None, } # extract attributes from the first column @@ -144,6 +201,8 @@ def abi_parse_line(line): attrs['hidden'] = True elif val.startswith('alias='): attrs['alias'] = val[6:] + elif val.startswith('handcode='): + attrs['handcode'] = val[9:] elif not val: pass else: @@ -166,10 +225,13 @@ def abi_parse(filename): # post-process attributes if attrs['alias']: try: - ent = entry_dict[attrs['alias']] - slot = ent.slot + 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 @@ -187,21 +249,39 @@ def abi_parse(filename): entries = entry_dict.values() entries.sort() - # sanity check + return entries + +def abi_sanity_check(entries): + if not entries: + return + + all_names = [] + last_slot = entries[-1].slot i = 0 - for slot in xrange(next_slot): + 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)) + % (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)) - return entries - class ABIPrinter(object): """MAPI Printer""" @@ -215,6 +295,7 @@ class ABIPrinter(object): 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"'] @@ -222,30 +303,52 @@ class ABIPrinter(object): self.api_entry = 'KHRONOS_APIENTRY' self.api_attrs = 'KHRONOS_APIATTRIBUTES' - def c_header(self): + 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_includes(self): + 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 c_mapi_table(self): - """Return defines of the dispatch table size.""" - num_static_entries = 0 + 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 ent.alias: - num_static_entries += 1 + 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 = [ent.name for ent in self.entries if not ent.alias] - pre = self.indent + '(mapi_proc) ' + prefix + 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): @@ -263,11 +366,38 @@ class ABIPrinter(object): return self.indent + self.indent.join(specv1) - def _c_decl(self, ent, prefix, need_attr=True): + 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(%s)' % (ent.c_return(), self.api_entry, - prefix, ent.name, ent.c_params()) - if need_attr and self.api_attrs: + 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 @@ -281,37 +411,60 @@ class ABIPrinter(object): def c_private_declarations(self, prefix): """Return the declarations of private functions.""" - decls = [self._c_decl(ent, prefix) + decls = [self._c_decl(ent, prefix) + ';' for ent in self.entries if not ent.alias] - return ";\n".join(decls) + ";" + return "\n".join(decls) - def c_public_dispatches(self, prefix): + def c_public_dispatches(self, prefix, no_hidden): """Return the public dispatch functions.""" dispatches = [] for ent in self.entries: - if ent.hidden: + if ent.hidden and no_hidden: continue - proto = self.api_call + ' ' + self._c_decl(ent, prefix) + 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 = u_current_get();' + stmt1 += 'const struct mapi_table *_tbl = %s();' % ( + self.current_get) stmt2 = self.indent - stmt2 += 'mapi_func func = ((const mapi_func *) tbl)[%d];' % ( + stmt2 += 'mapi_func _func = ((const mapi_func *) _tbl)[%d];' % ( ent.slot) stmt3 = self.indent - stmt3 += '%s((%s) func)(%s);' % (ret, cast, ent.c_args()) + 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 @@ -334,8 +487,8 @@ class ABIPrinter(object): """Return the initializer for struct mapi_stub array.""" stubs = [] for ent in self.entries_sorted_by_names: - stubs.append('%s{ (mapi_func) %s%s, %d, (void *) %d }' % ( - self.indent, prefix, ent.name, ent.slot, pool_offsets[ent])) + stubs.append('%s{ (void *) %d, %d, NULL }' % ( + self.indent, pool_offsets[ent], ent.slot)) return ',\n'.join(stubs) @@ -346,10 +499,10 @@ class ABIPrinter(object): if ent.alias: continue - proto = 'static ' + self._c_decl(ent, prefix) + proto = self._c_decl(ent, prefix, False, 'static') - stmt1 = self.indent + '%s("%s%s");' % ( - self.noop_warn, warn_prefix, ent.name) + 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) @@ -363,7 +516,8 @@ class ABIPrinter(object): def c_noop_initializer(self, prefix, use_generic): """Return an initializer for the noop dispatch table.""" - entries = [prefix + ent.name for ent in self.entries if not ent.alias] + entries = [self._c_function(ent, prefix) + for ent in self.entries if not ent.alias] if use_generic: entries = [self.noop_generic] * len(entries) @@ -372,86 +526,138 @@ class ABIPrinter(object): pre = self.indent + '(mapi_func) ' return pre + (',\n' + pre).join(entries) - def c_asm_gcc(self, prefix): + def c_asm_gcc(self, prefix, no_hidden): asm = [] - to_name = None - asm.append('__asm__(') for ent in self.entries: - name = prefix + ent.name + 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)) + asm.append('".hidden "%s"\\n"' % (name)) - if ent.alias: - asm.append('".globl %s\\n"' % (name)) - asm.append('".set %s, %s\\n"' % (name, to_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('STUB_ASM_ENTRY(%s)"\\n"' % (name)) asm.append('"\\t"STUB_ASM_CODE("%d")"\\n"' % (ent.slot)) - to_name = name - asm.append(');') + + if ent.handcode: + asm.append('#endif') + asm.append('') return "\n".join(asm) def output_for_lib(self): - print self.c_header() - print - print '#ifdef MAPI_TMP_DEFINES' - print self.c_includes() - print '#undef MAPI_TMP_DEFINES' - print '#endif /* MAPI_TMP_DEFINES */' - print - print '#ifdef MAPI_TMP_TABLE' - print self.c_mapi_table() - print '#undef MAPI_TMP_TABLE' - print '#endif /* MAPI_TMP_TABLE */' - print + print self.c_notice() - pool, pool_offsets = self.c_stub_string_pool() - 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 */' - print + if self.c_header: + print + print self.c_header - print '#ifdef MAPI_TMP_PUBLIC_ENTRIES' - print self.c_public_dispatches(self.prefix_lib) - print '#undef MAPI_TMP_PUBLIC_ENTRIES' - print '#endif /* MAPI_TMP_PUBLIC_ENTRIES */' - print - - print '#ifdef MAPI_TMP_NOOP_ARRAY' - print '#ifdef DEBUG' - print - print self.c_noop_functions(self.prefix_noop, self.prefix_lib) 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 '#endif /* DEBUG */' - print '#undef MAPI_TMP_NOOP_ARRAY' - print '#endif /* MAPI_TMP_NOOP_ARRAY */' + 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 */' - print '#ifdef MAPI_TMP_STUB_ASM_GCC' - print self.c_asm_gcc(self.prefix_lib) - print '#undef MAPI_TMP_STUB_ASM_GCC' - print '#endif /* MAPI_TMP_STUB_ASM_GCC */' + 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_header() + print self.c_notice() print print self.c_private_declarations(self.prefix_app) print @@ -469,8 +675,9 @@ class ABIPrinter(object): class GLAPIPrinter(ABIPrinter): """OpenGL API Printer""" - def __init__(self, entries): - super(GLAPIPrinter, self).__init__(entries) + 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"'] @@ -478,33 +685,539 @@ class GLAPIPrinter(ABIPrinter): self.api_entry = 'APIENTRY' self.api_attrs = '' - self.prefix_lib = 'gl' + 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 - def output_for_app(self): - # not used - pass + 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): - super(ES1APIPrinter, self).__init__(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' - self.api_headers = ['"GLES/gl.h"', '"GLES/glext.h"'] - self.api_call = 'GL_API' - self.api_entry = 'GL_APIENTRY' + 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): - super(ES2APIPrinter, self).__init__(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' - self.api_headers = ['"GLES2/gl2.h"', '"GLES2/gl2ext.h"'] - self.api_call = 'GL_APICALL' - self.api_entry = 'GL_APIENTRY' + 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""" @@ -521,9 +1234,10 @@ class VGAPIPrinter(ABIPrinter): self.prefix_lib = 'vg' self.prefix_app = 'vega' self.prefix_noop = 'noop' + self.prefix_warn = 'vg' def parse_args(): - printers = ['glapi', 'es1api', 'es2api', 'vgapi'] + printers = ['vgapi', 'glapi', 'es1api', 'es2api', 'shared-glapi'] modes = ['lib', 'app'] parser = OptionParser(usage='usage: %prog [options] <filename>') @@ -545,12 +1259,18 @@ def main(): 'vgapi': VGAPIPrinter, 'glapi': GLAPIPrinter, 'es1api': ES1APIPrinter, - 'es2api': ES2APIPrinter + 'es2api': ES2APIPrinter, + 'shared-glapi': SharedGLAPIPrinter, } filename, options = parse_args() - entries = abi_parse(filename) + 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() diff --git a/src/mapi/mapi/mapi_glapi.c b/src/mapi/mapi/mapi_glapi.c new file mode 100644 index 00000000000..adfc0cbcc9f --- /dev/null +++ b/src/mapi/mapi/mapi_glapi.c @@ -0,0 +1,240 @@ +/* + * Mesa 3-D graphics library + * Version: 7.9 + * + * Copyright (C) 1999-2008 Brian Paul All Rights Reserved. + * 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> + */ + +#include <string.h> +#include "glapi/glapi.h" +#include "mapi/u_current.h" +#include "mapi/table.h" /* for MAPI_TABLE_NUM_SLOTS */ +#include "mapi/stub.h" + +/* + * Global variables, _glapi_get_context, and _glapi_get_dispatch are defined in + * u_current.c. + */ + +#ifdef GLX_USE_TLS +/* not used, but defined for compatibility */ +const struct _glapi_table *_glapi_Dispatch; +const void *_glapi_Context; +#endif /* GLX_USE_TLS */ + +void +_glapi_destroy_multithread(void) +{ + u_current_destroy(); +} + +void +_glapi_check_multithread(void) +{ + u_current_init(); +} + +void +_glapi_set_context(void *context) +{ + u_current_set_user((const void *) context); +} + +void +_glapi_set_dispatch(struct _glapi_table *dispatch) +{ + u_current_set((const struct mapi_table *) dispatch); +} + +/** + * Return size of dispatch table struct as number of functions (or + * slots). + */ +unsigned int +_glapi_get_dispatch_table_size(void) +{ + return MAPI_TABLE_NUM_SLOTS; +} + +/** + * Fill-in the dispatch stub for the named function. + * + * This function is intended to be called by a hardware driver. When called, + * a dispatch stub may be created created for the function. A pointer to this + * dispatch function will be returned by glXGetProcAddress. + * + * \param function_names Array of pointers to function names that should + * share a common dispatch offset. + * \param parameter_signature String representing the types of the parameters + * passed to the named function. Parameter types + * are converted to characters using the following + * rules: + * - 'i' for \c GLint, \c GLuint, and \c GLenum + * - 'p' for any pointer type + * - 'f' for \c GLfloat and \c GLclampf + * - 'd' for \c GLdouble and \c GLclampd + * + * \returns + * The offset in the dispatch table of the named function. A pointer to the + * driver's implementation of the named function should be stored at + * \c dispatch_table[\c offset]. Return -1 if error/problem. + * + * \sa glXGetProcAddress + * + * \warning + * This function can only handle up to 8 names at a time. As far as I know, + * the maximum number of names ever associated with an existing GL function is + * 4 (\c glPointParameterfSGIS, \c glPointParameterfEXT, + * \c glPointParameterfARB, and \c glPointParameterf), so this should not be + * too painful of a limitation. + * + * \todo + * Check parameter_signature. + */ +int +_glapi_add_dispatch( const char * const * function_names, + const char * parameter_signature ) +{ + const struct mapi_stub *function_stubs[8]; + const struct mapi_stub *alias = NULL; + unsigned i; + + (void) memset(function_stubs, 0, sizeof(function_stubs)); + + /* find the missing stubs, and decide the alias */ + for (i = 0; function_names[i] != NULL && i < 8; i++) { + const char * funcName = function_names[i]; + const struct mapi_stub *stub; + int slot; + + if (!funcName || funcName[0] != 'g' || funcName[1] != 'l') + return -1; + funcName += 2; + + stub = stub_find_public(funcName); + if (!stub) + stub = stub_find_dynamic(funcName, 0); + + slot = (stub) ? stub_get_slot(stub) : -1; + if (slot >= 0) { + if (alias && stub_get_slot(alias) != slot) + return -1; + /* use the first existing stub as the alias */ + if (!alias) + alias = stub; + + function_stubs[i] = stub; + } + } + + /* generate missing stubs */ + for (i = 0; function_names[i] != NULL && i < 8; i++) { + const char * funcName = function_names[i] + 2; + struct mapi_stub *stub; + + if (function_stubs[i]) + continue; + + stub = stub_find_dynamic(funcName, 1); + if (!stub) + return -1; + + stub_fix_dynamic(stub, alias); + if (!alias) + alias = stub; + } + + return (alias) ? stub_get_slot(alias) : -1; +} + +static const struct mapi_stub * +_glapi_get_stub(const char *name, int generate) +{ + const struct mapi_stub *stub; + +#ifdef USE_MGL_NAMESPACE + if (name) + name++; +#endif + + if (!name || name[0] != 'g' || name[1] != 'l') + return NULL; + name += 2; + + stub = stub_find_public(name); + if (!stub) + stub = stub_find_dynamic(name, generate); + + return stub; +} + +/** + * Return offset of entrypoint for named function within dispatch table. + */ +int +_glapi_get_proc_offset(const char *funcName) +{ + const struct mapi_stub *stub = _glapi_get_stub(funcName, 0); + return (stub) ? stub_get_slot(stub) : -1; +} + +/** + * Return pointer to the named function. If the function name isn't found + * in the name of static functions, try generating a new API entrypoint on + * the fly with assembly language. + */ +_glapi_proc +_glapi_get_proc_address(const char *funcName) +{ + const struct mapi_stub *stub = _glapi_get_stub(funcName, 1); + return (stub) ? (_glapi_proc) stub_get_addr(stub) : NULL; +} + +/** + * Return the name of the function at the given dispatch offset. + * This is only intended for debugging. + */ +const char * +_glapi_get_proc_name(unsigned int offset) +{ + /* not implemented */ + return NULL; +} + +unsigned long +_glthread_GetID(void) +{ + return u_thread_self(); +} + +void +_glapi_noop_enable_warnings(unsigned char enable) +{ +} + +void +_glapi_set_warning_func(_glapi_proc func) +{ +} diff --git a/src/mapi/mapi/mapi_tmp.h b/src/mapi/mapi/mapi_tmp.h index a1b067fb73c..f326b4a4e14 100644 --- a/src/mapi/mapi/mapi_tmp.h +++ b/src/mapi/mapi/mapi_tmp.h @@ -30,4 +30,19 @@ #error "MAPI_ABI_HEADER must be defined" #endif +/* does not need hidden entries in bridge mode */ +#ifdef MAPI_MODE_BRIDGE + +#ifdef MAPI_TMP_PUBLIC_ENTRIES +#undef MAPI_TMP_PUBLIC_ENTRIES +#define MAPI_TMP_PUBLIC_ENTRIES_NO_HIDDEN +#endif + +#ifdef MAPI_TMP_STUB_ASM_GCC +#undef MAPI_TMP_STUB_ASM_GCC +#define MAPI_TMP_STUB_ASM_GCC_NO_HIDDEN +#endif + +#endif /* MAPI_MODE_BRIDGE */ + #include MAPI_ABI_HEADER diff --git a/src/mapi/mapi/sources.mak b/src/mapi/mapi/sources.mak index 5f327f3df62..c50234b5789 100644 --- a/src/mapi/mapi/sources.mak +++ b/src/mapi/mapi/sources.mak @@ -1,12 +1,20 @@ # src/mapi/mapi/sources.mak # -# When MAPI_GLAPI_CURRENT is defined, MAPI_GLAPI_SOURCES can be built without -# MAPI_SOURCES and it is used by glapi. +# mapi may be used in several ways # -# Otherwise, MAPI_ABI_HEADER must be defined. It should expand to the header -# generated by mapi_abi.py. +# - In default mode, mapi implements the interface defined by mapi.h. To use +# this mode, compile MAPI_SOURCES. +# +# - In util mode, mapi provides utility functions for use with glapi. To use +# this mode, compile MAPI_UTIL_SOURCES with MAPI_MODE_UTIL defined. +# +# - In glapi mode, mapi implements the interface defined by glapi.h. To use +# this mode, compile MAPI_GLAPI_SOURCES with MAPI_MODE_GLAPI defined. +# +# - In bridge mode, mapi provides entry points calling into glapi. To use +# this mode, compile MAPI_BRIDGE_SOURCES with MAPI_MODE_BRIDGE defined. -MAPI_GLAPI_SOURCES = \ +MAPI_UTIL_SOURCES = \ u_current.c \ u_execmem.c \ u_thread.c @@ -16,4 +24,14 @@ MAPI_SOURCES = \ mapi.c \ stub.c \ table.c \ - $(MAPI_GLAPI_SOURCES) + $(MAPI_UTIL_SOURCES) + +MAPI_GLAPI_SOURCES = \ + entry.c \ + mapi_glapi.c \ + stub.c \ + table.c \ + $(MAPI_UTIL_SOURCES) + +MAPI_BRIDGE_SOURCES = \ + entry.c diff --git a/src/mapi/mapi/stub.c b/src/mapi/mapi/stub.c index 3594eacb4ec..99b475a3b4b 100644 --- a/src/mapi/mapi/stub.c +++ b/src/mapi/mapi/stub.c @@ -27,7 +27,6 @@ */ #include <stdlib.h> -#include <stddef.h> /* for offsetof */ #include <string.h> #include <assert.h> @@ -39,6 +38,12 @@ #define ARRAY_SIZE(x) (sizeof(x)/sizeof((x)[0])) +struct mapi_stub { + const void *name; + int slot; + mapi_func addr; +}; + /* define public_string_pool and public_stubs */ #define MAPI_TMP_PUBLIC_STUBS #include "mapi_tmp.h" @@ -164,3 +169,39 @@ stub_fix_dynamic(struct mapi_stub *stub, const struct mapi_stub *alias) entry_patch(stub->addr, slot); stub->slot = slot; } + +/** + * Return the name of a stub. + */ +const char * +stub_get_name(const struct mapi_stub *stub) +{ + const char *name; + + if (stub >= public_stubs && + stub < public_stubs + ARRAY_SIZE(public_stubs)) + name = &public_string_pool[(unsigned long) stub->name]; + else + name = (const char *) stub->name; + + return name; +} + +/** + * Return the slot of a stub. + */ +int +stub_get_slot(const struct mapi_stub *stub) +{ + return stub->slot; +} + +/** + * Return the address of a stub. + */ +mapi_func +stub_get_addr(const struct mapi_stub *stub) +{ + assert(stub->addr || (unsigned int) stub->slot < MAPI_TABLE_NUM_STATIC); + return (stub->addr) ? stub->addr : entry_get_public(stub->slot); +} diff --git a/src/mapi/mapi/stub.h b/src/mapi/mapi/stub.h index c7e194cf4fc..b2b6f1839c6 100644 --- a/src/mapi/mapi/stub.h +++ b/src/mapi/mapi/stub.h @@ -29,13 +29,9 @@ #ifndef _STUB_H_ #define _STUB_H_ -typedef void (*mapi_func)(void); +#include "entry.h" -struct mapi_stub { - mapi_func addr; - int slot; - const void *name; -}; +struct mapi_stub; void stub_init_once(void); @@ -49,4 +45,13 @@ stub_find_dynamic(const char *name, int generate); void stub_fix_dynamic(struct mapi_stub *stub, const struct mapi_stub *alias); +const char * +stub_get_name(const struct mapi_stub *stub); + +int +stub_get_slot(const struct mapi_stub *stub); + +mapi_func +stub_get_addr(const struct mapi_stub *stub); + #endif /* _STUB_H_ */ diff --git a/src/mapi/mapi/table.c b/src/mapi/mapi/table.c index 8f4f700b920..9bb9f654a2a 100644 --- a/src/mapi/mapi/table.c +++ b/src/mapi/mapi/table.c @@ -29,7 +29,6 @@ #include <stdlib.h> #include <stdio.h> -#include "stub.h" #include "table.h" static void @@ -41,7 +40,7 @@ noop_warn(const char *name) debug = (getenv("MESA_DEBUG") || getenv("LIBGL_DEBUG")); if (debug) - fprintf(stderr, "%s is no-op", name); + fprintf(stderr, "%s is no-op\n", name); } static int @@ -52,5 +51,6 @@ noop_generic(void) } /* define noop_array */ +#define MAPI_TMP_DEFINES #define MAPI_TMP_NOOP_ARRAY #include "mapi_tmp.h" diff --git a/src/mapi/mapi/table.h b/src/mapi/mapi/table.h index ca2be568c70..d84523f7777 100644 --- a/src/mapi/mapi/table.h +++ b/src/mapi/mapi/table.h @@ -30,9 +30,8 @@ #define _TABLE_H_ #include "u_compiler.h" -#include "stub.h" +#include "entry.h" -#define MAPI_TMP_DEFINES #define MAPI_TMP_TABLE #include "mapi_tmp.h" @@ -51,24 +50,23 @@ table_get_noop(void) } /** - * Update the dispatch table to dispatch a stub to the given function. + * Set the function of a slot. */ static INLINE void -table_set_func(struct mapi_table *tbl, - const struct mapi_stub *stub, mapi_func func) +table_set_func(struct mapi_table *tbl, int slot, mapi_func func) { mapi_func *funcs = (mapi_func *) tbl; - funcs[stub->slot] = func; + funcs[slot] = func; } /** - * Return the dispatched function of a stub. + * Return the function of a slot. */ static INLINE mapi_func -table_get_func(const struct mapi_table *tbl, const struct mapi_stub *stub) +table_get_func(const struct mapi_table *tbl, int slot) { const mapi_func *funcs = (const mapi_func *) tbl; - return funcs[stub->slot]; + return funcs[slot]; } #endif /* _TABLE_H_ */ diff --git a/src/mapi/mapi/u_current.c b/src/mapi/mapi/u_current.c index 77a593b330c..21a07abbae5 100644 --- a/src/mapi/mapi/u_current.c +++ b/src/mapi/mapi/u_current.c @@ -51,7 +51,7 @@ #include "u_current.h" #include "u_thread.h" -#ifndef MAPI_GLAPI_CURRENT +#ifndef MAPI_MODE_UTIL #include "table.h" #include "stub.h" @@ -99,16 +99,13 @@ extern void (*__glapi_noop_table[])(void); /*@{*/ #if defined(GLX_USE_TLS) -__thread struct mapi_table *u_current_table_tls +__thread struct mapi_table *u_current_table __attribute__((tls_model("initial-exec"))) = (struct mapi_table *) table_noop_array; -__thread void *u_current_user_tls +__thread void *u_current_user __attribute__((tls_model("initial-exec"))); -const struct mapi_table *u_current_table; -const void *u_current_user; - #else struct mapi_table *u_current_table = @@ -147,15 +144,7 @@ u_current_init_tsd(void) /** * Mutex for multithread check. */ -#ifdef WIN32 -/* _glthread_DECLARE_STATIC_MUTEX is broken on windows. There will be race! */ -#define CHECK_MULTITHREAD_LOCK() -#define CHECK_MULTITHREAD_UNLOCK() -#else u_mutex_declare_static(ThreadCheckMutex); -#define CHECK_MULTITHREAD_LOCK() u_mutex_lock(ThreadCheckMutex) -#define CHECK_MULTITHREAD_UNLOCK() u_mutex_unlock(ThreadCheckMutex) -#endif /** * We should call this periodically from a function such as glXMakeCurrent @@ -170,7 +159,7 @@ u_current_init(void) if (ThreadSafe) return; - CHECK_MULTITHREAD_LOCK(); + u_mutex_lock(ThreadCheckMutex); if (firstCall) { u_current_init_tsd(); @@ -179,10 +168,10 @@ u_current_init(void) } else if (knownID != u_thread_self()) { ThreadSafe = 1; - u_current_set_internal(NULL); - u_current_set_user_internal(NULL); + u_current_set(NULL); + u_current_set_user(NULL); } - CHECK_MULTITHREAD_UNLOCK(); + u_mutex_unlock(ThreadCheckMutex); } #else @@ -202,17 +191,17 @@ u_current_init(void) * void from the real context pointer type. */ void -u_current_set_user_internal(void *ptr) +u_current_set_user(const void *ptr) { u_current_init(); #if defined(GLX_USE_TLS) - u_current_user_tls = ptr; + u_current_user = (void *) ptr; #elif defined(THREADS) - u_tsd_set(&u_current_user_tsd, ptr); - u_current_user = (ThreadSafe) ? NULL : ptr; + u_tsd_set(&u_current_user_tsd, (void *) ptr); + u_current_user = (ThreadSafe) ? NULL : (void *) ptr; #else - u_current_user = ptr; + u_current_user = (void *) ptr; #endif } @@ -225,7 +214,7 @@ void * u_current_get_user_internal(void) { #if defined(GLX_USE_TLS) - return u_current_user_tls; + return u_current_user; #elif defined(THREADS) return (ThreadSafe) ? u_tsd_get(&u_current_user_tsd) @@ -241,22 +230,22 @@ u_current_get_user_internal(void) * table (__glapi_noop_table). */ void -u_current_set_internal(struct mapi_table *tbl) +u_current_set(const struct mapi_table *tbl) { u_current_init(); stub_init_once(); if (!tbl) - tbl = (struct mapi_table *) table_noop_array; + tbl = (const struct mapi_table *) table_noop_array; #if defined(GLX_USE_TLS) - u_current_table_tls = tbl; + u_current_table = (struct mapi_table *) tbl; #elif defined(THREADS) u_tsd_set(&u_current_table_tsd, (void *) tbl); - u_current_table = (ThreadSafe) ? NULL : tbl; + u_current_table = (ThreadSafe) ? NULL : (void *) tbl; #else - u_current_table = tbl; + u_current_table = (struct mapi_table *) tbl; #endif } @@ -267,7 +256,7 @@ struct mapi_table * u_current_get_internal(void) { #if defined(GLX_USE_TLS) - return u_current_table_tls; + return u_current_table; #elif defined(THREADS) return (struct mapi_table *) ((ThreadSafe) ? u_tsd_get(&u_current_table_tsd) : (void *) u_current_table); diff --git a/src/mapi/mapi/u_current.h b/src/mapi/mapi/u_current.h index 62e54c6c93d..f9cffd8c3d0 100644 --- a/src/mapi/mapi/u_current.h +++ b/src/mapi/mapi/u_current.h @@ -1,28 +1,28 @@ #ifndef _U_CURRENT_H_ #define _U_CURRENT_H_ -#ifdef MAPI_GLAPI_CURRENT +#if defined(MAPI_MODE_UTIL) || defined(MAPI_MODE_GLAPI) || \ + defined(MAPI_MODE_BRIDGE) #include "glapi/glapi.h" /* ugly renames to match glapi.h */ #define mapi_table _glapi_table -#define u_current_table_tls _glapi_tls_Dispatch -#define u_current_user_tls _glapi_tls_Context +#ifdef GLX_USE_TLS +#define u_current_table _glapi_tls_Dispatch +#define u_current_user _glapi_tls_Context +#else #define u_current_table _glapi_Dispatch #define u_current_user _glapi_Context +#endif -#define u_current_destroy _glapi_destroy_multithread -#define u_current_init _glapi_check_multithread -#define u_current_set_internal _glapi_set_dispatch #define u_current_get_internal _glapi_get_dispatch -#define u_current_set_user_internal _glapi_set_context #define u_current_get_user_internal _glapi_get_context #define u_current_table_tsd _gl_DispatchTSD -#else /* MAPI_GLAPI_CURRENT */ +#else /* MAPI_MODE_UTIL || MAPI_MODE_GLAPI || MAPI_MODE_BRIDGE */ #include "u_compiler.h" @@ -30,15 +30,12 @@ struct mapi_table; #ifdef GLX_USE_TLS -extern __thread struct mapi_table *u_current_table_tls +extern __thread struct mapi_table *u_current_table __attribute__((tls_model("initial-exec"))); -extern __thread void *u_current_user_tls +extern __thread void *u_current_user __attribute__((tls_model("initial-exec"))); -extern const struct mapi_table *u_current_table; -extern const void *u_current_user; - #else /* GLX_USE_TLS */ extern struct mapi_table *u_current_table; @@ -46,6 +43,8 @@ extern void *u_current_user; #endif /* GLX_USE_TLS */ +#endif /* MAPI_MODE_UTIL || MAPI_MODE_GLAPI || MAPI_MODE_BRIDGE */ + void u_current_init(void); @@ -53,50 +52,36 @@ void u_current_destroy(void); void -u_current_set_internal(struct mapi_table *tbl); +u_current_set(const struct mapi_table *tbl); struct mapi_table * u_current_get_internal(void); void -u_current_set_user_internal(void *ptr); +u_current_set_user(const void *ptr); void * u_current_get_user_internal(void); -static INLINE void -u_current_set(const struct mapi_table *tbl) -{ - u_current_set_internal((struct mapi_table *) tbl); -} - static INLINE const struct mapi_table * u_current_get(void) { #ifdef GLX_USE_TLS - return (const struct mapi_table *) u_current_table_tls; + return u_current_table; #else return (likely(u_current_table) ? - (const struct mapi_table *) u_current_table : u_current_get_internal()); + u_current_table : u_current_get_internal()); #endif } -static INLINE void -u_current_set_user(void *ptr) -{ - u_current_set_internal(ptr); -} - -static INLINE void * +static INLINE const void * u_current_get_user(void) { #ifdef GLX_USE_TLS - return u_current_user_tls; + return u_current_user; #else return likely(u_current_user) ? u_current_user : u_current_get_user_internal(); #endif } -#endif /* MAPI_GLAPI_CURRENT */ - #endif /* _U_CURRENT_H_ */ diff --git a/src/mapi/mapi/u_thread.c b/src/mapi/mapi/u_thread.c index e9eae55364b..12e748fe8ba 100644 --- a/src/mapi/mapi/u_thread.c +++ b/src/mapi/mapi/u_thread.c @@ -113,11 +113,6 @@ u_tsd_set(struct u_tsd *tsd, void *ptr) */ #ifdef WIN32 -static void InsteadOf_exit(int nCode) -{ - DWORD dwErr = GetLastError(); -} - unsigned long u_thread_self(void) { @@ -131,7 +126,7 @@ u_tsd_init(struct u_tsd *tsd) tsd->key = TlsAlloc(); if (tsd->key == TLS_OUT_OF_INDEXES) { perror(INIT_TSD_ERROR); - InsteadOf_exit(-1); + exit(-1); } tsd->initMagic = INIT_MAGIC; } @@ -168,7 +163,7 @@ u_tsd_set(struct u_tsd *tsd, void *ptr) } if (TlsSetValue(tsd->key, ptr) == 0) { perror(SET_TSD_ERROR); - InsteadOf_exit(-1); + exit(-1); } } @@ -222,7 +217,7 @@ u_tsd_set(struct u_tsd *tsd, void *ptr) */ unsigned long -_glthread_GetID(void) +u_thread_self(void) { return 0; } diff --git a/src/mapi/mapi/u_thread.h b/src/mapi/mapi/u_thread.h index 92a0a3916d0..1cc8be3fa3f 100644 --- a/src/mapi/mapi/u_thread.h +++ b/src/mapi/mapi/u_thread.h @@ -97,7 +97,7 @@ typedef CRITICAL_SECTION u_mutex; /* http://locklessinc.com/articles/pthreads_on_windows/ */ #define u_mutex_declare_static(name) \ - /* static */ u_mutex name = {(void*)-1, -1, 0, 0, 0, 0} + static u_mutex name = {(PCRITICAL_SECTION_DEBUG)-1, -1, 0, 0, 0, 0} #define u_mutex_init(name) InitializeCriticalSection(&name) #define u_mutex_destroy(name) DeleteCriticalSection(&name) |