13464ebd5Sriastradh/* 23464ebd5Sriastradh * Mesa 3-D graphics library 33464ebd5Sriastradh * 43464ebd5Sriastradh * Copyright (C) 1999-2008 Brian Paul All Rights Reserved. 53464ebd5Sriastradh * 63464ebd5Sriastradh * Permission is hereby granted, free of charge, to any person obtaining a 73464ebd5Sriastradh * copy of this software and associated documentation files (the "Software"), 83464ebd5Sriastradh * to deal in the Software without restriction, including without limitation 93464ebd5Sriastradh * the rights to use, copy, modify, merge, publish, distribute, sublicense, 103464ebd5Sriastradh * and/or sell copies of the Software, and to permit persons to whom the 113464ebd5Sriastradh * Software is furnished to do so, subject to the following conditions: 123464ebd5Sriastradh * 133464ebd5Sriastradh * The above copyright notice and this permission notice shall be included 143464ebd5Sriastradh * in all copies or substantial portions of the Software. 153464ebd5Sriastradh * 163464ebd5Sriastradh * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 173464ebd5Sriastradh * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 183464ebd5Sriastradh * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19af69d88dSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20af69d88dSmrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21af69d88dSmrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22af69d88dSmrg * OTHER DEALINGS IN THE SOFTWARE. 233464ebd5Sriastradh */ 243464ebd5Sriastradh 253464ebd5Sriastradh/** 263464ebd5Sriastradh * \file glapi_getproc.c 273464ebd5Sriastradh * 283464ebd5Sriastradh * Code for implementing glXGetProcAddress(), etc. 293464ebd5Sriastradh * This was originally in glapi.c but refactored out. 303464ebd5Sriastradh */ 313464ebd5Sriastradh 323464ebd5Sriastradh 3301e04c3fSmrg#include <assert.h> 3401e04c3fSmrg#include <string.h> 3501e04c3fSmrg#include <stdlib.h> 363464ebd5Sriastradh#include "glapi/glapi_priv.h" 3701e04c3fSmrg#include "glapitable.h" 383464ebd5Sriastradh 393464ebd5Sriastradh 403464ebd5Sriastradh#define FIRST_DYNAMIC_OFFSET (sizeof(struct _glapi_table) / sizeof(void *)) 413464ebd5Sriastradh 423464ebd5Sriastradh 4301e04c3fSmrg 443464ebd5Sriastradh/********************************************************************** 453464ebd5Sriastradh * Static function management. 463464ebd5Sriastradh */ 473464ebd5Sriastradh 483464ebd5Sriastradh 493464ebd5Sriastradh#if !defined(DISPATCH_FUNCTION_SIZE) 503464ebd5Sriastradh# define NEED_FUNCTION_POINTER 513464ebd5Sriastradh#endif 5201e04c3fSmrg#include "glprocs.h" 533464ebd5Sriastradh 543464ebd5Sriastradh 553464ebd5Sriastradh/** 563464ebd5Sriastradh * Search the table of static entrypoint functions for the named function 573464ebd5Sriastradh * and return the corresponding glprocs_table_t entry. 583464ebd5Sriastradh */ 593464ebd5Sriastradhstatic const glprocs_table_t * 603464ebd5Sriastradhget_static_proc( const char * n ) 613464ebd5Sriastradh{ 623464ebd5Sriastradh GLuint i; 633464ebd5Sriastradh for (i = 0; static_functions[i].Name_offset >= 0; i++) { 643464ebd5Sriastradh const char *testName = gl_string_table + static_functions[i].Name_offset; 653464ebd5Sriastradh if (strcmp(testName, n) == 0) 663464ebd5Sriastradh { 673464ebd5Sriastradh return &static_functions[i]; 683464ebd5Sriastradh } 693464ebd5Sriastradh } 703464ebd5Sriastradh return NULL; 713464ebd5Sriastradh} 723464ebd5Sriastradh 733464ebd5Sriastradh 743464ebd5Sriastradh/** 753464ebd5Sriastradh * Return dispatch table offset of the named static (built-in) function. 763464ebd5Sriastradh * Return -1 if function not found. 773464ebd5Sriastradh */ 783464ebd5Sriastradhstatic GLint 793464ebd5Sriastradhget_static_proc_offset(const char *funcName) 803464ebd5Sriastradh{ 813464ebd5Sriastradh const glprocs_table_t * const f = get_static_proc( funcName ); 823464ebd5Sriastradh if (f == NULL) { 833464ebd5Sriastradh return -1; 843464ebd5Sriastradh } 853464ebd5Sriastradh 863464ebd5Sriastradh return f->Offset; 873464ebd5Sriastradh} 883464ebd5Sriastradh 893464ebd5Sriastradh 903464ebd5Sriastradh 913464ebd5Sriastradh/** 923464ebd5Sriastradh * Return dispatch function address for the named static (built-in) function. 933464ebd5Sriastradh * Return NULL if function not found. 943464ebd5Sriastradh */ 953464ebd5Sriastradhstatic _glapi_proc 963464ebd5Sriastradhget_static_proc_address(const char *funcName) 973464ebd5Sriastradh{ 983464ebd5Sriastradh const glprocs_table_t * const f = get_static_proc( funcName ); 993464ebd5Sriastradh if (f == NULL) { 1003464ebd5Sriastradh return NULL; 1013464ebd5Sriastradh } 1023464ebd5Sriastradh 1033464ebd5Sriastradh#if defined(DISPATCH_FUNCTION_SIZE) && defined(GLX_INDIRECT_RENDERING) 1043464ebd5Sriastradh return (f->Address == NULL) 1053464ebd5Sriastradh ? get_entrypoint_address(f->Offset) 1063464ebd5Sriastradh : f->Address; 1073464ebd5Sriastradh#elif defined(DISPATCH_FUNCTION_SIZE) 1083464ebd5Sriastradh return get_entrypoint_address(f->Offset); 1093464ebd5Sriastradh#else 1103464ebd5Sriastradh return f->Address; 1113464ebd5Sriastradh#endif 1123464ebd5Sriastradh} 1133464ebd5Sriastradh 1143464ebd5Sriastradh 1153464ebd5Sriastradh 1163464ebd5Sriastradh/** 1173464ebd5Sriastradh * Return the name of the function at the given offset in the dispatch 1183464ebd5Sriastradh * table. For debugging only. 1193464ebd5Sriastradh */ 1203464ebd5Sriastradhstatic const char * 1213464ebd5Sriastradhget_static_proc_name( GLuint offset ) 1223464ebd5Sriastradh{ 1233464ebd5Sriastradh GLuint i; 1243464ebd5Sriastradh for (i = 0; static_functions[i].Name_offset >= 0; i++) { 1253464ebd5Sriastradh if (static_functions[i].Offset == offset) { 1263464ebd5Sriastradh return gl_string_table + static_functions[i].Name_offset; 1273464ebd5Sriastradh } 1283464ebd5Sriastradh } 1293464ebd5Sriastradh return NULL; 1303464ebd5Sriastradh} 1313464ebd5Sriastradh 1323464ebd5Sriastradh 1333464ebd5Sriastradh 1343464ebd5Sriastradh/********************************************************************** 1353464ebd5Sriastradh * Extension function management. 1363464ebd5Sriastradh */ 1373464ebd5Sriastradh 1383464ebd5Sriastradh 1393464ebd5Sriastradh/** 1403464ebd5Sriastradh * Track information about a function added to the GL API. 1413464ebd5Sriastradh */ 1423464ebd5Sriastradhstruct _glapi_function { 1433464ebd5Sriastradh /** 1443464ebd5Sriastradh * Name of the function. 1453464ebd5Sriastradh */ 1463464ebd5Sriastradh const char * name; 1473464ebd5Sriastradh 1483464ebd5Sriastradh 1493464ebd5Sriastradh /** 1503464ebd5Sriastradh * Text string that describes the types of the parameters passed to the 1513464ebd5Sriastradh * named function. Parameter types are converted to characters using the 1523464ebd5Sriastradh * following rules: 1533464ebd5Sriastradh * - 'i' for \c GLint, \c GLuint, and \c GLenum 1543464ebd5Sriastradh * - 'p' for any pointer type 1553464ebd5Sriastradh * - 'f' for \c GLfloat and \c GLclampf 1563464ebd5Sriastradh * - 'd' for \c GLdouble and \c GLclampd 1573464ebd5Sriastradh */ 1583464ebd5Sriastradh const char * parameter_signature; 1593464ebd5Sriastradh 1603464ebd5Sriastradh 1613464ebd5Sriastradh /** 1623464ebd5Sriastradh * Offset in the dispatch table where the pointer to the real function is 1633464ebd5Sriastradh * located. If the driver has not requested that the named function be 1643464ebd5Sriastradh * added to the dispatch table, this will have the value ~0. 1653464ebd5Sriastradh */ 1663464ebd5Sriastradh unsigned dispatch_offset; 1673464ebd5Sriastradh 1683464ebd5Sriastradh 1693464ebd5Sriastradh /** 1703464ebd5Sriastradh * Pointer to the dispatch stub for the named function. 1713464ebd5Sriastradh * 1723464ebd5Sriastradh * \todo 1733464ebd5Sriastradh * The semantic of this field should be changed slightly. Currently, it 1743464ebd5Sriastradh * is always expected to be non-\c NULL. However, it would be better to 1753464ebd5Sriastradh * only allocate the entry-point stub when the application requests the 1763464ebd5Sriastradh * function via \c glXGetProcAddress. This would save memory for all the 1773464ebd5Sriastradh * functions that the driver exports but that the application never wants 1783464ebd5Sriastradh * to call. 1793464ebd5Sriastradh */ 1803464ebd5Sriastradh _glapi_proc dispatch_stub; 1813464ebd5Sriastradh}; 1823464ebd5Sriastradh 1833464ebd5Sriastradh 1843464ebd5Sriastradhstatic struct _glapi_function ExtEntryTable[MAX_EXTENSION_FUNCS]; 1853464ebd5Sriastradhstatic GLuint NumExtEntryPoints = 0; 1863464ebd5Sriastradh 1873464ebd5Sriastradh 1883464ebd5Sriastradhstatic struct _glapi_function * 1893464ebd5Sriastradhget_extension_proc(const char *funcName) 1903464ebd5Sriastradh{ 1913464ebd5Sriastradh GLuint i; 1923464ebd5Sriastradh for (i = 0; i < NumExtEntryPoints; i++) { 1933464ebd5Sriastradh if (strcmp(ExtEntryTable[i].name, funcName) == 0) { 1943464ebd5Sriastradh return & ExtEntryTable[i]; 1953464ebd5Sriastradh } 1963464ebd5Sriastradh } 1973464ebd5Sriastradh return NULL; 1983464ebd5Sriastradh} 1993464ebd5Sriastradh 2003464ebd5Sriastradh 2013464ebd5Sriastradhstatic GLint 2023464ebd5Sriastradhget_extension_proc_offset(const char *funcName) 2033464ebd5Sriastradh{ 2043464ebd5Sriastradh const struct _glapi_function * const f = get_extension_proc( funcName ); 2053464ebd5Sriastradh if (f == NULL) { 2063464ebd5Sriastradh return -1; 2073464ebd5Sriastradh } 2083464ebd5Sriastradh 2093464ebd5Sriastradh return f->dispatch_offset; 2103464ebd5Sriastradh} 2113464ebd5Sriastradh 2123464ebd5Sriastradh 2133464ebd5Sriastradhstatic _glapi_proc 2143464ebd5Sriastradhget_extension_proc_address(const char *funcName) 2153464ebd5Sriastradh{ 2163464ebd5Sriastradh const struct _glapi_function * const f = get_extension_proc( funcName ); 2173464ebd5Sriastradh if (f == NULL) { 2183464ebd5Sriastradh return NULL; 2193464ebd5Sriastradh } 2203464ebd5Sriastradh 2213464ebd5Sriastradh return f->dispatch_stub; 2223464ebd5Sriastradh} 2233464ebd5Sriastradh 2243464ebd5Sriastradh 2253464ebd5Sriastradhstatic const char * 2263464ebd5Sriastradhget_extension_proc_name(GLuint offset) 2273464ebd5Sriastradh{ 2283464ebd5Sriastradh GLuint i; 2293464ebd5Sriastradh for (i = 0; i < NumExtEntryPoints; i++) { 2303464ebd5Sriastradh if (ExtEntryTable[i].dispatch_offset == offset) { 2313464ebd5Sriastradh return ExtEntryTable[i].name; 2323464ebd5Sriastradh } 2333464ebd5Sriastradh } 2343464ebd5Sriastradh return NULL; 2353464ebd5Sriastradh} 2363464ebd5Sriastradh 2373464ebd5Sriastradh 2383464ebd5Sriastradh/** 2393464ebd5Sriastradh * strdup() is actually not a standard ANSI C or POSIX routine. 2403464ebd5Sriastradh * Irix will not define it if ANSI mode is in effect. 2413464ebd5Sriastradh */ 2423464ebd5Sriastradhstatic char * 2433464ebd5Sriastradhstr_dup(const char *str) 2443464ebd5Sriastradh{ 2453464ebd5Sriastradh char *copy; 246af69d88dSmrg copy = malloc(strlen(str) + 1); 2473464ebd5Sriastradh if (!copy) 2483464ebd5Sriastradh return NULL; 2493464ebd5Sriastradh strcpy(copy, str); 2503464ebd5Sriastradh return copy; 2513464ebd5Sriastradh} 2523464ebd5Sriastradh 2533464ebd5Sriastradh 2543464ebd5Sriastradh/** 2553464ebd5Sriastradh * Generate new entrypoint 2563464ebd5Sriastradh * 2573464ebd5Sriastradh * Use a temporary dispatch offset of ~0 (i.e. -1). Later, when the driver 2583464ebd5Sriastradh * calls \c _glapi_add_dispatch we'll put in the proper offset. If that 2593464ebd5Sriastradh * never happens, and the user calls this function, he'll segfault. That's 2603464ebd5Sriastradh * what you get when you try calling a GL function that doesn't really exist. 2613464ebd5Sriastradh * 2623464ebd5Sriastradh * \param funcName Name of the function to create an entry-point for. 2633464ebd5Sriastradh * 2643464ebd5Sriastradh * \sa _glapi_add_entrypoint 2653464ebd5Sriastradh */ 2663464ebd5Sriastradh 2673464ebd5Sriastradhstatic struct _glapi_function * 2683464ebd5Sriastradhadd_function_name( const char * funcName ) 2693464ebd5Sriastradh{ 2703464ebd5Sriastradh struct _glapi_function * entry = NULL; 2713464ebd5Sriastradh _glapi_proc entrypoint = NULL; 2723464ebd5Sriastradh char * name_dup = NULL; 2733464ebd5Sriastradh 2743464ebd5Sriastradh if (NumExtEntryPoints >= MAX_EXTENSION_FUNCS) 2753464ebd5Sriastradh return NULL; 2763464ebd5Sriastradh 2773464ebd5Sriastradh if (funcName == NULL) 2783464ebd5Sriastradh return NULL; 2793464ebd5Sriastradh 2803464ebd5Sriastradh name_dup = str_dup(funcName); 2813464ebd5Sriastradh if (name_dup == NULL) 2823464ebd5Sriastradh return NULL; 2833464ebd5Sriastradh 2843464ebd5Sriastradh entrypoint = generate_entrypoint(~0); 2853464ebd5Sriastradh 2863464ebd5Sriastradh if (entrypoint == NULL) { 2873464ebd5Sriastradh free(name_dup); 2883464ebd5Sriastradh return NULL; 2893464ebd5Sriastradh } 2903464ebd5Sriastradh 2913464ebd5Sriastradh entry = & ExtEntryTable[NumExtEntryPoints]; 2923464ebd5Sriastradh NumExtEntryPoints++; 2933464ebd5Sriastradh 2943464ebd5Sriastradh entry->name = name_dup; 2953464ebd5Sriastradh entry->parameter_signature = NULL; 2963464ebd5Sriastradh entry->dispatch_offset = ~0; 2973464ebd5Sriastradh entry->dispatch_stub = entrypoint; 2983464ebd5Sriastradh 2993464ebd5Sriastradh return entry; 3003464ebd5Sriastradh} 3013464ebd5Sriastradh 3023464ebd5Sriastradh 3033464ebd5Sriastradhstatic struct _glapi_function * 3043464ebd5Sriastradhset_entry_info( struct _glapi_function * entry, const char * signature, unsigned offset ) 3053464ebd5Sriastradh{ 3063464ebd5Sriastradh char * sig_dup = NULL; 3073464ebd5Sriastradh 3083464ebd5Sriastradh if (signature == NULL) 3093464ebd5Sriastradh return NULL; 3103464ebd5Sriastradh 3113464ebd5Sriastradh sig_dup = str_dup(signature); 3123464ebd5Sriastradh if (sig_dup == NULL) 3133464ebd5Sriastradh return NULL; 3143464ebd5Sriastradh 3153464ebd5Sriastradh fill_in_entrypoint_offset(entry->dispatch_stub, offset); 3163464ebd5Sriastradh 3173464ebd5Sriastradh entry->parameter_signature = sig_dup; 3183464ebd5Sriastradh entry->dispatch_offset = offset; 3193464ebd5Sriastradh 3203464ebd5Sriastradh return entry; 3213464ebd5Sriastradh} 3223464ebd5Sriastradh 3233464ebd5Sriastradh 3243464ebd5Sriastradh/** 3253464ebd5Sriastradh * Fill-in the dispatch stub for the named function. 3263464ebd5Sriastradh * 3273464ebd5Sriastradh * This function is intended to be called by a hardware driver. When called, 32801e04c3fSmrg * a dispatch stub may be created for the function. A pointer to this 3293464ebd5Sriastradh * dispatch function will be returned by glXGetProcAddress. 3303464ebd5Sriastradh * 3313464ebd5Sriastradh * \param function_names Array of pointers to function names that should 3323464ebd5Sriastradh * share a common dispatch offset. 3333464ebd5Sriastradh * \param parameter_signature String representing the types of the parameters 3343464ebd5Sriastradh * passed to the named function. Parameter types 3353464ebd5Sriastradh * are converted to characters using the following 3363464ebd5Sriastradh * rules: 3373464ebd5Sriastradh * - 'i' for \c GLint, \c GLuint, and \c GLenum 3383464ebd5Sriastradh * - 'p' for any pointer type 3393464ebd5Sriastradh * - 'f' for \c GLfloat and \c GLclampf 3403464ebd5Sriastradh * - 'd' for \c GLdouble and \c GLclampd 3413464ebd5Sriastradh * 3423464ebd5Sriastradh * \returns 3433464ebd5Sriastradh * The offset in the dispatch table of the named function. A pointer to the 3443464ebd5Sriastradh * driver's implementation of the named function should be stored at 3453464ebd5Sriastradh * \c dispatch_table[\c offset]. Return -1 if error/problem. 3463464ebd5Sriastradh * 3473464ebd5Sriastradh * \sa glXGetProcAddress 3483464ebd5Sriastradh * 3493464ebd5Sriastradh * \warning 3503464ebd5Sriastradh * This function can only handle up to 8 names at a time. As far as I know, 3513464ebd5Sriastradh * the maximum number of names ever associated with an existing GL function is 3523464ebd5Sriastradh * 4 (\c glPointParameterfSGIS, \c glPointParameterfEXT, 3533464ebd5Sriastradh * \c glPointParameterfARB, and \c glPointParameterf), so this should not be 3543464ebd5Sriastradh * too painful of a limitation. 3553464ebd5Sriastradh * 3563464ebd5Sriastradh * \todo 3573464ebd5Sriastradh * Determine whether or not \c parameter_signature should be allowed to be 3583464ebd5Sriastradh * \c NULL. It doesn't seem like much of a hardship for drivers to have to 3593464ebd5Sriastradh * pass in an empty string. 3603464ebd5Sriastradh * 3613464ebd5Sriastradh * \todo 3623464ebd5Sriastradh * Determine if code should be added to reject function names that start with 3633464ebd5Sriastradh * 'glX'. 3643464ebd5Sriastradh * 3653464ebd5Sriastradh * \bug 3663464ebd5Sriastradh * Add code to compare \c parameter_signature with the parameter signature of 3673464ebd5Sriastradh * a static function. In order to do that, we need to find a way to \b get 3683464ebd5Sriastradh * the parameter signature of a static function. 3693464ebd5Sriastradh */ 3703464ebd5Sriastradh 3713464ebd5Sriastradhint 3723464ebd5Sriastradh_glapi_add_dispatch( const char * const * function_names, 3733464ebd5Sriastradh const char * parameter_signature ) 3743464ebd5Sriastradh{ 3753464ebd5Sriastradh static int next_dynamic_offset = FIRST_DYNAMIC_OFFSET; 3763464ebd5Sriastradh const char * const real_sig = (parameter_signature != NULL) 3773464ebd5Sriastradh ? parameter_signature : ""; 3783464ebd5Sriastradh struct _glapi_function * entry[8]; 3793464ebd5Sriastradh GLboolean is_static[8]; 3803464ebd5Sriastradh unsigned i; 3813464ebd5Sriastradh int offset = ~0; 3823464ebd5Sriastradh 3833464ebd5Sriastradh init_glapi_relocs_once(); 3843464ebd5Sriastradh 3853464ebd5Sriastradh (void) memset( is_static, 0, sizeof( is_static ) ); 3863464ebd5Sriastradh (void) memset( entry, 0, sizeof( entry ) ); 3873464ebd5Sriastradh 3883464ebd5Sriastradh /* Find the _single_ dispatch offset for all function names that already 3893464ebd5Sriastradh * exist (and have a dispatch offset). 3903464ebd5Sriastradh */ 3913464ebd5Sriastradh 3923464ebd5Sriastradh for ( i = 0 ; function_names[i] != NULL ; i++ ) { 3933464ebd5Sriastradh const char * funcName = function_names[i]; 3943464ebd5Sriastradh int static_offset; 3953464ebd5Sriastradh int extension_offset; 3963464ebd5Sriastradh 3973464ebd5Sriastradh if (funcName[0] != 'g' || funcName[1] != 'l') 3983464ebd5Sriastradh return -1; 3993464ebd5Sriastradh 4003464ebd5Sriastradh /* search built-in functions */ 4013464ebd5Sriastradh static_offset = get_static_proc_offset(funcName); 4023464ebd5Sriastradh 4033464ebd5Sriastradh if (static_offset >= 0) { 4043464ebd5Sriastradh 4053464ebd5Sriastradh is_static[i] = GL_TRUE; 4063464ebd5Sriastradh 4073464ebd5Sriastradh /* FIXME: Make sure the parameter signatures match! How do we get 4083464ebd5Sriastradh * FIXME: the parameter signature for static functions? 4093464ebd5Sriastradh */ 4103464ebd5Sriastradh 4113464ebd5Sriastradh if ( (offset != ~0) && (static_offset != offset) ) { 4123464ebd5Sriastradh return -1; 4133464ebd5Sriastradh } 4143464ebd5Sriastradh 4153464ebd5Sriastradh offset = static_offset; 4163464ebd5Sriastradh 4173464ebd5Sriastradh continue; 4183464ebd5Sriastradh } 4193464ebd5Sriastradh 4203464ebd5Sriastradh /* search added extension functions */ 4213464ebd5Sriastradh entry[i] = get_extension_proc(funcName); 4223464ebd5Sriastradh 4233464ebd5Sriastradh if (entry[i] != NULL) { 4243464ebd5Sriastradh extension_offset = entry[i]->dispatch_offset; 4253464ebd5Sriastradh 4263464ebd5Sriastradh /* The offset may be ~0 if the function name was added by 4273464ebd5Sriastradh * glXGetProcAddress but never filled in by the driver. 4283464ebd5Sriastradh */ 4293464ebd5Sriastradh 4303464ebd5Sriastradh if (extension_offset == ~0) { 4313464ebd5Sriastradh continue; 4323464ebd5Sriastradh } 4333464ebd5Sriastradh 4343464ebd5Sriastradh if (strcmp(real_sig, entry[i]->parameter_signature) != 0) { 4353464ebd5Sriastradh return -1; 4363464ebd5Sriastradh } 4373464ebd5Sriastradh 4383464ebd5Sriastradh if ( (offset != ~0) && (extension_offset != offset) ) { 4393464ebd5Sriastradh return -1; 4403464ebd5Sriastradh } 4413464ebd5Sriastradh 4423464ebd5Sriastradh offset = extension_offset; 4433464ebd5Sriastradh } 4443464ebd5Sriastradh } 4453464ebd5Sriastradh 4463464ebd5Sriastradh /* If all function names are either new (or with no dispatch offset), 4473464ebd5Sriastradh * allocate a new dispatch offset. 4483464ebd5Sriastradh */ 4493464ebd5Sriastradh 4503464ebd5Sriastradh if (offset == ~0) { 4513464ebd5Sriastradh offset = next_dynamic_offset; 4523464ebd5Sriastradh next_dynamic_offset++; 4533464ebd5Sriastradh } 4543464ebd5Sriastradh 4553464ebd5Sriastradh /* Fill in the dispatch offset for the new function names (and those with 4563464ebd5Sriastradh * no dispatch offset). 4573464ebd5Sriastradh */ 4583464ebd5Sriastradh 4593464ebd5Sriastradh for ( i = 0 ; function_names[i] != NULL ; i++ ) { 4603464ebd5Sriastradh if (is_static[i]) { 4613464ebd5Sriastradh continue; 4623464ebd5Sriastradh } 4633464ebd5Sriastradh 4643464ebd5Sriastradh /* generate entrypoints for new function names */ 4653464ebd5Sriastradh if (entry[i] == NULL) { 4663464ebd5Sriastradh entry[i] = add_function_name( function_names[i] ); 4673464ebd5Sriastradh if (entry[i] == NULL) { 4683464ebd5Sriastradh /* FIXME: Possible memory leak here. */ 4693464ebd5Sriastradh return -1; 4703464ebd5Sriastradh } 4713464ebd5Sriastradh } 4723464ebd5Sriastradh 4733464ebd5Sriastradh if (entry[i]->dispatch_offset == ~0) { 4743464ebd5Sriastradh set_entry_info( entry[i], real_sig, offset ); 4753464ebd5Sriastradh } 4763464ebd5Sriastradh } 4773464ebd5Sriastradh 4783464ebd5Sriastradh return offset; 4793464ebd5Sriastradh} 4803464ebd5Sriastradh 4813464ebd5Sriastradh 4823464ebd5Sriastradh/** 4833464ebd5Sriastradh * Return offset of entrypoint for named function within dispatch table. 4843464ebd5Sriastradh */ 4853464ebd5SriastradhGLint 4863464ebd5Sriastradh_glapi_get_proc_offset(const char *funcName) 4873464ebd5Sriastradh{ 4883464ebd5Sriastradh GLint offset; 4893464ebd5Sriastradh 4903464ebd5Sriastradh /* search extension functions first */ 4913464ebd5Sriastradh offset = get_extension_proc_offset(funcName); 4923464ebd5Sriastradh if (offset >= 0) 4933464ebd5Sriastradh return offset; 4943464ebd5Sriastradh 4953464ebd5Sriastradh /* search static functions */ 4963464ebd5Sriastradh return get_static_proc_offset(funcName); 4973464ebd5Sriastradh} 4983464ebd5Sriastradh 4993464ebd5Sriastradh 5003464ebd5Sriastradh 5013464ebd5Sriastradh/** 5023464ebd5Sriastradh * Return pointer to the named function. If the function name isn't found 5033464ebd5Sriastradh * in the name of static functions, try generating a new API entrypoint on 5043464ebd5Sriastradh * the fly with assembly language. 5053464ebd5Sriastradh */ 5063464ebd5Sriastradh_glapi_proc 5073464ebd5Sriastradh_glapi_get_proc_address(const char *funcName) 5083464ebd5Sriastradh{ 5093464ebd5Sriastradh _glapi_proc func; 5103464ebd5Sriastradh struct _glapi_function * entry; 5113464ebd5Sriastradh 5123464ebd5Sriastradh init_glapi_relocs_once(); 5133464ebd5Sriastradh 51401e04c3fSmrg if (!funcName || funcName[0] != 'g' || funcName[1] != 'l') 51501e04c3fSmrg return NULL; 51601e04c3fSmrg 5173464ebd5Sriastradh /* search extension functions first */ 5183464ebd5Sriastradh func = get_extension_proc_address(funcName); 5193464ebd5Sriastradh if (func) 5203464ebd5Sriastradh return func; 5213464ebd5Sriastradh 5223464ebd5Sriastradh /* search static functions */ 5233464ebd5Sriastradh func = get_static_proc_address(funcName); 5243464ebd5Sriastradh if (func) 5253464ebd5Sriastradh return func; 5263464ebd5Sriastradh 5273464ebd5Sriastradh /* generate entrypoint, dispatch offset must be filled in by the driver */ 5283464ebd5Sriastradh entry = add_function_name(funcName); 5293464ebd5Sriastradh if (entry == NULL) 5303464ebd5Sriastradh return NULL; 5313464ebd5Sriastradh 5323464ebd5Sriastradh return entry->dispatch_stub; 5333464ebd5Sriastradh} 5343464ebd5Sriastradh 5353464ebd5Sriastradh 5363464ebd5Sriastradh 5373464ebd5Sriastradh/** 5383464ebd5Sriastradh * Return the name of the function at the given dispatch offset. 5393464ebd5Sriastradh * This is only intended for debugging. 5403464ebd5Sriastradh */ 5413464ebd5Sriastradhconst char * 5423464ebd5Sriastradh_glapi_get_proc_name(GLuint offset) 5433464ebd5Sriastradh{ 5443464ebd5Sriastradh const char * n; 5453464ebd5Sriastradh 5463464ebd5Sriastradh /* search built-in functions */ 5473464ebd5Sriastradh n = get_static_proc_name(offset); 5483464ebd5Sriastradh if ( n != NULL ) { 5493464ebd5Sriastradh return n; 5503464ebd5Sriastradh } 5513464ebd5Sriastradh 5523464ebd5Sriastradh /* search added extension functions */ 5533464ebd5Sriastradh return get_extension_proc_name(offset); 5543464ebd5Sriastradh} 5553464ebd5Sriastradh 5563464ebd5Sriastradh 5573464ebd5Sriastradh 5583464ebd5Sriastradh/********************************************************************** 5593464ebd5Sriastradh * GL API table functions. 5603464ebd5Sriastradh */ 5613464ebd5Sriastradh 5623464ebd5Sriastradh 5633464ebd5Sriastradh/** 5643464ebd5Sriastradh * Return size of dispatch table struct as number of functions (or 5653464ebd5Sriastradh * slots). 5663464ebd5Sriastradh */ 5673464ebd5SriastradhGLuint 5683464ebd5Sriastradh_glapi_get_dispatch_table_size(void) 5693464ebd5Sriastradh{ 5703464ebd5Sriastradh /* 5713464ebd5Sriastradh * The dispatch table size (number of entries) is the size of the 5723464ebd5Sriastradh * _glapi_table struct plus the number of dynamic entries we can add. 5733464ebd5Sriastradh * The extra slots can be filled in by DRI drivers that register new 5743464ebd5Sriastradh * extension functions. 5753464ebd5Sriastradh */ 5763464ebd5Sriastradh return FIRST_DYNAMIC_OFFSET + MAX_EXTENSION_FUNCS; 5773464ebd5Sriastradh} 578