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