*/
/**
- * \file glapi_getproc.
+ * \file glapi_getproc.c
*
* Code for implementing glXGetProcAddress(), etc.
* This was originally in glapi.c but refactored out.
*/
-#include <stdlib.h>
-#include <string.h>
-#include "glheader.h"
-#include "glapi.h"
-#include "glapioffsets.h"
-#include "glapitable.h"
-
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#include "glapi/mesa.h"
+#else
+#include "main/glheader.h"
+#include "main/compiler.h"
+#endif
-static void
-fill_in_entrypoint_offset(_glapi_proc entrypoint, GLuint offset);
+#include "glapi/glapi.h"
+#include "glapi/glapi_priv.h"
+#include "glapi/glapitable.h"
+#include "glapi/glapioffsets.h"
-/**
- * strdup() is actually not a standard ANSI C or POSIX routine.
- * Irix will not define it if ANSI mode is in effect.
+/**********************************************************************
+ * Static function management.
*/
-static char *
-str_dup(const char *str)
-{
- char *copy;
- copy = (char*) malloc(strlen(str) + 1);
- if (!copy)
- return NULL;
- strcpy(copy, str);
- return copy;
-}
-
-#if defined(USE_X64_64_ASM) && defined(GLX_USE_TLS)
-# define DISPATCH_FUNCTION_SIZE 16
-#elif defined(USE_X86_ASM)
-# if defined(THREADS) && !defined(GLX_USE_TLS)
-# define DISPATCH_FUNCTION_SIZE 32
-# else
-# define DISPATCH_FUNCTION_SIZE 16
-# endif
-#endif
-
-#if !defined(DISPATCH_FUNCTION_SIZE) && !defined(XFree86Server) && !defined(XGLServer)
+#if !defined(DISPATCH_FUNCTION_SIZE) && !defined(XFree86Server)
# define NEED_FUNCTION_POINTER
#endif
-
-/* The code in this file is auto-generated with Python */
-#include "glprocs.h"
+#include "glapi/glprocs.h"
/**
* and return the corresponding glprocs_table_t entry.
*/
static const glprocs_table_t *
-find_entry( const char * n )
+get_static_proc( const char * n )
{
GLuint i;
for (i = 0; static_functions[i].Name_offset >= 0; i++) {
const char *testName = gl_string_table + static_functions[i].Name_offset;
- if (strcmp(testName, n) == 0) {
+#ifdef MANGLE
+ /* skip the prefix on the name */
+ if (strcmp(testName, n + 1) == 0)
+#else
+ if (strcmp(testName, n) == 0)
+#endif
+ {
return &static_functions[i];
}
}
static GLint
get_static_proc_offset(const char *funcName)
{
- const glprocs_table_t * const f = find_entry( funcName );
- if (f) {
- return f->Offset;
+ const glprocs_table_t * const f = get_static_proc( funcName );
+ if (f == NULL) {
+ return -1;
}
- return -1;
-}
+ return f->Offset;
+}
-#if !defined(XFree86Server) && !defined(XGLServer)
-#ifdef USE_X86_ASM
-
-#if defined( GLX_USE_TLS )
-extern GLubyte gl_dispatch_functions_start[];
-extern GLubyte gl_dispatch_functions_end[];
-#else
-extern const GLubyte gl_dispatch_functions_start[];
-#endif
-
-#endif /* USE_X86_ASM */
+#if !defined(XFree86Server)
/**
* Return dispatch function address for the named static (built-in) function.
static _glapi_proc
get_static_proc_address(const char *funcName)
{
- const glprocs_table_t * const f = find_entry( funcName );
- if (f) {
+ const glprocs_table_t * const f = get_static_proc( funcName );
+ if (f == NULL) {
+ return NULL;
+ }
+
#if defined(DISPATCH_FUNCTION_SIZE) && defined(GLX_INDIRECT_RENDERING)
- return (f->Address == NULL)
- ? (_glapi_proc) (gl_dispatch_functions_start
- + (DISPATCH_FUNCTION_SIZE * f->Offset))
- : f->Address;
+ return (f->Address == NULL)
+ ? get_entrypoint_address(f->Offset)
+ : f->Address;
#elif defined(DISPATCH_FUNCTION_SIZE)
- return (_glapi_proc) (gl_dispatch_functions_start
- + (DISPATCH_FUNCTION_SIZE * f->Offset));
+ return get_entrypoint_address(f->Offset);
#else
- return f->Address;
+ return f->Address;
#endif
- }
- else {
- return NULL;
- }
}
-#endif /* !defined(XFree86Server) && !defined(XGLServer) */
+#else
+
+static _glapi_proc
+get_static_proc_address(const char *funcName)
+{
+ (void) funcName;
+ return NULL;
+}
+#endif /* !defined(XFree86Server) */
/**
};
+/*
+ * Number of extension functions which we can dynamically add at runtime.
+ */
+#define MAX_EXTENSION_FUNCS 300
+
+
static struct _glapi_function ExtEntryTable[MAX_EXTENSION_FUNCS];
static GLuint NumExtEntryPoints = 0;
-#ifdef USE_SPARC_ASM
-extern void __glapi_sparc_icache_flush(unsigned int *);
-#endif
-/**
- * Generate a dispatch function (entrypoint) which jumps through
- * the given slot number (offset) in the current dispatch table.
- * We need assembly language in order to accomplish this.
- */
-static _glapi_proc
-generate_entrypoint(GLuint functionOffset)
+static struct _glapi_function *
+get_extension_proc(const char *funcName)
{
-#if defined(USE_X86_ASM)
- /* 32 is chosen as something of a magic offset. For x86, the dispatch
- * at offset 32 is the first one where the offset in the
- * "jmp OFFSET*4(%eax)" can't be encoded in a single byte.
- */
- const GLubyte * const template_func = gl_dispatch_functions_start
- + (DISPATCH_FUNCTION_SIZE * 32);
- GLubyte * const code = (GLubyte *) malloc(DISPATCH_FUNCTION_SIZE);
+ GLuint i;
+ for (i = 0; i < NumExtEntryPoints; i++) {
+ if (strcmp(ExtEntryTable[i].name, funcName) == 0) {
+ return & ExtEntryTable[i];
+ }
+ }
+ return NULL;
+}
- if ( code != NULL ) {
- (void) memcpy(code, template_func, DISPATCH_FUNCTION_SIZE);
- fill_in_entrypoint_offset( (_glapi_proc) code, functionOffset );
+static GLint
+get_extension_proc_offset(const char *funcName)
+{
+ const struct _glapi_function * const f = get_extension_proc( funcName );
+ if (f == NULL) {
+ return -1;
}
- return (_glapi_proc) code;
-#elif defined(USE_SPARC_ASM)
-
-#ifdef __arch64__
- static const unsigned int insn_template[] = {
- 0x05000000, /* sethi %uhi(_glapi_Dispatch), %g2 */
- 0x03000000, /* sethi %hi(_glapi_Dispatch), %g1 */
- 0x8410a000, /* or %g2, %ulo(_glapi_Dispatch), %g2 */
- 0x82106000, /* or %g1, %lo(_glapi_Dispatch), %g1 */
- 0x8528b020, /* sllx %g2, 32, %g2 */
- 0xc2584002, /* ldx [%g1 + %g2], %g1 */
- 0x05000000, /* sethi %hi(8 * glapioffset), %g2 */
- 0x8410a000, /* or %g2, %lo(8 * glapioffset), %g2 */
- 0xc6584002, /* ldx [%g1 + %g2], %g3 */
- 0x81c0c000, /* jmpl %g3, %g0 */
- 0x01000000 /* nop */
- };
-#else
- static const unsigned int insn_template[] = {
- 0x03000000, /* sethi %hi(_glapi_Dispatch), %g1 */
- 0xc2006000, /* ld [%g1 + %lo(_glapi_Dispatch)], %g1 */
- 0xc6006000, /* ld [%g1 + %lo(4*glapioffset)], %g3 */
- 0x81c0c000, /* jmpl %g3, %g0 */
- 0x01000000 /* nop */
- };
-#endif /* __arch64__ */
- unsigned int *code = (unsigned int *) malloc(sizeof(insn_template));
- unsigned long glapi_addr = (unsigned long) &_glapi_Dispatch;
- if (code) {
- memcpy(code, insn_template, sizeof(insn_template));
-
-#ifdef __arch64__
- code[0] |= (glapi_addr >> (32 + 10));
- code[1] |= ((glapi_addr & 0xffffffff) >> 10);
- __glapi_sparc_icache_flush(&code[0]);
- code[2] |= ((glapi_addr >> 32) & ((1 << 10) - 1));
- code[3] |= (glapi_addr & ((1 << 10) - 1));
- __glapi_sparc_icache_flush(&code[2]);
- code[6] |= ((functionOffset * 8) >> 10);
- code[7] |= ((functionOffset * 8) & ((1 << 10) - 1));
- __glapi_sparc_icache_flush(&code[6]);
-#else
- code[0] |= (glapi_addr >> 10);
- code[1] |= (glapi_addr & ((1 << 10) - 1));
- __glapi_sparc_icache_flush(&code[0]);
- code[2] |= (functionOffset * 4);
- __glapi_sparc_icache_flush(&code[2]);
-#endif /* __arch64__ */
- }
- return (_glapi_proc) code;
-#else
- (void) functionOffset;
- return NULL;
-#endif /* USE_*_ASM */
+ return f->dispatch_offset;
}
-/**
- * This function inserts a new dispatch offset into the assembly language
- * stub that was generated with the preceeding function.
- */
-static void
-fill_in_entrypoint_offset(_glapi_proc entrypoint, GLuint offset)
+static _glapi_proc
+get_extension_proc_address(const char *funcName)
{
-#if defined(USE_X86_ASM)
- GLubyte * const code = (GLubyte *) entrypoint;
-
-#if DISPATCH_FUNCTION_SIZE == 32
- *((unsigned int *)(code + 11)) = 4 * offset;
- *((unsigned int *)(code + 22)) = 4 * offset;
-#elif DISPATCH_FUNCTION_SIZE == 16 && defined( GLX_USE_TLS )
- *((unsigned int *)(code + 8)) = 4 * offset;
-#elif DISPATCH_FUNCTION_SIZE == 16
- *((unsigned int *)(code + 7)) = 4 * offset;
-#else
-# error Invalid DISPATCH_FUNCTION_SIZE!
-#endif
+ const struct _glapi_function * const f = get_extension_proc( funcName );
+ if (f == NULL) {
+ return NULL;
+ }
-#elif defined(USE_SPARC_ASM)
-
- /* XXX this hasn't been tested! */
- unsigned int *code = (unsigned int *) entrypoint;
-#ifdef __arch64__
- code[6] = 0x05000000; /* sethi %hi(8 * glapioffset), %g2 */
- code[7] = 0x8410a000; /* or %g2, %lo(8 * glapioffset), %g2 */
- code[6] |= ((offset * 8) >> 10);
- code[7] |= ((offset * 8) & ((1 << 10) - 1));
- __glapi_sparc_icache_flush(&code[6]);
-#else /* __arch64__ */
- code[2] = 0xc6006000; /* ld [%g1 + %lo(4*glapioffset)], %g3 */
- code[2] |= (offset * 4);
- __glapi_sparc_icache_flush(&code[2]);
-#endif /* __arch64__ */
+ return f->dispatch_stub;
+}
-#else
- /* an unimplemented architecture */
- (void) entrypoint;
- (void) offset;
+static const char *
+get_extension_proc_name(GLuint offset)
+{
+ GLuint i;
+ for (i = 0; i < NumExtEntryPoints; i++) {
+ if (ExtEntryTable[i].dispatch_offset == offset) {
+ return ExtEntryTable[i].name;
+ }
+ }
+ return NULL;
+}
-#endif /* USE_*_ASM */
+
+/**
+ * strdup() is actually not a standard ANSI C or POSIX routine.
+ * Irix will not define it if ANSI mode is in effect.
+ */
+static char *
+str_dup(const char *str)
+{
+ char *copy;
+ copy = (char*) malloc(strlen(str) + 1);
+ if (!copy)
+ return NULL;
+ strcpy(copy, str);
+ return copy;
}
* \returns
* The offset in the dispatch table of the named function. A pointer to the
* driver's implementation of the named function should be stored at
- * \c dispatch_table[\c offset].
+ * \c dispatch_table[\c offset]. Return -1 if error/problem.
*
* \sa glXGetProcAddress
*
struct _glapi_function * entry[8];
GLboolean is_static[8];
unsigned i;
- unsigned j;
int offset = ~0;
int new_offset;
*/
if (!function_names[i] || function_names[i][0] != 'g' || function_names[i][1] != 'l')
- return GL_FALSE;
+ return -1;
/* Determine if the named function already exists. If the function does
* exist, it must have the same parameter signature as the function
}
- for ( j = 0 ; j < NumExtEntryPoints ; j++ ) {
- if (strcmp(ExtEntryTable[j].name, function_names[i]) == 0) {
+ entry[i] = get_extension_proc(function_names[i]);
+
+ if (entry[i] != NULL) {
+
/* The offset may be ~0 if the function name was added by
* glXGetProcAddress but never filled in by the driver.
*/
- if (ExtEntryTable[j].dispatch_offset != ~0) {
- if (strcmp(real_sig, ExtEntryTable[j].parameter_signature)
- != 0) {
+ if (entry[i]->dispatch_offset != ~0) {
+ if (strcmp(real_sig, entry[i]->parameter_signature) != 0) {
return -1;
}
- if ( (offset != ~0) && (ExtEntryTable[j].dispatch_offset != offset) ) {
+ if ( (offset != ~0) && (entry[i]->dispatch_offset != offset) ) {
return -1;
}
- offset = ExtEntryTable[j].dispatch_offset;
+ offset = entry[i]->dispatch_offset;
}
-
- entry[i] = & ExtEntryTable[j];
- break;
- }
}
}
PUBLIC GLint
_glapi_get_proc_offset(const char *funcName)
{
+ GLint offset;
+
/* search extension functions first */
- GLuint i;
- for (i = 0; i < NumExtEntryPoints; i++) {
- if (strcmp(ExtEntryTable[i].name, funcName) == 0) {
- return ExtEntryTable[i].dispatch_offset;
- }
- }
+ offset = get_extension_proc_offset(funcName);
+ if (offset >= 0)
+ return offset;
+
/* search static functions */
return get_static_proc_offset(funcName);
}
* in the name of static functions, try generating a new API entrypoint on
* the fly with assembly language.
*/
-_glapi_proc
+PUBLIC _glapi_proc
_glapi_get_proc_address(const char *funcName)
{
+ _glapi_proc func;
struct _glapi_function * entry;
- GLuint i;
#ifdef MANGLE
- if (funcName[0] != 'm' || funcName[1] != 'g' || funcName[2] != 'l')
+ /* skip the prefix on the name */
+ if (funcName[1] != 'g' || funcName[2] != 'l')
return NULL;
#else
if (funcName[0] != 'g' || funcName[1] != 'l')
#endif
/* search extension functions first */
- for (i = 0; i < NumExtEntryPoints; i++) {
- if (strcmp(ExtEntryTable[i].name, funcName) == 0) {
- return ExtEntryTable[i].dispatch_stub;
- }
- }
+ func = get_extension_proc_address(funcName);
+ if (func)
+ return func;
-#if !defined( XFree86Server ) && !defined( XGLServer )
/* search static functions */
- {
- const _glapi_proc func = get_static_proc_address(funcName);
- if (func)
- return func;
- }
-#endif /* !defined( XFree86Server ) */
+ func = get_static_proc_address(funcName);
+ if (func)
+ return func;
entry = add_function_name(funcName);
return (entry == NULL) ? NULL : entry->dispatch_stub;
const char *
_glapi_get_proc_name(GLuint offset)
{
- GLuint i;
const char * n;
/* search built-in functions */
}
/* search added extension functions */
- for (i = 0; i < NumExtEntryPoints; i++) {
- if (ExtEntryTable[i].dispatch_offset == offset) {
- return ExtEntryTable[i].name;
- }
+ return get_extension_proc_name(offset);
+}
+
+
+
+/**********************************************************************
+ * GL API table functions.
+ */
+
+
+/*
+ * The dispatch table size (number of entries) is the size of the
+ * _glapi_table struct plus the number of dynamic entries we can add.
+ * The extra slots can be filled in by DRI drivers that register new extension
+ * functions.
+ */
+#define DISPATCH_TABLE_SIZE (sizeof(struct _glapi_table) / sizeof(void *) + MAX_EXTENSION_FUNCS)
+
+
+/**
+ * Return size of dispatch table struct as number of functions (or
+ * slots).
+ */
+PUBLIC GLuint
+_glapi_get_dispatch_table_size(void)
+{
+ return DISPATCH_TABLE_SIZE;
+}
+
+
+/**
+ * Make sure there are no NULL pointers in the given dispatch table.
+ * Intended for debugging purposes.
+ */
+void
+_glapi_check_table_not_null(const struct _glapi_table *table)
+{
+#ifdef EXTRA_DEBUG /* set to DEBUG for extra DEBUG */
+ const GLuint entries = _glapi_get_dispatch_table_size();
+ const void **tab = (const void **) table;
+ GLuint i;
+ for (i = 1; i < entries; i++) {
+ assert(tab[i]);
}
- return NULL;
+#else
+ (void) table;
+#endif
+}
+
+
+/**
+ * Do some spot checks to be sure that the dispatch table
+ * slots are assigned correctly. For debugging only.
+ */
+void
+_glapi_check_table(const struct _glapi_table *table)
+{
+#ifdef EXTRA_DEBUG /* set to DEBUG for extra DEBUG */
+ {
+ GLuint BeginOffset = _glapi_get_proc_offset("glBegin");
+ char *BeginFunc = (char*) &table->Begin;
+ GLuint offset = (BeginFunc - (char *) table) / sizeof(void *);
+ assert(BeginOffset == _gloffset_Begin);
+ assert(BeginOffset == offset);
+ }
+ {
+ GLuint viewportOffset = _glapi_get_proc_offset("glViewport");
+ char *viewportFunc = (char*) &table->Viewport;
+ GLuint offset = (viewportFunc - (char *) table) / sizeof(void *);
+ assert(viewportOffset == _gloffset_Viewport);
+ assert(viewportOffset == offset);
+ }
+ {
+ GLuint VertexPointerOffset = _glapi_get_proc_offset("glVertexPointer");
+ char *VertexPointerFunc = (char*) &table->VertexPointer;
+ GLuint offset = (VertexPointerFunc - (char *) table) / sizeof(void *);
+ assert(VertexPointerOffset == _gloffset_VertexPointer);
+ assert(VertexPointerOffset == offset);
+ }
+ {
+ GLuint ResetMinMaxOffset = _glapi_get_proc_offset("glResetMinmax");
+ char *ResetMinMaxFunc = (char*) &table->ResetMinmax;
+ GLuint offset = (ResetMinMaxFunc - (char *) table) / sizeof(void *);
+ assert(ResetMinMaxOffset == _gloffset_ResetMinmax);
+ assert(ResetMinMaxOffset == offset);
+ }
+ {
+ GLuint blendColorOffset = _glapi_get_proc_offset("glBlendColor");
+ char *blendColorFunc = (char*) &table->BlendColor;
+ GLuint offset = (blendColorFunc - (char *) table) / sizeof(void *);
+ assert(blendColorOffset == _gloffset_BlendColor);
+ assert(blendColorOffset == offset);
+ }
+ {
+ GLuint secondaryColor3fOffset = _glapi_get_proc_offset("glSecondaryColor3fEXT");
+ char *secondaryColor3fFunc = (char*) &table->SecondaryColor3fEXT;
+ GLuint offset = (secondaryColor3fFunc - (char *) table) / sizeof(void *);
+ assert(secondaryColor3fOffset == _gloffset_SecondaryColor3fEXT);
+ assert(secondaryColor3fOffset == offset);
+ }
+ {
+ GLuint pointParameterivOffset = _glapi_get_proc_offset("glPointParameterivNV");
+ char *pointParameterivFunc = (char*) &table->PointParameterivNV;
+ GLuint offset = (pointParameterivFunc - (char *) table) / sizeof(void *);
+ assert(pointParameterivOffset == _gloffset_PointParameterivNV);
+ assert(pointParameterivOffset == offset);
+ }
+ {
+ GLuint setFenceOffset = _glapi_get_proc_offset("glSetFenceNV");
+ char *setFenceFunc = (char*) &table->SetFenceNV;
+ GLuint offset = (setFenceFunc - (char *) table) / sizeof(void *);
+ assert(setFenceOffset == _gloffset_SetFenceNV);
+ assert(setFenceOffset == offset);
+ }
+#else
+ (void) table;
+#endif
}