0,0 → 1,190 |
/* |
* 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> |
*/ |
|
#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); |
} |