1848b8605Smrg/* 2848b8605Smrg * Mesa 3-D graphics library 3848b8605Smrg * 4848b8605Smrg * Copyright (C) 1999-2008 Brian Paul All Rights Reserved. 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 17848b8605Smrg * OR 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 20848b8605Smrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21848b8605Smrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22848b8605Smrg * OTHER DEALINGS IN THE SOFTWARE. 23848b8605Smrg */ 24848b8605Smrg 25848b8605Smrg/** 26848b8605Smrg * \file glapi_getproc.c 27848b8605Smrg * 28848b8605Smrg * Code for implementing glXGetProcAddress(), etc. 29848b8605Smrg * This was originally in glapi.c but refactored out. 30848b8605Smrg */ 31848b8605Smrg 32848b8605Smrg 33b8e80941Smrg#include <assert.h> 34b8e80941Smrg#include <string.h> 35b8e80941Smrg#include <stdlib.h> 36848b8605Smrg#include "glapi/glapi_priv.h" 37b8e80941Smrg#include "glapitable.h" 38848b8605Smrg 39848b8605Smrg 40848b8605Smrg#define FIRST_DYNAMIC_OFFSET (sizeof(struct _glapi_table) / sizeof(void *)) 41848b8605Smrg 42848b8605Smrg 43b8e80941Smrg 44848b8605Smrg/********************************************************************** 45848b8605Smrg * Static function management. 46848b8605Smrg */ 47848b8605Smrg 48848b8605Smrg 49848b8605Smrg#if !defined(DISPATCH_FUNCTION_SIZE) 50848b8605Smrg# define NEED_FUNCTION_POINTER 51848b8605Smrg#endif 52b8e80941Smrg#include "glprocs.h" 53848b8605Smrg 54848b8605Smrg 55848b8605Smrg/** 56848b8605Smrg * Search the table of static entrypoint functions for the named function 57848b8605Smrg * and return the corresponding glprocs_table_t entry. 58848b8605Smrg */ 59848b8605Smrgstatic const glprocs_table_t * 60848b8605Smrgget_static_proc( const char * n ) 61848b8605Smrg{ 62848b8605Smrg GLuint i; 63848b8605Smrg for (i = 0; static_functions[i].Name_offset >= 0; i++) { 64848b8605Smrg const char *testName = gl_string_table + static_functions[i].Name_offset; 65848b8605Smrg if (strcmp(testName, n) == 0) 66848b8605Smrg { 67848b8605Smrg return &static_functions[i]; 68848b8605Smrg } 69848b8605Smrg } 70848b8605Smrg return NULL; 71848b8605Smrg} 72848b8605Smrg 73848b8605Smrg 74848b8605Smrg/** 75848b8605Smrg * Return dispatch table offset of the named static (built-in) function. 76848b8605Smrg * Return -1 if function not found. 77848b8605Smrg */ 78848b8605Smrgstatic GLint 79848b8605Smrgget_static_proc_offset(const char *funcName) 80848b8605Smrg{ 81848b8605Smrg const glprocs_table_t * const f = get_static_proc( funcName ); 82848b8605Smrg if (f == NULL) { 83848b8605Smrg return -1; 84848b8605Smrg } 85848b8605Smrg 86848b8605Smrg return f->Offset; 87848b8605Smrg} 88848b8605Smrg 89848b8605Smrg 90848b8605Smrg 91848b8605Smrg/** 92848b8605Smrg * Return dispatch function address for the named static (built-in) function. 93848b8605Smrg * Return NULL if function not found. 94848b8605Smrg */ 95848b8605Smrgstatic _glapi_proc 96848b8605Smrgget_static_proc_address(const char *funcName) 97848b8605Smrg{ 98848b8605Smrg const glprocs_table_t * const f = get_static_proc( funcName ); 99848b8605Smrg if (f == NULL) { 100848b8605Smrg return NULL; 101848b8605Smrg } 102848b8605Smrg 103848b8605Smrg#if defined(DISPATCH_FUNCTION_SIZE) && defined(GLX_INDIRECT_RENDERING) 104848b8605Smrg return (f->Address == NULL) 105848b8605Smrg ? get_entrypoint_address(f->Offset) 106848b8605Smrg : f->Address; 107848b8605Smrg#elif defined(DISPATCH_FUNCTION_SIZE) 108848b8605Smrg return get_entrypoint_address(f->Offset); 109848b8605Smrg#else 110848b8605Smrg return f->Address; 111848b8605Smrg#endif 112848b8605Smrg} 113848b8605Smrg 114848b8605Smrg 115848b8605Smrg 116848b8605Smrg/** 117848b8605Smrg * Return the name of the function at the given offset in the dispatch 118848b8605Smrg * table. For debugging only. 119848b8605Smrg */ 120848b8605Smrgstatic const char * 121848b8605Smrgget_static_proc_name( GLuint offset ) 122848b8605Smrg{ 123848b8605Smrg GLuint i; 124848b8605Smrg for (i = 0; static_functions[i].Name_offset >= 0; i++) { 125848b8605Smrg if (static_functions[i].Offset == offset) { 126848b8605Smrg return gl_string_table + static_functions[i].Name_offset; 127848b8605Smrg } 128848b8605Smrg } 129848b8605Smrg return NULL; 130848b8605Smrg} 131848b8605Smrg 132848b8605Smrg 133848b8605Smrg 134848b8605Smrg/********************************************************************** 135848b8605Smrg * Extension function management. 136848b8605Smrg */ 137848b8605Smrg 138848b8605Smrg 139848b8605Smrg/** 140848b8605Smrg * Track information about a function added to the GL API. 141848b8605Smrg */ 142848b8605Smrgstruct _glapi_function { 143848b8605Smrg /** 144848b8605Smrg * Name of the function. 145848b8605Smrg */ 146848b8605Smrg const char * name; 147848b8605Smrg 148848b8605Smrg 149848b8605Smrg /** 150848b8605Smrg * Text string that describes the types of the parameters passed to the 151848b8605Smrg * named function. Parameter types are converted to characters using the 152848b8605Smrg * following rules: 153848b8605Smrg * - 'i' for \c GLint, \c GLuint, and \c GLenum 154848b8605Smrg * - 'p' for any pointer type 155848b8605Smrg * - 'f' for \c GLfloat and \c GLclampf 156848b8605Smrg * - 'd' for \c GLdouble and \c GLclampd 157848b8605Smrg */ 158848b8605Smrg const char * parameter_signature; 159848b8605Smrg 160848b8605Smrg 161848b8605Smrg /** 162848b8605Smrg * Offset in the dispatch table where the pointer to the real function is 163848b8605Smrg * located. If the driver has not requested that the named function be 164848b8605Smrg * added to the dispatch table, this will have the value ~0. 165848b8605Smrg */ 166848b8605Smrg unsigned dispatch_offset; 167848b8605Smrg 168848b8605Smrg 169848b8605Smrg /** 170848b8605Smrg * Pointer to the dispatch stub for the named function. 171848b8605Smrg * 172848b8605Smrg * \todo 173848b8605Smrg * The semantic of this field should be changed slightly. Currently, it 174848b8605Smrg * is always expected to be non-\c NULL. However, it would be better to 175848b8605Smrg * only allocate the entry-point stub when the application requests the 176848b8605Smrg * function via \c glXGetProcAddress. This would save memory for all the 177848b8605Smrg * functions that the driver exports but that the application never wants 178848b8605Smrg * to call. 179848b8605Smrg */ 180848b8605Smrg _glapi_proc dispatch_stub; 181848b8605Smrg}; 182848b8605Smrg 183848b8605Smrg 184848b8605Smrgstatic struct _glapi_function ExtEntryTable[MAX_EXTENSION_FUNCS]; 185848b8605Smrgstatic GLuint NumExtEntryPoints = 0; 186848b8605Smrg 187848b8605Smrg 188848b8605Smrgstatic struct _glapi_function * 189848b8605Smrgget_extension_proc(const char *funcName) 190848b8605Smrg{ 191848b8605Smrg GLuint i; 192848b8605Smrg for (i = 0; i < NumExtEntryPoints; i++) { 193848b8605Smrg if (strcmp(ExtEntryTable[i].name, funcName) == 0) { 194848b8605Smrg return & ExtEntryTable[i]; 195848b8605Smrg } 196848b8605Smrg } 197848b8605Smrg return NULL; 198848b8605Smrg} 199848b8605Smrg 200848b8605Smrg 201848b8605Smrgstatic GLint 202848b8605Smrgget_extension_proc_offset(const char *funcName) 203848b8605Smrg{ 204848b8605Smrg const struct _glapi_function * const f = get_extension_proc( funcName ); 205848b8605Smrg if (f == NULL) { 206848b8605Smrg return -1; 207848b8605Smrg } 208848b8605Smrg 209848b8605Smrg return f->dispatch_offset; 210848b8605Smrg} 211848b8605Smrg 212848b8605Smrg 213848b8605Smrgstatic _glapi_proc 214848b8605Smrgget_extension_proc_address(const char *funcName) 215848b8605Smrg{ 216848b8605Smrg const struct _glapi_function * const f = get_extension_proc( funcName ); 217848b8605Smrg if (f == NULL) { 218848b8605Smrg return NULL; 219848b8605Smrg } 220848b8605Smrg 221848b8605Smrg return f->dispatch_stub; 222848b8605Smrg} 223848b8605Smrg 224848b8605Smrg 225848b8605Smrgstatic const char * 226848b8605Smrgget_extension_proc_name(GLuint offset) 227848b8605Smrg{ 228848b8605Smrg GLuint i; 229848b8605Smrg for (i = 0; i < NumExtEntryPoints; i++) { 230848b8605Smrg if (ExtEntryTable[i].dispatch_offset == offset) { 231848b8605Smrg return ExtEntryTable[i].name; 232848b8605Smrg } 233848b8605Smrg } 234848b8605Smrg return NULL; 235848b8605Smrg} 236848b8605Smrg 237848b8605Smrg 238848b8605Smrg/** 239848b8605Smrg * strdup() is actually not a standard ANSI C or POSIX routine. 240848b8605Smrg * Irix will not define it if ANSI mode is in effect. 241848b8605Smrg */ 242848b8605Smrgstatic char * 243848b8605Smrgstr_dup(const char *str) 244848b8605Smrg{ 245848b8605Smrg char *copy; 246848b8605Smrg copy = malloc(strlen(str) + 1); 247848b8605Smrg if (!copy) 248848b8605Smrg return NULL; 249848b8605Smrg strcpy(copy, str); 250848b8605Smrg return copy; 251848b8605Smrg} 252848b8605Smrg 253848b8605Smrg 254848b8605Smrg/** 255848b8605Smrg * Generate new entrypoint 256848b8605Smrg * 257848b8605Smrg * Use a temporary dispatch offset of ~0 (i.e. -1). Later, when the driver 258848b8605Smrg * calls \c _glapi_add_dispatch we'll put in the proper offset. If that 259848b8605Smrg * never happens, and the user calls this function, he'll segfault. That's 260848b8605Smrg * what you get when you try calling a GL function that doesn't really exist. 261848b8605Smrg * 262848b8605Smrg * \param funcName Name of the function to create an entry-point for. 263848b8605Smrg * 264848b8605Smrg * \sa _glapi_add_entrypoint 265848b8605Smrg */ 266848b8605Smrg 267848b8605Smrgstatic struct _glapi_function * 268848b8605Smrgadd_function_name( const char * funcName ) 269848b8605Smrg{ 270848b8605Smrg struct _glapi_function * entry = NULL; 271848b8605Smrg _glapi_proc entrypoint = NULL; 272848b8605Smrg char * name_dup = NULL; 273848b8605Smrg 274848b8605Smrg if (NumExtEntryPoints >= MAX_EXTENSION_FUNCS) 275848b8605Smrg return NULL; 276848b8605Smrg 277848b8605Smrg if (funcName == NULL) 278848b8605Smrg return NULL; 279848b8605Smrg 280848b8605Smrg name_dup = str_dup(funcName); 281848b8605Smrg if (name_dup == NULL) 282848b8605Smrg return NULL; 283848b8605Smrg 284848b8605Smrg entrypoint = generate_entrypoint(~0); 285848b8605Smrg 286848b8605Smrg if (entrypoint == NULL) { 287848b8605Smrg free(name_dup); 288848b8605Smrg return NULL; 289848b8605Smrg } 290848b8605Smrg 291848b8605Smrg entry = & ExtEntryTable[NumExtEntryPoints]; 292848b8605Smrg NumExtEntryPoints++; 293848b8605Smrg 294848b8605Smrg entry->name = name_dup; 295848b8605Smrg entry->parameter_signature = NULL; 296848b8605Smrg entry->dispatch_offset = ~0; 297848b8605Smrg entry->dispatch_stub = entrypoint; 298848b8605Smrg 299848b8605Smrg return entry; 300848b8605Smrg} 301848b8605Smrg 302848b8605Smrg 303848b8605Smrgstatic struct _glapi_function * 304848b8605Smrgset_entry_info( struct _glapi_function * entry, const char * signature, unsigned offset ) 305848b8605Smrg{ 306848b8605Smrg char * sig_dup = NULL; 307848b8605Smrg 308848b8605Smrg if (signature == NULL) 309848b8605Smrg return NULL; 310848b8605Smrg 311848b8605Smrg sig_dup = str_dup(signature); 312848b8605Smrg if (sig_dup == NULL) 313848b8605Smrg return NULL; 314848b8605Smrg 315848b8605Smrg fill_in_entrypoint_offset(entry->dispatch_stub, offset); 316848b8605Smrg 317848b8605Smrg entry->parameter_signature = sig_dup; 318848b8605Smrg entry->dispatch_offset = offset; 319848b8605Smrg 320848b8605Smrg return entry; 321848b8605Smrg} 322848b8605Smrg 323848b8605Smrg 324848b8605Smrg/** 325848b8605Smrg * Fill-in the dispatch stub for the named function. 326848b8605Smrg * 327848b8605Smrg * This function is intended to be called by a hardware driver. When called, 328b8e80941Smrg * a dispatch stub may be created for the function. A pointer to this 329848b8605Smrg * dispatch function will be returned by glXGetProcAddress. 330848b8605Smrg * 331848b8605Smrg * \param function_names Array of pointers to function names that should 332848b8605Smrg * share a common dispatch offset. 333848b8605Smrg * \param parameter_signature String representing the types of the parameters 334848b8605Smrg * passed to the named function. Parameter types 335848b8605Smrg * are converted to characters using the following 336848b8605Smrg * rules: 337848b8605Smrg * - 'i' for \c GLint, \c GLuint, and \c GLenum 338848b8605Smrg * - 'p' for any pointer type 339848b8605Smrg * - 'f' for \c GLfloat and \c GLclampf 340848b8605Smrg * - 'd' for \c GLdouble and \c GLclampd 341848b8605Smrg * 342848b8605Smrg * \returns 343848b8605Smrg * The offset in the dispatch table of the named function. A pointer to the 344848b8605Smrg * driver's implementation of the named function should be stored at 345848b8605Smrg * \c dispatch_table[\c offset]. Return -1 if error/problem. 346848b8605Smrg * 347848b8605Smrg * \sa glXGetProcAddress 348848b8605Smrg * 349848b8605Smrg * \warning 350848b8605Smrg * This function can only handle up to 8 names at a time. As far as I know, 351848b8605Smrg * the maximum number of names ever associated with an existing GL function is 352848b8605Smrg * 4 (\c glPointParameterfSGIS, \c glPointParameterfEXT, 353848b8605Smrg * \c glPointParameterfARB, and \c glPointParameterf), so this should not be 354848b8605Smrg * too painful of a limitation. 355848b8605Smrg * 356848b8605Smrg * \todo 357848b8605Smrg * Determine whether or not \c parameter_signature should be allowed to be 358848b8605Smrg * \c NULL. It doesn't seem like much of a hardship for drivers to have to 359848b8605Smrg * pass in an empty string. 360848b8605Smrg * 361848b8605Smrg * \todo 362848b8605Smrg * Determine if code should be added to reject function names that start with 363848b8605Smrg * 'glX'. 364848b8605Smrg * 365848b8605Smrg * \bug 366848b8605Smrg * Add code to compare \c parameter_signature with the parameter signature of 367848b8605Smrg * a static function. In order to do that, we need to find a way to \b get 368848b8605Smrg * the parameter signature of a static function. 369848b8605Smrg */ 370848b8605Smrg 371848b8605Smrgint 372848b8605Smrg_glapi_add_dispatch( const char * const * function_names, 373848b8605Smrg const char * parameter_signature ) 374848b8605Smrg{ 375848b8605Smrg static int next_dynamic_offset = FIRST_DYNAMIC_OFFSET; 376848b8605Smrg const char * const real_sig = (parameter_signature != NULL) 377848b8605Smrg ? parameter_signature : ""; 378848b8605Smrg struct _glapi_function * entry[8]; 379848b8605Smrg GLboolean is_static[8]; 380848b8605Smrg unsigned i; 381848b8605Smrg int offset = ~0; 382848b8605Smrg 383848b8605Smrg init_glapi_relocs_once(); 384848b8605Smrg 385848b8605Smrg (void) memset( is_static, 0, sizeof( is_static ) ); 386848b8605Smrg (void) memset( entry, 0, sizeof( entry ) ); 387848b8605Smrg 388848b8605Smrg /* Find the _single_ dispatch offset for all function names that already 389848b8605Smrg * exist (and have a dispatch offset). 390848b8605Smrg */ 391848b8605Smrg 392848b8605Smrg for ( i = 0 ; function_names[i] != NULL ; i++ ) { 393848b8605Smrg const char * funcName = function_names[i]; 394848b8605Smrg int static_offset; 395848b8605Smrg int extension_offset; 396848b8605Smrg 397848b8605Smrg if (funcName[0] != 'g' || funcName[1] != 'l') 398848b8605Smrg return -1; 399848b8605Smrg 400848b8605Smrg /* search built-in functions */ 401848b8605Smrg static_offset = get_static_proc_offset(funcName); 402848b8605Smrg 403848b8605Smrg if (static_offset >= 0) { 404848b8605Smrg 405848b8605Smrg is_static[i] = GL_TRUE; 406848b8605Smrg 407848b8605Smrg /* FIXME: Make sure the parameter signatures match! How do we get 408848b8605Smrg * FIXME: the parameter signature for static functions? 409848b8605Smrg */ 410848b8605Smrg 411848b8605Smrg if ( (offset != ~0) && (static_offset != offset) ) { 412848b8605Smrg return -1; 413848b8605Smrg } 414848b8605Smrg 415848b8605Smrg offset = static_offset; 416848b8605Smrg 417848b8605Smrg continue; 418848b8605Smrg } 419848b8605Smrg 420848b8605Smrg /* search added extension functions */ 421848b8605Smrg entry[i] = get_extension_proc(funcName); 422848b8605Smrg 423848b8605Smrg if (entry[i] != NULL) { 424848b8605Smrg extension_offset = entry[i]->dispatch_offset; 425848b8605Smrg 426848b8605Smrg /* The offset may be ~0 if the function name was added by 427848b8605Smrg * glXGetProcAddress but never filled in by the driver. 428848b8605Smrg */ 429848b8605Smrg 430848b8605Smrg if (extension_offset == ~0) { 431848b8605Smrg continue; 432848b8605Smrg } 433848b8605Smrg 434848b8605Smrg if (strcmp(real_sig, entry[i]->parameter_signature) != 0) { 435848b8605Smrg return -1; 436848b8605Smrg } 437848b8605Smrg 438848b8605Smrg if ( (offset != ~0) && (extension_offset != offset) ) { 439848b8605Smrg return -1; 440848b8605Smrg } 441848b8605Smrg 442848b8605Smrg offset = extension_offset; 443848b8605Smrg } 444848b8605Smrg } 445848b8605Smrg 446848b8605Smrg /* If all function names are either new (or with no dispatch offset), 447848b8605Smrg * allocate a new dispatch offset. 448848b8605Smrg */ 449848b8605Smrg 450848b8605Smrg if (offset == ~0) { 451848b8605Smrg offset = next_dynamic_offset; 452848b8605Smrg next_dynamic_offset++; 453848b8605Smrg } 454848b8605Smrg 455848b8605Smrg /* Fill in the dispatch offset for the new function names (and those with 456848b8605Smrg * no dispatch offset). 457848b8605Smrg */ 458848b8605Smrg 459848b8605Smrg for ( i = 0 ; function_names[i] != NULL ; i++ ) { 460848b8605Smrg if (is_static[i]) { 461848b8605Smrg continue; 462848b8605Smrg } 463848b8605Smrg 464848b8605Smrg /* generate entrypoints for new function names */ 465848b8605Smrg if (entry[i] == NULL) { 466848b8605Smrg entry[i] = add_function_name( function_names[i] ); 467848b8605Smrg if (entry[i] == NULL) { 468848b8605Smrg /* FIXME: Possible memory leak here. */ 469848b8605Smrg return -1; 470848b8605Smrg } 471848b8605Smrg } 472848b8605Smrg 473848b8605Smrg if (entry[i]->dispatch_offset == ~0) { 474848b8605Smrg set_entry_info( entry[i], real_sig, offset ); 475848b8605Smrg } 476848b8605Smrg } 477848b8605Smrg 478848b8605Smrg return offset; 479848b8605Smrg} 480848b8605Smrg 481848b8605Smrg 482848b8605Smrg/** 483848b8605Smrg * Return offset of entrypoint for named function within dispatch table. 484848b8605Smrg */ 485848b8605SmrgGLint 486848b8605Smrg_glapi_get_proc_offset(const char *funcName) 487848b8605Smrg{ 488848b8605Smrg GLint offset; 489848b8605Smrg 490848b8605Smrg /* search extension functions first */ 491848b8605Smrg offset = get_extension_proc_offset(funcName); 492848b8605Smrg if (offset >= 0) 493848b8605Smrg return offset; 494848b8605Smrg 495848b8605Smrg /* search static functions */ 496848b8605Smrg return get_static_proc_offset(funcName); 497848b8605Smrg} 498848b8605Smrg 499848b8605Smrg 500848b8605Smrg 501848b8605Smrg/** 502848b8605Smrg * Return pointer to the named function. If the function name isn't found 503848b8605Smrg * in the name of static functions, try generating a new API entrypoint on 504848b8605Smrg * the fly with assembly language. 505848b8605Smrg */ 506848b8605Smrg_glapi_proc 507848b8605Smrg_glapi_get_proc_address(const char *funcName) 508848b8605Smrg{ 509848b8605Smrg _glapi_proc func; 510848b8605Smrg struct _glapi_function * entry; 511848b8605Smrg 512848b8605Smrg init_glapi_relocs_once(); 513848b8605Smrg 514b8e80941Smrg#ifdef USE_MGL_NAMESPACE 515b8e80941Smrg if (funcName && funcName[0] == 'm') 516b8e80941Smrg funcName++; 517848b8605Smrg#endif 518848b8605Smrg 519b8e80941Smrg if (!funcName || funcName[0] != 'g' || funcName[1] != 'l') 520b8e80941Smrg return NULL; 521b8e80941Smrg 522848b8605Smrg /* search extension functions first */ 523848b8605Smrg func = get_extension_proc_address(funcName); 524848b8605Smrg if (func) 525848b8605Smrg return func; 526848b8605Smrg 527848b8605Smrg /* search static functions */ 528848b8605Smrg func = get_static_proc_address(funcName); 529848b8605Smrg if (func) 530848b8605Smrg return func; 531848b8605Smrg 532848b8605Smrg /* generate entrypoint, dispatch offset must be filled in by the driver */ 533848b8605Smrg entry = add_function_name(funcName); 534848b8605Smrg if (entry == NULL) 535848b8605Smrg return NULL; 536848b8605Smrg 537848b8605Smrg return entry->dispatch_stub; 538848b8605Smrg} 539848b8605Smrg 540848b8605Smrg 541848b8605Smrg 542848b8605Smrg/** 543848b8605Smrg * Return the name of the function at the given dispatch offset. 544848b8605Smrg * This is only intended for debugging. 545848b8605Smrg */ 546848b8605Smrgconst char * 547848b8605Smrg_glapi_get_proc_name(GLuint offset) 548848b8605Smrg{ 549848b8605Smrg const char * n; 550848b8605Smrg 551848b8605Smrg /* search built-in functions */ 552848b8605Smrg n = get_static_proc_name(offset); 553848b8605Smrg if ( n != NULL ) { 554848b8605Smrg return n; 555848b8605Smrg } 556848b8605Smrg 557848b8605Smrg /* search added extension functions */ 558848b8605Smrg return get_extension_proc_name(offset); 559848b8605Smrg} 560848b8605Smrg 561848b8605Smrg 562848b8605Smrg 563848b8605Smrg/********************************************************************** 564848b8605Smrg * GL API table functions. 565848b8605Smrg */ 566848b8605Smrg 567848b8605Smrg 568848b8605Smrg/** 569848b8605Smrg * Return size of dispatch table struct as number of functions (or 570848b8605Smrg * slots). 571848b8605Smrg */ 572848b8605SmrgGLuint 573848b8605Smrg_glapi_get_dispatch_table_size(void) 574848b8605Smrg{ 575848b8605Smrg /* 576848b8605Smrg * The dispatch table size (number of entries) is the size of the 577848b8605Smrg * _glapi_table struct plus the number of dynamic entries we can add. 578848b8605Smrg * The extra slots can be filled in by DRI drivers that register new 579848b8605Smrg * extension functions. 580848b8605Smrg */ 581848b8605Smrg return FIRST_DYNAMIC_OFFSET + MAX_EXTENSION_FUNCS; 582848b8605Smrg} 583