diff options
Diffstat (limited to 'src/mapi/mapi.c')
-rw-r--r-- | src/mapi/mapi.c | 191 |
1 files changed, 191 insertions, 0 deletions
diff --git a/src/mapi/mapi.c b/src/mapi/mapi.c new file mode 100644 index 00000000000..b471c40b144 --- /dev/null +++ b/src/mapi/mapi.c @@ -0,0 +1,191 @@ +/* + * 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 <[email protected]> + */ + +#include <stdlib.h> +#include <string.h> + +#include "u_current.h" +#include "u_thread.h" +#include "mapi.h" +#include "stub.h" +#include "table.h" + +/* dynamic stubs will run out before this array */ +static const struct mapi_stub *mapi_stub_map[MAPI_TABLE_NUM_SLOTS]; +static int mapi_num_stubs; + +static const struct mapi_stub * +get_stub(const char *name, const struct mapi_stub *alias) +{ + const struct mapi_stub *stub; + + stub = stub_find_public(name); + if (!stub) { + struct mapi_stub *dyn = stub_find_dynamic(name, 1); + if (dyn) { + stub_fix_dynamic(dyn, alias); + stub = dyn; + } + } + + return stub; +} + +/** + * Initialize mapi. spec consists of NULL-separated strings. The first string + * denotes the version. It is followed by variable numbers of entries. Each + * entry can have multiple names. An empty name terminates an entry. An empty + * entry terminates the spec. A spec of two entries, Foo and Bar, is as + * follows + * + * "1\0" + * "Foo\0" + * "FooEXT\0" + * "\0" + * "Bar\0" + * "\0" + */ +void +mapi_init(const char *spec) +{ + u_mutex_declare_static(mutex); + const char *p; + int ver, count; + + u_mutex_lock(mutex); + + /* already initialized */ + if (mapi_num_stubs) { + u_mutex_unlock(mutex); + return; + } + + count = 0; + p = spec; + + /* parse version string */ + ver = atoi(p); + if (ver != 1) { + u_mutex_unlock(mutex); + return; + } + p += strlen(p) + 1; + + while (*p) { + const struct mapi_stub *stub; + + stub = get_stub(p, NULL); + /* out of dynamic entries */ + if (!stub) + break; + p += strlen(p) + 1; + + while (*p) { + get_stub(p, stub); + p += strlen(p) + 1; + } + + mapi_stub_map[count++] = stub; + p++; + } + + mapi_num_stubs = count; + + u_mutex_unlock(mutex); +} + +/** + * Return the address of an entry. Optionally generate the entry if it does + * not exist. + */ +mapi_proc +mapi_get_proc_address(const char *name) +{ + const struct mapi_stub *stub; + + stub = stub_find_public(name); + if (!stub) + stub = stub_find_dynamic(name, 0); + + return (stub) ? (mapi_proc) stub_get_addr(stub) : NULL; +} + +/** + * Create a dispatch table. + */ +struct mapi_table * +mapi_table_create(void) +{ + const struct mapi_table *noop = table_get_noop(); + struct mapi_table *tbl; + + tbl = malloc(MAPI_TABLE_SIZE); + if (tbl) + memcpy(tbl, noop, MAPI_TABLE_SIZE); + + return tbl; +} + +/** + * Destroy a dispatch table. + */ +void +mapi_table_destroy(struct mapi_table *tbl) +{ + free(tbl); +} + +/** + * Fill a dispatch table. The order of the procs is determined when mapi_init + * is called. + */ +void +mapi_table_fill(struct mapi_table *tbl, const mapi_proc *procs) +{ + const struct mapi_table *noop = table_get_noop(); + int i; + + 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, slot); + table_set_func(tbl, slot, func); + } +} + +/** + * Make a dispatch table current. + */ +void +mapi_table_make_current(const struct mapi_table *tbl) +{ + u_current_set(tbl); +} |