glapi_getproc.c revision a73c6540d9a7f6e26d8568ba2fc522cb865f0a6c
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
33ec91810147425f4123ec80117109925e054cc66dGeorge Sapountzis#ifdef HAVE_DIX_CONFIG_H
34ec91810147425f4123ec80117109925e054cc66dGeorge Sapountzis#include <dix-config.h>
35ec91810147425f4123ec80117109925e054cc66dGeorge Sapountzis#include "glapi/mesa.h"
36ec91810147425f4123ec80117109925e054cc66dGeorge Sapountzis#else
378e7d941d7a29aaf66f94892b3f97670c0e972c8cKeith Whitwell#include "main/glheader.h"
38f2c023291a1f2887294d2aac504f8b82857ad092Brian Paul#include "main/compiler.h"
39ec91810147425f4123ec80117109925e054cc66dGeorge Sapountzis#endif
40ec91810147425f4123ec80117109925e054cc66dGeorge Sapountzis
415b426288c2dbc42ef44ea13fe37afa77223107bbChia-I Wu#include "glapi/glapi.h"
422c8b5ffed9a787e896b540a95be48ef401d5f007George Sapountzis#include "glapi/glapi_priv.h"
435b426288c2dbc42ef44ea13fe37afa77223107bbChia-I Wu#include "glapi/glapitable.h"
442c8b5ffed9a787e896b540a95be48ef401d5f007George Sapountzis#include "glapi/glapioffsets.h"
45a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul
46a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul
47f0c18da2cf01bc11dc720caed4590ae7eca128f1George Sapountzis/**********************************************************************
48f0c18da2cf01bc11dc720caed4590ae7eca128f1George Sapountzis * Static function management.
49f0c18da2cf01bc11dc720caed4590ae7eca128f1George Sapountzis */
50f0c18da2cf01bc11dc720caed4590ae7eca128f1George Sapountzis
51f0c18da2cf01bc11dc720caed4590ae7eca128f1George Sapountzis
52fe14868d96d4820dba73c3a507d191b8a73c6870George Sapountzis#if !defined(DISPATCH_FUNCTION_SIZE) && !defined(XFree86Server)
53a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul# define NEED_FUNCTION_POINTER
54a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul#endif
555b426288c2dbc42ef44ea13fe37afa77223107bbChia-I Wu#include "glapi/glprocs.h"
56a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul
57a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul
58a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul/**
59a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul * Search the table of static entrypoint functions for the named function
60a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul * and return the corresponding glprocs_table_t entry.
61a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul */
62a97226352fb8063d4d0084523312b4880dae5ac7Brian Paulstatic const glprocs_table_t *
63f0c18da2cf01bc11dc720caed4590ae7eca128f1George Sapountzisget_static_proc( const char * n )
64a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul{
65a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul   GLuint i;
66a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul   for (i = 0; static_functions[i].Name_offset >= 0; i++) {
67a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul      const char *testName = gl_string_table + static_functions[i].Name_offset;
684447fddc82a2c0245e798c90492293d875d186d0Brian Paul#ifdef MANGLE
6920ed2445b3b98f2b49a26ad4b45859a908583311George Sapountzis      /* skip the prefix on the name */
704447fddc82a2c0245e798c90492293d875d186d0Brian Paul      if (strcmp(testName, n + 1) == 0)
714447fddc82a2c0245e798c90492293d875d186d0Brian Paul#else
724447fddc82a2c0245e798c90492293d875d186d0Brian Paul      if (strcmp(testName, n) == 0)
734447fddc82a2c0245e798c90492293d875d186d0Brian Paul#endif
744447fddc82a2c0245e798c90492293d875d186d0Brian Paul      {
75a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul	 return &static_functions[i];
76a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul      }
77a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul   }
78a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul   return NULL;
79a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul}
80a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul
81a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul
82a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul/**
83a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul * Return dispatch table offset of the named static (built-in) function.
84a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul * Return -1 if function not found.
85a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul */
86a97226352fb8063d4d0084523312b4880dae5ac7Brian Paulstatic GLint
87a97226352fb8063d4d0084523312b4880dae5ac7Brian Paulget_static_proc_offset(const char *funcName)
88a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul{
89f0c18da2cf01bc11dc720caed4590ae7eca128f1George Sapountzis   const glprocs_table_t * const f = get_static_proc( funcName );
90f0c18da2cf01bc11dc720caed4590ae7eca128f1George Sapountzis   if (f == NULL) {
91f0c18da2cf01bc11dc720caed4590ae7eca128f1George Sapountzis      return -1;
92a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul   }
93f0c18da2cf01bc11dc720caed4590ae7eca128f1George Sapountzis
94f0c18da2cf01bc11dc720caed4590ae7eca128f1George Sapountzis   return f->Offset;
95a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul}
96a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul
97a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul
98fe14868d96d4820dba73c3a507d191b8a73c6870George Sapountzis#if !defined(XFree86Server)
99cccdc1783fda33da6fc12befdf288b74866e5dfaGeorge Sapountzis
100a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul/**
101a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul * Return dispatch function address for the named static (built-in) function.
102a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul * Return NULL if function not found.
103a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul */
104a97226352fb8063d4d0084523312b4880dae5ac7Brian Paulstatic _glapi_proc
105a97226352fb8063d4d0084523312b4880dae5ac7Brian Paulget_static_proc_address(const char *funcName)
106a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul{
107f0c18da2cf01bc11dc720caed4590ae7eca128f1George Sapountzis   const glprocs_table_t * const f = get_static_proc( funcName );
108f0c18da2cf01bc11dc720caed4590ae7eca128f1George Sapountzis   if (f == NULL) {
109f0c18da2cf01bc11dc720caed4590ae7eca128f1George Sapountzis      return NULL;
110f0c18da2cf01bc11dc720caed4590ae7eca128f1George Sapountzis   }
111f0c18da2cf01bc11dc720caed4590ae7eca128f1George Sapountzis
112a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul#if defined(DISPATCH_FUNCTION_SIZE) && defined(GLX_INDIRECT_RENDERING)
113f0c18da2cf01bc11dc720caed4590ae7eca128f1George Sapountzis   return (f->Address == NULL)
114f0c18da2cf01bc11dc720caed4590ae7eca128f1George Sapountzis      ? get_entrypoint_address(f->Offset)
115f0c18da2cf01bc11dc720caed4590ae7eca128f1George Sapountzis      : f->Address;
116a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul#elif defined(DISPATCH_FUNCTION_SIZE)
117f0c18da2cf01bc11dc720caed4590ae7eca128f1George Sapountzis   return get_entrypoint_address(f->Offset);
118a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul#else
119f0c18da2cf01bc11dc720caed4590ae7eca128f1George Sapountzis   return f->Address;
120a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul#endif
121a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul}
122a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul
123f0c18da2cf01bc11dc720caed4590ae7eca128f1George Sapountzis#else
124a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul
125f0c18da2cf01bc11dc720caed4590ae7eca128f1George Sapountzisstatic _glapi_proc
126f0c18da2cf01bc11dc720caed4590ae7eca128f1George Sapountzisget_static_proc_address(const char *funcName)
127f0c18da2cf01bc11dc720caed4590ae7eca128f1George Sapountzis{
128f0c18da2cf01bc11dc720caed4590ae7eca128f1George Sapountzis   (void) funcName;
129f0c18da2cf01bc11dc720caed4590ae7eca128f1George Sapountzis   return NULL;
130f0c18da2cf01bc11dc720caed4590ae7eca128f1George Sapountzis}
131f0c18da2cf01bc11dc720caed4590ae7eca128f1George Sapountzis
132f0c18da2cf01bc11dc720caed4590ae7eca128f1George Sapountzis#endif /* !defined(XFree86Server) */
133a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul
134a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul
135a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul/**
136a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul * Return the name of the function at the given offset in the dispatch
137a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul * table.  For debugging only.
138a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul */
139a97226352fb8063d4d0084523312b4880dae5ac7Brian Paulstatic const char *
140a97226352fb8063d4d0084523312b4880dae5ac7Brian Paulget_static_proc_name( GLuint offset )
141a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul{
142a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul   GLuint i;
143a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul   for (i = 0; static_functions[i].Name_offset >= 0; i++) {
144a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul      if (static_functions[i].Offset == offset) {
145a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul	 return gl_string_table + static_functions[i].Name_offset;
146a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul      }
147a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul   }
148a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul   return NULL;
149a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul}
150a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul
151a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul
152a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul
153a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul/**********************************************************************
154a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul * Extension function management.
155a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul */
156a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul
157a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul
158a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul/**
159a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul * Track information about a function added to the GL API.
160a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul */
161a97226352fb8063d4d0084523312b4880dae5ac7Brian Paulstruct _glapi_function {
162a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul   /**
163a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul    * Name of the function.
164a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul    */
165a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul   const char * name;
166a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul
167a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul
168a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul   /**
169a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul    * Text string that describes the types of the parameters passed to the
170a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul    * named function.   Parameter types are converted to characters using the
171a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul    * following rules:
172a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul    *   - 'i' for \c GLint, \c GLuint, and \c GLenum
173a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul    *   - 'p' for any pointer type
174a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul    *   - 'f' for \c GLfloat and \c GLclampf
175a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul    *   - 'd' for \c GLdouble and \c GLclampd
176a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul    */
177a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul   const char * parameter_signature;
178a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul
179a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul
180a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul   /**
181a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul    * Offset in the dispatch table where the pointer to the real function is
182a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul    * located.  If the driver has not requested that the named function be
183a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul    * added to the dispatch table, this will have the value ~0.
184a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul    */
185a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul   unsigned dispatch_offset;
186a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul
187a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul
188a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul   /**
189a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul    * Pointer to the dispatch stub for the named function.
190a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul    *
191a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul    * \todo
192a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul    * The semantic of this field should be changed slightly.  Currently, it
193a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul    * is always expected to be non-\c NULL.  However, it would be better to
194a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul    * only allocate the entry-point stub when the application requests the
195a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul    * function via \c glXGetProcAddress.  This would save memory for all the
196a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul    * functions that the driver exports but that the application never wants
197a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul    * to call.
198a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul    */
199a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul   _glapi_proc dispatch_stub;
200a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul};
201a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul
202a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul
203a97226352fb8063d4d0084523312b4880dae5ac7Brian Paulstatic struct _glapi_function ExtEntryTable[MAX_EXTENSION_FUNCS];
204a97226352fb8063d4d0084523312b4880dae5ac7Brian Paulstatic GLuint NumExtEntryPoints = 0;
205a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul
206a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul
2075b2340c493cdf8d776e717b00acf0a8002858976George Sapountzisstatic struct _glapi_function *
2085b2340c493cdf8d776e717b00acf0a8002858976George Sapountzisget_extension_proc(const char *funcName)
20958985c36be85c668d059165d8282f8c8e4c7a380George Sapountzis{
21058985c36be85c668d059165d8282f8c8e4c7a380George Sapountzis   GLuint i;
21158985c36be85c668d059165d8282f8c8e4c7a380George Sapountzis   for (i = 0; i < NumExtEntryPoints; i++) {
21258985c36be85c668d059165d8282f8c8e4c7a380George Sapountzis      if (strcmp(ExtEntryTable[i].name, funcName) == 0) {
2135b2340c493cdf8d776e717b00acf0a8002858976George Sapountzis         return & ExtEntryTable[i];
21458985c36be85c668d059165d8282f8c8e4c7a380George Sapountzis      }
21558985c36be85c668d059165d8282f8c8e4c7a380George Sapountzis   }
2165b2340c493cdf8d776e717b00acf0a8002858976George Sapountzis   return NULL;
2175b2340c493cdf8d776e717b00acf0a8002858976George Sapountzis}
2185b2340c493cdf8d776e717b00acf0a8002858976George Sapountzis
2195b2340c493cdf8d776e717b00acf0a8002858976George Sapountzis
2205b2340c493cdf8d776e717b00acf0a8002858976George Sapountzisstatic GLint
2215b2340c493cdf8d776e717b00acf0a8002858976George Sapountzisget_extension_proc_offset(const char *funcName)
2225b2340c493cdf8d776e717b00acf0a8002858976George Sapountzis{
2235b2340c493cdf8d776e717b00acf0a8002858976George Sapountzis   const struct _glapi_function * const f = get_extension_proc( funcName );
2245b2340c493cdf8d776e717b00acf0a8002858976George Sapountzis   if (f == NULL) {
2255b2340c493cdf8d776e717b00acf0a8002858976George Sapountzis      return -1;
2265b2340c493cdf8d776e717b00acf0a8002858976George Sapountzis   }
2275b2340c493cdf8d776e717b00acf0a8002858976George Sapountzis
2285b2340c493cdf8d776e717b00acf0a8002858976George Sapountzis   return f->dispatch_offset;
22958985c36be85c668d059165d8282f8c8e4c7a380George Sapountzis}
23058985c36be85c668d059165d8282f8c8e4c7a380George Sapountzis
23158985c36be85c668d059165d8282f8c8e4c7a380George Sapountzis
23258985c36be85c668d059165d8282f8c8e4c7a380George Sapountzisstatic _glapi_proc
23358985c36be85c668d059165d8282f8c8e4c7a380George Sapountzisget_extension_proc_address(const char *funcName)
23458985c36be85c668d059165d8282f8c8e4c7a380George Sapountzis{
2355b2340c493cdf8d776e717b00acf0a8002858976George Sapountzis   const struct _glapi_function * const f = get_extension_proc( funcName );
2365b2340c493cdf8d776e717b00acf0a8002858976George Sapountzis   if (f == NULL) {
2375b2340c493cdf8d776e717b00acf0a8002858976George Sapountzis      return NULL;
23858985c36be85c668d059165d8282f8c8e4c7a380George Sapountzis   }
2395b2340c493cdf8d776e717b00acf0a8002858976George Sapountzis
2405b2340c493cdf8d776e717b00acf0a8002858976George Sapountzis   return f->dispatch_stub;
24158985c36be85c668d059165d8282f8c8e4c7a380George Sapountzis}
24258985c36be85c668d059165d8282f8c8e4c7a380George Sapountzis
24358985c36be85c668d059165d8282f8c8e4c7a380George Sapountzis
24458985c36be85c668d059165d8282f8c8e4c7a380George Sapountzisstatic const char *
24558985c36be85c668d059165d8282f8c8e4c7a380George Sapountzisget_extension_proc_name(GLuint offset)
24658985c36be85c668d059165d8282f8c8e4c7a380George Sapountzis{
24758985c36be85c668d059165d8282f8c8e4c7a380George Sapountzis   GLuint i;
24858985c36be85c668d059165d8282f8c8e4c7a380George Sapountzis   for (i = 0; i < NumExtEntryPoints; i++) {
24958985c36be85c668d059165d8282f8c8e4c7a380George Sapountzis      if (ExtEntryTable[i].dispatch_offset == offset) {
25058985c36be85c668d059165d8282f8c8e4c7a380George Sapountzis         return ExtEntryTable[i].name;
25158985c36be85c668d059165d8282f8c8e4c7a380George Sapountzis      }
25258985c36be85c668d059165d8282f8c8e4c7a380George Sapountzis   }
25358985c36be85c668d059165d8282f8c8e4c7a380George Sapountzis   return NULL;
25458985c36be85c668d059165d8282f8c8e4c7a380George Sapountzis}
25558985c36be85c668d059165d8282f8c8e4c7a380George Sapountzis
25658985c36be85c668d059165d8282f8c8e4c7a380George Sapountzis
257a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul/**
258cccdc1783fda33da6fc12befdf288b74866e5dfaGeorge Sapountzis * strdup() is actually not a standard ANSI C or POSIX routine.
259cccdc1783fda33da6fc12befdf288b74866e5dfaGeorge Sapountzis * Irix will not define it if ANSI mode is in effect.
260cccdc1783fda33da6fc12befdf288b74866e5dfaGeorge Sapountzis */
261cccdc1783fda33da6fc12befdf288b74866e5dfaGeorge Sapountzisstatic char *
262cccdc1783fda33da6fc12befdf288b74866e5dfaGeorge Sapountzisstr_dup(const char *str)
263cccdc1783fda33da6fc12befdf288b74866e5dfaGeorge Sapountzis{
264cccdc1783fda33da6fc12befdf288b74866e5dfaGeorge Sapountzis   char *copy;
265cccdc1783fda33da6fc12befdf288b74866e5dfaGeorge Sapountzis   copy = (char*) malloc(strlen(str) + 1);
266cccdc1783fda33da6fc12befdf288b74866e5dfaGeorge Sapountzis   if (!copy)
267cccdc1783fda33da6fc12befdf288b74866e5dfaGeorge Sapountzis      return NULL;
2686405ecb399a52e4d3fe0c002bcd9b3485cbd1360Brian Paul   strcpy(copy, str);
269cccdc1783fda33da6fc12befdf288b74866e5dfaGeorge Sapountzis   return copy;
270cccdc1783fda33da6fc12befdf288b74866e5dfaGeorge Sapountzis}
271cccdc1783fda33da6fc12befdf288b74866e5dfaGeorge Sapountzis
272cccdc1783fda33da6fc12befdf288b74866e5dfaGeorge Sapountzis
273cccdc1783fda33da6fc12befdf288b74866e5dfaGeorge Sapountzis/**
274a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul * Generate new entrypoint
275a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul *
276a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul * Use a temporary dispatch offset of ~0 (i.e. -1).  Later, when the driver
277a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul * calls \c _glapi_add_dispatch we'll put in the proper offset.  If that
278a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul * never happens, and the user calls this function, he'll segfault.  That's
279a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul * what you get when you try calling a GL function that doesn't really exist.
280a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul *
281a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul * \param funcName  Name of the function to create an entry-point for.
282a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul *
283a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul * \sa _glapi_add_entrypoint
284a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul */
285a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul
286a97226352fb8063d4d0084523312b4880dae5ac7Brian Paulstatic struct _glapi_function *
287a97226352fb8063d4d0084523312b4880dae5ac7Brian Pauladd_function_name( const char * funcName )
288a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul{
289a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul   struct _glapi_function * entry = NULL;
290cae4fdda8d27cac21714571adb0bfada6d96152aGeorge Sapountzis   _glapi_proc entrypoint = NULL;
291cae4fdda8d27cac21714571adb0bfada6d96152aGeorge Sapountzis   char * name_dup = NULL;
292cae4fdda8d27cac21714571adb0bfada6d96152aGeorge Sapountzis
293cae4fdda8d27cac21714571adb0bfada6d96152aGeorge Sapountzis   if (NumExtEntryPoints >= MAX_EXTENSION_FUNCS)
294cae4fdda8d27cac21714571adb0bfada6d96152aGeorge Sapountzis      return NULL;
295cae4fdda8d27cac21714571adb0bfada6d96152aGeorge Sapountzis
296cae4fdda8d27cac21714571adb0bfada6d96152aGeorge Sapountzis   if (funcName == NULL)
297cae4fdda8d27cac21714571adb0bfada6d96152aGeorge Sapountzis      return NULL;
298cae4fdda8d27cac21714571adb0bfada6d96152aGeorge Sapountzis
299cae4fdda8d27cac21714571adb0bfada6d96152aGeorge Sapountzis   name_dup = str_dup(funcName);
300cae4fdda8d27cac21714571adb0bfada6d96152aGeorge Sapountzis   if (name_dup == NULL)
301cae4fdda8d27cac21714571adb0bfada6d96152aGeorge Sapountzis      return NULL;
302cae4fdda8d27cac21714571adb0bfada6d96152aGeorge Sapountzis
303cae4fdda8d27cac21714571adb0bfada6d96152aGeorge Sapountzis   entrypoint = generate_entrypoint(~0);
304cae4fdda8d27cac21714571adb0bfada6d96152aGeorge Sapountzis
305cae4fdda8d27cac21714571adb0bfada6d96152aGeorge Sapountzis   if (entrypoint == NULL) {
306cae4fdda8d27cac21714571adb0bfada6d96152aGeorge Sapountzis      free(name_dup);
307cae4fdda8d27cac21714571adb0bfada6d96152aGeorge Sapountzis      return NULL;
308a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul   }
309a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul
310cae4fdda8d27cac21714571adb0bfada6d96152aGeorge Sapountzis   entry = & ExtEntryTable[NumExtEntryPoints];
311cae4fdda8d27cac21714571adb0bfada6d96152aGeorge Sapountzis   NumExtEntryPoints++;
312cae4fdda8d27cac21714571adb0bfada6d96152aGeorge Sapountzis
313cae4fdda8d27cac21714571adb0bfada6d96152aGeorge Sapountzis   entry->name = name_dup;
314cae4fdda8d27cac21714571adb0bfada6d96152aGeorge Sapountzis   entry->parameter_signature = NULL;
315cae4fdda8d27cac21714571adb0bfada6d96152aGeorge Sapountzis   entry->dispatch_offset = ~0;
316cae4fdda8d27cac21714571adb0bfada6d96152aGeorge Sapountzis   entry->dispatch_stub = entrypoint;
317cae4fdda8d27cac21714571adb0bfada6d96152aGeorge Sapountzis
318a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul   return entry;
319a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul}
320a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul
321a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul
3223833a76eef6b45b82c102a49055602632f960a99George Sapountzisstatic struct _glapi_function *
3233833a76eef6b45b82c102a49055602632f960a99George Sapountzisset_entry_info( struct _glapi_function * entry, const char * signature, unsigned offset )
3243833a76eef6b45b82c102a49055602632f960a99George Sapountzis{
3253833a76eef6b45b82c102a49055602632f960a99George Sapountzis   char * sig_dup = NULL;
3263833a76eef6b45b82c102a49055602632f960a99George Sapountzis
3273833a76eef6b45b82c102a49055602632f960a99George Sapountzis   if (signature == NULL)
3283833a76eef6b45b82c102a49055602632f960a99George Sapountzis      return NULL;
3293833a76eef6b45b82c102a49055602632f960a99George Sapountzis
3303833a76eef6b45b82c102a49055602632f960a99George Sapountzis   sig_dup = str_dup(signature);
3313833a76eef6b45b82c102a49055602632f960a99George Sapountzis   if (sig_dup == NULL)
3323833a76eef6b45b82c102a49055602632f960a99George Sapountzis      return NULL;
3333833a76eef6b45b82c102a49055602632f960a99George Sapountzis
3343833a76eef6b45b82c102a49055602632f960a99George Sapountzis   fill_in_entrypoint_offset(entry->dispatch_stub, offset);
3353833a76eef6b45b82c102a49055602632f960a99George Sapountzis
3363833a76eef6b45b82c102a49055602632f960a99George Sapountzis   entry->parameter_signature = sig_dup;
3373833a76eef6b45b82c102a49055602632f960a99George Sapountzis   entry->dispatch_offset = offset;
3383833a76eef6b45b82c102a49055602632f960a99George Sapountzis
3393833a76eef6b45b82c102a49055602632f960a99George Sapountzis   return entry;
3403833a76eef6b45b82c102a49055602632f960a99George Sapountzis}
3413833a76eef6b45b82c102a49055602632f960a99George Sapountzis
3423833a76eef6b45b82c102a49055602632f960a99George Sapountzis
343a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul/**
344a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul * Fill-in the dispatch stub for the named function.
345a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul *
346a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul * This function is intended to be called by a hardware driver.  When called,
347a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul * a dispatch stub may be created created for the function.  A pointer to this
348a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul * dispatch function will be returned by glXGetProcAddress.
349a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul *
350a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul * \param function_names       Array of pointers to function names that should
351a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul *                             share a common dispatch offset.
352a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul * \param parameter_signature  String representing the types of the parameters
353a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul *                             passed to the named function.  Parameter types
354a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul *                             are converted to characters using the following
355a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul *                             rules:
356a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul *                               - 'i' for \c GLint, \c GLuint, and \c GLenum
357a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul *                               - 'p' for any pointer type
358a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul *                               - 'f' for \c GLfloat and \c GLclampf
359a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul *                               - 'd' for \c GLdouble and \c GLclampd
360a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul *
361a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul * \returns
362a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul * The offset in the dispatch table of the named function.  A pointer to the
363a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul * driver's implementation of the named function should be stored at
364a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul * \c dispatch_table[\c offset].  Return -1 if error/problem.
365a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul *
366a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul * \sa glXGetProcAddress
367a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul *
368a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul * \warning
369a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul * This function can only handle up to 8 names at a time.  As far as I know,
370a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul * the maximum number of names ever associated with an existing GL function is
371a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul * 4 (\c glPointParameterfSGIS, \c glPointParameterfEXT,
372a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul * \c glPointParameterfARB, and \c glPointParameterf), so this should not be
373a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul * too painful of a limitation.
374a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul *
375a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul * \todo
376a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul * Determine whether or not \c parameter_signature should be allowed to be
377a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul * \c NULL.  It doesn't seem like much of a hardship for drivers to have to
378a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul * pass in an empty string.
379a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul *
380a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul * \todo
381a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul * Determine if code should be added to reject function names that start with
382a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul * 'glX'.
383a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul *
384a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul * \bug
385a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul * Add code to compare \c parameter_signature with the parameter signature of
386a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul * a static function.  In order to do that, we need to find a way to \b get
387a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul * the parameter signature of a static function.
388a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul */
389a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul
390a73c6540d9a7f6e26d8568ba2fc522cb865f0a6cChia-I Wuint
391a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul_glapi_add_dispatch( const char * const * function_names,
392a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul		     const char * parameter_signature )
393a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul{
394a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul   static int next_dynamic_offset = _gloffset_FIRST_DYNAMIC;
395a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul   const char * const real_sig = (parameter_signature != NULL)
396a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul     ? parameter_signature : "";
397a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul   struct _glapi_function * entry[8];
398a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul   GLboolean is_static[8];
399a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul   unsigned i;
400a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul   int offset = ~0;
401a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul
4027cd8f0ef9d905080dc857c4739be9780b24a7fd2George Sapountzis   init_glapi_relocs_once();
403a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul
404a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul   (void) memset( is_static, 0, sizeof( is_static ) );
405a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul   (void) memset( entry, 0, sizeof( entry ) );
406a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul
4070d1dde5b010feba1afe5b51cc6fe66c85371f70bGeorge Sapountzis   /* Find the _single_ dispatch offset for all function names that already
4080d1dde5b010feba1afe5b51cc6fe66c85371f70bGeorge Sapountzis    * exist (and have a dispatch offset).
4090d1dde5b010feba1afe5b51cc6fe66c85371f70bGeorge Sapountzis    */
4100d1dde5b010feba1afe5b51cc6fe66c85371f70bGeorge Sapountzis
411a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul   for ( i = 0 ; function_names[i] != NULL ; i++ ) {
412ddabf0a151c2ef318e5de45238556c6568540681George Sapountzis      const char * funcName = function_names[i];
413ddabf0a151c2ef318e5de45238556c6568540681George Sapountzis      int static_offset;
414ddabf0a151c2ef318e5de45238556c6568540681George Sapountzis      int extension_offset;
415a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul
416ddabf0a151c2ef318e5de45238556c6568540681George Sapountzis      if (funcName[0] != 'g' || funcName[1] != 'l')
417a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul         return -1;
418ddabf0a151c2ef318e5de45238556c6568540681George Sapountzis
419ddabf0a151c2ef318e5de45238556c6568540681George Sapountzis      /* search built-in functions */
420ddabf0a151c2ef318e5de45238556c6568540681George Sapountzis      static_offset = get_static_proc_offset(funcName);
421ddabf0a151c2ef318e5de45238556c6568540681George Sapountzis
422ddabf0a151c2ef318e5de45238556c6568540681George Sapountzis      if (static_offset >= 0) {
423ddabf0a151c2ef318e5de45238556c6568540681George Sapountzis
424ddabf0a151c2ef318e5de45238556c6568540681George Sapountzis	 is_static[i] = GL_TRUE;
425ddabf0a151c2ef318e5de45238556c6568540681George Sapountzis
426a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul	 /* FIXME: Make sure the parameter signatures match!  How do we get
427a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul	  * FIXME: the parameter signature for static functions?
428a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul	  */
429a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul
430ddabf0a151c2ef318e5de45238556c6568540681George Sapountzis	 if ( (offset != ~0) && (static_offset != offset) ) {
431a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul	    return -1;
432a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul	 }
433a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul
434ddabf0a151c2ef318e5de45238556c6568540681George Sapountzis	 offset = static_offset;
435bae31355150f66f7130d76a2ab4d4b735f239c71George Sapountzis
436bae31355150f66f7130d76a2ab4d4b735f239c71George Sapountzis	 continue;
437a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul      }
438ddabf0a151c2ef318e5de45238556c6568540681George Sapountzis
439ddabf0a151c2ef318e5de45238556c6568540681George Sapountzis      /* search added extension functions */
440ddabf0a151c2ef318e5de45238556c6568540681George Sapountzis      entry[i] = get_extension_proc(funcName);
441f9cc6b3ee7c95130992d67c080ff9bc8e8a6d789George Sapountzis
442f9cc6b3ee7c95130992d67c080ff9bc8e8a6d789George Sapountzis      if (entry[i] != NULL) {
443ddabf0a151c2ef318e5de45238556c6568540681George Sapountzis	 extension_offset = entry[i]->dispatch_offset;
444f9cc6b3ee7c95130992d67c080ff9bc8e8a6d789George Sapountzis
445ddabf0a151c2ef318e5de45238556c6568540681George Sapountzis	 /* The offset may be ~0 if the function name was added by
446ddabf0a151c2ef318e5de45238556c6568540681George Sapountzis	  * glXGetProcAddress but never filled in by the driver.
447ddabf0a151c2ef318e5de45238556c6568540681George Sapountzis	  */
448a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul
449ddabf0a151c2ef318e5de45238556c6568540681George Sapountzis	 if (extension_offset == ~0) {
450ddabf0a151c2ef318e5de45238556c6568540681George Sapountzis	    continue;
451ddabf0a151c2ef318e5de45238556c6568540681George Sapountzis	 }
452a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul
453ddabf0a151c2ef318e5de45238556c6568540681George Sapountzis	 if (strcmp(real_sig, entry[i]->parameter_signature) != 0) {
454ddabf0a151c2ef318e5de45238556c6568540681George Sapountzis	    return -1;
455ddabf0a151c2ef318e5de45238556c6568540681George Sapountzis	 }
456a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul
457ddabf0a151c2ef318e5de45238556c6568540681George Sapountzis	 if ( (offset != ~0) && (extension_offset != offset) ) {
458ddabf0a151c2ef318e5de45238556c6568540681George Sapountzis	    return -1;
459ddabf0a151c2ef318e5de45238556c6568540681George Sapountzis	 }
460ddabf0a151c2ef318e5de45238556c6568540681George Sapountzis
461ddabf0a151c2ef318e5de45238556c6568540681George Sapountzis	 offset = extension_offset;
462a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul      }
463a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul   }
464a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul
4650d1dde5b010feba1afe5b51cc6fe66c85371f70bGeorge Sapountzis   /* If all function names are either new (or with no dispatch offset),
4660d1dde5b010feba1afe5b51cc6fe66c85371f70bGeorge Sapountzis    * allocate a new dispatch offset.
4670d1dde5b010feba1afe5b51cc6fe66c85371f70bGeorge Sapountzis    */
4680d1dde5b010feba1afe5b51cc6fe66c85371f70bGeorge Sapountzis
469a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul   if (offset == ~0) {
470a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul      offset = next_dynamic_offset;
471a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul      next_dynamic_offset++;
472a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul   }
473a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul
4740d1dde5b010feba1afe5b51cc6fe66c85371f70bGeorge Sapountzis   /* Fill in the dispatch offset for the new function names (and those with
4750d1dde5b010feba1afe5b51cc6fe66c85371f70bGeorge Sapountzis    * no dispatch offset).
4760d1dde5b010feba1afe5b51cc6fe66c85371f70bGeorge Sapountzis    */
4770d1dde5b010feba1afe5b51cc6fe66c85371f70bGeorge Sapountzis
478a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul   for ( i = 0 ; function_names[i] != NULL ; i++ ) {
479c4b630efdb882f824e9099b9cb2e07d8db2e3549George Sapountzis      if (is_static[i]) {
480c4b630efdb882f824e9099b9cb2e07d8db2e3549George Sapountzis	 continue;
481c4b630efdb882f824e9099b9cb2e07d8db2e3549George Sapountzis      }
482c4b630efdb882f824e9099b9cb2e07d8db2e3549George Sapountzis
4830d1dde5b010feba1afe5b51cc6fe66c85371f70bGeorge Sapountzis      /* generate entrypoints for new function names */
484c4b630efdb882f824e9099b9cb2e07d8db2e3549George Sapountzis      if (entry[i] == NULL) {
485c4b630efdb882f824e9099b9cb2e07d8db2e3549George Sapountzis	 entry[i] = add_function_name( function_names[i] );
486a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul	 if (entry[i] == NULL) {
487c4b630efdb882f824e9099b9cb2e07d8db2e3549George Sapountzis	    /* FIXME: Possible memory leak here. */
488c4b630efdb882f824e9099b9cb2e07d8db2e3549George Sapountzis	    return -1;
489a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul	 }
490a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul      }
491c4b630efdb882f824e9099b9cb2e07d8db2e3549George Sapountzis
492bae31355150f66f7130d76a2ab4d4b735f239c71George Sapountzis      if (entry[i]->dispatch_offset == ~0) {
493bae31355150f66f7130d76a2ab4d4b735f239c71George Sapountzis	 set_entry_info( entry[i], real_sig, offset );
494bae31355150f66f7130d76a2ab4d4b735f239c71George Sapountzis      }
495a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul   }
496c4b630efdb882f824e9099b9cb2e07d8db2e3549George Sapountzis
497a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul   return offset;
498a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul}
499a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul
500a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul
501a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul/**
502a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul * Return offset of entrypoint for named function within dispatch table.
503a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul */
504a73c6540d9a7f6e26d8568ba2fc522cb865f0a6cChia-I WuGLint
505a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul_glapi_get_proc_offset(const char *funcName)
506a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul{
50758985c36be85c668d059165d8282f8c8e4c7a380George Sapountzis   GLint offset;
50858985c36be85c668d059165d8282f8c8e4c7a380George Sapountzis
509a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul   /* search extension functions first */
51058985c36be85c668d059165d8282f8c8e4c7a380George Sapountzis   offset = get_extension_proc_offset(funcName);
51158985c36be85c668d059165d8282f8c8e4c7a380George Sapountzis   if (offset >= 0)
51258985c36be85c668d059165d8282f8c8e4c7a380George Sapountzis      return offset;
51358985c36be85c668d059165d8282f8c8e4c7a380George Sapountzis
514a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul   /* search static functions */
515a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul   return get_static_proc_offset(funcName);
516a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul}
517a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul
518a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul
519a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul
520a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul/**
521a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul * Return pointer to the named function.  If the function name isn't found
522a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul * in the name of static functions, try generating a new API entrypoint on
523a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul * the fly with assembly language.
524a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul */
525a73c6540d9a7f6e26d8568ba2fc522cb865f0a6cChia-I Wu_glapi_proc
526a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul_glapi_get_proc_address(const char *funcName)
527a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul{
52858985c36be85c668d059165d8282f8c8e4c7a380George Sapountzis   _glapi_proc func;
529a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul   struct _glapi_function * entry;
530a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul
5317cd8f0ef9d905080dc857c4739be9780b24a7fd2George Sapountzis   init_glapi_relocs_once();
5327cd8f0ef9d905080dc857c4739be9780b24a7fd2George Sapountzis
533a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul#ifdef MANGLE
53420ed2445b3b98f2b49a26ad4b45859a908583311George Sapountzis   /* skip the prefix on the name */
53520ed2445b3b98f2b49a26ad4b45859a908583311George Sapountzis   if (funcName[1] != 'g' || funcName[2] != 'l')
536a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul      return NULL;
537a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul#else
538a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul   if (funcName[0] != 'g' || funcName[1] != 'l')
539a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul      return NULL;
540a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul#endif
541a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul
542a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul   /* search extension functions first */
54358985c36be85c668d059165d8282f8c8e4c7a380George Sapountzis   func = get_extension_proc_address(funcName);
54458985c36be85c668d059165d8282f8c8e4c7a380George Sapountzis   if (func)
54558985c36be85c668d059165d8282f8c8e4c7a380George Sapountzis      return func;
546a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul
547a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul   /* search static functions */
548f0c18da2cf01bc11dc720caed4590ae7eca128f1George Sapountzis   func = get_static_proc_address(funcName);
549f0c18da2cf01bc11dc720caed4590ae7eca128f1George Sapountzis   if (func)
550f0c18da2cf01bc11dc720caed4590ae7eca128f1George Sapountzis      return func;
551a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul
5520d1dde5b010feba1afe5b51cc6fe66c85371f70bGeorge Sapountzis   /* generate entrypoint, dispatch offset must be filled in by the driver */
553a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul   entry = add_function_name(funcName);
5540d1dde5b010feba1afe5b51cc6fe66c85371f70bGeorge Sapountzis   if (entry == NULL)
5550d1dde5b010feba1afe5b51cc6fe66c85371f70bGeorge Sapountzis      return NULL;
5560d1dde5b010feba1afe5b51cc6fe66c85371f70bGeorge Sapountzis
5570d1dde5b010feba1afe5b51cc6fe66c85371f70bGeorge Sapountzis   return entry->dispatch_stub;
558a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul}
559a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul
560a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul
561a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul
562a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul/**
563a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul * Return the name of the function at the given dispatch offset.
564a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul * This is only intended for debugging.
565a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul */
566a97226352fb8063d4d0084523312b4880dae5ac7Brian Paulconst char *
567a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul_glapi_get_proc_name(GLuint offset)
568a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul{
569a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul   const char * n;
570a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul
571a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul   /* search built-in functions */
572a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul   n = get_static_proc_name(offset);
573a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul   if ( n != NULL ) {
574a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul      return n;
575a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul   }
576a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul
577a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul   /* search added extension functions */
57858985c36be85c668d059165d8282f8c8e4c7a380George Sapountzis   return get_extension_proc_name(offset);
579a97226352fb8063d4d0084523312b4880dae5ac7Brian Paul}
580fae5758fac963ce014e3d43f1bca7fb489e02bf9George Sapountzis
581fae5758fac963ce014e3d43f1bca7fb489e02bf9George Sapountzis
582fae5758fac963ce014e3d43f1bca7fb489e02bf9George Sapountzis
5832c8b5ffed9a787e896b540a95be48ef401d5f007George Sapountzis/**********************************************************************
5842c8b5ffed9a787e896b540a95be48ef401d5f007George Sapountzis * GL API table functions.
5852c8b5ffed9a787e896b540a95be48ef401d5f007George Sapountzis */
5862c8b5ffed9a787e896b540a95be48ef401d5f007George Sapountzis
5872c8b5ffed9a787e896b540a95be48ef401d5f007George Sapountzis
5882c8b5ffed9a787e896b540a95be48ef401d5f007George Sapountzis/*
5892c8b5ffed9a787e896b540a95be48ef401d5f007George Sapountzis * The dispatch table size (number of entries) is the size of the
5902c8b5ffed9a787e896b540a95be48ef401d5f007George Sapountzis * _glapi_table struct plus the number of dynamic entries we can add.
5912c8b5ffed9a787e896b540a95be48ef401d5f007George Sapountzis * The extra slots can be filled in by DRI drivers that register new extension
5922c8b5ffed9a787e896b540a95be48ef401d5f007George Sapountzis * functions.
5932c8b5ffed9a787e896b540a95be48ef401d5f007George Sapountzis */
5942c8b5ffed9a787e896b540a95be48ef401d5f007George Sapountzis#define DISPATCH_TABLE_SIZE (sizeof(struct _glapi_table) / sizeof(void *) + MAX_EXTENSION_FUNCS)
5952c8b5ffed9a787e896b540a95be48ef401d5f007George Sapountzis
5962c8b5ffed9a787e896b540a95be48ef401d5f007George Sapountzis
5972c8b5ffed9a787e896b540a95be48ef401d5f007George Sapountzis/**
5982c8b5ffed9a787e896b540a95be48ef401d5f007George Sapountzis * Return size of dispatch table struct as number of functions (or
5992c8b5ffed9a787e896b540a95be48ef401d5f007George Sapountzis * slots).
6002c8b5ffed9a787e896b540a95be48ef401d5f007George Sapountzis */
601a73c6540d9a7f6e26d8568ba2fc522cb865f0a6cChia-I WuGLuint
6022c8b5ffed9a787e896b540a95be48ef401d5f007George Sapountzis_glapi_get_dispatch_table_size(void)
6032c8b5ffed9a787e896b540a95be48ef401d5f007George Sapountzis{
6042c8b5ffed9a787e896b540a95be48ef401d5f007George Sapountzis   return DISPATCH_TABLE_SIZE;
6052c8b5ffed9a787e896b540a95be48ef401d5f007George Sapountzis}
6062c8b5ffed9a787e896b540a95be48ef401d5f007George Sapountzis
6072c8b5ffed9a787e896b540a95be48ef401d5f007George Sapountzis
6082c8b5ffed9a787e896b540a95be48ef401d5f007George Sapountzis/**
6092c8b5ffed9a787e896b540a95be48ef401d5f007George Sapountzis * Make sure there are no NULL pointers in the given dispatch table.
6102c8b5ffed9a787e896b540a95be48ef401d5f007George Sapountzis * Intended for debugging purposes.
6112c8b5ffed9a787e896b540a95be48ef401d5f007George Sapountzis */
6122c8b5ffed9a787e896b540a95be48ef401d5f007George Sapountzisvoid
6132c8b5ffed9a787e896b540a95be48ef401d5f007George Sapountzis_glapi_check_table_not_null(const struct _glapi_table *table)
6142c8b5ffed9a787e896b540a95be48ef401d5f007George Sapountzis{
6152c8b5ffed9a787e896b540a95be48ef401d5f007George Sapountzis#ifdef EXTRA_DEBUG /* set to DEBUG for extra DEBUG */
6162c8b5ffed9a787e896b540a95be48ef401d5f007George Sapountzis   const GLuint entries = _glapi_get_dispatch_table_size();
6172c8b5ffed9a787e896b540a95be48ef401d5f007George Sapountzis   const void **tab = (const void **) table;
6182c8b5ffed9a787e896b540a95be48ef401d5f007George Sapountzis   GLuint i;
6192c8b5ffed9a787e896b540a95be48ef401d5f007George Sapountzis   for (i = 1; i < entries; i++) {
6202c8b5ffed9a787e896b540a95be48ef401d5f007George Sapountzis      assert(tab[i]);
6212c8b5ffed9a787e896b540a95be48ef401d5f007George Sapountzis   }
6222c8b5ffed9a787e896b540a95be48ef401d5f007George Sapountzis#else
6232c8b5ffed9a787e896b540a95be48ef401d5f007George Sapountzis   (void) table;
6242c8b5ffed9a787e896b540a95be48ef401d5f007George Sapountzis#endif
6252c8b5ffed9a787e896b540a95be48ef401d5f007George Sapountzis}
6262c8b5ffed9a787e896b540a95be48ef401d5f007George Sapountzis
6272c8b5ffed9a787e896b540a95be48ef401d5f007George Sapountzis
628fae5758fac963ce014e3d43f1bca7fb489e02bf9George Sapountzis/**
629fae5758fac963ce014e3d43f1bca7fb489e02bf9George Sapountzis * Do some spot checks to be sure that the dispatch table
630fae5758fac963ce014e3d43f1bca7fb489e02bf9George Sapountzis * slots are assigned correctly. For debugging only.
631fae5758fac963ce014e3d43f1bca7fb489e02bf9George Sapountzis */
632fae5758fac963ce014e3d43f1bca7fb489e02bf9George Sapountzisvoid
633fae5758fac963ce014e3d43f1bca7fb489e02bf9George Sapountzis_glapi_check_table(const struct _glapi_table *table)
634fae5758fac963ce014e3d43f1bca7fb489e02bf9George Sapountzis{
6352c8b5ffed9a787e896b540a95be48ef401d5f007George Sapountzis#ifdef EXTRA_DEBUG /* set to DEBUG for extra DEBUG */
636fae5758fac963ce014e3d43f1bca7fb489e02bf9George Sapountzis   {
637fae5758fac963ce014e3d43f1bca7fb489e02bf9George Sapountzis      GLuint BeginOffset = _glapi_get_proc_offset("glBegin");
638fae5758fac963ce014e3d43f1bca7fb489e02bf9George Sapountzis      char *BeginFunc = (char*) &table->Begin;
639fae5758fac963ce014e3d43f1bca7fb489e02bf9George Sapountzis      GLuint offset = (BeginFunc - (char *) table) / sizeof(void *);
640fae5758fac963ce014e3d43f1bca7fb489e02bf9George Sapountzis      assert(BeginOffset == _gloffset_Begin);
641fae5758fac963ce014e3d43f1bca7fb489e02bf9George Sapountzis      assert(BeginOffset == offset);
642fae5758fac963ce014e3d43f1bca7fb489e02bf9George Sapountzis   }
643fae5758fac963ce014e3d43f1bca7fb489e02bf9George Sapountzis   {
644fae5758fac963ce014e3d43f1bca7fb489e02bf9George Sapountzis      GLuint viewportOffset = _glapi_get_proc_offset("glViewport");
645fae5758fac963ce014e3d43f1bca7fb489e02bf9George Sapountzis      char *viewportFunc = (char*) &table->Viewport;
646fae5758fac963ce014e3d43f1bca7fb489e02bf9George Sapountzis      GLuint offset = (viewportFunc - (char *) table) / sizeof(void *);
647fae5758fac963ce014e3d43f1bca7fb489e02bf9George Sapountzis      assert(viewportOffset == _gloffset_Viewport);
648fae5758fac963ce014e3d43f1bca7fb489e02bf9George Sapountzis      assert(viewportOffset == offset);
649fae5758fac963ce014e3d43f1bca7fb489e02bf9George Sapountzis   }
650fae5758fac963ce014e3d43f1bca7fb489e02bf9George Sapountzis   {
651fae5758fac963ce014e3d43f1bca7fb489e02bf9George Sapountzis      GLuint VertexPointerOffset = _glapi_get_proc_offset("glVertexPointer");
652fae5758fac963ce014e3d43f1bca7fb489e02bf9George Sapountzis      char *VertexPointerFunc = (char*) &table->VertexPointer;
653fae5758fac963ce014e3d43f1bca7fb489e02bf9George Sapountzis      GLuint offset = (VertexPointerFunc - (char *) table) / sizeof(void *);
654fae5758fac963ce014e3d43f1bca7fb489e02bf9George Sapountzis      assert(VertexPointerOffset == _gloffset_VertexPointer);
655fae5758fac963ce014e3d43f1bca7fb489e02bf9George Sapountzis      assert(VertexPointerOffset == offset);
656fae5758fac963ce014e3d43f1bca7fb489e02bf9George Sapountzis   }
657fae5758fac963ce014e3d43f1bca7fb489e02bf9George Sapountzis   {
658fae5758fac963ce014e3d43f1bca7fb489e02bf9George Sapountzis      GLuint ResetMinMaxOffset = _glapi_get_proc_offset("glResetMinmax");
659fae5758fac963ce014e3d43f1bca7fb489e02bf9George Sapountzis      char *ResetMinMaxFunc = (char*) &table->ResetMinmax;
660fae5758fac963ce014e3d43f1bca7fb489e02bf9George Sapountzis      GLuint offset = (ResetMinMaxFunc - (char *) table) / sizeof(void *);
661fae5758fac963ce014e3d43f1bca7fb489e02bf9George Sapountzis      assert(ResetMinMaxOffset == _gloffset_ResetMinmax);
662fae5758fac963ce014e3d43f1bca7fb489e02bf9George Sapountzis      assert(ResetMinMaxOffset == offset);
663fae5758fac963ce014e3d43f1bca7fb489e02bf9George Sapountzis   }
664fae5758fac963ce014e3d43f1bca7fb489e02bf9George Sapountzis   {
665fae5758fac963ce014e3d43f1bca7fb489e02bf9George Sapountzis      GLuint blendColorOffset = _glapi_get_proc_offset("glBlendColor");
666fae5758fac963ce014e3d43f1bca7fb489e02bf9George Sapountzis      char *blendColorFunc = (char*) &table->BlendColor;
667fae5758fac963ce014e3d43f1bca7fb489e02bf9George Sapountzis      GLuint offset = (blendColorFunc - (char *) table) / sizeof(void *);
668fae5758fac963ce014e3d43f1bca7fb489e02bf9George Sapountzis      assert(blendColorOffset == _gloffset_BlendColor);
669fae5758fac963ce014e3d43f1bca7fb489e02bf9George Sapountzis      assert(blendColorOffset == offset);
670fae5758fac963ce014e3d43f1bca7fb489e02bf9George Sapountzis   }
671fae5758fac963ce014e3d43f1bca7fb489e02bf9George Sapountzis   {
672fae5758fac963ce014e3d43f1bca7fb489e02bf9George Sapountzis      GLuint secondaryColor3fOffset = _glapi_get_proc_offset("glSecondaryColor3fEXT");
673fae5758fac963ce014e3d43f1bca7fb489e02bf9George Sapountzis      char *secondaryColor3fFunc = (char*) &table->SecondaryColor3fEXT;
674fae5758fac963ce014e3d43f1bca7fb489e02bf9George Sapountzis      GLuint offset = (secondaryColor3fFunc - (char *) table) / sizeof(void *);
675fae5758fac963ce014e3d43f1bca7fb489e02bf9George Sapountzis      assert(secondaryColor3fOffset == _gloffset_SecondaryColor3fEXT);
676fae5758fac963ce014e3d43f1bca7fb489e02bf9George Sapountzis      assert(secondaryColor3fOffset == offset);
677fae5758fac963ce014e3d43f1bca7fb489e02bf9George Sapountzis   }
678fae5758fac963ce014e3d43f1bca7fb489e02bf9George Sapountzis   {
679fae5758fac963ce014e3d43f1bca7fb489e02bf9George Sapountzis      GLuint pointParameterivOffset = _glapi_get_proc_offset("glPointParameterivNV");
680fae5758fac963ce014e3d43f1bca7fb489e02bf9George Sapountzis      char *pointParameterivFunc = (char*) &table->PointParameterivNV;
681fae5758fac963ce014e3d43f1bca7fb489e02bf9George Sapountzis      GLuint offset = (pointParameterivFunc - (char *) table) / sizeof(void *);
682fae5758fac963ce014e3d43f1bca7fb489e02bf9George Sapountzis      assert(pointParameterivOffset == _gloffset_PointParameterivNV);
683fae5758fac963ce014e3d43f1bca7fb489e02bf9George Sapountzis      assert(pointParameterivOffset == offset);
684fae5758fac963ce014e3d43f1bca7fb489e02bf9George Sapountzis   }
685fae5758fac963ce014e3d43f1bca7fb489e02bf9George Sapountzis   {
686fae5758fac963ce014e3d43f1bca7fb489e02bf9George Sapountzis      GLuint setFenceOffset = _glapi_get_proc_offset("glSetFenceNV");
687fae5758fac963ce014e3d43f1bca7fb489e02bf9George Sapountzis      char *setFenceFunc = (char*) &table->SetFenceNV;
688fae5758fac963ce014e3d43f1bca7fb489e02bf9George Sapountzis      GLuint offset = (setFenceFunc - (char *) table) / sizeof(void *);
689fae5758fac963ce014e3d43f1bca7fb489e02bf9George Sapountzis      assert(setFenceOffset == _gloffset_SetFenceNV);
690fae5758fac963ce014e3d43f1bca7fb489e02bf9George Sapountzis      assert(setFenceOffset == offset);
691fae5758fac963ce014e3d43f1bca7fb489e02bf9George Sapountzis   }
692d3f24ab33c284325abaf4b250f8928d4d53836e1George Sapountzis#else
693d3f24ab33c284325abaf4b250f8928d4d53836e1George Sapountzis   (void) table;
694d3f24ab33c284325abaf4b250f8928d4d53836e1George Sapountzis#endif
695fae5758fac963ce014e3d43f1bca7fb489e02bf9George Sapountzis}
696