Make the shared glapi files not include glheader.h.
[mesa.git] / src / mesa / glapi / glapi.c
1 /*
2 * Mesa 3-D graphics library
3 * Version: 6.5
4 *
5 * Copyright (C) 1999-2006 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 /*
27 * This file manages the OpenGL API dispatch layer.
28 * The dispatch table (struct _glapi_table) is basically just a list
29 * of function pointers.
30 * There are functions to set/get the current dispatch table for the
31 * current thread and to manage registration/dispatch of dynamically
32 * added extension functions.
33 *
34 * It's intended that this file and the other glapi*.[ch] files are
35 * flexible enough to be reused in several places: XFree86, DRI-
36 * based libGL.so, and perhaps the SGI SI.
37 *
38 * NOTE: There are no dependencies on Mesa in this code.
39 *
40 * Versions (API changes):
41 * 2000/02/23 - original version for Mesa 3.3 and XFree86 4.0
42 * 2001/01/16 - added dispatch override feature for Mesa 3.5
43 * 2002/06/28 - added _glapi_set_warning_func(), Mesa 4.1.
44 * 2002/10/01 - _glapi_get_proc_address() will now generate new entrypoints
45 * itself (using offset ~0). _glapi_add_entrypoint() can be
46 * called afterward and it'll fill in the correct dispatch
47 * offset. This allows DRI libGL to avoid probing for DRI
48 * drivers! No changes to the public glapi interface.
49 */
50
51
52
53 #ifdef HAVE_DIX_CONFIG_H
54
55 #include <dix-config.h>
56 #define PUBLIC
57
58 #else
59
60 #include "glheader.h"
61
62 #endif
63
64 #include <stdlib.h>
65 #include <string.h>
66
67 #include "glapi.h"
68 #include "glapioffsets.h"
69 #include "glapitable.h"
70
71 /***** BEGIN NO-OP DISPATCH *****/
72
73 static GLboolean WarnFlag = GL_FALSE;
74 static _glapi_warning_func warning_func;
75
76 #if defined(PTHREADS) || defined(GLX_USE_TLS)
77 static void init_glapi_relocs(void);
78 #endif
79
80 static _glapi_proc generate_entrypoint(GLuint functionOffset);
81 static void fill_in_entrypoint_offset(_glapi_proc entrypoint, GLuint offset);
82
83 /*
84 * Enable/disable printing of warning messages.
85 */
86 PUBLIC void
87 _glapi_noop_enable_warnings(GLboolean enable)
88 {
89 WarnFlag = enable;
90 }
91
92 /*
93 * Register a callback function for reporting errors.
94 */
95 PUBLIC void
96 _glapi_set_warning_func( _glapi_warning_func func )
97 {
98 warning_func = func;
99 }
100
101 static GLboolean
102 warn(void)
103 {
104 if ((WarnFlag || getenv("MESA_DEBUG") || getenv("LIBGL_DEBUG"))
105 && warning_func) {
106 return GL_TRUE;
107 }
108 else {
109 return GL_FALSE;
110 }
111 }
112
113
114 #define KEYWORD1 static
115 #define KEYWORD1_ALT static
116 #define KEYWORD2 GLAPIENTRY
117 #define NAME(func) NoOp##func
118
119 #define F NULL
120
121 #define DISPATCH(func, args, msg) \
122 if (warn()) { \
123 warning_func(NULL, "GL User Error: called without context: %s", #func); \
124 }
125
126 #define RETURN_DISPATCH(func, args, msg) \
127 if (warn()) { \
128 warning_func(NULL, "GL User Error: called without context: %s", #func); \
129 } \
130 return 0
131
132 #define DISPATCH_TABLE_NAME __glapi_noop_table
133 #define UNUSED_TABLE_NAME __unused_noop_functions
134
135 #define TABLE_ENTRY(name) (_glapi_proc) NoOp##name
136
137 static GLint NoOpUnused(void)
138 {
139 if (warn()) {
140 warning_func(NULL, "GL User Error: calling extension function without a current context\n");
141 }
142 return 0;
143 }
144
145 #include "glapitemp.h"
146
147 /***** END NO-OP DISPATCH *****/
148
149
150
151 /**
152 * \name Current dispatch and current context control variables
153 *
154 * Depending on whether or not multithreading is support, and the type of
155 * support available, several variables are used to store the current context
156 * pointer and the current dispatch table pointer. In the non-threaded case,
157 * the variables \c _glapi_Dispatch and \c _glapi_Context are used for this
158 * purpose.
159 *
160 * In the "normal" threaded case, the variables \c _glapi_Dispatch and
161 * \c _glapi_Context will be \c NULL if an application is detected as being
162 * multithreaded. Single-threaded applications will use \c _glapi_Dispatch
163 * and \c _glapi_Context just like the case without any threading support.
164 * When \c _glapi_Dispatch and \c _glapi_Context are \c NULL, the thread state
165 * data \c _gl_DispatchTSD and \c ContextTSD are used. Drivers and the
166 * static dispatch functions access these variables via \c _glapi_get_dispatch
167 * and \c _glapi_get_context.
168 *
169 * There is a race condition in setting \c _glapi_Dispatch to \c NULL. It is
170 * possible for the original thread to be setting it at the same instant a new
171 * thread, perhaps running on a different processor, is clearing it. Because
172 * of that, \c ThreadSafe, which can only ever be changed to \c GL_TRUE, is
173 * used to determine whether or not the application is multithreaded.
174 *
175 * In the TLS case, the variables \c _glapi_Dispatch and \c _glapi_Context are
176 * hardcoded to \c NULL. Instead the TLS variables \c _glapi_tls_Dispatch and
177 * \c _glapi_tls_Context are used. Having \c _glapi_Dispatch and
178 * \c _glapi_Context be hardcoded to \c NULL maintains binary compatability
179 * between TLS enabled loaders and non-TLS DRI drivers.
180 */
181 /*@{*/
182 #if defined(GLX_USE_TLS)
183
184 PUBLIC __thread struct _glapi_table * _glapi_tls_Dispatch
185 __attribute__((tls_model("initial-exec")))
186 = (struct _glapi_table *) __glapi_noop_table;
187
188 PUBLIC __thread void * _glapi_tls_Context
189 __attribute__((tls_model("initial-exec")));
190
191 PUBLIC const struct _glapi_table *_glapi_Dispatch = NULL;
192 PUBLIC const void *_glapi_Context = NULL;
193
194 #else
195
196 #if defined(THREADS)
197
198 static GLboolean ThreadSafe = GL_FALSE; /**< In thread-safe mode? */
199 _glthread_TSD _gl_DispatchTSD; /**< Per-thread dispatch pointer */
200 static _glthread_TSD ContextTSD; /**< Per-thread context pointer */
201
202 #if defined(WIN32_THREADS)
203 void FreeTSD(_glthread_TSD *p);
204 void FreeAllTSD(void)
205 {
206 FreeTSD(&_gl_DispatchTSD);
207 FreeTSD(&ContextTSD);
208 }
209 #endif /* defined(WIN32_THREADS) */
210
211 #endif /* defined(THREADS) */
212
213 PUBLIC struct _glapi_table *_glapi_Dispatch =
214 (struct _glapi_table *) __glapi_noop_table;
215 PUBLIC void *_glapi_Context = NULL;
216
217 #endif /* defined(GLX_USE_TLS) */
218 /*@}*/
219
220
221 /**
222 * strdup() is actually not a standard ANSI C or POSIX routine.
223 * Irix will not define it if ANSI mode is in effect.
224 */
225 static char *
226 str_dup(const char *str)
227 {
228 char *copy;
229 copy = (char*) malloc(strlen(str) + 1);
230 if (!copy)
231 return NULL;
232 strcpy(copy, str);
233 return copy;
234 }
235
236
237
238 /**
239 * We should call this periodically from a function such as glXMakeCurrent
240 * in order to test if multiple threads are being used.
241 */
242 void
243 _glapi_check_multithread(void)
244 {
245 #if defined(THREADS) && !defined(GLX_USE_TLS)
246 if (!ThreadSafe) {
247 static unsigned long knownID;
248 static GLboolean firstCall = GL_TRUE;
249 if (firstCall) {
250 knownID = _glthread_GetID();
251 firstCall = GL_FALSE;
252 }
253 else if (knownID != _glthread_GetID()) {
254 ThreadSafe = GL_TRUE;
255 _glapi_set_dispatch(NULL);
256 _glapi_set_context(NULL);
257 }
258 }
259 else if (!_glapi_get_dispatch()) {
260 /* make sure that this thread's dispatch pointer isn't null */
261 _glapi_set_dispatch(NULL);
262 }
263 #endif
264 }
265
266
267
268 /**
269 * Set the current context pointer for this thread.
270 * The context pointer is an opaque type which should be cast to
271 * void from the real context pointer type.
272 */
273 PUBLIC void
274 _glapi_set_context(void *context)
275 {
276 (void) __unused_noop_functions; /* silence a warning */
277 #if defined(GLX_USE_TLS)
278 _glapi_tls_Context = context;
279 #elif defined(THREADS)
280 _glthread_SetTSD(&ContextTSD, context);
281 _glapi_Context = (ThreadSafe) ? NULL : context;
282 #else
283 _glapi_Context = context;
284 #endif
285 }
286
287
288
289 /**
290 * Get the current context pointer for this thread.
291 * The context pointer is an opaque type which should be cast from
292 * void to the real context pointer type.
293 */
294 PUBLIC void *
295 _glapi_get_context(void)
296 {
297 #if defined(GLX_USE_TLS)
298 return _glapi_tls_Context;
299 #elif defined(THREADS)
300 if (ThreadSafe) {
301 return _glthread_GetTSD(&ContextTSD);
302 }
303 else {
304 return _glapi_Context;
305 }
306 #else
307 return _glapi_Context;
308 #endif
309 }
310
311
312
313 /**
314 * Set the global or per-thread dispatch table pointer.
315 * If the dispatch parameter is NULL we'll plug in the no-op dispatch
316 * table (__glapi_noop_table).
317 */
318 PUBLIC void
319 _glapi_set_dispatch(struct _glapi_table *dispatch)
320 {
321 #if defined(PTHREADS) || defined(GLX_USE_TLS)
322 static pthread_once_t once_control = PTHREAD_ONCE_INIT;
323 pthread_once( & once_control, init_glapi_relocs );
324 #endif
325
326 if (!dispatch) {
327 /* use the no-op functions */
328 dispatch = (struct _glapi_table *) __glapi_noop_table;
329 }
330 #ifdef DEBUG
331 else {
332 _glapi_check_table(dispatch);
333 }
334 #endif
335
336 #if defined(GLX_USE_TLS)
337 _glapi_tls_Dispatch = dispatch;
338 #elif defined(THREADS)
339 _glthread_SetTSD(&_gl_DispatchTSD, (void *) dispatch);
340 _glapi_Dispatch = (ThreadSafe) ? NULL : dispatch;
341 #else /*THREADS*/
342 _glapi_Dispatch = dispatch;
343 #endif /*THREADS*/
344 }
345
346
347
348 /**
349 * Return pointer to current dispatch table for calling thread.
350 */
351 PUBLIC struct _glapi_table *
352 _glapi_get_dispatch(void)
353 {
354 struct _glapi_table * api;
355 #if defined(GLX_USE_TLS)
356 api = _glapi_tls_Dispatch;
357 #elif defined(THREADS)
358 api = (ThreadSafe)
359 ? (struct _glapi_table *) _glthread_GetTSD(&_gl_DispatchTSD)
360 : _glapi_Dispatch;
361 #else
362 api = _glapi_Dispatch;
363 #endif
364 return api;
365 }
366
367
368
369 /***
370 *** The rest of this file is pretty much concerned with GetProcAddress
371 *** functionality.
372 ***/
373
374 #if defined(USE_X64_64_ASM) && defined(GLX_USE_TLS)
375 # define DISPATCH_FUNCTION_SIZE 16
376 #elif defined(USE_X86_ASM)
377 # if defined(THREADS) && !defined(GLX_USE_TLS)
378 # define DISPATCH_FUNCTION_SIZE 32
379 # else
380 # define DISPATCH_FUNCTION_SIZE 16
381 # endif
382 #endif
383
384 #if !defined(DISPATCH_FUNCTION_SIZE) && !defined(XFree86Server) && !defined(XGLServer)
385 # define NEED_FUNCTION_POINTER
386 #endif
387
388 /* The code in this file is auto-generated with Python */
389 #include "glprocs.h"
390
391
392 /**
393 * Search the table of static entrypoint functions for the named function
394 * and return the corresponding glprocs_table_t entry.
395 */
396 static const glprocs_table_t *
397 find_entry( const char * n )
398 {
399 GLuint i;
400 for (i = 0; static_functions[i].Name_offset >= 0; i++) {
401 const char *testName = gl_string_table + static_functions[i].Name_offset;
402 if (strcmp(testName, n) == 0) {
403 return &static_functions[i];
404 }
405 }
406 return NULL;
407 }
408
409
410 /**
411 * Return dispatch table offset of the named static (built-in) function.
412 * Return -1 if function not found.
413 */
414 static GLint
415 get_static_proc_offset(const char *funcName)
416 {
417 const glprocs_table_t * const f = find_entry( funcName );
418 if (f) {
419 return f->Offset;
420 }
421 return -1;
422 }
423
424
425 #if !defined(XFree86Server) && !defined(XGLServer)
426 #ifdef USE_X86_ASM
427
428 #if defined( GLX_USE_TLS )
429 extern GLubyte gl_dispatch_functions_start[];
430 extern GLubyte gl_dispatch_functions_end[];
431 #else
432 extern const GLubyte gl_dispatch_functions_start[];
433 #endif
434
435 #endif /* USE_X86_ASM */
436
437
438 /**
439 * Return dispatch function address for the named static (built-in) function.
440 * Return NULL if function not found.
441 */
442 static _glapi_proc
443 get_static_proc_address(const char *funcName)
444 {
445 const glprocs_table_t * const f = find_entry( funcName );
446 if (f) {
447 #if defined(DISPATCH_FUNCTION_SIZE) && defined(GLX_INDIRECT_RENDERING)
448 return (f->Address == NULL)
449 ? (_glapi_proc) (gl_dispatch_functions_start
450 + (DISPATCH_FUNCTION_SIZE * f->Offset))
451 : f->Address;
452 #elif defined(DISPATCH_FUNCTION_SIZE)
453 return (_glapi_proc) (gl_dispatch_functions_start
454 + (DISPATCH_FUNCTION_SIZE * f->Offset));
455 #else
456 return f->Address;
457 #endif
458 }
459 else {
460 return NULL;
461 }
462 }
463
464 #endif /* !defined(XFree86Server) && !defined(XGLServer) */
465
466
467
468 /**
469 * Return the name of the function at the given offset in the dispatch
470 * table. For debugging only.
471 */
472 static const char *
473 get_static_proc_name( GLuint offset )
474 {
475 GLuint i;
476 for (i = 0; static_functions[i].Name_offset >= 0; i++) {
477 if (static_functions[i].Offset == offset) {
478 return gl_string_table + static_functions[i].Name_offset;
479 }
480 }
481 return NULL;
482 }
483
484
485
486 /**********************************************************************
487 * Extension function management.
488 */
489
490 /*
491 * Number of extension functions which we can dynamically add at runtime.
492 */
493 #define MAX_EXTENSION_FUNCS 300
494
495
496 /*
497 * The dispatch table size (number of entries) is the size of the
498 * _glapi_table struct plus the number of dynamic entries we can add.
499 * The extra slots can be filled in by DRI drivers that register new extension
500 * functions.
501 */
502 #define DISPATCH_TABLE_SIZE (sizeof(struct _glapi_table) / sizeof(void *) + MAX_EXTENSION_FUNCS)
503
504
505 /**
506 * Track information about a function added to the GL API.
507 */
508 struct _glapi_function {
509 /**
510 * Name of the function.
511 */
512 const char * name;
513
514
515 /**
516 * Text string that describes the types of the parameters passed to the
517 * named function. Parameter types are converted to characters using the
518 * following rules:
519 * - 'i' for \c GLint, \c GLuint, and \c GLenum
520 * - 'p' for any pointer type
521 * - 'f' for \c GLfloat and \c GLclampf
522 * - 'd' for \c GLdouble and \c GLclampd
523 */
524 const char * parameter_signature;
525
526
527 /**
528 * Offset in the dispatch table where the pointer to the real function is
529 * located. If the driver has not requested that the named function be
530 * added to the dispatch table, this will have the value ~0.
531 */
532 unsigned dispatch_offset;
533
534
535 /**
536 * Pointer to the dispatch stub for the named function.
537 *
538 * \todo
539 * The semantic of this field should be changed slightly. Currently, it
540 * is always expected to be non-\c NULL. However, it would be better to
541 * only allocate the entry-point stub when the application requests the
542 * function via \c glXGetProcAddress. This would save memory for all the
543 * functions that the driver exports but that the application never wants
544 * to call.
545 */
546 _glapi_proc dispatch_stub;
547 };
548
549
550 static struct _glapi_function ExtEntryTable[MAX_EXTENSION_FUNCS];
551 static GLuint NumExtEntryPoints = 0;
552
553 #ifdef USE_SPARC_ASM
554 extern void __glapi_sparc_icache_flush(unsigned int *);
555 #endif
556
557 /**
558 * Generate a dispatch function (entrypoint) which jumps through
559 * the given slot number (offset) in the current dispatch table.
560 * We need assembly language in order to accomplish this.
561 */
562 static _glapi_proc
563 generate_entrypoint(GLuint functionOffset)
564 {
565 #if defined(USE_X86_ASM)
566 /* 32 is chosen as something of a magic offset. For x86, the dispatch
567 * at offset 32 is the first one where the offset in the
568 * "jmp OFFSET*4(%eax)" can't be encoded in a single byte.
569 */
570 const GLubyte * const template_func = gl_dispatch_functions_start
571 + (DISPATCH_FUNCTION_SIZE * 32);
572 GLubyte * const code = (GLubyte *) malloc(DISPATCH_FUNCTION_SIZE);
573
574
575 if ( code != NULL ) {
576 (void) memcpy(code, template_func, DISPATCH_FUNCTION_SIZE);
577 fill_in_entrypoint_offset( (_glapi_proc) code, functionOffset );
578 }
579
580 return (_glapi_proc) code;
581 #elif defined(USE_SPARC_ASM)
582
583 #ifdef __arch64__
584 static const unsigned int insn_template[] = {
585 0x05000000, /* sethi %uhi(_glapi_Dispatch), %g2 */
586 0x03000000, /* sethi %hi(_glapi_Dispatch), %g1 */
587 0x8410a000, /* or %g2, %ulo(_glapi_Dispatch), %g2 */
588 0x82106000, /* or %g1, %lo(_glapi_Dispatch), %g1 */
589 0x8528b020, /* sllx %g2, 32, %g2 */
590 0xc2584002, /* ldx [%g1 + %g2], %g1 */
591 0x05000000, /* sethi %hi(8 * glapioffset), %g2 */
592 0x8410a000, /* or %g2, %lo(8 * glapioffset), %g2 */
593 0xc6584002, /* ldx [%g1 + %g2], %g3 */
594 0x81c0c000, /* jmpl %g3, %g0 */
595 0x01000000 /* nop */
596 };
597 #else
598 static const unsigned int insn_template[] = {
599 0x03000000, /* sethi %hi(_glapi_Dispatch), %g1 */
600 0xc2006000, /* ld [%g1 + %lo(_glapi_Dispatch)], %g1 */
601 0xc6006000, /* ld [%g1 + %lo(4*glapioffset)], %g3 */
602 0x81c0c000, /* jmpl %g3, %g0 */
603 0x01000000 /* nop */
604 };
605 #endif /* __arch64__ */
606 unsigned int *code = (unsigned int *) malloc(sizeof(insn_template));
607 unsigned long glapi_addr = (unsigned long) &_glapi_Dispatch;
608 if (code) {
609 memcpy(code, insn_template, sizeof(insn_template));
610
611 #ifdef __arch64__
612 code[0] |= (glapi_addr >> (32 + 10));
613 code[1] |= ((glapi_addr & 0xffffffff) >> 10);
614 __glapi_sparc_icache_flush(&code[0]);
615 code[2] |= ((glapi_addr >> 32) & ((1 << 10) - 1));
616 code[3] |= (glapi_addr & ((1 << 10) - 1));
617 __glapi_sparc_icache_flush(&code[2]);
618 code[6] |= ((functionOffset * 8) >> 10);
619 code[7] |= ((functionOffset * 8) & ((1 << 10) - 1));
620 __glapi_sparc_icache_flush(&code[6]);
621 #else
622 code[0] |= (glapi_addr >> 10);
623 code[1] |= (glapi_addr & ((1 << 10) - 1));
624 __glapi_sparc_icache_flush(&code[0]);
625 code[2] |= (functionOffset * 4);
626 __glapi_sparc_icache_flush(&code[2]);
627 #endif /* __arch64__ */
628 }
629 return (_glapi_proc) code;
630 #else
631 (void) functionOffset;
632 return NULL;
633 #endif /* USE_*_ASM */
634 }
635
636
637 /**
638 * This function inserts a new dispatch offset into the assembly language
639 * stub that was generated with the preceeding function.
640 */
641 static void
642 fill_in_entrypoint_offset(_glapi_proc entrypoint, GLuint offset)
643 {
644 #if defined(USE_X86_ASM)
645 GLubyte * const code = (GLubyte *) entrypoint;
646
647 #if DISPATCH_FUNCTION_SIZE == 32
648 *((unsigned int *)(code + 11)) = 4 * offset;
649 *((unsigned int *)(code + 22)) = 4 * offset;
650 #elif DISPATCH_FUNCTION_SIZE == 16 && defined( GLX_USE_TLS )
651 *((unsigned int *)(code + 8)) = 4 * offset;
652 #elif DISPATCH_FUNCTION_SIZE == 16
653 *((unsigned int *)(code + 7)) = 4 * offset;
654 #else
655 # error Invalid DISPATCH_FUNCTION_SIZE!
656 #endif
657
658 #elif defined(USE_SPARC_ASM)
659
660 /* XXX this hasn't been tested! */
661 unsigned int *code = (unsigned int *) entrypoint;
662 #ifdef __arch64__
663 code[6] = 0x05000000; /* sethi %hi(8 * glapioffset), %g2 */
664 code[7] = 0x8410a000; /* or %g2, %lo(8 * glapioffset), %g2 */
665 code[6] |= ((offset * 8) >> 10);
666 code[7] |= ((offset * 8) & ((1 << 10) - 1));
667 __glapi_sparc_icache_flush(&code[6]);
668 #else /* __arch64__ */
669 code[2] = 0xc6006000; /* ld [%g1 + %lo(4*glapioffset)], %g3 */
670 code[2] |= (offset * 4);
671 __glapi_sparc_icache_flush(&code[2]);
672 #endif /* __arch64__ */
673
674 #else
675
676 /* an unimplemented architecture */
677 (void) entrypoint;
678 (void) offset;
679
680 #endif /* USE_*_ASM */
681 }
682
683
684 /**
685 * Generate new entrypoint
686 *
687 * Use a temporary dispatch offset of ~0 (i.e. -1). Later, when the driver
688 * calls \c _glapi_add_dispatch we'll put in the proper offset. If that
689 * never happens, and the user calls this function, he'll segfault. That's
690 * what you get when you try calling a GL function that doesn't really exist.
691 *
692 * \param funcName Name of the function to create an entry-point for.
693 *
694 * \sa _glapi_add_entrypoint
695 */
696
697 static struct _glapi_function *
698 add_function_name( const char * funcName )
699 {
700 struct _glapi_function * entry = NULL;
701
702 if (NumExtEntryPoints < MAX_EXTENSION_FUNCS) {
703 _glapi_proc entrypoint = generate_entrypoint(~0);
704 if (entrypoint != NULL) {
705 entry = & ExtEntryTable[NumExtEntryPoints];
706
707 ExtEntryTable[NumExtEntryPoints].name = str_dup(funcName);
708 ExtEntryTable[NumExtEntryPoints].parameter_signature = NULL;
709 ExtEntryTable[NumExtEntryPoints].dispatch_offset = ~0;
710 ExtEntryTable[NumExtEntryPoints].dispatch_stub = entrypoint;
711 NumExtEntryPoints++;
712 }
713 }
714
715 return entry;
716 }
717
718
719 /**
720 * Fill-in the dispatch stub for the named function.
721 *
722 * This function is intended to be called by a hardware driver. When called,
723 * a dispatch stub may be created created for the function. A pointer to this
724 * dispatch function will be returned by glXGetProcAddress.
725 *
726 * \param function_names Array of pointers to function names that should
727 * share a common dispatch offset.
728 * \param parameter_signature String representing the types of the parameters
729 * passed to the named function. Parameter types
730 * are converted to characters using the following
731 * rules:
732 * - 'i' for \c GLint, \c GLuint, and \c GLenum
733 * - 'p' for any pointer type
734 * - 'f' for \c GLfloat and \c GLclampf
735 * - 'd' for \c GLdouble and \c GLclampd
736 *
737 * \returns
738 * The offset in the dispatch table of the named function. A pointer to the
739 * driver's implementation of the named function should be stored at
740 * \c dispatch_table[\c offset].
741 *
742 * \sa glXGetProcAddress
743 *
744 * \warning
745 * This function can only handle up to 8 names at a time. As far as I know,
746 * the maximum number of names ever associated with an existing GL function is
747 * 4 (\c glPointParameterfSGIS, \c glPointParameterfEXT,
748 * \c glPointParameterfARB, and \c glPointParameterf), so this should not be
749 * too painful of a limitation.
750 *
751 * \todo
752 * Determine whether or not \c parameter_signature should be allowed to be
753 * \c NULL. It doesn't seem like much of a hardship for drivers to have to
754 * pass in an empty string.
755 *
756 * \todo
757 * Determine if code should be added to reject function names that start with
758 * 'glX'.
759 *
760 * \bug
761 * Add code to compare \c parameter_signature with the parameter signature of
762 * a static function. In order to do that, we need to find a way to \b get
763 * the parameter signature of a static function.
764 */
765
766 PUBLIC int
767 _glapi_add_dispatch( const char * const * function_names,
768 const char * parameter_signature )
769 {
770 static int next_dynamic_offset = _gloffset_FIRST_DYNAMIC;
771 const char * const real_sig = (parameter_signature != NULL)
772 ? parameter_signature : "";
773 struct _glapi_function * entry[8];
774 GLboolean is_static[8];
775 unsigned i;
776 unsigned j;
777 int offset = ~0;
778 int new_offset;
779
780
781 (void) memset( is_static, 0, sizeof( is_static ) );
782 (void) memset( entry, 0, sizeof( entry ) );
783
784 for ( i = 0 ; function_names[i] != NULL ; i++ ) {
785 /* Do some trivial validation on the name of the function.
786 */
787
788 if (!function_names[i] || function_names[i][0] != 'g' || function_names[i][1] != 'l')
789 return GL_FALSE;
790
791 /* Determine if the named function already exists. If the function does
792 * exist, it must have the same parameter signature as the function
793 * being added.
794 */
795
796 new_offset = get_static_proc_offset(function_names[i]);
797 if (new_offset >= 0) {
798 /* FIXME: Make sure the parameter signatures match! How do we get
799 * FIXME: the parameter signature for static functions?
800 */
801
802 if ( (offset != ~0) && (new_offset != offset) ) {
803 return -1;
804 }
805
806 is_static[i] = GL_TRUE;
807 offset = new_offset;
808 }
809
810
811 for ( j = 0 ; j < NumExtEntryPoints ; j++ ) {
812 if (strcmp(ExtEntryTable[j].name, function_names[i]) == 0) {
813 /* The offset may be ~0 if the function name was added by
814 * glXGetProcAddress but never filled in by the driver.
815 */
816
817 if (ExtEntryTable[j].dispatch_offset != ~0) {
818 if (strcmp(real_sig, ExtEntryTable[j].parameter_signature)
819 != 0) {
820 return -1;
821 }
822
823 if ( (offset != ~0) && (ExtEntryTable[j].dispatch_offset != offset) ) {
824 return -1;
825 }
826
827 offset = ExtEntryTable[j].dispatch_offset;
828 }
829
830 entry[i] = & ExtEntryTable[j];
831 break;
832 }
833 }
834 }
835
836 if (offset == ~0) {
837 offset = next_dynamic_offset;
838 next_dynamic_offset++;
839 }
840
841 for ( i = 0 ; function_names[i] != NULL ; i++ ) {
842 if (! is_static[i] ) {
843 if (entry[i] == NULL) {
844 entry[i] = add_function_name( function_names[i] );
845 if (entry[i] == NULL) {
846 /* FIXME: Possible memory leak here.
847 */
848 return -1;
849 }
850 }
851
852 entry[i]->parameter_signature = str_dup(real_sig);
853 fill_in_entrypoint_offset(entry[i]->dispatch_stub, offset);
854 entry[i]->dispatch_offset = offset;
855 }
856 }
857
858 return offset;
859 }
860
861
862 /**
863 * Return offset of entrypoint for named function within dispatch table.
864 */
865 PUBLIC GLint
866 _glapi_get_proc_offset(const char *funcName)
867 {
868 /* search extension functions first */
869 GLuint i;
870 for (i = 0; i < NumExtEntryPoints; i++) {
871 if (strcmp(ExtEntryTable[i].name, funcName) == 0) {
872 return ExtEntryTable[i].dispatch_offset;
873 }
874 }
875 /* search static functions */
876 return get_static_proc_offset(funcName);
877 }
878
879
880
881 /**
882 * Return pointer to the named function. If the function name isn't found
883 * in the name of static functions, try generating a new API entrypoint on
884 * the fly with assembly language.
885 */
886 _glapi_proc
887 _glapi_get_proc_address(const char *funcName)
888 {
889 struct _glapi_function * entry;
890 GLuint i;
891
892 #ifdef MANGLE
893 if (funcName[0] != 'm' || funcName[1] != 'g' || funcName[2] != 'l')
894 return NULL;
895 #else
896 if (funcName[0] != 'g' || funcName[1] != 'l')
897 return NULL;
898 #endif
899
900 /* search extension functions first */
901 for (i = 0; i < NumExtEntryPoints; i++) {
902 if (strcmp(ExtEntryTable[i].name, funcName) == 0) {
903 return ExtEntryTable[i].dispatch_stub;
904 }
905 }
906
907 #if !defined( XFree86Server ) && !defined( XGLServer )
908 /* search static functions */
909 {
910 const _glapi_proc func = get_static_proc_address(funcName);
911 if (func)
912 return func;
913 }
914 #endif /* !defined( XFree86Server ) */
915
916 entry = add_function_name(funcName);
917 return (entry == NULL) ? NULL : entry->dispatch_stub;
918 }
919
920
921
922 /**
923 * Return the name of the function at the given dispatch offset.
924 * This is only intended for debugging.
925 */
926 const char *
927 _glapi_get_proc_name(GLuint offset)
928 {
929 GLuint i;
930 const char * n;
931
932 /* search built-in functions */
933 n = get_static_proc_name(offset);
934 if ( n != NULL ) {
935 return n;
936 }
937
938 /* search added extension functions */
939 for (i = 0; i < NumExtEntryPoints; i++) {
940 if (ExtEntryTable[i].dispatch_offset == offset) {
941 return ExtEntryTable[i].name;
942 }
943 }
944 return NULL;
945 }
946
947
948
949 /**
950 * Return size of dispatch table struct as number of functions (or
951 * slots).
952 */
953 PUBLIC GLuint
954 _glapi_get_dispatch_table_size(void)
955 {
956 return DISPATCH_TABLE_SIZE;
957 }
958
959
960
961 /**
962 * Make sure there are no NULL pointers in the given dispatch table.
963 * Intended for debugging purposes.
964 */
965 void
966 _glapi_check_table(const struct _glapi_table *table)
967 {
968 #ifdef DEBUG
969 const GLuint entries = _glapi_get_dispatch_table_size();
970 const void **tab = (const void **) table;
971 GLuint i;
972 for (i = 1; i < entries; i++) {
973 assert(tab[i]);
974 }
975
976 /* Do some spot checks to be sure that the dispatch table
977 * slots are assigned correctly.
978 */
979 {
980 GLuint BeginOffset = _glapi_get_proc_offset("glBegin");
981 char *BeginFunc = (char*) &table->Begin;
982 GLuint offset = (BeginFunc - (char *) table) / sizeof(void *);
983 assert(BeginOffset == _gloffset_Begin);
984 assert(BeginOffset == offset);
985 }
986 {
987 GLuint viewportOffset = _glapi_get_proc_offset("glViewport");
988 char *viewportFunc = (char*) &table->Viewport;
989 GLuint offset = (viewportFunc - (char *) table) / sizeof(void *);
990 assert(viewportOffset == _gloffset_Viewport);
991 assert(viewportOffset == offset);
992 }
993 {
994 GLuint VertexPointerOffset = _glapi_get_proc_offset("glVertexPointer");
995 char *VertexPointerFunc = (char*) &table->VertexPointer;
996 GLuint offset = (VertexPointerFunc - (char *) table) / sizeof(void *);
997 assert(VertexPointerOffset == _gloffset_VertexPointer);
998 assert(VertexPointerOffset == offset);
999 }
1000 {
1001 GLuint ResetMinMaxOffset = _glapi_get_proc_offset("glResetMinmax");
1002 char *ResetMinMaxFunc = (char*) &table->ResetMinmax;
1003 GLuint offset = (ResetMinMaxFunc - (char *) table) / sizeof(void *);
1004 assert(ResetMinMaxOffset == _gloffset_ResetMinmax);
1005 assert(ResetMinMaxOffset == offset);
1006 }
1007 {
1008 GLuint blendColorOffset = _glapi_get_proc_offset("glBlendColor");
1009 char *blendColorFunc = (char*) &table->BlendColor;
1010 GLuint offset = (blendColorFunc - (char *) table) / sizeof(void *);
1011 assert(blendColorOffset == _gloffset_BlendColor);
1012 assert(blendColorOffset == offset);
1013 }
1014 {
1015 GLuint secondaryColor3fOffset = _glapi_get_proc_offset("glSecondaryColor3fEXT");
1016 char *secondaryColor3fFunc = (char*) &table->SecondaryColor3fEXT;
1017 GLuint offset = (secondaryColor3fFunc - (char *) table) / sizeof(void *);
1018 assert(secondaryColor3fOffset == _gloffset_SecondaryColor3fEXT);
1019 assert(secondaryColor3fOffset == offset);
1020 }
1021 {
1022 GLuint pointParameterivOffset = _glapi_get_proc_offset("glPointParameterivNV");
1023 char *pointParameterivFunc = (char*) &table->PointParameterivNV;
1024 GLuint offset = (pointParameterivFunc - (char *) table) / sizeof(void *);
1025 assert(pointParameterivOffset == _gloffset_PointParameterivNV);
1026 assert(pointParameterivOffset == offset);
1027 }
1028 {
1029 GLuint setFenceOffset = _glapi_get_proc_offset("glSetFenceNV");
1030 char *setFenceFunc = (char*) &table->SetFenceNV;
1031 GLuint offset = (setFenceFunc - (char *) table) / sizeof(void *);
1032 assert(setFenceOffset == _gloffset_SetFenceNV);
1033 assert(setFenceOffset == offset);
1034 }
1035 #else
1036 (void) table;
1037 #endif
1038 }
1039
1040
1041 #if defined(PTHREADS) || defined(GLX_USE_TLS)
1042 /**
1043 * Perform platform-specific GL API entry-point fixups.
1044 */
1045 static void
1046 init_glapi_relocs( void )
1047 {
1048 #if defined(USE_X86_ASM) && defined(GLX_USE_TLS) && !defined(GLX_X86_READONLY_TEXT)
1049 extern unsigned long _x86_get_dispatch(void);
1050 char run_time_patch[] = {
1051 0x65, 0xa1, 0, 0, 0, 0 /* movl %gs:0,%eax */
1052 };
1053 GLuint *offset = (GLuint *) &run_time_patch[2]; /* 32-bits for x86/32 */
1054 const GLubyte * const get_disp = (const GLubyte *) run_time_patch;
1055 GLubyte * curr_func = (GLubyte *) gl_dispatch_functions_start;
1056
1057 *offset = _x86_get_dispatch();
1058 while ( curr_func != (GLubyte *) gl_dispatch_functions_end ) {
1059 (void) memcpy( curr_func, get_disp, sizeof(run_time_patch));
1060 curr_func += DISPATCH_FUNCTION_SIZE;
1061 }
1062 #endif
1063 }
1064 #endif /* defined(PTHREADS) || defined(GLX_USE_TLS) */