1 /* 2 * Mesa 3-D graphics library 3 * 4 * Copyright (C) 1999-2008 Brian Paul All Rights Reserved. 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 (at) lunarg.com> 27 */ 28 29 #include <string.h> 30 #include <stdlib.h> 31 #include "glapi/glapi.h" 32 #include "u_current.h" 33 #include "table.h" /* for MAPI_TABLE_NUM_SLOTS */ 34 #include "stub.h" 35 36 /* 37 * Global variables, _glapi_get_context, and _glapi_get_dispatch are defined in 38 * u_current.c. 39 */ 40 41 #ifdef GLX_USE_TLS 42 /* not used, but defined for compatibility */ 43 const struct _glapi_table *_glapi_Dispatch; 44 const void *_glapi_Context; 45 #endif /* GLX_USE_TLS */ 46 47 void 48 _glapi_destroy_multithread(void) 49 { 50 u_current_destroy(); 51 } 52 53 void 54 _glapi_check_multithread(void) 55 { 56 u_current_init(); 57 } 58 59 void 60 _glapi_set_context(void *context) 61 { 62 u_current_set_context((const void *) context); 63 } 64 65 void 66 _glapi_set_dispatch(struct _glapi_table *dispatch) 67 { 68 u_current_set_table((const struct mapi_table *) dispatch); 69 } 70 71 /** 72 * Return size of dispatch table struct as number of functions (or 73 * slots). 74 */ 75 unsigned int 76 _glapi_get_dispatch_table_size(void) 77 { 78 return MAPI_TABLE_NUM_SLOTS; 79 } 80 81 /** 82 * Fill-in the dispatch stub for the named function. 83 * 84 * This function is intended to be called by a hardware driver. When called, 85 * a dispatch stub may be created created for the function. A pointer to this 86 * dispatch function will be returned by glXGetProcAddress. 87 * 88 * \param function_names Array of pointers to function names that should 89 * share a common dispatch offset. 90 * \param parameter_signature String representing the types of the parameters 91 * passed to the named function. Parameter types 92 * are converted to characters using the following 93 * rules: 94 * - 'i' for \c GLint, \c GLuint, and \c GLenum 95 * - 'p' for any pointer type 96 * - 'f' for \c GLfloat and \c GLclampf 97 * - 'd' for \c GLdouble and \c GLclampd 98 * 99 * \returns 100 * The offset in the dispatch table of the named function. A pointer to the 101 * driver's implementation of the named function should be stored at 102 * \c dispatch_table[\c offset]. Return -1 if error/problem. 103 * 104 * \sa glXGetProcAddress 105 * 106 * \warning 107 * This function can only handle up to 8 names at a time. As far as I know, 108 * the maximum number of names ever associated with an existing GL function is 109 * 4 (\c glPointParameterfSGIS, \c glPointParameterfEXT, 110 * \c glPointParameterfARB, and \c glPointParameterf), so this should not be 111 * too painful of a limitation. 112 * 113 * \todo 114 * Check parameter_signature. 115 */ 116 int 117 _glapi_add_dispatch( const char * const * function_names, 118 const char * parameter_signature ) 119 { 120 const struct mapi_stub *function_stubs[8]; 121 const struct mapi_stub *alias = NULL; 122 unsigned i; 123 124 (void) memset(function_stubs, 0, sizeof(function_stubs)); 125 126 /* find the missing stubs, and decide the alias */ 127 for (i = 0; function_names[i] != NULL && i < 8; i++) { 128 const char * funcName = function_names[i]; 129 const struct mapi_stub *stub; 130 int slot; 131 132 if (!funcName || funcName[0] != 'g' || funcName[1] != 'l') 133 return -1; 134 funcName += 2; 135 136 stub = stub_find_public(funcName); 137 if (!stub) 138 stub = stub_find_dynamic(funcName, 0); 139 140 slot = (stub) ? stub_get_slot(stub) : -1; 141 if (slot >= 0) { 142 if (alias && stub_get_slot(alias) != slot) 143 return -1; 144 /* use the first existing stub as the alias */ 145 if (!alias) 146 alias = stub; 147 148 function_stubs[i] = stub; 149 } 150 } 151 152 /* generate missing stubs */ 153 for (i = 0; function_names[i] != NULL && i < 8; i++) { 154 const char * funcName = function_names[i] + 2; 155 struct mapi_stub *stub; 156 157 if (function_stubs[i]) 158 continue; 159 160 stub = stub_find_dynamic(funcName, 1); 161 if (!stub) 162 return -1; 163 164 stub_fix_dynamic(stub, alias); 165 if (!alias) 166 alias = stub; 167 } 168 169 return (alias) ? stub_get_slot(alias) : -1; 170 } 171 172 static const struct mapi_stub * 173 _glapi_get_stub(const char *name, int generate) 174 { 175 const struct mapi_stub *stub; 176 177 #ifdef USE_MGL_NAMESPACE 178 if (name && name[0] == 'm') 179 name++; 180 #endif 181 182 if (!name || name[0] != 'g' || name[1] != 'l') 183 return NULL; 184 name += 2; 185 186 stub = stub_find_public(name); 187 if (!stub) 188 stub = stub_find_dynamic(name, generate); 189 190 return stub; 191 } 192 193 /** 194 * Return offset of entrypoint for named function within dispatch table. 195 */ 196 int 197 _glapi_get_proc_offset(const char *funcName) 198 { 199 const struct mapi_stub *stub = _glapi_get_stub(funcName, 0); 200 return (stub) ? stub_get_slot(stub) : -1; 201 } 202 203 /** 204 * Return pointer to the named function. If the function name isn't found 205 * in the name of static functions, try generating a new API entrypoint on 206 * the fly with assembly language. 207 */ 208 _glapi_proc 209 _glapi_get_proc_address(const char *funcName) 210 { 211 const struct mapi_stub *stub = _glapi_get_stub(funcName, 1); 212 return (stub) ? (_glapi_proc) stub_get_addr(stub) : NULL; 213 } 214 215 /** 216 * Return the name of the function at the given dispatch offset. 217 * This is only intended for debugging. 218 */ 219 const char * 220 _glapi_get_proc_name(unsigned int offset) 221 { 222 const struct mapi_stub *stub = stub_find_by_slot(offset); 223 return stub ? stub_get_name(stub) : NULL; 224 } 225 226 /** Return pointer to new dispatch table filled with no-op functions */ 227 struct _glapi_table * 228 _glapi_new_nop_table(unsigned num_entries) 229 { 230 struct _glapi_table *table; 231 232 if (num_entries > MAPI_TABLE_NUM_SLOTS) 233 num_entries = MAPI_TABLE_NUM_SLOTS; 234 235 table = malloc(num_entries * sizeof(mapi_func)); 236 if (table) { 237 memcpy(table, table_noop_array, num_entries * sizeof(mapi_func)); 238 } 239 return table; 240 } 241 242 void 243 _glapi_set_nop_handler(_glapi_nop_handler_proc func) 244 { 245 table_set_noop_handler(func); 246 } 247 248 /** 249 * This is a deprecated function which should not be used anymore. 250 * It's only present to satisfy linking with older versions of libGL. 251 */ 252 unsigned long 253 _glthread_GetID(void) 254 { 255 return 0; 256 } 257 258 void 259 _glapi_noop_enable_warnings(unsigned char enable) 260 { 261 } 262 263 void 264 _glapi_set_warning_func(_glapi_proc func) 265 { 266 } 267