remap.c revision 848b8605
1/* 2 * Mesa 3-D graphics library 3 * 4 * Copyright (C) 2009 Chia-I Wu <olv@0xlab.org> 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 25 26/** 27 * \file remap.c 28 * Remap table management. 29 * 30 * Entries in the dispatch table are either static or dynamic. The 31 * dispatch table is shared by mesa core and glapi. When they are 32 * built separately, it is possible that a static entry in mesa core 33 * is dynamic, or assigned a different static offset, in glapi. The 34 * remap table is in charge of mapping a static entry in mesa core to 35 * a dynamic entry, or the corresponding static entry, in glapi. 36 */ 37 38#include "remap.h" 39#include "imports.h" 40#include "glapi/glapi.h" 41 42#define MAX_ENTRY_POINTS 16 43 44#define need_MESA_remap_table 45#include "main/remap_helper.h" 46 47 48/* this is global for quick access */ 49int driDispatchRemapTable[driDispatchRemapTable_size]; 50 51 52/** 53 * Return the spec string associated with the given function index. 54 * The index is available from including remap_helper.h. 55 * 56 * \param func_index an opaque function index. 57 * 58 * \return the spec string associated with the function index, or NULL. 59 */ 60const char * 61_mesa_get_function_spec(GLint func_index) 62{ 63 if (func_index < Elements(_mesa_function_pool)) 64 return _mesa_function_pool + func_index; 65 else 66 return NULL; 67} 68 69 70/** 71 * Map a function by its spec. The function will be added to glapi, 72 * and the dispatch offset will be returned. 73 * 74 * \param spec a '\0'-separated string array specifying a function. 75 * It begins with the parameter signature of the function, 76 * followed by the names of the entry points. An empty entry 77 * point name terminates the array. 78 * 79 * \return the offset of the (re-)mapped function in the dispatch 80 * table, or -1. 81 */ 82GLint 83_mesa_map_function_spec(const char *spec) 84{ 85 const char *signature; 86 const char *names[MAX_ENTRY_POINTS + 1]; 87 GLint num_names = 0; 88 89 if (!spec) 90 return -1; 91 92 signature = spec; 93 spec += strlen(spec) + 1; 94 95 /* spec is terminated by an empty string */ 96 while (*spec) { 97 names[num_names] = spec; 98 num_names++; 99 if (num_names >= MAX_ENTRY_POINTS) 100 break; 101 spec += strlen(spec) + 1; 102 } 103 if (!num_names) 104 return -1; 105 106 names[num_names] = NULL; 107 108 /* add the entry points to the dispatch table */ 109 return _glapi_add_dispatch(names, signature); 110} 111 112 113/** 114 * Map an array of functions. This is a convenient function for 115 * use with arrays available from including remap_helper.h. 116 * 117 * Note that the dispatch offsets of the functions are not returned. 118 * If they are needed, _mesa_map_function_spec() should be used. 119 * 120 * \param func_array an array of function remaps. 121 */ 122void 123_mesa_map_function_array(const struct gl_function_remap *func_array) 124{ 125 GLint i; 126 127 if (!func_array) 128 return; 129 130 for (i = 0; func_array[i].func_index != -1; i++) { 131 const char *spec; 132 GLint offset; 133 134 spec = _mesa_get_function_spec(func_array[i].func_index); 135 if (!spec) { 136 _mesa_problem(NULL, "invalid function index %d", 137 func_array[i].func_index); 138 continue; 139 } 140 141 offset = _mesa_map_function_spec(spec); 142 /* error checks */ 143 if (offset < 0) { 144 const char *name = spec + strlen(spec) + 1; 145 _mesa_warning(NULL, "failed to remap %s", name); 146 } 147 else if (func_array[i].dispatch_offset >= 0 && 148 offset != func_array[i].dispatch_offset) { 149 const char *name = spec + strlen(spec) + 1; 150 _mesa_problem(NULL, "%s should be mapped to %d, not %d", 151 name, func_array[i].dispatch_offset, offset); 152 } 153 } 154} 155 156 157/** 158 * Map the functions which are already static. 159 * 160 * When a extension function are incorporated into the ABI, the 161 * extension suffix is usually stripped. Mapping such functions 162 * makes sure the alternative names are available. 163 * 164 * Note that functions mapped by _mesa_init_remap_table() are 165 * excluded. 166 */ 167void 168_mesa_map_static_functions(void) 169{ 170 /* Remap static functions which have alternative names and are in the ABI. 171 * This is to be on the safe side. glapi should have defined those names. 172 */ 173 _mesa_map_function_array(MESA_alt_functions); 174} 175 176 177/** 178 * Initialize the remap table. This is called in one_time_init(). 179 * The remap table needs to be initialized before calling the 180 * CALL/GET/SET macros defined in main/dispatch.h. 181 */ 182static void 183_mesa_do_init_remap_table(const char *pool, 184 int size, 185 const struct gl_function_pool_remap *remap) 186{ 187 static GLboolean initialized = GL_FALSE; 188 GLint i; 189 190 if (initialized) 191 return; 192 initialized = GL_TRUE; 193 194 /* initialize the remap table */ 195 for (i = 0; i < size; i++) { 196 GLint offset; 197 const char *spec; 198 199 /* sanity check */ 200 ASSERT(i == remap[i].remap_index); 201 spec = _mesa_function_pool + remap[i].pool_index; 202 203 offset = _mesa_map_function_spec(spec); 204 /* store the dispatch offset in the remap table */ 205 driDispatchRemapTable[i] = offset; 206 if (offset < 0) { 207 const char *name = spec + strlen(spec) + 1; 208 _mesa_warning(NULL, "failed to remap %s", name); 209 } 210 } 211} 212 213 214void 215_mesa_init_remap_table(void) 216{ 217 _mesa_do_init_remap_table(_mesa_function_pool, 218 driDispatchRemapTable_size, 219 MESA_remap_table_functions); 220} 221