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