1a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul/*
2a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul * Mesa 3-D graphics library
3a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul * Version:  7.1
4a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul *
5a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul * Copyright (C) 1999-2008  Brian Paul   All Rights Reserved.
6a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul *
7a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul * Permission is hereby granted, free of charge, to any person obtaining a
8a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul * copy of this software and associated documentation files (the "Software"),
9a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul * to deal in the Software without restriction, including without limitation
10a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul * and/or sell copies of the Software, and to permit persons to whom the
12a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul * Software is furnished to do so, subject to the following conditions:
13a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul *
14a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul * The above copyright notice and this permission notice shall be included
15a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul * in all copies or substantial portions of the Software.
16a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul *
17a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul */
24a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul
25a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul/**
261eee1bac1f6d911e6124daafc9b9291666d91cefVinson Lee * \file glapi_getproc.c
27a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul *
28a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul * Code for implementing glXGetProcAddress(), etc.
29a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul * This was originally in glapi.c but refactored out.
30a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul */
31a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul
32a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul
332c8b5ffed9a787e896b540a95be48ef401d5f007George Sapountzis#include "glapi/glapi_priv.h"
345b426288c2dbc42ef44ea13fe37afa77223107bbChia-I Wu#include "glapi/glapitable.h"
35e4dbfa44ed018d124e1531077d506c8c914c1a51Chia-I Wu
36e4dbfa44ed018d124e1531077d506c8c914c1a51Chia-I Wu
37e4dbfa44ed018d124e1531077d506c8c914c1a51Chia-I Wu#define FIRST_DYNAMIC_OFFSET (sizeof(struct _glapi_table) / sizeof(void *))
38a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul
39a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul
40f0c18da2cf01bc11dc720caed4590ae7eca128f1George Sapountzis/**********************************************************************
41f0c18da2cf01bc11dc720caed4590ae7eca128f1George Sapountzis * Static function management.
42f0c18da2cf01bc11dc720caed4590ae7eca128f1George Sapountzis */
43f0c18da2cf01bc11dc720caed4590ae7eca128f1George Sapountzis
44f0c18da2cf01bc11dc720caed4590ae7eca128f1George Sapountzis
451ccef926be46dce3b6b5c76e812e2fae4e205ce7Adam Jackson#if !defined(DISPATCH_FUNCTION_SIZE)
46a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul# define NEED_FUNCTION_POINTER
47a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul#endif
485b426288c2dbc42ef44ea13fe37afa77223107bbChia-I Wu#include "glapi/glprocs.h"
49a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul
50a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul
51a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul/**
52a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul * Search the table of static entrypoint functions for the named function
53a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul * and return the corresponding glprocs_table_t entry.
54a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul */
55a97226352fb8063d4d0084523312b4880dae5ac7Brian Paulstatic const glprocs_table_t *
56f0c18da2cf01bc11dc720caed4590ae7eca128f1George Sapountzisget_static_proc( const char * n )
57a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul{
58a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul   GLuint i;
59a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul   for (i = 0; static_functions[i].Name_offset >= 0; i++) {
60a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul      const char *testName = gl_string_table + static_functions[i].Name_offset;
614447fddc82a2c0245e798c90492293d875d186d0Brian Paul#ifdef MANGLE
6220ed2445b3b98f2b49a26ad4b45859a908583311George Sapountzis      /* skip the prefix on the name */
634447fddc82a2c0245e798c90492293d875d186d0Brian Paul      if (strcmp(testName, n + 1) == 0)
644447fddc82a2c0245e798c90492293d875d186d0Brian Paul#else
654447fddc82a2c0245e798c90492293d875d186d0Brian Paul      if (strcmp(testName, n) == 0)
664447fddc82a2c0245e798c90492293d875d186d0Brian Paul#endif
674447fddc82a2c0245e798c90492293d875d186d0Brian Paul      {
68a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul	 return &static_functions[i];
69a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul      }
70a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul   }
71a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul   return NULL;
72a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul}
73a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul
74a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul
75a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul/**
76a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul * Return dispatch table offset of the named static (built-in) function.
77a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul * Return -1 if function not found.
78a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul */
79a97226352fb8063d4d0084523312b4880dae5ac7Brian Paulstatic GLint
80a97226352fb8063d4d0084523312b4880dae5ac7Brian Paulget_static_proc_offset(const char *funcName)
81a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul{
82f0c18da2cf01bc11dc720caed4590ae7eca128f1George Sapountzis   const glprocs_table_t * const f = get_static_proc( funcName );
83f0c18da2cf01bc11dc720caed4590ae7eca128f1George Sapountzis   if (f == NULL) {
84f0c18da2cf01bc11dc720caed4590ae7eca128f1George Sapountzis      return -1;
85a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul   }
86f0c18da2cf01bc11dc720caed4590ae7eca128f1George Sapountzis
87f0c18da2cf01bc11dc720caed4590ae7eca128f1George Sapountzis   return f->Offset;
88a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul}
89a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul
90a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul
91cccdc1783fda33da6fc12befdf288b74866e5dfaGeorge Sapountzis
92a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul/**
93a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul * Return dispatch function address for the named static (built-in) function.
94a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul * Return NULL if function not found.
95a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul */
96a97226352fb8063d4d0084523312b4880dae5ac7Brian Paulstatic _glapi_proc
97a97226352fb8063d4d0084523312b4880dae5ac7Brian Paulget_static_proc_address(const char *funcName)
98a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul{
99f0c18da2cf01bc11dc720caed4590ae7eca128f1George Sapountzis   const glprocs_table_t * const f = get_static_proc( funcName );
100f0c18da2cf01bc11dc720caed4590ae7eca128f1George Sapountzis   if (f == NULL) {
101f0c18da2cf01bc11dc720caed4590ae7eca128f1George Sapountzis      return NULL;
102f0c18da2cf01bc11dc720caed4590ae7eca128f1George Sapountzis   }
103f0c18da2cf01bc11dc720caed4590ae7eca128f1George Sapountzis
104a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul#if defined(DISPATCH_FUNCTION_SIZE) && defined(GLX_INDIRECT_RENDERING)
105f0c18da2cf01bc11dc720caed4590ae7eca128f1George Sapountzis   return (f->Address == NULL)
106f0c18da2cf01bc11dc720caed4590ae7eca128f1George Sapountzis      ? get_entrypoint_address(f->Offset)
107f0c18da2cf01bc11dc720caed4590ae7eca128f1George Sapountzis      : f->Address;
108a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul#elif defined(DISPATCH_FUNCTION_SIZE)
109f0c18da2cf01bc11dc720caed4590ae7eca128f1George Sapountzis   return get_entrypoint_address(f->Offset);
110a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul#else
111f0c18da2cf01bc11dc720caed4590ae7eca128f1George Sapountzis   return f->Address;
112a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul#endif
113a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul}
114a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul
115a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul
116a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul
117a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul/**
118a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul * Return the name of the function at the given offset in the dispatch
119a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul * table.  For debugging only.
120a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul */
121a97226352fb8063d4d0084523312b4880dae5ac7Brian Paulstatic const char *
122a97226352fb8063d4d0084523312b4880dae5ac7Brian Paulget_static_proc_name( GLuint offset )
123a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul{
124a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul   GLuint i;
125a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul   for (i = 0; static_functions[i].Name_offset >= 0; i++) {
126a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul      if (static_functions[i].Offset == offset) {
127a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul	 return gl_string_table + static_functions[i].Name_offset;
128a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul      }
129a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul   }
130a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul   return NULL;
131a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul}
132a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul
133a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul
134a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul
135a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul/**********************************************************************
136a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul * Extension function management.
137a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul */
138a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul
139a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul
140a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul/**
141a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul * Track information about a function added to the GL API.
142a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul */
143a97226352fb8063d4d0084523312b4880dae5ac7Brian Paulstruct _glapi_function {
144a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul   /**
145a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul    * Name of the function.
146a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul    */
147a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul   const char * name;
148a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul
149a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul
150a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul   /**
151a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul    * Text string that describes the types of the parameters passed to the
152a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul    * named function.   Parameter types are converted to characters using the
153a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul    * following rules:
154a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul    *   - 'i' for \c GLint, \c GLuint, and \c GLenum
155a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul    *   - 'p' for any pointer type
156a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul    *   - 'f' for \c GLfloat and \c GLclampf
157a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul    *   - 'd' for \c GLdouble and \c GLclampd
158a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul    */
159a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul   const char * parameter_signature;
160a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul
161a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul
162a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul   /**
163a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul    * Offset in the dispatch table where the pointer to the real function is
164a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul    * located.  If the driver has not requested that the named function be
165a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul    * added to the dispatch table, this will have the value ~0.
166a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul    */
167a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul   unsigned dispatch_offset;
168a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul
169a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul
170a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul   /**
171a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul    * Pointer to the dispatch stub for the named function.
172a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul    *
173a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul    * \todo
174a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul    * The semantic of this field should be changed slightly.  Currently, it
175a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul    * is always expected to be non-\c NULL.  However, it would be better to
176a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul    * only allocate the entry-point stub when the application requests the
177a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul    * function via \c glXGetProcAddress.  This would save memory for all the
178a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul    * functions that the driver exports but that the application never wants
179a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul    * to call.
180a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul    */
181a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul   _glapi_proc dispatch_stub;
182a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul};
183a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul
184a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul
185a97226352fb8063d4d0084523312b4880dae5ac7Brian Paulstatic struct _glapi_function ExtEntryTable[MAX_EXTENSION_FUNCS];
186a97226352fb8063d4d0084523312b4880dae5ac7Brian Paulstatic GLuint NumExtEntryPoints = 0;
187a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul
188a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul
1895b2340c493cdf8d776e717b00acf0a8002858976George Sapountzisstatic struct _glapi_function *
1905b2340c493cdf8d776e717b00acf0a8002858976George Sapountzisget_extension_proc(const char *funcName)
19158985c36be85c668d059165d8282f8c8e4c7a380George Sapountzis{
19258985c36be85c668d059165d8282f8c8e4c7a380George Sapountzis   GLuint i;
19358985c36be85c668d059165d8282f8c8e4c7a380George Sapountzis   for (i = 0; i < NumExtEntryPoints; i++) {
19458985c36be85c668d059165d8282f8c8e4c7a380George Sapountzis      if (strcmp(ExtEntryTable[i].name, funcName) == 0) {
1955b2340c493cdf8d776e717b00acf0a8002858976George Sapountzis         return & ExtEntryTable[i];
19658985c36be85c668d059165d8282f8c8e4c7a380George Sapountzis      }
19758985c36be85c668d059165d8282f8c8e4c7a380George Sapountzis   }
1985b2340c493cdf8d776e717b00acf0a8002858976George Sapountzis   return NULL;
1995b2340c493cdf8d776e717b00acf0a8002858976George Sapountzis}
2005b2340c493cdf8d776e717b00acf0a8002858976George Sapountzis
2015b2340c493cdf8d776e717b00acf0a8002858976George Sapountzis
2025b2340c493cdf8d776e717b00acf0a8002858976George Sapountzisstatic GLint
2035b2340c493cdf8d776e717b00acf0a8002858976George Sapountzisget_extension_proc_offset(const char *funcName)
2045b2340c493cdf8d776e717b00acf0a8002858976George Sapountzis{
2055b2340c493cdf8d776e717b00acf0a8002858976George Sapountzis   const struct _glapi_function * const f = get_extension_proc( funcName );
2065b2340c493cdf8d776e717b00acf0a8002858976George Sapountzis   if (f == NULL) {
2075b2340c493cdf8d776e717b00acf0a8002858976George Sapountzis      return -1;
2085b2340c493cdf8d776e717b00acf0a8002858976George Sapountzis   }
2095b2340c493cdf8d776e717b00acf0a8002858976George Sapountzis
2105b2340c493cdf8d776e717b00acf0a8002858976George Sapountzis   return f->dispatch_offset;
21158985c36be85c668d059165d8282f8c8e4c7a380George Sapountzis}
21258985c36be85c668d059165d8282f8c8e4c7a380George Sapountzis
21358985c36be85c668d059165d8282f8c8e4c7a380George Sapountzis
21458985c36be85c668d059165d8282f8c8e4c7a380George Sapountzisstatic _glapi_proc
21558985c36be85c668d059165d8282f8c8e4c7a380George Sapountzisget_extension_proc_address(const char *funcName)
21658985c36be85c668d059165d8282f8c8e4c7a380George Sapountzis{
2175b2340c493cdf8d776e717b00acf0a8002858976George Sapountzis   const struct _glapi_function * const f = get_extension_proc( funcName );
2185b2340c493cdf8d776e717b00acf0a8002858976George Sapountzis   if (f == NULL) {
2195b2340c493cdf8d776e717b00acf0a8002858976George Sapountzis      return NULL;
22058985c36be85c668d059165d8282f8c8e4c7a380George Sapountzis   }
2215b2340c493cdf8d776e717b00acf0a8002858976George Sapountzis
2225b2340c493cdf8d776e717b00acf0a8002858976George Sapountzis   return f->dispatch_stub;
22358985c36be85c668d059165d8282f8c8e4c7a380George Sapountzis}
22458985c36be85c668d059165d8282f8c8e4c7a380George Sapountzis
22558985c36be85c668d059165d8282f8c8e4c7a380George Sapountzis
22658985c36be85c668d059165d8282f8c8e4c7a380George Sapountzisstatic const char *
22758985c36be85c668d059165d8282f8c8e4c7a380George Sapountzisget_extension_proc_name(GLuint offset)
22858985c36be85c668d059165d8282f8c8e4c7a380George Sapountzis{
22958985c36be85c668d059165d8282f8c8e4c7a380George Sapountzis   GLuint i;
23058985c36be85c668d059165d8282f8c8e4c7a380George Sapountzis   for (i = 0; i < NumExtEntryPoints; i++) {
23158985c36be85c668d059165d8282f8c8e4c7a380George Sapountzis      if (ExtEntryTable[i].dispatch_offset == offset) {
23258985c36be85c668d059165d8282f8c8e4c7a380George Sapountzis         return ExtEntryTable[i].name;
23358985c36be85c668d059165d8282f8c8e4c7a380George Sapountzis      }
23458985c36be85c668d059165d8282f8c8e4c7a380George Sapountzis   }
23558985c36be85c668d059165d8282f8c8e4c7a380George Sapountzis   return NULL;
23658985c36be85c668d059165d8282f8c8e4c7a380George Sapountzis}
23758985c36be85c668d059165d8282f8c8e4c7a380George Sapountzis
23858985c36be85c668d059165d8282f8c8e4c7a380George Sapountzis
239a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul/**
240cccdc1783fda33da6fc12befdf288b74866e5dfaGeorge Sapountzis * strdup() is actually not a standard ANSI C or POSIX routine.
241cccdc1783fda33da6fc12befdf288b74866e5dfaGeorge Sapountzis * Irix will not define it if ANSI mode is in effect.
242cccdc1783fda33da6fc12befdf288b74866e5dfaGeorge Sapountzis */
243cccdc1783fda33da6fc12befdf288b74866e5dfaGeorge Sapountzisstatic char *
244cccdc1783fda33da6fc12befdf288b74866e5dfaGeorge Sapountzisstr_dup(const char *str)
245cccdc1783fda33da6fc12befdf288b74866e5dfaGeorge Sapountzis{
246cccdc1783fda33da6fc12befdf288b74866e5dfaGeorge Sapountzis   char *copy;
247cccdc1783fda33da6fc12befdf288b74866e5dfaGeorge Sapountzis   copy = (char*) malloc(strlen(str) + 1);
248cccdc1783fda33da6fc12befdf288b74866e5dfaGeorge Sapountzis   if (!copy)
249cccdc1783fda33da6fc12befdf288b74866e5dfaGeorge Sapountzis      return NULL;
2506405ecb399a52e4d3fe0c002bcd9b3485cbd1360Brian Paul   strcpy(copy, str);
251cccdc1783fda33da6fc12befdf288b74866e5dfaGeorge Sapountzis   return copy;
252cccdc1783fda33da6fc12befdf288b74866e5dfaGeorge Sapountzis}
253cccdc1783fda33da6fc12befdf288b74866e5dfaGeorge Sapountzis
254cccdc1783fda33da6fc12befdf288b74866e5dfaGeorge Sapountzis
255cccdc1783fda33da6fc12befdf288b74866e5dfaGeorge Sapountzis/**
256a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul * Generate new entrypoint
257a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul *
258a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul * Use a temporary dispatch offset of ~0 (i.e. -1).  Later, when the driver
259a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul * calls \c _glapi_add_dispatch we'll put in the proper offset.  If that
260a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul * never happens, and the user calls this function, he'll segfault.  That's
261a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul * what you get when you try calling a GL function that doesn't really exist.
262a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul *
263a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul * \param funcName  Name of the function to create an entry-point for.
264a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul *
265a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul * \sa _glapi_add_entrypoint
266a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul */
267a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul
268a97226352fb8063d4d0084523312b4880dae5ac7Brian Paulstatic struct _glapi_function *
269a97226352fb8063d4d0084523312b4880dae5ac7Brian Pauladd_function_name( const char * funcName )
270a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul{
271a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul   struct _glapi_function * entry = NULL;
272cae4fdda8d27cac21714571adb0bfada6d96152aGeorge Sapountzis   _glapi_proc entrypoint = NULL;
273cae4fdda8d27cac21714571adb0bfada6d96152aGeorge Sapountzis   char * name_dup = NULL;
274cae4fdda8d27cac21714571adb0bfada6d96152aGeorge Sapountzis
275cae4fdda8d27cac21714571adb0bfada6d96152aGeorge Sapountzis   if (NumExtEntryPoints >= MAX_EXTENSION_FUNCS)
276cae4fdda8d27cac21714571adb0bfada6d96152aGeorge Sapountzis      return NULL;
277cae4fdda8d27cac21714571adb0bfada6d96152aGeorge Sapountzis
278cae4fdda8d27cac21714571adb0bfada6d96152aGeorge Sapountzis   if (funcName == NULL)
279cae4fdda8d27cac21714571adb0bfada6d96152aGeorge Sapountzis      return NULL;
280cae4fdda8d27cac21714571adb0bfada6d96152aGeorge Sapountzis
281cae4fdda8d27cac21714571adb0bfada6d96152aGeorge Sapountzis   name_dup = str_dup(funcName);
282cae4fdda8d27cac21714571adb0bfada6d96152aGeorge Sapountzis   if (name_dup == NULL)
283cae4fdda8d27cac21714571adb0bfada6d96152aGeorge Sapountzis      return NULL;
284cae4fdda8d27cac21714571adb0bfada6d96152aGeorge Sapountzis
285cae4fdda8d27cac21714571adb0bfada6d96152aGeorge Sapountzis   entrypoint = generate_entrypoint(~0);
286cae4fdda8d27cac21714571adb0bfada6d96152aGeorge Sapountzis
287cae4fdda8d27cac21714571adb0bfada6d96152aGeorge Sapountzis   if (entrypoint == NULL) {
288cae4fdda8d27cac21714571adb0bfada6d96152aGeorge Sapountzis      free(name_dup);
289cae4fdda8d27cac21714571adb0bfada6d96152aGeorge Sapountzis      return NULL;
290a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul   }
291a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul
292cae4fdda8d27cac21714571adb0bfada6d96152aGeorge Sapountzis   entry = & ExtEntryTable[NumExtEntryPoints];
293cae4fdda8d27cac21714571adb0bfada6d96152aGeorge Sapountzis   NumExtEntryPoints++;
294cae4fdda8d27cac21714571adb0bfada6d96152aGeorge Sapountzis
295cae4fdda8d27cac21714571adb0bfada6d96152aGeorge Sapountzis   entry->name = name_dup;
296cae4fdda8d27cac21714571adb0bfada6d96152aGeorge Sapountzis   entry->parameter_signature = NULL;
297cae4fdda8d27cac21714571adb0bfada6d96152aGeorge Sapountzis   entry->dispatch_offset = ~0;
298cae4fdda8d27cac21714571adb0bfada6d96152aGeorge Sapountzis   entry->dispatch_stub = entrypoint;
299cae4fdda8d27cac21714571adb0bfada6d96152aGeorge Sapountzis
300a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul   return entry;
301a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul}
302a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul
303a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul
3043833a76eef6b45b82c102a49055602632f960a99George Sapountzisstatic struct _glapi_function *
3053833a76eef6b45b82c102a49055602632f960a99George Sapountzisset_entry_info( struct _glapi_function * entry, const char * signature, unsigned offset )
3063833a76eef6b45b82c102a49055602632f960a99George Sapountzis{
3073833a76eef6b45b82c102a49055602632f960a99George Sapountzis   char * sig_dup = NULL;
3083833a76eef6b45b82c102a49055602632f960a99George Sapountzis
3093833a76eef6b45b82c102a49055602632f960a99George Sapountzis   if (signature == NULL)
3103833a76eef6b45b82c102a49055602632f960a99George Sapountzis      return NULL;
3113833a76eef6b45b82c102a49055602632f960a99George Sapountzis
3123833a76eef6b45b82c102a49055602632f960a99George Sapountzis   sig_dup = str_dup(signature);
3133833a76eef6b45b82c102a49055602632f960a99George Sapountzis   if (sig_dup == NULL)
3143833a76eef6b45b82c102a49055602632f960a99George Sapountzis      return NULL;
3153833a76eef6b45b82c102a49055602632f960a99George Sapountzis
3163833a76eef6b45b82c102a49055602632f960a99George Sapountzis   fill_in_entrypoint_offset(entry->dispatch_stub, offset);
3173833a76eef6b45b82c102a49055602632f960a99George Sapountzis
3183833a76eef6b45b82c102a49055602632f960a99George Sapountzis   entry->parameter_signature = sig_dup;
3193833a76eef6b45b82c102a49055602632f960a99George Sapountzis   entry->dispatch_offset = offset;
3203833a76eef6b45b82c102a49055602632f960a99George Sapountzis
3213833a76eef6b45b82c102a49055602632f960a99George Sapountzis   return entry;
3223833a76eef6b45b82c102a49055602632f960a99George Sapountzis}
3233833a76eef6b45b82c102a49055602632f960a99George Sapountzis
3243833a76eef6b45b82c102a49055602632f960a99George Sapountzis
325a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul/**
326a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul * Fill-in the dispatch stub for the named function.
327a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul *
328a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul * This function is intended to be called by a hardware driver.  When called,
329a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul * a dispatch stub may be created created for the function.  A pointer to this
330a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul * dispatch function will be returned by glXGetProcAddress.
331a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul *
332a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul * \param function_names       Array of pointers to function names that should
333a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul *                             share a common dispatch offset.
334a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul * \param parameter_signature  String representing the types of the parameters
335a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul *                             passed to the named function.  Parameter types
336a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul *                             are converted to characters using the following
337a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul *                             rules:
338a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul *                               - 'i' for \c GLint, \c GLuint, and \c GLenum
339a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul *                               - 'p' for any pointer type
340a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul *                               - 'f' for \c GLfloat and \c GLclampf
341a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul *                               - 'd' for \c GLdouble and \c GLclampd
342a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul *
343a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul * \returns
344a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul * The offset in the dispatch table of the named function.  A pointer to the
345a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul * driver's implementation of the named function should be stored at
346a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul * \c dispatch_table[\c offset].  Return -1 if error/problem.
347a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul *
348a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul * \sa glXGetProcAddress
349a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul *
350a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul * \warning
351a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul * This function can only handle up to 8 names at a time.  As far as I know,
352a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul * the maximum number of names ever associated with an existing GL function is
353a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul * 4 (\c glPointParameterfSGIS, \c glPointParameterfEXT,
354a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul * \c glPointParameterfARB, and \c glPointParameterf), so this should not be
355a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul * too painful of a limitation.
356a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul *
357a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul * \todo
358a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul * Determine whether or not \c parameter_signature should be allowed to be
359a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul * \c NULL.  It doesn't seem like much of a hardship for drivers to have to
360a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul * pass in an empty string.
361a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul *
362a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul * \todo
363a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul * Determine if code should be added to reject function names that start with
364a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul * 'glX'.
365a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul *
366a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul * \bug
367a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul * Add code to compare \c parameter_signature with the parameter signature of
368a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul * a static function.  In order to do that, we need to find a way to \b get
369a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul * the parameter signature of a static function.
370a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul */
371a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul
372a73c6540d9a7f6e26d8568ba2fc522cb865f0a6cChia-I Wuint
373a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul_glapi_add_dispatch( const char * const * function_names,
374a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul		     const char * parameter_signature )
375a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul{
376e4dbfa44ed018d124e1531077d506c8c914c1a51Chia-I Wu   static int next_dynamic_offset = FIRST_DYNAMIC_OFFSET;
377a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul   const char * const real_sig = (parameter_signature != NULL)
378a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul     ? parameter_signature : "";
379a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul   struct _glapi_function * entry[8];
380a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul   GLboolean is_static[8];
381a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul   unsigned i;
382a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul   int offset = ~0;
383a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul
3847cd8f0ef9d905080dc857c4739be9780b24a7fd2George Sapountzis   init_glapi_relocs_once();
385a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul
386a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul   (void) memset( is_static, 0, sizeof( is_static ) );
387a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul   (void) memset( entry, 0, sizeof( entry ) );
388a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul
3890d1dde5b010feba1afe5b51cc6fe66c85371f70bGeorge Sapountzis   /* Find the _single_ dispatch offset for all function names that already
3900d1dde5b010feba1afe5b51cc6fe66c85371f70bGeorge Sapountzis    * exist (and have a dispatch offset).
3910d1dde5b010feba1afe5b51cc6fe66c85371f70bGeorge Sapountzis    */
3920d1dde5b010feba1afe5b51cc6fe66c85371f70bGeorge Sapountzis
393a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul   for ( i = 0 ; function_names[i] != NULL ; i++ ) {
394ddabf0a151c2ef318e5de45238556c6568540681George Sapountzis      const char * funcName = function_names[i];
395ddabf0a151c2ef318e5de45238556c6568540681George Sapountzis      int static_offset;
396ddabf0a151c2ef318e5de45238556c6568540681George Sapountzis      int extension_offset;
397a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul
398ddabf0a151c2ef318e5de45238556c6568540681George Sapountzis      if (funcName[0] != 'g' || funcName[1] != 'l')
399a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul         return -1;
400ddabf0a151c2ef318e5de45238556c6568540681George Sapountzis
401ddabf0a151c2ef318e5de45238556c6568540681George Sapountzis      /* search built-in functions */
402ddabf0a151c2ef318e5de45238556c6568540681George Sapountzis      static_offset = get_static_proc_offset(funcName);
403ddabf0a151c2ef318e5de45238556c6568540681George Sapountzis
404ddabf0a151c2ef318e5de45238556c6568540681George Sapountzis      if (static_offset >= 0) {
405ddabf0a151c2ef318e5de45238556c6568540681George Sapountzis
406ddabf0a151c2ef318e5de45238556c6568540681George Sapountzis	 is_static[i] = GL_TRUE;
407ddabf0a151c2ef318e5de45238556c6568540681George Sapountzis
408a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul	 /* FIXME: Make sure the parameter signatures match!  How do we get
409a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul	  * FIXME: the parameter signature for static functions?
410a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul	  */
411a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul
412ddabf0a151c2ef318e5de45238556c6568540681George Sapountzis	 if ( (offset != ~0) && (static_offset != offset) ) {
413a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul	    return -1;
414a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul	 }
415a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul
416ddabf0a151c2ef318e5de45238556c6568540681George Sapountzis	 offset = static_offset;
417bae31355150f66f7130d76a2ab4d4b735f239c71George Sapountzis
418bae31355150f66f7130d76a2ab4d4b735f239c71George Sapountzis	 continue;
419a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul      }
420ddabf0a151c2ef318e5de45238556c6568540681George Sapountzis
421ddabf0a151c2ef318e5de45238556c6568540681George Sapountzis      /* search added extension functions */
422ddabf0a151c2ef318e5de45238556c6568540681George Sapountzis      entry[i] = get_extension_proc(funcName);
423f9cc6b3ee7c95130992d67c080ff9bc8e8a6d789George Sapountzis
424f9cc6b3ee7c95130992d67c080ff9bc8e8a6d789George Sapountzis      if (entry[i] != NULL) {
425ddabf0a151c2ef318e5de45238556c6568540681George Sapountzis	 extension_offset = entry[i]->dispatch_offset;
426f9cc6b3ee7c95130992d67c080ff9bc8e8a6d789George Sapountzis
427ddabf0a151c2ef318e5de45238556c6568540681George Sapountzis	 /* The offset may be ~0 if the function name was added by
428ddabf0a151c2ef318e5de45238556c6568540681George Sapountzis	  * glXGetProcAddress but never filled in by the driver.
429ddabf0a151c2ef318e5de45238556c6568540681George Sapountzis	  */
430a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul
431ddabf0a151c2ef318e5de45238556c6568540681George Sapountzis	 if (extension_offset == ~0) {
432ddabf0a151c2ef318e5de45238556c6568540681George Sapountzis	    continue;
433ddabf0a151c2ef318e5de45238556c6568540681George Sapountzis	 }
434a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul
435ddabf0a151c2ef318e5de45238556c6568540681George Sapountzis	 if (strcmp(real_sig, entry[i]->parameter_signature) != 0) {
436ddabf0a151c2ef318e5de45238556c6568540681George Sapountzis	    return -1;
437ddabf0a151c2ef318e5de45238556c6568540681George Sapountzis	 }
438a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul
439ddabf0a151c2ef318e5de45238556c6568540681George Sapountzis	 if ( (offset != ~0) && (extension_offset != offset) ) {
440ddabf0a151c2ef318e5de45238556c6568540681George Sapountzis	    return -1;
441ddabf0a151c2ef318e5de45238556c6568540681George Sapountzis	 }
442ddabf0a151c2ef318e5de45238556c6568540681George Sapountzis
443ddabf0a151c2ef318e5de45238556c6568540681George Sapountzis	 offset = extension_offset;
444a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul      }
445a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul   }
446a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul
4470d1dde5b010feba1afe5b51cc6fe66c85371f70bGeorge Sapountzis   /* If all function names are either new (or with no dispatch offset),
4480d1dde5b010feba1afe5b51cc6fe66c85371f70bGeorge Sapountzis    * allocate a new dispatch offset.
4490d1dde5b010feba1afe5b51cc6fe66c85371f70bGeorge Sapountzis    */
4500d1dde5b010feba1afe5b51cc6fe66c85371f70bGeorge Sapountzis
451a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul   if (offset == ~0) {
452a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul      offset = next_dynamic_offset;
453a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul      next_dynamic_offset++;
454a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul   }
455a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul
4560d1dde5b010feba1afe5b51cc6fe66c85371f70bGeorge Sapountzis   /* Fill in the dispatch offset for the new function names (and those with
4570d1dde5b010feba1afe5b51cc6fe66c85371f70bGeorge Sapountzis    * no dispatch offset).
4580d1dde5b010feba1afe5b51cc6fe66c85371f70bGeorge Sapountzis    */
4590d1dde5b010feba1afe5b51cc6fe66c85371f70bGeorge Sapountzis
460a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul   for ( i = 0 ; function_names[i] != NULL ; i++ ) {
461c4b630efdb882f824e9099b9cb2e07d8db2e3549George Sapountzis      if (is_static[i]) {
462c4b630efdb882f824e9099b9cb2e07d8db2e3549George Sapountzis	 continue;
463c4b630efdb882f824e9099b9cb2e07d8db2e3549George Sapountzis      }
464c4b630efdb882f824e9099b9cb2e07d8db2e3549George Sapountzis
4650d1dde5b010feba1afe5b51cc6fe66c85371f70bGeorge Sapountzis      /* generate entrypoints for new function names */
466c4b630efdb882f824e9099b9cb2e07d8db2e3549George Sapountzis      if (entry[i] == NULL) {
467c4b630efdb882f824e9099b9cb2e07d8db2e3549George Sapountzis	 entry[i] = add_function_name( function_names[i] );
468a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul	 if (entry[i] == NULL) {
469c4b630efdb882f824e9099b9cb2e07d8db2e3549George Sapountzis	    /* FIXME: Possible memory leak here. */
470c4b630efdb882f824e9099b9cb2e07d8db2e3549George Sapountzis	    return -1;
471a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul	 }
472a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul      }
473c4b630efdb882f824e9099b9cb2e07d8db2e3549George Sapountzis
474bae31355150f66f7130d76a2ab4d4b735f239c71George Sapountzis      if (entry[i]->dispatch_offset == ~0) {
475bae31355150f66f7130d76a2ab4d4b735f239c71George Sapountzis	 set_entry_info( entry[i], real_sig, offset );
476bae31355150f66f7130d76a2ab4d4b735f239c71George Sapountzis      }
477a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul   }
478c4b630efdb882f824e9099b9cb2e07d8db2e3549George Sapountzis
479a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul   return offset;
480a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul}
481a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul
482a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul
483a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul/**
484a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul * Return offset of entrypoint for named function within dispatch table.
485a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul */
486a73c6540d9a7f6e26d8568ba2fc522cb865f0a6cChia-I WuGLint
487a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul_glapi_get_proc_offset(const char *funcName)
488a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul{
48958985c36be85c668d059165d8282f8c8e4c7a380George Sapountzis   GLint offset;
49058985c36be85c668d059165d8282f8c8e4c7a380George Sapountzis
491a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul   /* search extension functions first */
49258985c36be85c668d059165d8282f8c8e4c7a380George Sapountzis   offset = get_extension_proc_offset(funcName);
49358985c36be85c668d059165d8282f8c8e4c7a380George Sapountzis   if (offset >= 0)
49458985c36be85c668d059165d8282f8c8e4c7a380George Sapountzis      return offset;
49558985c36be85c668d059165d8282f8c8e4c7a380George Sapountzis
496a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul   /* search static functions */
497a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul   return get_static_proc_offset(funcName);
498a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul}
499a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul
500a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul
501a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul
502a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul/**
503a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul * Return pointer to the named function.  If the function name isn't found
504a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul * in the name of static functions, try generating a new API entrypoint on
505a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul * the fly with assembly language.
506a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul */
507a73c6540d9a7f6e26d8568ba2fc522cb865f0a6cChia-I Wu_glapi_proc
508a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul_glapi_get_proc_address(const char *funcName)
509a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul{
51058985c36be85c668d059165d8282f8c8e4c7a380George Sapountzis   _glapi_proc func;
511a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul   struct _glapi_function * entry;
512a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul
5137cd8f0ef9d905080dc857c4739be9780b24a7fd2George Sapountzis   init_glapi_relocs_once();
5147cd8f0ef9d905080dc857c4739be9780b24a7fd2George Sapountzis
515a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul#ifdef MANGLE
51620ed2445b3b98f2b49a26ad4b45859a908583311George Sapountzis   /* skip the prefix on the name */
51720ed2445b3b98f2b49a26ad4b45859a908583311George Sapountzis   if (funcName[1] != 'g' || funcName[2] != 'l')
518a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul      return NULL;
519a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul#else
520a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul   if (funcName[0] != 'g' || funcName[1] != 'l')
521a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul      return NULL;
522a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul#endif
523a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul
524a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul   /* search extension functions first */
52558985c36be85c668d059165d8282f8c8e4c7a380George Sapountzis   func = get_extension_proc_address(funcName);
52658985c36be85c668d059165d8282f8c8e4c7a380George Sapountzis   if (func)
52758985c36be85c668d059165d8282f8c8e4c7a380George Sapountzis      return func;
528a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul
529a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul   /* search static functions */
530f0c18da2cf01bc11dc720caed4590ae7eca128f1George Sapountzis   func = get_static_proc_address(funcName);
531f0c18da2cf01bc11dc720caed4590ae7eca128f1George Sapountzis   if (func)
532f0c18da2cf01bc11dc720caed4590ae7eca128f1George Sapountzis      return func;
533a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul
5340d1dde5b010feba1afe5b51cc6fe66c85371f70bGeorge Sapountzis   /* generate entrypoint, dispatch offset must be filled in by the driver */
535a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul   entry = add_function_name(funcName);
5360d1dde5b010feba1afe5b51cc6fe66c85371f70bGeorge Sapountzis   if (entry == NULL)
5370d1dde5b010feba1afe5b51cc6fe66c85371f70bGeorge Sapountzis      return NULL;
5380d1dde5b010feba1afe5b51cc6fe66c85371f70bGeorge Sapountzis
5390d1dde5b010feba1afe5b51cc6fe66c85371f70bGeorge Sapountzis   return entry->dispatch_stub;
540a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul}
541a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul
542a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul
543a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul
544a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul/**
545a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul * Return the name of the function at the given dispatch offset.
546a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul * This is only intended for debugging.
547a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul */
548a97226352fb8063d4d0084523312b4880dae5ac7Brian Paulconst char *
549a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul_glapi_get_proc_name(GLuint offset)
550a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul{
551a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul   const char * n;
552a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul
553a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul   /* search built-in functions */
554a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul   n = get_static_proc_name(offset);
555a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul   if ( n != NULL ) {
556a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul      return n;
557a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul   }
558a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul
559a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul   /* search added extension functions */
56058985c36be85c668d059165d8282f8c8e4c7a380George Sapountzis   return get_extension_proc_name(offset);
561a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul}
562fae5758fac963ce014e3d43f1bca7fb489e02bf9George Sapountzis
563fae5758fac963ce014e3d43f1bca7fb489e02bf9George Sapountzis
564fae5758fac963ce014e3d43f1bca7fb489e02bf9George Sapountzis
5652c8b5ffed9a787e896b540a95be48ef401d5f007George Sapountzis/**********************************************************************
5662c8b5ffed9a787e896b540a95be48ef401d5f007George Sapountzis * GL API table functions.
5672c8b5ffed9a787e896b540a95be48ef401d5f007George Sapountzis */
5682c8b5ffed9a787e896b540a95be48ef401d5f007George Sapountzis
5692c8b5ffed9a787e896b540a95be48ef401d5f007George Sapountzis
5702c8b5ffed9a787e896b540a95be48ef401d5f007George Sapountzis/**
5712c8b5ffed9a787e896b540a95be48ef401d5f007George Sapountzis * Return size of dispatch table struct as number of functions (or
5722c8b5ffed9a787e896b540a95be48ef401d5f007George Sapountzis * slots).
5732c8b5ffed9a787e896b540a95be48ef401d5f007George Sapountzis */
574a73c6540d9a7f6e26d8568ba2fc522cb865f0a6cChia-I WuGLuint
5752c8b5ffed9a787e896b540a95be48ef401d5f007George Sapountzis_glapi_get_dispatch_table_size(void)
5762c8b5ffed9a787e896b540a95be48ef401d5f007George Sapountzis{
577e4dbfa44ed018d124e1531077d506c8c914c1a51Chia-I Wu   /*
578e4dbfa44ed018d124e1531077d506c8c914c1a51Chia-I Wu    * The dispatch table size (number of entries) is the size of the
579e4dbfa44ed018d124e1531077d506c8c914c1a51Chia-I Wu    * _glapi_table struct plus the number of dynamic entries we can add.
580e4dbfa44ed018d124e1531077d506c8c914c1a51Chia-I Wu    * The extra slots can be filled in by DRI drivers that register new
581e4dbfa44ed018d124e1531077d506c8c914c1a51Chia-I Wu    * extension functions.
582e4dbfa44ed018d124e1531077d506c8c914c1a51Chia-I Wu    */
583e4dbfa44ed018d124e1531077d506c8c914c1a51Chia-I Wu   return FIRST_DYNAMIC_OFFSET + MAX_EXTENSION_FUNCS;
5842c8b5ffed9a787e896b540a95be48ef401d5f007George Sapountzis}
5852c8b5ffed9a787e896b540a95be48ef401d5f007George Sapountzis
5862c8b5ffed9a787e896b540a95be48ef401d5f007George Sapountzis
5872c8b5ffed9a787e896b540a95be48ef401d5f007George Sapountzis/**
5882c8b5ffed9a787e896b540a95be48ef401d5f007George Sapountzis * Make sure there are no NULL pointers in the given dispatch table.
5892c8b5ffed9a787e896b540a95be48ef401d5f007George Sapountzis * Intended for debugging purposes.
5902c8b5ffed9a787e896b540a95be48ef401d5f007George Sapountzis */
5912c8b5ffed9a787e896b540a95be48ef401d5f007George Sapountzisvoid
5922c8b5ffed9a787e896b540a95be48ef401d5f007George Sapountzis_glapi_check_table_not_null(const struct _glapi_table *table)
5932c8b5ffed9a787e896b540a95be48ef401d5f007George Sapountzis{
5942c8b5ffed9a787e896b540a95be48ef401d5f007George Sapountzis#ifdef EXTRA_DEBUG /* set to DEBUG for extra DEBUG */
5952c8b5ffed9a787e896b540a95be48ef401d5f007George Sapountzis   const GLuint entries = _glapi_get_dispatch_table_size();
5962c8b5ffed9a787e896b540a95be48ef401d5f007George Sapountzis   const void **tab = (const void **) table;
5972c8b5ffed9a787e896b540a95be48ef401d5f007George Sapountzis   GLuint i;
5982c8b5ffed9a787e896b540a95be48ef401d5f007George Sapountzis   for (i = 1; i < entries; i++) {
5992c8b5ffed9a787e896b540a95be48ef401d5f007George Sapountzis      assert(tab[i]);
6002c8b5ffed9a787e896b540a95be48ef401d5f007George Sapountzis   }
6012c8b5ffed9a787e896b540a95be48ef401d5f007George Sapountzis#else
6022c8b5ffed9a787e896b540a95be48ef401d5f007George Sapountzis   (void) table;
6032c8b5ffed9a787e896b540a95be48ef401d5f007George Sapountzis#endif
6042c8b5ffed9a787e896b540a95be48ef401d5f007George Sapountzis}
6052c8b5ffed9a787e896b540a95be48ef401d5f007George Sapountzis
6062c8b5ffed9a787e896b540a95be48ef401d5f007George Sapountzis
607fae5758fac963ce014e3d43f1bca7fb489e02bf9George Sapountzis/**
608fae5758fac963ce014e3d43f1bca7fb489e02bf9George Sapountzis * Do some spot checks to be sure that the dispatch table
609fae5758fac963ce014e3d43f1bca7fb489e02bf9George Sapountzis * slots are assigned correctly. For debugging only.
610fae5758fac963ce014e3d43f1bca7fb489e02bf9George Sapountzis */
611fae5758fac963ce014e3d43f1bca7fb489e02bf9George Sapountzisvoid
612fae5758fac963ce014e3d43f1bca7fb489e02bf9George Sapountzis_glapi_check_table(const struct _glapi_table *table)
613fae5758fac963ce014e3d43f1bca7fb489e02bf9George Sapountzis{
6142c8b5ffed9a787e896b540a95be48ef401d5f007George Sapountzis#ifdef EXTRA_DEBUG /* set to DEBUG for extra DEBUG */
615fae5758fac963ce014e3d43f1bca7fb489e02bf9George Sapountzis   {
616fae5758fac963ce014e3d43f1bca7fb489e02bf9George Sapountzis      GLuint BeginOffset = _glapi_get_proc_offset("glBegin");
617fae5758fac963ce014e3d43f1bca7fb489e02bf9George Sapountzis      char *BeginFunc = (char*) &table->Begin;
618fae5758fac963ce014e3d43f1bca7fb489e02bf9George Sapountzis      GLuint offset = (BeginFunc - (char *) table) / sizeof(void *);
619fae5758fac963ce014e3d43f1bca7fb489e02bf9George Sapountzis      assert(BeginOffset == offset);
620fae5758fac963ce014e3d43f1bca7fb489e02bf9George Sapountzis   }
621fae5758fac963ce014e3d43f1bca7fb489e02bf9George Sapountzis   {
622fae5758fac963ce014e3d43f1bca7fb489e02bf9George Sapountzis      GLuint viewportOffset = _glapi_get_proc_offset("glViewport");
623fae5758fac963ce014e3d43f1bca7fb489e02bf9George Sapountzis      char *viewportFunc = (char*) &table->Viewport;
624fae5758fac963ce014e3d43f1bca7fb489e02bf9George Sapountzis      GLuint offset = (viewportFunc - (char *) table) / sizeof(void *);
625fae5758fac963ce014e3d43f1bca7fb489e02bf9George Sapountzis      assert(viewportOffset == offset);
626fae5758fac963ce014e3d43f1bca7fb489e02bf9George Sapountzis   }
627fae5758fac963ce014e3d43f1bca7fb489e02bf9George Sapountzis   {
628fae5758fac963ce014e3d43f1bca7fb489e02bf9George Sapountzis      GLuint VertexPointerOffset = _glapi_get_proc_offset("glVertexPointer");
629fae5758fac963ce014e3d43f1bca7fb489e02bf9George Sapountzis      char *VertexPointerFunc = (char*) &table->VertexPointer;
630fae5758fac963ce014e3d43f1bca7fb489e02bf9George Sapountzis      GLuint offset = (VertexPointerFunc - (char *) table) / sizeof(void *);
631fae5758fac963ce014e3d43f1bca7fb489e02bf9George Sapountzis      assert(VertexPointerOffset == offset);
632fae5758fac963ce014e3d43f1bca7fb489e02bf9George Sapountzis   }
633fae5758fac963ce014e3d43f1bca7fb489e02bf9George Sapountzis   {
634fae5758fac963ce014e3d43f1bca7fb489e02bf9George Sapountzis      GLuint ResetMinMaxOffset = _glapi_get_proc_offset("glResetMinmax");
635fae5758fac963ce014e3d43f1bca7fb489e02bf9George Sapountzis      char *ResetMinMaxFunc = (char*) &table->ResetMinmax;
636fae5758fac963ce014e3d43f1bca7fb489e02bf9George Sapountzis      GLuint offset = (ResetMinMaxFunc - (char *) table) / sizeof(void *);
637fae5758fac963ce014e3d43f1bca7fb489e02bf9George Sapountzis      assert(ResetMinMaxOffset == offset);
638fae5758fac963ce014e3d43f1bca7fb489e02bf9George Sapountzis   }
639fae5758fac963ce014e3d43f1bca7fb489e02bf9George Sapountzis   {
640fae5758fac963ce014e3d43f1bca7fb489e02bf9George Sapountzis      GLuint blendColorOffset = _glapi_get_proc_offset("glBlendColor");
641fae5758fac963ce014e3d43f1bca7fb489e02bf9George Sapountzis      char *blendColorFunc = (char*) &table->BlendColor;
642fae5758fac963ce014e3d43f1bca7fb489e02bf9George Sapountzis      GLuint offset = (blendColorFunc - (char *) table) / sizeof(void *);
643fae5758fac963ce014e3d43f1bca7fb489e02bf9George Sapountzis      assert(blendColorOffset == offset);
644fae5758fac963ce014e3d43f1bca7fb489e02bf9George Sapountzis   }
645fae5758fac963ce014e3d43f1bca7fb489e02bf9George Sapountzis   {
646fae5758fac963ce014e3d43f1bca7fb489e02bf9George Sapountzis      GLuint secondaryColor3fOffset = _glapi_get_proc_offset("glSecondaryColor3fEXT");
647fae5758fac963ce014e3d43f1bca7fb489e02bf9George Sapountzis      char *secondaryColor3fFunc = (char*) &table->SecondaryColor3fEXT;
648fae5758fac963ce014e3d43f1bca7fb489e02bf9George Sapountzis      GLuint offset = (secondaryColor3fFunc - (char *) table) / sizeof(void *);
649fae5758fac963ce014e3d43f1bca7fb489e02bf9George Sapountzis      assert(secondaryColor3fOffset == offset);
650fae5758fac963ce014e3d43f1bca7fb489e02bf9George Sapountzis   }
651fae5758fac963ce014e3d43f1bca7fb489e02bf9George Sapountzis   {
652fae5758fac963ce014e3d43f1bca7fb489e02bf9George Sapountzis      GLuint pointParameterivOffset = _glapi_get_proc_offset("glPointParameterivNV");
653fae5758fac963ce014e3d43f1bca7fb489e02bf9George Sapountzis      char *pointParameterivFunc = (char*) &table->PointParameterivNV;
654fae5758fac963ce014e3d43f1bca7fb489e02bf9George Sapountzis      GLuint offset = (pointParameterivFunc - (char *) table) / sizeof(void *);
655fae5758fac963ce014e3d43f1bca7fb489e02bf9George Sapountzis      assert(pointParameterivOffset == offset);
656fae5758fac963ce014e3d43f1bca7fb489e02bf9George Sapountzis   }
657fae5758fac963ce014e3d43f1bca7fb489e02bf9George Sapountzis   {
658fae5758fac963ce014e3d43f1bca7fb489e02bf9George Sapountzis      GLuint setFenceOffset = _glapi_get_proc_offset("glSetFenceNV");
659fae5758fac963ce014e3d43f1bca7fb489e02bf9George Sapountzis      char *setFenceFunc = (char*) &table->SetFenceNV;
660fae5758fac963ce014e3d43f1bca7fb489e02bf9George Sapountzis      GLuint offset = (setFenceFunc - (char *) table) / sizeof(void *);
661fae5758fac963ce014e3d43f1bca7fb489e02bf9George Sapountzis      assert(setFenceOffset == offset);
662fae5758fac963ce014e3d43f1bca7fb489e02bf9George Sapountzis   }
663d3f24ab33c284325abaf4b250f8928d4d53836e1George Sapountzis#else
664d3f24ab33c284325abaf4b250f8928d4d53836e1George Sapountzis   (void) table;
665d3f24ab33c284325abaf4b250f8928d4d53836e1George Sapountzis#endif
666fae5758fac963ce014e3d43f1bca7fb489e02bf9George Sapountzis}
667