~mmach/netext73/mesa-ryzen

« back to all changes in this revision

Viewing changes to src/mapi/glapi/glapi_getproc.c

  • Committer: mmach
  • Date: 2023-11-02 21:31:35 UTC
  • Revision ID: netbit73@gmail.com-20231102213135-18d4tzh7tj0uz752
2023-11-02 22:11:57

Show diffs side-by-side

added added

removed removed

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