remap.c revision 848b8605
1848b8605Smrg/*
2848b8605Smrg * Mesa 3-D graphics library
3848b8605Smrg *
4848b8605Smrg * Copyright (C) 2009 Chia-I Wu <olv@0xlab.org>
5848b8605Smrg *
6848b8605Smrg * Permission is hereby granted, free of charge, to any person obtaining a
7848b8605Smrg * copy of this software and associated documentation files (the "Software"),
8848b8605Smrg * to deal in the Software without restriction, including without limitation
9848b8605Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10848b8605Smrg * and/or sell copies of the Software, and to permit persons to whom the
11848b8605Smrg * Software is furnished to do so, subject to the following conditions:
12848b8605Smrg *
13848b8605Smrg * The above copyright notice and this permission notice shall be included
14848b8605Smrg * in all copies or substantial portions of the Software.
15848b8605Smrg *
16848b8605Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17848b8605Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18848b8605Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19848b8605Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20848b8605Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21848b8605Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22848b8605Smrg * DEALINGS IN THE SOFTWARE.
23848b8605Smrg */
24848b8605Smrg
25848b8605Smrg
26848b8605Smrg/**
27848b8605Smrg * \file remap.c
28848b8605Smrg * Remap table management.
29848b8605Smrg *
30848b8605Smrg * Entries in the dispatch table are either static or dynamic.  The
31848b8605Smrg * dispatch table is shared by mesa core and glapi.  When they are
32848b8605Smrg * built separately, it is possible that a static entry in mesa core
33848b8605Smrg * is dynamic, or assigned a different static offset, in glapi.  The
34848b8605Smrg * remap table is in charge of mapping a static entry in mesa core to
35848b8605Smrg * a dynamic entry, or the corresponding static entry, in glapi.
36848b8605Smrg */
37848b8605Smrg
38848b8605Smrg#include "remap.h"
39848b8605Smrg#include "imports.h"
40848b8605Smrg#include "glapi/glapi.h"
41848b8605Smrg
42848b8605Smrg#define MAX_ENTRY_POINTS 16
43848b8605Smrg
44848b8605Smrg#define need_MESA_remap_table
45848b8605Smrg#include "main/remap_helper.h"
46848b8605Smrg
47848b8605Smrg
48848b8605Smrg/* this is global for quick access */
49848b8605Smrgint driDispatchRemapTable[driDispatchRemapTable_size];
50848b8605Smrg
51848b8605Smrg
52848b8605Smrg/**
53848b8605Smrg * Return the spec string associated with the given function index.
54848b8605Smrg * The index is available from including remap_helper.h.
55848b8605Smrg *
56848b8605Smrg * \param func_index an opaque function index.
57848b8605Smrg *
58848b8605Smrg * \return the spec string associated with the function index, or NULL.
59848b8605Smrg */
60848b8605Smrgconst char *
61848b8605Smrg_mesa_get_function_spec(GLint func_index)
62848b8605Smrg{
63848b8605Smrg   if (func_index < Elements(_mesa_function_pool))
64848b8605Smrg      return _mesa_function_pool + func_index;
65848b8605Smrg   else
66848b8605Smrg      return NULL;
67848b8605Smrg}
68848b8605Smrg
69848b8605Smrg
70848b8605Smrg/**
71848b8605Smrg * Map a function by its spec.  The function will be added to glapi,
72848b8605Smrg * and the dispatch offset will be returned.
73848b8605Smrg *
74848b8605Smrg * \param spec a '\0'-separated string array specifying a function.
75848b8605Smrg *        It begins with the parameter signature of the function,
76848b8605Smrg *        followed by the names of the entry points.  An empty entry
77848b8605Smrg *        point name terminates the array.
78848b8605Smrg *
79848b8605Smrg * \return the offset of the (re-)mapped function in the dispatch
80848b8605Smrg *         table, or -1.
81848b8605Smrg */
82848b8605SmrgGLint
83848b8605Smrg_mesa_map_function_spec(const char *spec)
84848b8605Smrg{
85848b8605Smrg   const char *signature;
86848b8605Smrg   const char *names[MAX_ENTRY_POINTS + 1];
87848b8605Smrg   GLint num_names = 0;
88848b8605Smrg
89848b8605Smrg   if (!spec)
90848b8605Smrg      return -1;
91848b8605Smrg
92848b8605Smrg   signature = spec;
93848b8605Smrg   spec += strlen(spec) + 1;
94848b8605Smrg
95848b8605Smrg   /* spec is terminated by an empty string */
96848b8605Smrg   while (*spec) {
97848b8605Smrg      names[num_names] = spec;
98848b8605Smrg      num_names++;
99848b8605Smrg      if (num_names >= MAX_ENTRY_POINTS)
100848b8605Smrg         break;
101848b8605Smrg      spec += strlen(spec) + 1;
102848b8605Smrg   }
103848b8605Smrg   if (!num_names)
104848b8605Smrg      return -1;
105848b8605Smrg
106848b8605Smrg   names[num_names] = NULL;
107848b8605Smrg
108848b8605Smrg   /* add the entry points to the dispatch table */
109848b8605Smrg   return _glapi_add_dispatch(names, signature);
110848b8605Smrg}
111848b8605Smrg
112848b8605Smrg
113848b8605Smrg/**
114848b8605Smrg * Map an array of functions.  This is a convenient function for
115848b8605Smrg * use with arrays available from including remap_helper.h.
116848b8605Smrg *
117848b8605Smrg * Note that the dispatch offsets of the functions are not returned.
118848b8605Smrg * If they are needed, _mesa_map_function_spec() should be used.
119848b8605Smrg *
120848b8605Smrg * \param func_array an array of function remaps.
121848b8605Smrg */
122848b8605Smrgvoid
123848b8605Smrg_mesa_map_function_array(const struct gl_function_remap *func_array)
124848b8605Smrg{
125848b8605Smrg   GLint i;
126848b8605Smrg
127848b8605Smrg   if (!func_array)
128848b8605Smrg      return;
129848b8605Smrg
130848b8605Smrg   for (i = 0; func_array[i].func_index != -1; i++) {
131848b8605Smrg      const char *spec;
132848b8605Smrg      GLint offset;
133848b8605Smrg
134848b8605Smrg      spec = _mesa_get_function_spec(func_array[i].func_index);
135848b8605Smrg      if (!spec) {
136848b8605Smrg         _mesa_problem(NULL, "invalid function index %d",
137848b8605Smrg                       func_array[i].func_index);
138848b8605Smrg         continue;
139848b8605Smrg      }
140848b8605Smrg
141848b8605Smrg      offset = _mesa_map_function_spec(spec);
142848b8605Smrg      /* error checks */
143848b8605Smrg      if (offset < 0) {
144848b8605Smrg         const char *name = spec + strlen(spec) + 1;
145848b8605Smrg         _mesa_warning(NULL, "failed to remap %s", name);
146848b8605Smrg      }
147848b8605Smrg      else if (func_array[i].dispatch_offset >= 0 &&
148848b8605Smrg               offset != func_array[i].dispatch_offset) {
149848b8605Smrg         const char *name = spec + strlen(spec) + 1;
150848b8605Smrg         _mesa_problem(NULL, "%s should be mapped to %d, not %d",
151848b8605Smrg                       name, func_array[i].dispatch_offset, offset);
152848b8605Smrg      }
153848b8605Smrg   }
154848b8605Smrg}
155848b8605Smrg
156848b8605Smrg
157848b8605Smrg/**
158848b8605Smrg * Map the functions which are already static.
159848b8605Smrg *
160848b8605Smrg * When a extension function are incorporated into the ABI, the
161848b8605Smrg * extension suffix is usually stripped.  Mapping such functions
162848b8605Smrg * makes sure the alternative names are available.
163848b8605Smrg *
164848b8605Smrg * Note that functions mapped by _mesa_init_remap_table() are
165848b8605Smrg * excluded.
166848b8605Smrg */
167848b8605Smrgvoid
168848b8605Smrg_mesa_map_static_functions(void)
169848b8605Smrg{
170848b8605Smrg   /* Remap static functions which have alternative names and are in the ABI.
171848b8605Smrg    * This is to be on the safe side.  glapi should have defined those names.
172848b8605Smrg    */
173848b8605Smrg   _mesa_map_function_array(MESA_alt_functions);
174848b8605Smrg}
175848b8605Smrg
176848b8605Smrg
177848b8605Smrg/**
178848b8605Smrg * Initialize the remap table.  This is called in one_time_init().
179848b8605Smrg * The remap table needs to be initialized before calling the
180848b8605Smrg * CALL/GET/SET macros defined in main/dispatch.h.
181848b8605Smrg */
182848b8605Smrgstatic void
183848b8605Smrg_mesa_do_init_remap_table(const char *pool,
184848b8605Smrg			  int size,
185848b8605Smrg			  const struct gl_function_pool_remap *remap)
186848b8605Smrg{
187848b8605Smrg   static GLboolean initialized = GL_FALSE;
188848b8605Smrg   GLint i;
189848b8605Smrg
190848b8605Smrg   if (initialized)
191848b8605Smrg      return;
192848b8605Smrg   initialized = GL_TRUE;
193848b8605Smrg
194848b8605Smrg   /* initialize the remap table */
195848b8605Smrg   for (i = 0; i < size; i++) {
196848b8605Smrg      GLint offset;
197848b8605Smrg      const char *spec;
198848b8605Smrg
199848b8605Smrg      /* sanity check */
200848b8605Smrg      ASSERT(i == remap[i].remap_index);
201848b8605Smrg      spec = _mesa_function_pool + remap[i].pool_index;
202848b8605Smrg
203848b8605Smrg      offset = _mesa_map_function_spec(spec);
204848b8605Smrg      /* store the dispatch offset in the remap table */
205848b8605Smrg      driDispatchRemapTable[i] = offset;
206848b8605Smrg      if (offset < 0) {
207848b8605Smrg         const char *name = spec + strlen(spec) + 1;
208848b8605Smrg         _mesa_warning(NULL, "failed to remap %s", name);
209848b8605Smrg      }
210848b8605Smrg   }
211848b8605Smrg}
212848b8605Smrg
213848b8605Smrg
214848b8605Smrgvoid
215848b8605Smrg_mesa_init_remap_table(void)
216848b8605Smrg{
217848b8605Smrg   _mesa_do_init_remap_table(_mesa_function_pool,
218848b8605Smrg			     driDispatchRemapTable_size,
219848b8605Smrg			     MESA_remap_table_functions);
220848b8605Smrg}
221