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