Merge remote branch 'origin/master' into nv50-compiler
[mesa.git] / src / mapi / 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 #include "glapi/glapi_priv.h"
34 #include "glapi/glapitable.h"
35 #include "glapi/glapioffsets.h"
36
37
38 /**********************************************************************
39 * Static function management.
40 */
41
42
43 #if !defined(DISPATCH_FUNCTION_SIZE) && !defined(XFree86Server)
44 # define NEED_FUNCTION_POINTER
45 #endif
46 #include "glapi/glprocs.h"
47
48
49 /**
50 * Search the table of static entrypoint functions for the named function
51 * and return the corresponding glprocs_table_t entry.
52 */
53 static const glprocs_table_t *
54 get_static_proc( const char * n )
55 {
56 GLuint i;
57 for (i = 0; static_functions[i].Name_offset >= 0; i++) {
58 const char *testName = gl_string_table + static_functions[i].Name_offset;
59 #ifdef MANGLE
60 /* skip the prefix on the name */
61 if (strcmp(testName, n + 1) == 0)
62 #else
63 if (strcmp(testName, n) == 0)
64 #endif
65 {
66 return &static_functions[i];
67 }
68 }
69 return NULL;
70 }
71
72
73 /**
74 * Return dispatch table offset of the named static (built-in) function.
75 * Return -1 if function not found.
76 */
77 static GLint
78 get_static_proc_offset(const char *funcName)
79 {
80 const glprocs_table_t * const f = get_static_proc( funcName );
81 if (f == NULL) {
82 return -1;
83 }
84
85 return f->Offset;
86 }
87
88
89 #if !defined(XFree86Server)
90
91 /**
92 * Return dispatch function address for the named static (built-in) function.
93 * Return NULL if function not found.
94 */
95 static _glapi_proc
96 get_static_proc_address(const char *funcName)
97 {
98 const glprocs_table_t * const f = get_static_proc( funcName );
99 if (f == NULL) {
100 return NULL;
101 }
102
103 #if defined(DISPATCH_FUNCTION_SIZE) && defined(GLX_INDIRECT_RENDERING)
104 return (f->Address == NULL)
105 ? get_entrypoint_address(f->Offset)
106 : f->Address;
107 #elif defined(DISPATCH_FUNCTION_SIZE)
108 return get_entrypoint_address(f->Offset);
109 #else
110 return f->Address;
111 #endif
112 }
113
114 #else
115
116 static _glapi_proc
117 get_static_proc_address(const char *funcName)
118 {
119 (void) funcName;
120 return NULL;
121 }
122
123 #endif /* !defined(XFree86Server) */
124
125
126 /**
127 * Return the name of the function at the given offset in the dispatch
128 * table. For debugging only.
129 */
130 static const char *
131 get_static_proc_name( GLuint offset )
132 {
133 GLuint i;
134 for (i = 0; static_functions[i].Name_offset >= 0; i++) {
135 if (static_functions[i].Offset == offset) {
136 return gl_string_table + static_functions[i].Name_offset;
137 }
138 }
139 return NULL;
140 }
141
142
143
144 /**********************************************************************
145 * Extension function management.
146 */
147
148
149 /**
150 * Track information about a function added to the GL API.
151 */
152 struct _glapi_function {
153 /**
154 * Name of the function.
155 */
156 const char * name;
157
158
159 /**
160 * Text string that describes the types of the parameters passed to the
161 * named function. Parameter types are converted to characters using the
162 * following rules:
163 * - 'i' for \c GLint, \c GLuint, and \c GLenum
164 * - 'p' for any pointer type
165 * - 'f' for \c GLfloat and \c GLclampf
166 * - 'd' for \c GLdouble and \c GLclampd
167 */
168 const char * parameter_signature;
169
170
171 /**
172 * Offset in the dispatch table where the pointer to the real function is
173 * located. If the driver has not requested that the named function be
174 * added to the dispatch table, this will have the value ~0.
175 */
176 unsigned dispatch_offset;
177
178
179 /**
180 * Pointer to the dispatch stub for the named function.
181 *
182 * \todo
183 * The semantic of this field should be changed slightly. Currently, it
184 * is always expected to be non-\c NULL. However, it would be better to
185 * only allocate the entry-point stub when the application requests the
186 * function via \c glXGetProcAddress. This would save memory for all the
187 * functions that the driver exports but that the application never wants
188 * to call.
189 */
190 _glapi_proc dispatch_stub;
191 };
192
193
194 static struct _glapi_function ExtEntryTable[MAX_EXTENSION_FUNCS];
195 static GLuint NumExtEntryPoints = 0;
196
197
198 static struct _glapi_function *
199 get_extension_proc(const char *funcName)
200 {
201 GLuint i;
202 for (i = 0; i < NumExtEntryPoints; i++) {
203 if (strcmp(ExtEntryTable[i].name, funcName) == 0) {
204 return & ExtEntryTable[i];
205 }
206 }
207 return NULL;
208 }
209
210
211 static GLint
212 get_extension_proc_offset(const char *funcName)
213 {
214 const struct _glapi_function * const f = get_extension_proc( funcName );
215 if (f == NULL) {
216 return -1;
217 }
218
219 return f->dispatch_offset;
220 }
221
222
223 static _glapi_proc
224 get_extension_proc_address(const char *funcName)
225 {
226 const struct _glapi_function * const f = get_extension_proc( funcName );
227 if (f == NULL) {
228 return NULL;
229 }
230
231 return f->dispatch_stub;
232 }
233
234
235 static const char *
236 get_extension_proc_name(GLuint offset)
237 {
238 GLuint i;
239 for (i = 0; i < NumExtEntryPoints; i++) {
240 if (ExtEntryTable[i].dispatch_offset == offset) {
241 return ExtEntryTable[i].name;
242 }
243 }
244 return NULL;
245 }
246
247
248 /**
249 * strdup() is actually not a standard ANSI C or POSIX routine.
250 * Irix will not define it if ANSI mode is in effect.
251 */
252 static char *
253 str_dup(const char *str)
254 {
255 char *copy;
256 copy = (char*) malloc(strlen(str) + 1);
257 if (!copy)
258 return NULL;
259 strcpy(copy, str);
260 return copy;
261 }
262
263
264 /**
265 * Generate new entrypoint
266 *
267 * Use a temporary dispatch offset of ~0 (i.e. -1). Later, when the driver
268 * calls \c _glapi_add_dispatch we'll put in the proper offset. If that
269 * never happens, and the user calls this function, he'll segfault. That's
270 * what you get when you try calling a GL function that doesn't really exist.
271 *
272 * \param funcName Name of the function to create an entry-point for.
273 *
274 * \sa _glapi_add_entrypoint
275 */
276
277 static struct _glapi_function *
278 add_function_name( const char * funcName )
279 {
280 struct _glapi_function * entry = NULL;
281 _glapi_proc entrypoint = NULL;
282 char * name_dup = NULL;
283
284 if (NumExtEntryPoints >= MAX_EXTENSION_FUNCS)
285 return NULL;
286
287 if (funcName == NULL)
288 return NULL;
289
290 name_dup = str_dup(funcName);
291 if (name_dup == NULL)
292 return NULL;
293
294 entrypoint = generate_entrypoint(~0);
295
296 if (entrypoint == NULL) {
297 free(name_dup);
298 return NULL;
299 }
300
301 entry = & ExtEntryTable[NumExtEntryPoints];
302 NumExtEntryPoints++;
303
304 entry->name = name_dup;
305 entry->parameter_signature = NULL;
306 entry->dispatch_offset = ~0;
307 entry->dispatch_stub = entrypoint;
308
309 return entry;
310 }
311
312
313 static struct _glapi_function *
314 set_entry_info( struct _glapi_function * entry, const char * signature, unsigned offset )
315 {
316 char * sig_dup = NULL;
317
318 if (signature == NULL)
319 return NULL;
320
321 sig_dup = str_dup(signature);
322 if (sig_dup == NULL)
323 return NULL;
324
325 fill_in_entrypoint_offset(entry->dispatch_stub, offset);
326
327 entry->parameter_signature = sig_dup;
328 entry->dispatch_offset = offset;
329
330 return entry;
331 }
332
333
334 /**
335 * Fill-in the dispatch stub for the named function.
336 *
337 * This function is intended to be called by a hardware driver. When called,
338 * a dispatch stub may be created created for the function. A pointer to this
339 * dispatch function will be returned by glXGetProcAddress.
340 *
341 * \param function_names Array of pointers to function names that should
342 * share a common dispatch offset.
343 * \param parameter_signature String representing the types of the parameters
344 * passed to the named function. Parameter types
345 * are converted to characters using the following
346 * rules:
347 * - 'i' for \c GLint, \c GLuint, and \c GLenum
348 * - 'p' for any pointer type
349 * - 'f' for \c GLfloat and \c GLclampf
350 * - 'd' for \c GLdouble and \c GLclampd
351 *
352 * \returns
353 * The offset in the dispatch table of the named function. A pointer to the
354 * driver's implementation of the named function should be stored at
355 * \c dispatch_table[\c offset]. Return -1 if error/problem.
356 *
357 * \sa glXGetProcAddress
358 *
359 * \warning
360 * This function can only handle up to 8 names at a time. As far as I know,
361 * the maximum number of names ever associated with an existing GL function is
362 * 4 (\c glPointParameterfSGIS, \c glPointParameterfEXT,
363 * \c glPointParameterfARB, and \c glPointParameterf), so this should not be
364 * too painful of a limitation.
365 *
366 * \todo
367 * Determine whether or not \c parameter_signature should be allowed to be
368 * \c NULL. It doesn't seem like much of a hardship for drivers to have to
369 * pass in an empty string.
370 *
371 * \todo
372 * Determine if code should be added to reject function names that start with
373 * 'glX'.
374 *
375 * \bug
376 * Add code to compare \c parameter_signature with the parameter signature of
377 * a static function. In order to do that, we need to find a way to \b get
378 * the parameter signature of a static function.
379 */
380
381 int
382 _glapi_add_dispatch( const char * const * function_names,
383 const char * parameter_signature )
384 {
385 static int next_dynamic_offset = _gloffset_FIRST_DYNAMIC;
386 const char * const real_sig = (parameter_signature != NULL)
387 ? parameter_signature : "";
388 struct _glapi_function * entry[8];
389 GLboolean is_static[8];
390 unsigned i;
391 int offset = ~0;
392
393 init_glapi_relocs_once();
394
395 (void) memset( is_static, 0, sizeof( is_static ) );
396 (void) memset( entry, 0, sizeof( entry ) );
397
398 /* Find the _single_ dispatch offset for all function names that already
399 * exist (and have a dispatch offset).
400 */
401
402 for ( i = 0 ; function_names[i] != NULL ; i++ ) {
403 const char * funcName = function_names[i];
404 int static_offset;
405 int extension_offset;
406
407 if (funcName[0] != 'g' || funcName[1] != 'l')
408 return -1;
409
410 /* search built-in functions */
411 static_offset = get_static_proc_offset(funcName);
412
413 if (static_offset >= 0) {
414
415 is_static[i] = GL_TRUE;
416
417 /* FIXME: Make sure the parameter signatures match! How do we get
418 * FIXME: the parameter signature for static functions?
419 */
420
421 if ( (offset != ~0) && (static_offset != offset) ) {
422 return -1;
423 }
424
425 offset = static_offset;
426
427 continue;
428 }
429
430 /* search added extension functions */
431 entry[i] = get_extension_proc(funcName);
432
433 if (entry[i] != NULL) {
434 extension_offset = entry[i]->dispatch_offset;
435
436 /* The offset may be ~0 if the function name was added by
437 * glXGetProcAddress but never filled in by the driver.
438 */
439
440 if (extension_offset == ~0) {
441 continue;
442 }
443
444 if (strcmp(real_sig, entry[i]->parameter_signature) != 0) {
445 return -1;
446 }
447
448 if ( (offset != ~0) && (extension_offset != offset) ) {
449 return -1;
450 }
451
452 offset = extension_offset;
453 }
454 }
455
456 /* If all function names are either new (or with no dispatch offset),
457 * allocate a new dispatch offset.
458 */
459
460 if (offset == ~0) {
461 offset = next_dynamic_offset;
462 next_dynamic_offset++;
463 }
464
465 /* Fill in the dispatch offset for the new function names (and those with
466 * no dispatch offset).
467 */
468
469 for ( i = 0 ; function_names[i] != NULL ; i++ ) {
470 if (is_static[i]) {
471 continue;
472 }
473
474 /* generate entrypoints for new function names */
475 if (entry[i] == NULL) {
476 entry[i] = add_function_name( function_names[i] );
477 if (entry[i] == NULL) {
478 /* FIXME: Possible memory leak here. */
479 return -1;
480 }
481 }
482
483 if (entry[i]->dispatch_offset == ~0) {
484 set_entry_info( entry[i], real_sig, offset );
485 }
486 }
487
488 return offset;
489 }
490
491
492 /**
493 * Return offset of entrypoint for named function within dispatch table.
494 */
495 GLint
496 _glapi_get_proc_offset(const char *funcName)
497 {
498 GLint offset;
499
500 /* search extension functions first */
501 offset = get_extension_proc_offset(funcName);
502 if (offset >= 0)
503 return offset;
504
505 /* search static functions */
506 return get_static_proc_offset(funcName);
507 }
508
509
510
511 /**
512 * Return pointer to the named function. If the function name isn't found
513 * in the name of static functions, try generating a new API entrypoint on
514 * the fly with assembly language.
515 */
516 _glapi_proc
517 _glapi_get_proc_address(const char *funcName)
518 {
519 _glapi_proc func;
520 struct _glapi_function * entry;
521
522 init_glapi_relocs_once();
523
524 #ifdef MANGLE
525 /* skip the prefix on the name */
526 if (funcName[1] != 'g' || funcName[2] != 'l')
527 return NULL;
528 #else
529 if (funcName[0] != 'g' || funcName[1] != 'l')
530 return NULL;
531 #endif
532
533 /* search extension functions first */
534 func = get_extension_proc_address(funcName);
535 if (func)
536 return func;
537
538 /* search static functions */
539 func = get_static_proc_address(funcName);
540 if (func)
541 return func;
542
543 /* generate entrypoint, dispatch offset must be filled in by the driver */
544 entry = add_function_name(funcName);
545 if (entry == NULL)
546 return NULL;
547
548 return entry->dispatch_stub;
549 }
550
551
552
553 /**
554 * Return the name of the function at the given dispatch offset.
555 * This is only intended for debugging.
556 */
557 const char *
558 _glapi_get_proc_name(GLuint offset)
559 {
560 const char * n;
561
562 /* search built-in functions */
563 n = get_static_proc_name(offset);
564 if ( n != NULL ) {
565 return n;
566 }
567
568 /* search added extension functions */
569 return get_extension_proc_name(offset);
570 }
571
572
573
574 /**********************************************************************
575 * GL API table functions.
576 */
577
578
579 /*
580 * The dispatch table size (number of entries) is the size of the
581 * _glapi_table struct plus the number of dynamic entries we can add.
582 * The extra slots can be filled in by DRI drivers that register new extension
583 * functions.
584 */
585 #define DISPATCH_TABLE_SIZE (sizeof(struct _glapi_table) / sizeof(void *) + MAX_EXTENSION_FUNCS)
586
587
588 /**
589 * Return size of dispatch table struct as number of functions (or
590 * slots).
591 */
592 GLuint
593 _glapi_get_dispatch_table_size(void)
594 {
595 return DISPATCH_TABLE_SIZE;
596 }
597
598
599 /**
600 * Make sure there are no NULL pointers in the given dispatch table.
601 * Intended for debugging purposes.
602 */
603 void
604 _glapi_check_table_not_null(const struct _glapi_table *table)
605 {
606 #ifdef EXTRA_DEBUG /* set to DEBUG for extra DEBUG */
607 const GLuint entries = _glapi_get_dispatch_table_size();
608 const void **tab = (const void **) table;
609 GLuint i;
610 for (i = 1; i < entries; i++) {
611 assert(tab[i]);
612 }
613 #else
614 (void) table;
615 #endif
616 }
617
618
619 /**
620 * Do some spot checks to be sure that the dispatch table
621 * slots are assigned correctly. For debugging only.
622 */
623 void
624 _glapi_check_table(const struct _glapi_table *table)
625 {
626 #ifdef EXTRA_DEBUG /* set to DEBUG for extra DEBUG */
627 {
628 GLuint BeginOffset = _glapi_get_proc_offset("glBegin");
629 char *BeginFunc = (char*) &table->Begin;
630 GLuint offset = (BeginFunc - (char *) table) / sizeof(void *);
631 assert(BeginOffset == _gloffset_Begin);
632 assert(BeginOffset == offset);
633 }
634 {
635 GLuint viewportOffset = _glapi_get_proc_offset("glViewport");
636 char *viewportFunc = (char*) &table->Viewport;
637 GLuint offset = (viewportFunc - (char *) table) / sizeof(void *);
638 assert(viewportOffset == _gloffset_Viewport);
639 assert(viewportOffset == offset);
640 }
641 {
642 GLuint VertexPointerOffset = _glapi_get_proc_offset("glVertexPointer");
643 char *VertexPointerFunc = (char*) &table->VertexPointer;
644 GLuint offset = (VertexPointerFunc - (char *) table) / sizeof(void *);
645 assert(VertexPointerOffset == _gloffset_VertexPointer);
646 assert(VertexPointerOffset == offset);
647 }
648 {
649 GLuint ResetMinMaxOffset = _glapi_get_proc_offset("glResetMinmax");
650 char *ResetMinMaxFunc = (char*) &table->ResetMinmax;
651 GLuint offset = (ResetMinMaxFunc - (char *) table) / sizeof(void *);
652 assert(ResetMinMaxOffset == _gloffset_ResetMinmax);
653 assert(ResetMinMaxOffset == offset);
654 }
655 {
656 GLuint blendColorOffset = _glapi_get_proc_offset("glBlendColor");
657 char *blendColorFunc = (char*) &table->BlendColor;
658 GLuint offset = (blendColorFunc - (char *) table) / sizeof(void *);
659 assert(blendColorOffset == _gloffset_BlendColor);
660 assert(blendColorOffset == offset);
661 }
662 {
663 GLuint secondaryColor3fOffset = _glapi_get_proc_offset("glSecondaryColor3fEXT");
664 char *secondaryColor3fFunc = (char*) &table->SecondaryColor3fEXT;
665 GLuint offset = (secondaryColor3fFunc - (char *) table) / sizeof(void *);
666 assert(secondaryColor3fOffset == _gloffset_SecondaryColor3fEXT);
667 assert(secondaryColor3fOffset == offset);
668 }
669 {
670 GLuint pointParameterivOffset = _glapi_get_proc_offset("glPointParameterivNV");
671 char *pointParameterivFunc = (char*) &table->PointParameterivNV;
672 GLuint offset = (pointParameterivFunc - (char *) table) / sizeof(void *);
673 assert(pointParameterivOffset == _gloffset_PointParameterivNV);
674 assert(pointParameterivOffset == offset);
675 }
676 {
677 GLuint setFenceOffset = _glapi_get_proc_offset("glSetFenceNV");
678 char *setFenceFunc = (char*) &table->SetFenceNV;
679 GLuint offset = (setFenceFunc - (char *) table) / sizeof(void *);
680 assert(setFenceOffset == _gloffset_SetFenceNV);
681 assert(setFenceOffset == offset);
682 }
683 #else
684 (void) table;
685 #endif
686 }