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