glapi: mv table functions to glapi_getproc.c and add local header
[mesa.git] / src / mesa / glapi / glapi_getproc.c
1 /*
2 * Mesa 3-D graphics library
3 * Version: 7.1
4 *
5 * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25 /**
26 * \file glapi_getproc.c
27 *
28 * Code for implementing glXGetProcAddress(), etc.
29 * This was originally in glapi.c but refactored out.
30 */
31
32
33 #ifdef HAVE_DIX_CONFIG_H
34 #include <dix-config.h>
35 #include "glapi/mesa.h"
36 #else
37 #include "main/glheader.h"
38 #include "main/compiler.h"
39 #endif
40
41 #include "glapi/glapi.h"
42 #include "glapi/glapi_priv.h"
43 #include "glapi/glapitable.h"
44 #include "glapi/glapioffsets.h"
45
46
47 #if defined(USE_X64_64_ASM) && defined(GLX_USE_TLS)
48 # define DISPATCH_FUNCTION_SIZE 16
49 #elif defined(USE_X86_ASM)
50 # if defined(THREADS) && !defined(GLX_USE_TLS)
51 # define DISPATCH_FUNCTION_SIZE 32
52 # else
53 # define DISPATCH_FUNCTION_SIZE 16
54 # endif
55 #endif
56
57 #if !defined(DISPATCH_FUNCTION_SIZE) && !defined(XFree86Server)
58 # define NEED_FUNCTION_POINTER
59 #endif
60
61 /* The code in this file is auto-generated with Python */
62 #include "glapi/glprocs.h"
63
64
65 /**
66 * Search the table of static entrypoint functions for the named function
67 * and return the corresponding glprocs_table_t entry.
68 */
69 static const glprocs_table_t *
70 find_entry( const char * n )
71 {
72 GLuint i;
73 for (i = 0; static_functions[i].Name_offset >= 0; i++) {
74 const char *testName = gl_string_table + static_functions[i].Name_offset;
75 #ifdef MANGLE
76 /* skip the "m" prefix on the name */
77 if (strcmp(testName, n + 1) == 0)
78 #else
79 if (strcmp(testName, n) == 0)
80 #endif
81 {
82 return &static_functions[i];
83 }
84 }
85 return NULL;
86 }
87
88
89 /**
90 * Return dispatch table offset of the named static (built-in) function.
91 * Return -1 if function not found.
92 */
93 static GLint
94 get_static_proc_offset(const char *funcName)
95 {
96 const glprocs_table_t * const f = find_entry( funcName );
97 if (f) {
98 return f->Offset;
99 }
100 return -1;
101 }
102
103
104 #ifdef USE_X86_ASM
105
106 #if defined( GLX_USE_TLS )
107 extern GLubyte gl_dispatch_functions_start[];
108 extern GLubyte gl_dispatch_functions_end[];
109 #else
110 extern const GLubyte gl_dispatch_functions_start[];
111 #endif
112
113 #endif /* USE_X86_ASM */
114
115
116 #if !defined(XFree86Server)
117
118 /**
119 * Return dispatch function address for the named static (built-in) function.
120 * Return NULL if function not found.
121 */
122 static _glapi_proc
123 get_static_proc_address(const char *funcName)
124 {
125 const glprocs_table_t * const f = find_entry( funcName );
126 if (f) {
127 #if defined(DISPATCH_FUNCTION_SIZE) && defined(GLX_INDIRECT_RENDERING)
128 return (f->Address == NULL)
129 ? (_glapi_proc) (gl_dispatch_functions_start
130 + (DISPATCH_FUNCTION_SIZE * f->Offset))
131 : f->Address;
132 #elif defined(DISPATCH_FUNCTION_SIZE)
133 return (_glapi_proc) (gl_dispatch_functions_start
134 + (DISPATCH_FUNCTION_SIZE * f->Offset));
135 #else
136 return f->Address;
137 #endif
138 }
139 else {
140 return NULL;
141 }
142 }
143
144 #endif /* !defined(XFree86Server) */
145
146
147
148 /**
149 * Return the name of the function at the given offset in the dispatch
150 * table. For debugging only.
151 */
152 static const char *
153 get_static_proc_name( GLuint offset )
154 {
155 GLuint i;
156 for (i = 0; static_functions[i].Name_offset >= 0; i++) {
157 if (static_functions[i].Offset == offset) {
158 return gl_string_table + static_functions[i].Name_offset;
159 }
160 }
161 return NULL;
162 }
163
164
165
166 #if defined(PTHREADS) || defined(GLX_USE_TLS)
167
168 /**
169 * Perform platform-specific GL API entry-point fixups.
170 */
171 static void
172 init_glapi_relocs( void )
173 {
174 #if defined(USE_X86_ASM) && defined(GLX_USE_TLS) && !defined(GLX_X86_READONLY_TEXT)
175 extern unsigned long _x86_get_dispatch(void);
176 char run_time_patch[] = {
177 0x65, 0xa1, 0, 0, 0, 0 /* movl %gs:0,%eax */
178 };
179 GLuint *offset = (GLuint *) &run_time_patch[2]; /* 32-bits for x86/32 */
180 const GLubyte * const get_disp = (const GLubyte *) run_time_patch;
181 GLubyte * curr_func = (GLubyte *) gl_dispatch_functions_start;
182
183 *offset = _x86_get_dispatch();
184 while ( curr_func != (GLubyte *) gl_dispatch_functions_end ) {
185 (void) memcpy( curr_func, get_disp, sizeof(run_time_patch));
186 curr_func += DISPATCH_FUNCTION_SIZE;
187 }
188 #endif
189 #ifdef USE_SPARC_ASM
190 extern void __glapi_sparc_icache_flush(unsigned int *);
191 static const unsigned int template[] = {
192 #ifdef GLX_USE_TLS
193 0x05000000, /* sethi %hi(_glapi_tls_Dispatch), %g2 */
194 0x8730e00a, /* srl %g3, 10, %g3 */
195 0x8410a000, /* or %g2, %lo(_glapi_tls_Dispatch), %g2 */
196 #ifdef __arch64__
197 0xc259c002, /* ldx [%g7 + %g2], %g1 */
198 0xc2584003, /* ldx [%g1 + %g3], %g1 */
199 #else
200 0xc201c002, /* ld [%g7 + %g2], %g1 */
201 0xc2004003, /* ld [%g1 + %g3], %g1 */
202 #endif
203 0x81c04000, /* jmp %g1 */
204 0x01000000, /* nop */
205 #else
206 #ifdef __arch64__
207 0x03000000, /* 64-bit 0x00 --> sethi %hh(_glapi_Dispatch), %g1 */
208 0x05000000, /* 64-bit 0x04 --> sethi %lm(_glapi_Dispatch), %g2 */
209 0x82106000, /* 64-bit 0x08 --> or %g1, %hm(_glapi_Dispatch), %g1 */
210 0x8730e00a, /* 64-bit 0x0c --> srl %g3, 10, %g3 */
211 0x83287020, /* 64-bit 0x10 --> sllx %g1, 32, %g1 */
212 0x82004002, /* 64-bit 0x14 --> add %g1, %g2, %g1 */
213 0xc2586000, /* 64-bit 0x18 --> ldx [%g1 + %lo(_glapi_Dispatch)], %g1 */
214 #else
215 0x03000000, /* 32-bit 0x00 --> sethi %hi(_glapi_Dispatch), %g1 */
216 0x8730e00a, /* 32-bit 0x04 --> srl %g3, 10, %g3 */
217 0xc2006000, /* 32-bit 0x08 --> ld [%g1 + %lo(_glapi_Dispatch)], %g1 */
218 #endif
219 0x80a06000, /* --> cmp %g1, 0 */
220 0x02800005, /* --> be +4*5 */
221 0x01000000, /* --> nop */
222 #ifdef __arch64__
223 0xc2584003, /* 64-bit --> ldx [%g1 + %g3], %g1 */
224 #else
225 0xc2004003, /* 32-bit --> ld [%g1 + %g3], %g1 */
226 #endif
227 0x81c04000, /* --> jmp %g1 */
228 0x01000000, /* --> nop */
229 #ifdef __arch64__
230 0x9de3bf80, /* 64-bit --> save %sp, -128, %sp */
231 #else
232 0x9de3bfc0, /* 32-bit --> save %sp, -64, %sp */
233 #endif
234 0xa0100003, /* --> mov %g3, %l0 */
235 0x40000000, /* --> call _glapi_get_dispatch */
236 0x01000000, /* --> nop */
237 0x82100008, /* --> mov %o0, %g1 */
238 0x86100010, /* --> mov %l0, %g3 */
239 0x10bffff7, /* --> ba -4*9 */
240 0x81e80000, /* --> restore */
241 #endif
242 };
243 #ifdef GLX_USE_TLS
244 extern unsigned int __glapi_sparc_tls_stub;
245 extern unsigned long __glapi_sparc_get_dispatch(void);
246 unsigned int *code = &__glapi_sparc_tls_stub;
247 unsigned long dispatch = __glapi_sparc_get_dispatch();
248 #else
249 extern unsigned int __glapi_sparc_pthread_stub;
250 unsigned int *code = &__glapi_sparc_pthread_stub;
251 unsigned long dispatch = (unsigned long) &_glapi_Dispatch;
252 unsigned long call_dest = (unsigned long ) &_glapi_get_dispatch;
253 int idx;
254 #endif
255
256 #if defined(GLX_USE_TLS)
257 code[0] = template[0] | (dispatch >> 10);
258 code[1] = template[1];
259 __glapi_sparc_icache_flush(&code[0]);
260 code[2] = template[2] | (dispatch & 0x3ff);
261 code[3] = template[3];
262 __glapi_sparc_icache_flush(&code[2]);
263 code[4] = template[4];
264 code[5] = template[5];
265 __glapi_sparc_icache_flush(&code[4]);
266 code[6] = template[6];
267 __glapi_sparc_icache_flush(&code[6]);
268 #else
269 #if defined(__arch64__)
270 code[0] = template[0] | (dispatch >> (32 + 10));
271 code[1] = template[1] | ((dispatch & 0xffffffff) >> 10);
272 __glapi_sparc_icache_flush(&code[0]);
273 code[2] = template[2] | ((dispatch >> 32) & 0x3ff);
274 code[3] = template[3];
275 __glapi_sparc_icache_flush(&code[2]);
276 code[4] = template[4];
277 code[5] = template[5];
278 __glapi_sparc_icache_flush(&code[4]);
279 code[6] = template[6] | (dispatch & 0x3ff);
280 idx = 7;
281 #else
282 code[0] = template[0] | (dispatch >> 10);
283 code[1] = template[1];
284 __glapi_sparc_icache_flush(&code[0]);
285 code[2] = template[2] | (dispatch & 0x3ff);
286 idx = 3;
287 #endif
288 code[idx + 0] = template[idx + 0];
289 __glapi_sparc_icache_flush(&code[idx - 1]);
290 code[idx + 1] = template[idx + 1];
291 code[idx + 2] = template[idx + 2];
292 __glapi_sparc_icache_flush(&code[idx + 1]);
293 code[idx + 3] = template[idx + 3];
294 code[idx + 4] = template[idx + 4];
295 __glapi_sparc_icache_flush(&code[idx + 3]);
296 code[idx + 5] = template[idx + 5];
297 code[idx + 6] = template[idx + 6];
298 __glapi_sparc_icache_flush(&code[idx + 5]);
299 code[idx + 7] = template[idx + 7];
300 code[idx + 8] = template[idx + 8] |
301 (((call_dest - ((unsigned long) &code[idx + 8]))
302 >> 2) & 0x3fffffff);
303 __glapi_sparc_icache_flush(&code[idx + 7]);
304 code[idx + 9] = template[idx + 9];
305 code[idx + 10] = template[idx + 10];
306 __glapi_sparc_icache_flush(&code[idx + 9]);
307 code[idx + 11] = template[idx + 11];
308 code[idx + 12] = template[idx + 12];
309 __glapi_sparc_icache_flush(&code[idx + 11]);
310 code[idx + 13] = template[idx + 13];
311 __glapi_sparc_icache_flush(&code[idx + 13]);
312 #endif
313 #endif
314 }
315
316 void
317 init_glapi_relocs_once( void )
318 {
319 static pthread_once_t once_control = PTHREAD_ONCE_INIT;
320 pthread_once( & once_control, init_glapi_relocs );
321 }
322
323 #else
324
325 void
326 init_glapi_relocs_once( void ) { }
327
328 #endif /* defined(PTHREADS) || defined(GLX_USE_TLS) */
329
330
331
332 /**********************************************************************
333 * Extension function management.
334 */
335
336
337 /**
338 * Track information about a function added to the GL API.
339 */
340 struct _glapi_function {
341 /**
342 * Name of the function.
343 */
344 const char * name;
345
346
347 /**
348 * Text string that describes the types of the parameters passed to the
349 * named function. Parameter types are converted to characters using the
350 * following rules:
351 * - 'i' for \c GLint, \c GLuint, and \c GLenum
352 * - 'p' for any pointer type
353 * - 'f' for \c GLfloat and \c GLclampf
354 * - 'd' for \c GLdouble and \c GLclampd
355 */
356 const char * parameter_signature;
357
358
359 /**
360 * Offset in the dispatch table where the pointer to the real function is
361 * located. If the driver has not requested that the named function be
362 * added to the dispatch table, this will have the value ~0.
363 */
364 unsigned dispatch_offset;
365
366
367 /**
368 * Pointer to the dispatch stub for the named function.
369 *
370 * \todo
371 * The semantic of this field should be changed slightly. Currently, it
372 * is always expected to be non-\c NULL. However, it would be better to
373 * only allocate the entry-point stub when the application requests the
374 * function via \c glXGetProcAddress. This would save memory for all the
375 * functions that the driver exports but that the application never wants
376 * to call.
377 */
378 _glapi_proc dispatch_stub;
379 };
380
381
382 /*
383 * Number of extension functions which we can dynamically add at runtime.
384 */
385 #define MAX_EXTENSION_FUNCS 300
386
387
388 static struct _glapi_function ExtEntryTable[MAX_EXTENSION_FUNCS];
389 static GLuint NumExtEntryPoints = 0;
390
391 #ifdef USE_SPARC_ASM
392 extern void __glapi_sparc_icache_flush(unsigned int *);
393 #endif
394
395 static void
396 fill_in_entrypoint_offset(_glapi_proc entrypoint, GLuint offset);
397
398 /**
399 * Generate a dispatch function (entrypoint) which jumps through
400 * the given slot number (offset) in the current dispatch table.
401 * We need assembly language in order to accomplish this.
402 */
403 static _glapi_proc
404 generate_entrypoint(GLuint functionOffset)
405 {
406 #if defined(USE_X86_ASM)
407 /* 32 is chosen as something of a magic offset. For x86, the dispatch
408 * at offset 32 is the first one where the offset in the
409 * "jmp OFFSET*4(%eax)" can't be encoded in a single byte.
410 */
411 const GLubyte * const template_func = gl_dispatch_functions_start
412 + (DISPATCH_FUNCTION_SIZE * 32);
413 GLubyte * const code = (GLubyte *) malloc(DISPATCH_FUNCTION_SIZE);
414
415
416 if ( code != NULL ) {
417 (void) memcpy(code, template_func, DISPATCH_FUNCTION_SIZE);
418 fill_in_entrypoint_offset( (_glapi_proc) code, functionOffset );
419 }
420
421 return (_glapi_proc) code;
422 #elif defined(USE_SPARC_ASM)
423
424 #if defined(PTHREADS) || defined(GLX_USE_TLS)
425 static const unsigned int template[] = {
426 0x07000000, /* sethi %hi(0), %g3 */
427 0x8210000f, /* mov %o7, %g1 */
428 0x40000000, /* call */
429 0x9e100001, /* mov %g1, %o7 */
430 };
431 #ifdef GLX_USE_TLS
432 extern unsigned int __glapi_sparc_tls_stub;
433 unsigned long call_dest = (unsigned long ) &__glapi_sparc_tls_stub;
434 #else
435 extern unsigned int __glapi_sparc_pthread_stub;
436 unsigned long call_dest = (unsigned long ) &__glapi_sparc_pthread_stub;
437 #endif
438 unsigned int *code = (unsigned int *) malloc(sizeof(template));
439 if (code) {
440 code[0] = template[0] | (functionOffset & 0x3fffff);
441 code[1] = template[1];
442 __glapi_sparc_icache_flush(&code[0]);
443 code[2] = template[2] |
444 (((call_dest - ((unsigned long) &code[2]))
445 >> 2) & 0x3fffffff);
446 code[3] = template[3];
447 __glapi_sparc_icache_flush(&code[2]);
448 }
449 return (_glapi_proc) code;
450 #endif
451
452 #else
453 (void) functionOffset;
454 return NULL;
455 #endif /* USE_*_ASM */
456 }
457
458
459 /**
460 * This function inserts a new dispatch offset into the assembly language
461 * stub that was generated with the preceeding function.
462 */
463 static void
464 fill_in_entrypoint_offset(_glapi_proc entrypoint, GLuint offset)
465 {
466 #if defined(USE_X86_ASM)
467 GLubyte * const code = (GLubyte *) entrypoint;
468
469 #if DISPATCH_FUNCTION_SIZE == 32
470 *((unsigned int *)(code + 11)) = 4 * offset;
471 *((unsigned int *)(code + 22)) = 4 * offset;
472 #elif DISPATCH_FUNCTION_SIZE == 16 && defined( GLX_USE_TLS )
473 *((unsigned int *)(code + 8)) = 4 * offset;
474 #elif DISPATCH_FUNCTION_SIZE == 16
475 *((unsigned int *)(code + 7)) = 4 * offset;
476 #else
477 # error Invalid DISPATCH_FUNCTION_SIZE!
478 #endif
479
480 #elif defined(USE_SPARC_ASM)
481 unsigned int *code = (unsigned int *) entrypoint;
482 code[0] &= ~0x3fffff;
483 code[0] |= (offset * sizeof(void *)) & 0x3fffff;
484 __glapi_sparc_icache_flush(&code[0]);
485 #else
486
487 /* an unimplemented architecture */
488 (void) entrypoint;
489 (void) offset;
490
491 #endif /* USE_*_ASM */
492 }
493
494
495 /**
496 * strdup() is actually not a standard ANSI C or POSIX routine.
497 * Irix will not define it if ANSI mode is in effect.
498 */
499 static char *
500 str_dup(const char *str)
501 {
502 char *copy;
503 copy = (char*) malloc(strlen(str) + 1);
504 if (!copy)
505 return NULL;
506 strcpy(copy, str);
507 return copy;
508 }
509
510
511 /**
512 * Generate new entrypoint
513 *
514 * Use a temporary dispatch offset of ~0 (i.e. -1). Later, when the driver
515 * calls \c _glapi_add_dispatch we'll put in the proper offset. If that
516 * never happens, and the user calls this function, he'll segfault. That's
517 * what you get when you try calling a GL function that doesn't really exist.
518 *
519 * \param funcName Name of the function to create an entry-point for.
520 *
521 * \sa _glapi_add_entrypoint
522 */
523
524 static struct _glapi_function *
525 add_function_name( const char * funcName )
526 {
527 struct _glapi_function * entry = NULL;
528
529 if (NumExtEntryPoints < MAX_EXTENSION_FUNCS) {
530 _glapi_proc entrypoint = generate_entrypoint(~0);
531 if (entrypoint != NULL) {
532 entry = & ExtEntryTable[NumExtEntryPoints];
533
534 ExtEntryTable[NumExtEntryPoints].name = str_dup(funcName);
535 ExtEntryTable[NumExtEntryPoints].parameter_signature = NULL;
536 ExtEntryTable[NumExtEntryPoints].dispatch_offset = ~0;
537 ExtEntryTable[NumExtEntryPoints].dispatch_stub = entrypoint;
538 NumExtEntryPoints++;
539 }
540 }
541
542 return entry;
543 }
544
545
546 /**
547 * Fill-in the dispatch stub for the named function.
548 *
549 * This function is intended to be called by a hardware driver. When called,
550 * a dispatch stub may be created created for the function. A pointer to this
551 * dispatch function will be returned by glXGetProcAddress.
552 *
553 * \param function_names Array of pointers to function names that should
554 * share a common dispatch offset.
555 * \param parameter_signature String representing the types of the parameters
556 * passed to the named function. Parameter types
557 * are converted to characters using the following
558 * rules:
559 * - 'i' for \c GLint, \c GLuint, and \c GLenum
560 * - 'p' for any pointer type
561 * - 'f' for \c GLfloat and \c GLclampf
562 * - 'd' for \c GLdouble and \c GLclampd
563 *
564 * \returns
565 * The offset in the dispatch table of the named function. A pointer to the
566 * driver's implementation of the named function should be stored at
567 * \c dispatch_table[\c offset]. Return -1 if error/problem.
568 *
569 * \sa glXGetProcAddress
570 *
571 * \warning
572 * This function can only handle up to 8 names at a time. As far as I know,
573 * the maximum number of names ever associated with an existing GL function is
574 * 4 (\c glPointParameterfSGIS, \c glPointParameterfEXT,
575 * \c glPointParameterfARB, and \c glPointParameterf), so this should not be
576 * too painful of a limitation.
577 *
578 * \todo
579 * Determine whether or not \c parameter_signature should be allowed to be
580 * \c NULL. It doesn't seem like much of a hardship for drivers to have to
581 * pass in an empty string.
582 *
583 * \todo
584 * Determine if code should be added to reject function names that start with
585 * 'glX'.
586 *
587 * \bug
588 * Add code to compare \c parameter_signature with the parameter signature of
589 * a static function. In order to do that, we need to find a way to \b get
590 * the parameter signature of a static function.
591 */
592
593 PUBLIC int
594 _glapi_add_dispatch( const char * const * function_names,
595 const char * parameter_signature )
596 {
597 static int next_dynamic_offset = _gloffset_FIRST_DYNAMIC;
598 const char * const real_sig = (parameter_signature != NULL)
599 ? parameter_signature : "";
600 struct _glapi_function * entry[8];
601 GLboolean is_static[8];
602 unsigned i;
603 unsigned j;
604 int offset = ~0;
605 int new_offset;
606
607
608 (void) memset( is_static, 0, sizeof( is_static ) );
609 (void) memset( entry, 0, sizeof( entry ) );
610
611 for ( i = 0 ; function_names[i] != NULL ; i++ ) {
612 /* Do some trivial validation on the name of the function.
613 */
614
615 if (!function_names[i] || function_names[i][0] != 'g' || function_names[i][1] != 'l')
616 return -1;
617
618 /* Determine if the named function already exists. If the function does
619 * exist, it must have the same parameter signature as the function
620 * being added.
621 */
622
623 new_offset = get_static_proc_offset(function_names[i]);
624 if (new_offset >= 0) {
625 /* FIXME: Make sure the parameter signatures match! How do we get
626 * FIXME: the parameter signature for static functions?
627 */
628
629 if ( (offset != ~0) && (new_offset != offset) ) {
630 return -1;
631 }
632
633 is_static[i] = GL_TRUE;
634 offset = new_offset;
635 }
636
637
638 for ( j = 0 ; j < NumExtEntryPoints ; j++ ) {
639 if (strcmp(ExtEntryTable[j].name, function_names[i]) == 0) {
640 /* The offset may be ~0 if the function name was added by
641 * glXGetProcAddress but never filled in by the driver.
642 */
643
644 if (ExtEntryTable[j].dispatch_offset != ~0) {
645 if (strcmp(real_sig, ExtEntryTable[j].parameter_signature)
646 != 0) {
647 return -1;
648 }
649
650 if ( (offset != ~0) && (ExtEntryTable[j].dispatch_offset != offset) ) {
651 return -1;
652 }
653
654 offset = ExtEntryTable[j].dispatch_offset;
655 }
656
657 entry[i] = & ExtEntryTable[j];
658 break;
659 }
660 }
661 }
662
663 if (offset == ~0) {
664 offset = next_dynamic_offset;
665 next_dynamic_offset++;
666 }
667
668 for ( i = 0 ; function_names[i] != NULL ; i++ ) {
669 if (! is_static[i] ) {
670 if (entry[i] == NULL) {
671 entry[i] = add_function_name( function_names[i] );
672 if (entry[i] == NULL) {
673 /* FIXME: Possible memory leak here.
674 */
675 return -1;
676 }
677 }
678
679 entry[i]->parameter_signature = str_dup(real_sig);
680 fill_in_entrypoint_offset(entry[i]->dispatch_stub, offset);
681 entry[i]->dispatch_offset = offset;
682 }
683 }
684
685 return offset;
686 }
687
688
689 /**
690 * Return offset of entrypoint for named function within dispatch table.
691 */
692 PUBLIC GLint
693 _glapi_get_proc_offset(const char *funcName)
694 {
695 /* search extension functions first */
696 GLuint i;
697 for (i = 0; i < NumExtEntryPoints; i++) {
698 if (strcmp(ExtEntryTable[i].name, funcName) == 0) {
699 return ExtEntryTable[i].dispatch_offset;
700 }
701 }
702 /* search static functions */
703 return get_static_proc_offset(funcName);
704 }
705
706
707
708 /**
709 * Return pointer to the named function. If the function name isn't found
710 * in the name of static functions, try generating a new API entrypoint on
711 * the fly with assembly language.
712 */
713 PUBLIC _glapi_proc
714 _glapi_get_proc_address(const char *funcName)
715 {
716 struct _glapi_function * entry;
717 GLuint i;
718
719 #ifdef MANGLE
720 if (funcName[0] != 'm' || funcName[1] != 'g' || funcName[2] != 'l')
721 return NULL;
722 #else
723 if (funcName[0] != 'g' || funcName[1] != 'l')
724 return NULL;
725 #endif
726
727 /* search extension functions first */
728 for (i = 0; i < NumExtEntryPoints; i++) {
729 if (strcmp(ExtEntryTable[i].name, funcName) == 0) {
730 return ExtEntryTable[i].dispatch_stub;
731 }
732 }
733
734 #if !defined( XFree86Server )
735 /* search static functions */
736 {
737 const _glapi_proc func = get_static_proc_address(funcName);
738 if (func)
739 return func;
740 }
741 #endif /* !defined( XFree86Server ) */
742
743 entry = add_function_name(funcName);
744 return (entry == NULL) ? NULL : entry->dispatch_stub;
745 }
746
747
748
749 /**
750 * Return the name of the function at the given dispatch offset.
751 * This is only intended for debugging.
752 */
753 const char *
754 _glapi_get_proc_name(GLuint offset)
755 {
756 GLuint i;
757 const char * n;
758
759 /* search built-in functions */
760 n = get_static_proc_name(offset);
761 if ( n != NULL ) {
762 return n;
763 }
764
765 /* search added extension functions */
766 for (i = 0; i < NumExtEntryPoints; i++) {
767 if (ExtEntryTable[i].dispatch_offset == offset) {
768 return ExtEntryTable[i].name;
769 }
770 }
771 return NULL;
772 }
773
774
775
776 /**********************************************************************
777 * GL API table functions.
778 */
779
780
781 /*
782 * The dispatch table size (number of entries) is the size of the
783 * _glapi_table struct plus the number of dynamic entries we can add.
784 * The extra slots can be filled in by DRI drivers that register new extension
785 * functions.
786 */
787 #define DISPATCH_TABLE_SIZE (sizeof(struct _glapi_table) / sizeof(void *) + MAX_EXTENSION_FUNCS)
788
789
790 /**
791 * Return size of dispatch table struct as number of functions (or
792 * slots).
793 */
794 PUBLIC GLuint
795 _glapi_get_dispatch_table_size(void)
796 {
797 return DISPATCH_TABLE_SIZE;
798 }
799
800
801 /**
802 * Make sure there are no NULL pointers in the given dispatch table.
803 * Intended for debugging purposes.
804 */
805 void
806 _glapi_check_table_not_null(const struct _glapi_table *table)
807 {
808 #ifdef EXTRA_DEBUG /* set to DEBUG for extra DEBUG */
809 const GLuint entries = _glapi_get_dispatch_table_size();
810 const void **tab = (const void **) table;
811 GLuint i;
812 for (i = 1; i < entries; i++) {
813 assert(tab[i]);
814 }
815 #else
816 (void) table;
817 #endif
818 }
819
820
821 /**
822 * Do some spot checks to be sure that the dispatch table
823 * slots are assigned correctly. For debugging only.
824 */
825 void
826 _glapi_check_table(const struct _glapi_table *table)
827 {
828 #ifdef EXTRA_DEBUG /* set to DEBUG for extra DEBUG */
829 {
830 GLuint BeginOffset = _glapi_get_proc_offset("glBegin");
831 char *BeginFunc = (char*) &table->Begin;
832 GLuint offset = (BeginFunc - (char *) table) / sizeof(void *);
833 assert(BeginOffset == _gloffset_Begin);
834 assert(BeginOffset == offset);
835 }
836 {
837 GLuint viewportOffset = _glapi_get_proc_offset("glViewport");
838 char *viewportFunc = (char*) &table->Viewport;
839 GLuint offset = (viewportFunc - (char *) table) / sizeof(void *);
840 assert(viewportOffset == _gloffset_Viewport);
841 assert(viewportOffset == offset);
842 }
843 {
844 GLuint VertexPointerOffset = _glapi_get_proc_offset("glVertexPointer");
845 char *VertexPointerFunc = (char*) &table->VertexPointer;
846 GLuint offset = (VertexPointerFunc - (char *) table) / sizeof(void *);
847 assert(VertexPointerOffset == _gloffset_VertexPointer);
848 assert(VertexPointerOffset == offset);
849 }
850 {
851 GLuint ResetMinMaxOffset = _glapi_get_proc_offset("glResetMinmax");
852 char *ResetMinMaxFunc = (char*) &table->ResetMinmax;
853 GLuint offset = (ResetMinMaxFunc - (char *) table) / sizeof(void *);
854 assert(ResetMinMaxOffset == _gloffset_ResetMinmax);
855 assert(ResetMinMaxOffset == offset);
856 }
857 {
858 GLuint blendColorOffset = _glapi_get_proc_offset("glBlendColor");
859 char *blendColorFunc = (char*) &table->BlendColor;
860 GLuint offset = (blendColorFunc - (char *) table) / sizeof(void *);
861 assert(blendColorOffset == _gloffset_BlendColor);
862 assert(blendColorOffset == offset);
863 }
864 {
865 GLuint secondaryColor3fOffset = _glapi_get_proc_offset("glSecondaryColor3fEXT");
866 char *secondaryColor3fFunc = (char*) &table->SecondaryColor3fEXT;
867 GLuint offset = (secondaryColor3fFunc - (char *) table) / sizeof(void *);
868 assert(secondaryColor3fOffset == _gloffset_SecondaryColor3fEXT);
869 assert(secondaryColor3fOffset == offset);
870 }
871 {
872 GLuint pointParameterivOffset = _glapi_get_proc_offset("glPointParameterivNV");
873 char *pointParameterivFunc = (char*) &table->PointParameterivNV;
874 GLuint offset = (pointParameterivFunc - (char *) table) / sizeof(void *);
875 assert(pointParameterivOffset == _gloffset_PointParameterivNV);
876 assert(pointParameterivOffset == offset);
877 }
878 {
879 GLuint setFenceOffset = _glapi_get_proc_offset("glSetFenceNV");
880 char *setFenceFunc = (char*) &table->SetFenceNV;
881 GLuint offset = (setFenceFunc - (char *) table) / sizeof(void *);
882 assert(setFenceOffset == _gloffset_SetFenceNV);
883 assert(setFenceOffset == offset);
884 }
885 #else
886 (void) table;
887 #endif
888 }