1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Mesa 3-D graphics library 3bf215546Sopenharmony_ci * 4bf215546Sopenharmony_ci * Copyright (C) 1999-2008 Brian Paul All Rights Reserved. 5bf215546Sopenharmony_ci * 6bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 7bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 8bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation 9bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 11bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 12bf215546Sopenharmony_ci * 13bf215546Sopenharmony_ci * The above copyright notice and this permission notice shall be included 14bf215546Sopenharmony_ci * in all copies or substantial portions of the Software. 15bf215546Sopenharmony_ci * 16bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 17bf215546Sopenharmony_ci * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20bf215546Sopenharmony_ci * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21bf215546Sopenharmony_ci * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22bf215546Sopenharmony_ci * OTHER DEALINGS IN THE SOFTWARE. 23bf215546Sopenharmony_ci */ 24bf215546Sopenharmony_ci 25bf215546Sopenharmony_ci/** 26bf215546Sopenharmony_ci * \file glapi_getproc.c 27bf215546Sopenharmony_ci * 28bf215546Sopenharmony_ci * Code for implementing glXGetProcAddress(), etc. 29bf215546Sopenharmony_ci * This was originally in glapi.c but refactored out. 30bf215546Sopenharmony_ci */ 31bf215546Sopenharmony_ci 32bf215546Sopenharmony_ci 33bf215546Sopenharmony_ci#include <assert.h> 34bf215546Sopenharmony_ci#include <string.h> 35bf215546Sopenharmony_ci#include <stdlib.h> 36bf215546Sopenharmony_ci#include "glapi/glapi_priv.h" 37bf215546Sopenharmony_ci#include "glapitable.h" 38bf215546Sopenharmony_ci 39bf215546Sopenharmony_ci 40bf215546Sopenharmony_ci#define FIRST_DYNAMIC_OFFSET (sizeof(struct _glapi_table) / sizeof(void *)) 41bf215546Sopenharmony_ci 42bf215546Sopenharmony_ci 43bf215546Sopenharmony_ci 44bf215546Sopenharmony_ci/********************************************************************** 45bf215546Sopenharmony_ci * Static function management. 46bf215546Sopenharmony_ci */ 47bf215546Sopenharmony_ci 48bf215546Sopenharmony_ci 49bf215546Sopenharmony_ci#if !defined(DISPATCH_FUNCTION_SIZE) 50bf215546Sopenharmony_ci# define NEED_FUNCTION_POINTER 51bf215546Sopenharmony_ci#endif 52bf215546Sopenharmony_ci#include "glprocs.h" 53bf215546Sopenharmony_ci 54bf215546Sopenharmony_ci 55bf215546Sopenharmony_ci/** 56bf215546Sopenharmony_ci * Search the table of static entrypoint functions for the named function 57bf215546Sopenharmony_ci * and return the corresponding glprocs_table_t entry. 58bf215546Sopenharmony_ci */ 59bf215546Sopenharmony_cistatic const glprocs_table_t * 60bf215546Sopenharmony_ciget_static_proc( const char * n ) 61bf215546Sopenharmony_ci{ 62bf215546Sopenharmony_ci GLuint i; 63bf215546Sopenharmony_ci for (i = 0; static_functions[i].Name_offset >= 0; i++) { 64bf215546Sopenharmony_ci const char *testName = gl_string_table + static_functions[i].Name_offset; 65bf215546Sopenharmony_ci if (strcmp(testName, n) == 0) 66bf215546Sopenharmony_ci { 67bf215546Sopenharmony_ci return &static_functions[i]; 68bf215546Sopenharmony_ci } 69bf215546Sopenharmony_ci } 70bf215546Sopenharmony_ci return NULL; 71bf215546Sopenharmony_ci} 72bf215546Sopenharmony_ci 73bf215546Sopenharmony_ci 74bf215546Sopenharmony_ci/** 75bf215546Sopenharmony_ci * Return dispatch table offset of the named static (built-in) function. 76bf215546Sopenharmony_ci * Return -1 if function not found. 77bf215546Sopenharmony_ci */ 78bf215546Sopenharmony_cistatic GLint 79bf215546Sopenharmony_ciget_static_proc_offset(const char *funcName) 80bf215546Sopenharmony_ci{ 81bf215546Sopenharmony_ci const glprocs_table_t * const f = get_static_proc( funcName ); 82bf215546Sopenharmony_ci if (f == NULL) { 83bf215546Sopenharmony_ci return -1; 84bf215546Sopenharmony_ci } 85bf215546Sopenharmony_ci 86bf215546Sopenharmony_ci return f->Offset; 87bf215546Sopenharmony_ci} 88bf215546Sopenharmony_ci 89bf215546Sopenharmony_ci 90bf215546Sopenharmony_ci 91bf215546Sopenharmony_ci/** 92bf215546Sopenharmony_ci * Return dispatch function address for the named static (built-in) function. 93bf215546Sopenharmony_ci * Return NULL if function not found. 94bf215546Sopenharmony_ci */ 95bf215546Sopenharmony_cistatic _glapi_proc 96bf215546Sopenharmony_ciget_static_proc_address(const char *funcName) 97bf215546Sopenharmony_ci{ 98bf215546Sopenharmony_ci const glprocs_table_t * const f = get_static_proc( funcName ); 99bf215546Sopenharmony_ci if (f == NULL) { 100bf215546Sopenharmony_ci return NULL; 101bf215546Sopenharmony_ci } 102bf215546Sopenharmony_ci 103bf215546Sopenharmony_ci#if defined(DISPATCH_FUNCTION_SIZE) && defined(GLX_INDIRECT_RENDERING) 104bf215546Sopenharmony_ci return (f->Address == NULL) 105bf215546Sopenharmony_ci ? get_entrypoint_address(f->Offset) 106bf215546Sopenharmony_ci : f->Address; 107bf215546Sopenharmony_ci#elif defined(DISPATCH_FUNCTION_SIZE) 108bf215546Sopenharmony_ci return get_entrypoint_address(f->Offset); 109bf215546Sopenharmony_ci#else 110bf215546Sopenharmony_ci return f->Address; 111bf215546Sopenharmony_ci#endif 112bf215546Sopenharmony_ci} 113bf215546Sopenharmony_ci 114bf215546Sopenharmony_ci 115bf215546Sopenharmony_ci 116bf215546Sopenharmony_ci/** 117bf215546Sopenharmony_ci * Return the name of the function at the given offset in the dispatch 118bf215546Sopenharmony_ci * table. For debugging only. 119bf215546Sopenharmony_ci */ 120bf215546Sopenharmony_cistatic const char * 121bf215546Sopenharmony_ciget_static_proc_name( GLuint offset ) 122bf215546Sopenharmony_ci{ 123bf215546Sopenharmony_ci GLuint i; 124bf215546Sopenharmony_ci for (i = 0; static_functions[i].Name_offset >= 0; i++) { 125bf215546Sopenharmony_ci if (static_functions[i].Offset == offset) { 126bf215546Sopenharmony_ci return gl_string_table + static_functions[i].Name_offset; 127bf215546Sopenharmony_ci } 128bf215546Sopenharmony_ci } 129bf215546Sopenharmony_ci return NULL; 130bf215546Sopenharmony_ci} 131bf215546Sopenharmony_ci 132bf215546Sopenharmony_ci 133bf215546Sopenharmony_ci 134bf215546Sopenharmony_ci/********************************************************************** 135bf215546Sopenharmony_ci * Extension function management. 136bf215546Sopenharmony_ci */ 137bf215546Sopenharmony_ci 138bf215546Sopenharmony_ci 139bf215546Sopenharmony_ci/** 140bf215546Sopenharmony_ci * Track information about a function added to the GL API. 141bf215546Sopenharmony_ci */ 142bf215546Sopenharmony_cistruct _glapi_function { 143bf215546Sopenharmony_ci /** 144bf215546Sopenharmony_ci * Name of the function. 145bf215546Sopenharmony_ci */ 146bf215546Sopenharmony_ci const char * name; 147bf215546Sopenharmony_ci 148bf215546Sopenharmony_ci 149bf215546Sopenharmony_ci /** 150bf215546Sopenharmony_ci * Text string that describes the types of the parameters passed to the 151bf215546Sopenharmony_ci * named function. Parameter types are converted to characters using the 152bf215546Sopenharmony_ci * following rules: 153bf215546Sopenharmony_ci * - 'i' for \c GLint, \c GLuint, and \c GLenum 154bf215546Sopenharmony_ci * - 'p' for any pointer type 155bf215546Sopenharmony_ci * - 'f' for \c GLfloat and \c GLclampf 156bf215546Sopenharmony_ci * - 'd' for \c GLdouble and \c GLclampd 157bf215546Sopenharmony_ci */ 158bf215546Sopenharmony_ci const char * parameter_signature; 159bf215546Sopenharmony_ci 160bf215546Sopenharmony_ci 161bf215546Sopenharmony_ci /** 162bf215546Sopenharmony_ci * Offset in the dispatch table where the pointer to the real function is 163bf215546Sopenharmony_ci * located. If the driver has not requested that the named function be 164bf215546Sopenharmony_ci * added to the dispatch table, this will have the value ~0. 165bf215546Sopenharmony_ci */ 166bf215546Sopenharmony_ci unsigned dispatch_offset; 167bf215546Sopenharmony_ci 168bf215546Sopenharmony_ci 169bf215546Sopenharmony_ci /** 170bf215546Sopenharmony_ci * Pointer to the dispatch stub for the named function. 171bf215546Sopenharmony_ci * 172bf215546Sopenharmony_ci * \todo 173bf215546Sopenharmony_ci * The semantic of this field should be changed slightly. Currently, it 174bf215546Sopenharmony_ci * is always expected to be non-\c NULL. However, it would be better to 175bf215546Sopenharmony_ci * only allocate the entry-point stub when the application requests the 176bf215546Sopenharmony_ci * function via \c glXGetProcAddress. This would save memory for all the 177bf215546Sopenharmony_ci * functions that the driver exports but that the application never wants 178bf215546Sopenharmony_ci * to call. 179bf215546Sopenharmony_ci */ 180bf215546Sopenharmony_ci _glapi_proc dispatch_stub; 181bf215546Sopenharmony_ci}; 182bf215546Sopenharmony_ci 183bf215546Sopenharmony_ci 184bf215546Sopenharmony_cistatic struct _glapi_function ExtEntryTable[MAX_EXTENSION_FUNCS]; 185bf215546Sopenharmony_cistatic GLuint NumExtEntryPoints = 0; 186bf215546Sopenharmony_ci 187bf215546Sopenharmony_ci 188bf215546Sopenharmony_cistatic struct _glapi_function * 189bf215546Sopenharmony_ciget_extension_proc(const char *funcName) 190bf215546Sopenharmony_ci{ 191bf215546Sopenharmony_ci GLuint i; 192bf215546Sopenharmony_ci for (i = 0; i < NumExtEntryPoints; i++) { 193bf215546Sopenharmony_ci if (strcmp(ExtEntryTable[i].name, funcName) == 0) { 194bf215546Sopenharmony_ci return & ExtEntryTable[i]; 195bf215546Sopenharmony_ci } 196bf215546Sopenharmony_ci } 197bf215546Sopenharmony_ci return NULL; 198bf215546Sopenharmony_ci} 199bf215546Sopenharmony_ci 200bf215546Sopenharmony_ci 201bf215546Sopenharmony_cistatic GLint 202bf215546Sopenharmony_ciget_extension_proc_offset(const char *funcName) 203bf215546Sopenharmony_ci{ 204bf215546Sopenharmony_ci const struct _glapi_function * const f = get_extension_proc( funcName ); 205bf215546Sopenharmony_ci if (f == NULL) { 206bf215546Sopenharmony_ci return -1; 207bf215546Sopenharmony_ci } 208bf215546Sopenharmony_ci 209bf215546Sopenharmony_ci return f->dispatch_offset; 210bf215546Sopenharmony_ci} 211bf215546Sopenharmony_ci 212bf215546Sopenharmony_ci 213bf215546Sopenharmony_cistatic _glapi_proc 214bf215546Sopenharmony_ciget_extension_proc_address(const char *funcName) 215bf215546Sopenharmony_ci{ 216bf215546Sopenharmony_ci const struct _glapi_function * const f = get_extension_proc( funcName ); 217bf215546Sopenharmony_ci if (f == NULL) { 218bf215546Sopenharmony_ci return NULL; 219bf215546Sopenharmony_ci } 220bf215546Sopenharmony_ci 221bf215546Sopenharmony_ci return f->dispatch_stub; 222bf215546Sopenharmony_ci} 223bf215546Sopenharmony_ci 224bf215546Sopenharmony_ci 225bf215546Sopenharmony_cistatic const char * 226bf215546Sopenharmony_ciget_extension_proc_name(GLuint offset) 227bf215546Sopenharmony_ci{ 228bf215546Sopenharmony_ci GLuint i; 229bf215546Sopenharmony_ci for (i = 0; i < NumExtEntryPoints; i++) { 230bf215546Sopenharmony_ci if (ExtEntryTable[i].dispatch_offset == offset) { 231bf215546Sopenharmony_ci return ExtEntryTable[i].name; 232bf215546Sopenharmony_ci } 233bf215546Sopenharmony_ci } 234bf215546Sopenharmony_ci return NULL; 235bf215546Sopenharmony_ci} 236bf215546Sopenharmony_ci 237bf215546Sopenharmony_ci 238bf215546Sopenharmony_ci/** 239bf215546Sopenharmony_ci * strdup() is actually not a standard ANSI C or POSIX routine. 240bf215546Sopenharmony_ci * Irix will not define it if ANSI mode is in effect. 241bf215546Sopenharmony_ci */ 242bf215546Sopenharmony_cistatic char * 243bf215546Sopenharmony_cistr_dup(const char *str) 244bf215546Sopenharmony_ci{ 245bf215546Sopenharmony_ci char *copy; 246bf215546Sopenharmony_ci copy = malloc(strlen(str) + 1); 247bf215546Sopenharmony_ci if (!copy) 248bf215546Sopenharmony_ci return NULL; 249bf215546Sopenharmony_ci strcpy(copy, str); 250bf215546Sopenharmony_ci return copy; 251bf215546Sopenharmony_ci} 252bf215546Sopenharmony_ci 253bf215546Sopenharmony_ci 254bf215546Sopenharmony_ci/** 255bf215546Sopenharmony_ci * Generate new entrypoint 256bf215546Sopenharmony_ci * 257bf215546Sopenharmony_ci * Use a temporary dispatch offset of ~0 (i.e. -1). Later, when the driver 258bf215546Sopenharmony_ci * calls \c _glapi_add_dispatch we'll put in the proper offset. If that 259bf215546Sopenharmony_ci * never happens, and the user calls this function, he'll segfault. That's 260bf215546Sopenharmony_ci * what you get when you try calling a GL function that doesn't really exist. 261bf215546Sopenharmony_ci * 262bf215546Sopenharmony_ci * \param funcName Name of the function to create an entry-point for. 263bf215546Sopenharmony_ci * 264bf215546Sopenharmony_ci * \sa _glapi_add_entrypoint 265bf215546Sopenharmony_ci */ 266bf215546Sopenharmony_ci 267bf215546Sopenharmony_cistatic struct _glapi_function * 268bf215546Sopenharmony_ciadd_function_name( const char * funcName ) 269bf215546Sopenharmony_ci{ 270bf215546Sopenharmony_ci struct _glapi_function * entry = NULL; 271bf215546Sopenharmony_ci _glapi_proc entrypoint = NULL; 272bf215546Sopenharmony_ci char * name_dup = NULL; 273bf215546Sopenharmony_ci 274bf215546Sopenharmony_ci if (NumExtEntryPoints >= MAX_EXTENSION_FUNCS) 275bf215546Sopenharmony_ci return NULL; 276bf215546Sopenharmony_ci 277bf215546Sopenharmony_ci if (funcName == NULL) 278bf215546Sopenharmony_ci return NULL; 279bf215546Sopenharmony_ci 280bf215546Sopenharmony_ci name_dup = str_dup(funcName); 281bf215546Sopenharmony_ci if (name_dup == NULL) 282bf215546Sopenharmony_ci return NULL; 283bf215546Sopenharmony_ci 284bf215546Sopenharmony_ci entrypoint = generate_entrypoint(~0); 285bf215546Sopenharmony_ci 286bf215546Sopenharmony_ci if (entrypoint == NULL) { 287bf215546Sopenharmony_ci free(name_dup); 288bf215546Sopenharmony_ci return NULL; 289bf215546Sopenharmony_ci } 290bf215546Sopenharmony_ci 291bf215546Sopenharmony_ci entry = & ExtEntryTable[NumExtEntryPoints]; 292bf215546Sopenharmony_ci NumExtEntryPoints++; 293bf215546Sopenharmony_ci 294bf215546Sopenharmony_ci entry->name = name_dup; 295bf215546Sopenharmony_ci entry->parameter_signature = NULL; 296bf215546Sopenharmony_ci entry->dispatch_offset = ~0; 297bf215546Sopenharmony_ci entry->dispatch_stub = entrypoint; 298bf215546Sopenharmony_ci 299bf215546Sopenharmony_ci return entry; 300bf215546Sopenharmony_ci} 301bf215546Sopenharmony_ci 302bf215546Sopenharmony_ci 303bf215546Sopenharmony_cistatic struct _glapi_function * 304bf215546Sopenharmony_ciset_entry_info( struct _glapi_function * entry, const char * signature, unsigned offset ) 305bf215546Sopenharmony_ci{ 306bf215546Sopenharmony_ci char * sig_dup = NULL; 307bf215546Sopenharmony_ci 308bf215546Sopenharmony_ci if (signature == NULL) 309bf215546Sopenharmony_ci return NULL; 310bf215546Sopenharmony_ci 311bf215546Sopenharmony_ci sig_dup = str_dup(signature); 312bf215546Sopenharmony_ci if (sig_dup == NULL) 313bf215546Sopenharmony_ci return NULL; 314bf215546Sopenharmony_ci 315bf215546Sopenharmony_ci fill_in_entrypoint_offset(entry->dispatch_stub, offset); 316bf215546Sopenharmony_ci 317bf215546Sopenharmony_ci entry->parameter_signature = sig_dup; 318bf215546Sopenharmony_ci entry->dispatch_offset = offset; 319bf215546Sopenharmony_ci 320bf215546Sopenharmony_ci return entry; 321bf215546Sopenharmony_ci} 322bf215546Sopenharmony_ci 323bf215546Sopenharmony_ci 324bf215546Sopenharmony_ci/** 325bf215546Sopenharmony_ci * Fill-in the dispatch stub for the named function. 326bf215546Sopenharmony_ci * 327bf215546Sopenharmony_ci * This function is intended to be called by a hardware driver. When called, 328bf215546Sopenharmony_ci * a dispatch stub may be created for the function. A pointer to this 329bf215546Sopenharmony_ci * dispatch function will be returned by glXGetProcAddress. 330bf215546Sopenharmony_ci * 331bf215546Sopenharmony_ci * \param function_names Array of pointers to function names that should 332bf215546Sopenharmony_ci * share a common dispatch offset. 333bf215546Sopenharmony_ci * \param parameter_signature String representing the types of the parameters 334bf215546Sopenharmony_ci * passed to the named function. Parameter types 335bf215546Sopenharmony_ci * are converted to characters using the following 336bf215546Sopenharmony_ci * rules: 337bf215546Sopenharmony_ci * - 'i' for \c GLint, \c GLuint, and \c GLenum 338bf215546Sopenharmony_ci * - 'p' for any pointer type 339bf215546Sopenharmony_ci * - 'f' for \c GLfloat and \c GLclampf 340bf215546Sopenharmony_ci * - 'd' for \c GLdouble and \c GLclampd 341bf215546Sopenharmony_ci * 342bf215546Sopenharmony_ci * \returns 343bf215546Sopenharmony_ci * The offset in the dispatch table of the named function. A pointer to the 344bf215546Sopenharmony_ci * driver's implementation of the named function should be stored at 345bf215546Sopenharmony_ci * \c dispatch_table[\c offset]. Return -1 if error/problem. 346bf215546Sopenharmony_ci * 347bf215546Sopenharmony_ci * \sa glXGetProcAddress 348bf215546Sopenharmony_ci * 349bf215546Sopenharmony_ci * \warning 350bf215546Sopenharmony_ci * This function can only handle up to 8 names at a time. As far as I know, 351bf215546Sopenharmony_ci * the maximum number of names ever associated with an existing GL function is 352bf215546Sopenharmony_ci * 4 (\c glPointParameterfSGIS, \c glPointParameterfEXT, 353bf215546Sopenharmony_ci * \c glPointParameterfARB, and \c glPointParameterf), so this should not be 354bf215546Sopenharmony_ci * too painful of a limitation. 355bf215546Sopenharmony_ci * 356bf215546Sopenharmony_ci * \todo 357bf215546Sopenharmony_ci * Determine whether or not \c parameter_signature should be allowed to be 358bf215546Sopenharmony_ci * \c NULL. It doesn't seem like much of a hardship for drivers to have to 359bf215546Sopenharmony_ci * pass in an empty string. 360bf215546Sopenharmony_ci * 361bf215546Sopenharmony_ci * \todo 362bf215546Sopenharmony_ci * Determine if code should be added to reject function names that start with 363bf215546Sopenharmony_ci * 'glX'. 364bf215546Sopenharmony_ci * 365bf215546Sopenharmony_ci * \bug 366bf215546Sopenharmony_ci * Add code to compare \c parameter_signature with the parameter signature of 367bf215546Sopenharmony_ci * a static function. In order to do that, we need to find a way to \b get 368bf215546Sopenharmony_ci * the parameter signature of a static function. 369bf215546Sopenharmony_ci */ 370bf215546Sopenharmony_ci 371bf215546Sopenharmony_ciint 372bf215546Sopenharmony_ci_glapi_add_dispatch( const char * const * function_names, 373bf215546Sopenharmony_ci const char * parameter_signature ) 374bf215546Sopenharmony_ci{ 375bf215546Sopenharmony_ci static int next_dynamic_offset = FIRST_DYNAMIC_OFFSET; 376bf215546Sopenharmony_ci const char * const real_sig = (parameter_signature != NULL) 377bf215546Sopenharmony_ci ? parameter_signature : ""; 378bf215546Sopenharmony_ci struct _glapi_function * entry[8]; 379bf215546Sopenharmony_ci GLboolean is_static[8]; 380bf215546Sopenharmony_ci unsigned i; 381bf215546Sopenharmony_ci int offset = ~0; 382bf215546Sopenharmony_ci 383bf215546Sopenharmony_ci init_glapi_relocs_once(); 384bf215546Sopenharmony_ci 385bf215546Sopenharmony_ci (void) memset( is_static, 0, sizeof( is_static ) ); 386bf215546Sopenharmony_ci (void) memset( entry, 0, sizeof( entry ) ); 387bf215546Sopenharmony_ci 388bf215546Sopenharmony_ci /* Find the _single_ dispatch offset for all function names that already 389bf215546Sopenharmony_ci * exist (and have a dispatch offset). 390bf215546Sopenharmony_ci */ 391bf215546Sopenharmony_ci 392bf215546Sopenharmony_ci for ( i = 0 ; function_names[i] != NULL ; i++ ) { 393bf215546Sopenharmony_ci const char * funcName = function_names[i]; 394bf215546Sopenharmony_ci int static_offset; 395bf215546Sopenharmony_ci int extension_offset; 396bf215546Sopenharmony_ci 397bf215546Sopenharmony_ci if (funcName[0] != 'g' || funcName[1] != 'l') 398bf215546Sopenharmony_ci return -1; 399bf215546Sopenharmony_ci 400bf215546Sopenharmony_ci /* search built-in functions */ 401bf215546Sopenharmony_ci static_offset = get_static_proc_offset(funcName); 402bf215546Sopenharmony_ci 403bf215546Sopenharmony_ci if (static_offset >= 0) { 404bf215546Sopenharmony_ci 405bf215546Sopenharmony_ci is_static[i] = GL_TRUE; 406bf215546Sopenharmony_ci 407bf215546Sopenharmony_ci /* FIXME: Make sure the parameter signatures match! How do we get 408bf215546Sopenharmony_ci * FIXME: the parameter signature for static functions? 409bf215546Sopenharmony_ci */ 410bf215546Sopenharmony_ci 411bf215546Sopenharmony_ci if ( (offset != ~0) && (static_offset != offset) ) { 412bf215546Sopenharmony_ci return -1; 413bf215546Sopenharmony_ci } 414bf215546Sopenharmony_ci 415bf215546Sopenharmony_ci offset = static_offset; 416bf215546Sopenharmony_ci 417bf215546Sopenharmony_ci continue; 418bf215546Sopenharmony_ci } 419bf215546Sopenharmony_ci 420bf215546Sopenharmony_ci /* search added extension functions */ 421bf215546Sopenharmony_ci entry[i] = get_extension_proc(funcName); 422bf215546Sopenharmony_ci 423bf215546Sopenharmony_ci if (entry[i] != NULL) { 424bf215546Sopenharmony_ci extension_offset = entry[i]->dispatch_offset; 425bf215546Sopenharmony_ci 426bf215546Sopenharmony_ci /* The offset may be ~0 if the function name was added by 427bf215546Sopenharmony_ci * glXGetProcAddress but never filled in by the driver. 428bf215546Sopenharmony_ci */ 429bf215546Sopenharmony_ci 430bf215546Sopenharmony_ci if (extension_offset == ~0) { 431bf215546Sopenharmony_ci continue; 432bf215546Sopenharmony_ci } 433bf215546Sopenharmony_ci 434bf215546Sopenharmony_ci if (strcmp(real_sig, entry[i]->parameter_signature) != 0) { 435bf215546Sopenharmony_ci return -1; 436bf215546Sopenharmony_ci } 437bf215546Sopenharmony_ci 438bf215546Sopenharmony_ci if ( (offset != ~0) && (extension_offset != offset) ) { 439bf215546Sopenharmony_ci return -1; 440bf215546Sopenharmony_ci } 441bf215546Sopenharmony_ci 442bf215546Sopenharmony_ci offset = extension_offset; 443bf215546Sopenharmony_ci } 444bf215546Sopenharmony_ci } 445bf215546Sopenharmony_ci 446bf215546Sopenharmony_ci /* If all function names are either new (or with no dispatch offset), 447bf215546Sopenharmony_ci * allocate a new dispatch offset. 448bf215546Sopenharmony_ci */ 449bf215546Sopenharmony_ci 450bf215546Sopenharmony_ci if (offset == ~0) { 451bf215546Sopenharmony_ci offset = next_dynamic_offset; 452bf215546Sopenharmony_ci next_dynamic_offset++; 453bf215546Sopenharmony_ci } 454bf215546Sopenharmony_ci 455bf215546Sopenharmony_ci /* Fill in the dispatch offset for the new function names (and those with 456bf215546Sopenharmony_ci * no dispatch offset). 457bf215546Sopenharmony_ci */ 458bf215546Sopenharmony_ci 459bf215546Sopenharmony_ci for ( i = 0 ; function_names[i] != NULL ; i++ ) { 460bf215546Sopenharmony_ci if (is_static[i]) { 461bf215546Sopenharmony_ci continue; 462bf215546Sopenharmony_ci } 463bf215546Sopenharmony_ci 464bf215546Sopenharmony_ci /* generate entrypoints for new function names */ 465bf215546Sopenharmony_ci if (entry[i] == NULL) { 466bf215546Sopenharmony_ci entry[i] = add_function_name( function_names[i] ); 467bf215546Sopenharmony_ci if (entry[i] == NULL) { 468bf215546Sopenharmony_ci /* FIXME: Possible memory leak here. */ 469bf215546Sopenharmony_ci return -1; 470bf215546Sopenharmony_ci } 471bf215546Sopenharmony_ci } 472bf215546Sopenharmony_ci 473bf215546Sopenharmony_ci if (entry[i]->dispatch_offset == ~0) { 474bf215546Sopenharmony_ci set_entry_info( entry[i], real_sig, offset ); 475bf215546Sopenharmony_ci } 476bf215546Sopenharmony_ci } 477bf215546Sopenharmony_ci 478bf215546Sopenharmony_ci return offset; 479bf215546Sopenharmony_ci} 480bf215546Sopenharmony_ci 481bf215546Sopenharmony_ci 482bf215546Sopenharmony_ci/** 483bf215546Sopenharmony_ci * Return offset of entrypoint for named function within dispatch table. 484bf215546Sopenharmony_ci */ 485bf215546Sopenharmony_ciGLint 486bf215546Sopenharmony_ci_glapi_get_proc_offset(const char *funcName) 487bf215546Sopenharmony_ci{ 488bf215546Sopenharmony_ci GLint offset; 489bf215546Sopenharmony_ci 490bf215546Sopenharmony_ci /* search extension functions first */ 491bf215546Sopenharmony_ci offset = get_extension_proc_offset(funcName); 492bf215546Sopenharmony_ci if (offset >= 0) 493bf215546Sopenharmony_ci return offset; 494bf215546Sopenharmony_ci 495bf215546Sopenharmony_ci /* search static functions */ 496bf215546Sopenharmony_ci return get_static_proc_offset(funcName); 497bf215546Sopenharmony_ci} 498bf215546Sopenharmony_ci 499bf215546Sopenharmony_ci 500bf215546Sopenharmony_ci 501bf215546Sopenharmony_ci/** 502bf215546Sopenharmony_ci * Return pointer to the named function. If the function name isn't found 503bf215546Sopenharmony_ci * in the name of static functions, try generating a new API entrypoint on 504bf215546Sopenharmony_ci * the fly with assembly language. 505bf215546Sopenharmony_ci */ 506bf215546Sopenharmony_ci_glapi_proc 507bf215546Sopenharmony_ci_glapi_get_proc_address(const char *funcName) 508bf215546Sopenharmony_ci{ 509bf215546Sopenharmony_ci _glapi_proc func; 510bf215546Sopenharmony_ci struct _glapi_function * entry; 511bf215546Sopenharmony_ci 512bf215546Sopenharmony_ci init_glapi_relocs_once(); 513bf215546Sopenharmony_ci 514bf215546Sopenharmony_ci if (!funcName || funcName[0] != 'g' || funcName[1] != 'l') 515bf215546Sopenharmony_ci return NULL; 516bf215546Sopenharmony_ci 517bf215546Sopenharmony_ci /* search extension functions first */ 518bf215546Sopenharmony_ci func = get_extension_proc_address(funcName); 519bf215546Sopenharmony_ci if (func) 520bf215546Sopenharmony_ci return func; 521bf215546Sopenharmony_ci 522bf215546Sopenharmony_ci /* search static functions */ 523bf215546Sopenharmony_ci func = get_static_proc_address(funcName); 524bf215546Sopenharmony_ci if (func) 525bf215546Sopenharmony_ci return func; 526bf215546Sopenharmony_ci 527bf215546Sopenharmony_ci /* generate entrypoint, dispatch offset must be filled in by the driver */ 528bf215546Sopenharmony_ci entry = add_function_name(funcName); 529bf215546Sopenharmony_ci if (entry == NULL) 530bf215546Sopenharmony_ci return NULL; 531bf215546Sopenharmony_ci 532bf215546Sopenharmony_ci return entry->dispatch_stub; 533bf215546Sopenharmony_ci} 534bf215546Sopenharmony_ci 535bf215546Sopenharmony_ci 536bf215546Sopenharmony_ci 537bf215546Sopenharmony_ci/** 538bf215546Sopenharmony_ci * Return the name of the function at the given dispatch offset. 539bf215546Sopenharmony_ci * This is only intended for debugging. 540bf215546Sopenharmony_ci */ 541bf215546Sopenharmony_ciconst char * 542bf215546Sopenharmony_ci_glapi_get_proc_name(GLuint offset) 543bf215546Sopenharmony_ci{ 544bf215546Sopenharmony_ci const char * n; 545bf215546Sopenharmony_ci 546bf215546Sopenharmony_ci /* search built-in functions */ 547bf215546Sopenharmony_ci n = get_static_proc_name(offset); 548bf215546Sopenharmony_ci if ( n != NULL ) { 549bf215546Sopenharmony_ci return n; 550bf215546Sopenharmony_ci } 551bf215546Sopenharmony_ci 552bf215546Sopenharmony_ci /* search added extension functions */ 553bf215546Sopenharmony_ci return get_extension_proc_name(offset); 554bf215546Sopenharmony_ci} 555bf215546Sopenharmony_ci 556bf215546Sopenharmony_ci 557bf215546Sopenharmony_ci 558bf215546Sopenharmony_ci/********************************************************************** 559bf215546Sopenharmony_ci * GL API table functions. 560bf215546Sopenharmony_ci */ 561bf215546Sopenharmony_ci 562bf215546Sopenharmony_ci 563bf215546Sopenharmony_ci/** 564bf215546Sopenharmony_ci * Return size of dispatch table struct as number of functions (or 565bf215546Sopenharmony_ci * slots). 566bf215546Sopenharmony_ci */ 567bf215546Sopenharmony_ciGLuint 568bf215546Sopenharmony_ci_glapi_get_dispatch_table_size(void) 569bf215546Sopenharmony_ci{ 570bf215546Sopenharmony_ci /* 571bf215546Sopenharmony_ci * The dispatch table size (number of entries) is the size of the 572bf215546Sopenharmony_ci * _glapi_table struct plus the number of dynamic entries we can add. 573bf215546Sopenharmony_ci * The extra slots can be filled in by DRI drivers that register new 574bf215546Sopenharmony_ci * extension functions. 575bf215546Sopenharmony_ci */ 576bf215546Sopenharmony_ci return FIRST_DYNAMIC_OFFSET + MAX_EXTENSION_FUNCS; 577bf215546Sopenharmony_ci} 578