• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Mesa 3-D graphics library
3  *
4  * Copyright (C) 2010 LunarG Inc.
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a
7  * copy of this software and associated documentation files (the "Software"),
8  * to deal in the Software without restriction, including without limitation
9  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10  * and/or sell copies of the Software, and to permit persons to whom the
11  * Software is furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included
14  * in all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22  * DEALINGS IN THE SOFTWARE.
23  *
24  * Authors:
25  *    Chia-I Wu <olv@lunarg.com>
26  */
27 
28 #include <stdlib.h>
29 #include <string.h>
30 
31 #include "u_current.h"
32 #include "mapi.h"
33 #include "stub.h"
34 #include "table.h"
35 
36 /* dynamic stubs will run out before this array */
37 static const struct mapi_stub *mapi_stub_map[MAPI_TABLE_NUM_SLOTS];
38 static int mapi_num_stubs;
39 
40 static const struct mapi_stub *
get_stub(const char * name,const struct mapi_stub * alias)41 get_stub(const char *name, const struct mapi_stub *alias)
42 {
43    const struct mapi_stub *stub;
44 
45    stub = stub_find_public(name);
46    if (!stub) {
47       struct mapi_stub *dyn = stub_find_dynamic(name, 1);
48       if (dyn) {
49          stub_fix_dynamic(dyn, alias);
50          stub = dyn;
51       }
52    }
53 
54    return stub;
55 }
56 
57 /**
58  * Initialize mapi.  spec consists of NULL-separated strings.  The first string
59  * denotes the version.  It is followed by variable numbers of entries.  Each
60  * entry can have multiple names.  An empty name terminates an entry.  An empty
61  * entry terminates the spec.  A spec of two entries, Foo and Bar, is as
62  * follows
63  *
64  *   "1\0"
65  *   "Foo\0"
66  *   "FooEXT\0"
67  *   "\0"
68  *   "Bar\0"
69  *   "\0"
70  */
71 void
mapi_init(const char * spec)72 mapi_init(const char *spec)
73 {
74    static mtx_t mutex = _MTX_INITIALIZER_NP;
75    const char *p;
76    int ver, count;
77 
78    mtx_lock(&mutex);
79 
80    /* already initialized */
81    if (mapi_num_stubs) {
82       mtx_unlock(&mutex);
83       return;
84    }
85 
86    count = 0;
87    p = spec;
88 
89    /* parse version string */
90    ver = atoi(p);
91    if (ver != 1) {
92       mtx_unlock(&mutex);
93       return;
94    }
95    p += strlen(p) + 1;
96 
97    while (*p) {
98       const struct mapi_stub *stub;
99 
100       stub = get_stub(p, NULL);
101       /* out of dynamic entries */
102       if (!stub)
103          break;
104       p += strlen(p) + 1;
105 
106       while (*p) {
107          get_stub(p, stub);
108          p += strlen(p) + 1;
109       }
110 
111       mapi_stub_map[count++] = stub;
112       p++;
113    }
114 
115    mapi_num_stubs = count;
116 
117    mtx_unlock(&mutex);
118 }
119 
120 /**
121  * Return the address of an entry.  Optionally generate the entry if it does
122  * not exist.
123  */
124 mapi_proc
mapi_get_proc_address(const char * name)125 mapi_get_proc_address(const char *name)
126 {
127    const struct mapi_stub *stub;
128 
129    stub = stub_find_public(name);
130    if (!stub)
131       stub = stub_find_dynamic(name, 0);
132 
133    return (stub) ? (mapi_proc) stub_get_addr(stub) : NULL;
134 }
135 
136 /**
137  * Create a dispatch table.
138  */
139 struct mapi_table *
mapi_table_create(void)140 mapi_table_create(void)
141 {
142    const struct mapi_table *noop = table_get_noop();
143    struct mapi_table *tbl;
144 
145    tbl = malloc(MAPI_TABLE_SIZE);
146    if (tbl)
147       memcpy(tbl, noop, MAPI_TABLE_SIZE);
148 
149    return tbl;
150 }
151 
152 /**
153  * Destroy a dispatch table.
154  */
155 void
mapi_table_destroy(struct mapi_table * tbl)156 mapi_table_destroy(struct mapi_table *tbl)
157 {
158    free(tbl);
159 }
160 
161 /**
162  * Fill a dispatch table.  The order of the procs is determined when mapi_init
163  * is called.
164  */
165 void
mapi_table_fill(struct mapi_table * tbl,const mapi_proc * procs)166 mapi_table_fill(struct mapi_table *tbl, const mapi_proc *procs)
167 {
168    const struct mapi_table *noop = table_get_noop();
169    int i;
170 
171    for (i = 0; i < mapi_num_stubs; i++) {
172       const struct mapi_stub *stub = mapi_stub_map[i];
173       int slot = stub_get_slot(stub);
174       mapi_func func = (mapi_func) procs[i];
175 
176       if (!func)
177          func = table_get_func(noop, slot);
178       table_set_func(tbl, slot, func);
179    }
180 }
181 
182 /**
183  * Make a dispatch table current.
184  */
185 void
mapi_table_make_current(const struct mapi_table * tbl)186 mapi_table_make_current(const struct mapi_table *tbl)
187 {
188    u_current_set_table(tbl);
189 }
190