aboutsummaryrefslogtreecommitdiff
path: root/mesalib/src/mesa/main/remap.c
blob: 44ec964989db9c5075107177439d2f8bff2550b3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
/*
 * Mesa 3-D graphics library
 * Version:  7.7
 *
 * Copyright (C) 2009 Chia-I Wu <olv@0xlab.org>
 *
 * 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.
 */


/**
 * \file remap.c
 * Remap table management.
 *
 * Entries in the dispatch table are either static or dynamic.  The
 * dispatch table is shared by mesa core and glapi.  When they are
 * built separately, it is possible that a static entry in mesa core
 * is dynamic, or assigned a different static offset, in glapi.  The
 * remap table is in charge of mapping a static entry in mesa core to
 * a dynamic entry, or the corresponding static entry, in glapi.
 */

#include "remap.h"
#include "imports.h"
#include "glapi/glapi.h"

#define MAX_ENTRY_POINTS 16

#define need_MESA_remap_table
#include "main/remap_helper.h"


/* this is global for quick access */
int driDispatchRemapTable[driDispatchRemapTable_size];


/**
 * Return the spec string associated with the given function index.
 * The index is available from including remap_helper.h.
 *
 * \param func_index an opaque function index.
 *
 * \return the spec string associated with the function index, or NULL.
 */
const char *
_mesa_get_function_spec(GLint func_index)
{
   if (func_index < Elements(_mesa_function_pool))
      return _mesa_function_pool + func_index;
   else
      return NULL;
}


/**
 * Map a function by its spec.  The function will be added to glapi,
 * and the dispatch offset will be returned.
 *
 * \param spec a '\0'-separated string array specifying a function.
 *        It begins with the parameter signature of the function,
 *        followed by the names of the entry points.  An empty entry
 *        point name terminates the array.
 *
 * \return the offset of the (re-)mapped function in the dispatch
 *         table, or -1.
 */
GLint
_mesa_map_function_spec(const char *spec)
{
   const char *signature;
   const char *names[MAX_ENTRY_POINTS + 1];
   GLint num_names = 0;

   if (!spec)
      return -1;

   signature = spec;
   spec += strlen(spec) + 1;

   /* spec is terminated by an empty string */
   while (*spec) {
      names[num_names] = spec;
      num_names++;
      if (num_names >= MAX_ENTRY_POINTS)
         break;
      spec += strlen(spec) + 1;
   }
   if (!num_names)
      return -1;

   names[num_names] = NULL;

   /* add the entry points to the dispatch table */
   return _glapi_add_dispatch(names, signature);
}


/**
 * Map an array of functions.  This is a convenient function for
 * use with arrays available from including remap_helper.h.
 *
 * Note that the dispatch offsets of the functions are not returned.
 * If they are needed, _mesa_map_function_spec() should be used.
 *
 * \param func_array an array of function remaps.
 */
void
_mesa_map_function_array(const struct gl_function_remap *func_array)
{
   GLint i;

   if (!func_array)
      return;

   for (i = 0; func_array[i].func_index != -1; i++) {
      const char *spec;
      GLint offset;

      spec = _mesa_get_function_spec(func_array[i].func_index);
      if (!spec) {
         _mesa_problem(NULL, "invalid function index %d",
                       func_array[i].func_index);
         continue;
      }

      offset = _mesa_map_function_spec(spec);
      /* error checks */
      if (offset < 0) {
         const char *name = spec + strlen(spec) + 1;
         _mesa_warning(NULL, "failed to remap %s", name);
      }
      else if (func_array[i].dispatch_offset >= 0 &&
               offset != func_array[i].dispatch_offset) {
         const char *name = spec + strlen(spec) + 1;
         _mesa_problem(NULL, "%s should be mapped to %d, not %d",
                       name, func_array[i].dispatch_offset, offset);
      }
   }
}


/**
 * Map the functions which are already static.
 *
 * When a extension function are incorporated into the ABI, the
 * extension suffix is usually stripped.  Mapping such functions
 * makes sure the alternative names are available.
 *
 * Note that functions mapped by _mesa_init_remap_table() are
 * excluded.
 */
void
_mesa_map_static_functions(void)
{
   /* Remap static functions which have alternative names and are in the ABI.
    * This is to be on the safe side.  glapi should have defined those names.
    */
   _mesa_map_function_array(MESA_alt_functions);
}


/**
 * Initialize the remap table.  This is called in one_time_init().
 * The remap table needs to be initialized before calling the
 * CALL/GET/SET macros defined in main/dispatch.h.
 */
static void
_mesa_do_init_remap_table(const char *pool,
			  int size,
			  const struct gl_function_pool_remap *remap)
{
   static GLboolean initialized = GL_FALSE;
   GLint i;

   if (initialized)
      return;
   initialized = GL_TRUE;

   /* initialize the remap table */
   for (i = 0; i < size; i++) {
      GLint offset;
      const char *spec;

      /* sanity check */
      ASSERT(i == remap[i].remap_index);
      spec = _mesa_function_pool + remap[i].pool_index;

      offset = _mesa_map_function_spec(spec);
      /* store the dispatch offset in the remap table */
      driDispatchRemapTable[i] = offset;
      if (offset < 0) {
         const char *name = spec + strlen(spec) + 1;
         _mesa_warning(NULL, "failed to remap %s", name);
      }
   }
}


void
_mesa_init_remap_table(void)
{
   _mesa_do_init_remap_table(_mesa_function_pool,
			     driDispatchRemapTable_size,
			     MESA_remap_table_functions);
}