implement NV_vdpau_interop v7
[mesa.git] / src / mapi / mapi.c
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 "u_thread.h"
33 #include "mapi.h"
34 #include "stub.h"
35 #include "table.h"
36
37 /* dynamic stubs will run out before this array */
38 static const struct mapi_stub *mapi_stub_map[MAPI_TABLE_NUM_SLOTS];
39 static int mapi_num_stubs;
40
41 static const struct mapi_stub *
42 get_stub(const char *name, const struct mapi_stub *alias)
43 {
44 const struct mapi_stub *stub;
45
46 stub = stub_find_public(name);
47 if (!stub) {
48 struct mapi_stub *dyn = stub_find_dynamic(name, 1);
49 if (dyn) {
50 stub_fix_dynamic(dyn, alias);
51 stub = dyn;
52 }
53 }
54
55 return stub;
56 }
57
58 /**
59 * Initialize mapi. spec consists of NULL-separated strings. The first string
60 * denotes the version. It is followed by variable numbers of entries. Each
61 * entry can have multiple names. An empty name terminates an entry. An empty
62 * entry terminates the spec. A spec of two entries, Foo and Bar, is as
63 * follows
64 *
65 * "1\0"
66 * "Foo\0"
67 * "FooEXT\0"
68 * "\0"
69 * "Bar\0"
70 * "\0"
71 */
72 void
73 mapi_init(const char *spec)
74 {
75 u_mutex_declare_static(mutex);
76 const char *p;
77 int ver, count;
78
79 u_mutex_lock(mutex);
80
81 /* already initialized */
82 if (mapi_num_stubs) {
83 u_mutex_unlock(mutex);
84 return;
85 }
86
87 count = 0;
88 p = spec;
89
90 /* parse version string */
91 ver = atoi(p);
92 if (ver != 1) {
93 u_mutex_unlock(mutex);
94 return;
95 }
96 p += strlen(p) + 1;
97
98 while (*p) {
99 const struct mapi_stub *stub;
100
101 stub = get_stub(p, NULL);
102 /* out of dynamic entries */
103 if (!stub)
104 break;
105 p += strlen(p) + 1;
106
107 while (*p) {
108 get_stub(p, stub);
109 p += strlen(p) + 1;
110 }
111
112 mapi_stub_map[count++] = stub;
113 p++;
114 }
115
116 mapi_num_stubs = count;
117
118 u_mutex_unlock(mutex);
119 }
120
121 /**
122 * Return the address of an entry. Optionally generate the entry if it does
123 * not exist.
124 */
125 mapi_proc
126 mapi_get_proc_address(const char *name)
127 {
128 const struct mapi_stub *stub;
129
130 stub = stub_find_public(name);
131 if (!stub)
132 stub = stub_find_dynamic(name, 0);
133
134 return (stub) ? (mapi_proc) stub_get_addr(stub) : NULL;
135 }
136
137 /**
138 * Create a dispatch table.
139 */
140 struct mapi_table *
141 mapi_table_create(void)
142 {
143 const struct mapi_table *noop = table_get_noop();
144 struct mapi_table *tbl;
145
146 tbl = malloc(MAPI_TABLE_SIZE);
147 if (tbl)
148 memcpy(tbl, noop, MAPI_TABLE_SIZE);
149
150 return tbl;
151 }
152
153 /**
154 * Destroy a dispatch table.
155 */
156 void
157 mapi_table_destroy(struct mapi_table *tbl)
158 {
159 free(tbl);
160 }
161
162 /**
163 * Fill a dispatch table. The order of the procs is determined when mapi_init
164 * is called.
165 */
166 void
167 mapi_table_fill(struct mapi_table *tbl, const mapi_proc *procs)
168 {
169 const struct mapi_table *noop = table_get_noop();
170 int i;
171
172 for (i = 0; i < mapi_num_stubs; i++) {
173 const struct mapi_stub *stub = mapi_stub_map[i];
174 int slot = stub_get_slot(stub);
175 mapi_func func = (mapi_func) procs[i];
176
177 if (!func)
178 func = table_get_func(noop, slot);
179 table_set_func(tbl, slot, func);
180 }
181 }
182
183 /**
184 * Make a dispatch table current.
185 */
186 void
187 mapi_table_make_current(const struct mapi_table *tbl)
188 {
189 u_current_set(tbl);
190 }