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